pointer.c revision e07dc26b
1e07dc26bSmrg/* $Id: pointer.c,v 1.1.1.1 2019/01/09 23:50:31 mrg Exp $ */ 2e07dc26bSmrg/** @file 3e07dc26bSmrg * VirtualBox X11 Additions graphics driver utility functions 4e07dc26bSmrg */ 5e07dc26bSmrg 6e07dc26bSmrg/* 7e07dc26bSmrg * Copyright (C) 2006-2017 Oracle Corporation 8e07dc26bSmrg * 9e07dc26bSmrg * Permission is hereby granted, free of charge, to any person obtaining a 10e07dc26bSmrg * copy of this software and associated documentation files (the "Software"), 11e07dc26bSmrg * to deal in the Software without restriction, including without limitation 12e07dc26bSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 13e07dc26bSmrg * and/or sell copies of the Software, and to permit persons to whom the 14e07dc26bSmrg * Software is furnished to do so, subject to the following conditions: 15e07dc26bSmrg * 16e07dc26bSmrg * The above copyright notice and this permission notice shall be included in 17e07dc26bSmrg * all copies or substantial portions of the Software. 18e07dc26bSmrg * 19e07dc26bSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20e07dc26bSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21e07dc26bSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 22e07dc26bSmrg * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 23e07dc26bSmrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 24e07dc26bSmrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 25e07dc26bSmrg * USE OR OTHER DEALINGS IN THE SOFTWARE. 26e07dc26bSmrg */ 27e07dc26bSmrg 28e07dc26bSmrg#ifndef PCIACCESS 29e07dc26bSmrg# include "xf86Pci.h" 30e07dc26bSmrg# include <Pci.h> 31e07dc26bSmrg#endif 32e07dc26bSmrg 33e07dc26bSmrg#include "xf86.h" 34e07dc26bSmrg#define NEED_XF86_TYPES 35e07dc26bSmrg#include "compiler.h" 36e07dc26bSmrg#include "cursorstr.h" 37e07dc26bSmrg#include "servermd.h" 38e07dc26bSmrg 39e07dc26bSmrg#include "vboxvideo.h" 40e07dc26bSmrg 41e07dc26bSmrg#ifdef XORG_7X 42e07dc26bSmrg# include <stdlib.h> 43e07dc26bSmrg# include <string.h> 44e07dc26bSmrg#endif 45e07dc26bSmrg 46e07dc26bSmrg#define VBOX_MAX_CURSOR_WIDTH 64 47e07dc26bSmrg#define VBOX_MAX_CURSOR_HEIGHT 64 48e07dc26bSmrg 49e07dc26bSmrg/************************************************************************** 50e07dc26bSmrg* Debugging functions and macros * 51e07dc26bSmrg**************************************************************************/ 52e07dc26bSmrg 53e07dc26bSmrg/* #define DEBUG_POINTER */ 54e07dc26bSmrg 55e07dc26bSmrg#ifdef DEBUG 56e07dc26bSmrg# define PUT_PIXEL(c) ErrorF ("%c", c) 57e07dc26bSmrg#else /* DEBUG_VIDEO not defined */ 58e07dc26bSmrg# define PUT_PIXEL(c) do { } while(0) 59e07dc26bSmrg#endif /* DEBUG_VIDEO not defined */ 60e07dc26bSmrg 61e07dc26bSmrg/** Macro to printf an error message and return from a function */ 62e07dc26bSmrg#define RETERROR(scrnIndex, RetVal, ...) \ 63e07dc26bSmrg do \ 64e07dc26bSmrg { \ 65e07dc26bSmrg xf86DrvMsg(scrnIndex, X_ERROR, __VA_ARGS__); \ 66e07dc26bSmrg return RetVal; \ 67e07dc26bSmrg } \ 68e07dc26bSmrg while (0) 69e07dc26bSmrg 70e07dc26bSmrg/** Structure to pass cursor image data between realise_cursor() and 71e07dc26bSmrg * load_cursor_image(). The members match the parameters to 72e07dc26bSmrg * @a VBoxHGSMIUpdatePointerShape(). */ 73e07dc26bSmrgstruct vboxCursorImage 74e07dc26bSmrg{ 75e07dc26bSmrg uint32_t fFlags; 76e07dc26bSmrg uint32_t cHotX; 77e07dc26bSmrg uint32_t cHotY; 78e07dc26bSmrg uint32_t cWidth; 79e07dc26bSmrg uint32_t cHeight; 80e07dc26bSmrg uint8_t *pPixels; 81e07dc26bSmrg uint32_t cbLength; 82e07dc26bSmrg}; 83e07dc26bSmrg 84e07dc26bSmrg#ifdef DEBUG_POINTER 85e07dc26bSmrgstatic void 86e07dc26bSmrgvbox_show_shape(unsigned short w, unsigned short h, CARD32 bg, unsigned char *image) 87e07dc26bSmrg{ 88e07dc26bSmrg size_t x, y; 89e07dc26bSmrg unsigned short pitch; 90e07dc26bSmrg CARD32 *color; 91e07dc26bSmrg unsigned char *mask; 92e07dc26bSmrg size_t sizeMask; 93e07dc26bSmrg 94e07dc26bSmrg image += sizeof(struct vboxCursorImage); 95e07dc26bSmrg mask = image; 96e07dc26bSmrg pitch = (w + 7) / 8; 97e07dc26bSmrg sizeMask = (pitch * h + 3) & ~3; 98e07dc26bSmrg color = (CARD32 *)(image + sizeMask); 99e07dc26bSmrg 100e07dc26bSmrg TRACE_ENTRY(); 101e07dc26bSmrg for (y = 0; y < h; ++y, mask += pitch, color += w) 102e07dc26bSmrg { 103e07dc26bSmrg for (x = 0; x < w; ++x) 104e07dc26bSmrg { 105e07dc26bSmrg if (mask[x / 8] & (1 << (7 - (x % 8)))) 106e07dc26bSmrg ErrorF (" "); 107e07dc26bSmrg else 108e07dc26bSmrg { 109e07dc26bSmrg CARD32 c = color[x]; 110e07dc26bSmrg if (c == bg) 111e07dc26bSmrg ErrorF("Y"); 112e07dc26bSmrg else 113e07dc26bSmrg ErrorF("X"); 114e07dc26bSmrg } 115e07dc26bSmrg } 116e07dc26bSmrg ErrorF("\n"); 117e07dc26bSmrg } 118e07dc26bSmrg} 119e07dc26bSmrg#endif 120e07dc26bSmrg 121e07dc26bSmrg/************************************************************************** 122e07dc26bSmrg* Main functions * 123e07dc26bSmrg**************************************************************************/ 124e07dc26bSmrg 125e07dc26bSmrgvoid vbvxCursorTerm(VBOXPtr pVBox) 126e07dc26bSmrg{ 127e07dc26bSmrg TRACE_ENTRY(); 128e07dc26bSmrg 129e07dc26bSmrg xf86DestroyCursorInfoRec(pVBox->pCurs); 130e07dc26bSmrg pVBox->pCurs = NULL; 131e07dc26bSmrg TRACE_EXIT(); 132e07dc26bSmrg} 133e07dc26bSmrg 134e07dc26bSmrgstatic void 135e07dc26bSmrgvbox_vmm_hide_cursor(ScrnInfoPtr pScrn, VBOXPtr pVBox) 136e07dc26bSmrg{ 137e07dc26bSmrg int rc; 138e07dc26bSmrg RT_NOREF(pScrn); 139e07dc26bSmrg 140e07dc26bSmrg rc = VBoxHGSMIUpdatePointerShape(&pVBox->guestCtx, 0, 0, 0, 0, 0, NULL, 0); 141e07dc26bSmrg AssertMsg(rc == VINF_SUCCESS, ("Could not hide the virtual mouse pointer, VBox error %d.\n", rc)); 142e07dc26bSmrg} 143e07dc26bSmrg 144e07dc26bSmrgstatic void 145e07dc26bSmrgvbox_vmm_show_cursor(ScrnInfoPtr pScrn, VBOXPtr pVBox) 146e07dc26bSmrg{ 147e07dc26bSmrg int rc; 148e07dc26bSmrg RT_NOREF(pScrn); 149e07dc26bSmrg 150e07dc26bSmrg if (!pVBox->fUseHardwareCursor) 151e07dc26bSmrg return; 152e07dc26bSmrg rc = VBoxHGSMIUpdatePointerShape(&pVBox->guestCtx, VBOX_MOUSE_POINTER_VISIBLE, 153e07dc26bSmrg 0, 0, 0, 0, NULL, 0); 154e07dc26bSmrg AssertMsg(rc == VINF_SUCCESS, ("Could not unhide the virtual mouse pointer.\n")); 155e07dc26bSmrg} 156e07dc26bSmrg 157e07dc26bSmrgstatic void 158e07dc26bSmrgvbox_vmm_load_cursor_image(ScrnInfoPtr pScrn, VBOXPtr pVBox, 159e07dc26bSmrg unsigned char *pvImage) 160e07dc26bSmrg{ 161e07dc26bSmrg int rc; 162e07dc26bSmrg struct vboxCursorImage *pImage; 163e07dc26bSmrg pImage = (struct vboxCursorImage *)pvImage; 164e07dc26bSmrg RT_NOREF(pScrn); 165e07dc26bSmrg 166e07dc26bSmrg#ifdef DEBUG_POINTER 167e07dc26bSmrg vbox_show_shape(pImage->cWidth, pImage->cHeight, 0, pvImage); 168e07dc26bSmrg#endif 169e07dc26bSmrg 170e07dc26bSmrg rc = VBoxHGSMIUpdatePointerShape(&pVBox->guestCtx, pImage->fFlags, 171e07dc26bSmrg pImage->cHotX, pImage->cHotY, pImage->cWidth, pImage->cHeight, 172e07dc26bSmrg pImage->pPixels, pImage->cbLength); 173e07dc26bSmrg AssertMsg(rc == VINF_SUCCESS, ("Unable to set the virtual mouse pointer image.\n")); 174e07dc26bSmrg} 175e07dc26bSmrg 176e07dc26bSmrgstatic void 177e07dc26bSmrgvbox_set_cursor_colors(ScrnInfoPtr pScrn, int bg, int fg) 178e07dc26bSmrg{ 179e07dc26bSmrg RT_NOREF(pScrn); 180e07dc26bSmrg RT_NOREF(bg); 181e07dc26bSmrg RT_NOREF(fg); 182e07dc26bSmrg /* ErrorF("vbox_set_cursor_colors NOT IMPLEMENTED\n"); */ 183e07dc26bSmrg} 184e07dc26bSmrg 185e07dc26bSmrg 186e07dc26bSmrgstatic void 187e07dc26bSmrgvbox_set_cursor_position(ScrnInfoPtr pScrn, int x, int y) 188e07dc26bSmrg{ 189e07dc26bSmrg VBOXPtr pVBox = pScrn->driverPrivate; 190e07dc26bSmrg 191e07dc26bSmrg /* This currently does nothing. */ 192e07dc26bSmrg VBoxHGSMICursorPosition(&pVBox->guestCtx, true, x, y, NULL, NULL); 193e07dc26bSmrg} 194e07dc26bSmrg 195e07dc26bSmrgstatic void 196e07dc26bSmrgvbox_hide_cursor(ScrnInfoPtr pScrn) 197e07dc26bSmrg{ 198e07dc26bSmrg VBOXPtr pVBox = pScrn->driverPrivate; 199e07dc26bSmrg 200e07dc26bSmrg vbox_vmm_hide_cursor(pScrn, pVBox); 201e07dc26bSmrg} 202e07dc26bSmrg 203e07dc26bSmrgstatic void 204e07dc26bSmrgvbox_show_cursor(ScrnInfoPtr pScrn) 205e07dc26bSmrg{ 206e07dc26bSmrg VBOXPtr pVBox = pScrn->driverPrivate; 207e07dc26bSmrg 208e07dc26bSmrg vbox_vmm_show_cursor(pScrn, pVBox); 209e07dc26bSmrg} 210e07dc26bSmrg 211e07dc26bSmrgstatic void 212e07dc26bSmrgvbox_load_cursor_image(ScrnInfoPtr pScrn, unsigned char *image) 213e07dc26bSmrg{ 214e07dc26bSmrg VBOXPtr pVBox = pScrn->driverPrivate; 215e07dc26bSmrg 216e07dc26bSmrg vbox_vmm_load_cursor_image(pScrn, pVBox, image); 217e07dc26bSmrg} 218e07dc26bSmrg 219e07dc26bSmrgstatic Bool 220e07dc26bSmrgvbox_use_hw_cursor(ScreenPtr pScreen, CursorPtr pCurs) 221e07dc26bSmrg{ 222e07dc26bSmrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 223e07dc26bSmrg VBOXPtr pVBox = pScrn->driverPrivate; 224e07dc26bSmrg RT_NOREF(pCurs); 225e07dc26bSmrg return pVBox->fUseHardwareCursor; 226e07dc26bSmrg} 227e07dc26bSmrg 228e07dc26bSmrgstatic unsigned char 229e07dc26bSmrgcolor_to_byte(unsigned c) 230e07dc26bSmrg{ 231e07dc26bSmrg return (c >> 8) & 0xff; 232e07dc26bSmrg} 233e07dc26bSmrg 234e07dc26bSmrgstatic unsigned char * 235e07dc26bSmrgvbox_realize_cursor(xf86CursorInfoPtr infoPtr, CursorPtr pCurs) 236e07dc26bSmrg{ 237e07dc26bSmrg VBOXPtr pVBox; 238e07dc26bSmrg CursorBitsPtr bitsp; 239e07dc26bSmrg unsigned short w, h, x, y; 240e07dc26bSmrg unsigned char *c, *p, *pm, *ps, *m; 241e07dc26bSmrg size_t sizeRequest, sizeRgba, sizeMask, srcPitch, dstPitch; 242e07dc26bSmrg CARD32 fc, bc, *cp; 243e07dc26bSmrg int scrnIndex = infoPtr->pScrn->scrnIndex; 244e07dc26bSmrg struct vboxCursorImage *pImage; 245e07dc26bSmrg 246e07dc26bSmrg pVBox = infoPtr->pScrn->driverPrivate; 247e07dc26bSmrg bitsp = pCurs->bits; 248e07dc26bSmrg w = bitsp->width; 249e07dc26bSmrg h = bitsp->height; 250e07dc26bSmrg 251e07dc26bSmrg if (!w || !h || w > VBOX_MAX_CURSOR_WIDTH || h > VBOX_MAX_CURSOR_HEIGHT) 252e07dc26bSmrg RETERROR(scrnIndex, NULL, 253e07dc26bSmrg "Error invalid cursor dimensions %dx%d\n", w, h); 254e07dc26bSmrg 255e07dc26bSmrg if ((bitsp->xhot > w) || (bitsp->yhot > h)) 256e07dc26bSmrg RETERROR(scrnIndex, NULL, 257e07dc26bSmrg "Error invalid cursor hotspot location %dx%d (max %dx%d)\n", 258e07dc26bSmrg bitsp->xhot, bitsp->yhot, w, h); 259e07dc26bSmrg 260e07dc26bSmrg srcPitch = PixmapBytePad (bitsp->width, 1); 261e07dc26bSmrg dstPitch = (w + 7) / 8; 262e07dc26bSmrg sizeMask = ((dstPitch * h) + 3) & (size_t) ~3; 263e07dc26bSmrg sizeRgba = w * h * 4; 264e07dc26bSmrg sizeRequest = sizeMask + sizeRgba + sizeof(*pImage); 265e07dc26bSmrg 266e07dc26bSmrg p = c = calloc (1, sizeRequest); 267e07dc26bSmrg if (!c) 268e07dc26bSmrg RETERROR(scrnIndex, NULL, 269e07dc26bSmrg "Error failed to alloc %lu bytes for cursor\n", 270e07dc26bSmrg (unsigned long) sizeRequest); 271e07dc26bSmrg 272e07dc26bSmrg pImage = (struct vboxCursorImage *)p; 273e07dc26bSmrg pImage->pPixels = m = p + sizeof(*pImage); 274e07dc26bSmrg cp = (CARD32 *)(m + sizeMask); 275e07dc26bSmrg 276e07dc26bSmrg TRACE_LOG ("w=%d h=%d sm=%d sr=%d p=%d\n", 277e07dc26bSmrg w, h, (int) sizeMask, (int) sizeRgba, (int) dstPitch); 278e07dc26bSmrg TRACE_LOG ("m=%p c=%p cp=%p\n", m, c, (void *)cp); 279e07dc26bSmrg 280e07dc26bSmrg fc = color_to_byte (pCurs->foreBlue) 281e07dc26bSmrg | (color_to_byte (pCurs->foreGreen) << 8) 282e07dc26bSmrg | (color_to_byte (pCurs->foreRed) << 16); 283e07dc26bSmrg 284e07dc26bSmrg bc = color_to_byte (pCurs->backBlue) 285e07dc26bSmrg | (color_to_byte (pCurs->backGreen) << 8) 286e07dc26bSmrg | (color_to_byte (pCurs->backRed) << 16); 287e07dc26bSmrg 288e07dc26bSmrg /* 289e07dc26bSmrg * Convert the Xorg source/mask bits to the and/xor bits VBox needs. 290e07dc26bSmrg * Xorg: 291e07dc26bSmrg * The mask is a bitmap indicating which parts of the cursor are 292e07dc26bSmrg * transparent and which parts are drawn. The source is a bitmap 293e07dc26bSmrg * indicating which parts of the non-transparent portion of the 294e07dc26bSmrg * the cursor should be painted in the foreground color and which 295e07dc26bSmrg * should be painted in the background color. By default, set bits 296e07dc26bSmrg * indicate the opaque part of the mask bitmap and clear bits 297e07dc26bSmrg * indicate the transparent part. 298e07dc26bSmrg * VBox: 299e07dc26bSmrg * The color data is the XOR mask. The AND mask bits determine 300e07dc26bSmrg * which pixels of the color data (XOR mask) will replace (overwrite) 301e07dc26bSmrg * the screen pixels (AND mask bit = 0) and which ones will be XORed 302e07dc26bSmrg * with existing screen pixels (AND mask bit = 1). 303e07dc26bSmrg * For example when you have the AND mask all 0, then you see the 304e07dc26bSmrg * correct mouse pointer image surrounded by black square. 305e07dc26bSmrg */ 306e07dc26bSmrg for (pm = bitsp->mask, ps = bitsp->source, y = 0; 307e07dc26bSmrg y < h; 308e07dc26bSmrg ++y, pm += srcPitch, ps += srcPitch, m += dstPitch) 309e07dc26bSmrg { 310e07dc26bSmrg for (x = 0; x < w; ++x) 311e07dc26bSmrg { 312e07dc26bSmrg if (pm[x / 8] & (1 << (x % 8))) 313e07dc26bSmrg { 314e07dc26bSmrg /* opaque, leave AND mask bit at 0 */ 315e07dc26bSmrg if (ps[x / 8] & (1 << (x % 8))) 316e07dc26bSmrg { 317e07dc26bSmrg *cp++ = fc; 318e07dc26bSmrg PUT_PIXEL('X'); 319e07dc26bSmrg } 320e07dc26bSmrg else 321e07dc26bSmrg { 322e07dc26bSmrg *cp++ = bc; 323e07dc26bSmrg PUT_PIXEL('*'); 324e07dc26bSmrg } 325e07dc26bSmrg } 326e07dc26bSmrg else 327e07dc26bSmrg { 328e07dc26bSmrg /* transparent, set AND mask bit */ 329e07dc26bSmrg m[x / 8] |= 1 << (7 - (x % 8)); 330e07dc26bSmrg /* don't change the screen pixel */ 331e07dc26bSmrg *cp++ = 0; 332e07dc26bSmrg PUT_PIXEL(' '); 333e07dc26bSmrg } 334e07dc26bSmrg } 335e07dc26bSmrg PUT_PIXEL('\n'); 336e07dc26bSmrg } 337e07dc26bSmrg 338e07dc26bSmrg pImage->cWidth = w; 339e07dc26bSmrg pImage->cHeight = h; 340e07dc26bSmrg pImage->cHotX = bitsp->xhot; 341e07dc26bSmrg pImage->cHotY = bitsp->yhot; 342e07dc26bSmrg pImage->fFlags = VBOX_MOUSE_POINTER_VISIBLE | VBOX_MOUSE_POINTER_SHAPE; 343e07dc26bSmrg pImage->cbLength = sizeRequest - sizeof(*pImage); 344e07dc26bSmrg 345e07dc26bSmrg#ifdef DEBUG_POINTER 346e07dc26bSmrg ErrorF("shape = %p\n", p); 347e07dc26bSmrg vbox_show_shape(w, h, bc, c); 348e07dc26bSmrg#endif 349e07dc26bSmrg 350e07dc26bSmrg return p; 351e07dc26bSmrg} 352e07dc26bSmrg 353e07dc26bSmrg#ifdef ARGB_CURSOR 354e07dc26bSmrgstatic Bool 355e07dc26bSmrgvbox_use_hw_cursor_argb(ScreenPtr pScreen, CursorPtr pCurs) 356e07dc26bSmrg{ 357e07dc26bSmrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 358e07dc26bSmrg VBOXPtr pVBox = pScrn->driverPrivate; 359e07dc26bSmrg 360e07dc26bSmrg if (!pVBox->fUseHardwareCursor) 361e07dc26bSmrg return FALSE; 362e07dc26bSmrg if ( (pCurs->bits->height > VBOX_MAX_CURSOR_HEIGHT) 363e07dc26bSmrg || (pCurs->bits->width > VBOX_MAX_CURSOR_WIDTH) 364e07dc26bSmrg || (pScrn->bitsPerPixel <= 8)) 365e07dc26bSmrg return FALSE; 366e07dc26bSmrg return TRUE; 367e07dc26bSmrg} 368e07dc26bSmrg 369e07dc26bSmrg 370e07dc26bSmrgstatic void 371e07dc26bSmrgvbox_load_cursor_argb(ScrnInfoPtr pScrn, CursorPtr pCurs) 372e07dc26bSmrg{ 373e07dc26bSmrg VBOXPtr pVBox; 374e07dc26bSmrg CursorBitsPtr bitsp; 375e07dc26bSmrg unsigned short w, h; 376e07dc26bSmrg unsigned short cx, cy; 377e07dc26bSmrg unsigned char *pm; 378e07dc26bSmrg CARD32 *pc; 379e07dc26bSmrg size_t sizeData, sizeMask; 380e07dc26bSmrg CARD8 *p; 381e07dc26bSmrg int scrnIndex; 382e07dc26bSmrg uint32_t fFlags = VBOX_MOUSE_POINTER_VISIBLE | VBOX_MOUSE_POINTER_SHAPE 383e07dc26bSmrg | VBOX_MOUSE_POINTER_ALPHA; 384e07dc26bSmrg 385e07dc26bSmrg pVBox = pScrn->driverPrivate; 386e07dc26bSmrg bitsp = pCurs->bits; 387e07dc26bSmrg w = bitsp->width; 388e07dc26bSmrg h = bitsp->height; 389e07dc26bSmrg scrnIndex = pScrn->scrnIndex; 390e07dc26bSmrg 391e07dc26bSmrg /* Mask must be generated for alpha cursors, that is required by VBox. */ 392e07dc26bSmrg /* note: (michael) the next struct must be 32bit aligned. */ 393e07dc26bSmrg sizeMask = ((w + 7) / 8 * h + 3) & ~3; 394e07dc26bSmrg 395e07dc26bSmrg if (!w || !h || w > VBOX_MAX_CURSOR_WIDTH || h > VBOX_MAX_CURSOR_HEIGHT) 396e07dc26bSmrg RETERROR(scrnIndex, , 397e07dc26bSmrg "Error invalid cursor dimensions %dx%d\n", w, h); 398e07dc26bSmrg 399e07dc26bSmrg if ((bitsp->xhot > w) || (bitsp->yhot > h)) 400e07dc26bSmrg RETERROR(scrnIndex, , 401e07dc26bSmrg "Error invalid cursor hotspot location %dx%d (max %dx%d)\n", 402e07dc26bSmrg bitsp->xhot, bitsp->yhot, w, h); 403e07dc26bSmrg 404e07dc26bSmrg sizeData = w * h * 4 + sizeMask; 405e07dc26bSmrg p = calloc(1, sizeData); 406e07dc26bSmrg if (!p) 407e07dc26bSmrg RETERROR(scrnIndex, , 408e07dc26bSmrg "Error failed to alloc %lu bytes for cursor\n", 409e07dc26bSmrg (unsigned long)sizeData); 410e07dc26bSmrg 411e07dc26bSmrg memcpy(p + sizeMask, bitsp->argb, w * h * 4); 412e07dc26bSmrg 413e07dc26bSmrg /* Emulate the AND mask. */ 414e07dc26bSmrg pm = p; 415e07dc26bSmrg pc = bitsp->argb; 416e07dc26bSmrg 417e07dc26bSmrg /* Init AND mask to 1 */ 418e07dc26bSmrg memset(pm, 0xFF, sizeMask); 419e07dc26bSmrg 420e07dc26bSmrg /* 421e07dc26bSmrg * The additions driver must provide the AND mask for alpha cursors. The host frontend 422e07dc26bSmrg * which can handle alpha channel, will ignore the AND mask and draw an alpha cursor. 423e07dc26bSmrg * But if the host does not support ARGB, then it simply uses the AND mask and the color 424e07dc26bSmrg * data to draw a normal color cursor. 425e07dc26bSmrg */ 426e07dc26bSmrg for (cy = 0; cy < h; cy++) 427e07dc26bSmrg { 428e07dc26bSmrg unsigned char bitmask = 0x80; 429e07dc26bSmrg 430e07dc26bSmrg for (cx = 0; cx < w; cx++, bitmask >>= 1) 431e07dc26bSmrg { 432e07dc26bSmrg if (bitmask == 0) 433e07dc26bSmrg bitmask = 0x80; 434e07dc26bSmrg 435e07dc26bSmrg if (pc[cx] >= 0xF0000000) 436e07dc26bSmrg pm[cx / 8] &= ~bitmask; 437e07dc26bSmrg } 438e07dc26bSmrg 439e07dc26bSmrg /* Point to next source and dest scans */ 440e07dc26bSmrg pc += w; 441e07dc26bSmrg pm += (w + 7) / 8; 442e07dc26bSmrg } 443e07dc26bSmrg 444e07dc26bSmrg VBoxHGSMIUpdatePointerShape(&pVBox->guestCtx, fFlags, bitsp->xhot, 445e07dc26bSmrg bitsp->yhot, w, h, p, sizeData); 446e07dc26bSmrg free(p); 447e07dc26bSmrg} 448e07dc26bSmrg#endif 449e07dc26bSmrg 450e07dc26bSmrgBool vbvxCursorInit(ScreenPtr pScreen) 451e07dc26bSmrg{ 452e07dc26bSmrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 453e07dc26bSmrg VBOXPtr pVBox = pScrn->driverPrivate; 454e07dc26bSmrg xf86CursorInfoPtr pCurs = NULL; 455e07dc26bSmrg Bool rc = TRUE; 456e07dc26bSmrg 457e07dc26bSmrg TRACE_ENTRY(); 458e07dc26bSmrg pVBox->pCurs = pCurs = xf86CreateCursorInfoRec(); 459e07dc26bSmrg if (!pCurs) { 460e07dc26bSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 461e07dc26bSmrg "Failed to create X Window cursor information structures for virtual mouse.\n"); 462e07dc26bSmrg rc = FALSE; 463e07dc26bSmrg } 464e07dc26bSmrg if (rc) { 465e07dc26bSmrg pCurs->MaxWidth = VBOX_MAX_CURSOR_WIDTH; 466e07dc26bSmrg pCurs->MaxHeight = VBOX_MAX_CURSOR_HEIGHT; 467e07dc26bSmrg pCurs->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP 468e07dc26bSmrg | HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 469e07dc26bSmrg | HARDWARE_CURSOR_BIT_ORDER_MSBFIRST 470e07dc26bSmrg | HARDWARE_CURSOR_UPDATE_UNHIDDEN; 471e07dc26bSmrg 472e07dc26bSmrg pCurs->SetCursorColors = vbox_set_cursor_colors; 473e07dc26bSmrg pCurs->SetCursorPosition = vbox_set_cursor_position; 474e07dc26bSmrg pCurs->LoadCursorImage = vbox_load_cursor_image; 475e07dc26bSmrg pCurs->HideCursor = vbox_hide_cursor; 476e07dc26bSmrg pCurs->ShowCursor = vbox_show_cursor; 477e07dc26bSmrg pCurs->UseHWCursor = vbox_use_hw_cursor; 478e07dc26bSmrg pCurs->RealizeCursor = vbox_realize_cursor; 479e07dc26bSmrg 480e07dc26bSmrg#ifdef ARGB_CURSOR 481e07dc26bSmrg pCurs->UseHWCursorARGB = vbox_use_hw_cursor_argb; 482e07dc26bSmrg pCurs->LoadCursorARGB = vbox_load_cursor_argb; 483e07dc26bSmrg#endif 484e07dc26bSmrg 485e07dc26bSmrg rc = xf86InitCursor(pScreen, pCurs); 486e07dc26bSmrg } 487e07dc26bSmrg if (!rc) 488e07dc26bSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 489e07dc26bSmrg "Failed to enable mouse pointer integration.\n"); 490e07dc26bSmrg if (!rc && (pCurs != NULL)) 491e07dc26bSmrg xf86DestroyCursorInfoRec(pCurs); 492e07dc26bSmrg return rc; 493e07dc26bSmrg} 494