~ubuntu-branches/ubuntu/raring/virtualbox-ose/raring

« back to all changes in this revision

Viewing changes to src/VBox/Additions/x11/vboxvideo/vboxutils.c

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2011-01-30 23:27:25 UTC
  • mfrom: (0.3.12 upstream)
  • Revision ID: james.westby@ubuntu.com-20110130232725-2ouajjd2ggdet0zd
Tags: 4.0.2-dfsg-1ubuntu1
* Merge from Debian unstable, remaining changes:
  - Add Apport hook.
    - debian/virtualbox-ose.files/source_virtualbox-ose.py
    - debian/virtualbox-ose.install
  - Drop *-source packages.
* Drop ubuntu-01-fix-build-gcc45.patch, fixed upstream.
* Drop ubuntu-02-as-needed.patch, added to the Debian package.

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
 
25
25
#include "xf86.h"
26
26
#define NEED_XF86_TYPES
27
 
#ifdef NO_ANSIC
28
 
# include <string.h>
29
 
#else
30
 
# include "xf86_ansic.h"
31
 
#endif
 
27
#include <iprt/string.h>
32
28
#include "compiler.h"
33
29
#include "cursorstr.h"
34
30
 
58
54
    } \
59
55
    while (0)
60
56
 
 
57
/** Structure to pass cursor image data between realise_cursor() and
 
58
 * load_cursor_image().  The members match the parameters to
 
59
 * @a VBoxHGSMIUpdatePointerShape(). */
 
60
struct vboxCursorImage
 
61
{
 
62
    uint32_t fFlags;
 
63
    uint32_t cHotX;
 
64
    uint32_t cHotY;
 
65
    uint32_t cWidth;
 
66
    uint32_t cHeight;
 
67
    uint8_t *pPixels;
 
68
    uint32_t cbLength;
 
69
};
 
70
 
61
71
#ifdef DEBUG_POINTER
62
72
static void
63
73
vbox_show_shape(unsigned short w, unsigned short h, CARD32 bg, unsigned char *image)
68
78
    unsigned char *mask;
69
79
    size_t sizeMask;
70
80
 
71
 
    image    += offsetof(VMMDevReqMousePointer, pointerData);
 
81
    image    += sizeof(struct vboxCursorImage);
72
82
    mask      = image;
73
83
    pitch     = (w + 7) / 8;
74
84
    sizeMask  = (pitch * h + 3) & ~3;
110
120
    uint32_t fFeatures = 0;
111
121
    VBOXPtr pVBox = pScrn->driverPrivate;
112
122
 
113
 
    TRACE_ENTRY();
114
123
    /* We may want to force the use of a software cursor.  Currently this is
115
124
     * needed if the guest uses a large virtual resolution, as in this case
116
125
     * the host and guest tend to disagree about the pointer location. */
141
150
            pVBox->guestCanAbsolute = TRUE;
142
151
        if (   (fFeatures & VMMDEV_MOUSE_HOST_CANNOT_HWPOINTER)
143
152
            || !pVBox->guestCanAbsolute
144
 
            || !(fFeatures & VMMDEV_MOUSE_HOST_CAN_ABSOLUTE)
 
153
            || !(fFeatures & VMMDEV_MOUSE_HOST_WANTS_ABSOLUTE)
145
154
           )
146
155
            rc = FALSE;
147
156
    }
148
 
    TRACE_LOG("rc=%s\n", BOOL_STR(rc));
149
157
    return rc;
150
158
}
151
159
 
152
 
/**
153
 
 * Macro to disable VBVA extensions and return, for use when an
154
 
 * unexplained error occurs.
155
 
 */
156
 
#define DISABLE_VBVA_AND_RETURN(pScrn, ...) \
157
 
    do \
158
 
    { \
159
 
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, __VA_ARGS__); \
160
 
        vboxDisableVbva(pScrn); \
161
 
        pVBox->useVbva = FALSE; \
162
 
        return; \
163
 
    } \
164
 
    while (0)
165
 
 
166
160
/**************************************************************************
167
161
* Main functions                                                          *
168
162
**************************************************************************/
172
166
{
173
167
    TRACE_ENTRY();
174
168
 
175
 
    free (pVBox->reqp);
176
 
    pVBox->reqp = NULL;
 
169
    xf86DestroyCursorInfoRec(pVBox->pCurs);
 
170
    pVBox->pCurs = NULL;
177
171
    TRACE_EXIT();
178
172
}
179
173
 
192
186
{
193
187
    VBVACMDHDR cmdHdr;
194
188
    VBOXPtr pVBox;
195
 
    VBVARECORD *pRecord;
196
 
    VBVAMEMORY *pMem;
197
 
    CARD32 indexRecordNext;
198
 
    CARD32 off32Data;
199
 
    CARD32 off32Free;
200
 
    INT32 i32Diff;
201
 
    CARD32 cbHwBufferAvail;
202
 
    int scrnIndex;
203
189
    int i;
 
190
    unsigned j;
204
191
 
205
192
    pVBox = pScrn->driverPrivate;
206
 
    if (pVBox->useVbva == FALSE)
207
 
        return;
208
 
    pMem = pVBox->pVbvaMemory;
209
 
    /* Just return quietly if VBVA is not currently active. */
210
 
    if ((pMem->fu32ModeFlags & VBVA_F_MODE_ENABLED) == 0)
211
 
        return;
212
 
    scrnIndex = pScrn->scrnIndex;
213
 
 
214
 
    for (i = 0; i < iRects; i++)
 
193
    if (pVBox->fHaveHGSMI == FALSE || pVBox->vtSwitch)
 
194
        return;
 
195
 
 
196
    for (i = 0; i < iRects; ++i)
 
197
        for (j = 0; j < pVBox->cScreens; ++j)
 
198
        {
 
199
            /* Just continue quietly if VBVA is not currently active. */
 
200
            struct VBVABUFFER *pVBVA = pVBox->aVbvaCtx[j].pVBVA;
 
201
            if (   !pVBVA
 
202
                || !(pVBVA->hostFlags.u32HostEvents & VBVA_F_MODE_ENABLED))
 
203
                continue;
 
204
            if (   aRects[i].x1 >   pVBox->aScreenLocation[j].x
 
205
                                  + pVBox->aScreenLocation[j].cx
 
206
                || aRects[i].y1 >   pVBox->aScreenLocation[j].y
 
207
                                  + pVBox->aScreenLocation[j].cy
 
208
                || aRects[i].x2 <   pVBox->aScreenLocation[j].x
 
209
                || aRects[i].y2 <   pVBox->aScreenLocation[j].y)
 
210
                continue;
 
211
            cmdHdr.x = (int16_t)aRects[i].x1;
 
212
            cmdHdr.y = (int16_t)aRects[i].y1;
 
213
            cmdHdr.w = (uint16_t)(aRects[i].x2 - aRects[i].x1);
 
214
            cmdHdr.h = (uint16_t)(aRects[i].y2 - aRects[i].y1);
 
215
 
 
216
#if 0
 
217
            TRACE_LOG("display=%u, x=%d, y=%d, w=%d, h=%d\n",
 
218
                      j, cmdHdr.x, cmdHdr.y, cmdHdr.w, cmdHdr.h);
 
219
#endif
 
220
 
 
221
            if (VBoxVBVABufferBeginUpdate(&pVBox->aVbvaCtx[j],
 
222
                                          &pVBox->guestCtx))
 
223
            {
 
224
                VBoxVBVAWrite(&pVBox->aVbvaCtx[j], &pVBox->guestCtx, &cmdHdr,
 
225
                              sizeof(cmdHdr));
 
226
                VBoxVBVABufferEndUpdate(&pVBox->aVbvaCtx[j]);
 
227
            }
 
228
        }
 
229
}
 
230
 
 
231
/** Callback to fill in the view structures */
 
232
static int
 
233
vboxFillViewInfo(void *pvVBox, struct VBVAINFOVIEW *pViews, uint32_t cViews)
 
