VirtualBox

Ignore:
Timestamp:
Nov 28, 2010 10:12:07 PM (14 years ago)
Author:
vboxsync
Message:

Additions/WINNT/Graphics and Additions/common/VBoxVideo: move the base VBVA support functions into the common driver code

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/WINNT/Graphics/Display/vbox.c

    r34438 r34440  
    55
    66/*
    7  * Copyright (C) 2006-2007 Oracle Corporation
     7 * Copyright (C) 2006-2010 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2525#include <iprt/asm-amd64-x86.h>
    2626#include <iprt/assert.h>
    27 
    28 /*
    29  * There is a hardware ring buffer in the VBox VMMDev PCI memory space.
    30  * All graphics commands go there serialized by VBoxVBVABufferBeginUpdate.
    31  * and vboxHwBufferEndUpdate.
    32  *
    33  * off32Free is writing position. off32Data is reading position.
    34  * off32Free == off32Data means buffer is empty.
    35  * There must be always gap between off32Data and off32Free when data
    36  * are in the buffer.
    37  * Guest only changes off32Free, host changes off32Data.
    38  */
    39 
    40 /* Forward declarations of internal functions. */
    41 static void vboxHwBufferFlush(PHGSMIGUESTCOMMANDCONTEXT pCtx);
    42 static void vboxHwBufferPlaceDataAt(PVBVABUFFERCONTEXT pCtx, const void *p,
    43                                     uint32_t cb, uint32_t offset);
    44 static bool vboxHwBufferWrite(PVBVABUFFERCONTEXT pCtx,
    45                               PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx,
    46                               const void *p, uint32_t cb);
    47 
    48 
    49 static bool vboxVBVAInformHost(PVBVABUFFERCONTEXT pCtx,
    50                                PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx,
    51                                bool bEnable)
    52 {
    53     bool bRc = false;
    54 
    55 #if 0  /* All callers check this */
    56     if (ppdev->bHGSMISupported)
    57 #endif
    58     {
    59         void *p = VBoxHGSMIBufferAlloc(pHGSMICtx,
    60                                        sizeof (VBVAENABLE),
    61                                        HGSMI_CH_VBVA,
    62                                        VBVA_ENABLE);
    63         if (!p)
    64         {
    65             LogFunc(("HGSMIHeapAlloc failed\n"));
    66         }
    67         else
    68         {
    69             VBVAENABLE *pEnable = (VBVAENABLE *)p;
    70 
    71             pEnable->u32Flags  = bEnable? VBVA_F_ENABLE: VBVA_F_DISABLE;
    72             pEnable->u32Offset = pCtx->offVRAMBuffer;
    73             pEnable->i32Result = VERR_NOT_SUPPORTED;
    74 
    75             VBoxHGSMIBufferSubmit(pHGSMICtx, p);
    76 
    77             if (bEnable)
    78             {
    79                 bRc = RT_SUCCESS(pEnable->i32Result);
    80             }
    81             else
    82             {
    83                 bRc = true;
    84             }
    85 
    86             VBoxHGSMIBufferFree(pHGSMICtx, p);
    87         }
    88     }
    89 
    90     return bRc;
    91 }
    92 
    93 /*
    94  * Public hardware buffer methods.
    95  */
    96 RTDECL(bool) VBoxVBVAEnable(PVBVABUFFERCONTEXT pCtx,
    97                             PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx,
    98                             VBVABUFFER *pVBVA)
    99 {
    100     bool bRc = false;
    101 
    102     LogFlowFunc(("pVBVA %p\n", pVBVA));
    103 
    104 #if 0  /* All callers check this */
    105     if (ppdev->bHGSMISupported)
    106 #endif
    107     {
    108         LogFunc(("pVBVA %p vbva off 0x%x\n", pVBVA, pCtx->offVRAMBuffer));
    109 
    110         pVBVA->hostFlags.u32HostEvents      = 0;
    111         pVBVA->hostFlags.u32SupportedOrders = 0;
    112         pVBVA->off32Data          = 0;
    113         pVBVA->off32Free          = 0;
    114         memset(pVBVA->aRecords, 0, sizeof (pVBVA->aRecords));
    115         pVBVA->indexRecordFirst   = 0;
    116         pVBVA->indexRecordFree    = 0;
    117         pVBVA->cbPartialWriteThreshold = 256;
    118         pVBVA->cbData             = pCtx->cbBuffer - sizeof (VBVABUFFER) + sizeof (pVBVA->au8Data);
    119 
    120         pCtx->fHwBufferOverflow = false;
    121         pCtx->pRecord    = NULL;
    122         pCtx->pVBVA      = pVBVA;
    123 
    124         bRc = vboxVBVAInformHost(pCtx, pHGSMICtx, true);
    125     }
    126 
    127     if (!bRc)
    128     {
    129         VBoxVBVADisable(pCtx, pHGSMICtx);
    130     }
    131 
    132     return bRc;
    133 }
    134 
    135 RTDECL(void) VBoxVBVADisable(PVBVABUFFERCONTEXT pCtx,
    136                              PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx)
    137 {
    138     LogFlowFunc(("\n"));
    139 
    140     pCtx->fHwBufferOverflow = false;
    141     pCtx->pRecord           = NULL;
    142     pCtx->pVBVA             = NULL;
    143 
    144     vboxVBVAInformHost(pCtx, pHGSMICtx, false);
    145 
    146     return;
    147 }
    148 
    149 RTDECL(bool) VBoxVBVABufferBeginUpdate(PVBVABUFFERCONTEXT pCtx,
    150                                        PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx)
    151 {
    152     bool bRc = false;
    153 
    154     // LogFunc(("flags = 0x%08X\n", pCtx->pVBVA? pCtx->pVBVA->u32HostEvents: -1));
    155 
    156     if (   pCtx->pVBVA
    157         && (pCtx->pVBVA->hostFlags.u32HostEvents & VBVA_F_MODE_ENABLED))
    158     {
    159         uint32_t indexRecordNext;
    160 
    161         Assert(!pCtx->fHwBufferOverflow);
    162         Assert(pCtx->pRecord == NULL);
    163 
    164         indexRecordNext = (pCtx->pVBVA->indexRecordFree + 1) % VBVA_MAX_RECORDS;
    165 
    166         if (indexRecordNext == pCtx->pVBVA->indexRecordFirst)
    167         {
    168             /* All slots in the records queue are used. */
    169             vboxHwBufferFlush (pHGSMICtx);
    170         }
    171 
    172         if (indexRecordNext == pCtx->pVBVA->indexRecordFirst)
    173         {
    174             /* Even after flush there is no place. Fail the request. */
    175             LogFunc(("no space in the queue of records!!! first %d, last %d\n",
    176                      pCtx->pVBVA->indexRecordFirst, pCtx->pVBVA->indexRecordFree));
    177         }
    178         else
    179         {
    180             /* Initialize the record. */
    181             VBVARECORD *pRecord = &pCtx->pVBVA->aRecords[pCtx->pVBVA->indexRecordFree];
    182 
    183             pRecord->cbRecord = VBVA_F_RECORD_PARTIAL;
    184 
    185             pCtx->pVBVA->indexRecordFree = indexRecordNext;
    186 
    187             // LogFunc(("indexRecordNext = %d\n", indexRecordNext));
    188 
    189             /* Remember which record we are using. */
    190             pCtx->pRecord = pRecord;
    191 
    192             bRc = true;
    193         }
    194     }
    195 
    196     return bRc;
    197 }
    198 
    199 RTDECL(void) VBoxVBVABufferEndUpdate(PVBVABUFFERCONTEXT pCtx)
    200 {
    201     VBVARECORD *pRecord;
    202 
    203     // LogFunc(("\n"));
    204 
    205     Assert(pCtx->pVBVA);
    206 
    207     pRecord = pCtx->pRecord;
    208     Assert(pRecord && (pRecord->cbRecord & VBVA_F_RECORD_PARTIAL));
    209 
    210     /* Mark the record completed. */
    211     pRecord->cbRecord &= ~VBVA_F_RECORD_PARTIAL;
    212 
    213     pCtx->fHwBufferOverflow = false;
    214     pCtx->pRecord = NULL;
    215 
    216     return;
    217 }
    218 
    219 /*
    220  * Private operations.
    221  */
    222 static uint32_t vboxHwBufferAvail (const VBVABUFFER *pVBVA)
    223 {
    224     int32_t i32Diff = pVBVA->off32Data - pVBVA->off32Free;
    225 
    226     return i32Diff > 0? i32Diff: pVBVA->cbData + i32Diff;
    227 }
    228 
    229 static void vboxHwBufferFlush(PHGSMIGUESTCOMMANDCONTEXT pCtx)
    230 {
    231     /* Issue the flush command. */
    232     void *p = VBoxHGSMIBufferAlloc(pCtx,
    233                                    sizeof (VBVAFLUSH),
    234                                    HGSMI_CH_VBVA,
    235                                    VBVA_FLUSH);
    236     if (!p)
    237     {
    238         LogFunc(("HGSMIHeapAlloc failed\n"));
    239     }
    240     else
    241     {
    242         VBVAFLUSH *pFlush = (VBVAFLUSH *)p;
    243 
    244         pFlush->u32Reserved = 0;
    245 
    246         VBoxHGSMIBufferSubmit(pCtx, p);
    247 
    248         VBoxHGSMIBufferSubmit(pCtx, p);
    249     }
    250 
    251     return;
    252 }
    253 
    254 static void vboxHwBufferPlaceDataAt(PVBVABUFFERCONTEXT pCtx, const void *p,
    255                                     uint32_t cb, uint32_t offset)
    256 {
    257     VBVABUFFER *pVBVA = pCtx->pVBVA;
    258     uint32_t u32BytesTillBoundary = pVBVA->cbData - offset;
    259     uint8_t  *dst                 = &pVBVA->au8Data[offset];
    260     int32_t i32Diff               = cb - u32BytesTillBoundary;
    261 
    262     if (i32Diff <= 0)
    263     {
    264         /* Chunk will not cross buffer boundary. */
    265         memcpy (dst, p, cb);
    266     }
    267     else
    268     {
    269         /* Chunk crosses buffer boundary. */
    270         memcpy (dst, p, u32BytesTillBoundary);
    271         memcpy (&pVBVA->au8Data[0], (uint8_t *)p + u32BytesTillBoundary, i32Diff);
    272     }
    273 
    274     return;
    275 }
    276 
    277 static bool vboxHwBufferWrite(PVBVABUFFERCONTEXT pCtx,
    278                               PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx,
    279                               const void *p, uint32_t cb)
    280 {
    281     VBVARECORD *pRecord;
    282     uint32_t cbHwBufferAvail;
    283 
    284     uint32_t cbWritten = 0;
    285 
    286     VBVABUFFER *pVBVA = pCtx->pVBVA;
    287     Assert(pVBVA);
    288 
    289     if (!pVBVA || pCtx->fHwBufferOverflow)
    290     {
    291         return false;
    292     }
    293 
    294     Assert(pVBVA->indexRecordFirst != pVBVA->indexRecordFree);
    295 
    296     pRecord = pCtx->pRecord;
    297     Assert(pRecord && (pRecord->cbRecord & VBVA_F_RECORD_PARTIAL));
    298 
    299     LogFunc(("%d\n", cb));
    300 
    301     cbHwBufferAvail = vboxHwBufferAvail (pVBVA);
    302 
    303     while (cb > 0)
    304     {
    305         uint32_t cbChunk = cb;
    306 
    307         // LogFunc(("pVBVA->off32Free %d, pRecord->cbRecord 0x%08X, cbHwBufferAvail %d, cb %d, cbWritten %d\n",
    308         //             pVBVA->off32Free, pRecord->cbRecord, cbHwBufferAvail, cb, cbWritten));
    309 
    310         if (cbChunk >= cbHwBufferAvail)
    311         {
    312             LogFunc(("1) avail %d, chunk %d\n", cbHwBufferAvail, cbChunk));
    313 
    314             vboxHwBufferFlush (pHGSMICtx);
    315 
    316             cbHwBufferAvail = vboxHwBufferAvail (pVBVA);
    317 
    318             if (cbChunk >= cbHwBufferAvail)
    319             {
    320                 LogFunc(("no place for %d bytes. Only %d bytes available after flush. Going to partial writes.\n",
    321                             cb, cbHwBufferAvail));
    322 
    323                 if (cbHwBufferAvail <= pVBVA->cbPartialWriteThreshold)
    324                 {
    325                     LogFunc(("Buffer overflow!!!\n"));
    326                     pCtx->fHwBufferOverflow = true;
    327                     Assert(false);
    328                     return false;
    329                 }
    330 
    331                 cbChunk = cbHwBufferAvail - pVBVA->cbPartialWriteThreshold;
    332             }
    333         }
    334 
    335         Assert(cbChunk <= cb);
    336         Assert(cbChunk <= vboxHwBufferAvail (pVBVA));
    337 
    338         vboxHwBufferPlaceDataAt (pCtx, (uint8_t *)p + cbWritten, cbChunk, pVBVA->off32Free);
    339 
    340         pVBVA->off32Free   = (pVBVA->off32Free + cbChunk) % pVBVA->cbData;
    341         pRecord->cbRecord += cbChunk;
    342         cbHwBufferAvail -= cbChunk;
    343 
    344         cb        -= cbChunk;
    345         cbWritten += cbChunk;
    346     }
    347 
    348     return true;
    349 }
    350 
    351 /*
    352  * Public writer to the hardware buffer.
    353  */
    354 RTDECL(bool) VBoxVBVAWrite(PVBVABUFFERCONTEXT pCtx,
    355                            PHGSMIGUESTCOMMANDCONTEXT pHGSMICtx,
    356                            const void *pv, uint32_t cb)
    357 {
    358     return vboxHwBufferWrite (pCtx, pHGSMICtx, pv, cb);
    359 }
    360 
    361 RTDECL(bool) VBoxVBVAOrderSupported(PVBVABUFFERCONTEXT pCtx, unsigned code)
    362 {
    363     VBVABUFFER *pVBVA = pCtx->pVBVA;
    364 
    365     if (!pVBVA)
    366     {
    367         return FALSE;
    368     }
    369 
    370     if (pVBVA->hostFlags.u32SupportedOrders & (1 << code))
    371     {
    372         return true;
    373     }
    374 
    375     return FALSE;
    376 }
    377 
    378 RTDECL(void) VBoxHGSMIProcessDisplayInfo(PHGSMIGUESTCOMMANDCONTEXT pCtx,
    379                                          uint32_t cDisplay,
    380                                          int32_t  cOriginX,
    381                                          int32_t  cOriginY,
    382                                          uint32_t offStart,
    383                                          uint32_t cbPitch,
    384                                          uint32_t cWidth,
    385                                          uint32_t cHeight,
    386                                          uint16_t cBPP)
    387 {
    388     /* Issue the screen info command. */
    389     void *p = VBoxHGSMIBufferAlloc(pCtx,
    390                                    sizeof (VBVAINFOSCREEN),
    391                                    HGSMI_CH_VBVA,
    392                                    VBVA_INFO_SCREEN);
    393     if (!p)
    394     {
    395         LogFunc(("HGSMIHeapAlloc failed\n"));
    396     }
    397     else
    398     {
    399         VBVAINFOSCREEN *pScreen = (VBVAINFOSCREEN *)p;
    400 
    401         pScreen->u32ViewIndex    = cDisplay;
    402         pScreen->i32OriginX      = cOriginX;
    403         pScreen->i32OriginY      = cOriginY;
    404         pScreen->u32StartOffset  = offStart;
    405         pScreen->u32LineSize     = cbPitch;
    406         pScreen->u32Width        = cWidth;
    407         pScreen->u32Height       = cHeight;
    408         pScreen->u16BitsPerPixel = cBPP;
    409         pScreen->u16Flags        = VBVA_SCREEN_F_ACTIVE;
    410 
    411         VBoxHGSMIBufferSubmit(pCtx, p);
    412 
    413         VBoxHGSMIBufferFree(pCtx, p);
    414     }
    415 }
    41627
    41728void VBoxProcessDisplayInfo (PPDEV ppdev)
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette