2
* Linux Additions X11 graphics driver helper module
6
* Copyright (C) 2006-2007 Oracle Corporation
8
* This file is part of VirtualBox Open Source Edition (OSE), as
9
* available from http://www.virtualbox.org. This file is free software;
10
* you can redistribute it and/or modify it under the terms of the GNU
11
* General Public License (GPL) as published by the Free Software
12
* Foundation, in version 2 as it comes in the "COPYING" file of the
13
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17
#include <VBox/VBoxGuest.h>
18
#include <VBox/VBoxGuestLib.h>
24
#define NEED_XF86_TYPES
25
#include "xf86_ansic.h"
27
#include "cursorstr.h"
29
#include "vboxvideo_68.h"
31
#define VBOX_MAX_CURSOR_WIDTH 64
32
#define VBOX_MAX_CURSOR_HEIGHT 64
38
#define TRACE_ENTRY() do \
40
ErrorF ("%s\n", __FUNCTION__); \
42
#define TRACE_LINE() do \
44
ErrorF ("%s: line %d\n", __FUNCTION__, __LINE__); \
46
#define PUT_PIXEL(c) ErrorF ("%c", c)
47
#define dolog(...) ErrorF (__VA_ARGS__)
49
#define PUT_PIXEL(c) do { } while(0)
50
#define TRACE_ENTRY() do { } while(0)
51
#define TRACE_LINE() do { } while(0)
52
#define dolog(...) do { } while(0)
55
/** Macro to printf an error message and return from a function */
56
#define RETERROR(scrnIndex, RetVal, ...) \
59
xf86DrvMsg(scrnIndex, X_ERROR, __VA_ARGS__); \
65
static void vbox_show_shape (unsigned short w, unsigned short h,
66
CARD32 bg, unsigned char *image)
74
image += offsetof (VMMDevReqMousePointer, pointerData);
77
size_mask = (pitch * h + 3) & ~3;
78
color = (CARD32 *) (image + size_mask);
81
for (y = 0; y < h; ++y, mask += pitch, color += w)
83
for (x = 0; x < w; ++x)
85
if (mask[x / 8] & (1 << (7 - (x % 8))))
102
static Bool vbox_vmmcall (ScrnInfoPtr pScrn, VBOXPtr pVBox,
103
VMMDevRequestHeader *hdrp)
109
err = ioctl (pVBox->vbox_fd, VBOXGUEST_IOCTL_VMMREQUEST(hdrp->size), hdrp);
112
* @todo this should work fine on other platforms too, but it needs to be
113
* checked for each one.
118
RETERROR(pScrn->scrnIndex, FALSE,
119
"Ioctl call failed during a request to the virtual machine: %s\n",
122
if (RT_FAILURE (hdrp->rc))
123
RETERROR(pScrn->scrnIndex, FALSE,
124
"A request to the virtual machine returned %d\n",
132
vbox_host_uses_hwcursor(ScrnInfoPtr pScrn)
135
VBOXPtr pVBox = pScrn->driverPrivate;
136
VMMDevReqMouseStatus req;
138
/* We may want to force the use of a software cursor. Currently this is
139
* needed if the guest uses a large virtual resolution, as in this case
140
* the host and guest tend to disagree about the pointer location. */
141
if (pVBox->forceSWCursor)
145
int vrc = vmmdevInitRequest ((VMMDevRequestHeader*)&req, VMMDevReq_GetMouseStatus);
146
if (RT_FAILURE (vrc))
147
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
148
"Unable to determine whether the virtual machine supports mouse pointer integration - request initialization failed with return code %d\n", rc);
151
&& (ioctl(pVBox->vbox_fd, VBOXGUEST_IOCTL_VMMREQUEST(sizeof(req)), (void*)&req) < 0))
156
vrc = VERR_FILE_IO_ERROR;
157
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
158
"Unable to determine whether the virtual machine supports mouse pointer integration - request system call failed: %s.\n",
162
&& !(req.mouseFeatures & VMMDEV_MOUSE_HOST_CANNOT_HWPOINTER)
163
&& (req.mouseFeatures & VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE))
171
vbox_close(ScrnInfoPtr pScrn, VBOXPtr pVBox)
181
if (close (pVBox->vbox_fd))
182
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
183
"Unable to close the virtual machine device (file %d): %s\n",
184
pVBox->vbox_fd, strerror (errno));
190
* Macro to disable VBVA extensions and return, for use when an
191
* unexplained error occurs.
193
#define DISABLE_VBVA_AND_RETURN(pScrn, ...) \
196
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, __VA_ARGS__); \
197
vboxDisableVbva(pScrn); \
198
pVBox->useVbva = FALSE; \
204
* Callback function called by the X server to tell us about dirty
205
* rectangles in the video buffer.
207
* @param pScreen pointer to the information structure for the current
209
* @param iRects Number of dirty rectangles to update
210
* @param aRects Array of structures containing the coordinates of the
214
vboxHandleDirtyRect(ScrnInfoPtr pScrn, int iRects, BoxPtr aRects)
220
CARD32 indexRecordNext;
224
CARD32 cbHwBufferAvail;
228
pVBox = pScrn->driverPrivate;
229
if (pVBox->useVbva == FALSE)
231
pMem = pVBox->pVbvaMemory;
232
/* Just return quietly if VBVA is not currently active. */
233
if ((pMem->fu32ModeFlags & VBVA_F_MODE_ENABLED) == 0)
235
scrnIndex = pScrn->scrnIndex;
237
for (i = 0; i < iRects; i++)
239
cmdHdr.x = (int16_t)aRects[i].x1 - pVBox->viewportX;
240
cmdHdr.y = (int16_t)aRects[i].y1 - pVBox->viewportY;
241
cmdHdr.w = (uint16_t)(aRects[i].x2 - aRects[i].x1);
242
cmdHdr.h = (uint16_t)(aRects[i].y2 - aRects[i].y1);
244
/* Get the active record and move the pointer along */
245
indexRecordNext = (pMem->indexRecordFree + 1)
247
if (indexRecordNext == pMem->indexRecordFirst)
249
/* All slots in the records queue are used. */
250
if (vbox_vmmcall(pScrn, pVBox,
251
(VMMDevRequestHeader *) pVBox->reqf) != TRUE)
252
DISABLE_VBVA_AND_RETURN(pScrn,
253
"Unable to clear the VirtualBox graphics acceleration queue "
254
"- the request to the virtual machine failed. Switching to "
255
"unaccelerated mode.\n");
257
if (indexRecordNext == pMem->indexRecordFirst)
258
DISABLE_VBVA_AND_RETURN(pScrn,
259
"Failed to clear the VirtualBox graphics acceleration queue. "
260
"Switching to unaccelerated mode.\n");
261
pRecord = &pMem->aRecords[pMem->indexRecordFree];
262
/* Mark the record as being updated. */
263
pRecord->cbRecord = VBVA_F_RECORD_PARTIAL;
264
pMem->indexRecordFree = indexRecordNext;
265
/* Compute how many bytes we have in the ring buffer. */
266
off32Free = pMem->off32Free;
267
off32Data = pMem->off32Data;
268
/* Free is writing position. Data is reading position.
269
* Data == Free means buffer is free.
270
* There must be always gap between free and data when data
272
* Guest only changes free, host only changes data.
274
i32Diff = off32Data - off32Free;
275
cbHwBufferAvail = i32Diff > 0? i32Diff: VBVA_RING_BUFFER_SIZE
277
if (cbHwBufferAvail <= VBVA_RING_BUFFER_THRESHOLD)
279
if (vbox_vmmcall(pScrn, pVBox,
280
(VMMDevRequestHeader *) pVBox->reqf) != TRUE)
281
DISABLE_VBVA_AND_RETURN(pScrn,
282
"Unable to clear the VirtualBox graphics acceleration queue "
283
"- the request to the virtual machine failed. Switching to "
284
"unaccelerated mode.\n");
285
/* Calculate the free space again. */
286
off32Free = pMem->off32Free;
287
off32Data = pMem->off32Data;
288
i32Diff = off32Data - off32Free;
289
cbHwBufferAvail = i32Diff > 0? i32Diff:
290
VBVA_RING_BUFFER_SIZE + i32Diff;
291
if (cbHwBufferAvail <= VBVA_RING_BUFFER_THRESHOLD)
292
DISABLE_VBVA_AND_RETURN(pScrn,
293
"No space left in the VirtualBox graphics acceleration command buffer, "
294
"despite clearing the queue. Switching to unaccelerated mode.\n");
296
/* Now copy the data into the buffer */
297
if (off32Free + sizeof(cmdHdr) < VBVA_RING_BUFFER_SIZE)
299
memcpy(&pMem->au8RingBuffer[off32Free], &cmdHdr,
301
pMem->off32Free = pMem->off32Free + sizeof(cmdHdr);
305
CARD32 u32First = VBVA_RING_BUFFER_SIZE - off32Free;
306
/* The following is impressively ugly! */
307
CARD8 *pu8Second = (CARD8 *)&cmdHdr + u32First;
308
CARD32 u32Second = sizeof(cmdHdr) - u32First;
309
memcpy(&pMem->au8RingBuffer[off32Free], &cmdHdr, u32First);
311
memcpy(&pMem->au8RingBuffer[0], (void *)pu8Second, u32Second);
312
pMem->off32Free = u32Second;
314
pRecord->cbRecord += sizeof(cmdHdr);
315
/* Mark the record completed. */
316
pRecord->cbRecord &= ~VBVA_F_RECORD_PARTIAL;
322
* Initialise VirtualBox's accelerated video extensions.
323
* Note that we assume that the PCI memory is 32bit mapped,
324
* as X doesn't seem to support mapping 64bit memory.
326
* @returns True on success, false on failure
329
vboxInitVbva(int scrnIndex, ScreenPtr pScreen, VBOXPtr pVBox)
335
/* Locate the device. It should already have been enabled by
336
the kernel driver. */
337
pciTagDev = pciFindFirst((unsigned) VMMDEV_DEVICEID << 16 | VMMDEV_VENDORID,
339
if (pciTagDev == PCI_NOT_FOUND)
341
xf86DrvMsg(scrnIndex, X_ERROR,
342
"Could not find the VirtualBox base device on the PCI bus.\n");
345
/* Read the address and size of the second I/O region. */
346
pciAddrDev = pciReadLong(pciTagDev, PCI_MAP_REG_START + 4);
347
if (pciAddrDev == 0 || pciAddrDev == (CARD32) ~0)
348
RETERROR(scrnIndex, FALSE,
349
"The VirtualBox base device contains an invalid memory address.\n");
350
if (PCI_MAP_IS64BITMEM(pciAddrDev))
351
RETERROR(scrnIndex, FALSE,
352
"The VirtualBox base device has a 64bit mapping address. "
353
"This is currently not supported.\n");
354
/* Map it. We hardcode the size as X does not export the
355
function needed to determine it. */
356
pVBox->pVMMDevMemory = xf86MapPciMem(scrnIndex, 0, pciTagDev, pciAddrDev,
357
sizeof(VMMDevMemory));
358
if (pVBox->pVMMDevMemory == NULL)
360
xf86DrvMsg(scrnIndex, X_ERROR,
361
"Failed to map VirtualBox video extension memory.\n");
364
pVBox->pVbvaMemory = &pVBox->pVMMDevMemory->vbvaMemory;
365
/* Initialise requests */
366
pVBox->reqf = xcalloc(1, vmmdevGetRequestSize(VMMDevReq_VideoAccelFlush));
369
xf86DrvMsg(scrnIndex, X_ERROR,
370
"Could not allocate memory for VBVA flush request.\n");
373
rc = vmmdevInitRequest ((VMMDevRequestHeader *) pVBox->reqf,
374
VMMDevReq_VideoAccelFlush);
377
xf86DrvMsg(scrnIndex, X_ERROR,
378
"Could not initialise VBVA flush request: return value %d\n", rc);
382
pVBox->reqe = xcalloc(1, vmmdevGetRequestSize(VMMDevReq_VideoAccelEnable));
385
xf86DrvMsg(scrnIndex, X_ERROR,
386
"Could not allocate memory for VBVA enable request.\n");
390
rc = vmmdevInitRequest ((VMMDevRequestHeader *) pVBox->reqe,
391
VMMDevReq_VideoAccelEnable);
394
xf86DrvMsg(scrnIndex, X_ERROR,
395
"Could not initialise VBVA enable request: return value = %d\n",
401
/* Set up the dirty rectangle handler. Since this seems to be a
402
delicate operation, and removing it doubly so, this will
403
remain in place whether it is needed or not, and will simply
404
return if VBVA is not active. I assume that it will be active
406
if (ShadowFBInit2(pScreen, NULL, vboxHandleDirtyRect) != TRUE)
408
xf86DrvMsg(scrnIndex, X_ERROR,
409
"Unable to install dirty rectangle handler for VirtualBox graphics acceleration.\n");
418
vbox_open (ScrnInfoPtr pScrn, ScreenPtr pScreen, VBOXPtr pVBox)
423
int scrnIndex = pScrn->scrnIndex;
428
pVBox->useVbva = FALSE;
434
/* still open, just re-enable VBVA after CloseScreen was called */
435
pVBox->useVbva = vboxInitVbva(scrnIndex, pScreen, pVBox);
442
xf86DrvMsg(scrnIndex, X_ERROR, "VbglR3Init failed vrc=%d.\n", vrc);
446
if (pVBox->vbox_fd != -1 && pVBox->reqp)
448
/* still open, just re-enable VBVA after CloseScreen was called */
449
pVBox->useVbva = vboxInitVbva(scrnIndex, pScreen, pVBox);
453
fd = open (VBOXGUEST_DEVICE_NAME, O_RDWR, 0);
456
xf86DrvMsg(scrnIndex, X_ERROR,
457
"Error opening kernel module: %s\n",
464
size = vmmdevGetRequestSize (VMMDevReq_SetPointerShape);
466
p = xcalloc (1, size);
468
xf86DrvMsg(scrnIndex, X_ERROR,
469
"Could not allocate %lu bytes for VMM request\n",
470
(unsigned long) size);
475
vrc = vmmdevInitRequest (p, VMMDevReq_SetPointerShape);
476
if (RT_FAILURE (vrc))
478
xf86DrvMsg(scrnIndex, X_ERROR,
479
"Could not init VMM request: vrc = %d\n", vrc);
484
#ifndef RT_OS_SOLARIS
489
pVBox->pointerHeaderSize = size;
490
pVBox->useVbva = vboxInitVbva(scrnIndex, pScreen, pVBox);
499
xf86DrvMsg(scrnIndex, X_ERROR,
500
"Error closing kernel module file descriptor(%d): %s\n",
501
fd, strerror (errno));
508
static void vbox_vmm_hide_cursor (ScrnInfoPtr pScrn, VBOXPtr pVBox)
510
pVBox->reqp->fFlags = 0;
511
if (vbox_vmmcall (pScrn, pVBox, &pVBox->reqp->header) != TRUE)
512
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
513
"Could not hide the virtual mouse pointer.\n");
516
static void vbox_vmm_show_cursor (ScrnInfoPtr pScrn, VBOXPtr pVBox)
518
pVBox->reqp->fFlags = VBOX_MOUSE_POINTER_VISIBLE;
519
if (vbox_vmmcall (pScrn, pVBox, &pVBox->reqp->header) != TRUE)
520
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
521
"Could not unhide the virtual mouse pointer.\n");
524
static void vbox_vmm_load_cursor_image (ScrnInfoPtr pScrn, VBOXPtr pVBox,
525
unsigned char *image)
527
VMMDevReqMousePointer *reqp;
528
reqp = (VMMDevReqMousePointer *) image;
530
dolog ("w=%d h=%d size=%d\n",
536
vbox_show_shape (reqp->width, reqp->height, 0, image);
539
if (vbox_vmmcall (pScrn, pVBox, &reqp->header) != TRUE)
540
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
541
"Unable to set the virtual mouse pointer image.\n");
544
static void vbox_set_cursor_colors (ScrnInfoPtr pScrn, int bg, int fg)
551
/* ErrorF ("vbox_set_cursor_colors NOT IMPLEMENTED\n"); */
555
vbox_set_cursor_position (ScrnInfoPtr pScrn, int x, int y)
557
(void) pScrn; (void) x; (void) y;
560
static void vbox_hide_cursor (ScrnInfoPtr pScrn)
562
VBOXPtr pVBox = pScrn->driverPrivate;
566
vbox_vmm_hide_cursor (pScrn, pVBox);
569
static void vbox_show_cursor (ScrnInfoPtr pScrn)
571
VBOXPtr pVBox = pScrn->driverPrivate;
575
vbox_vmm_show_cursor (pScrn, pVBox);
578
static void vbox_load_cursor_image (ScrnInfoPtr pScrn, unsigned char *image)
580
VBOXPtr pVBox = pScrn->driverPrivate;
584
vbox_vmm_load_cursor_image (pScrn, pVBox, image);
588
vbox_use_hw_cursor (ScreenPtr pScreen, CursorPtr pCurs)
590
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
591
return vbox_host_uses_hwcursor(pScrn);
594
static unsigned char color_to_byte (unsigned c)
596
return (c >> 8) & 0xff;
599
static unsigned char *
600
vbox_realize_cursor(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)
604
unsigned short w, h, x, y;
605
unsigned char *c, *p, *pm, *ps, *m;
606
size_t size, size_rgba, size_mask, src_pitch, dst_pitch;
608
int rc, scrnIndex = infoPtr->pScrn->scrnIndex;
609
VMMDevReqMousePointer *reqp;
611
pVBox = infoPtr->pScrn->driverPrivate;
616
if (!w || !h || w > VBOX_MAX_CURSOR_WIDTH || h > VBOX_MAX_CURSOR_HEIGHT)
617
RETERROR(scrnIndex, NULL,
618
"Error invalid cursor dimensions %dx%d\n", w, h);
620
if ((bitsp->xhot > w) || (bitsp->yhot > h))
621
RETERROR(scrnIndex, NULL,
622
"Error invalid cursor hotspot location %dx%d (max %dx%d)\n",
623
bitsp->xhot, bitsp->yhot, w, h);
625
src_pitch = PixmapBytePad (bitsp->width, 1);
626
dst_pitch = (w + 7) / 8;
627
size_mask = ((dst_pitch * h) + 3) & (size_t) ~3;
628
size_rgba = w * h * 4;
629
size = size_mask + size_rgba + pVBox->pointerHeaderSize;
631
p = c = xcalloc (1, size);
633
RETERROR(scrnIndex, NULL,
634
"Error failed to alloc %lu bytes for cursor\n",
635
(unsigned long) size);
637
rc = vmmdevInitRequest ((VMMDevRequestHeader *) p,
638
VMMDevReq_SetPointerShape);
639
if (RT_FAILURE (rc)) {
641
RETERROR(scrnIndex, NULL,
642
"Could not init VMM request: rc = %d\n", rc);
645
m = p + offsetof (VMMDevReqMousePointer, pointerData);
646
cp = (CARD32 *) (m + size_mask);
648
dolog ("w=%d h=%d sm=%d sr=%d p=%d\n",
649
w, h, (int) size_mask, (int) size_rgba, (int) dst_pitch);
650
dolog ("m=%p c=%p cp=%p\n", m, c, (void *) (void *)cp);
652
fc = color_to_byte (pCurs->foreBlue)
653
| (color_to_byte (pCurs->foreGreen) << 8)
654
| (color_to_byte (pCurs->foreRed) << 16);
656
bc = color_to_byte (pCurs->backBlue)
657
| (color_to_byte (pCurs->backGreen) << 8)
658
| (color_to_byte (pCurs->backRed) << 16);
661
* Convert the Xorg source/mask bits to the and/xor bits VBox needs.
663
* The mask is a bitmap indicating which parts of the cursor are
664
* transparent and which parts are drawn. The source is a bitmap
665
* indicating which parts of the non-transparent portion of the
666
* the cursor should be painted in the foreground color and which
667
* should be painted in the background color. By default, set bits
668
* indicate the opaque part of the mask bitmap and clear bits
669
* indicate the transparent part.
671
* The color data is the XOR mask. The AND mask bits determine
672
* which pixels of the color data (XOR mask) will replace (overwrite)
673
* the screen pixels (AND mask bit = 0) and which ones will be XORed
674
* with existing screen pixels (AND mask bit = 1).
675
* For example when you have the AND mask all 0, then you see the
676
* correct mouse pointer image surrounded by black square.
678
for (pm = bitsp->mask, ps = bitsp->source, y = 0;
680
++y, pm += src_pitch, ps += src_pitch, m += dst_pitch)
682
for (x = 0; x < w; ++x)
684
if (pm[x / 8] & (1 << (x % 8)))
686
/* opaque, leave AND mask bit at 0 */
687
if (ps[x / 8] & (1 << (x % 8)))
700
/* transparent, set AND mask bit */
701
m[x / 8] |= 1 << (7 - (x % 8));
702
/* don't change the screen pixel */
710
reqp = (VMMDevReqMousePointer *) p;
713
reqp->xHot = bitsp->xhot;
714
reqp->yHot = bitsp->yhot;
715
reqp->fFlags = VBOX_MOUSE_POINTER_SHAPE;
716
reqp->header.size = size;
719
ErrorF ("shape = %p\n", p);
720
vbox_show_shape (w, h, bc, c);
727
static Bool vbox_use_hw_cursor_argb (ScreenPtr pScreen, CursorPtr pCurs)
729
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
732
if (!vbox_host_uses_hwcursor(pScrn))
735
&& ( (pCurs->bits->height > VBOX_MAX_CURSOR_HEIGHT)
736
|| (pCurs->bits->width > VBOX_MAX_CURSOR_WIDTH)
737
|| (pScrn->bitsPerPixel <= 8)
744
static void vbox_load_cursor_argb (ScrnInfoPtr pScrn, CursorPtr pCurs)
747
VMMDevReqMousePointer *reqp;
750
unsigned short cx, cy;
753
size_t size, mask_size;
757
pVBox = pScrn->driverPrivate;
761
scrnIndex = pScrn->scrnIndex;
763
/* Mask must be generated for alpha cursors, that is required by VBox. */
764
/* @note: (michael) the next struct must be 32bit aligned. */
765
mask_size = ((w + 7) / 8 * h + 3) & ~3;
767
if (!w || !h || w > VBOX_MAX_CURSOR_WIDTH || h > VBOX_MAX_CURSOR_HEIGHT)
768
RETERROR(scrnIndex, ,
769
"Error invalid cursor dimensions %dx%d\n", w, h);
771
if ((bitsp->xhot > w) || (bitsp->yhot > h))
772
RETERROR(scrnIndex, ,
773
"Error invalid cursor hotspot location %dx%d (max %dx%d)\n",
774
bitsp->xhot, bitsp->yhot, w, h);
776
size = w * h * 4 + pVBox->pointerHeaderSize + mask_size;
777
p = xcalloc (1, size);
779
RETERROR(scrnIndex, ,
780
"Error failed to alloc %lu bytes for cursor\n",
781
(unsigned long) size);
783
reqp = (VMMDevReqMousePointer *) p;
784
*reqp = *pVBox->reqp;
787
reqp->xHot = bitsp->xhot;
788
reqp->yHot = bitsp->yhot;
789
reqp->fFlags = VBOX_MOUSE_POINTER_SHAPE | VBOX_MOUSE_POINTER_ALPHA;
790
reqp->header.size = size;
792
memcpy (p + offsetof (VMMDevReqMousePointer, pointerData) + mask_size,
793
bitsp->argb, w * h * 4);
796
/* Emulate the AND mask. */
797
pm = p + offsetof (VMMDevReqMousePointer, pointerData);
800
/* Init AND mask to 1 */
801
memset (pm, 0xFF, mask_size);
804
* The additions driver must provide the AND mask for alpha cursors. The host frontend
805
* which can handle alpha channel, will ignore the AND mask and draw an alpha cursor.
806
* But if the host does not support ARGB, then it simply uses the AND mask and the color
807
* data to draw a normal color cursor.
809
for (cy = 0; cy < h; cy++)
811
unsigned char bitmask = 0x80;
813
for (cx = 0; cx < w; cx++, bitmask >>= 1)
818
if (pc[cx] >= 0xF0000000)
819
pm[cx / 8] &= ~bitmask;
822
/* Point to next source and dest scans */
827
if (vbox_vmmcall (pScrn, pVBox, &reqp->header) != TRUE)
828
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
829
"Request to virtual machine failed "
830
"- unable to set the virtual mouse pointer ARGB cursor image.\n");
836
Bool vbox_cursor_init (ScreenPtr pScreen)
838
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
839
VBOXPtr pVBox = pScrn->driverPrivate;
840
xf86CursorInfoPtr pCurs;
843
pVBox->pCurs = pCurs = xf86CreateCursorInfoRec ();
845
RETERROR(pScrn->scrnIndex, FALSE,
846
"Failed to create X Window cursor information structures for virtual mouse.\n");
848
pCurs->MaxWidth = VBOX_MAX_CURSOR_WIDTH;
849
pCurs->MaxHeight = VBOX_MAX_CURSOR_HEIGHT;
850
pCurs->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP
851
| HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1
852
| HARDWARE_CURSOR_BIT_ORDER_MSBFIRST;
854
pCurs->SetCursorColors = vbox_set_cursor_colors;
855
pCurs->SetCursorPosition = vbox_set_cursor_position;
856
pCurs->LoadCursorImage = vbox_load_cursor_image;
857
pCurs->HideCursor = vbox_hide_cursor;
858
pCurs->ShowCursor = vbox_show_cursor;
859
pCurs->UseHWCursor = vbox_use_hw_cursor;
860
pCurs->RealizeCursor = vbox_realize_cursor;
863
pCurs->UseHWCursorARGB = vbox_use_hw_cursor_argb;
864
pCurs->LoadCursorARGB = vbox_load_cursor_argb;
867
/* Hide the host cursor before we initialise if we wish to use a
868
* software cursor. */
869
if (pVBox->forceSWCursor)
870
vbox_vmm_hide_cursor(pScrn, pVBox);
871
rc = xf86InitCursor (pScreen, pCurs);
874
RETERROR(pScrn->scrnIndex, FALSE, "Failed to enable mouse pointer integration.\n");
878
* Inform VBox that we will supply it with dirty rectangle information
879
* and install the dirty rectangle handler.
881
* @returns TRUE for success, FALSE for failure
882
* @param pScreen Pointer to a structure describing the X screen in use
885
vboxEnableVbva(ScrnInfoPtr pScrn)
887
int scrnIndex = pScrn->scrnIndex;
888
VBOXPtr pVBox = pScrn->driverPrivate;
890
if (pVBox->useVbva != TRUE)
892
pVBox->reqe->u32Enable = 1;
893
pVBox->reqe->cbRingBuffer = VBVA_RING_BUFFER_SIZE;
894
pVBox->reqe->fu32Status = 0;
895
if (vbox_vmmcall(pScrn, pVBox, (VMMDevRequestHeader *) pVBox->reqe)
898
/* Request not accepted - disable for old hosts. */
899
xf86DrvMsg(scrnIndex, X_ERROR,
900
"Unable to activate VirtualBox graphics acceleration "
901
"- the request to the virtual machine failed. "
902
"You may be running an old version of VirtualBox.\n");
903
pVBox->useVbva = FALSE;
904
pVBox->reqe->u32Enable = 0;
905
pVBox->reqe->cbRingBuffer = VBVA_RING_BUFFER_SIZE;
906
pVBox->reqe->fu32Status = 0;
907
vbox_vmmcall(pScrn, pVBox, (VMMDevRequestHeader *) pVBox->reqe);
915
* Inform VBox that we will stop supplying it with dirty rectangle
916
* information. This function is intended to be called when an X
917
* virtual terminal is disabled, or the X server is terminated.
919
* @returns TRUE for success, FALSE for failure
920
* @param pScreen Pointer to a structure describing the X screen in use
923
vboxDisableVbva(ScrnInfoPtr pScrn)
925
int scrnIndex = pScrn->scrnIndex;
926
VBOXPtr pVBox = pScrn->driverPrivate;
928
if (pVBox->useVbva != TRUE) /* Ths function should not have been called */
930
pVBox->reqe->u32Enable = 0;
931
pVBox->reqe->cbRingBuffer = VBVA_RING_BUFFER_SIZE;
932
pVBox->reqe->fu32Status = 0;
933
if (vbox_vmmcall(pScrn, pVBox, (VMMDevRequestHeader *) pVBox->reqe)
935
xf86DrvMsg(scrnIndex, X_ERROR,
936
"Unable to disable VirtualBox graphics acceleration "
937
"- the request to the virtual machine failed.\n");
939
memset(pVBox->pVbvaMemory, 0, sizeof(VBVAMEMORY));
945
* Query the last display change request.
947
* @returns iprt status value
948
* @param xres where to store the horizontal pixel resolution requested
949
* (0 = do not change)
950
* @param yres where to store the vertical pixel resolution requested
951
* (0 = do not change)
952
* @param bpp where to store the bits per pixel requeste
953
* (0 = do not change)
954
* @param display Where to store the display number the request was for -
955
* 0 for the primary display, 1 for the first secondary, etc.
958
vboxGetDisplayChangeRequest(ScrnInfoPtr pScrn, uint32_t *pX, uint32_t *pY,
959
uint32_t *pBpp, uint32_t *pDisplay)
961
int rc, scrnIndex = pScrn->scrnIndex;
962
VBOXPtr pVBox = pScrn->driverPrivate;
964
VMMDevDisplayChangeRequest2 Req = { { 0 } };
965
vmmdevInitRequest(&Req.header, VMMDevReq_GetDisplayChangeRequest2);
966
rc = vbox_vmmcall(pScrn, pVBox, &Req.header);
972
*pDisplay = Req.display;
975
xf86DrvMsg(scrnIndex, X_ERROR,
976
"Failed to request the last resolution requested from the guest, rc=%d.\n",