234
{
 
235
    VBOXPtr pVBox = (VBOXPtr)pvVBox;
 
236
    unsigned i;
 
237
    for (i = 0; i < cViews; ++i)
215
238
    {
216
 
        cmdHdr.x = (int16_t)aRects[i].x1 - pVBox->viewportX;
217
 
        cmdHdr.y = (int16_t)aRects[i].y1 - pVBox->viewportY;
218
 
        cmdHdr.w = (uint16_t)(aRects[i].x2 - aRects[i].x1);
219
 
        cmdHdr.h = (uint16_t)(aRects[i].y2 - aRects[i].y1);
220
 
 
221
 
        /* Get the active record and move the pointer along */
222
 
        indexRecordNext = (pMem->indexRecordFree + 1) % VBVA_MAX_RECORDS;
223
 
        if (indexRecordNext == pMem->indexRecordFirst)
224
 
        {
225
 
            /* All slots in the records queue are used. */
226
 
            if (VbglR3VideoAccelFlush() < 0)
227
 
                DISABLE_VBVA_AND_RETURN(pScrn,
228
 
                    "Unable to clear the VirtualBox graphics acceleration queue "
229
 
                    "- the request to the virtual machine failed.  Switching to "
230
 
                    "unaccelerated mode.\n");
231
 
        }
232
 
        if (indexRecordNext == pMem->indexRecordFirst)
233
 
            DISABLE_VBVA_AND_RETURN(pScrn,
234
 
                "Failed to clear the VirtualBox graphics acceleration queue.  "
235
 
                "Switching to unaccelerated mode.\n");
236
 
        pRecord = &pMem->aRecords[pMem->indexRecordFree];
237
 
        /* Mark the record as being updated. */
238
 
        pRecord->cbRecord = VBVA_F_RECORD_PARTIAL;
239
 
        pMem->indexRecordFree = indexRecordNext;
240
 
        /* Compute how many bytes we have in the ring buffer. */
241
 
        off32Free = pMem->off32Free;
242
 
        off32Data = pMem->off32Data;
243
 
        /* Free is writing position. Data is reading position.
244
 
         * Data == Free means buffer is free.
245
 
         * There must be always gap between free and data when data
246
 
         * are in the buffer.
247
 
         * Guest only changes free, host only changes data.
248
 
         */
249
 
        i32Diff = off32Data - off32Free;
250
 
        cbHwBufferAvail = i32Diff > 0 ? i32Diff : VBVA_RING_BUFFER_SIZE + i32Diff;
251
 
        if (cbHwBufferAvail <= VBVA_RING_BUFFER_THRESHOLD)
252
 
        {
253
 
            if (VbglR3VideoAccelFlush() < 0)
254
 
                DISABLE_VBVA_AND_RETURN(pScrn,
255
 
                    "Unable to clear the VirtualBox graphics acceleration queue "
256
 
                    "- the request to the virtual machine failed.  Switching to "
257
 
                    "unaccelerated mode.\n");
258
 
            /* Calculate the free space again. */
259
 
            off32Free = pMem->off32Free;
260
 
            off32Data = pMem->off32Data;
261
 
            i32Diff = off32Data - off32Free;
262
 
            cbHwBufferAvail = i32Diff > 0? i32Diff:
263
 
                                  VBVA_RING_BUFFER_SIZE + i32Diff;
264
 
            if (cbHwBufferAvail <= VBVA_RING_BUFFER_THRESHOLD)
265
 
                DISABLE_VBVA_AND_RETURN(pScrn,
266
 
                    "No space left in the VirtualBox graphics acceleration command buffer, "
267
 
                    "despite clearing the queue.  Switching to unaccelerated mode.\n");
268
 
        }
269
 
        /* Now copy the data into the buffer */
270
 
        if (off32Free + sizeof(cmdHdr) < VBVA_RING_BUFFER_SIZE)
271
 
        {
272
 
            memcpy(&pMem->au8RingBuffer[off32Free], &cmdHdr, sizeof(cmdHdr));
273
 
            pMem->off32Free = pMem->off32Free + sizeof(cmdHdr);
274
 
        }
275
 
        else
276
 
        {
277
 
            CARD32 u32First = VBVA_RING_BUFFER_SIZE - off32Free;
278
 
            /* The following is impressively ugly! */
279
 
            CARD8 *pu8Second = (CARD8 *)&cmdHdr + u32First;
280
 
            CARD32 u32Second = sizeof(cmdHdr) - u32First;
281
 
            memcpy(&pMem->au8RingBuffer[off32Free], &cmdHdr, u32First);
282
 
            if (u32Second)
283
 
                memcpy(&pMem->au8RingBuffer[0], pu8Second, u32Second);
284
 
            pMem->off32Free = u32Second;
285
 
        }
286
 
        pRecord->cbRecord += sizeof(cmdHdr);
287
 
        /* Mark the record completed. */
288
 
        pRecord->cbRecord &= ~VBVA_F_RECORD_PARTIAL;
 
239
        pViews[i].u32ViewIndex = i;
 
240
        pViews[i].u32ViewOffset = 0;
 
241
        pViews[i].u32ViewSize = pVBox->cbView;
 
242
        pViews[i].u32MaxScreenSize = pVBox->cbFBMax;
289
243
    }
 
244
    return VINF_SUCCESS;
290
245
}
291
246
 
292
 
#ifdef PCIACCESS
293
 
/* As of X.org server 1.5, we are using the pciaccess library functions to
294
 
 * access PCI.  This structure describes our VMM device. */
295
 
/** Structure describing the VMM device */
296
 
static const struct pci_id_match vboxVMMDevID =
297
 
{ VMMDEV_VENDORID, VMMDEV_DEVICEID, PCI_MATCH_ANY, PCI_MATCH_ANY,
298
 
  0, 0, 0 };
299
 
#endif
300
 
 
301
247
/**
302
248
 * Initialise VirtualBox's accelerated video extensions.
303
249
 *
306
252
static Bool
307
253
vboxInitVbva(int scrnIndex, ScreenPtr pScreen, VBOXPtr pVBox)
308
254
{
309
 
#ifdef PCIACCESS
310
 
    struct pci_device_iterator *devIter = NULL;
311
 
 
312
 
    TRACE_ENTRY();
313
 
    pVBox->vmmDevInfo = NULL;
314
 
    devIter = pci_id_match_iterator_create(&vboxVMMDevID);
315
 
    if (devIter)
316
 
    {
317
 
        pVBox->vmmDevInfo = pci_device_next(devIter);
318
 
        pci_iterator_destroy(devIter);
319
 
    }
320
 
    if (pVBox->vmmDevInfo)
321
 
    {
322
 
        if (pci_device_probe(pVBox->vmmDevInfo) != 0)
323
 
        {
324
 
            xf86DrvMsg (scrnIndex, X_ERROR,
325
 
                        "Failed to probe VMM device (vendor=%04x, devid=%04x)\n",
326
 
                        pVBox->vmmDevInfo->vendor_id,
327
 
                        pVBox->vmmDevInfo->device_id);
328
 
        }
329
 
        else
330
 
        {
331
 
            if (pci_device_map_range(pVBox->vmmDevInfo,
332
 
                                     pVBox->vmmDevInfo->regions[1].base_addr,
333
 
                                     pVBox->vmmDevInfo->regions[1].size,
334
 
                                     PCI_DEV_MAP_FLAG_WRITABLE,
335
 
                                     (void **)&pVBox->pVMMDevMemory) != 0)
336
 
                xf86DrvMsg (scrnIndex, X_ERROR,
337
 
                            "Failed to map VMM device range\n");
338
 
        }
339
 
    }
340
 
#else
341
 
    PCITAG pciTagDev;
342
 
    ADDRESS pciAddrDev;
343
 
 
344
 
    TRACE_ENTRY();
345
 
    /* Locate the device.  It should already have been enabled by
346
 
       the kernel driver. */
347
 
    pciTagDev = pciFindFirst((unsigned) VMMDEV_DEVICEID << 16 | VMMDEV_VENDORID,
348
 
                             (CARD32) ~0);
349
 
    if (pciTagDev == PCI_NOT_FOUND)
350
 
    {
351
 
        xf86DrvMsg(scrnIndex, X_ERROR,
352
 
                   "Could not find the VirtualBox base device on the PCI bus.\n");
353
 
        return FALSE;
354
 
    }
355
 
    /* Read the address and size of the second I/O region. */
356
 
    pciAddrDev = pciReadLong(pciTagDev, PCI_MAP_REG_START + 4);
357
 
    if (pciAddrDev == 0 || pciAddrDev == (CARD32) ~0)
358
 
        RETERROR(scrnIndex, FALSE,
359
 
                 "The VirtualBox base device contains an invalid memory address.\n");
360
 
    if (PCI_MAP_IS64BITMEM(pciAddrDev))
361
 
        RETERROR(scrnIndex, FALSE,
362
 
                 "The VirtualBox base device has a 64bit mapping address.  "
363
 
                 "This is currently not supported.\n");
364
 
    /* Map it.  We hardcode the size as X does not export the
365
 
       function needed to determine it. */
366
 
    pVBox->pVMMDevMemory = xf86MapPciMem(scrnIndex, 0, pciTagDev, pciAddrDev,
367
 
                                         sizeof(VMMDevMemory));
368
 
#endif
369
 
    if (pVBox->pVMMDevMemory == NULL)
370
 
    {
371
 
        xf86DrvMsg(scrnIndex, X_ERROR,
372
 
                   "Failed to map VirtualBox video extension memory.\n");
373
 
        return FALSE;
374
 
    }
375
 
    pVBox->pVbvaMemory = &pVBox->pVMMDevMemory->vbvaMemory;
376
 
    /* Set up the dirty rectangle handler.  Since this seems to be a
377
 
       delicate operation, and removing it doubly so, this will
378
 
       remain in place whether it is needed or not, and will simply
379
 
       return if VBVA is not active.  I assume that it will be active
380
 
       most of the time. */
 
255
    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
 
256
    int rc = VINF_SUCCESS;
 
257
 
 
258
    pVBox->cScreens = 1;
 
259
    if (!VBoxHGSMIIsSupported())
 
260
    {
 
261
        xf86DrvMsg(scrnIndex, X_ERROR, "The graphics device does not seem to support HGSMI.  Disableing video acceleration.\n");
 
262
        return FALSE;
 
263
    }
 
264
 
 
265
    /* Set up the dirty rectangle handler.  It will be added into a function
 
266
     * chain and gets removed when the screen is cleaned up. */
381
267
    if (ShadowFBInit2(pScreen, NULL, vboxHandleDirtyRect) != TRUE)
382
268
    {
383
269
        xf86DrvMsg(scrnIndex, X_ERROR,
387
273
    return TRUE;
388
274
}
389
275
 
 
276
/**
 
277
 * Initialise VirtualBox's accelerated video extensions.
 
278
 *
 
279
 * @returns TRUE on success, FALSE on failure
 
280
 */
 
281
static Bool
 
282
vboxSetupVRAMVbva(ScrnInfoPtr pScrn, VBOXPtr pVBox)
 
283
{
 
284
    int rc = VINF_SUCCESS;
 
285
    unsigned i;
 
286
    uint32_t offVRAMBaseMapping, offGuestHeapMemory, cbGuestHeapMemory;
 
287
    void *pvGuestHeapMemory;
 
288
 
 
289
    if (!pVBox->fHaveHGSMI)
 
290
        return FALSE;
 
291
    VBoxHGSMIGetBaseMappingInfo(pScrn->videoRam * 1024, &offVRAMBaseMapping,
 
292
                                NULL, &offGuestHeapMemory, &cbGuestHeapMemory,
 
293
                                NULL);
 
294
    pvGuestHeapMemory =   ((uint8_t *)pVBox->base) + offVRAMBaseMapping
 
295
                        + offGuestHeapMemory;
 
296
    TRACE_LOG("video RAM: %u KB, guest heap offset: 0x%x, cbGuestHeapMemory: %u\n",
 
297
              pScrn->videoRam, offVRAMBaseMapping + offGuestHeapMemory,
 
298
              cbGuestHeapMemory);
 
299
    rc = VBoxHGSMISetupGuestContext(&pVBox->guestCtx, pvGuestHeapMemory,
 
300
                                    cbGuestHeapMemory,
 
301
                                    offVRAMBaseMapping + offGuestHeapMemory);
 
302
    if (RT_FAILURE(rc))
 
303
    {
 
304
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to set up the guest-to-host communication context, rc=%d\n", rc);
 
305
        return FALSE;
 
306
    }
 
307
    pVBox->cbView = pVBox->cbFBMax = offVRAMBaseMapping;
 
308
    pVBox->cScreens = VBoxHGSMIGetMonitorCount(&pVBox->guestCtx);
 
309
    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Requested monitor count: %u\n",
 
310
               pVBox->cScreens);
 
311
    for (i = 0; i < pVBox->cScreens; ++i)
 
312
    {
 
313
        pVBox->cbFBMax -= VBVA_MIN_BUFFER_SIZE;
 
314
        pVBox->aoffVBVABuffer[i] = pVBox->cbFBMax;
 
315
        TRACE_LOG("VBVA buffer offset for screen %u: 0x%lx\n", i,
 
316
                  (unsigned long) pVBox->cbFBMax);
 
317
        VBoxVBVASetupBufferContext(&pVBox->aVbvaCtx[i],
 
318
                                   pVBox->aoffVBVABuffer[i],
 
319
                                   VBVA_MIN_BUFFER_SIZE);
 
320
    }
 
321
    TRACE_LOG("Maximum framebuffer size: %lu (0x%lx)\n",
 
322
              (unsigned long) pVBox->cbFBMax,
 
323
              (unsigned long) pVBox->cbFBMax);
 
324
    rc = VBoxHGSMISendViewInfo(&pVBox->guestCtx, pVBox->cScreens,
 
325
                               vboxFillViewInfo, (void *)pVBox);
 
326
    if (RT_FAILURE(rc))
 
327
    {
 
328
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to send the view information to the host, rc=%d\n", rc);
 
329
        return FALSE;
 
330
    }
 
331
    return TRUE;
 
332
}
 
333
 
390
334
Bool
391
335
vbox_init(int scrnIndex, VBOXPtr pVBox)
392
336
{
395
339
    uint32_t fMouseFeatures = 0;
396
340
 
397
341
    TRACE_ENTRY();
398
 
    pVBox->useVbva = FALSE;
399
342
    vrc = VbglR3Init();
400
343
    if (RT_FAILURE(vrc))
401
344
    {
418
361
Bool
419
362
vbox_open(ScrnInfoPtr pScrn, ScreenPtr pScreen, VBOXPtr pVBox)
420
363
{
421
 
    int rc;
422
 
    void *p;
423
 
    size_t size;
424
 
    int scrnIndex = pScrn->scrnIndex;
425
 
 
426
364
    TRACE_ENTRY();
427
365
 
428
 
    if (!pVBox->useDevice)
429
 
        return FALSE;
430
 
 
431
 
    if (pVBox->reqp)
432
 
    {
433
 
        /* still open, just re-enable VBVA after CloseScreen was called */
434
 
        pVBox->useVbva = vboxInitVbva(scrnIndex, pScreen, pVBox);
435
 
        return TRUE;
436
 
    }
437
 
 
438
 
    size = vmmdevGetRequestSize(VMMDevReq_SetPointerShape);
439
 
    p = calloc(1, size);
440
 
    if (p)
441
 
    {
442
 
        rc = vmmdevInitRequest(p, VMMDevReq_SetPointerShape);
443
 
        if (RT_SUCCESS(rc))
444
 
        {
445
 
            pVBox->reqp = p;
446
 
            pVBox->pCurs = NULL;
447
 
            pVBox->pointerHeaderSize = size;
448
 
            pVBox->useVbva = vboxInitVbva(scrnIndex, pScreen, pVBox);
449
 
            return TRUE;
450
 
        }
451
 
        xf86DrvMsg(scrnIndex, X_ERROR, "Could not init VMM request: rc = %d\n", rc);
452
 
        free(p);
453
 
    }
454
 
    xf86DrvMsg(scrnIndex, X_ERROR, "Could not allocate %lu bytes for VMM request\n", (unsigned long)size);
455
 
    return FALSE;
 
366
    pVBox->fHaveHGSMI = vboxInitVbva(pScrn->scrnIndex, pScreen, pVBox);
 
367
    return pVBox->fHaveHGSMI;
456
368
}
457
369
 
458
370
Bool
466
378
{
467
379
    int rc;
468
380
 
469
 
    pVBox->reqp->fFlags = 0;
470
 
    rc = VbglR3SetPointerShapeReq(pVBox->reqp);
 
381
    rc = VBoxHGSMIUpdatePointerShape(&pVBox->guestCtx, 0, 0, 0, 0, 0, NULL, 0);
471
382
    if (RT_FAILURE(rc))
472
383
    {
473
 
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Could not hide the virtual mouse pointer.\n");
 
384
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Could not hide the virtual mouse pointer, VBox error %d.\n", rc);
474
385
        /* Play safe, and disable the hardware cursor until the next mode
475
386
         * switch, since obviously something happened that we didn't
476
387
         * anticipate. */
483
394
{
484
395
    int rc;
485
396
 
486
 
    if (vbox_host_uses_hwcursor(pScrn)) {
487
 
        pVBox->reqp->fFlags = VBOX_MOUSE_POINTER_VISIBLE;
488
 
        rc = VbglR3SetPointerShapeReq(pVBox->reqp);
489
 
        if (RT_FAILURE(rc)) {
490
 
            xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Could not unhide the virtual mouse pointer.\n");
491
 
            /* Play safe, and disable the hardware cursor until the next mode
492
 
             * switch, since obviously something happened that we didn't
493
 
             * anticipate. */
494
 
            pVBox->forceSWCursor = TRUE;
495
 
        }
 
397
    if (!vbox_host_uses_hwcursor(pScrn))
 
398
        return;
 
399
    rc = VBoxHGSMIUpdatePointerShape(&pVBox->guestCtx, VBOX_MOUSE_POINTER_VISIBLE,
 
400
                                     0, 0, 0, 0, NULL, 0);
 
401
    if (RT_FAILURE(rc)) {
 
402
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Could not unhide the virtual mouse pointer.\n");
 
403
        /* Play safe, and disable the hardware cursor until the next mode
 
404
         * switch, since obviously something happened that we didn't
 
405
         * anticipate. */
 
406
        pVBox->forceSWCursor = TRUE;
496
407
    }
497
408
}
498
409
 
499
410
static void
500
411
vbox_vmm_load_cursor_image(ScrnInfoPtr pScrn, VBOXPtr pVBox,
501
 
                           unsigned char *image)
 
412
                           unsigned char *pvImage)
502
413
{
503
414
    int rc;
504
 
    VMMDevReqMousePointer *reqp;
505
 
    reqp = (VMMDevReqMousePointer *)image;
 
415
    struct vboxCursorImage *pImage;
 
416
    pImage = (struct vboxCursorImage *)pvImage;
506
417
 
507
418
#ifdef DEBUG_POINTER
508
 
    vbox_show_shape(reqp->width, reqp->height, 0, image);
 
419
    vbox_show_shape(pImage->cWidth, pImage->cHeight, 0, pvImage);
509
420
#endif
510
421
 
511
 
    rc = VbglR3SetPointerShapeReq(reqp);
 
422
    rc = VBoxHGSMIUpdatePointerShape(&pVBox->guestCtx, pImage->fFlags,
 
423
             pImage->cHotX, pImage->cHotY, pImage->cWidth, pImage->cHeight,
 
424
             pImage->pPixels, pImage->cbLength);
512
425
    if (RT_FAILURE(rc)) {
513
426
        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,  "Unable to set the virtual mouse pointer image.\n");
514
427
        /* Play safe, and disable the hardware cursor until the next mode
585
498
    size_t sizeRequest, sizeRgba, sizeMask, srcPitch, dstPitch;
586
499
    CARD32 fc, bc, *cp;
587
500
    int rc, scrnIndex = infoPtr->pScrn->scrnIndex;
588
 
    VMMDevReqMousePointer *reqp;
 
501
    struct vboxCursorImage *pImage;
589
502
 
590
503
    pVBox = infoPtr->pScrn->driverPrivate;
591
504
    bitsp = pCurs->bits;
605
518
    dstPitch = (w + 7) / 8;
606
519
    sizeMask = ((dstPitch * h) + 3) & (size_t) ~3;
607
520
    sizeRgba = w * h * 4;
608
 
    pVBox->pointerSize = sizeMask + sizeRgba;
609
 
    sizeRequest = pVBox->pointerSize + pVBox->pointerHeaderSize;
 
521
    sizeRequest = sizeMask + sizeRgba + sizeof(*pImage);
610
522
 
611
523
    p = c = calloc (1, sizeRequest);
612
524
    if (!c)
614
526
                 "Error failed to alloc %lu bytes for cursor\n",
615
527
                 (unsigned long) sizeRequest);
616
528
 
617
 
    rc = vmmdevInitRequest((VMMDevRequestHeader *)p, VMMDevReq_SetPointerShape);
618
 
    if (RT_FAILURE(rc))
619
 
    {
620
 
        xf86DrvMsg(scrnIndex, X_ERROR, "Could not init VMM request: rc = %d\n", rc);
621
 
        free(p);
622
 
        return NULL;
623
 
    }
624
 
 
625
 
    m = p + offsetof(VMMDevReqMousePointer, pointerData);
 
529
    pImage = (struct vboxCursorImage *)p;
 
530
    pImage->pPixels = m = p + sizeof(*pImage);
626
531
    cp = (CARD32 *)(m + sizeMask);
627
532
 
628
533
    TRACE_LOG ("w=%d h=%d sm=%d sr=%d p=%d\n",
687
592
        PUT_PIXEL('\n');
688
593
    }
689
594
 
690
 
    reqp = (VMMDevReqMousePointer *)p;
691
 
    reqp->width  = w;
692
 
    reqp->height = h;
693
 
    reqp->xHot   = bitsp->xhot;
694
 
    reqp->yHot   = bitsp->yhot;
695
 
    reqp->fFlags = VBOX_MOUSE_POINTER_VISIBLE | VBOX_MOUSE_POINTER_SHAPE;
696
 
    reqp->header.size = sizeRequest;
 
595
    pImage->cWidth   = w;
 
596
    pImage->cHeight  = h;
 
597
    pImage->cHotX    = bitsp->xhot;
 
598
    pImage->cHotY    = bitsp->yhot;
 
599
    pImage->fFlags   = VBOX_MOUSE_POINTER_VISIBLE | VBOX_MOUSE_POINTER_SHAPE;
 
600
    pImage->cbLength = sizeRequest - sizeof(*pImage);
697
601
 
698
602
#ifdef DEBUG_POINTER
699
603
    ErrorF("shape = %p\n", p);
724
628
     * our list of video modes. */
725
629
    vboxWriteHostModes(pScrn, pScrn->currentMode);
726
630
#endif
727
 
    TRACE_LOG("rc=%s\n", BOOL_STR(rc));
728
631
    return rc;
729
632
}
730
633
 
739
642
    unsigned short cx, cy;
740
643
    unsigned char *pm;
741
644
    CARD32 *pc;
742
 
    size_t sizeRequest, sizeMask;
 
645
    size_t sizeData, sizeMask;
743
646
    CARD8 *p;
744
647
    int scrnIndex;
 
648
    uint32_t fFlags =   VBOX_MOUSE_POINTER_VISIBLE | VBOX_MOUSE_POINTER_SHAPE
 
649
                      | VBOX_MOUSE_POINTER_ALPHA;
 
650
    int rc;
745
651
 
746
 
    TRACE_ENTRY();
747
652
    pVBox = pScrn->driverPrivate;
748
653
    bitsp = pCurs->bits;
749
654
    w     = bitsp->width;
763
668
                 "Error invalid cursor hotspot location %dx%d (max %dx%d)\n",
764
669
                 bitsp->xhot, bitsp->yhot, w, h);
765
670
 
766
 
    pVBox->pointerSize = w * h * 4 + sizeMask;
767
 
    sizeRequest = pVBox->pointerSize + pVBox->pointerHeaderSize;
768
 
    p = calloc(1, sizeRequest);
 
671
    sizeData = w * h * 4 + sizeMask;
 
672
    p = calloc(1, sizeData);
769
673
    if (!p)
770
674
        RETERROR(scrnIndex, ,
771
675
                 "Error failed to alloc %lu bytes for cursor\n",
772
 
                 (unsigned long)sizeRequest);
773
 
 
774
 
    reqp = (VMMDevReqMousePointer *)p;
775
 
    *reqp = *pVBox->reqp;
776
 
    reqp->width  = w;
777
 
    reqp->height = h;
778
 
    reqp->xHot   = bitsp->xhot;
779
 
    reqp->yHot   = bitsp->yhot;
780
 
    reqp->fFlags =   VBOX_MOUSE_POINTER_VISIBLE | VBOX_MOUSE_POINTER_SHAPE
781
 
                   | VBOX_MOUSE_POINTER_ALPHA;
782
 
    reqp->header.size = sizeRequest;
783
 
 
784
 
    memcpy(p + offsetof(VMMDevReqMousePointer, pointerData) + sizeMask, bitsp->argb, w * h * 4);
 
676
                 (unsigned long)sizeData);
 
677
 
 
678
    memcpy(p + sizeMask, bitsp->argb, w * h * 4);
785
679
 
786
680
    /* Emulate the AND mask. */
787
 
    pm = p + offsetof(VMMDevReqMousePointer, pointerData);
 
681
    pm = p;
788
682
    pc = bitsp->argb;
789
683
 
790
684
    /* Init AND mask to 1 */
814
708
        pm += (w + 7) / 8;
815
709
    }
816
710
 
817
 
    VbglR3SetPointerShapeReq(reqp);
 
711
    rc = VBoxHGSMIUpdatePointerShape(&pVBox->guestCtx, fFlags, bitsp->xhot,
 
712
                                     bitsp->yhot, w, h, p, sizeData);
818
713
    free(p);
819
714
}
820
715
#endif
828
723
    Bool rc = TRUE;
