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