829
724
 
830
725
    TRACE_ENTRY();
831
 
    if (!pVBox->useDevice)
 
726
    if (!pVBox->fHaveHGSMI)
832
727
        return FALSE;
833
728
    pVBox->pCurs = pCurs = xf86CreateCursorInfoRec();
834
729
    if (!pCurs) {
882
777
{
883
778
    bool rc = TRUE;
884
779
    int scrnIndex = pScrn->scrnIndex;
 
780
    unsigned i;
885
781
    VBOXPtr pVBox = pScrn->driverPrivate;
886
782
 
887
783
    TRACE_ENTRY();
888
 
    if (pVBox->useVbva != TRUE)
889
 
        rc = FALSE;
890
 
    if (rc && RT_FAILURE(VbglR3VideoAccelEnable(true)))
 
784
    if (!vboxSetupVRAMVbva(pScrn, pVBox))
 
785
        return FALSE;
 
786
    for (i = 0; i < pVBox->cScreens; ++i)
 
787
    {
 
788
        struct VBVABUFFER *pVBVA;
 
789
 
 
790
        pVBVA = (struct VBVABUFFER *) (  ((uint8_t *)pVBox->base)
 
791
                                       + pVBox->aoffVBVABuffer[i]);
 
792
        if (!VBoxVBVAEnable(&pVBox->aVbvaCtx[i], &pVBox->guestCtx, pVBVA, i))
 
793
            rc = FALSE;
 
794
    }
 
795
    if (!rc)
 
796
    {
891
797
        /* Request not accepted - disable for old hosts. */
892
798
        xf86DrvMsg(scrnIndex, X_ERROR,
893
 
                   "Unable to activate VirtualBox graphics acceleration "
894
 
                   "- the request to the virtual machine failed.  "
895
 
                   "You may be running an old version of VirtualBox.\n");
896
 
    pVBox->useVbva = rc;
897
 
    if (!rc)
898
 
        VbglR3VideoAccelEnable(false);
 
799
                   "Failed to enable screen update reporting for at least one virtual monitor.\n");
 
800
         vboxDisableVbva(pScrn);
 
801
    }
899
802
    return rc;
900
803
}
901
804
 
907
810
 * @returns TRUE for success, FALSE for failure
908
811
 * @param   pScrn   Pointer to a structure describing the X screen in use
909
812
 */
910
 
Bool
 
813
void
911
814
vboxDisableVbva(ScrnInfoPtr pScrn)
912
815
{
913
816
    int rc;
914
817
    int scrnIndex = pScrn->scrnIndex;
 
818
    unsigned i;
915
819
    VBOXPtr pVBox = pScrn->driverPrivate;
916
820
 
917
821
    TRACE_ENTRY();
918
 
    if (pVBox->useVbva != TRUE)  /* Ths function should not have been called */
919
 
        return FALSE;
920
 
    rc = VbglR3VideoAccelEnable(false);
921
 
    if (RT_FAILURE(rc))
922
 
    {
923
 
        xf86DrvMsg(scrnIndex, X_ERROR,
924
 
                   "Unable to disable VirtualBox graphics acceleration "
925
 
                   "- the request to the virtual machine failed.\n");
926
 
    }
927
 
    else
928
 
        memset(pVBox->pVbvaMemory, 0, sizeof(VBVAMEMORY));
929
 
    return TRUE;
 
822
    if (!pVBox->fHaveHGSMI)  /* Ths function should not have been called */
 
823
        return;
 
824
    for (i = 0; i < pVBox->cScreens; ++i)
 
825
        VBoxVBVADisable(&pVBox->aVbvaCtx[i], &pVBox->guestCtx, i);
930
826
}
931
827
 
932
828
/**
978
874
    TRACE_ENTRY();
979
875
    if (!pVBox->useDevice)
980
876
        return FALSE;
981
 
    int rc = VbglR3GetDisplayChangeRequest(pcx, pcy, pcBits, piDisplay, true);
 
877
    int rc = VbglR3GetDisplayChangeRequest(pcx, pcy, pcBits, piDisplay, false);
982
878
    if (RT_SUCCESS(rc))
983
879
        return TRUE;
984
880
    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to obtain the last resolution requested by the guest, rc=%d.\n", rc);
1181
1077
 *
1182
1078
 * The return type is void as we guarantee we will return some mode.
1183
1079
 */
1184
 
void vboxGetPreferredMode(ScrnInfoPtr pScrn, uint32_t *pcx,
 
1080
void vboxGetPreferredMode(ScrnInfoPtr pScrn, uint32_t iScreen, uint32_t *pcx,
1185
1081
                          uint32_t *pcy, uint32_t *pcBits)
1186
1082
{
1187
1083
    /* Query the host for the preferred resolution and colour depth */
1188
 
    uint32_t cx = 0, cy = 0, iDisplay = 0, cBits = 32;
 
1084
    uint32_t cx = 0, cy = 0, iScreenIn = iScreen, cBits = 32;
1189
1085
    VBOXPtr pVBox = pScrn->driverPrivate;
1190
1086
 
1191
 
    TRACE_ENTRY();
 
1087
    TRACE_LOG("iScreen=%u\n", iScreen);
 
1088
    bool found = false;
 
1089
    if (   pVBox->aPreferredSize[iScreen].cx
 
1090
        && pVBox->aPreferredSize[iScreen].cy)
 
1091
    {
 
1092
        cx = pVBox->aPreferredSize[iScreen].cx;
 
1093
        cy = pVBox->aPreferredSize[iScreen].cy;
 
1094
        found = true;
 
1095
    }
1192
1096
    if (pVBox->useDevice)
1193
1097
    {
1194
 
        bool found = vboxGetDisplayChangeRequest(pScrn, &cx, &cy, &cBits, &iDisplay);
1195
 
        if ((cx == 0) || (cy == 0))
 
1098
        if (!found)
 
1099
            found = vboxGetDisplayChangeRequest(pScrn, &cx, &cy, &cBits,
 
1100
                                                &iScreenIn);
 
1101
        if ((cx == 0) || (cy == 0) || iScreenIn != iScreen)
1196
1102
            found = false;
1197
1103
        if (!found)
1198
1104
            found = vboxRetrieveVideoMode(pScrn, &cx, &cy, &cBits);
1217
1123
        *pcx = cx;
1218
1124
    if (pcy)
1219
1125
        *pcy = cy;
1220
 
    if (pcx)
 
1126
    if (pcBits)
1221
1127
        *pcBits = cBits;
 
1128
    TRACE_LOG("cx=%u, cy=%u, cBits=%u\n", cx, cy, cBits);
1222
1129
}
1223
1130
 
1224
1131
/* Move a screen mode found to the end of the list, so that RandR will give
1258
1165
    bool found = false;
1259
1166
 
1260
1167
    TRACE_ENTRY();
1261
 
    vboxGetPreferredMode(pScrn, &cx, &cy, &cBits);
 
1168
    vboxGetPreferredMode(pScrn, 0, &cx, &cy, &cBits);
1262
1169
#ifdef DEBUG
1263
1170
    /* Count the number of modes for sanity */
1264
1171
    unsigned cModes = 1, cMode = 0;