VirtualBox

Changeset 86265 in vbox


Ignore:
Timestamp:
Sep 24, 2020 12:42:43 PM (4 years ago)
Author:
vboxsync
Message:

Devices/Graphics: Split DevVGA-SVGA.cpp to two source files (device and command implementation) and an internal header file. bugref:9830

Location:
trunk/src/VBox/Devices
Files:
2 edited
2 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Graphics/DevVGA-SVGA-cmd.cpp

    r86252 r86265  
    11/* $Id$ */
    22/** @file
    3  * VMware SVGA device.
    4  *
    5  * Logging levels guidelines for this and related files:
    6  *  - Log() for normal bits.
    7  *  - LogFlow() for more info.
    8  *  - Log2 for hex dump of cursor data.
    9  *  - Log3 for hex dump of shader code.
    10  *  - Log4 for hex dumps of 3D data.
    11  *  - Log5 for info about GMR pages.
    12  *  - LogRel for the usual important stuff.
    13  *  - LogRel2 for cursor.
    14  *  - LogRel3 for 3D performance data.
    15  *  - LogRel4 for HW accelerated graphics output.
     3 * VMware SVGA device - implementation of VMSVGA commands.
    164 */
    175
     
    2816 */
    2917
    30 
    31 /** @page pg_dev_vmsvga     VMSVGA - VMware SVGA II Device Emulation
    32  *
    33  * This device emulation was contributed by trivirt AG.  It offers an
    34  * alternative to our Bochs based VGA graphics and 3d emulations.  This is
    35  * valuable for Xorg based guests, as there is driver support shipping with Xorg
    36  * since it forked from XFree86.
    37  *
    38  *
    39  * @section sec_dev_vmsvga_sdk  The VMware SDK
    40  *
    41  * This is officially deprecated now, however it's still quite useful,
    42  * especially for getting the old features working:
    43  * http://vmware-svga.sourceforge.net/
    44  *
    45  * They currently point developers at the following resources.
    46  *  - http://cgit.freedesktop.org/xorg/driver/xf86-video-vmware/
    47  *  - http://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/svga/
    48  *  - http://cgit.freedesktop.org/mesa/vmwgfx/
    49  *
    50  * @subsection subsec_dev_vmsvga_sdk_results  Test results
    51  *
    52  * Test results:
    53  *  - 2dmark.img:
    54  *       + todo
    55  *  - backdoor-tclo.img:
    56  *       + todo
    57  *  - blit-cube.img:
    58  *       + todo
    59  *  - bunnies.img:
    60  *       + todo
    61  *  - cube.img:
    62  *       + todo
    63  *  - cubemark.img:
    64  *       + todo
    65  *  - dynamic-vertex-stress.img:
    66  *       + todo
    67  *  - dynamic-vertex.img:
    68  *       + todo
    69  *  - fence-stress.img:
    70  *       + todo
    71  *  - gmr-test.img:
    72  *       + todo
    73  *  - half-float-test.img:
    74  *       + todo
    75  *  - noscreen-cursor.img:
    76  *       - The CURSOR I/O and FIFO registers are not implemented, so the mouse
    77  *         cursor doesn't show. (Hacking the GUI a little, would make the cursor
    78  *         visible though.)
    79  *       - Cursor animation via the palette doesn't work.
    80  *       - During debugging, it turns out that the framebuffer content seems to
    81  *         be halfways ignore or something (memset(fb, 0xcc, lots)).
    82  *       - Trouble with way to small FIFO and the 256x256 cursor fails. Need to
    83  *         grow it 0x10 fold (128KB -> 2MB like in WS10).
    84  *  - null.img:
    85  *       + todo
    86  *  - pong.img:
    87  *       + todo
    88  *  - presentReadback.img:
    89  *       + todo
    90  *  - resolution-set.img:
    91  *       + todo
    92  *  - rt-gamma-test.img:
    93  *       + todo
    94  *  - screen-annotation.img:
    95  *       + todo
    96  *  - screen-cursor.img:
    97  *       + todo
    98  *  - screen-dma-coalesce.img:
    99  *       + todo
    100  *  - screen-gmr-discontig.img:
    101  *       + todo
    102  *  - screen-gmr-remap.img:
    103  *       + todo
    104  *  - screen-multimon.img:
    105  *       + todo
    106  *  - screen-present-clip.img:
    107  *       + todo
    108  *  - screen-render-test.img:
    109  *       + todo
    110  *  - screen-simple.img:
    111  *       + todo
    112  *  - screen-text.img:
    113  *       + todo
    114  *  - simple-shaders.img:
    115  *       + todo
    116  *  - simple_blit.img:
    117  *       + todo
    118  *  - tiny-2d-updates.img:
    119  *       + todo
    120  *  - video-formats.img:
    121  *       + todo
    122  *  - video-sync.img:
    123  *       + todo
    124  *
    125  */
    126 
    127 
    128 /*********************************************************************************************************************************
    129 *   Header Files                                                                                                                 *
    130 *********************************************************************************************************************************/
     18#ifndef IN_RING3
     19# error "DevVGA-SVGA-cmd.cpp is only for ring-3 code"
     20#endif
     21
     22
    13123#define LOG_GROUP LOG_GROUP_DEV_VMSVGA
    132 #define VMSVGA_USE_EMT_HALT_CODE
     24#include <iprt/mem.h>
     25#include <VBox/AssertGuest.h>
     26#include <VBox/log.h>
    13327#include <VBox/vmm/pdmdev.h>
    134 #include <VBox/version.h>
    135 #include <VBox/err.h>
    136 #include <VBox/log.h>
    137 #include <VBox/vmm/pgm.h>
    138 #ifdef VMSVGA_USE_EMT_HALT_CODE
    139 # include <VBox/vmm/vmapi.h>
    140 # include <VBox/vmm/vmcpuset.h>
    141 #endif
    142 #include <VBox/sup.h>
    143 
    144 #include <iprt/assert.h>
    145 #include <iprt/semaphore.h>
    146 #include <iprt/uuid.h>
    147 #ifdef IN_RING3
    148 # include <iprt/ctype.h>
    149 # include <iprt/mem.h>
    150 # ifdef VBOX_STRICT
    151 #  include <iprt/time.h>
    152 # endif
    153 #endif
    154 
    155 #include <VBox/AssertGuest.h>
    156 #include <VBox/VMMDev.h>
    15728#include <VBoxVideo.h>
    158 #include <VBox/bioslogo.h>
    15929
    16030/* should go BEFORE any other DevVGA include to make all DevVGA.h config defines be visible */
    16131#include "DevVGA.h"
    16232
    163 #include "DevVGA-SVGA.h"
     33#include "DevVGA-SVGA-internal.h"
    16434#ifdef VBOX_WITH_VMSVGA3D
    16535# include "DevVGA-SVGA3d.h"
    166 # ifdef RT_OS_DARWIN
    167 #  include "DevVGA-SVGA3d-cocoa.h"
    168 # endif
    169 # ifdef RT_OS_LINUX
    170 #  ifdef IN_RING3
    171 #   include "DevVGA-SVGA3d-glLdr.h"
    172 #  endif
    173 # endif
    17436#endif
    17537
    17638
    177 /*********************************************************************************************************************************
    178 *   Defined Constants And Macros                                                                                                 *
    179 *********************************************************************************************************************************/
    180 /**
    181  * Macro for checking if a fixed FIFO register is valid according to the
    182  * current FIFO configuration.
    183  *
    184  * @returns true / false.
    185  * @param   a_iIndex        The fifo register index (like SVGA_FIFO_CAPABILITIES).
    186  * @param   a_offFifoMin    A valid SVGA_FIFO_MIN value.
    187  */
    188 #define VMSVGA_IS_VALID_FIFO_REG(a_iIndex, a_offFifoMin) ( ((a_iIndex) + 1) * sizeof(uint32_t) <= (a_offFifoMin) )
    189 
    190 
    191 /*********************************************************************************************************************************
    192 *   Structures and Typedefs                                                                                                      *
    193 *********************************************************************************************************************************/
    194 /**
    195  * 64-bit GMR descriptor.
    196  */
    197 typedef struct
    198 {
    199    RTGCPHYS GCPhys;
    200    uint64_t numPages;
    201 } VMSVGAGMRDESCRIPTOR, *PVMSVGAGMRDESCRIPTOR;
    202 
    203 /**
    204  * GMR slot
    205  */
    206 typedef struct
    207 {
    208     uint32_t                    cMaxPages;
    209     uint32_t                    cbTotal;
    210     uint32_t                    numDescriptors;
    211     PVMSVGAGMRDESCRIPTOR        paDesc;
    212 } GMR, *PGMR;
    213 
    214 #ifdef IN_RING3
    215 typedef struct VMSVGACMDBUF *PVMSVGACMDBUF;
    216 typedef struct VMSVGACMDBUFCTX *PVMSVGACMDBUFCTX;
    217 
    218 /* Command buffer. */
    219 typedef struct VMSVGACMDBUF
    220 {
    221     RTLISTNODE nodeBuffer;
    222     /* Context of the buffer. */
    223     PVMSVGACMDBUFCTX pCmdBufCtx;
    224     /* PA of the buffer. */
    225     RTGCPHYS GCPhysCB;
    226     /* A copy of the buffer header. */
    227     SVGACBHeader hdr;
    228     /* A copy of the commands. Size of the memory buffer is hdr.length */
    229     void *pvCommands;
    230 } VMSVGACMDBUF;
    231 
    232 /* Command buffer context. */
    233 typedef struct VMSVGACMDBUFCTX
    234 {
    235     /* Buffers submitted to processing for the FIFO thread. */
    236     RTLISTANCHOR listSubmitted;
    237     /* How many buffers in the queue. */
    238     uint32_t cSubmitted;
    239 } VMSVGACMDBUFCTX;
    240 
    241 /**
    242  * Internal SVGA ring-3 only state.
    243  */
    244 typedef struct VMSVGAR3STATE
    245 {
    246     GMR                    *paGMR; // [VMSVGAState::cGMR]
    247     struct
    248     {
    249         SVGAGuestPtr RT_UNTRUSTED_GUEST         ptr;
    250         uint32_t RT_UNTRUSTED_GUEST             bytesPerLine;
    251         SVGAGMRImageFormat RT_UNTRUSTED_GUEST   format;
    252     } GMRFB;
    253     struct
    254     {
    255         bool                fActive;
    256         uint32_t            xHotspot;
    257         uint32_t            yHotspot;
    258         uint32_t            width;
    259         uint32_t            height;
    260         uint32_t            cbData;
    261         void               *pData;
    262     } Cursor;
    263     SVGAColorBGRX           colorAnnotation;
    264 
    265 # ifdef VMSVGA_USE_EMT_HALT_CODE
    266     /** Number of EMTs in BusyDelayedEmts (quicker than scanning the set). */
    267     uint32_t volatile       cBusyDelayedEmts;
    268     /** Set of EMTs that are   */
    269     VMCPUSET                BusyDelayedEmts;
    270 # else
    271     /** Number of EMTs waiting on hBusyDelayedEmts. */
    272     uint32_t volatile       cBusyDelayedEmts;
    273     /** Semaphore that EMTs wait on when reading SVGA_REG_BUSY and the FIFO is
    274      *  busy (ugly).  */
    275     RTSEMEVENTMULTI         hBusyDelayedEmts;
    276 # endif
    277 
    278     /** Information about screens. */
    279     VMSVGASCREENOBJECT      aScreens[64];
    280 
    281     /** Command buffer contexts. */
    282     PVMSVGACMDBUFCTX        apCmdBufCtxs[SVGA_CB_CONTEXT_MAX];
    283     /** The special Device Context for synchronous commands. */
    284     VMSVGACMDBUFCTX         CmdBufCtxDC;
    285     /** Flag which indicates that there are buffers to be processed. */
    286     uint32_t volatile       fCmdBuf;
    287     /** Critical section for accessing the command buffer data. */
    288     RTCRITSECT              CritSectCmdBuf;
    289 
    290     /** Tracks how much time we waste reading SVGA_REG_BUSY with a busy FIFO. */
    291     STAMPROFILE             StatBusyDelayEmts;
    292 
    293     STAMPROFILE             StatR3Cmd3dPresentProf;
    294     STAMPROFILE             StatR3Cmd3dDrawPrimitivesProf;
    295     STAMPROFILE             StatR3Cmd3dSurfaceDmaProf;
    296     STAMPROFILE             StatR3Cmd3dBlitSurfaceToScreenProf;
    297     STAMCOUNTER             StatR3CmdDefineGmr2;
    298     STAMCOUNTER             StatR3CmdDefineGmr2Free;
    299     STAMCOUNTER             StatR3CmdDefineGmr2Modify;
    300     STAMCOUNTER             StatR3CmdRemapGmr2;
    301     STAMCOUNTER             StatR3CmdRemapGmr2Modify;
    302     STAMCOUNTER             StatR3CmdInvalidCmd;
    303     STAMCOUNTER             StatR3CmdFence;
    304     STAMCOUNTER             StatR3CmdUpdate;
    305     STAMCOUNTER             StatR3CmdUpdateVerbose;
    306     STAMCOUNTER             StatR3CmdDefineCursor;
    307     STAMCOUNTER             StatR3CmdDefineAlphaCursor;
    308     STAMCOUNTER             StatR3CmdMoveCursor;
    309     STAMCOUNTER             StatR3CmdDisplayCursor;
    310     STAMCOUNTER             StatR3CmdRectFill;
    311     STAMCOUNTER             StatR3CmdRectCopy;
    312     STAMCOUNTER             StatR3CmdRectRopCopy;
    313     STAMCOUNTER             StatR3CmdEscape;
    314     STAMCOUNTER             StatR3CmdDefineScreen;
    315     STAMCOUNTER             StatR3CmdDestroyScreen;
    316     STAMCOUNTER             StatR3CmdDefineGmrFb;
    317     STAMCOUNTER             StatR3CmdBlitGmrFbToScreen;
    318     STAMCOUNTER             StatR3CmdBlitScreentoGmrFb;
    319     STAMCOUNTER             StatR3CmdAnnotationFill;
    320     STAMCOUNTER             StatR3CmdAnnotationCopy;
    321     STAMCOUNTER             StatR3Cmd3dSurfaceDefine;
    322     STAMCOUNTER             StatR3Cmd3dSurfaceDefineV2;
    323     STAMCOUNTER             StatR3Cmd3dSurfaceDestroy;
    324     STAMCOUNTER             StatR3Cmd3dSurfaceCopy;
    325     STAMCOUNTER             StatR3Cmd3dSurfaceStretchBlt;
    326     STAMCOUNTER             StatR3Cmd3dSurfaceDma;
    327     STAMCOUNTER             StatR3Cmd3dSurfaceScreen;
    328     STAMCOUNTER             StatR3Cmd3dContextDefine;
    329     STAMCOUNTER             StatR3Cmd3dContextDestroy;
    330     STAMCOUNTER             StatR3Cmd3dSetTransform;
    331     STAMCOUNTER             StatR3Cmd3dSetZRange;
    332     STAMCOUNTER             StatR3Cmd3dSetRenderState;
    333     STAMCOUNTER             StatR3Cmd3dSetRenderTarget;
    334     STAMCOUNTER             StatR3Cmd3dSetTextureState;
    335     STAMCOUNTER             StatR3Cmd3dSetMaterial;
    336     STAMCOUNTER             StatR3Cmd3dSetLightData;
    337     STAMCOUNTER             StatR3Cmd3dSetLightEnable;
    338     STAMCOUNTER             StatR3Cmd3dSetViewPort;
    339     STAMCOUNTER             StatR3Cmd3dSetClipPlane;
    340     STAMCOUNTER             StatR3Cmd3dClear;
    341     STAMCOUNTER             StatR3Cmd3dPresent;
    342     STAMCOUNTER             StatR3Cmd3dPresentReadBack;
    343     STAMCOUNTER             StatR3Cmd3dShaderDefine;
    344     STAMCOUNTER             StatR3Cmd3dShaderDestroy;
    345     STAMCOUNTER             StatR3Cmd3dSetShader;
    346     STAMCOUNTER             StatR3Cmd3dSetShaderConst;
    347     STAMCOUNTER             StatR3Cmd3dDrawPrimitives;
    348     STAMCOUNTER             StatR3Cmd3dSetScissorRect;
    349     STAMCOUNTER             StatR3Cmd3dBeginQuery;
    350     STAMCOUNTER             StatR3Cmd3dEndQuery;
    351     STAMCOUNTER             StatR3Cmd3dWaitForQuery;
    352     STAMCOUNTER             StatR3Cmd3dGenerateMipmaps;
    353     STAMCOUNTER             StatR3Cmd3dActivateSurface;
    354     STAMCOUNTER             StatR3Cmd3dDeactivateSurface;
    355 
    356     STAMCOUNTER             StatR3RegConfigDoneWr;
    357     STAMCOUNTER             StatR3RegGmrDescriptorWr;
    358     STAMCOUNTER             StatR3RegGmrDescriptorWrErrors;
    359     STAMCOUNTER             StatR3RegGmrDescriptorWrFree;
    360 
    361     STAMCOUNTER             StatFifoCommands;
    362     STAMCOUNTER             StatFifoErrors;
    363     STAMCOUNTER             StatFifoUnkCmds;
    364     STAMCOUNTER             StatFifoTodoTimeout;
    365     STAMCOUNTER             StatFifoTodoWoken;
    366     STAMPROFILE             StatFifoStalls;
    367     STAMPROFILE             StatFifoExtendedSleep;
    368 # ifdef VMSVGA_USE_FIFO_ACCESS_HANDLER
    369     STAMCOUNTER             StatFifoAccessHandler;
    370 # endif
    371     STAMCOUNTER             StatFifoCursorFetchAgain;
    372     STAMCOUNTER             StatFifoCursorNoChange;
    373     STAMCOUNTER             StatFifoCursorPosition;
    374     STAMCOUNTER             StatFifoCursorVisiblity;
    375     STAMCOUNTER             StatFifoWatchdogWakeUps;
    376 } VMSVGAR3STATE, *PVMSVGAR3STATE;
    377 #endif /* IN_RING3 */
    378 
    379 
    380 /*********************************************************************************************************************************
    381 *   Internal Functions                                                                                                           *
    382 *********************************************************************************************************************************/
    383 #ifdef IN_RING3
    384 # if defined(VMSVGA_USE_FIFO_ACCESS_HANDLER) || defined(DEBUG_FIFO_ACCESS)
    385 static FNPGMPHYSHANDLER vmsvgaR3FifoAccessHandler;
    386 # endif
    387 # ifdef DEBUG_GMR_ACCESS
    388 static FNPGMPHYSHANDLER vmsvgaR3GmrAccessHandler;
    389 # endif
    390 #endif
    391 
    392 
    393 /*********************************************************************************************************************************
    394 *   Global Variables                                                                                                             *
    395 *********************************************************************************************************************************/
    396 #ifdef IN_RING3
    397 
    398 /**
    399  * SSM descriptor table for the VMSVGAGMRDESCRIPTOR structure.
    400  */
    401 static SSMFIELD const g_aVMSVGAGMRDESCRIPTORFields[] =
    402 {
    403     SSMFIELD_ENTRY_GCPHYS(      VMSVGAGMRDESCRIPTOR,     GCPhys),
    404     SSMFIELD_ENTRY(             VMSVGAGMRDESCRIPTOR,     numPages),
    405     SSMFIELD_ENTRY_TERM()
    406 };
    407 
    408 /**
    409  * SSM descriptor table for the GMR structure.
    410  */
    411 static SSMFIELD const g_aGMRFields[] =
    412 {
    413     SSMFIELD_ENTRY(             GMR, cMaxPages),
    414     SSMFIELD_ENTRY(             GMR, cbTotal),
    415     SSMFIELD_ENTRY(             GMR, numDescriptors),
    416     SSMFIELD_ENTRY_IGN_HCPTR(   GMR, paDesc),
    417     SSMFIELD_ENTRY_TERM()
    418 };
    419 
    420 /**
    421  * SSM descriptor table for the VMSVGASCREENOBJECT structure.
    422  */
    423 static SSMFIELD const g_aVMSVGASCREENOBJECTFields[] =
    424 {
    425     SSMFIELD_ENTRY(             VMSVGASCREENOBJECT, fuScreen),
    426     SSMFIELD_ENTRY(             VMSVGASCREENOBJECT, idScreen),
    427     SSMFIELD_ENTRY(             VMSVGASCREENOBJECT, xOrigin),
    428     SSMFIELD_ENTRY(             VMSVGASCREENOBJECT, yOrigin),
    429     SSMFIELD_ENTRY(             VMSVGASCREENOBJECT, cWidth),
    430     SSMFIELD_ENTRY(             VMSVGASCREENOBJECT, cHeight),
    431     SSMFIELD_ENTRY(             VMSVGASCREENOBJECT, offVRAM),
    432     SSMFIELD_ENTRY(             VMSVGASCREENOBJECT, cbPitch),
    433     SSMFIELD_ENTRY(             VMSVGASCREENOBJECT, cBpp),
    434     SSMFIELD_ENTRY(             VMSVGASCREENOBJECT, fDefined),
    435     SSMFIELD_ENTRY(             VMSVGASCREENOBJECT, fModified),
    436     SSMFIELD_ENTRY_TERM()
    437 };
    438 
    439 /**
    440  * SSM descriptor table for the VMSVGAR3STATE structure.
    441  */
    442 static SSMFIELD const g_aVMSVGAR3STATEFields[] =
    443 {
    444     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, paGMR),
    445     SSMFIELD_ENTRY(             VMSVGAR3STATE, GMRFB),
    446     SSMFIELD_ENTRY(             VMSVGAR3STATE, Cursor.fActive),
    447     SSMFIELD_ENTRY(             VMSVGAR3STATE, Cursor.xHotspot),
    448     SSMFIELD_ENTRY(             VMSVGAR3STATE, Cursor.yHotspot),
    449     SSMFIELD_ENTRY(             VMSVGAR3STATE, Cursor.width),
    450     SSMFIELD_ENTRY(             VMSVGAR3STATE, Cursor.height),
    451     SSMFIELD_ENTRY(             VMSVGAR3STATE, Cursor.cbData),
    452     SSMFIELD_ENTRY_IGN_HCPTR(   VMSVGAR3STATE, Cursor.pData),
    453     SSMFIELD_ENTRY(             VMSVGAR3STATE, colorAnnotation),
    454     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, cBusyDelayedEmts),
    455 #ifdef VMSVGA_USE_EMT_HALT_CODE
    456     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, BusyDelayedEmts),
    457 #else
    458     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, hBusyDelayedEmts),
    459 #endif
    460     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatBusyDelayEmts),
    461     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dPresentProf),
    462     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dDrawPrimitivesProf),
    463     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSurfaceDmaProf),
    464     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dBlitSurfaceToScreenProf),
    465     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdDefineGmr2),
    466     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdDefineGmr2Free),
    467     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdDefineGmr2Modify),
    468     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdRemapGmr2),
    469     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdRemapGmr2Modify),
    470     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdInvalidCmd),
    471     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdFence),
    472     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdUpdate),
    473     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdUpdateVerbose),
    474     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdDefineCursor),
    475     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdDefineAlphaCursor),
    476     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdMoveCursor),
    477     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdDisplayCursor),
    478     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdRectFill),
    479     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdRectCopy),
    480     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdRectRopCopy),
    481     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdEscape),
    482     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdDefineScreen),
    483     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdDestroyScreen),
    484     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdDefineGmrFb),
    485     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdBlitGmrFbToScreen),
    486     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdBlitScreentoGmrFb),
    487     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdAnnotationFill),
    488     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdAnnotationCopy),
    489     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSurfaceDefine),
    490     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSurfaceDefineV2),
    491     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSurfaceDestroy),
    492     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSurfaceCopy),
    493     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSurfaceStretchBlt),
    494     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSurfaceDma),
    495     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSurfaceScreen),
    496     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dContextDefine),
    497     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dContextDestroy),
    498     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSetTransform),
    499     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSetZRange),
    500     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSetRenderState),
    501     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSetRenderTarget),
    502     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSetTextureState),
    503     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSetMaterial),
    504     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSetLightData),
    505     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSetLightEnable),
    506     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSetViewPort),
    507     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSetClipPlane),
    508     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dClear),
    509     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dPresent),
    510     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dPresentReadBack),
    511     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dShaderDefine),
    512     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dShaderDestroy),
    513     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSetShader),
    514     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSetShaderConst),
    515     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dDrawPrimitives),
    516     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSetScissorRect),
    517     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dBeginQuery),
    518     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dEndQuery),
    519     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dWaitForQuery),
    520     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dGenerateMipmaps),
    521     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dActivateSurface),
    522     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dDeactivateSurface),
    523 
    524     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3RegConfigDoneWr),
    525     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3RegGmrDescriptorWr),
    526     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3RegGmrDescriptorWrErrors),
    527     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3RegGmrDescriptorWrFree),
    528 
    529     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatFifoCommands),
    530     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatFifoErrors),
    531     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatFifoUnkCmds),
    532     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatFifoTodoTimeout),
    533     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatFifoTodoWoken),
    534     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatFifoStalls),
    535     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatFifoExtendedSleep),
    536 # if defined(VMSVGA_USE_FIFO_ACCESS_HANDLER) || defined(DEBUG_FIFO_ACCESS)
    537     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatFifoAccessHandler),
    538 # endif
    539     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatFifoCursorFetchAgain),
    540     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatFifoCursorNoChange),
    541     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatFifoCursorPosition),
    542     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatFifoCursorVisiblity),
    543 
    544     SSMFIELD_ENTRY_TERM()
    545 };
    546 
    547 /**
    548  * SSM descriptor table for the VGAState.svga structure.
    549  */
    550 static SSMFIELD const g_aVGAStateSVGAFields[] =
    551 {
    552     SSMFIELD_ENTRY_IGN_GCPHYS(      VMSVGAState, GCPhysFIFO),
    553     SSMFIELD_ENTRY_IGNORE(          VMSVGAState, cbFIFO),
    554     SSMFIELD_ENTRY_IGNORE(          VMSVGAState, cbFIFOConfig),
    555     SSMFIELD_ENTRY(                 VMSVGAState, u32SVGAId),
    556     SSMFIELD_ENTRY(                 VMSVGAState, fEnabled),
    557     SSMFIELD_ENTRY(                 VMSVGAState, fConfigured),
    558     SSMFIELD_ENTRY(                 VMSVGAState, fBusy),
    559     SSMFIELD_ENTRY(                 VMSVGAState, fTraces),
    560     SSMFIELD_ENTRY(                 VMSVGAState, u32GuestId),
    561     SSMFIELD_ENTRY(                 VMSVGAState, cScratchRegion),
    562     SSMFIELD_ENTRY(                 VMSVGAState, au32ScratchRegion),
    563     SSMFIELD_ENTRY(                 VMSVGAState, u32IrqStatus),
    564     SSMFIELD_ENTRY(                 VMSVGAState, u32IrqMask),
    565     SSMFIELD_ENTRY(                 VMSVGAState, u32PitchLock),
    566     SSMFIELD_ENTRY(                 VMSVGAState, u32CurrentGMRId),
    567     SSMFIELD_ENTRY(                 VMSVGAState, u32DeviceCaps),
    568     SSMFIELD_ENTRY(                 VMSVGAState, u32IndexReg),
    569     SSMFIELD_ENTRY_IGNORE(          VMSVGAState, hFIFORequestSem),
    570     SSMFIELD_ENTRY_IGNORE(          VMSVGAState, uLastCursorUpdateCount),
    571     SSMFIELD_ENTRY_IGNORE(          VMSVGAState, fFIFOThreadSleeping),
    572     SSMFIELD_ENTRY_VER(             VMSVGAState, fGFBRegisters, VGA_SAVEDSTATE_VERSION_VMSVGA_SCREENS),
    573     SSMFIELD_ENTRY(                 VMSVGAState, uWidth),
    574     SSMFIELD_ENTRY(                 VMSVGAState, uHeight),
    575     SSMFIELD_ENTRY(                 VMSVGAState, uBpp),
    576     SSMFIELD_ENTRY(                 VMSVGAState, cbScanline),
    577     SSMFIELD_ENTRY_VER(             VMSVGAState, uScreenOffset, VGA_SAVEDSTATE_VERSION_VMSVGA),
    578     SSMFIELD_ENTRY_VER(             VMSVGAState, uCursorX, VGA_SAVEDSTATE_VERSION_VMSVGA_CURSOR),
    579     SSMFIELD_ENTRY_VER(             VMSVGAState, uCursorY, VGA_SAVEDSTATE_VERSION_VMSVGA_CURSOR),
    580     SSMFIELD_ENTRY_VER(             VMSVGAState, uCursorID, VGA_SAVEDSTATE_VERSION_VMSVGA_CURSOR),
    581     SSMFIELD_ENTRY_VER(             VMSVGAState, uCursorOn, VGA_SAVEDSTATE_VERSION_VMSVGA_CURSOR),
    582     SSMFIELD_ENTRY(                 VMSVGAState, u32MaxWidth),
    583     SSMFIELD_ENTRY(                 VMSVGAState, u32MaxHeight),
    584     SSMFIELD_ENTRY(                 VMSVGAState, u32ActionFlags),
    585     SSMFIELD_ENTRY(                 VMSVGAState, f3DEnabled),
    586     SSMFIELD_ENTRY(                 VMSVGAState, fVRAMTracking),
    587     SSMFIELD_ENTRY_IGNORE(          VMSVGAState, u8FIFOExtCommand),
    588     SSMFIELD_ENTRY_IGNORE(          VMSVGAState, fFifoExtCommandWakeup),
    589     SSMFIELD_ENTRY_IGNORE(          VMSVGAState, cGMR),
    590     SSMFIELD_ENTRY_TERM()
    591 };
    592 #endif /* IN_RING3 */
    593 
    594 
    595 /*********************************************************************************************************************************
    596 *   Internal Functions                                                                                                           *
    597 *********************************************************************************************************************************/
    598 #ifdef IN_RING3
    599 static void vmsvgaR3SetTraces(PPDMDEVINS pDevIns, PVGASTATE pThis, bool fTraces);
    600 static int vmsvgaR3LoadExecFifo(PCPDMDEVHLPR3 pHlp, PVGASTATE pThis, PVGASTATECC pThisCC, PSSMHANDLE pSSM,
    601                                 uint32_t uVersion, uint32_t uPass);
    602 static int vmsvgaR3SaveExecFifo(PCPDMDEVHLPR3 pHlp, PVGASTATECC pThisCC, PSSMHANDLE pSSM);
    603 static void vmsvgaR3CmdBufSubmit(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, RTGCPHYS GCPhysCB, SVGACBContext CBCtx);
    604 # ifdef VBOX_WITH_VMSVGA3D
    605 static void vmsvgaR3GmrFree(PVGASTATECC pThisCC, uint32_t idGMR);
    606 # endif /* VBOX_WITH_VMSVGA3D */
    607 #endif /* IN_RING3 */
    608 
    609 
    610 
    611 #ifdef IN_RING3
    612 VMSVGASCREENOBJECT *vmsvgaR3GetScreenObject(PVGASTATECC pThisCC, uint32_t idScreen)
    613 {
    614     PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
    615     if (   idScreen < (uint32_t)RT_ELEMENTS(pSVGAState->aScreens)
    616         && pSVGAState
    617         && pSVGAState->aScreens[idScreen].fDefined)
    618     {
    619         return &pSVGAState->aScreens[idScreen];
    620     }
    621     return NULL;
    622 }
    623 
    624 void vmsvgaR3ResetScreens(PVGASTATE pThis, PVGASTATECC pThisCC)
    625 {
    626 # ifdef VBOX_WITH_VMSVGA3D
    627     if (pThis->svga.f3DEnabled)
    628     {
    629         for (uint32_t idScreen = 0; idScreen < (uint32_t)RT_ELEMENTS(pThisCC->svga.pSvgaR3State->aScreens); ++idScreen)
    630         {
    631             VMSVGASCREENOBJECT *pScreen = vmsvgaR3GetScreenObject(pThisCC, idScreen);
    632             if (pScreen)
    633                 vmsvga3dDestroyScreen(pThisCC, pScreen);
    634         }
    635     }
    636 # else
    637     RT_NOREF(pThis, pThisCC);
    638 # endif
    639 }
    640 #endif /* IN_RING3 */
    641 
    642 #define SVGA_CASE_ID2STR(idx) case idx: return #idx
    643 
    644 #if defined(LOG_ENABLED)
    645 /**
    646  * Index register string name lookup
    647  *
    648  * @returns Index register string or "UNKNOWN"
    649  * @param   pThis       The shared VGA/VMSVGA state.
    650  * @param   idxReg      The index register.
    651  */
    652 static const char *vmsvgaIndexToString(PVGASTATE pThis, uint32_t idxReg)
    653 {
    654     switch (idxReg)
    655     {
    656         SVGA_CASE_ID2STR(SVGA_REG_ID);
    657         SVGA_CASE_ID2STR(SVGA_REG_ENABLE);
    658         SVGA_CASE_ID2STR(SVGA_REG_WIDTH);
    659         SVGA_CASE_ID2STR(SVGA_REG_HEIGHT);
    660         SVGA_CASE_ID2STR(SVGA_REG_MAX_WIDTH);
    661         SVGA_CASE_ID2STR(SVGA_REG_MAX_HEIGHT);
    662         SVGA_CASE_ID2STR(SVGA_REG_DEPTH);
    663         SVGA_CASE_ID2STR(SVGA_REG_BITS_PER_PIXEL);       /* Current bpp in the guest */
    664         SVGA_CASE_ID2STR(SVGA_REG_PSEUDOCOLOR);
    665         SVGA_CASE_ID2STR(SVGA_REG_RED_MASK);
    666         SVGA_CASE_ID2STR(SVGA_REG_GREEN_MASK);
    667         SVGA_CASE_ID2STR(SVGA_REG_BLUE_MASK);
    668         SVGA_CASE_ID2STR(SVGA_REG_BYTES_PER_LINE);
    669         SVGA_CASE_ID2STR(SVGA_REG_FB_START);            /* (Deprecated) */
    670         SVGA_CASE_ID2STR(SVGA_REG_FB_OFFSET);
    671         SVGA_CASE_ID2STR(SVGA_REG_VRAM_SIZE);
    672         SVGA_CASE_ID2STR(SVGA_REG_FB_SIZE);
    673 
    674         /* ID 0 implementation only had the above registers, then the palette */
    675         SVGA_CASE_ID2STR(SVGA_REG_CAPABILITIES);
    676         SVGA_CASE_ID2STR(SVGA_REG_MEM_START);           /* (Deprecated) */
    677         SVGA_CASE_ID2STR(SVGA_REG_MEM_SIZE);
    678         SVGA_CASE_ID2STR(SVGA_REG_CONFIG_DONE);         /* Set when memory area configured */
    679         SVGA_CASE_ID2STR(SVGA_REG_SYNC);                /* See "FIFO Synchronization Registers" */
    680         SVGA_CASE_ID2STR(SVGA_REG_BUSY);                /* See "FIFO Synchronization Registers" */
    681         SVGA_CASE_ID2STR(SVGA_REG_GUEST_ID);            /* Set guest OS identifier */
    682         SVGA_CASE_ID2STR(SVGA_REG_CURSOR_ID);           /* (Deprecated) */
    683         SVGA_CASE_ID2STR(SVGA_REG_CURSOR_X);            /* (Deprecated) */
    684         SVGA_CASE_ID2STR(SVGA_REG_CURSOR_Y);            /* (Deprecated) */
    685         SVGA_CASE_ID2STR(SVGA_REG_CURSOR_ON);           /* (Deprecated) */
    686         SVGA_CASE_ID2STR(SVGA_REG_HOST_BITS_PER_PIXEL); /* (Deprecated) */
    687         SVGA_CASE_ID2STR(SVGA_REG_SCRATCH_SIZE);        /* Number of scratch registers */
    688         SVGA_CASE_ID2STR(SVGA_REG_MEM_REGS);            /* Number of FIFO registers */
    689         SVGA_CASE_ID2STR(SVGA_REG_NUM_DISPLAYS);        /* (Deprecated) */
    690         SVGA_CASE_ID2STR(SVGA_REG_PITCHLOCK);           /* Fixed pitch for all modes */
    691         SVGA_CASE_ID2STR(SVGA_REG_IRQMASK);             /* Interrupt mask */
    692 
    693         /* Legacy multi-monitor support */
    694         SVGA_CASE_ID2STR(SVGA_REG_NUM_GUEST_DISPLAYS); /* Number of guest displays in X/Y direction */
    695         SVGA_CASE_ID2STR(SVGA_REG_DISPLAY_ID);         /* Display ID for the following display attributes */
    696         SVGA_CASE_ID2STR(SVGA_REG_DISPLAY_IS_PRIMARY); /* Whether this is a primary display */
    697         SVGA_CASE_ID2STR(SVGA_REG_DISPLAY_POSITION_X); /* The display position x */
    698         SVGA_CASE_ID2STR(SVGA_REG_DISPLAY_POSITION_Y); /* The display position y */
    699         SVGA_CASE_ID2STR(SVGA_REG_DISPLAY_WIDTH);      /* The display's width */
    700         SVGA_CASE_ID2STR(SVGA_REG_DISPLAY_HEIGHT);     /* The display's height */
    701 
    702         SVGA_CASE_ID2STR(SVGA_REG_GMR_ID);
    703         SVGA_CASE_ID2STR(SVGA_REG_GMR_DESCRIPTOR);
    704         SVGA_CASE_ID2STR(SVGA_REG_GMR_MAX_IDS);
    705         SVGA_CASE_ID2STR(SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH);
    706 
    707         SVGA_CASE_ID2STR(SVGA_REG_TRACES);             /* Enable trace-based updates even when FIFO is on */
    708         SVGA_CASE_ID2STR(SVGA_REG_GMRS_MAX_PAGES);     /* Maximum number of 4KB pages for all GMRs */
    709         SVGA_CASE_ID2STR(SVGA_REG_MEMORY_SIZE);        /* Total dedicated device memory excluding FIFO */
    710         SVGA_CASE_ID2STR(SVGA_REG_COMMAND_LOW);        /* Lower 32 bits and submits commands */
    711         SVGA_CASE_ID2STR(SVGA_REG_COMMAND_HIGH);       /* Upper 32 bits of command buffer PA */
    712         SVGA_CASE_ID2STR(SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM);   /* Max primary memory */
    713         SVGA_CASE_ID2STR(SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB); /* Suggested limit on mob mem */
    714         SVGA_CASE_ID2STR(SVGA_REG_DEV_CAP);            /* Write dev cap index, read value */
    715         SVGA_CASE_ID2STR(SVGA_REG_CMD_PREPEND_LOW);
    716         SVGA_CASE_ID2STR(SVGA_REG_iCMD_PREPEND_HIGH);
    717         SVGA_CASE_ID2STR(SVGA_REG_SCREENTARGET_MAX_WIDTH);
    718         SVGA_CASE_ID2STR(SVGA_REG_SCREENTARGET_MAX_HEIGHT);
    719         SVGA_CASE_ID2STR(SVGA_REG_MOB_MAX_SIZE);
    720         SVGA_CASE_ID2STR(SVGA_REG_TOP);                /* Must be 1 more than the last register */
    721 
    722         default:
    723             if (idxReg - (uint32_t)SVGA_SCRATCH_BASE < pThis->svga.cScratchRegion)
    724                 return "SVGA_SCRATCH_BASE reg";
    725             if (idxReg - (uint32_t)SVGA_PALETTE_BASE < (uint32_t)SVGA_NUM_PALETTE_REGS)
    726                 return "SVGA_PALETTE_BASE reg";
    727             return "UNKNOWN";
    728     }
    729 }
    730 #endif /* LOG_ENABLED */
    731 
    732 #if defined(IN_RING3) && (defined(LOG_ENABLED) || defined(VBOX_STRICT))
     39#if defined(LOG_ENABLED) || defined(VBOX_STRICT)
     40# define SVGA_CASE_ID2STR(idx) case idx: return #idx
    73341/**
    73442 * FIFO command name lookup
     
    73745 * @param   u32Cmd      FIFO command
    73846 */
    739 static const char *vmsvgaR3FifoCmdToString(uint32_t u32Cmd)
     47const char *vmsvgaR3FifoCmdToString(uint32_t u32Cmd)
    74048{
    74149    switch (u32Cmd)
     
    959267    }
    960268}
    961 #endif /* IN_RING3 && (LOG_ENABLED || VBOX_STRICT) */
    962 
    963 #ifdef IN_RING3
    964 
    965 /**
    966  * @interface_method_impl{PDMIDISPLAYPORT,pfnSetViewport}
    967  */
    968 DECLCALLBACK(void) vmsvgaR3PortSetViewport(PPDMIDISPLAYPORT pInterface, uint32_t idScreen, uint32_t x, uint32_t y, uint32_t cx, uint32_t cy)
    969 {
    970     PVGASTATECC pThisCC = RT_FROM_MEMBER(pInterface, VGASTATECC, IPort);
    971     PVGASTATE   pThis   = PDMDEVINS_2_DATA(pThisCC->pDevIns, PVGASTATE);
    972 
    973     Log(("vmsvgaPortSetViewPort: screen %d (%d,%d)(%d,%d)\n", idScreen, x, y, cx, cy));
    974     VMSVGAVIEWPORT const OldViewport = pThis->svga.viewport;
    975 
    976     /** @todo Test how it interacts with multiple screen objects. */
    977     VMSVGASCREENOBJECT *pScreen = vmsvgaR3GetScreenObject(pThisCC, idScreen);
    978     uint32_t const uWidth = pScreen ? pScreen->cWidth : 0;
    979     uint32_t const uHeight = pScreen ? pScreen->cHeight : 0;
    980 
    981     if (x < uWidth)
    982     {
    983         pThis->svga.viewport.x      = x;
    984         pThis->svga.viewport.cx     = RT_MIN(cx, uWidth - x);
    985         pThis->svga.viewport.xRight = x + pThis->svga.viewport.cx;
    986     }
    987     else
    988     {
    989         pThis->svga.viewport.x      = uWidth;
    990         pThis->svga.viewport.cx     = 0;
    991         pThis->svga.viewport.xRight = uWidth;
    992     }
    993     if (y < uHeight)
    994     {
    995         pThis->svga.viewport.y       = y;
    996         pThis->svga.viewport.cy      = RT_MIN(cy, uHeight - y);
    997         pThis->svga.viewport.yLowWC  = uHeight - y - pThis->svga.viewport.cy;
    998         pThis->svga.viewport.yHighWC = uHeight - y;
    999     }
    1000     else
    1001     {
    1002         pThis->svga.viewport.y       = uHeight;
    1003         pThis->svga.viewport.cy      = 0;
    1004         pThis->svga.viewport.yLowWC  = 0;
    1005         pThis->svga.viewport.yHighWC = 0;
    1006     }
    1007 
    1008 # ifdef VBOX_WITH_VMSVGA3D
    1009     /*
    1010      * Now inform the 3D backend.
    1011      */
     269# undef SVGA_CASE_ID2STR
     270#endif /* LOG_ENABLED || VBOX_STRICT */
     271
     272
     273VMSVGASCREENOBJECT *vmsvgaR3GetScreenObject(PVGASTATECC pThisCC, uint32_t idScreen)
     274{
     275    PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
     276    if (   idScreen < (uint32_t)RT_ELEMENTS(pSVGAState->aScreens)
     277        && pSVGAState
     278        && pSVGAState->aScreens[idScreen].fDefined)
     279    {
     280        return &pSVGAState->aScreens[idScreen];
     281    }
     282    return NULL;
     283}
     284
     285void vmsvgaR3ResetScreens(PVGASTATE pThis, PVGASTATECC pThisCC)
     286{
     287#ifdef VBOX_WITH_VMSVGA3D
    1012288    if (pThis->svga.f3DEnabled)
    1013         vmsvga3dUpdateHostScreenViewport(pThisCC, idScreen, &OldViewport);
    1014 # else
    1015     RT_NOREF(OldViewport);
    1016 # endif
    1017 }
    1018 
    1019 
    1020 /**
    1021  * Updating screen information in API
    1022  *
    1023  * @param   pThis       The The shared VGA/VMSVGA instance data.
    1024  * @param   pThisCC     The VGA/VMSVGA state for ring-3.
    1025  */
    1026 void vmsvgaR3VBVAResize(PVGASTATE pThis, PVGASTATECC pThisCC)
    1027 {
    1028     int rc;
    1029 
    1030     PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
    1031 
    1032     for (unsigned iScreen = 0; iScreen < RT_ELEMENTS(pSVGAState->aScreens); ++iScreen)
    1033     {
    1034         VMSVGASCREENOBJECT *pScreen = &pSVGAState->aScreens[iScreen];
    1035         if (!pScreen->fModified)
    1036             continue;
    1037 
    1038         pScreen->fModified = false;
    1039 
    1040         VBVAINFOVIEW view;
    1041         RT_ZERO(view);
    1042         view.u32ViewIndex     = pScreen->idScreen;
    1043         // view.u32ViewOffset    = 0;
    1044         view.u32ViewSize      = pThis->vram_size;
    1045         view.u32MaxScreenSize = pThis->vram_size;
    1046 
    1047         VBVAINFOSCREEN screen;
    1048         RT_ZERO(screen);
    1049         screen.u32ViewIndex   = pScreen->idScreen;
    1050 
    1051         if (pScreen->fDefined)
     289    {
     290        for (uint32_t idScreen = 0; idScreen < (uint32_t)RT_ELEMENTS(pThisCC->svga.pSvgaR3State->aScreens); ++idScreen)
    1052291        {
    1053             if (   pScreen->cWidth  == VMSVGA_VAL_UNINITIALIZED
    1054                 || pScreen->cHeight == VMSVGA_VAL_UNINITIALIZED
    1055                 || pScreen->cBpp    == VMSVGA_VAL_UNINITIALIZED)
    1056             {
    1057                 Assert(pThis->svga.fGFBRegisters);
    1058                 continue;
    1059             }
    1060 
    1061             screen.i32OriginX      = pScreen->xOrigin;
    1062             screen.i32OriginY      = pScreen->yOrigin;
    1063             screen.u32StartOffset  = pScreen->offVRAM;
    1064             screen.u32LineSize     = pScreen->cbPitch;
    1065             screen.u32Width        = pScreen->cWidth;
    1066             screen.u32Height       = pScreen->cHeight;
    1067             screen.u16BitsPerPixel = pScreen->cBpp;
    1068             if (!(pScreen->fuScreen & SVGA_SCREEN_DEACTIVATE))
    1069                 screen.u16Flags    = VBVA_SCREEN_F_ACTIVE;
    1070             if (pScreen->fuScreen & SVGA_SCREEN_BLANKING)
    1071                 screen.u16Flags   |= VBVA_SCREEN_F_BLANK2;
     292            VMSVGASCREENOBJECT *pScreen = vmsvgaR3GetScreenObject(pThisCC, idScreen);
     293            if (pScreen)
     294                vmsvga3dDestroyScreen(pThisCC, pScreen);
    1072295        }
    1073         else
    1074         {
    1075             /* Screen is destroyed. */
    1076             screen.u16Flags        = VBVA_SCREEN_F_DISABLED;
    1077         }
    1078 
    1079         rc = pThisCC->pDrv->pfnVBVAResize(pThisCC->pDrv, &view, &screen, pThisCC->pbVRam, /*fResetInputMapping=*/ true);
    1080         AssertRC(rc);
    1081     }
    1082 }
    1083 
    1084 
    1085 /**
    1086  * @interface_method_impl{PDMIDISPLAYPORT,pfnReportMonitorPositions}
    1087  *
    1088  * Used to update screen offsets (positions) since appearently vmwgfx fails to
    1089  * pass correct offsets thru FIFO.
    1090  */
    1091 DECLCALLBACK(void) vmsvgaR3PortReportMonitorPositions(PPDMIDISPLAYPORT pInterface, uint32_t cPositions, PCRTPOINT paPositions)
    1092 {
    1093     PVGASTATECC         pThisCC    = RT_FROM_MEMBER(pInterface, VGASTATECC, IPort);
    1094     PVGASTATE           pThis      = PDMDEVINS_2_DATA(pThisCC->pDevIns, PVGASTATE);
    1095     PVMSVGAR3STATE      pSVGAState = pThisCC->svga.pSvgaR3State;
    1096 
    1097     AssertReturnVoid(pSVGAState);
    1098 
    1099     /* We assume cPositions is the # of outputs Xserver reports and paPositions is (-1, -1) for disabled monitors. */
    1100     cPositions = RT_MIN(cPositions, RT_ELEMENTS(pSVGAState->aScreens));
    1101     for (uint32_t i = 0; i < cPositions; ++i)
    1102     {
    1103         if (   pSVGAState->aScreens[i].xOrigin == paPositions[i].x
    1104             && pSVGAState->aScreens[i].yOrigin == paPositions[i].y)
    1105             continue;
    1106 
    1107         if (pSVGAState->aScreens[i].xOrigin == -1)
    1108             continue;
    1109         if (pSVGAState->aScreens[i].yOrigin == -1)
    1110             continue;
    1111 
    1112         pSVGAState->aScreens[i].xOrigin = paPositions[i].x;
    1113         pSVGAState->aScreens[i].yOrigin = paPositions[i].y;
    1114         pSVGAState->aScreens[i].fModified = true;
    1115     }
    1116 
    1117     vmsvgaR3VBVAResize(pThis, pThisCC);
    1118 }
    1119 
    1120 #endif /* IN_RING3 */
    1121 
    1122 /**
    1123  * Read port register
    1124  *
    1125  * @returns VBox status code.
    1126  * @param   pDevIns     The device instance.
    1127  * @param   pThis       The shared VGA/VMSVGA state.
    1128  * @param   pu32        Where to store the read value
    1129  */
    1130 static int vmsvgaReadPort(PPDMDEVINS pDevIns, PVGASTATE pThis, uint32_t *pu32)
    1131 {
    1132 #ifdef IN_RING3
    1133     PVGASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
     296    }
     297#else
     298    RT_NOREF(pThis, pThisCC);
    1134299#endif
    1135     int rc = VINF_SUCCESS;
    1136     *pu32 = 0;
    1137 
    1138     /* Rough index register validation. */
    1139     uint32_t idxReg = pThis->svga.u32IndexReg;
    1140 #if !defined(IN_RING3) && defined(VBOX_STRICT)
    1141     ASSERT_GUEST_MSG_RETURN(idxReg < SVGA_SCRATCH_BASE + pThis->svga.cScratchRegion, ("idxReg=%#x\n", idxReg),
    1142                             VINF_IOM_R3_IOPORT_READ);
    1143 #else
    1144     ASSERT_GUEST_MSG_STMT_RETURN(idxReg < SVGA_SCRATCH_BASE + pThis->svga.cScratchRegion, ("idxReg=%#x\n", idxReg),
    1145                                  STAM_REL_COUNTER_INC(&pThis->svga.StatRegUnknownRd),
    1146                                  VINF_SUCCESS);
    1147 #endif
    1148     RT_UNTRUSTED_VALIDATED_FENCE();
    1149 
    1150     /* We must adjust the register number if we're in SVGA_ID_0 mode because the PALETTE range moved. */
    1151     if (   idxReg >= SVGA_REG_ID_0_TOP
    1152         && pThis->svga.u32SVGAId == SVGA_ID_0)
    1153     {
    1154         idxReg += SVGA_PALETTE_BASE - SVGA_REG_ID_0_TOP;
    1155         Log(("vmsvgaWritePort: SVGA_ID_0 reg adj %#x -> %#x\n", pThis->svga.u32IndexReg, idxReg));
    1156     }
    1157 
    1158     switch (idxReg)
    1159     {
    1160         case SVGA_REG_ID:
    1161             STAM_REL_COUNTER_INC(&pThis->svga.StatRegIdRd);
    1162             *pu32 = pThis->svga.u32SVGAId;
    1163             break;
    1164 
    1165         case SVGA_REG_ENABLE:
    1166             STAM_REL_COUNTER_INC(&pThis->svga.StatRegEnableRd);
    1167             *pu32 = pThis->svga.fEnabled;
    1168             break;
    1169 
    1170         case SVGA_REG_WIDTH:
    1171         {
    1172             STAM_REL_COUNTER_INC(&pThis->svga.StatRegWidthRd);
    1173             if (    pThis->svga.fEnabled
    1174                 &&  pThis->svga.uWidth != VMSVGA_VAL_UNINITIALIZED)
    1175                 *pu32 = pThis->svga.uWidth;
    1176             else
    1177             {
    1178 #ifndef IN_RING3
    1179                 rc = VINF_IOM_R3_IOPORT_READ;
    1180 #else
    1181                 *pu32 = pThisCC->pDrv->cx;
    1182 #endif
    1183             }
    1184             break;
    1185         }
    1186 
    1187         case SVGA_REG_HEIGHT:
    1188         {
    1189             STAM_REL_COUNTER_INC(&pThis->svga.StatRegHeightRd);
    1190             if (    pThis->svga.fEnabled
    1191                 &&  pThis->svga.uHeight != VMSVGA_VAL_UNINITIALIZED)
    1192                 *pu32 = pThis->svga.uHeight;
    1193             else
    1194             {
    1195 #ifndef IN_RING3
    1196                 rc = VINF_IOM_R3_IOPORT_READ;
    1197 #else
    1198                 *pu32 = pThisCC->pDrv->cy;
    1199 #endif
    1200             }
    1201             break;
    1202         }
    1203 
    1204         case SVGA_REG_MAX_WIDTH:
    1205             STAM_REL_COUNTER_INC(&pThis->svga.StatRegMaxWidthRd);
    1206             *pu32 = pThis->svga.u32MaxWidth;
    1207             break;
    1208 
    1209         case SVGA_REG_MAX_HEIGHT:
    1210             STAM_REL_COUNTER_INC(&pThis->svga.StatRegMaxHeightRd);
    1211             *pu32 = pThis->svga.u32MaxHeight;
    1212             break;
    1213 
    1214         case SVGA_REG_DEPTH:
    1215             /* This returns the color depth of the current mode. */
    1216             STAM_REL_COUNTER_INC(&pThis->svga.StatRegDepthRd);
    1217             switch (pThis->svga.uBpp)
    1218             {
    1219                 case 15:
    1220                 case 16:
    1221                 case 24:
    1222                     *pu32 = pThis->svga.uBpp;
    1223                     break;
    1224 
    1225                 default:
    1226                 case 32:
    1227                     *pu32 = 24; /* The upper 8 bits are either alpha bits or not used. */
    1228                     break;
    1229             }
    1230             break;
    1231 
    1232         case SVGA_REG_HOST_BITS_PER_PIXEL: /* (Deprecated) */
    1233             STAM_REL_COUNTER_INC(&pThis->svga.StatRegHostBitsPerPixelRd);
    1234             *pu32 = pThis->svga.uHostBpp;
    1235             break;
    1236 
    1237         case SVGA_REG_BITS_PER_PIXEL:      /* Current bpp in the guest */
    1238             STAM_REL_COUNTER_INC(&pThis->svga.StatRegBitsPerPixelRd);
    1239             *pu32 = pThis->svga.uBpp;
    1240             break;
    1241 
    1242         case SVGA_REG_PSEUDOCOLOR:
    1243             STAM_REL_COUNTER_INC(&pThis->svga.StatRegPsuedoColorRd);
    1244             *pu32 = pThis->svga.uBpp == 8; /* See section 6 "Pseudocolor" in svga_interface.txt. */
    1245             break;
    1246 
    1247         case SVGA_REG_RED_MASK:
    1248         case SVGA_REG_GREEN_MASK:
    1249         case SVGA_REG_BLUE_MASK:
    1250         {
    1251             uint32_t uBpp;
    1252 
    1253             if (pThis->svga.fEnabled)
    1254                 uBpp = pThis->svga.uBpp;
    1255             else
    1256                 uBpp = pThis->svga.uHostBpp;
    1257 
    1258             uint32_t u32RedMask, u32GreenMask, u32BlueMask;
    1259             switch (uBpp)
    1260             {
    1261                 case 8:
    1262                     u32RedMask   = 0x07;
    1263                     u32GreenMask = 0x38;
    1264                     u32BlueMask  = 0xc0;
    1265                     break;
    1266 
    1267                 case 15:
    1268                     u32RedMask   = 0x0000001f;
    1269                     u32GreenMask = 0x000003e0;
    1270                     u32BlueMask  = 0x00007c00;
    1271                     break;
    1272 
    1273                 case 16:
    1274                     u32RedMask   = 0x0000001f;
    1275                     u32GreenMask = 0x000007e0;
    1276                     u32BlueMask  = 0x0000f800;
    1277                     break;
    1278 
    1279                 case 24:
    1280                 case 32:
    1281                 default:
    1282                     u32RedMask   = 0x00ff0000;
    1283                     u32GreenMask = 0x0000ff00;
    1284                     u32BlueMask  = 0x000000ff;
    1285                     break;
    1286             }
    1287             switch (idxReg)
    1288             {
    1289                 case SVGA_REG_RED_MASK:
    1290                     STAM_REL_COUNTER_INC(&pThis->svga.StatRegRedMaskRd);
    1291                     *pu32 = u32RedMask;
    1292                     break;
    1293 
    1294                 case SVGA_REG_GREEN_MASK:
    1295                     STAM_REL_COUNTER_INC(&pThis->svga.StatRegGreenMaskRd);
    1296                     *pu32 = u32GreenMask;
    1297                     break;
    1298 
    1299                 case SVGA_REG_BLUE_MASK:
    1300                     STAM_REL_COUNTER_INC(&pThis->svga.StatRegBlueMaskRd);
    1301                     *pu32 = u32BlueMask;
    1302                     break;
    1303             }
    1304             break;
    1305         }
    1306 
    1307         case SVGA_REG_BYTES_PER_LINE:
    1308         {
    1309             STAM_REL_COUNTER_INC(&pThis->svga.StatRegBytesPerLineRd);
    1310             if (    pThis->svga.fEnabled
    1311                 &&  pThis->svga.cbScanline)
    1312                 *pu32 = pThis->svga.cbScanline;
    1313             else
    1314             {
    1315 #ifndef IN_RING3
    1316                 rc = VINF_IOM_R3_IOPORT_READ;
    1317 #else
    1318                 *pu32 = pThisCC->pDrv->cbScanline;
    1319 #endif
    1320             }
    1321             break;
    1322         }
    1323 
    1324         case SVGA_REG_VRAM_SIZE:            /* VRAM size */
    1325             STAM_REL_COUNTER_INC(&pThis->svga.StatRegVramSizeRd);
    1326             *pu32 = pThis->vram_size;
    1327             break;
    1328 
    1329         case SVGA_REG_FB_START:             /* Frame buffer physical address. */
    1330             STAM_REL_COUNTER_INC(&pThis->svga.StatRegFbStartRd);
    1331             Assert(pThis->GCPhysVRAM <= 0xffffffff);
    1332             *pu32 = pThis->GCPhysVRAM;
    1333             break;
    1334 
    1335         case SVGA_REG_FB_OFFSET:            /* Offset of the frame buffer in VRAM */
    1336             STAM_REL_COUNTER_INC(&pThis->svga.StatRegFbOffsetRd);
    1337             /* Always zero in our case. */
    1338             *pu32 = 0;
    1339             break;
    1340 
    1341         case SVGA_REG_FB_SIZE:              /* Frame buffer size */
    1342         {
    1343 #ifndef IN_RING3
    1344             rc = VINF_IOM_R3_IOPORT_READ;
    1345 #else
    1346             STAM_REL_COUNTER_INC(&pThis->svga.StatRegFbSizeRd);
    1347 
    1348             /* VMWare testcases want at least 4 MB in case the hardware is disabled. */
    1349             if (    pThis->svga.fEnabled
    1350                 &&  pThis->svga.uHeight != VMSVGA_VAL_UNINITIALIZED)
    1351             {
    1352                 /* Hardware enabled; return real framebuffer size .*/
    1353                 *pu32 = (uint32_t)pThis->svga.uHeight * pThis->svga.cbScanline;
    1354             }
    1355             else
    1356                 *pu32 = RT_MAX(0x100000, (uint32_t)pThisCC->pDrv->cy * pThisCC->pDrv->cbScanline);
    1357 
    1358             *pu32 = RT_MIN(pThis->vram_size, *pu32);
    1359             Log(("h=%d w=%d bpp=%d\n", pThisCC->pDrv->cy, pThisCC->pDrv->cx, pThisCC->pDrv->cBits));
    1360 #endif
    1361             break;
    1362         }
    1363 
    1364         case SVGA_REG_CAPABILITIES:
    1365             STAM_REL_COUNTER_INC(&pThis->svga.StatRegCapabilitesRd);
    1366             *pu32 = pThis->svga.u32DeviceCaps;
    1367             break;
    1368 
    1369         case SVGA_REG_MEM_START:           /* FIFO start */
    1370             STAM_REL_COUNTER_INC(&pThis->svga.StatRegMemStartRd);
    1371             Assert(pThis->svga.GCPhysFIFO <= 0xffffffff);
    1372             *pu32 = pThis->svga.GCPhysFIFO;
    1373             break;
    1374 
    1375         case SVGA_REG_MEM_SIZE:            /* FIFO size */
    1376             STAM_REL_COUNTER_INC(&pThis->svga.StatRegMemSizeRd);
    1377             *pu32 = pThis->svga.cbFIFO;
    1378             break;
    1379 
    1380         case SVGA_REG_CONFIG_DONE:         /* Set when memory area configured */
    1381             STAM_REL_COUNTER_INC(&pThis->svga.StatRegConfigDoneRd);
    1382             *pu32 = pThis->svga.fConfigured;
    1383             break;
    1384 
    1385         case SVGA_REG_SYNC:                /* See "FIFO Synchronization Registers" */
    1386             STAM_REL_COUNTER_INC(&pThis->svga.StatRegSyncRd);
    1387             *pu32 = 0;
    1388             break;
    1389 
    1390         case SVGA_REG_BUSY:                /* See "FIFO Synchronization Registers" */
    1391             STAM_REL_COUNTER_INC(&pThis->svga.StatRegBusyRd);
    1392             if (pThis->svga.fBusy)
    1393             {
    1394 #ifndef IN_RING3
    1395                 /* Go to ring-3 and halt the CPU. */
    1396                 rc = VINF_IOM_R3_IOPORT_READ;
    1397                 RT_NOREF(pDevIns);
    1398                 break;
    1399 #else
    1400 # if defined(VMSVGA_USE_EMT_HALT_CODE)
    1401                 /* The guest is basically doing a HLT via the device here, but with
    1402                    a special wake up condition on FIFO completion. */
    1403                 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
    1404                 STAM_REL_PROFILE_START(&pSVGAState->StatBusyDelayEmts, EmtDelay);
    1405                 PVM         pVM   = PDMDevHlpGetVM(pDevIns);
    1406                 VMCPUID     idCpu = PDMDevHlpGetCurrentCpuId(pDevIns);
    1407                 VMCPUSET_ATOMIC_ADD(&pSVGAState->BusyDelayedEmts, idCpu);
    1408                 ASMAtomicIncU32(&pSVGAState->cBusyDelayedEmts);
    1409                 if (pThis->svga.fBusy)
    1410                 {
    1411                     PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect); /* hack around lock order issue. */
    1412                     rc = VMR3WaitForDeviceReady(pVM, idCpu);
    1413                     PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VERR_IGNORED);
    1414                 }
    1415                 ASMAtomicDecU32(&pSVGAState->cBusyDelayedEmts);
    1416                 VMCPUSET_ATOMIC_DEL(&pSVGAState->BusyDelayedEmts, idCpu);
    1417 # else
    1418 
    1419                 /* Delay the EMT a bit so the FIFO and others can get some work done.
    1420                    This used to be a crude 50 ms sleep. The current code tries to be
    1421                    more efficient, but the consept is still very crude. */
    1422                 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
    1423                 STAM_REL_PROFILE_START(&pSVGAState->StatBusyDelayEmts, EmtDelay);
    1424                 RTThreadYield();
    1425                 if (pThis->svga.fBusy)
    1426                 {
    1427                     uint32_t cRefs = ASMAtomicIncU32(&pSVGAState->cBusyDelayedEmts);
    1428 
    1429                     if (pThis->svga.fBusy && cRefs == 1)
    1430                         RTSemEventMultiReset(pSVGAState->hBusyDelayedEmts);
    1431                     if (pThis->svga.fBusy)
    1432                     {
    1433                         /** @todo If this code is going to stay, we need to call into the halt/wait
    1434                          *        code in VMEmt.cpp here, otherwise all kind of EMT interaction will
    1435                          *        suffer when the guest is polling on a busy FIFO. */
    1436                         uint64_t cNsMaxWait = TMVirtualSyncGetNsToDeadline(PDMDevHlpGetVM(pDevIns));
    1437                         if (cNsMaxWait >= RT_NS_100US)
    1438                             RTSemEventMultiWaitEx(pSVGAState->hBusyDelayedEmts,
    1439                                                   RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_NORESUME,
    1440                                                   RT_MIN(cNsMaxWait, RT_NS_10MS));
    1441                     }
    1442 
    1443                     ASMAtomicDecU32(&pSVGAState->cBusyDelayedEmts);
    1444                 }
    1445                 STAM_REL_PROFILE_STOP(&pSVGAState->StatBusyDelayEmts, EmtDelay);
    1446 # endif
    1447                 *pu32 = pThis->svga.fBusy != 0;
    1448 #endif
    1449             }
    1450             else
    1451                 *pu32 = false;
    1452             break;
    1453 
    1454         case SVGA_REG_GUEST_ID:            /* Set guest OS identifier */
    1455             STAM_REL_COUNTER_INC(&pThis->svga.StatRegGuestIdRd);
    1456             *pu32 = pThis->svga.u32GuestId;
    1457             break;
    1458 
    1459         case SVGA_REG_SCRATCH_SIZE:        /* Number of scratch registers */
    1460             STAM_REL_COUNTER_INC(&pThis->svga.StatRegScratchSizeRd);
    1461             *pu32 = pThis->svga.cScratchRegion;
    1462             break;
    1463 
    1464         case SVGA_REG_MEM_REGS:            /* Number of FIFO registers */
    1465             STAM_REL_COUNTER_INC(&pThis->svga.StatRegMemRegsRd);
    1466             *pu32 = SVGA_FIFO_NUM_REGS;
    1467             break;
    1468 
    1469         case SVGA_REG_PITCHLOCK:           /* Fixed pitch for all modes */
    1470             STAM_REL_COUNTER_INC(&pThis->svga.StatRegPitchLockRd);
    1471             *pu32 = pThis->svga.u32PitchLock;
    1472             break;
    1473 
    1474         case SVGA_REG_IRQMASK:             /* Interrupt mask */
    1475             STAM_REL_COUNTER_INC(&pThis->svga.StatRegIrqMaskRd);
    1476             *pu32 = pThis->svga.u32IrqMask;
    1477             break;
    1478 
    1479         /* See "Guest memory regions" below. */
    1480         case SVGA_REG_GMR_ID:
    1481             STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrIdRd);
    1482             *pu32 = pThis->svga.u32CurrentGMRId;
    1483             break;
    1484 
    1485         case SVGA_REG_GMR_DESCRIPTOR:
    1486             STAM_REL_COUNTER_INC(&pThis->svga.StatRegWriteOnlyRd);
    1487             /* Write only */
    1488             *pu32 = 0;
    1489             break;
    1490 
    1491         case SVGA_REG_GMR_MAX_IDS:
    1492             STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrMaxIdsRd);
    1493             *pu32 = pThis->svga.cGMR;
    1494             break;
    1495 
    1496         case SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH:
    1497             STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrMaxDescriptorLengthRd);
    1498             *pu32 = VMSVGA_MAX_GMR_PAGES;
    1499             break;
    1500 
    1501         case SVGA_REG_TRACES:            /* Enable trace-based updates even when FIFO is on */
    1502             STAM_REL_COUNTER_INC(&pThis->svga.StatRegTracesRd);
    1503             *pu32 = pThis->svga.fTraces;
    1504             break;
    1505 
    1506         case SVGA_REG_GMRS_MAX_PAGES:    /* Maximum number of 4KB pages for all GMRs */
    1507             STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrsMaxPagesRd);
    1508             *pu32 = VMSVGA_MAX_GMR_PAGES;
    1509             break;
    1510 
    1511         case SVGA_REG_MEMORY_SIZE:       /* Total dedicated device memory excluding FIFO */
    1512             STAM_REL_COUNTER_INC(&pThis->svga.StatRegMemorySizeRd);
    1513             *pu32 = VMSVGA_SURFACE_SIZE;
    1514             break;
    1515 
    1516         case SVGA_REG_TOP:               /* Must be 1 more than the last register */
    1517             STAM_REL_COUNTER_INC(&pThis->svga.StatRegTopRd);
    1518             break;
    1519 
    1520         /* Mouse cursor support. */
    1521         case SVGA_REG_CURSOR_ID:
    1522             STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorIdRd);
    1523             *pu32 = pThis->svga.uCursorID;
    1524             break;
    1525 
    1526         case SVGA_REG_CURSOR_X:
    1527             STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorXRd);
    1528             *pu32 = pThis->svga.uCursorX;
    1529             break;
    1530 
    1531         case SVGA_REG_CURSOR_Y:
    1532             STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorYRd);
    1533             *pu32 = pThis->svga.uCursorY;
    1534             break;
    1535 
    1536         case SVGA_REG_CURSOR_ON:
    1537             STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorOnRd);
    1538             *pu32 = pThis->svga.uCursorOn;
    1539             break;
    1540 
    1541         /* Legacy multi-monitor support */
    1542         case SVGA_REG_NUM_GUEST_DISPLAYS:/* Number of guest displays in X/Y direction */
    1543             STAM_REL_COUNTER_INC(&pThis->svga.StatRegNumGuestDisplaysRd);
    1544             *pu32 = 1;
    1545             break;
    1546 
    1547         case SVGA_REG_DISPLAY_ID:        /* Display ID for the following display attributes */
    1548             STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayIdRd);
    1549             *pu32 = 0;
    1550             break;
    1551 
    1552         case SVGA_REG_DISPLAY_IS_PRIMARY:/* Whether this is a primary display */
    1553             STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayIsPrimaryRd);
    1554             *pu32 = 0;
    1555             break;
    1556 
    1557         case SVGA_REG_DISPLAY_POSITION_X:/* The display position x */
    1558             STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayPositionXRd);
    1559             *pu32 = 0;
    1560             break;
    1561 
    1562         case SVGA_REG_DISPLAY_POSITION_Y:/* The display position y */
    1563             STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayPositionYRd);
    1564             *pu32 = 0;
    1565             break;
    1566 
    1567         case SVGA_REG_DISPLAY_WIDTH:     /* The display's width */
    1568             STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayWidthRd);
    1569             *pu32 = pThis->svga.uWidth;
    1570             break;
    1571 
    1572         case SVGA_REG_DISPLAY_HEIGHT:    /* The display's height */
    1573             STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayHeightRd);
    1574             *pu32 = pThis->svga.uHeight;
    1575             break;
    1576 
    1577         case SVGA_REG_NUM_DISPLAYS:        /* (Deprecated) */
    1578             STAM_REL_COUNTER_INC(&pThis->svga.StatRegNumDisplaysRd);
    1579             /* We must return something sensible here otherwise the Linux driver
    1580                will take a legacy code path without 3d support.  This number also
    1581                limits how many screens Linux guests will allow. */
    1582             *pu32 = pThis->cMonitors;
    1583             break;
    1584 
    1585         /*
    1586          * SVGA_CAP_GBOBJECTS+ registers.
    1587          */
    1588         case SVGA_REG_COMMAND_LOW:
    1589             /* Lower 32 bits of command buffer physical address. */
    1590             STAM_REL_COUNTER_INC(&pThis->svga.StatRegCommandLowRd);
    1591             *pu32 = pThis->svga.u32RegCommandLow;
    1592             break;
    1593 
    1594         case SVGA_REG_COMMAND_HIGH:
    1595             /* Upper 32 bits of command buffer PA. */
    1596             STAM_REL_COUNTER_INC(&pThis->svga.StatRegCommandHighRd);
    1597             *pu32 = pThis->svga.u32RegCommandHigh;
    1598             break;
    1599 
    1600         case SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM:
    1601             /* Max primary (screen) memory. */
    1602             STAM_REL_COUNTER_INC(&pThis->svga.StatRegMaxPrimBBMemRd);
    1603             *pu32 = pThis->vram_size; /** @todo Maybe half VRAM? */
    1604             break;
    1605 
    1606         case SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB:
    1607             /* Suggested limit on mob mem (i.e. size of the guest mapped VRAM in KB) */
    1608             STAM_REL_COUNTER_INC(&pThis->svga.StatRegGBMemSizeRd);
    1609             *pu32 = pThis->vram_size / 1024;
    1610             break;
    1611 
    1612         case SVGA_REG_DEV_CAP:
    1613             /* Write dev cap index, read value */
    1614             STAM_REL_COUNTER_INC(&pThis->svga.StatRegDevCapRd);
    1615             if (pThis->svga.u32DevCapIndex < RT_ELEMENTS(pThis->svga.au32DevCaps))
    1616             {
    1617                 RT_UNTRUSTED_VALIDATED_FENCE();
    1618                 *pu32 = pThis->svga.au32DevCaps[pThis->svga.u32DevCapIndex];
    1619             }
    1620             else
    1621                 *pu32 = 0;
    1622             break;
    1623 
    1624         case SVGA_REG_CMD_PREPEND_LOW:
    1625             STAM_REL_COUNTER_INC(&pThis->svga.StatRegCmdPrependLowRd);
    1626             *pu32 = 0; /* Not supported. */
    1627             break;
    1628 
    1629         case SVGA_REG_iCMD_PREPEND_HIGH:
    1630             STAM_REL_COUNTER_INC(&pThis->svga.StatRegCmdPrependHighRd);
    1631             *pu32 = 0; /* Not supported. */
    1632             break;
    1633 
    1634         case SVGA_REG_SCREENTARGET_MAX_WIDTH:
    1635             STAM_REL_COUNTER_INC(&pThis->svga.StatRegScrnTgtMaxWidthRd);
    1636             *pu32 = pThis->svga.u32MaxWidth;
    1637             break;
    1638 
    1639         case SVGA_REG_SCREENTARGET_MAX_HEIGHT:
    1640             STAM_REL_COUNTER_INC(&pThis->svga.StatRegScrnTgtMaxHeightRd);
    1641             *pu32 = pThis->svga.u32MaxHeight;
    1642             break;
    1643 
    1644         case SVGA_REG_MOB_MAX_SIZE:
    1645             /* Essentially the max texture size */
    1646             STAM_REL_COUNTER_INC(&pThis->svga.StatRegMobMaxSizeRd);
    1647             *pu32 = _128M; /** @todo Some actual value. Probably the mapped VRAM size. */
    1648             break;
    1649 
    1650         default:
    1651         {
    1652             uint32_t offReg;
    1653             if ((offReg = idxReg - SVGA_SCRATCH_BASE) < pThis->svga.cScratchRegion)
    1654             {
    1655                 STAM_REL_COUNTER_INC(&pThis->svga.StatRegScratchRd);
    1656                 RT_UNTRUSTED_VALIDATED_FENCE();
    1657                 *pu32 = pThis->svga.au32ScratchRegion[offReg];
    1658             }
    1659             else if ((offReg = idxReg - SVGA_PALETTE_BASE) < (uint32_t)SVGA_NUM_PALETTE_REGS)
    1660             {
    1661                 /* Note! Using last_palette rather than palette here to preserve the VGA one. */
    1662                 STAM_REL_COUNTER_INC(&pThis->svga.StatRegPaletteRd);
    1663                 RT_UNTRUSTED_VALIDATED_FENCE();
    1664                 uint32_t u32 = pThis->last_palette[offReg / 3];
    1665                 switch (offReg % 3)
    1666                 {
    1667                     case 0: *pu32 = (u32 >> 16) & 0xff; break; /* red */
    1668                     case 1: *pu32 = (u32 >>  8) & 0xff; break; /* green */
    1669                     case 2: *pu32 =  u32        & 0xff; break; /* blue */
    1670                 }
    1671             }
    1672             else
    1673             {
    1674 #if !defined(IN_RING3) && defined(VBOX_STRICT)
    1675                 rc = VINF_IOM_R3_IOPORT_READ;
    1676 #else
    1677                 STAM_REL_COUNTER_INC(&pThis->svga.StatRegUnknownRd);
    1678 
    1679                 /* Do not assert. The guest might be reading all registers. */
    1680                 LogFunc(("Unknown reg=%#x\n", idxReg));
    1681 #endif
    1682             }
    1683             break;
    1684         }
    1685     }
    1686     Log(("vmsvgaReadPort index=%s (%d) val=%#x rc=%x\n", vmsvgaIndexToString(pThis, idxReg), idxReg, *pu32, rc));
    1687     return rc;
    1688 }
    1689 
    1690 #ifdef IN_RING3
    1691 /**
    1692  * Apply the current resolution settings to change the video mode.
    1693  *
    1694  * @returns VBox status code.
    1695  * @param   pThis       The shared VGA state.
    1696  * @param   pThisCC     The ring-3 VGA state.
    1697  */
    1698 static int vmsvgaR3ChangeMode(PVGASTATE pThis, PVGASTATECC pThisCC)
    1699 {
    1700     /* Always do changemode on FIFO thread. */
    1701     Assert(RTThreadSelf() == pThisCC->svga.pFIFOIOThread->Thread);
    1702 
    1703     PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
    1704 
    1705     pThisCC->pDrv->pfnLFBModeChange(pThisCC->pDrv, true);
    1706 
    1707     if (pThis->svga.fGFBRegisters)
    1708     {
    1709         /* "For backwards compatibility, when the GFB mode registers (WIDTH,
    1710          * HEIGHT, PITCHLOCK, BITS_PER_PIXEL) are modified, the SVGA device
    1711          * deletes all screens other than screen #0, and redefines screen
    1712          * #0 according to the specified mode. Drivers that use
    1713          * SVGA_CMD_DEFINE_SCREEN should destroy or redefine screen #0."
    1714          */
    1715 
    1716         VMSVGASCREENOBJECT *pScreen = &pSVGAState->aScreens[0];
    1717         pScreen->fDefined  = true;
    1718         pScreen->fModified = true;
    1719         pScreen->fuScreen  = SVGA_SCREEN_MUST_BE_SET | SVGA_SCREEN_IS_PRIMARY;
    1720         pScreen->idScreen  = 0;
    1721         pScreen->xOrigin   = 0;
    1722         pScreen->yOrigin   = 0;
    1723         pScreen->offVRAM   = 0;
    1724         pScreen->cbPitch   = pThis->svga.cbScanline;
    1725         pScreen->cWidth    = pThis->svga.uWidth;
    1726         pScreen->cHeight   = pThis->svga.uHeight;
    1727         pScreen->cBpp      = pThis->svga.uBpp;
    1728 
    1729         for (unsigned iScreen = 1; iScreen < RT_ELEMENTS(pSVGAState->aScreens); ++iScreen)
    1730         {
    1731             /* Delete screen. */
    1732             pScreen = &pSVGAState->aScreens[iScreen];
    1733             if (pScreen->fDefined)
    1734             {
    1735                 pScreen->fModified = true;
    1736                 pScreen->fDefined = false;
    1737             }
    1738         }
    1739     }
    1740     else
    1741     {
    1742         /* "If Screen Objects are supported, they can be used to fully
    1743          * replace the functionality provided by the framebuffer registers
    1744          * (SVGA_REG_WIDTH, HEIGHT, etc.) and by SVGA_CAP_DISPLAY_TOPOLOGY."
    1745          */
    1746         pThis->svga.uWidth  = VMSVGA_VAL_UNINITIALIZED;
    1747         pThis->svga.uHeight = VMSVGA_VAL_UNINITIALIZED;
    1748         pThis->svga.uBpp    = pThis->svga.uHostBpp;
    1749     }
    1750 
    1751     vmsvgaR3VBVAResize(pThis, pThisCC);
    1752 
    1753     /* Last stuff. For the VGA device screenshot. */
    1754     pThis->last_bpp        = pSVGAState->aScreens[0].cBpp;
    1755     pThis->last_scr_width  = pSVGAState->aScreens[0].cWidth;
    1756     pThis->last_scr_height = pSVGAState->aScreens[0].cHeight;
    1757     pThis->last_width      = pSVGAState->aScreens[0].cWidth;
    1758     pThis->last_height     = pSVGAState->aScreens[0].cHeight;
    1759 
    1760     /* vmsvgaPortSetViewPort not called after state load; set sensible defaults. */
    1761     if (    pThis->svga.viewport.cx == 0
    1762         &&  pThis->svga.viewport.cy == 0)
    1763     {
    1764         pThis->svga.viewport.cx      = pSVGAState->aScreens[0].cWidth;
    1765         pThis->svga.viewport.xRight  = pSVGAState->aScreens[0].cWidth;
    1766         pThis->svga.viewport.cy      = pSVGAState->aScreens[0].cHeight;
    1767         pThis->svga.viewport.yHighWC = pSVGAState->aScreens[0].cHeight;
    1768         pThis->svga.viewport.yLowWC  = 0;
    1769     }
    1770 
    1771     return VINF_SUCCESS;
    1772 }
    1773 
    1774 int vmsvgaR3UpdateScreen(PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen, int x, int y, int w, int h)
    1775 {
    1776     VBVACMDHDR cmd;
    1777     cmd.x = (int16_t)(pScreen->xOrigin + x);
    1778     cmd.y = (int16_t)(pScreen->yOrigin + y);
    1779     cmd.w = (uint16_t)w;
    1780     cmd.h = (uint16_t)h;
    1781 
    1782     pThisCC->pDrv->pfnVBVAUpdateBegin(pThisCC->pDrv, pScreen->idScreen);
    1783     pThisCC->pDrv->pfnVBVAUpdateProcess(pThisCC->pDrv, pScreen->idScreen, &cmd, sizeof(cmd));
    1784     pThisCC->pDrv->pfnVBVAUpdateEnd(pThisCC->pDrv, pScreen->idScreen,
    1785                                     pScreen->xOrigin + x, pScreen->yOrigin + y, w, h);
    1786 
    1787     return VINF_SUCCESS;
    1788 }
    1789 
    1790 #endif /* IN_RING3 */
    1791 #if defined(IN_RING0) || defined(IN_RING3)
    1792 
    1793 /**
    1794  * Safely updates the SVGA_FIFO_BUSY register (in shared memory).
    1795  *
    1796  * @param   pThis       The shared VGA/VMSVGA instance data.
    1797  * @param   pThisCC     The VGA/VMSVGA state for the current context.
    1798  * @param   fState      The busy state.
    1799  */
    1800 DECLINLINE(void) vmsvgaHCSafeFifoBusyRegUpdate(PVGASTATE pThis, PVGASTATECC pThisCC, bool fState)
    1801 {
    1802     ASMAtomicWriteU32(&pThisCC->svga.pau32FIFO[SVGA_FIFO_BUSY], fState);
    1803 
    1804     if (RT_UNLIKELY(fState != (pThis->svga.fBusy != 0)))
    1805     {
    1806         /* Race / unfortunately scheduling. Highly unlikly. */
    1807         uint32_t cLoops = 64;
    1808         do
    1809         {
    1810             ASMNopPause();
    1811             fState = (pThis->svga.fBusy != 0);
    1812             ASMAtomicWriteU32(&pThisCC->svga.pau32FIFO[SVGA_FIFO_BUSY], fState != 0);
    1813         } while (cLoops-- > 0 && fState != (pThis->svga.fBusy != 0));
    1814     }
    1815 }
    1816 
    1817 
    1818 /**
    1819  * Update the scanline pitch in response to the guest changing mode
    1820  * width/bpp.
    1821  *
    1822  * @param   pThis       The shared VGA/VMSVGA state.
    1823  * @param   pThisCC     The VGA/VMSVGA state for the current context.
    1824  */
    1825 DECLINLINE(void) vmsvgaHCUpdatePitch(PVGASTATE pThis, PVGASTATECC pThisCC)
    1826 {
    1827     uint32_t RT_UNTRUSTED_VOLATILE_GUEST *pFIFO = pThisCC->svga.pau32FIFO;
    1828     uint32_t uFifoPitchLock = pFIFO[SVGA_FIFO_PITCHLOCK];
    1829     uint32_t uRegPitchLock  = pThis->svga.u32PitchLock;
    1830     uint32_t uFifoMin       = pFIFO[SVGA_FIFO_MIN];
    1831 
    1832     /* The SVGA_FIFO_PITCHLOCK register is only valid if SVGA_FIFO_MIN points past
    1833      * it. If SVGA_FIFO_MIN is small, there may well be data at the SVGA_FIFO_PITCHLOCK
    1834      * location but it has a different meaning.
    1835      */
    1836     if ((uFifoMin / sizeof(uint32_t)) <= SVGA_FIFO_PITCHLOCK)
    1837         uFifoPitchLock = 0;
    1838 
    1839     /* Sanitize values. */
    1840     if ((uFifoPitchLock < 200) || (uFifoPitchLock > 32768))
    1841         uFifoPitchLock = 0;
    1842     if ((uRegPitchLock  < 200) || (uRegPitchLock  > 32768))
    1843         uRegPitchLock = 0;
    1844 
    1845     /* Prefer the register value to the FIFO value.*/
    1846     if (uRegPitchLock)
    1847         pThis->svga.cbScanline = uRegPitchLock;
    1848     else if (uFifoPitchLock)
    1849         pThis->svga.cbScanline = uFifoPitchLock;
    1850     else
    1851         pThis->svga.cbScanline = pThis->svga.uWidth * (RT_ALIGN(pThis->svga.uBpp, 8) / 8);
    1852 
    1853     if ((uFifoMin / sizeof(uint32_t)) <= SVGA_FIFO_PITCHLOCK)
    1854         pThis->svga.u32PitchLock = pThis->svga.cbScanline;
    1855 }
    1856 
    1857 #endif /* IN_RING0 || IN_RING3 */
    1858 
    1859 #ifdef IN_RING3
    1860 
    1861 /**
    1862  * Sends cursor position and visibility information from legacy
    1863  * SVGA registers to the front-end.
    1864  */
    1865 static void vmsvgaR3RegUpdateCursor(PVGASTATECC pThisCC, PVGASTATE pThis, uint32_t uCursorOn)
    1866 {
    1867     /*
    1868      * Writing the X/Y/ID registers does not trigger changes; only writing the
    1869      * SVGA_REG_CURSOR_ON register does. That minimizes the overhead.
    1870      * We boldly assume that guests aren't stupid and aren't writing the CURSOR_ON
    1871      * register if they don't have to.
    1872      */
    1873     uint32_t x, y, idScreen;
    1874     uint32_t fFlags = VBVA_CURSOR_VALID_DATA;
    1875 
    1876     x = pThis->svga.uCursorX;
    1877     y = pThis->svga.uCursorY;
    1878     idScreen = SVGA_ID_INVALID; /* The old register interface is single screen only. */
    1879 
    1880     /* The original values for SVGA_REG_CURSOR_ON were off (0) and on (1); later, the values
    1881      * were extended as follows:
    1882      *
    1883      *   SVGA_CURSOR_ON_HIDE               0
    1884      *   SVGA_CURSOR_ON_SHOW               1
    1885      *   SVGA_CURSOR_ON_REMOVE_FROM_FB     2 - cursor on but not in the framebuffer
    1886      *   SVGA_CURSOR_ON_RESTORE_TO_FB      3 - cursor on, possibly in the framebuffer
    1887      *
    1888      * Since we never draw the cursor into the guest's framebuffer, we do not need to
    1889      * distinguish between the non-zero values but still remember them.
    1890      */
    1891     if (RT_BOOL(pThis->svga.uCursorOn) != RT_BOOL(uCursorOn))
    1892     {
    1893         LogRel2(("vmsvgaR3RegUpdateCursor: uCursorOn %d prev CursorOn %d (%d,%d)\n", uCursorOn, pThis->svga.uCursorOn, x, y));
    1894         pThisCC->pDrv->pfnVBVAMousePointerShape(pThisCC->pDrv, RT_BOOL(uCursorOn), false, 0, 0, 0, 0, NULL);
    1895     }
    1896     pThis->svga.uCursorOn = uCursorOn;
    1897     pThisCC->pDrv->pfnVBVAReportCursorPosition(pThisCC->pDrv, fFlags, idScreen, x, y);
    1898300}
    1899301
     
    1953355    }
    1954356}
    1955 
    1956 #endif /* IN_RING3 */
    1957 
    1958 
    1959 /**
    1960  * Write port register
    1961  *
    1962  * @returns Strict VBox status code.
    1963  * @param   pDevIns     The device instance.
    1964  * @param   pThis       The shared VGA/VMSVGA state.
    1965  * @param   pThisCC     The VGA/VMSVGA state for the current context.
    1966  * @param   u32         Value to write
    1967  */
    1968 static VBOXSTRICTRC vmsvgaWritePort(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, uint32_t u32)
    1969 {
    1970 #ifdef IN_RING3
    1971     PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
    1972 #endif
    1973     VBOXSTRICTRC rc = VINF_SUCCESS;
    1974     RT_NOREF(pThisCC);
    1975 
    1976     /* Rough index register validation. */
    1977     uint32_t idxReg = pThis->svga.u32IndexReg;
    1978 #if !defined(IN_RING3) && defined(VBOX_STRICT)
    1979     ASSERT_GUEST_MSG_RETURN(idxReg < SVGA_SCRATCH_BASE + pThis->svga.cScratchRegion, ("idxReg=%#x\n", idxReg),
    1980                             VINF_IOM_R3_IOPORT_WRITE);
    1981 #else
    1982     ASSERT_GUEST_MSG_STMT_RETURN(idxReg < SVGA_SCRATCH_BASE + pThis->svga.cScratchRegion, ("idxReg=%#x\n", idxReg),
    1983                                  STAM_REL_COUNTER_INC(&pThis->svga.StatRegUnknownWr),
    1984                                  VINF_SUCCESS);
    1985 #endif
    1986     RT_UNTRUSTED_VALIDATED_FENCE();
    1987 
    1988     /* We must adjust the register number if we're in SVGA_ID_0 mode because the PALETTE range moved. */
    1989     if (   idxReg >= SVGA_REG_ID_0_TOP
    1990         && pThis->svga.u32SVGAId == SVGA_ID_0)
    1991     {
    1992         idxReg += SVGA_PALETTE_BASE - SVGA_REG_ID_0_TOP;
    1993         Log(("vmsvgaWritePort: SVGA_ID_0 reg adj %#x -> %#x\n", pThis->svga.u32IndexReg, idxReg));
    1994     }
    1995     Log(("vmsvgaWritePort index=%s (%d) val=%#x\n", vmsvgaIndexToString(pThis, idxReg), idxReg, u32));
    1996     /* Check if the guest uses legacy registers. See vmsvgaR3ChangeMode */
    1997     switch (idxReg)
    1998     {
    1999         case SVGA_REG_WIDTH:
    2000         case SVGA_REG_HEIGHT:
    2001         case SVGA_REG_PITCHLOCK:
    2002         case SVGA_REG_BITS_PER_PIXEL:
    2003             pThis->svga.fGFBRegisters = true;
    2004             break;
    2005         default:
    2006             break;
    2007     }
    2008 
    2009     switch (idxReg)
    2010     {
    2011         case SVGA_REG_ID:
    2012             STAM_REL_COUNTER_INC(&pThis->svga.StatRegIdWr);
    2013             if (   u32 == SVGA_ID_0
    2014                 || u32 == SVGA_ID_1
    2015                 || u32 == SVGA_ID_2)
    2016                 pThis->svga.u32SVGAId = u32;
    2017             else
    2018                 PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "Trying to set SVGA_REG_ID to %#x (%d)\n", u32, u32);
    2019             break;
    2020 
    2021         case SVGA_REG_ENABLE:
    2022             STAM_REL_COUNTER_INC(&pThis->svga.StatRegEnableWr);
    2023 #ifdef IN_RING3
    2024             if (    (u32 & SVGA_REG_ENABLE_ENABLE)
    2025                 &&  pThis->svga.fEnabled == false)
    2026             {
    2027                 /* Make a backup copy of the first 512kb in order to save font data etc. */
    2028                 /** @todo should probably swap here, rather than copy + zero */
    2029                 memcpy(pThisCC->svga.pbVgaFrameBufferR3, pThisCC->pbVRam, VMSVGA_VGA_FB_BACKUP_SIZE);
    2030                 memset(pThisCC->pbVRam, 0, VMSVGA_VGA_FB_BACKUP_SIZE);
    2031             }
    2032 
    2033             pThis->svga.fEnabled = u32;
    2034             if (pThis->svga.fEnabled)
    2035             {
    2036                 if (    pThis->svga.uWidth  == VMSVGA_VAL_UNINITIALIZED
    2037                     &&  pThis->svga.uHeight == VMSVGA_VAL_UNINITIALIZED)
    2038                 {
    2039                     /* Keep the current mode. */
    2040                     pThis->svga.uWidth  = pThisCC->pDrv->cx;
    2041                     pThis->svga.uHeight = pThisCC->pDrv->cy;
    2042                     pThis->svga.uBpp    = (pThisCC->pDrv->cBits + 7) & ~7;
    2043                 }
    2044 
    2045                 if (    pThis->svga.uWidth  != VMSVGA_VAL_UNINITIALIZED
    2046                     &&  pThis->svga.uHeight != VMSVGA_VAL_UNINITIALIZED)
    2047                     ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE);
    2048 # ifdef LOG_ENABLED
    2049                 uint32_t *pFIFO = pThisCC->svga.pau32FIFO;
    2050                 Log(("configured=%d busy=%d\n", pThis->svga.fConfigured, pFIFO[SVGA_FIFO_BUSY]));
    2051                 Log(("next %x stop %x\n", pFIFO[SVGA_FIFO_NEXT_CMD], pFIFO[SVGA_FIFO_STOP]));
    2052 # endif
    2053 
    2054                 /* Disable or enable dirty page tracking according to the current fTraces value. */
    2055                 vmsvgaR3SetTraces(pDevIns, pThis, !!pThis->svga.fTraces);
    2056 
    2057                 /* bird: Whatever this is was added to make screenshot work, ask sunlover should explain... */
    2058                 for (uint32_t idScreen = 0; idScreen < pThis->cMonitors; ++idScreen)
    2059                     pThisCC->pDrv->pfnVBVAEnable(pThisCC->pDrv, idScreen, NULL /*pHostFlags*/);
    2060 
    2061                 /* Make the cursor visible again as needed. */
    2062                 if (pSVGAState->Cursor.fActive)
    2063                     pThisCC->pDrv->pfnVBVAMousePointerShape(pThisCC->pDrv, true /*fVisible*/, false, 0, 0, 0, 0, NULL);
    2064             }
    2065             else
    2066             {
    2067                 /* Make sure the cursor is off. */
    2068                 if (pSVGAState->Cursor.fActive)
    2069                     pThisCC->pDrv->pfnVBVAMousePointerShape(pThisCC->pDrv, false /*fVisible*/, false, 0, 0, 0, 0, NULL);
    2070 
    2071                 /* Restore the text mode backup. */
    2072                 memcpy(pThisCC->pbVRam, pThisCC->svga.pbVgaFrameBufferR3, VMSVGA_VGA_FB_BACKUP_SIZE);
    2073 
    2074                 pThisCC->pDrv->pfnLFBModeChange(pThisCC->pDrv, false);
    2075 
    2076                 /* Enable dirty page tracking again when going into legacy mode. */
    2077                 vmsvgaR3SetTraces(pDevIns, pThis, true);
    2078 
    2079                 /* bird: Whatever this is was added to make screenshot work, ask sunlover should explain... */
    2080                 for (uint32_t idScreen = 0; idScreen < pThis->cMonitors; ++idScreen)
    2081                     pThisCC->pDrv->pfnVBVADisable(pThisCC->pDrv, idScreen);
    2082 
    2083                 /* Clear the pitch lock. */
    2084                 pThis->svga.u32PitchLock = 0;
    2085             }
    2086 #else  /* !IN_RING3 */
    2087             rc = VINF_IOM_R3_IOPORT_WRITE;
    2088 #endif /* !IN_RING3 */
    2089             break;
    2090 
    2091         case SVGA_REG_WIDTH:
    2092             STAM_REL_COUNTER_INC(&pThis->svga.StatRegWidthWr);
    2093             if (pThis->svga.uWidth != u32)
    2094             {
    2095 #if defined(IN_RING3) || defined(IN_RING0)
    2096                 pThis->svga.uWidth = u32;
    2097                 vmsvgaHCUpdatePitch(pThis, pThisCC);
    2098                 if (pThis->svga.fEnabled)
    2099                     ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE);
    2100 #else
    2101                 rc = VINF_IOM_R3_IOPORT_WRITE;
    2102 #endif
    2103             }
    2104             /* else: nop */
    2105             break;
    2106 
    2107         case SVGA_REG_HEIGHT:
    2108             STAM_REL_COUNTER_INC(&pThis->svga.StatRegHeightWr);
    2109             if (pThis->svga.uHeight != u32)
    2110             {
    2111                 pThis->svga.uHeight = u32;
    2112                 if (pThis->svga.fEnabled)
    2113                     ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE);
    2114             }
    2115             /* else: nop */
    2116             break;
    2117 
    2118         case SVGA_REG_DEPTH:
    2119             STAM_REL_COUNTER_INC(&pThis->svga.StatRegDepthWr);
    2120             /** @todo read-only?? */
    2121             break;
    2122 
    2123         case SVGA_REG_BITS_PER_PIXEL:      /* Current bpp in the guest */
    2124             STAM_REL_COUNTER_INC(&pThis->svga.StatRegBitsPerPixelWr);
    2125             if (pThis->svga.uBpp != u32)
    2126             {
    2127 #if defined(IN_RING3) || defined(IN_RING0)
    2128                 pThis->svga.uBpp = u32;
    2129                 vmsvgaHCUpdatePitch(pThis, pThisCC);
    2130                 if (pThis->svga.fEnabled)
    2131                     ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE);
    2132 #else
    2133                 rc = VINF_IOM_R3_IOPORT_WRITE;
    2134 #endif
    2135             }
    2136             /* else: nop */
    2137             break;
    2138 
    2139         case SVGA_REG_PSEUDOCOLOR:
    2140             STAM_REL_COUNTER_INC(&pThis->svga.StatRegPseudoColorWr);
    2141             break;
    2142 
    2143         case SVGA_REG_CONFIG_DONE:         /* Set when memory area configured */
    2144 #ifdef IN_RING3
    2145             STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegConfigDoneWr);
    2146             pThis->svga.fConfigured = u32;
    2147             /* Disabling the FIFO enables tracing (dirty page detection) by default. */
    2148             if (!pThis->svga.fConfigured)
    2149                 pThis->svga.fTraces = true;
    2150             vmsvgaR3SetTraces(pDevIns, pThis, !!pThis->svga.fTraces);
    2151 #else
    2152             rc = VINF_IOM_R3_IOPORT_WRITE;
    2153 #endif
    2154             break;
    2155 
    2156         case SVGA_REG_SYNC:                /* See "FIFO Synchronization Registers" */
    2157             STAM_REL_COUNTER_INC(&pThis->svga.StatRegSyncWr);
    2158             if (    pThis->svga.fEnabled
    2159                 &&  pThis->svga.fConfigured)
    2160             {
    2161 #if defined(IN_RING3) || defined(IN_RING0)
    2162                 Log(("SVGA_REG_SYNC: SVGA_FIFO_BUSY=%d\n", pThisCC->svga.pau32FIFO[SVGA_FIFO_BUSY]));
    2163                 /*
    2164                  * The VMSVGA_BUSY_F_EMT_FORCE flag makes sure we will check if the FIFO is empty
    2165                  * at least once; VMSVGA_BUSY_F_FIFO alone does not ensure that.
    2166                  */
    2167                 ASMAtomicWriteU32(&pThis->svga.fBusy, VMSVGA_BUSY_F_EMT_FORCE | VMSVGA_BUSY_F_FIFO);
    2168                 if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_BUSY, pThisCC->svga.pau32FIFO[SVGA_FIFO_MIN]))
    2169                     vmsvgaHCSafeFifoBusyRegUpdate(pThis, pThisCC, true);
    2170 
    2171                 /* Kick the FIFO thread to start processing commands again. */
    2172                 PDMDevHlpSUPSemEventSignal(pDevIns, pThis->svga.hFIFORequestSem);
    2173 #else
    2174                 rc = VINF_IOM_R3_IOPORT_WRITE;
    2175 #endif
    2176             }
    2177             /* else nothing to do. */
    2178             else
    2179                 Log(("Sync ignored enabled=%d configured=%d\n", pThis->svga.fEnabled, pThis->svga.fConfigured));
    2180 
    2181             break;
    2182 
    2183         case SVGA_REG_BUSY:                /* See "FIFO Synchronization Registers" (read-only) */
    2184             STAM_REL_COUNTER_INC(&pThis->svga.StatRegBusyWr);
    2185             break;
    2186 
    2187         case SVGA_REG_GUEST_ID:            /* Set guest OS identifier */
    2188             STAM_REL_COUNTER_INC(&pThis->svga.StatRegGuestIdWr);
    2189             pThis->svga.u32GuestId = u32;
    2190             break;
    2191 
    2192         case SVGA_REG_PITCHLOCK:           /* Fixed pitch for all modes */
    2193             STAM_REL_COUNTER_INC(&pThis->svga.StatRegPitchLockWr);
    2194             pThis->svga.u32PitchLock = u32;
    2195             /* Should this also update the FIFO pitch lock? Unclear. */
    2196             break;
    2197 
    2198         case SVGA_REG_IRQMASK:             /* Interrupt mask */
    2199             STAM_REL_COUNTER_INC(&pThis->svga.StatRegIrqMaskWr);
    2200             pThis->svga.u32IrqMask = u32;
    2201 
    2202             /* Irq pending after the above change? */
    2203             if (pThis->svga.u32IrqStatus & u32)
    2204             {
    2205                 Log(("SVGA_REG_IRQMASK: Trigger interrupt with status %x\n", pThis->svga.u32IrqStatus));
    2206                 PDMDevHlpPCISetIrqNoWait(pDevIns, 0, 1);
    2207             }
    2208             else
    2209                 PDMDevHlpPCISetIrqNoWait(pDevIns, 0, 0);
    2210             break;
    2211 
    2212         /* Mouse cursor support */
    2213         case SVGA_REG_CURSOR_ID:
    2214             STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorIdWr);
    2215             pThis->svga.uCursorID = u32;
    2216             break;
    2217 
    2218         case SVGA_REG_CURSOR_X:
    2219             STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorXWr);
    2220             pThis->svga.uCursorX = u32;
    2221             break;
    2222 
    2223         case SVGA_REG_CURSOR_Y:
    2224             STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorYWr);
    2225             pThis->svga.uCursorY = u32;
    2226             break;
    2227 
    2228         case SVGA_REG_CURSOR_ON:
    2229 #ifdef IN_RING3
    2230             /* The cursor is only updated when SVGA_REG_CURSOR_ON is written. */
    2231             STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorOnWr);
    2232             vmsvgaR3RegUpdateCursor(pThisCC, pThis, u32);
    2233 #else
    2234             rc = VINF_IOM_R3_IOPORT_WRITE;
    2235 #endif
    2236             break;
    2237 
    2238         /* Legacy multi-monitor support */
    2239         case SVGA_REG_NUM_GUEST_DISPLAYS:/* Number of guest displays in X/Y direction */
    2240             STAM_REL_COUNTER_INC(&pThis->svga.StatRegNumGuestDisplaysWr);
    2241             break;
    2242         case SVGA_REG_DISPLAY_ID:        /* Display ID for the following display attributes */
    2243             STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayIdWr);
    2244             break;
    2245         case SVGA_REG_DISPLAY_IS_PRIMARY:/* Whether this is a primary display */
    2246             STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayIsPrimaryWr);
    2247             break;
    2248         case SVGA_REG_DISPLAY_POSITION_X:/* The display position x */
    2249             STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayPositionXWr);
    2250             break;
    2251         case SVGA_REG_DISPLAY_POSITION_Y:/* The display position y */
    2252             STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayPositionYWr);
    2253             break;
    2254         case SVGA_REG_DISPLAY_WIDTH:     /* The display's width */
    2255             STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayWidthWr);
    2256             break;
    2257         case SVGA_REG_DISPLAY_HEIGHT:    /* The display's height */
    2258             STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayHeightWr);
    2259             break;
    2260 #ifdef VBOX_WITH_VMSVGA3D
    2261         /* See "Guest memory regions" below. */
    2262         case SVGA_REG_GMR_ID:
    2263             STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrIdWr);
    2264             pThis->svga.u32CurrentGMRId = u32;
    2265             break;
    2266 
    2267         case SVGA_REG_GMR_DESCRIPTOR:
    2268 # ifndef IN_RING3
    2269             rc = VINF_IOM_R3_IOPORT_WRITE;
    2270             break;
    2271 # else /* IN_RING3 */
    2272         {
    2273             STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegGmrDescriptorWr);
    2274 
    2275             /* Validate current GMR id. */
    2276             uint32_t idGMR = pThis->svga.u32CurrentGMRId;
    2277             AssertBreak(idGMR < pThis->svga.cGMR);
    2278             RT_UNTRUSTED_VALIDATED_FENCE();
    2279 
    2280             /* Free the old GMR if present. */
    2281             vmsvgaR3GmrFree(pThisCC, idGMR);
    2282 
    2283             /* Just undefine the GMR? */
    2284             RTGCPHYS GCPhys = (RTGCPHYS)u32 << PAGE_SHIFT;
    2285             if (GCPhys == 0)
    2286             {
    2287                 STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegGmrDescriptorWrFree);
    2288                 break;
    2289             }
    2290 
    2291 
    2292             /* Never cross a page boundary automatically. */
    2293             const uint32_t          cMaxPages   = RT_MIN(VMSVGA_MAX_GMR_PAGES, UINT32_MAX / X86_PAGE_SIZE);
    2294             uint32_t                cPagesTotal = 0;
    2295             uint32_t                iDesc       = 0;
    2296             PVMSVGAGMRDESCRIPTOR    paDescs     = NULL;
    2297             uint32_t                cLoops      = 0;
    2298             RTGCPHYS                GCPhysBase  = GCPhys;
    2299             while (PHYS_PAGE_ADDRESS(GCPhys) == PHYS_PAGE_ADDRESS(GCPhysBase))
    2300             {
    2301                 /* Read descriptor. */
    2302                 SVGAGuestMemDescriptor desc;
    2303                 rc = PDMDevHlpPhysRead(pDevIns, GCPhys, &desc, sizeof(desc));
    2304                 AssertRCBreak(VBOXSTRICTRC_VAL(rc));
    2305 
    2306                 if (desc.numPages != 0)
    2307                 {
    2308                     AssertBreakStmt(desc.numPages <= cMaxPages, rc = VERR_OUT_OF_RANGE);
    2309                     cPagesTotal += desc.numPages;
    2310                     AssertBreakStmt(cPagesTotal   <= cMaxPages, rc = VERR_OUT_OF_RANGE);
    2311 
    2312                     if ((iDesc & 15) == 0)
    2313                     {
    2314                         void *pvNew = RTMemRealloc(paDescs, (iDesc + 16) * sizeof(VMSVGAGMRDESCRIPTOR));
    2315                         AssertBreakStmt(pvNew, rc = VERR_NO_MEMORY);
    2316                         paDescs = (PVMSVGAGMRDESCRIPTOR)pvNew;
    2317                     }
    2318 
    2319                     paDescs[iDesc].GCPhys     = (RTGCPHYS)desc.ppn << PAGE_SHIFT;
    2320                     paDescs[iDesc++].numPages = desc.numPages;
    2321 
    2322                     /* Continue with the next descriptor. */
    2323                     GCPhys += sizeof(desc);
    2324                 }
    2325                 else if (desc.ppn == 0)
    2326                     break;  /* terminator */
    2327                 else /* Pointer to the next physical page of descriptors. */
    2328                     GCPhys = GCPhysBase = (RTGCPHYS)desc.ppn << PAGE_SHIFT;
    2329 
    2330                 cLoops++;
    2331                 AssertBreakStmt(cLoops < VMSVGA_MAX_GMR_DESC_LOOP_COUNT, rc = VERR_OUT_OF_RANGE);
    2332             }
    2333 
    2334             AssertStmt(iDesc > 0 || RT_FAILURE_NP(rc), rc = VERR_OUT_OF_RANGE);
    2335             if (RT_SUCCESS(rc))
    2336             {
    2337                 /* Commit the GMR. */
    2338                 pSVGAState->paGMR[idGMR].paDesc         = paDescs;
    2339                 pSVGAState->paGMR[idGMR].numDescriptors = iDesc;
    2340                 pSVGAState->paGMR[idGMR].cMaxPages      = cPagesTotal;
    2341                 pSVGAState->paGMR[idGMR].cbTotal        = cPagesTotal * PAGE_SIZE;
    2342                 Assert((pSVGAState->paGMR[idGMR].cbTotal >> PAGE_SHIFT) == cPagesTotal);
    2343                 Log(("Defined new gmr %x numDescriptors=%d cbTotal=%x (%#x pages)\n",
    2344                      idGMR, iDesc, pSVGAState->paGMR[idGMR].cbTotal, cPagesTotal));
    2345             }
    2346             else
    2347             {
    2348                 RTMemFree(paDescs);
    2349                 STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegGmrDescriptorWrErrors);
    2350             }
    2351             break;
    2352         }
    2353 # endif /* IN_RING3 */
    2354 #endif // VBOX_WITH_VMSVGA3D
    2355 
    2356         case SVGA_REG_TRACES:            /* Enable trace-based updates even when FIFO is on */
    2357             STAM_REL_COUNTER_INC(&pThis->svga.StatRegTracesWr);
    2358             if (pThis->svga.fTraces == u32)
    2359                 break; /* nothing to do */
    2360 
    2361 #ifdef IN_RING3
    2362             vmsvgaR3SetTraces(pDevIns, pThis, !!u32);
    2363 #else
    2364             rc = VINF_IOM_R3_IOPORT_WRITE;
    2365 #endif
    2366             break;
    2367 
    2368         case SVGA_REG_TOP:               /* Must be 1 more than the last register */
    2369             STAM_REL_COUNTER_INC(&pThis->svga.StatRegTopWr);
    2370             break;
    2371 
    2372         case SVGA_REG_NUM_DISPLAYS:        /* (Deprecated) */
    2373             STAM_REL_COUNTER_INC(&pThis->svga.StatRegNumDisplaysWr);
    2374             Log(("Write to deprecated register %x - val %x ignored\n", idxReg, u32));
    2375             break;
    2376 
    2377         /*
    2378          * SVGA_CAP_GBOBJECTS+ registers.
    2379          */
    2380         case SVGA_REG_COMMAND_LOW:
    2381         {
    2382             /* Lower 32 bits of command buffer physical address and submit the command buffer. */
    2383 #ifdef IN_RING3
    2384             STAM_REL_COUNTER_INC(&pThis->svga.StatRegCommandLowWr);
    2385             pThis->svga.u32RegCommandLow = u32;
    2386 
    2387             /* "lower 6 bits are used for the SVGACBContext" */
    2388             RTGCPHYS GCPhysCB = pThis->svga.u32RegCommandHigh;
    2389             GCPhysCB <<= 32;
    2390             GCPhysCB |= pThis->svga.u32RegCommandLow & ~SVGA_CB_CONTEXT_MASK;
    2391             SVGACBContext const CBCtx = (SVGACBContext)(pThis->svga.u32RegCommandLow & SVGA_CB_CONTEXT_MASK);
    2392             vmsvgaR3CmdBufSubmit(pDevIns, pThis, pThisCC, GCPhysCB, CBCtx);
    2393 #else
    2394             rc = VINF_IOM_R3_IOPORT_WRITE;
    2395 #endif
    2396             break;
    2397         }
    2398 
    2399         case SVGA_REG_COMMAND_HIGH:
    2400             /* Upper 32 bits of command buffer PA. */
    2401             STAM_REL_COUNTER_INC(&pThis->svga.StatRegCommandHighWr);
    2402             pThis->svga.u32RegCommandHigh = u32;
    2403             break;
    2404 
    2405         case SVGA_REG_DEV_CAP:
    2406             /* Write dev cap index, read value */
    2407             STAM_REL_COUNTER_INC(&pThis->svga.StatRegDevCapWr);
    2408             pThis->svga.u32DevCapIndex = u32;
    2409             break;
    2410 
    2411         case SVGA_REG_CMD_PREPEND_LOW:
    2412             STAM_REL_COUNTER_INC(&pThis->svga.StatRegCmdPrependLowWr);
    2413             /* Not supported. */
    2414             break;
    2415 
    2416         case SVGA_REG_iCMD_PREPEND_HIGH:
    2417             STAM_REL_COUNTER_INC(&pThis->svga.StatRegCmdPrependHighWr);
    2418             /* Not supported. */
    2419             break;
    2420 
    2421         case SVGA_REG_FB_START:
    2422         case SVGA_REG_MEM_START:
    2423         case SVGA_REG_HOST_BITS_PER_PIXEL:
    2424         case SVGA_REG_MAX_WIDTH:
    2425         case SVGA_REG_MAX_HEIGHT:
    2426         case SVGA_REG_VRAM_SIZE:
    2427         case SVGA_REG_FB_SIZE:
    2428         case SVGA_REG_CAPABILITIES:
    2429         case SVGA_REG_MEM_SIZE:
    2430         case SVGA_REG_SCRATCH_SIZE:        /* Number of scratch registers */
    2431         case SVGA_REG_MEM_REGS:            /* Number of FIFO registers */
    2432         case SVGA_REG_BYTES_PER_LINE:
    2433         case SVGA_REG_FB_OFFSET:
    2434         case SVGA_REG_RED_MASK:
    2435         case SVGA_REG_GREEN_MASK:
    2436         case SVGA_REG_BLUE_MASK:
    2437         case SVGA_REG_GMRS_MAX_PAGES:    /* Maximum number of 4KB pages for all GMRs */
    2438         case SVGA_REG_MEMORY_SIZE:       /* Total dedicated device memory excluding FIFO */
    2439         case SVGA_REG_GMR_MAX_IDS:
    2440         case SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH:
    2441         case SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM:
    2442         case SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB:
    2443         case SVGA_REG_SCREENTARGET_MAX_WIDTH:
    2444         case SVGA_REG_SCREENTARGET_MAX_HEIGHT:
    2445         case SVGA_REG_MOB_MAX_SIZE:
    2446             /* Read only - ignore. */
    2447             Log(("Write to R/O register %x - val %x ignored\n", idxReg, u32));
    2448             STAM_REL_COUNTER_INC(&pThis->svga.StatRegReadOnlyWr);
    2449             break;
    2450 
    2451         default:
    2452         {
    2453             uint32_t offReg;
    2454             if ((offReg = idxReg - SVGA_SCRATCH_BASE) < pThis->svga.cScratchRegion)
    2455             {
    2456                 RT_UNTRUSTED_VALIDATED_FENCE();
    2457                 pThis->svga.au32ScratchRegion[offReg] = u32;
    2458                 STAM_REL_COUNTER_INC(&pThis->svga.StatRegScratchWr);
    2459             }
    2460             else if ((offReg = idxReg - SVGA_PALETTE_BASE) < (uint32_t)SVGA_NUM_PALETTE_REGS)
    2461             {
    2462                 /* Note! Using last_palette rather than palette here to preserve the VGA one.
    2463                          Btw, see rgb_to_pixel32.  */
    2464                 STAM_REL_COUNTER_INC(&pThis->svga.StatRegPaletteWr);
    2465                 u32 &= 0xff;
    2466                 RT_UNTRUSTED_VALIDATED_FENCE();
    2467                 uint32_t uRgb = pThis->last_palette[offReg / 3];
    2468                 switch (offReg % 3)
    2469                 {
    2470                     case 0: uRgb = (uRgb & UINT32_C(0x0000ffff)) | (u32 << 16); break; /* red */
    2471                     case 1: uRgb = (uRgb & UINT32_C(0x00ff00ff)) | (u32 <<  8); break; /* green */
    2472                     case 2: uRgb = (uRgb & UINT32_C(0x00ffff00)) |  u32       ; break; /* blue */
    2473                 }
    2474                 pThis->last_palette[offReg / 3] = uRgb;
    2475             }
    2476             else
    2477             {
    2478 #if !defined(IN_RING3) && defined(VBOX_STRICT)
    2479                 rc = VINF_IOM_R3_IOPORT_WRITE;
    2480 #else
    2481                 STAM_REL_COUNTER_INC(&pThis->svga.StatRegUnknownWr);
    2482                 AssertMsgFailed(("reg=%#x u32=%#x\n", idxReg, u32));
    2483 #endif
    2484             }
    2485             break;
    2486         }
    2487     }
    2488     return rc;
    2489 }
    2490 
    2491 /**
    2492  * @callback_method_impl{FNIOMIOPORTNEWIN}
    2493  */
    2494 DECLCALLBACK(VBOXSTRICTRC) vmsvgaIORead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb)
    2495 {
    2496     PVGASTATE   pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
    2497     RT_NOREF_PV(pvUser);
    2498 
    2499     /* Only dword accesses. */
    2500     if (cb == 4)
    2501     {
    2502         switch (offPort)
    2503         {
    2504             case SVGA_INDEX_PORT:
    2505                 *pu32 = pThis->svga.u32IndexReg;
    2506                 break;
    2507 
    2508             case SVGA_VALUE_PORT:
    2509                 return vmsvgaReadPort(pDevIns, pThis, pu32);
    2510 
    2511             case SVGA_BIOS_PORT:
    2512                 Log(("Ignoring BIOS port read\n"));
    2513                 *pu32 = 0;
    2514                 break;
    2515 
    2516             case SVGA_IRQSTATUS_PORT:
    2517                 LogFlow(("vmsvgaIORead: SVGA_IRQSTATUS_PORT %x\n", pThis->svga.u32IrqStatus));
    2518                 *pu32 = pThis->svga.u32IrqStatus;
    2519                 break;
    2520 
    2521             default:
    2522                 ASSERT_GUEST_MSG_FAILED(("vmsvgaIORead: Unknown register %u was read from.\n", offPort));
    2523                 *pu32 = UINT32_MAX;
    2524                 break;
    2525         }
    2526     }
    2527     else
    2528     {
    2529         Log(("Ignoring non-dword I/O port read at %x cb=%d\n", offPort, cb));
    2530         *pu32 = UINT32_MAX;
    2531     }
    2532     return VINF_SUCCESS;
    2533 }
    2534 
    2535 /**
    2536  * @callback_method_impl{FNIOMIOPORTNEWOUT}
    2537  */
    2538 DECLCALLBACK(VBOXSTRICTRC) vmsvgaIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb)
    2539 {
    2540     PVGASTATE   pThis   = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
    2541     PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
    2542     RT_NOREF_PV(pvUser);
    2543 
    2544     /* Only dword accesses. */
    2545     if (cb == 4)
    2546         switch (offPort)
    2547         {
    2548             case SVGA_INDEX_PORT:
    2549                 pThis->svga.u32IndexReg = u32;
    2550                 break;
    2551 
    2552             case SVGA_VALUE_PORT:
    2553                 return vmsvgaWritePort(pDevIns, pThis, pThisCC, u32);
    2554 
    2555             case SVGA_BIOS_PORT:
    2556                 Log(("Ignoring BIOS port write (val=%x)\n", u32));
    2557                 break;
    2558 
    2559             case SVGA_IRQSTATUS_PORT:
    2560                 Log(("vmsvgaIOWrite SVGA_IRQSTATUS_PORT %x: status %x -> %x\n", u32, pThis->svga.u32IrqStatus, pThis->svga.u32IrqStatus & ~u32));
    2561                 ASMAtomicAndU32(&pThis->svga.u32IrqStatus, ~u32);
    2562                 /* Clear the irq in case all events have been cleared. */
    2563                 if (!(pThis->svga.u32IrqStatus & pThis->svga.u32IrqMask))
    2564                 {
    2565                     Log(("vmsvgaIOWrite SVGA_IRQSTATUS_PORT: clearing IRQ\n"));
    2566                     PDMDevHlpPCISetIrqNoWait(pDevIns, 0, 0);
    2567                 }
    2568                 break;
    2569 
    2570             default:
    2571                 ASSERT_GUEST_MSG_FAILED(("vmsvgaIOWrite: Unknown register %u was written to, value %#x LB %u.\n", offPort, u32, cb));
    2572                 break;
    2573         }
    2574     else
    2575         Log(("Ignoring non-dword write at %x val=%x cb=%d\n", offPort, u32, cb));
    2576 
    2577     return VINF_SUCCESS;
    2578 }
    2579 
    2580 #ifdef IN_RING3
    2581 
    2582 # ifdef DEBUG_FIFO_ACCESS
    2583 /**
    2584  * Handle FIFO memory access.
    2585  * @returns VBox status code.
    2586  * @param   pVM             VM handle.
    2587  * @param   pThis           The shared VGA/VMSVGA instance data.
    2588  * @param   GCPhys          The access physical address.
    2589  * @param   fWriteAccess    Read or write access
    2590  */
    2591 static int vmsvgaR3DebugFifoAccess(PVM pVM, PVGASTATE pThis, RTGCPHYS GCPhys, bool fWriteAccess)
    2592 {
    2593     RT_NOREF(pVM);
    2594     RTGCPHYS GCPhysOffset = GCPhys - pThis->svga.GCPhysFIFO;
    2595     uint32_t *pFIFO = pThisCC->svga.pau32FIFO;
    2596 
    2597     switch (GCPhysOffset >> 2)
    2598     {
    2599     case SVGA_FIFO_MIN:
    2600         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_MIN = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2601         break;
    2602     case SVGA_FIFO_MAX:
    2603         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_MAX = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2604         break;
    2605     case SVGA_FIFO_NEXT_CMD:
    2606         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_NEXT_CMD = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2607         break;
    2608     case SVGA_FIFO_STOP:
    2609         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_STOP = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2610         break;
    2611     case SVGA_FIFO_CAPABILITIES:
    2612         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CAPABILITIES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2613         break;
    2614     case SVGA_FIFO_FLAGS:
    2615         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_FLAGS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2616         break;
    2617     case SVGA_FIFO_FENCE:
    2618         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_FENCE = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2619         break;
    2620     case SVGA_FIFO_3D_HWVERSION:
    2621         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_HWVERSION = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2622         break;
    2623     case SVGA_FIFO_PITCHLOCK:
    2624         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_PITCHLOCK = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2625         break;
    2626     case SVGA_FIFO_CURSOR_ON:
    2627         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_ON = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2628         break;
    2629     case SVGA_FIFO_CURSOR_X:
    2630         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_X = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2631         break;
    2632     case SVGA_FIFO_CURSOR_Y:
    2633         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_Y = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2634         break;
    2635     case SVGA_FIFO_CURSOR_COUNT:
    2636         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_COUNT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2637         break;
    2638     case SVGA_FIFO_CURSOR_LAST_UPDATED:
    2639         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_LAST_UPDATED = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2640         break;
    2641     case SVGA_FIFO_RESERVED:
    2642         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_RESERVED = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2643         break;
    2644     case SVGA_FIFO_CURSOR_SCREEN_ID:
    2645         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_SCREEN_ID = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2646         break;
    2647     case SVGA_FIFO_DEAD:
    2648         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_DEAD = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2649         break;
    2650     case SVGA_FIFO_3D_HWVERSION_REVISED:
    2651         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_HWVERSION_REVISED = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2652         break;
    2653     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_3D:
    2654         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_3D = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2655         break;
    2656     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_LIGHTS:
    2657         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_LIGHTS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2658         break;
    2659     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURES:
    2660         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2661         break;
    2662     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_CLIP_PLANES:
    2663         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_CLIP_PLANES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2664         break;
    2665     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_VERTEX_SHADER_VERSION:
    2666         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_VERTEX_SHADER_VERSION = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2667         break;
    2668     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_VERTEX_SHADER:
    2669         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_VERTEX_SHADER = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2670         break;
    2671     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_FRAGMENT_SHADER_VERSION:
    2672         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_FRAGMENT_SHADER_VERSION = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2673         break;
    2674     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_FRAGMENT_SHADER:
    2675         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_FRAGMENT_SHADER = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2676         break;
    2677     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_RENDER_TARGETS:
    2678         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_RENDER_TARGETS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2679         break;
    2680     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_S23E8_TEXTURES:
    2681         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_S23E8_TEXTURES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2682         break;
    2683     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_S10E5_TEXTURES:
    2684         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_S10E5_TEXTURES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2685         break;
    2686     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_FIXED_VERTEXBLEND:
    2687         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_FIXED_VERTEXBLEND = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2688         break;
    2689     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_D16_BUFFER_FORMAT:
    2690         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_D16_BUFFER_FORMAT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2691         break;
    2692     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_D24S8_BUFFER_FORMAT:
    2693         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_D24S8_BUFFER_FORMAT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2694         break;
    2695     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_D24X8_BUFFER_FORMAT:
    2696         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_D24X8_BUFFER_FORMAT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2697         break;
    2698     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_QUERY_TYPES:
    2699         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_QUERY_TYPES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2700         break;
    2701     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_TEXTURE_GRADIENT_SAMPLING:
    2702         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_TEXTURE_GRADIENT_SAMPLING = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2703         break;
    2704     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_POINT_SIZE:
    2705         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_POINT_SIZE = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2706         break;
    2707     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_SHADER_TEXTURES:
    2708         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_SHADER_TEXTURES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2709         break;
    2710     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURE_WIDTH:
    2711         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURE_WIDTH = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2712         break;
    2713     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURE_HEIGHT:
    2714         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURE_HEIGHT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2715         break;
    2716     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_VOLUME_EXTENT:
    2717         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_VOLUME_EXTENT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2718         break;
    2719     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURE_REPEAT:
    2720         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURE_REPEAT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2721         break;
    2722     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURE_ASPECT_RATIO:
    2723         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURE_ASPECT_RATIO = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2724         break;
    2725     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURE_ANISOTROPY:
    2726         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURE_ANISOTROPY = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2727         break;
    2728     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_PRIMITIVE_COUNT:
    2729         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_PRIMITIVE_COUNT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2730         break;
    2731     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_VERTEX_INDEX:
    2732         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_VERTEX_INDEX = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2733         break;
    2734     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_VERTEX_SHADER_INSTRUCTIONS:
    2735         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_VERTEX_SHADER_INSTRUCTIONS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2736         break;
    2737     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_INSTRUCTIONS:
    2738         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_INSTRUCTIONS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2739         break;
    2740     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEMPS:
    2741         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEMPS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2742         break;
    2743     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_TEMPS:
    2744         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_TEMPS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2745         break;
    2746     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_TEXTURE_OPS:
    2747         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_TEXTURE_OPS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2748         break;
    2749     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8:
    2750         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2751         break;
    2752     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8:
    2753         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2754         break;
    2755     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10:
    2756         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2757         break;
    2758     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5:
    2759         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2760         break;
    2761     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5:
    2762         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2763         break;
    2764     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4:
    2765         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2766         break;
    2767     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_R5G6B5:
    2768         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_R5G6B5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2769         break;
    2770     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE16:
    2771         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2772         break;
    2773     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8:
    2774         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2775         break;
    2776     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_ALPHA8:
    2777         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_ALPHA8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2778         break;
    2779     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8:
    2780         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2781         break;
    2782     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_D16:
    2783         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_D16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2784         break;
    2785     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8:
    2786         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2787         break;
    2788     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8:
    2789         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2790         break;
    2791     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_DXT1:
    2792         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_DXT1 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2793         break;
    2794     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_DXT2:
    2795         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_DXT2 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2796         break;
    2797     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_DXT3:
    2798         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_DXT3 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2799         break;
    2800     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_DXT4:
    2801         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_DXT4 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2802         break;
    2803     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_DXT5:
    2804         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_DXT5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2805         break;
    2806     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_BUMPX8L8V8U8:
    2807         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_BUMPX8L8V8U8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2808         break;
    2809     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A2W10V10U10:
    2810         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A2W10V10U10 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2811         break;
    2812     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_BUMPU8V8:
    2813         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_BUMPU8V8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2814         break;
    2815     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Q8W8V8U8:
    2816         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Q8W8V8U8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2817         break;
    2818     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_CxV8U8:
    2819         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_CxV8U8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2820         break;
    2821     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_R_S10E5:
    2822         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_R_S10E5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2823         break;
    2824     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_R_S23E8:
    2825         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_R_S23E8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2826         break;
    2827     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_RG_S10E5:
    2828         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_RG_S10E5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2829         break;
    2830     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_RG_S23E8:
    2831         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_RG_S23E8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2832         break;
    2833     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_ARGB_S10E5:
    2834         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_ARGB_S10E5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2835         break;
    2836     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_ARGB_S23E8:
    2837         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_ARGB_S23E8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2838         break;
    2839     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEXTURES:
    2840         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEXTURES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2841         break;
    2842     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_SIMULTANEOUS_RENDER_TARGETS:
    2843         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_SIMULTANEOUS_RENDER_TARGETS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2844         break;
    2845     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_V16U16:
    2846         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_V16U16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2847         break;
    2848     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_G16R16:
    2849         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_G16R16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2850         break;
    2851     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16:
    2852         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2853         break;
    2854     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_UYVY:
    2855         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_UYVY = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2856         break;
    2857     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_YUY2:
    2858         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_YUY2 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2859         break;
    2860     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MULTISAMPLE_NONMASKABLESAMPLES:
    2861         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MULTISAMPLE_NONMASKABLESAMPLES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2862         break;
    2863     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MULTISAMPLE_MASKABLESAMPLES:
    2864         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MULTISAMPLE_MASKABLESAMPLES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2865         break;
    2866     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_ALPHATOCOVERAGE:
    2867         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_ALPHATOCOVERAGE = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2868         break;
    2869     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SUPERSAMPLE:
    2870         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SUPERSAMPLE = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2871         break;
    2872     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_AUTOGENMIPMAPS:
    2873         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_AUTOGENMIPMAPS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2874         break;
    2875     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_NV12:
    2876         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_NV12 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2877         break;
    2878     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_AYUV:
    2879         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_AYUV = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2880         break;
    2881     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_CONTEXT_IDS:
    2882         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_CONTEXT_IDS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2883         break;
    2884     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_SURFACE_IDS:
    2885         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_SURFACE_IDS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2886         break;
    2887     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_DF16:
    2888         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_DF16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2889         break;
    2890     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_DF24:
    2891         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_DF24 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2892         break;
    2893     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8_INT:
    2894         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8_INT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2895         break;
    2896     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_ATI1:
    2897         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_ATI1 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2898         break;
    2899     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_ATI2:
    2900         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_ATI2 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2901         break;
    2902     case SVGA_FIFO_3D_CAPS_LAST:
    2903         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS_LAST = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2904         break;
    2905     case SVGA_FIFO_GUEST_3D_HWVERSION:
    2906         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_GUEST_3D_HWVERSION = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2907         break;
    2908     case SVGA_FIFO_FENCE_GOAL:
    2909         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_FENCE_GOAL = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2910         break;
    2911     case SVGA_FIFO_BUSY:
    2912         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_BUSY = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2913         break;
    2914     default:
    2915         Log(("vmsvgaFIFOAccess [0x%x]: %s access at offset %x = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", GCPhysOffset, pFIFO[GCPhysOffset >> 2]));
    2916         break;
    2917     }
    2918 
    2919     return VINF_EM_RAW_EMULATE_INSTR;
    2920 }
    2921 # endif /* DEBUG_FIFO_ACCESS */
    2922 
    2923 # if defined(VMSVGA_USE_FIFO_ACCESS_HANDLER) || defined(DEBUG_FIFO_ACCESS)
    2924 /**
    2925  * HC access handler for the FIFO.
    2926  *
    2927  * @returns VINF_SUCCESS if the handler have carried out the operation.
    2928  * @returns VINF_PGM_HANDLER_DO_DEFAULT if the caller should carry out the access operation.
    2929  * @param   pVM             VM Handle.
    2930  * @param   pVCpu           The cross context CPU structure for the calling EMT.
    2931  * @param   GCPhys          The physical address the guest is writing to.
    2932  * @param   pvPhys          The HC mapping of that address.
    2933  * @param   pvBuf           What the guest is reading/writing.
    2934  * @param   cbBuf           How much it's reading/writing.
    2935  * @param   enmAccessType   The access type.
    2936  * @param   enmOrigin       Who is making the access.
    2937  * @param   pvUser          User argument.
    2938  */
    2939 static DECLCALLBACK(VBOXSTRICTRC)
    2940 vmsvgaR3FifoAccessHandler(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf,
    2941                           PGMACCESSTYPE enmAccessType, PGMACCESSORIGIN enmOrigin, void *pvUser)
    2942 {
    2943     NOREF(pVCpu); NOREF(pvPhys); NOREF(pvBuf); NOREF(cbBuf); NOREF(enmOrigin); NOREF(enmAccessType); NOREF(GCPhys);
    2944     PVGASTATE pThis = (PVGASTATE)pvUser;
    2945     AssertPtr(pThis);
    2946 
    2947 # ifdef VMSVGA_USE_FIFO_ACCESS_HANDLER
    2948     /*
    2949      * Wake up the FIFO thread as it might have work to do now.
    2950      */
    2951     int rc = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->svga.hFIFORequestSem);
    2952     AssertLogRelRC(rc);
    2953 # endif
    2954 
    2955 # ifdef DEBUG_FIFO_ACCESS
    2956     /*
    2957      * When in debug-fifo-access mode, we do not disable the access handler,
    2958      * but leave it on as we wish to catch all access.
    2959      */
    2960     Assert(GCPhys >= pThis->svga.GCPhysFIFO);
    2961     rc = vmsvgaR3DebugFifoAccess(pVM, pThis, GCPhys, enmAccessType == PGMACCESSTYPE_WRITE);
    2962 # elif defined(VMSVGA_USE_FIFO_ACCESS_HANDLER)
    2963     /*
    2964      * Temporarily disable the access handler now that we've kicked the FIFO thread.
    2965      */
    2966     STAM_REL_COUNTER_INC(&pThisCC->svga.pSvgaR3State->StatFifoAccessHandler);
    2967     rc = PGMHandlerPhysicalPageTempOff(pVM, pThis->svga.GCPhysFIFO, pThis->svga.GCPhysFIFO);
    2968 # endif
    2969     if (RT_SUCCESS(rc))
    2970         return VINF_PGM_HANDLER_DO_DEFAULT;
    2971     AssertMsg(rc <= VINF_SUCCESS, ("rc=%Rrc\n", rc));
    2972     return rc;
    2973 }
    2974 # endif /* VMSVGA_USE_FIFO_ACCESS_HANDLER || DEBUG_FIFO_ACCESS */
    2975 
    2976 #endif /* IN_RING3 */
    2977 
    2978 #ifdef DEBUG_GMR_ACCESS
    2979 # ifdef IN_RING3
    2980 
    2981 /**
    2982  * HC access handler for the FIFO.
    2983  *
    2984  * @returns VINF_SUCCESS if the handler have carried out the operation.
    2985  * @returns VINF_PGM_HANDLER_DO_DEFAULT if the caller should carry out the access operation.
    2986  * @param   pVM             VM Handle.
    2987  * @param   pVCpu           The cross context CPU structure for the calling EMT.
    2988  * @param   GCPhys          The physical address the guest is writing to.
    2989  * @param   pvPhys          The HC mapping of that address.
    2990  * @param   pvBuf           What the guest is reading/writing.
    2991  * @param   cbBuf           How much it's reading/writing.
    2992  * @param   enmAccessType   The access type.
    2993  * @param   enmOrigin       Who is making the access.
    2994  * @param   pvUser          User argument.
    2995  */
    2996 static DECLCALLBACK(VBOXSTRICTRC)
    2997 vmsvgaR3GmrAccessHandler(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf,
    2998                          PGMACCESSTYPE enmAccessType, PGMACCESSORIGIN enmOrigin, void *pvUser)
    2999 {
    3000     PVGASTATE   pThis = (PVGASTATE)pvUser;
    3001     Assert(pThis);
    3002     PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
    3003     NOREF(pVCpu); NOREF(pvPhys); NOREF(pvBuf); NOREF(cbBuf); NOREF(enmAccessType); NOREF(enmOrigin);
    3004 
    3005     Log(("vmsvgaR3GmrAccessHandler: GMR access to page %RGp\n", GCPhys));
    3006 
    3007     for (uint32_t i = 0; i < pThis->svga.cGMR; ++i)
    3008     {
    3009         PGMR pGMR = &pSVGAState->paGMR[i];
    3010 
    3011         if (pGMR->numDescriptors)
    3012         {
    3013             for (uint32_t j = 0; j < pGMR->numDescriptors; j++)
    3014             {
    3015                 if (    GCPhys >= pGMR->paDesc[j].GCPhys
    3016                     &&  GCPhys < pGMR->paDesc[j].GCPhys + pGMR->paDesc[j].numPages * PAGE_SIZE)
    3017                 {
    3018                     /*
    3019                      * Turn off the write handler for this particular page and make it R/W.
    3020                      * Then return telling the caller to restart the guest instruction.
    3021                      */
    3022                     int rc = PGMHandlerPhysicalPageTempOff(pVM, pGMR->paDesc[j].GCPhys, GCPhys);
    3023                     AssertRC(rc);
    3024                     return VINF_PGM_HANDLER_DO_DEFAULT;
    3025                 }
    3026             }
    3027         }
    3028     }
    3029 
    3030     return VINF_PGM_HANDLER_DO_DEFAULT;
    3031 }
    3032 
    3033 /** Callback handler for VMR3ReqCallWaitU */
    3034 static DECLCALLBACK(int) vmsvgaR3RegisterGmr(PPDMDEVINS pDevIns, uint32_t gmrId)
    3035 {
    3036     PVGASTATE       pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
    3037     PVMSVGAR3STATE  pSVGAState = pThisCC->svga.pSvgaR3State;
    3038     PGMR pGMR = &pSVGAState->paGMR[gmrId];
    3039     int rc;
    3040 
    3041     for (uint32_t i = 0; i < pGMR->numDescriptors; i++)
    3042     {
    3043         rc = PGMHandlerPhysicalRegister(PDMDevHlpGetVM(pDevIns),
    3044                                         pGMR->paDesc[i].GCPhys, pGMR->paDesc[i].GCPhys + pGMR->paDesc[i].numPages * PAGE_SIZE - 1,
    3045                                         pThis->svga.hGmrAccessHandlerType, pThis, NIL_RTR0PTR, NIL_RTRCPTR, "VMSVGA GMR");
    3046         AssertRC(rc);
    3047     }
    3048     return VINF_SUCCESS;
    3049 }
    3050 
    3051 /** Callback handler for VMR3ReqCallWaitU */
    3052 static DECLCALLBACK(int) vmsvgaR3DeregisterGmr(PPDMDEVINS pDevIns, uint32_t gmrId)
    3053 {
    3054     PVGASTATE       pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
    3055     PVMSVGAR3STATE  pSVGAState = pThisCC->svga.pSvgaR3State;
    3056     PGMR pGMR = &pSVGAState->paGMR[gmrId];
    3057 
    3058     for (uint32_t i = 0; i < pGMR->numDescriptors; i++)
    3059     {
    3060         int rc = PGMHandlerPhysicalDeregister(PDMDevHlpGetVM(pDevIns), pGMR->paDesc[i].GCPhys);
    3061         AssertRC(rc);
    3062     }
    3063     return VINF_SUCCESS;
    3064 }
    3065 
    3066 /** Callback handler for VMR3ReqCallWaitU */
    3067 static DECLCALLBACK(int) vmsvgaR3ResetGmrHandlers(PVGASTATE pThis)
    3068 {
    3069     PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
    3070 
    3071     for (uint32_t i = 0; i < pThis->svga.cGMR; ++i)
    3072     {
    3073         PGMR pGMR = &pSVGAState->paGMR[i];
    3074 
    3075         if (pGMR->numDescriptors)
    3076         {
    3077             for (uint32_t j = 0; j < pGMR->numDescriptors; j++)
    3078             {
    3079                 int rc = PGMHandlerPhysicalReset(PDMDevHlpGetVM(pDevIns), pGMR->paDesc[j].GCPhys);
    3080                 AssertRC(rc);
    3081             }
    3082         }
    3083     }
    3084     return VINF_SUCCESS;
    3085 }
    3086 
    3087 # endif /* IN_RING3 */
    3088 #endif /* DEBUG_GMR_ACCESS */
    3089 
    3090 /* -=-=-=-=-=- Ring 3 -=-=-=-=-=- */
    3091 
    3092 #ifdef IN_RING3
    3093357
    3094358
     
    3110374{
    3111375    LogRel2(("vmsvgaR3InstallNewCursor: cx=%d cy=%d xHot=%d yHot=%d fAlpha=%d cbData=%#x\n", cx, cy, xHot, yHot, fAlpha, cbData));
    3112 # ifdef LOG_ENABLED
     376#ifdef LOG_ENABLED
    3113377    if (LogIs2Enabled())
    3114378    {
     
    3151415        }
    3152416    }
    3153 # endif
     417#endif
    3154418
    3155419    int rc = pThisCC->pDrv->pfnVBVAMousePointerShape(pThisCC->pDrv, true /*fVisible*/, fAlpha, xHot, yHot, cx, cy, pbData);
     
    3169433
    3170434
    3171 # ifdef VBOX_WITH_VMSVGA3D
     435#ifdef VBOX_WITH_VMSVGA3D
    3172436/** @def VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK
    3173437 * Check that the 3D command has at least a_cbMin of payload bytes after the
    3174438 * header.  Will break out of the switch if it doesn't.
    3175439 */
    3176 #  define VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(a_cbMin) \
     440# define VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(a_cbMin) \
    3177441     if (1) { \
    3178442          AssertMsgBreak(cbCmd >= (a_cbMin), ("size=%#x a_cbMin=%#zx\n", cbCmd, (size_t)(a_cbMin))); \
     
    3180444     } else do {} while (0)
    3181445
    3182 #  define VMSVGA_3D_CMD_NOTIMPL() \
     446# define VMSVGA_3D_CMD_NOTIMPL() \
    3183447     if (1) { \
    3184448          AssertMsgFailed(("Not implemented %d %s\n", enmCmdId, vmsvgaR3FifoCmdToString(enmCmdId))); \
     
    3195459 * @returns VBox status code if an error was detected parsing a command.
    3196460 */
    3197 static int vmsvgaR3Process3dCmd(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifo3dCmdId enmCmdId, uint32_t cbCmd, void const *pvCmd)
     461int vmsvgaR3Process3dCmd(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifo3dCmdId enmCmdId, uint32_t cbCmd, void const *pvCmd)
    3198462{
    3199463    int rcParse = VINF_SUCCESS;
     
    3211475        vmsvga3dSurfaceDefine(pThisCC, pCmd->sid, (uint32_t)pCmd->surfaceFlags, pCmd->format, pCmd->face, 0,
    3212476                              SVGA3D_TEX_FILTER_NONE, cMipLevels, (SVGA3dSize *)(pCmd + 1));
    3213 #  ifdef DEBUG_GMR_ACCESS
     477# ifdef DEBUG_GMR_ACCESS
    3214478        VMR3ReqCallWaitU(PDMDevHlpGetUVM(pDevIns), VMCPUID_ANY, (PFNRT)vmsvgaR3ResetGmrHandlers, 1, pThis);
    3215 #  endif
     479# endif
    3216480        break;
    3217481    }
     
    40951359    return rcParse;
    40961360}
    4097 #  undef VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK
    4098 # endif // VBOX_WITH_VMSVGA3D
     1361# undef VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK
     1362#endif /* VBOX_WITH_VMSVGA3D */
    40991363
    41001364
     
    41121376
    41131377/* SVGA_CMD_UPDATE */
    4114 static void vmsvgaR3CmdUpdate(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdUpdate const *pCmd)
     1378void vmsvgaR3CmdUpdate(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdUpdate const *pCmd)
    41151379{
    41161380    RT_NOREF(pThis);
     
    41301394
    41311395/* SVGA_CMD_UPDATE_VERBOSE */
    4132 static void vmsvgaR3CmdUpdateVerbose(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdUpdateVerbose const *pCmd)
     1396void vmsvgaR3CmdUpdateVerbose(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdUpdateVerbose const *pCmd)
    41331397{
    41341398    RT_NOREF(pThis);
     
    41481412
    41491413/* SVGA_CMD_RECT_FILL */
    4150 static void vmsvgaR3CmdRectFill(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdRectFill const *pCmd)
     1414void vmsvgaR3CmdRectFill(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdRectFill const *pCmd)
    41511415{
    41521416    RT_NOREF(pThis, pCmd);
     
    41601424
    41611425/* SVGA_CMD_RECT_COPY */
    4162 static void vmsvgaR3CmdRectCopy(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdRectCopy const *pCmd)
     1426void vmsvgaR3CmdRectCopy(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdRectCopy const *pCmd)
    41631427{
    41641428    PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
     
    41851449
    41861450/* SVGA_CMD_RECT_ROP_COPY */
    4187 static void vmsvgaR3CmdRectRopCopy(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdRectRopCopy const *pCmd)
     1451void vmsvgaR3CmdRectRopCopy(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdRectRopCopy const *pCmd)
    41881452{
    41891453    PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
     
    42221486
    42231487/* SVGA_CMD_DISPLAY_CURSOR */
    4224 static void vmsvgaR3CmdDisplayCursor(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDisplayCursor const *pCmd)
     1488void vmsvgaR3CmdDisplayCursor(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDisplayCursor const *pCmd)
    42251489{
    42261490    RT_NOREF(pThis, pCmd);
     
    42341498
    42351499/* SVGA_CMD_MOVE_CURSOR */
    4236 static void vmsvgaR3CmdMoveCursor(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdMoveCursor const *pCmd)
     1500void vmsvgaR3CmdMoveCursor(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdMoveCursor const *pCmd)
    42371501{
    42381502    RT_NOREF(pThis, pCmd);
     
    42461510
    42471511/* SVGA_CMD_DEFINE_CURSOR */
    4248 static void vmsvgaR3CmdDefineCursor(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineCursor const *pCmd)
     1512void vmsvgaR3CmdDefineCursor(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineCursor const *pCmd)
    42491513{
    42501514    PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
     
    44991763
    45001764/* SVGA_CMD_DEFINE_ALPHA_CURSOR */
    4501 static void vmsvgaR3CmdDefineAlphaCursor(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineAlphaCursor const *pCmd)
     1765void vmsvgaR3CmdDefineAlphaCursor(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineAlphaCursor const *pCmd)
    45021766{
    45031767    RT_NOREF(pThis);
     
    45311795
    45321796/* SVGA_CMD_ESCAPE */
    4533 static void vmsvgaR3CmdEscape(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdEscape const *pCmd)
     1797void vmsvgaR3CmdEscape(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdEscape const *pCmd)
    45341798{
    45351799    RT_NOREF(pThis);
     
    45831847
    45841848/* SVGA_CMD_DEFINE_SCREEN */
    4585 static void vmsvgaR3CmdDefineScreen(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineScreen const *pCmd)
     1849void vmsvgaR3CmdDefineScreen(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineScreen const *pCmd)
    45861850{
    45871851    PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
     
    46411905    vmsvgaR3ChangeMode(pThis, pThisCC);
    46421906
    4643 # ifdef VBOX_WITH_VMSVGA3D
     1907#ifdef VBOX_WITH_VMSVGA3D
    46441908    if (RT_LIKELY(pThis->svga.f3DEnabled))
    46451909        vmsvga3dDefineScreen(pThis, pThisCC, pScreen);
    4646 # endif
     1910#endif
    46471911}
    46481912
    46491913
    46501914/* SVGA_CMD_DESTROY_SCREEN */
    4651 static void vmsvgaR3CmdDestroyScreen(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDestroyScreen const *pCmd)
     1915void vmsvgaR3CmdDestroyScreen(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDestroyScreen const *pCmd)
    46521916{
    46531917    PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
     
    46651929    pScreen->idScreen  = idScreen;
    46661930
    4667 # ifdef VBOX_WITH_VMSVGA3D
     1931#ifdef VBOX_WITH_VMSVGA3D
    46681932    if (RT_LIKELY(pThis->svga.f3DEnabled))
    46691933        vmsvga3dDestroyScreen(pThisCC, pScreen);
    4670 # endif
     1934#endif
    46711935    vmsvgaR3ChangeMode(pThis, pThisCC);
    46721936}
     
    46741938
    46751939/* SVGA_CMD_DEFINE_GMRFB */
    4676 static void vmsvgaR3CmdDefineGMRFB(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineGMRFB const *pCmd)
     1940void vmsvgaR3CmdDefineGMRFB(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineGMRFB const *pCmd)
    46771941{
    46781942    RT_NOREF(pThis);
     
    46901954
    46911955/* SVGA_CMD_BLIT_GMRFB_TO_SCREEN */
    4692 static void vmsvgaR3CmdBlitGMRFBToScreen(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdBlitGMRFBToScreen const *pCmd)
     1956void vmsvgaR3CmdBlitGMRFBToScreen(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdBlitGMRFBToScreen const *pCmd)
    46931957{
    46941958    PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
     
    47612025
    47622026/* SVGA_CMD_BLIT_SCREEN_TO_GMRFB */
    4763 static void vmsvgaR3CmdBlitScreenToGMRFB(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdBlitScreenToGMRFB const *pCmd)
     2027void vmsvgaR3CmdBlitScreenToGMRFB(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdBlitScreenToGMRFB const *pCmd)
    47642028{
    47652029    PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
     
    48322096
    48332097/* SVGA_CMD_ANNOTATION_FILL */
    4834 static void vmsvgaR3CmdAnnotationFill(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdAnnotationFill const *pCmd)
     2098void vmsvgaR3CmdAnnotationFill(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdAnnotationFill const *pCmd)
    48352099{
    48362100    RT_NOREF(pThis);
     
    48452109
    48462110/* SVGA_CMD_ANNOTATION_COPY */
    4847 static void vmsvgaR3CmdAnnotationCopy(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdAnnotationCopy const *pCmd)
     2111void vmsvgaR3CmdAnnotationCopy(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdAnnotationCopy const *pCmd)
    48482112{
    48492113    RT_NOREF(pThis, pCmd);
     
    48572121
    48582122
    4859 # ifdef VBOX_WITH_VMSVGA3D
     2123#ifdef VBOX_WITH_VMSVGA3D
    48602124/* SVGA_CMD_DEFINE_GMR2 */
    4861 static void vmsvgaR3CmdDefineGMR2(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineGMR2 const *pCmd)
     2125void vmsvgaR3CmdDefineGMR2(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineGMR2 const *pCmd)
    48622126{
    48632127    PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
     
    48952159
    48962160/* SVGA_CMD_REMAP_GMR2 */
    4897 static void vmsvgaR3CmdRemapGMR2(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdRemapGMR2 const *pCmd)
     2161void vmsvgaR3CmdRemapGMR2(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdRemapGMR2 const *pCmd)
    48982162{
    48992163    PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
     
    50242288        RTMemFree(paNewPage64);
    50252289}
    5026 # endif // VBOX_WITH_VMSVGA3D
    5027 
    5028 
    5029 /*
    5030  *
    5031  * Command buffer submission.
    5032  *
    5033  * Guest submits a buffer by writing to SVGA_REG_COMMAND_LOW register.
    5034  *
    5035  * EMT thread appends a command buffer to the context queue (VMSVGACMDBUFCTX::listSubmitted)
    5036  * and wakes up the FIFO thread.
    5037  *
    5038  * FIFO thread fetches the command buffer from the queue, processes the commands and writes
    5039  * the buffer header back to the guest memory.
    5040  *
    5041  * If buffers are preempted, then the EMT thread removes all buffers from the context queue.
    5042  *
    5043  */
    5044 
    5045 
    5046 /** Update a command buffer header 'status' and 'errorOffset' fields in the guest memory.
    5047  *
    5048  * @param pDevIns     The device instance.
    5049  * @param GCPhysCB    Guest physical address of the command buffer header.
    5050  * @param status      Command buffer status (SVGA_CB_STATUS_*).
    5051  * @param errorOffset Offset to the first byte of the failing command for SVGA_CB_STATUS_COMMAND_ERROR.
    5052  *                    errorOffset is ignored if the status is not SVGA_CB_STATUS_COMMAND_ERROR.
    5053  * @thread FIFO or EMT.
    5054  */
    5055 static void vmsvgaR3CmdBufWriteStatus(PPDMDEVINS pDevIns, RTGCPHYS GCPhysCB, SVGACBStatus status, uint32_t errorOffset)
    5056 {
    5057     SVGACBHeader hdr;
    5058     hdr.status = status;
    5059     hdr.errorOffset = errorOffset;
    5060     AssertCompile(   RT_OFFSETOF(SVGACBHeader, status) == 0
    5061                   && RT_OFFSETOF(SVGACBHeader, errorOffset) == 4
    5062                   && RT_OFFSETOF(SVGACBHeader, id) == 8);
    5063     size_t const cbWrite = status == SVGA_CB_STATUS_COMMAND_ERROR
    5064                          ? RT_UOFFSET_AFTER(SVGACBHeader, errorOffset)  /* Both 'status' and 'errorOffset' fields. */
    5065                          : RT_UOFFSET_AFTER(SVGACBHeader, status);      /* Only 'status' field. */
    5066     PDMDevHlpPhysWrite(pDevIns, GCPhysCB, &hdr, cbWrite);
    5067 }
    5068 
    5069 
    5070 /** Raise an IRQ.
    5071  *
    5072  * @param pDevIns     The device instance.
    5073  * @param pThis       The shared VGA/VMSVGA state.
    5074  * @param fIRQ        SVGA_IRQFLAG_* bits.
    5075  * @thread FIFO or EMT.
    5076  */
    5077 static void vmsvgaR3CmdBufRaiseIRQ(PPDMDEVINS pDevIns, PVGASTATE pThis, uint32_t fIRQ)
    5078 {
    5079     int rc = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VERR_IGNORED);
    5080     AssertRC(rc);
    5081 
    5082     if (pThis->svga.u32IrqMask & fIRQ)
    5083     {
    5084         LogFunc(("Trigger interrupt with status %#x\n", fIRQ));
    5085         ASMAtomicOrU32(&pThis->svga.u32IrqStatus, fIRQ);
    5086         PDMDevHlpPCISetIrq(pDevIns, 0, 1);
    5087     }
    5088 
    5089     PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect);
    5090 }
    5091 
    5092 
    5093 /** Allocate a command buffer structure.
    5094  *
    5095  * @param pCmdBufCtx  The command buffer context which must allocate the buffer.
    5096  * @return Pointer to the allocated command buffer structure.
    5097  */
    5098 static PVMSVGACMDBUF vmsvgaR3CmdBufAlloc(PVMSVGACMDBUFCTX pCmdBufCtx)
    5099 {
    5100     if (!pCmdBufCtx)
    5101         return NULL;
    5102 
    5103     PVMSVGACMDBUF pCmdBuf = (PVMSVGACMDBUF)RTMemAllocZ(sizeof(*pCmdBuf));
    5104     if (pCmdBuf)
    5105     {
    5106         // RT_ZERO(pCmdBuf->nodeBuffer);
    5107         pCmdBuf->pCmdBufCtx = pCmdBufCtx;
    5108         // pCmdBuf->GCPhysCB = 0;
    5109         // RT_ZERO(pCmdBuf->hdr);
    5110         // pCmdBuf->pvCommands = NULL;
    5111     }
    5112 
    5113     return pCmdBuf;
    5114 }
    5115 
    5116 
    5117 /** Free a command buffer structure.
    5118  *
    5119  * @param pCmdBuf  The command buffer pointer.
    5120  */
    5121 static void vmsvgaR3CmdBufFree(PVMSVGACMDBUF pCmdBuf)
    5122 {
    5123     if (pCmdBuf)
    5124         RTMemFree(pCmdBuf->pvCommands);
    5125     RTMemFree(pCmdBuf);
    5126 }
    5127 
    5128 
    5129 /** Initialize a command buffer context.
    5130  *
    5131  * @param pCmdBufCtx  The command buffer context.
    5132  */
    5133 static void vmsvgaR3CmdBufCtxInit(PVMSVGACMDBUFCTX pCmdBufCtx)
    5134 {
    5135     RTListInit(&pCmdBufCtx->listSubmitted);
    5136     pCmdBufCtx->cSubmitted = 0;
    5137 }
    5138 
    5139 
    5140 /** Destroy a command buffer context.
    5141  *
    5142  * @param pCmdBufCtx  The command buffer context pointer.
    5143  */
    5144 static void vmsvgaR3CmdBufCtxTerm(PVMSVGACMDBUFCTX pCmdBufCtx)
    5145 {
    5146     if (!pCmdBufCtx)
    5147         return;
    5148 
    5149     if (pCmdBufCtx->listSubmitted.pNext)
    5150     {
    5151         /* If the list has been initialized. */
    5152         PVMSVGACMDBUF pIter, pNext;
    5153         RTListForEachSafe(&pCmdBufCtx->listSubmitted, pIter, pNext, VMSVGACMDBUF, nodeBuffer)
    5154         {
    5155             RTListNodeRemove(&pIter->nodeBuffer);
    5156             --pCmdBufCtx->cSubmitted;
    5157             vmsvgaR3CmdBufFree(pIter);
    5158         }
    5159     }
    5160     Assert(pCmdBufCtx->cSubmitted == 0);
    5161     pCmdBufCtx->cSubmitted = 0;
    5162 }
    5163 
    5164 
    5165 /** Handles SVGA_DC_CMD_START_STOP_CONTEXT command.
    5166  *
    5167  * @param pSvgaR3State VMSVGA R3 state.
    5168  * @param pCmd         The command data.
    5169  * @return SVGACBStatus code.
    5170  * @thread EMT
    5171  */
    5172 static SVGACBStatus vmsvgaR3CmdBufDCStartStop(PVMSVGAR3STATE pSvgaR3State, SVGADCCmdStartStop const *pCmd)
    5173 {
    5174     /* Create or destroy a regular command buffer context. */
    5175     if (pCmd->context >= RT_ELEMENTS(pSvgaR3State->apCmdBufCtxs))
    5176         return SVGA_CB_STATUS_COMMAND_ERROR;
    5177     RT_UNTRUSTED_VALIDATED_FENCE();
    5178 
    5179     SVGACBStatus CBStatus = SVGA_CB_STATUS_COMPLETED;
    5180 
    5181     int rc = RTCritSectEnter(&pSvgaR3State->CritSectCmdBuf);
    5182     AssertRC(rc);
    5183     if (pCmd->enable)
    5184     {
    5185         pSvgaR3State->apCmdBufCtxs[pCmd->context] = (PVMSVGACMDBUFCTX)RTMemAlloc(sizeof(VMSVGACMDBUFCTX));
    5186         if (pSvgaR3State->apCmdBufCtxs[pCmd->context])
    5187             vmsvgaR3CmdBufCtxInit(pSvgaR3State->apCmdBufCtxs[pCmd->context]);
    5188         else
    5189             CBStatus = SVGA_CB_STATUS_QUEUE_FULL;
    5190     }
    5191     else
    5192     {
    5193         vmsvgaR3CmdBufCtxTerm(pSvgaR3State->apCmdBufCtxs[pCmd->context]);
    5194         pSvgaR3State->apCmdBufCtxs[pCmd->context] = NULL;
    5195     }
    5196     RTCritSectLeave(&pSvgaR3State->CritSectCmdBuf);
    5197 
    5198     return CBStatus;
    5199 }
    5200 
    5201 
    5202 /** Handles SVGA_DC_CMD_PREEMPT command.
    5203  *
    5204  * @param pDevIns      The device instance.
    5205  * @param pSvgaR3State VMSVGA R3 state.
    5206  * @param pCmd         The command data.
    5207  * @return SVGACBStatus code.
    5208  * @thread EMT
    5209  */
    5210 static SVGACBStatus vmsvgaR3CmdBufDCPreempt(PPDMDEVINS pDevIns, PVMSVGAR3STATE pSvgaR3State, SVGADCCmdPreempt const *pCmd)
    5211 {
    5212     /* Remove buffers from the processing queue of the specified context. */
    5213     if (pCmd->context >= RT_ELEMENTS(pSvgaR3State->apCmdBufCtxs))
    5214         return SVGA_CB_STATUS_COMMAND_ERROR;
    5215     RT_UNTRUSTED_VALIDATED_FENCE();
    5216 
    5217     PVMSVGACMDBUFCTX const pCmdBufCtx = pSvgaR3State->apCmdBufCtxs[pCmd->context];
    5218     RTLISTANCHOR listPreempted;
    5219 
    5220     int rc = RTCritSectEnter(&pSvgaR3State->CritSectCmdBuf);
    5221     AssertRC(rc);
    5222     if (pCmd->ignoreIDZero)
    5223     {
    5224         RTListInit(&listPreempted);
    5225 
    5226         PVMSVGACMDBUF pIter, pNext;
    5227         RTListForEachSafe(&pCmdBufCtx->listSubmitted, pIter, pNext, VMSVGACMDBUF, nodeBuffer)
    5228         {
    5229             if (pIter->hdr.id == 0)
    5230                 continue;
    5231 
    5232             RTListNodeRemove(&pIter->nodeBuffer);
    5233             --pCmdBufCtx->cSubmitted;
    5234             RTListAppend(&listPreempted, &pIter->nodeBuffer);
    5235         }
    5236     }
    5237     else
    5238     {
    5239         RTListMove(&listPreempted, &pCmdBufCtx->listSubmitted);
    5240     }
    5241     RTCritSectLeave(&pSvgaR3State->CritSectCmdBuf);
    5242 
    5243     PVMSVGACMDBUF pIter, pNext;
    5244     RTListForEachSafe(&listPreempted, pIter, pNext, VMSVGACMDBUF, nodeBuffer)
    5245     {
    5246         RTListNodeRemove(&pIter->nodeBuffer);
    5247         vmsvgaR3CmdBufWriteStatus(pDevIns, pIter->GCPhysCB, SVGA_CB_STATUS_PREEMPTED, 0);
    5248         vmsvgaR3CmdBufFree(pIter);
    5249     }
    5250 
    5251     return SVGA_CB_STATUS_COMPLETED;
    5252 }
    5253 
    5254 
    5255 /** @def VMSVGA_INC_CMD_SIZE_BREAK
    5256  * Increments the size of the command cbCmd by a_cbMore.
    5257  * Checks that the command buffer has at least cbCmd bytes. Will break out of the switch if it doesn't.
    5258  * Used by vmsvgaR3CmdBufProcessDC and vmsvgaR3CmdBufProcessCommands.
    5259  */
    5260 #define VMSVGA_INC_CMD_SIZE_BREAK(a_cbMore) \
    5261      if (1) { \
    5262           cbCmd += (a_cbMore); \
    5263           ASSERT_GUEST_MSG_STMT_BREAK(cbRemain >= cbCmd, ("size=%#x remain=%#zx\n", cbCmd, (size_t)cbRemain), CBstatus = SVGA_CB_STATUS_COMMAND_ERROR); \
    5264           RT_UNTRUSTED_VALIDATED_FENCE(); \
    5265      } else do {} while (0)
    5266 
    5267 
    5268 /** Processes Device Context command buffer.
    5269  *
    5270  * @param pDevIns      The device instance.
    5271  * @param pSvgaR3State VMSVGA R3 state.
    5272  * @param pvCommands   Pointer to the command buffer.
    5273  * @param cbCommands   Size of the command buffer.
    5274  * @param poffNextCmd  Where to store the offset of the first unprocessed command.
    5275  * @return SVGACBStatus code.
    5276  * @thread EMT
    5277  */
    5278 static SVGACBStatus vmsvgaR3CmdBufProcessDC(PPDMDEVINS pDevIns, PVMSVGAR3STATE pSvgaR3State, void const *pvCommands, uint32_t cbCommands, uint32_t *poffNextCmd)
    5279 {
    5280     SVGACBStatus CBstatus = SVGA_CB_STATUS_COMPLETED;
    5281 
    5282     uint8_t const *pu8Cmd = (uint8_t *)pvCommands;
    5283     uint32_t cbRemain = cbCommands;
    5284     while (cbRemain)
    5285     {
    5286         /* Command identifier is a 32 bit value. */
    5287         if (cbRemain < sizeof(uint32_t))
    5288         {
    5289             CBstatus = SVGA_CB_STATUS_COMMAND_ERROR;
    5290             break;
    5291         }
    5292 
    5293          /* Fetch the command id. */
    5294         uint32_t const cmdId = *(uint32_t *)pu8Cmd;
    5295         uint32_t cbCmd = sizeof(uint32_t);
    5296         switch (cmdId)
    5297         {
    5298             case SVGA_DC_CMD_NOP:
    5299             {
    5300                 /* NOP */
    5301                 break;
    5302             }
    5303 
    5304             case SVGA_DC_CMD_START_STOP_CONTEXT:
    5305             {
    5306                 SVGADCCmdStartStop *pCmd = (SVGADCCmdStartStop *)&pu8Cmd[cbCmd];
    5307                 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
    5308                 CBstatus = vmsvgaR3CmdBufDCStartStop(pSvgaR3State, pCmd);
    5309                 break;
    5310             }
    5311 
    5312             case SVGA_DC_CMD_PREEMPT:
    5313             {
    5314                 SVGADCCmdPreempt *pCmd = (SVGADCCmdPreempt *)&pu8Cmd[cbCmd];
    5315                 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
    5316                 CBstatus = vmsvgaR3CmdBufDCPreempt(pDevIns, pSvgaR3State, pCmd);
    5317                 break;
    5318             }
    5319 
    5320             default:
    5321             {
    5322                 /* Unsupported command. */
    5323                 CBstatus = SVGA_CB_STATUS_COMMAND_ERROR;
    5324                 break;
    5325             }
    5326         }
    5327 
    5328         if (CBstatus != SVGA_CB_STATUS_COMPLETED)
    5329             break;
    5330 
    5331         pu8Cmd += cbCmd;
    5332         cbRemain -= cbCmd;
    5333     }
    5334 
    5335     Assert(cbRemain <= cbCommands);
    5336     *poffNextCmd = cbCommands - cbRemain;
    5337     return CBstatus;
    5338 }
    5339 
    5340 
    5341 /** Submits a device context command buffer for synchronous processing.
    5342  *
    5343  * @param pDevIns      The device instance.
    5344  * @param pThisCC      The VGA/VMSVGA state for the current context.
    5345  * @param ppCmdBuf     Pointer to the command buffer pointer.
    5346  *                     The function can set the command buffer pointer to NULL to prevent deallocation by the caller.
    5347  * @param poffNextCmd  Where to store the offset of the first unprocessed command.
    5348  * @return SVGACBStatus code.
    5349  * @thread EMT
    5350  */
    5351 static SVGACBStatus vmsvgaR3CmdBufSubmitDC(PPDMDEVINS pDevIns, PVGASTATECC pThisCC, PVMSVGACMDBUF *ppCmdBuf, uint32_t *poffNextCmd)
    5352 {
    5353     /* Synchronously process the device context commands. */
    5354     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    5355     return vmsvgaR3CmdBufProcessDC(pDevIns, pSvgaR3State, (*ppCmdBuf)->pvCommands, (*ppCmdBuf)->hdr.length, poffNextCmd);
    5356 }
    5357 
    5358 /** Submits a command buffer for asynchronous processing by the FIFO thread.
    5359  *
    5360  * @param pDevIns      The device instance.
    5361  * @param pThis        The shared VGA/VMSVGA state.
    5362  * @param pThisCC      The VGA/VMSVGA state for the current context.
    5363  * @param ppCmdBuf     Pointer to the command buffer pointer.
    5364  *                     The function can set the command buffer pointer to NULL to prevent deallocation by the caller.
    5365  * @return SVGACBStatus code.
    5366  * @thread EMT
    5367  */
    5368 static SVGACBStatus vmsvgaR3CmdBufSubmit(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, PVMSVGACMDBUF *ppCmdBuf)
    5369 {
    5370     /* Command buffer submission. */
    5371     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    5372 
    5373     SVGACBStatus CBstatus = SVGA_CB_STATUS_NONE;
    5374 
    5375     PVMSVGACMDBUF const pCmdBuf = *ppCmdBuf;
    5376     PVMSVGACMDBUFCTX const pCmdBufCtx = pCmdBuf->pCmdBufCtx;
    5377 
    5378     int rc = RTCritSectEnter(&pSvgaR3State->CritSectCmdBuf);
    5379     AssertRC(rc);
    5380 
    5381     if (RT_LIKELY(pCmdBufCtx->cSubmitted < SVGA_CB_MAX_QUEUED_PER_CONTEXT))
    5382     {
    5383         RTListAppend(&pCmdBufCtx->listSubmitted, &pCmdBuf->nodeBuffer);
    5384         ++pCmdBufCtx->cSubmitted;
    5385         *ppCmdBuf = NULL; /* Consume the buffer. */
    5386         ASMAtomicWriteU32(&pThisCC->svga.pSvgaR3State->fCmdBuf, 1);
    5387     }
    5388     else
    5389         CBstatus = SVGA_CB_STATUS_QUEUE_FULL;
    5390 
    5391     RTCritSectLeave(&pSvgaR3State->CritSectCmdBuf);
    5392 
    5393     /* Inform the FIFO thread. */
    5394     if (*ppCmdBuf == NULL)
    5395         PDMDevHlpSUPSemEventSignal(pDevIns, pThis->svga.hFIFORequestSem);
    5396 
    5397     return CBstatus;
    5398 }
    5399 
    5400 
    5401 /** SVGA_REG_COMMAND_LOW write handler.
    5402  * Submits a command buffer to the FIFO thread or processes a device context command.
    5403  *
    5404  * @param pDevIns     The device instance.
    5405  * @param pThis       The shared VGA/VMSVGA state.
    5406  * @param pThisCC     The VGA/VMSVGA state for the current context.
    5407  * @param GCPhysCB    Guest physical address of the command buffer header.
    5408  * @param CBCtx       Context the command buffer is submitted to.
    5409  * @thread EMT
    5410  */
    5411 static void vmsvgaR3CmdBufSubmit(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, RTGCPHYS GCPhysCB, SVGACBContext CBCtx)
    5412 {
    5413     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    5414 
    5415     SVGACBStatus CBstatus = SVGA_CB_STATUS_NONE;
    5416     uint32_t offNextCmd = 0;
    5417     uint32_t fIRQ = 0;
    5418 
    5419     /* Get the context if the device has the capability. */
    5420     PVMSVGACMDBUFCTX pCmdBufCtx = NULL;
    5421     if (pThis->svga.u32DeviceCaps & SVGA_CAP_COMMAND_BUFFERS)
    5422     {
    5423         if (RT_LIKELY(CBCtx < RT_ELEMENTS(pSvgaR3State->apCmdBufCtxs)))
    5424             pCmdBufCtx = pSvgaR3State->apCmdBufCtxs[CBCtx];
    5425         else if (CBCtx == SVGA_CB_CONTEXT_DEVICE)
    5426             pCmdBufCtx = &pSvgaR3State->CmdBufCtxDC;
    5427         RT_UNTRUSTED_VALIDATED_FENCE();
    5428     }
    5429 
    5430     /* Allocate a new command buffer. */
    5431     PVMSVGACMDBUF pCmdBuf = vmsvgaR3CmdBufAlloc(pCmdBufCtx);
    5432     if (RT_LIKELY(pCmdBuf))
    5433     {
    5434         pCmdBuf->GCPhysCB = GCPhysCB;
    5435 
    5436         int rc = PDMDevHlpPhysRead(pDevIns, GCPhysCB, &pCmdBuf->hdr, sizeof(pCmdBuf->hdr));
    5437         if (RT_SUCCESS(rc))
    5438         {
    5439             /* Verify the command buffer header. */
    5440             if (RT_LIKELY(   pCmdBuf->hdr.status == SVGA_CB_STATUS_NONE
    5441                           && (pCmdBuf->hdr.flags & ~(SVGA_CB_FLAG_NO_IRQ)) == 0 /* No unexpected flags. */
    5442                           && pCmdBuf->hdr.length <= SVGA_CB_MAX_SIZE))
    5443             {
    5444                 RT_UNTRUSTED_VALIDATED_FENCE();
    5445 
    5446                 /* Read the command buffer content. */
    5447                 pCmdBuf->pvCommands = RTMemAlloc(pCmdBuf->hdr.length);
    5448                 if (pCmdBuf->pvCommands)
    5449                 {
    5450                     RTGCPHYS const GCPhysCmd = (RTGCPHYS)pCmdBuf->hdr.ptr.pa;
    5451                     rc = PDMDevHlpPhysRead(pDevIns, GCPhysCmd, pCmdBuf->pvCommands, pCmdBuf->hdr.length);
    5452                     if (RT_SUCCESS(rc))
    5453                     {
    5454                         /* Submit the buffer. Device context buffers will be processed synchronously. */
    5455                         if (RT_LIKELY(CBCtx < RT_ELEMENTS(pSvgaR3State->apCmdBufCtxs)))
    5456                             /* This usually processes the CB async and sets pCmbBuf to NULL. */
    5457                             CBstatus = vmsvgaR3CmdBufSubmit(pDevIns, pThis, pThisCC, &pCmdBuf);
    5458                         else
    5459                             CBstatus = vmsvgaR3CmdBufSubmitDC(pDevIns, pThisCC, &pCmdBuf, &offNextCmd);
    5460                     }
    5461                     else
    5462                     {
    5463                         ASSERT_GUEST_MSG_FAILED(("Failed to read commands at %RGp\n", GCPhysCmd));
    5464                         CBstatus = SVGA_CB_STATUS_CB_HEADER_ERROR;
    5465                         fIRQ = SVGA_IRQFLAG_ERROR | SVGA_IRQFLAG_COMMAND_BUFFER;
    5466                     }
    5467                 }
    5468                 else
    5469                 {
    5470                     /* No memory for commands. */
    5471                     CBstatus = SVGA_CB_STATUS_QUEUE_FULL;
    5472                 }
    5473             }
    5474             else
    5475             {
    5476                 ASSERT_GUEST_MSG_FAILED(("Invalid buffer header\n"));
    5477                 CBstatus = SVGA_CB_STATUS_CB_HEADER_ERROR;
    5478                 fIRQ = SVGA_IRQFLAG_ERROR | SVGA_IRQFLAG_COMMAND_BUFFER;
    5479             }
    5480         }
    5481         else
    5482         {
    5483             LogFunc(("Failed to read buffer header at %RGp\n", GCPhysCB));
    5484             ASSERT_GUEST_FAILED();
    5485             /* Do not attempt to write the status. */
    5486         }
    5487 
    5488         /* Free the buffer if pfnCmdBufSubmit did not consume it. */
    5489         vmsvgaR3CmdBufFree(pCmdBuf);
    5490     }
    5491     else
    5492     {
    5493         LogFunc(("Can't allocate buffer for context id %#x\n", CBCtx));
    5494         ASSERT_GUEST_FAILED();
    5495         CBstatus = SVGA_CB_STATUS_QUEUE_FULL;
    5496     }
    5497 
    5498     if (CBstatus != SVGA_CB_STATUS_NONE)
    5499     {
    5500         LogFunc(("Write status %#x, offNextCmd %#x (of %#x), fIRQ %#x\n", CBstatus, offNextCmd, pCmdBuf->hdr.length, fIRQ));
    5501         vmsvgaR3CmdBufWriteStatus(pDevIns, GCPhysCB, CBstatus, offNextCmd);
    5502         if (fIRQ)
    5503             vmsvgaR3CmdBufRaiseIRQ(pDevIns, pThis, fIRQ);
    5504     }
    5505 }
    5506 
    5507 
    5508 /** Checks if there are some buffers to be processed.
    5509  *
    5510  * @param pThisCC     The VGA/VMSVGA state for the current context.
    5511  * @return true if buffers must be processed.
    5512  * @thread FIFO
    5513  */
    5514 static bool vmsvgaR3CmdBufHasWork(PVGASTATECC pThisCC)
    5515 {
    5516     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    5517     return RT_BOOL(ASMAtomicReadU32(&pSvgaR3State->fCmdBuf));
    5518 }
    5519 
    5520 
    5521 /** Processes a command buffer.
    5522  *
    5523  * @param pDevIns      The device instance.
    5524  * @param pThis        The shared VGA/VMSVGA state.
    5525  * @param pThisCC      The VGA/VMSVGA state for the current context.
    5526  * @param pvCommands   Pointer to the command buffer.
    5527  * @param cbCommands   Size of the command buffer.
    5528  * @param poffNextCmd  Where to store the offset of the first unprocessed command.
    5529  * @return SVGACBStatus code.
    5530  * @thread FIFO
    5531  */
    5532 static SVGACBStatus vmsvgaR3CmdBufProcessCommands(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, void const *pvCommands, uint32_t cbCommands, uint32_t *poffNextCmd)
    5533 {
    5534     SVGACBStatus CBstatus = SVGA_CB_STATUS_COMPLETED;
    5535     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    5536 
    5537     uint32_t RT_UNTRUSTED_VOLATILE_GUEST * const pFIFO = pThisCC->svga.pau32FIFO;
    5538 
    5539     uint8_t const *pu8Cmd = (uint8_t *)pvCommands;
    5540     uint32_t cbRemain = cbCommands;
    5541     while (cbRemain)
    5542     {
    5543         /* Command identifier is a 32 bit value. */
    5544         if (cbRemain < sizeof(uint32_t))
    5545         {
    5546             CBstatus = SVGA_CB_STATUS_COMMAND_ERROR;
    5547             break;
    5548         }
    5549 
    5550         /* Fetch the command id.
    5551          * 'cmdId' is actually a SVGAFifoCmdId. It is treated as uint32_t in order to avoid a compiler
    5552          * warning. Because we support some obsolete and deprecated commands, which are not included in
    5553          * the SVGAFifoCmdId enum in the VMSVGA headers anymore.
    5554          */
    5555         uint32_t const cmdId = *(uint32_t *)pu8Cmd;
    5556         uint32_t cbCmd = sizeof(uint32_t);
    5557 
    5558         LogFlowFunc(("%s %d\n", vmsvgaR3FifoCmdToString(cmdId), cmdId));
    5559 
    5560         /* At the end of the switch cbCmd is equal to the total length of the command including the cmdId.
    5561          * I.e. pu8Cmd + cbCmd must point to the next command.
    5562          * However if CBstatus is set to anything but SVGA_CB_STATUS_COMPLETED in the switch, then
    5563          * the cbCmd value is ignored (and pu8Cmd still points to the failed command).
    5564          */
    5565         /** @todo This code is very similar to the FIFO loop command processing. Think about merging. */
    5566         switch (cmdId)
    5567         {
    5568             case SVGA_CMD_INVALID_CMD:
    5569             {
    5570                 /* Nothing to do. */
    5571                 STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdInvalidCmd);
    5572                 break;
    5573             }
    5574 
    5575             case SVGA_CMD_FENCE:
    5576             {
    5577                 SVGAFifoCmdFence *pCmd = (SVGAFifoCmdFence *)&pu8Cmd[cbCmd];
    5578                 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
    5579                 STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdFence);
    5580                 Log(("SVGA_CMD_FENCE %#x\n", pCmd->fence));
    5581 
    5582                 uint32_t const offFifoMin = pFIFO[SVGA_FIFO_MIN];
    5583                 if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_FENCE, offFifoMin))
    5584                 {
    5585                     pFIFO[SVGA_FIFO_FENCE] = pCmd->fence;
    5586 
    5587                     uint32_t u32IrqStatus = 0;
    5588                     if (pThis->svga.u32IrqMask & SVGA_IRQFLAG_ANY_FENCE)
    5589                     {
    5590                         Log(("any fence irq\n"));
    5591                         u32IrqStatus |= SVGA_IRQFLAG_ANY_FENCE;
    5592                     }
    5593                     else if (    VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_FENCE_GOAL, offFifoMin)
    5594                              &&  (pThis->svga.u32IrqMask & SVGA_IRQFLAG_FENCE_GOAL)
    5595                              &&  pFIFO[SVGA_FIFO_FENCE_GOAL] == pCmd->fence)
    5596                     {
    5597                         Log(("fence goal reached irq (fence=%#x)\n", pCmd->fence));
    5598                         u32IrqStatus |= SVGA_IRQFLAG_FENCE_GOAL;
    5599                     }
    5600 
    5601                     if (u32IrqStatus)
    5602                         vmsvgaR3CmdBufRaiseIRQ(pDevIns, pThis, u32IrqStatus);
    5603                 }
    5604                 else
    5605                     Log(("SVGA_CMD_FENCE is bogus when offFifoMin is %#x!\n", offFifoMin));
    5606                 break;
    5607             }
    5608 
    5609             case SVGA_CMD_UPDATE:
    5610             {
    5611                 SVGAFifoCmdUpdate *pCmd = (SVGAFifoCmdUpdate *)&pu8Cmd[cbCmd];
    5612                 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
    5613                 vmsvgaR3CmdUpdate(pThis, pThisCC, pCmd);
    5614                 break;
    5615             }
    5616 
    5617             case SVGA_CMD_UPDATE_VERBOSE:
    5618             {
    5619                 SVGAFifoCmdUpdateVerbose *pCmd = (SVGAFifoCmdUpdateVerbose *)&pu8Cmd[cbCmd];
    5620                 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
    5621                 vmsvgaR3CmdUpdateVerbose(pThis, pThisCC, pCmd);
    5622                 break;
    5623             }
    5624 
    5625             case SVGA_CMD_DEFINE_CURSOR:
    5626             {
    5627                 /* Followed by bitmap data. */
    5628                 SVGAFifoCmdDefineCursor *pCmd = (SVGAFifoCmdDefineCursor *)&pu8Cmd[cbCmd];
    5629                 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
    5630 
    5631                 /* Figure out the size of the bitmap data. */
    5632                 ASSERT_GUEST_STMT_BREAK(pCmd->height < 2048 && pCmd->width < 2048, CBstatus = SVGA_CB_STATUS_COMMAND_ERROR);
    5633                 ASSERT_GUEST_STMT_BREAK(pCmd->andMaskDepth <= 32, CBstatus = SVGA_CB_STATUS_COMMAND_ERROR);
    5634                 ASSERT_GUEST_STMT_BREAK(pCmd->xorMaskDepth <= 32, CBstatus = SVGA_CB_STATUS_COMMAND_ERROR);
    5635                 RT_UNTRUSTED_VALIDATED_FENCE();
    5636 
    5637                 uint32_t const cbAndLine = RT_ALIGN_32(pCmd->width * (pCmd->andMaskDepth + (pCmd->andMaskDepth == 15)), 32) / 8;
    5638                 uint32_t const cbAndMask = cbAndLine * pCmd->height;
    5639                 uint32_t const cbXorLine = RT_ALIGN_32(pCmd->width * (pCmd->xorMaskDepth + (pCmd->xorMaskDepth == 15)), 32) / 8;
    5640                 uint32_t const cbXorMask = cbXorLine * pCmd->height;
    5641 
    5642                 VMSVGA_INC_CMD_SIZE_BREAK(cbAndMask + cbXorMask);
    5643                 vmsvgaR3CmdDefineCursor(pThis, pThisCC, pCmd);
    5644                 break;
    5645             }
    5646 
    5647             case SVGA_CMD_DEFINE_ALPHA_CURSOR:
    5648             {
    5649                 /* Followed by bitmap data. */
    5650                 SVGAFifoCmdDefineAlphaCursor *pCmd = (SVGAFifoCmdDefineAlphaCursor *)&pu8Cmd[cbCmd];
    5651                 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
    5652 
    5653                 /* Figure out the size of the bitmap data. */
    5654                 ASSERT_GUEST_STMT_BREAK(pCmd->height < 2048 && pCmd->width < 2048, CBstatus = SVGA_CB_STATUS_COMMAND_ERROR);
    5655 
    5656                 VMSVGA_INC_CMD_SIZE_BREAK(pCmd->width * pCmd->height * sizeof(uint32_t)); /* 32-bit BRGA format */
    5657                 vmsvgaR3CmdDefineAlphaCursor(pThis, pThisCC, pCmd);
    5658                 break;
    5659             }
    5660 
    5661             case SVGA_CMD_MOVE_CURSOR:
    5662             {
    5663                 /* Deprecated; there should be no driver which *requires* this command. However, if
    5664                  * we do ecncounter this command, it might be useful to not get the FIFO completely out of
    5665                  * alignment.
    5666                  * May be issued by guest if SVGA_CAP_CURSOR_BYPASS is missing.
    5667                  */
    5668                 SVGAFifoCmdMoveCursor *pCmd = (SVGAFifoCmdMoveCursor *)&pu8Cmd[cbCmd];
    5669                 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
    5670                 vmsvgaR3CmdMoveCursor(pThis, pThisCC, pCmd);
    5671                 break;
    5672             }
    5673 
    5674             case SVGA_CMD_DISPLAY_CURSOR:
    5675             {
    5676                 /* Deprecated; there should be no driver which *requires* this command. However, if
    5677                  * we do ecncounter this command, it might be useful to not get the FIFO completely out of
    5678                  * alignment.
    5679                  * May be issued by guest if SVGA_CAP_CURSOR_BYPASS is missing.
    5680                  */
    5681                 SVGAFifoCmdDisplayCursor *pCmd = (SVGAFifoCmdDisplayCursor *)&pu8Cmd[cbCmd];
    5682                 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
    5683                 vmsvgaR3CmdDisplayCursor(pThis, pThisCC, pCmd);
    5684                 break;
    5685             }
    5686 
    5687             case SVGA_CMD_RECT_FILL:
    5688             {
    5689                 SVGAFifoCmdRectFill *pCmd = (SVGAFifoCmdRectFill *)&pu8Cmd[cbCmd];
    5690                 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
    5691                 vmsvgaR3CmdRectFill(pThis, pThisCC, pCmd);
    5692                 break;
    5693             }
    5694 
    5695             case SVGA_CMD_RECT_COPY:
    5696             {
    5697                 SVGAFifoCmdRectCopy *pCmd = (SVGAFifoCmdRectCopy *)&pu8Cmd[cbCmd];
    5698                 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
    5699                 vmsvgaR3CmdRectCopy(pThis, pThisCC, pCmd);
    5700                 break;
    5701             }
    5702 
    5703             case SVGA_CMD_RECT_ROP_COPY:
    5704             {
    5705                 SVGAFifoCmdRectRopCopy *pCmd = (SVGAFifoCmdRectRopCopy *)&pu8Cmd[cbCmd];
    5706                 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
    5707                 vmsvgaR3CmdRectRopCopy(pThis, pThisCC, pCmd);
    5708                 break;
    5709             }
    5710 
    5711             case SVGA_CMD_ESCAPE:
    5712             {
    5713                 /* Followed by 'size' bytes of data. */
    5714                 SVGAFifoCmdEscape *pCmd = (SVGAFifoCmdEscape *)&pu8Cmd[cbCmd];
    5715                 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
    5716 
    5717                 ASSERT_GUEST_STMT_BREAK(pCmd->size < pThis->svga.cbFIFO - sizeof(SVGAFifoCmdEscape), CBstatus = SVGA_CB_STATUS_COMMAND_ERROR);
    5718                 RT_UNTRUSTED_VALIDATED_FENCE();
    5719 
    5720                 VMSVGA_INC_CMD_SIZE_BREAK(pCmd->size);
    5721                 vmsvgaR3CmdEscape(pThis, pThisCC, pCmd);
    5722                 break;
    5723             }
    5724 # ifdef VBOX_WITH_VMSVGA3D
    5725             case SVGA_CMD_DEFINE_GMR2:
    5726             {
    5727                 SVGAFifoCmdDefineGMR2 *pCmd = (SVGAFifoCmdDefineGMR2 *)&pu8Cmd[cbCmd];
    5728                 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
    5729                 vmsvgaR3CmdDefineGMR2(pThis, pThisCC, pCmd);
    5730                 break;
    5731             }
    5732 
    5733             case SVGA_CMD_REMAP_GMR2:
    5734             {
    5735                 /* Followed by page descriptors or guest ptr. */
    5736                 SVGAFifoCmdRemapGMR2 *pCmd = (SVGAFifoCmdRemapGMR2 *)&pu8Cmd[cbCmd];
    5737                 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
    5738 
    5739                 /* Calculate the size of what comes after next and fetch it. */
    5740                 uint32_t cbMore = 0;
    5741                 if (pCmd->flags & SVGA_REMAP_GMR2_VIA_GMR)
    5742                     cbMore = sizeof(SVGAGuestPtr);
    5743                 else
    5744                 {
    5745                     uint32_t const cbPageDesc = (pCmd->flags & SVGA_REMAP_GMR2_PPN64) ? sizeof(uint64_t) : sizeof(uint32_t);
    5746                     if (pCmd->flags & SVGA_REMAP_GMR2_SINGLE_PPN)
    5747                     {
    5748                         cbMore         = cbPageDesc;
    5749                         pCmd->numPages = 1;
    5750                     }
    5751                     else
    5752                     {
    5753                         ASSERT_GUEST_STMT_BREAK(pCmd->numPages <= pThis->svga.cbFIFO / cbPageDesc, CBstatus = SVGA_CB_STATUS_COMMAND_ERROR);
    5754                         cbMore = cbPageDesc * pCmd->numPages;
    5755                     }
    5756                 }
    5757                 VMSVGA_INC_CMD_SIZE_BREAK(cbMore);
    5758                 vmsvgaR3CmdRemapGMR2(pThis, pThisCC, pCmd);
    5759 #  ifdef DEBUG_GMR_ACCESS
    5760                 VMR3ReqCallWaitU(PDMDevHlpGetUVM(pDevIns), VMCPUID_ANY, (PFNRT)vmsvgaR3RegisterGmr, 2, pDevIns, pCmd->gmrId);
    5761 #  endif
    5762                 break;
    5763             }
    5764 # endif // VBOX_WITH_VMSVGA3D
    5765             case SVGA_CMD_DEFINE_SCREEN:
    5766             {
    5767                 /* The size of this command is specified by the guest and depends on capabilities. */
    5768                 SVGAFifoCmdDefineScreen *pCmd = (SVGAFifoCmdDefineScreen *)&pu8Cmd[cbCmd];
    5769                 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(pCmd->screen.structSize));
    5770                 ASSERT_GUEST_STMT_BREAK(pCmd->screen.structSize < pThis->svga.cbFIFO, CBstatus = SVGA_CB_STATUS_COMMAND_ERROR);
    5771                 RT_UNTRUSTED_VALIDATED_FENCE();
    5772 
    5773                 VMSVGA_INC_CMD_SIZE_BREAK(RT_MAX(sizeof(pCmd->screen.structSize), pCmd->screen.structSize) - sizeof(pCmd->screen.structSize));
    5774                 vmsvgaR3CmdDefineScreen(pThis, pThisCC, pCmd);
    5775                 break;
    5776             }
    5777 
    5778             case SVGA_CMD_DESTROY_SCREEN:
    5779             {
    5780                 SVGAFifoCmdDestroyScreen *pCmd = (SVGAFifoCmdDestroyScreen *)&pu8Cmd[cbCmd];
    5781                 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
    5782                 vmsvgaR3CmdDestroyScreen(pThis, pThisCC, pCmd);
    5783                 break;
    5784             }
    5785 
    5786             case SVGA_CMD_DEFINE_GMRFB:
    5787             {
    5788                 SVGAFifoCmdDefineGMRFB *pCmd = (SVGAFifoCmdDefineGMRFB *)&pu8Cmd[cbCmd];
    5789                 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
    5790                 vmsvgaR3CmdDefineGMRFB(pThis, pThisCC, pCmd);
    5791                 break;
    5792             }
    5793 
    5794             case SVGA_CMD_BLIT_GMRFB_TO_SCREEN:
    5795             {
    5796                 SVGAFifoCmdBlitGMRFBToScreen *pCmd = (SVGAFifoCmdBlitGMRFBToScreen *)&pu8Cmd[cbCmd];
    5797                 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
    5798                 vmsvgaR3CmdBlitGMRFBToScreen(pThis, pThisCC, pCmd);
    5799                 break;
    5800             }
    5801 
    5802             case SVGA_CMD_BLIT_SCREEN_TO_GMRFB:
    5803             {
    5804                 SVGAFifoCmdBlitScreenToGMRFB *pCmd = (SVGAFifoCmdBlitScreenToGMRFB *)&pu8Cmd[cbCmd];
    5805                 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
    5806                 vmsvgaR3CmdBlitScreenToGMRFB(pThis, pThisCC, pCmd);
    5807                 break;
    5808             }
    5809 
    5810             case SVGA_CMD_ANNOTATION_FILL:
    5811             {
    5812                 SVGAFifoCmdAnnotationFill *pCmd = (SVGAFifoCmdAnnotationFill *)&pu8Cmd[cbCmd];
    5813                 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
    5814                 vmsvgaR3CmdAnnotationFill(pThis, pThisCC, pCmd);
    5815                 break;
    5816             }
    5817 
    5818             case SVGA_CMD_ANNOTATION_COPY:
    5819             {
    5820                 SVGAFifoCmdAnnotationCopy *pCmd = (SVGAFifoCmdAnnotationCopy *)&pu8Cmd[cbCmd];
    5821                 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
    5822                 vmsvgaR3CmdAnnotationCopy(pThis, pThisCC, pCmd);
    5823                 break;
    5824             }
    5825 
    5826             default:
    5827             {
    5828 # ifdef VBOX_WITH_VMSVGA3D
    5829                 if (   cmdId >= SVGA_3D_CMD_BASE
    5830                     && cmdId <  SVGA_3D_CMD_MAX)
    5831                 {
    5832                     RT_UNTRUSTED_VALIDATED_FENCE();
    5833 
    5834                     /* All 3d commands start with a common header, which defines the identifier and the size
    5835                      * of the command. The identifier has been already read. Fetch the size.
    5836                      */
    5837                     uint32_t const *pcbMore = (uint32_t const *)&pu8Cmd[cbCmd];
    5838                     VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pcbMore));
    5839                     VMSVGA_INC_CMD_SIZE_BREAK(*pcbMore);
    5840                     if (RT_LIKELY(pThis->svga.f3DEnabled))
    5841                     { /* likely */ }
    5842                     else
    5843                     {
    5844                         LogRelMax(8, ("VMSVGA: 3D disabled, command %d skipped\n", cmdId));
    5845                         break;
    5846                     }
    5847 
    5848                     /* Command data begins after the 32 bit command length. */
    5849                     int rc = vmsvgaR3Process3dCmd(pThis, pThisCC, (SVGAFifo3dCmdId)cmdId, *pcbMore, pcbMore + 1);
    5850                     if (RT_SUCCESS(rc))
    5851                     { /* likely */ }
    5852                     else
    5853                     {
    5854                         CBstatus = SVGA_CB_STATUS_COMMAND_ERROR;
    5855                         break;
    5856                     }
    5857                 }
    5858                 else
    5859 # endif // VBOX_WITH_VMSVGA3D
    5860                 {
    5861                     /* Unsupported command. */
    5862                     STAM_REL_COUNTER_INC(&pSvgaR3State->StatFifoUnkCmds);
    5863                     ASSERT_GUEST_MSG_FAILED(("cmdId=%d\n", cmdId));
    5864                     CBstatus = SVGA_CB_STATUS_COMMAND_ERROR;
    5865                     break;
    5866                 }
    5867             }
    5868         }
    5869 
    5870         if (CBstatus != SVGA_CB_STATUS_COMPLETED)
    5871             break;
    5872 
    5873         pu8Cmd += cbCmd;
    5874         cbRemain -= cbCmd;
    5875     }
    5876 
    5877     Assert(cbRemain <= cbCommands);
    5878     *poffNextCmd = cbCommands - cbRemain;
    5879     return CBstatus;
    5880 }
    5881 
    5882 
    5883 /** Process command buffers.
    5884  *
    5885  * @param pDevIns     The device instance.
    5886  * @param pThis       The shared VGA/VMSVGA state.
    5887  * @param pThisCC     The VGA/VMSVGA state for the current context.
    5888  * @param pThread     Handle of the FIFO thread.
    5889  * @thread FIFO
    5890  */
    5891 static void vmsvgaR3CmdBufProcessBuffers(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, PPDMTHREAD pThread)
    5892 {
    5893     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    5894 
    5895     for (;;)
    5896     {
    5897         if (pThread->enmState != PDMTHREADSTATE_RUNNING)
    5898             break;
    5899 
    5900         /* See if there is a submitted buffer. */
    5901         PVMSVGACMDBUF pCmdBuf = NULL;
    5902 
    5903         int rc = RTCritSectEnter(&pSvgaR3State->CritSectCmdBuf);
    5904         AssertRC(rc);
    5905 
    5906         /* It seems that a higher queue index has a higher priority.
    5907          * See SVGACBContext in svga_reg.h from latest vmwgfx Linux driver.
    5908          */
    5909         for (unsigned i = RT_ELEMENTS(pSvgaR3State->apCmdBufCtxs); i > 0; --i)
    5910         {
    5911             PVMSVGACMDBUFCTX pCmdBufCtx = pSvgaR3State->apCmdBufCtxs[i - 1];
    5912             if (pCmdBufCtx)
    5913             {
    5914                 pCmdBuf = RTListRemoveFirst(&pCmdBufCtx->listSubmitted, VMSVGACMDBUF, nodeBuffer);
    5915                 if (pCmdBuf)
    5916                 {
    5917                     Assert(pCmdBufCtx->cSubmitted > 0);
    5918                     --pCmdBufCtx->cSubmitted;
    5919                     break;
    5920                 }
    5921             }
    5922         }
    5923 
    5924         if (!pCmdBuf)
    5925         {
    5926             ASMAtomicWriteU32(&pSvgaR3State->fCmdBuf, 0);
    5927             RTCritSectLeave(&pSvgaR3State->CritSectCmdBuf);
    5928             break;
    5929         }
    5930 
    5931         RTCritSectLeave(&pSvgaR3State->CritSectCmdBuf);
    5932 
    5933         SVGACBStatus CBstatus = SVGA_CB_STATUS_NONE;
    5934         uint32_t offNextCmd = 0;
    5935 
    5936         /* Process one buffer. */
    5937         CBstatus = vmsvgaR3CmdBufProcessCommands(pDevIns, pThis, pThisCC, pCmdBuf->pvCommands, pCmdBuf->hdr.length, &offNextCmd);
    5938 
    5939         uint32_t fIRQ = 0;
    5940         if (!RT_BOOL(pCmdBuf->hdr.flags & SVGA_CB_FLAG_NO_IRQ))
    5941             fIRQ |= SVGA_IRQFLAG_COMMAND_BUFFER;
    5942         if (CBstatus == SVGA_CB_STATUS_COMMAND_ERROR)
    5943             fIRQ |= SVGA_IRQFLAG_ERROR;
    5944 
    5945         vmsvgaR3CmdBufWriteStatus(pDevIns, pCmdBuf->GCPhysCB, CBstatus, offNextCmd);
    5946         if (fIRQ)
    5947             vmsvgaR3CmdBufRaiseIRQ(pDevIns, pThis, fIRQ);
    5948 
    5949         vmsvgaR3CmdBufFree(pCmdBuf);
    5950     }
    5951 }
    5952 
    5953 
    5954 /**
    5955  * Worker for vmsvgaR3FifoThread that handles an external command.
    5956  *
    5957  * @param   pDevIns         The device instance.
    5958  * @param   pThis           The shared VGA/VMSVGA instance data.
    5959  * @param   pThisCC         The VGA/VMSVGA state for ring-3.
    5960  */
    5961 static void vmsvgaR3FifoHandleExtCmd(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC)
    5962 {
    5963     uint8_t uExtCmd = pThis->svga.u8FIFOExtCommand;
    5964     switch (pThis->svga.u8FIFOExtCommand)
    5965     {
    5966         case VMSVGA_FIFO_EXTCMD_RESET:
    5967             Log(("vmsvgaR3FifoLoop: reset the fifo thread.\n"));
    5968             Assert(pThisCC->svga.pvFIFOExtCmdParam == NULL);
    5969 
    5970             vmsvgaR3ResetScreens(pThis, pThisCC);
    5971 # ifdef VBOX_WITH_VMSVGA3D
    5972             if (pThis->svga.f3DEnabled)
    5973             {
    5974                 /* The 3d subsystem must be reset from the fifo thread. */
    5975                 vmsvga3dReset(pThisCC);
    5976             }
    5977 # endif
    5978             break;
    5979 
    5980         case VMSVGA_FIFO_EXTCMD_POWEROFF:
    5981             Log(("vmsvgaR3FifoLoop: power off.\n"));
    5982             Assert(pThisCC->svga.pvFIFOExtCmdParam == NULL);
    5983 
    5984             /* The screens must be reset on the FIFO thread, because they may use 3D resources. */
    5985             vmsvgaR3ResetScreens(pThis, pThisCC);
    5986             break;
    5987 
    5988         case VMSVGA_FIFO_EXTCMD_TERMINATE:
    5989             Log(("vmsvgaR3FifoLoop: terminate the fifo thread.\n"));
    5990             Assert(pThisCC->svga.pvFIFOExtCmdParam == NULL);
    5991 # ifdef VBOX_WITH_VMSVGA3D
    5992             if (pThis->svga.f3DEnabled)
    5993             {
    5994                 /* The 3d subsystem must be shut down from the fifo thread. */
    5995                 vmsvga3dTerminate(pThisCC);
    5996             }
    5997 # endif
    5998             break;
    5999 
    6000         case VMSVGA_FIFO_EXTCMD_SAVESTATE:
    6001         {
    6002             Log(("vmsvgaR3FifoLoop: VMSVGA_FIFO_EXTCMD_SAVESTATE.\n"));
    6003             PSSMHANDLE pSSM = (PSSMHANDLE)pThisCC->svga.pvFIFOExtCmdParam;
    6004             AssertLogRelMsgBreak(RT_VALID_PTR(pSSM), ("pSSM=%p\n", pSSM));
    6005             vmsvgaR3SaveExecFifo(pDevIns->pHlpR3, pThisCC, pSSM);
    6006 # ifdef VBOX_WITH_VMSVGA3D
    6007             if (pThis->svga.f3DEnabled)
    6008                 vmsvga3dSaveExec(pDevIns, pThisCC, pSSM);
    6009 # endif
    6010             break;
    6011         }
    6012 
    6013         case VMSVGA_FIFO_EXTCMD_LOADSTATE:
    6014         {
    6015             Log(("vmsvgaR3FifoLoop: VMSVGA_FIFO_EXTCMD_LOADSTATE.\n"));
    6016             PVMSVGA_STATE_LOAD pLoadState = (PVMSVGA_STATE_LOAD)pThisCC->svga.pvFIFOExtCmdParam;
    6017             AssertLogRelMsgBreak(RT_VALID_PTR(pLoadState), ("pLoadState=%p\n", pLoadState));
    6018             vmsvgaR3LoadExecFifo(pDevIns->pHlpR3, pThis, pThisCC, pLoadState->pSSM, pLoadState->uVersion, pLoadState->uPass);
    6019 # ifdef VBOX_WITH_VMSVGA3D
    6020             if (pThis->svga.f3DEnabled)
    6021                 vmsvga3dLoadExec(pDevIns, pThis, pThisCC, pLoadState->pSSM, pLoadState->uVersion, pLoadState->uPass);
    6022 # endif
    6023             break;
    6024         }
    6025 
    6026         case VMSVGA_FIFO_EXTCMD_UPDATE_SURFACE_HEAP_BUFFERS:
    6027         {
    6028 # ifdef VBOX_WITH_VMSVGA3D
    6029             uint32_t sid = (uint32_t)(uintptr_t)pThisCC->svga.pvFIFOExtCmdParam;
    6030             Log(("vmsvgaR3FifoLoop: VMSVGA_FIFO_EXTCMD_UPDATE_SURFACE_HEAP_BUFFERS sid=%#x\n", sid));
    6031             vmsvga3dUpdateHeapBuffersForSurfaces(pThisCC, sid);
    6032 # endif
    6033             break;
    6034         }
    6035 
    6036 
    6037         default:
    6038             AssertLogRelMsgFailed(("uExtCmd=%#x pvFIFOExtCmdParam=%p\n", uExtCmd, pThisCC->svga.pvFIFOExtCmdParam));
    6039             break;
    6040     }
    6041 
    6042     /*
    6043      * Signal the end of the external command.
    6044      */
    6045     pThisCC->svga.pvFIFOExtCmdParam = NULL;
    6046     pThis->svga.u8FIFOExtCommand  = VMSVGA_FIFO_EXTCMD_NONE;
    6047     ASMMemoryFence(); /* paranoia^2 */
    6048     int rc = RTSemEventSignal(pThisCC->svga.hFIFOExtCmdSem);
    6049     AssertLogRelRC(rc);
    6050 }
    6051 
    6052 /**
    6053  * Worker for vmsvgaR3Destruct, vmsvgaR3Reset, vmsvgaR3Save and vmsvgaR3Load for
    6054  * doing a job on the FIFO thread (even when it's officially suspended).
    6055  *
    6056  * @returns VBox status code (fully asserted).
    6057  * @param   pDevIns         The device instance.
    6058  * @param   pThis           The shared VGA/VMSVGA instance data.
    6059  * @param   pThisCC         The VGA/VMSVGA state for ring-3.
    6060  * @param   uExtCmd         The command to execute on the FIFO thread.
    6061  * @param   pvParam         Pointer to command parameters.
    6062  * @param   cMsWait         The time to wait for the command, given in
    6063  *                          milliseconds.
    6064  */
    6065 static int vmsvgaR3RunExtCmdOnFifoThread(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC,
    6066                                          uint8_t uExtCmd, void *pvParam, RTMSINTERVAL cMsWait)
    6067 {
    6068     Assert(cMsWait >= RT_MS_1SEC * 5);
    6069     AssertLogRelMsg(pThis->svga.u8FIFOExtCommand == VMSVGA_FIFO_EXTCMD_NONE,
    6070                     ("old=%d new=%d\n", pThis->svga.u8FIFOExtCommand, uExtCmd));
    6071 
    6072     int rc;
    6073     PPDMTHREAD      pThread  = pThisCC->svga.pFIFOIOThread;
    6074     PDMTHREADSTATE  enmState = pThread->enmState;
    6075     if (enmState == PDMTHREADSTATE_SUSPENDED)
    6076     {
    6077         /*
    6078          * The thread is suspended, we have to temporarily wake it up so it can
    6079          * perform the task.
    6080          * (We ASSUME not racing code here, both wrt thread state and ext commands.)
    6081          */
    6082         Log(("vmsvgaR3RunExtCmdOnFifoThread: uExtCmd=%d enmState=SUSPENDED\n", uExtCmd));
    6083         /* Post the request. */
    6084         pThis->svga.fFifoExtCommandWakeup = true;
    6085         pThisCC->svga.pvFIFOExtCmdParam     = pvParam;
    6086         pThis->svga.u8FIFOExtCommand      = uExtCmd;
    6087         ASMMemoryFence(); /* paranoia^3 */
    6088 
    6089         /* Resume the thread. */
    6090         rc = PDMDevHlpThreadResume(pDevIns, pThread);
    6091         AssertLogRelRC(rc);
    6092         if (RT_SUCCESS(rc))
    6093         {
    6094             /* Wait. Take care in case the semaphore was already posted (same as below). */
    6095             rc = RTSemEventWait(pThisCC->svga.hFIFOExtCmdSem, cMsWait);
    6096             if (   rc == VINF_SUCCESS
    6097                 && pThis->svga.u8FIFOExtCommand == uExtCmd)
    6098                 rc = RTSemEventWait(pThisCC->svga.hFIFOExtCmdSem, cMsWait);
    6099             AssertLogRelMsg(pThis->svga.u8FIFOExtCommand != uExtCmd || RT_FAILURE_NP(rc),
    6100                             ("%#x %Rrc\n", pThis->svga.u8FIFOExtCommand, rc));
    6101 
    6102             /* suspend the thread */
    6103             pThis->svga.fFifoExtCommandWakeup = false;
    6104             int rc2 = PDMDevHlpThreadSuspend(pDevIns, pThread);
    6105             AssertLogRelRC(rc2);
    6106             if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
    6107                 rc = rc2;
    6108         }
    6109         pThis->svga.fFifoExtCommandWakeup = false;
    6110         pThisCC->svga.pvFIFOExtCmdParam     = NULL;
    6111     }
    6112     else if (enmState == PDMTHREADSTATE_RUNNING)
    6113     {
    6114         /*
    6115          * The thread is running, should only happen during reset and vmsvga3dsfc.
    6116          * We ASSUME not racing code here, both wrt thread state and ext commands.
    6117          */
    6118         Log(("vmsvgaR3RunExtCmdOnFifoThread: uExtCmd=%d enmState=RUNNING\n", uExtCmd));
    6119         Assert(uExtCmd == VMSVGA_FIFO_EXTCMD_RESET || uExtCmd == VMSVGA_FIFO_EXTCMD_UPDATE_SURFACE_HEAP_BUFFERS || uExtCmd == VMSVGA_FIFO_EXTCMD_POWEROFF);
    6120 
    6121         /* Post the request. */
    6122         pThisCC->svga.pvFIFOExtCmdParam = pvParam;
    6123         pThis->svga.u8FIFOExtCommand  = uExtCmd;
    6124         ASMMemoryFence(); /* paranoia^2 */
    6125         rc = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->svga.hFIFORequestSem);
    6126         AssertLogRelRC(rc);
    6127 
    6128         /* Wait. Take care in case the semaphore was already posted (same as above). */
    6129         rc = RTSemEventWait(pThisCC->svga.hFIFOExtCmdSem, cMsWait);
    6130         if (   rc == VINF_SUCCESS
    6131             && pThis->svga.u8FIFOExtCommand == uExtCmd)
    6132             rc = RTSemEventWait(pThisCC->svga.hFIFOExtCmdSem, cMsWait); /* it was already posted, retry the wait. */
    6133         AssertLogRelMsg(pThis->svga.u8FIFOExtCommand != uExtCmd || RT_FAILURE_NP(rc),
    6134                         ("%#x %Rrc\n", pThis->svga.u8FIFOExtCommand, rc));
    6135 
    6136         pThisCC->svga.pvFIFOExtCmdParam = NULL;
    6137     }
    6138     else
    6139     {
    6140         /*
    6141          * Something is wrong with the thread!
    6142          */
    6143         AssertLogRelMsgFailed(("uExtCmd=%d enmState=%d\n", uExtCmd, enmState));
    6144         rc = VERR_INVALID_STATE;
    6145     }
    6146     return rc;
    6147 }
    6148 
    6149 
    6150 /**
    6151  * Marks the FIFO non-busy, notifying any waiting EMTs.
    6152  *
    6153  * @param   pDevIns         The device instance.
    6154  * @param   pThis           The shared VGA/VMSVGA instance data.
    6155  * @param   pThisCC         The VGA/VMSVGA state for ring-3.
    6156  * @param   pSVGAState      Pointer to the ring-3 only SVGA state data.
    6157  * @param   offFifoMin      The start byte offset of the command FIFO.
    6158  */
    6159 static void vmsvgaR3FifoSetNotBusy(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, PVMSVGAR3STATE pSVGAState, uint32_t offFifoMin)
    6160 {
    6161     ASMAtomicAndU32(&pThis->svga.fBusy, ~(VMSVGA_BUSY_F_FIFO | VMSVGA_BUSY_F_EMT_FORCE));
    6162     if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_BUSY, offFifoMin))
    6163         vmsvgaHCSafeFifoBusyRegUpdate(pThis, pThisCC, pThis->svga.fBusy != 0);
    6164 
    6165     /* Wake up any waiting EMTs. */
    6166     if (pSVGAState->cBusyDelayedEmts > 0)
    6167     {
    6168 # ifdef VMSVGA_USE_EMT_HALT_CODE
    6169         PVM pVM = PDMDevHlpGetVM(pDevIns);
    6170         VMCPUID idCpu = VMCpuSetFindLastPresentInternal(&pSVGAState->BusyDelayedEmts);
    6171         if (idCpu != NIL_VMCPUID)
    6172         {
    6173             VMR3NotifyCpuDeviceReady(pVM, idCpu);
    6174             while (idCpu-- > 0)
    6175                 if (VMCPUSET_IS_PRESENT(&pSVGAState->BusyDelayedEmts, idCpu))
    6176                     VMR3NotifyCpuDeviceReady(pVM, idCpu);
    6177         }
    6178 # else
    6179         int rc2 = RTSemEventMultiSignal(pSVGAState->hBusyDelayedEmts);
    6180         AssertRC(rc2);
    6181 # endif
    6182     }
    6183 }
    6184 
    6185 /**
    6186  * Reads (more) payload into the command buffer.
    6187  *
    6188  * @returns pbBounceBuf on success
    6189  * @retval  (void *)1 if the thread was requested to stop.
    6190  * @retval  NULL on FIFO error.
    6191  *
    6192  * @param   cbPayloadReq    The number of bytes of payload requested.
    6193  * @param   pFIFO           The FIFO.
    6194  * @param   offCurrentCmd   The FIFO byte offset of the current command.
    6195  * @param   offFifoMin      The start byte offset of the command FIFO.
    6196  * @param   offFifoMax      The end byte offset of the command FIFO.
    6197  * @param   pbBounceBuf     The bounch buffer. Same size as the entire FIFO, so
    6198  *                          always sufficient size.
    6199  * @param   pcbAlreadyRead  How much payload we've already read into the bounce
    6200  *                          buffer. (We will NEVER re-read anything.)
    6201  * @param   pThread         The calling PDM thread handle.
    6202  * @param   pThis           The shared VGA/VMSVGA instance data.
    6203  * @param   pSVGAState      Pointer to the ring-3 only SVGA state data. For
    6204  *                          statistics collection.
    6205  * @param   pDevIns         The device instance.
    6206  */
    6207 static void *vmsvgaR3FifoGetCmdPayload(uint32_t cbPayloadReq, uint32_t RT_UNTRUSTED_VOLATILE_GUEST *pFIFO,
    6208                                        uint32_t offCurrentCmd, uint32_t offFifoMin, uint32_t offFifoMax,
    6209                                        uint8_t *pbBounceBuf, uint32_t *pcbAlreadyRead,
    6210                                        PPDMTHREAD pThread, PVGASTATE pThis, PVMSVGAR3STATE pSVGAState, PPDMDEVINS pDevIns)
    6211 {
    6212     Assert(pbBounceBuf);
    6213     Assert(pcbAlreadyRead);
    6214     Assert(offFifoMin < offFifoMax);
    6215     Assert(offCurrentCmd >= offFifoMin && offCurrentCmd < offFifoMax);
    6216     Assert(offFifoMax <= pThis->svga.cbFIFO);
    6217 
    6218     /*
    6219      * Check if the requested payload size has already been satisfied                                                                                                .
    6220      *                                                                                                                                                       .
    6221      * When called to read more, the caller is responsible for making sure the                                                                               .
    6222      * new command size (cbRequsted) never is smaller than what has already                                                                                  .
    6223      * been read.
    6224      */
    6225     uint32_t cbAlreadyRead = *pcbAlreadyRead;
    6226     if (cbPayloadReq <= cbAlreadyRead)
    6227     {
    6228         AssertLogRelReturn(cbPayloadReq == cbAlreadyRead, NULL);
    6229         return pbBounceBuf;
    6230     }
    6231 
    6232     /*
    6233      * Commands bigger than the fifo buffer are invalid.
    6234      */
    6235     uint32_t const cbFifoCmd = offFifoMax - offFifoMin;
    6236     AssertMsgReturnStmt(cbPayloadReq <= cbFifoCmd, ("cbPayloadReq=%#x cbFifoCmd=%#x\n", cbPayloadReq, cbFifoCmd),
    6237                         STAM_REL_COUNTER_INC(&pSVGAState->StatFifoErrors),
    6238                         NULL);
    6239 
    6240     /*
    6241      * Move offCurrentCmd past the command dword.
    6242      */
    6243     offCurrentCmd += sizeof(uint32_t);
    6244     if (offCurrentCmd >= offFifoMax)
    6245         offCurrentCmd = offFifoMin;
    6246 
    6247     /*
    6248      * Do we have sufficient payload data available already?
    6249      * The host should not read beyond [SVGA_FIFO_NEXT_CMD], therefore '>=' in the condition below.
    6250      */
    6251     uint32_t cbAfter, cbBefore;
    6252     uint32_t offNextCmd = pFIFO[SVGA_FIFO_NEXT_CMD];
    6253     RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
    6254     if (offNextCmd >= offCurrentCmd)
    6255     {
    6256         if (RT_LIKELY(offNextCmd < offFifoMax))
    6257             cbAfter = offNextCmd - offCurrentCmd;
    6258         else
    6259         {
    6260             STAM_REL_COUNTER_INC(&pSVGAState->StatFifoErrors);
    6261             LogRelMax(16, ("vmsvgaR3FifoGetCmdPayload: Invalid offNextCmd=%#x (offFifoMin=%#x offFifoMax=%#x)\n",
    6262                            offNextCmd, offFifoMin, offFifoMax));
    6263             cbAfter = offFifoMax - offCurrentCmd;
    6264         }
    6265         cbBefore = 0;
    6266     }
    6267     else
    6268     {
    6269         cbAfter  = offFifoMax - offCurrentCmd;
    6270         if (offNextCmd >= offFifoMin)
    6271             cbBefore = offNextCmd - offFifoMin;
    6272         else
    6273         {
    6274             STAM_REL_COUNTER_INC(&pSVGAState->StatFifoErrors);
    6275             LogRelMax(16, ("vmsvgaR3FifoGetCmdPayload: Invalid offNextCmd=%#x (offFifoMin=%#x offFifoMax=%#x)\n",
    6276                            offNextCmd, offFifoMin, offFifoMax));
    6277             cbBefore = 0;
    6278         }
    6279     }
    6280     if (cbAfter + cbBefore < cbPayloadReq)
    6281     {
    6282         /*
    6283          * Insufficient, must wait for it to arrive.
    6284          */
    6285 /** @todo Should clear the busy flag here to maybe encourage the guest to wake us up. */
    6286         STAM_REL_PROFILE_START(&pSVGAState->StatFifoStalls, Stall);
    6287         for (uint32_t i = 0;; i++)
    6288         {
    6289             if (pThread->enmState != PDMTHREADSTATE_RUNNING)
    6290             {
    6291                 STAM_REL_PROFILE_STOP(&pSVGAState->StatFifoStalls, Stall);
    6292                 return (void *)(uintptr_t)1;
    6293             }
    6294             Log(("Guest still copying (%x vs %x) current %x next %x stop %x loop %u; sleep a bit\n",
    6295                  cbPayloadReq, cbAfter + cbBefore, offCurrentCmd, offNextCmd, pFIFO[SVGA_FIFO_STOP], i));
    6296 
    6297             PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pThis->svga.hFIFORequestSem, i < 16 ? 1 : 2);
    6298 
    6299             offNextCmd = pFIFO[SVGA_FIFO_NEXT_CMD];
    6300             RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
    6301             if (offNextCmd >= offCurrentCmd)
    6302             {
    6303                 cbAfter = RT_MIN(offNextCmd, offFifoMax) - offCurrentCmd;
    6304                 cbBefore = 0;
    6305             }
    6306             else
    6307             {
    6308                 cbAfter  = offFifoMax - offCurrentCmd;
    6309                 cbBefore = RT_MAX(offNextCmd, offFifoMin) - offFifoMin;
    6310             }
    6311 
    6312             if (cbAfter + cbBefore >= cbPayloadReq)
    6313                 break;
    6314         }
    6315         STAM_REL_PROFILE_STOP(&pSVGAState->StatFifoStalls, Stall);
    6316     }
    6317 
    6318     /*
    6319      * Copy out the memory and update what pcbAlreadyRead points to.
    6320      */
    6321     if (cbAfter >= cbPayloadReq)
    6322         memcpy(pbBounceBuf + cbAlreadyRead,
    6323                (uint8_t *)pFIFO + offCurrentCmd + cbAlreadyRead,
    6324                cbPayloadReq - cbAlreadyRead);
    6325     else
    6326     {
    6327         LogFlow(("Split data buffer at %x (%u-%u)\n", offCurrentCmd, cbAfter, cbBefore));
    6328         if (cbAlreadyRead < cbAfter)
    6329         {
    6330             memcpy(pbBounceBuf + cbAlreadyRead,
    6331                    (uint8_t *)pFIFO + offCurrentCmd + cbAlreadyRead,
    6332                    cbAfter - cbAlreadyRead);
    6333             cbAlreadyRead = cbAfter;
    6334         }
    6335         memcpy(pbBounceBuf + cbAlreadyRead,
    6336                (uint8_t *)pFIFO + offFifoMin + cbAlreadyRead - cbAfter,
    6337                cbPayloadReq - cbAlreadyRead);
    6338     }
    6339     *pcbAlreadyRead = cbPayloadReq;
    6340     RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
    6341     return pbBounceBuf;
    6342 }
    6343 
    6344 
    6345 /**
    6346  * Sends cursor position and visibility information from the FIFO to the front-end.
    6347  * @returns SVGA_FIFO_CURSOR_COUNT value used.
    6348  */
    6349 static uint32_t
    6350 vmsvgaR3FifoUpdateCursor(PVGASTATECC pThisCC, PVMSVGAR3STATE  pSVGAState, uint32_t RT_UNTRUSTED_VOLATILE_GUEST *pFIFO,
    6351                          uint32_t offFifoMin,  uint32_t uCursorUpdateCount,
    6352                          uint32_t *pxLast, uint32_t *pyLast, uint32_t *pfLastVisible)
    6353 {
    6354     /*
    6355      * Check if the cursor update counter has changed and try get a stable
    6356      * set of values if it has.  This is race-prone, especially consindering
    6357      * the screen ID, but little we can do about that.
    6358      */
    6359     uint32_t x, y, fVisible, idScreen;
    6360     for (uint32_t i = 0; ; i++)
    6361     {
    6362         x        = pFIFO[SVGA_FIFO_CURSOR_X];
    6363         y        = pFIFO[SVGA_FIFO_CURSOR_Y];
    6364         fVisible = pFIFO[SVGA_FIFO_CURSOR_ON];
    6365         idScreen = VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_CURSOR_SCREEN_ID, offFifoMin)
    6366                  ? pFIFO[SVGA_FIFO_CURSOR_SCREEN_ID] : SVGA_ID_INVALID;
    6367         if (   uCursorUpdateCount == pFIFO[SVGA_FIFO_CURSOR_COUNT]
    6368             || i > 3)
    6369             break;
    6370         if (i == 0)
    6371             STAM_REL_COUNTER_INC(&pSVGAState->StatFifoCursorFetchAgain);
    6372         ASMNopPause();
    6373         uCursorUpdateCount = pFIFO[SVGA_FIFO_CURSOR_COUNT];
    6374     }
    6375 
    6376     /*
    6377      * Check if anything has changed, as calling into pDrv is not light-weight.
    6378      */
    6379     if (   *pxLast == x
    6380         && *pyLast == y
    6381         && (idScreen != SVGA_ID_INVALID || *pfLastVisible == fVisible))
    6382         STAM_REL_COUNTER_INC(&pSVGAState->StatFifoCursorNoChange);
    6383     else
    6384     {
    6385         /*
    6386          * Detected changes.
    6387          *
    6388          * We handle global, not per-screen visibility information by sending
    6389          * pfnVBVAMousePointerShape without shape data.
    6390          */
    6391         *pxLast = x;
    6392         *pyLast = y;
    6393         uint32_t fFlags = VBVA_CURSOR_VALID_DATA;
    6394         if (idScreen != SVGA_ID_INVALID)
    6395             fFlags |= VBVA_CURSOR_SCREEN_RELATIVE;
    6396         else if (*pfLastVisible != fVisible)
    6397         {
    6398             LogRel2(("vmsvgaR3FifoUpdateCursor: fVisible %d fLastVisible %d (%d,%d)\n", fVisible, *pfLastVisible, x, y));
    6399             *pfLastVisible = fVisible;
    6400             pThisCC->pDrv->pfnVBVAMousePointerShape(pThisCC->pDrv, RT_BOOL(fVisible), false, 0, 0, 0, 0, NULL);
    6401             STAM_REL_COUNTER_INC(&pSVGAState->StatFifoCursorVisiblity);
    6402         }
    6403         pThisCC->pDrv->pfnVBVAReportCursorPosition(pThisCC->pDrv, fFlags, idScreen, x, y);
    6404         STAM_REL_COUNTER_INC(&pSVGAState->StatFifoCursorPosition);
    6405     }
    6406 
    6407     /*
    6408      * Update done.  Signal this to the guest.
    6409      */
    6410     pFIFO[SVGA_FIFO_CURSOR_LAST_UPDATED] = uCursorUpdateCount;
    6411 
    6412     return uCursorUpdateCount;
    6413 }
    6414 
    6415 
    6416 /**
    6417  * Checks if there is work to be done, either cursor updating or FIFO commands.
    6418  *
    6419  * @returns true if pending work, false if not.
    6420  * @param   pThisCC             The VGA/VMSVGA state for ring-3.
    6421  * @param   uLastCursorCount    The last cursor update counter value.
    6422  */
    6423 DECLINLINE(bool) vmsvgaR3FifoHasWork(PVGASTATECC pThisCC, uint32_t uLastCursorCount)
    6424 {
    6425     /* If FIFO does not exist than there is nothing to do. Command buffers also require the enabled FIFO. */
    6426     uint32_t RT_UNTRUSTED_VOLATILE_GUEST * const pFIFO = pThisCC->svga.pau32FIFO;
    6427     AssertReturn(pFIFO, false);
    6428 
    6429     if (vmsvgaR3CmdBufHasWork(pThisCC))
    6430         return true;
    6431 
    6432     if (pFIFO[SVGA_FIFO_NEXT_CMD] != pFIFO[SVGA_FIFO_STOP])
    6433         return true;
    6434 
    6435     if (   uLastCursorCount != pFIFO[SVGA_FIFO_CURSOR_COUNT]
    6436         && VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_CURSOR_LAST_UPDATED, pFIFO[SVGA_FIFO_MIN]))
    6437         return true;
    6438 
    6439     return false;
    6440 }
    6441 
    6442 
    6443 /**
    6444  * Called by the VGA refresh timer to wake up the FIFO thread when needed.
    6445  *
    6446  * @param   pDevIns     The device instance.
    6447  * @param   pThis       The shared VGA/VMSVGA instance data.
    6448  * @param   pThisCC     The VGA/VMSVGA state for ring-3.
    6449  */
    6450 void vmsvgaR3FifoWatchdogTimer(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC)
    6451 {
    6452     /* Caller already checked pThis->svga.fFIFOThreadSleeping, so we only have
    6453        to recheck it before doing the signalling. */
    6454     if (   vmsvgaR3FifoHasWork(pThisCC, ASMAtomicReadU32(&pThis->svga.uLastCursorUpdateCount))
    6455         && pThis->svga.fFIFOThreadSleeping)
    6456     {
    6457         int rc = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->svga.hFIFORequestSem);
    6458         AssertRC(rc);
    6459         STAM_REL_COUNTER_INC(&pThisCC->svga.pSvgaR3State->StatFifoWatchdogWakeUps);
    6460     }
    6461 }
    6462 
    6463 
    6464 /**
    6465  * Called by the FIFO thread to process pending actions.
    6466  *
    6467  * @param   pDevIns     The device instance.
    6468  * @param   pThis       The shared VGA/VMSVGA instance data.
    6469  * @param   pThisCC     The VGA/VMSVGA state for ring-3.
    6470  */
    6471 void vmsvgaR3FifoPendingActions(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC)
    6472 {
    6473     RT_NOREF(pDevIns);
    6474 
    6475     /* Currently just mode changes. */
    6476     if (ASMBitTestAndClear(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE_BIT))
    6477     {
    6478         vmsvgaR3ChangeMode(pThis, pThisCC);
    6479 # ifdef VBOX_WITH_VMSVGA3D
    6480         if (pThisCC->svga.p3dState != NULL)
    6481             vmsvga3dChangeMode(pThisCC);
    6482 # endif
    6483     }
    6484 }
    6485 
    6486 
    6487 /*
    6488  * These two macros are put outside vmsvgaR3FifoLoop because doxygen gets confused,
    6489  * even the latest version, and thinks we're documenting vmsvgaR3FifoLoop. Sigh.
    6490  */
    6491 /** @def VMSVGAFIFO_GET_CMD_BUFFER_BREAK
    6492  * Macro for shortening calls to vmsvgaR3FifoGetCmdPayload.
    6493  *
    6494  * Will break out of the switch on failure.
    6495  * Will restart and quit the loop if the thread was requested to stop.
    6496  *
    6497  * @param   a_PtrVar        Request variable pointer.
    6498  * @param   a_Type          Request typedef (not pointer) for casting.
    6499  * @param   a_cbPayloadReq  How much payload to fetch.
    6500  * @remarks Accesses a bunch of variables in the current scope!
    6501  */
    6502 # define VMSVGAFIFO_GET_CMD_BUFFER_BREAK(a_PtrVar, a_Type, a_cbPayloadReq) \
    6503             if (1) { \
    6504                 (a_PtrVar) = (a_Type *)vmsvgaR3FifoGetCmdPayload((a_cbPayloadReq), pFIFO, offCurrentCmd, offFifoMin, offFifoMax, \
    6505                                                                  pbBounceBuf, &cbPayload, pThread, pThis, pSVGAState, pDevIns); \
    6506                 if (RT_UNLIKELY((uintptr_t)(a_PtrVar) < 2)) { if ((uintptr_t)(a_PtrVar) == 1) continue; break; } \
    6507                 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE(); \
    6508             } else do {} while (0)
    6509 /* @def VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK
    6510  * Macro for shortening calls to vmsvgaR3FifoGetCmdPayload for refetching the
    6511  * buffer after figuring out the actual command size.
    6512  *
    6513  * Will break out of the switch on failure.
    6514  *
    6515  * @param   a_PtrVar        Request variable pointer.
    6516  * @param   a_Type          Request typedef (not pointer) for casting.
    6517  * @param   a_cbPayloadReq  How much payload to fetch.
    6518  * @remarks Accesses a bunch of variables in the current scope!
    6519  */
    6520 # define VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(a_PtrVar, a_Type, a_cbPayloadReq) \
    6521             if (1) { \
    6522                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(a_PtrVar, a_Type, a_cbPayloadReq); \
    6523             } else do {} while (0)
    6524 
    6525 /**
    6526  * @callback_method_impl{PFNPDMTHREADDEV, The async FIFO handling thread.}
    6527  */
    6528 static DECLCALLBACK(int) vmsvgaR3FifoLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
    6529 {
    6530     PVGASTATE       pThis      = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
    6531     PVGASTATER3     pThisCC    = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
    6532     PVMSVGAR3STATE  pSVGAState = pThisCC->svga.pSvgaR3State;
    6533     int             rc;
    6534 
    6535 # if defined(VBOX_WITH_VMSVGA3D) && defined(RT_OS_LINUX)
    6536     if (pThis->svga.f3DEnabled)
    6537     {
    6538         /* The FIFO thread may use X API for accelerated screen output. */
    6539         XInitThreads();
    6540     }
    6541 # endif
    6542 
    6543     if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
    6544         return VINF_SUCCESS;
    6545 
    6546     /*
    6547      * Special mode where we only execute an external command and the go back
    6548      * to being suspended.  Currently, all ext cmds ends up here, with the reset
    6549      * one also being eligble for runtime execution further down as well.
    6550      */
    6551     if (pThis->svga.fFifoExtCommandWakeup)
    6552     {
    6553         vmsvgaR3FifoHandleExtCmd(pDevIns, pThis, pThisCC);
    6554         while (pThread->enmState == PDMTHREADSTATE_RUNNING)
    6555             if (pThis->svga.u8FIFOExtCommand == VMSVGA_FIFO_EXTCMD_NONE)
    6556                 PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pThis->svga.hFIFORequestSem, RT_MS_1MIN);
    6557             else
    6558                 vmsvgaR3FifoHandleExtCmd(pDevIns, pThis, pThisCC);
    6559         return VINF_SUCCESS;
    6560     }
    6561 
    6562 
    6563     /*
    6564      * Signal the semaphore to make sure we don't wait for 250ms after a
    6565      * suspend & resume scenario (see vmsvgaR3FifoGetCmdPayload).
    6566      */
    6567     PDMDevHlpSUPSemEventSignal(pDevIns, pThis->svga.hFIFORequestSem);
    6568 
    6569     /*
    6570      * Allocate a bounce buffer for command we get from the FIFO.
    6571      * (All code must return via the end of the function to free this buffer.)
    6572      */
    6573     uint8_t *pbBounceBuf = (uint8_t *)RTMemAllocZ(pThis->svga.cbFIFO);
    6574     AssertReturn(pbBounceBuf, VERR_NO_MEMORY);
    6575 
    6576     /*
    6577      * Polling/sleep interval config.
    6578      *
    6579      * We wait for an a short interval if the guest has recently given us work
    6580      * to do, but the interval increases the longer we're kept idle.  Once we've
    6581      * reached the refresh timer interval, we'll switch to extended waits,
    6582      * depending on it or the guest to kick us into action when needed.
    6583      *
    6584      * Should the refresh time go fishing, we'll just continue increasing the
    6585      * sleep length till we reaches the 250 ms max after about 16 seconds.
    6586      */
    6587     RTMSINTERVAL const  cMsMinSleep           = 16;
    6588     RTMSINTERVAL const  cMsIncSleep           = 2;
    6589     RTMSINTERVAL const  cMsMaxSleep           = 250;
    6590     RTMSINTERVAL const  cMsExtendedSleep      = 15 * RT_MS_1SEC; /* Regular paranoia dictates that this cannot be indefinite. */
    6591     RTMSINTERVAL        cMsSleep              = cMsMaxSleep;
    6592 
    6593     /*
    6594      * Cursor update state (SVGA_FIFO_CAP_CURSOR_BYPASS_3).
    6595      *
    6596      * Initialize with values that will detect an update from the guest.
    6597      * Make sure that if the guest never updates the cursor position, then the device does not report it.
    6598      * The guest has to change the value of uLastCursorUpdateCount, when the cursor position is actually updated.
    6599      * xLastCursor, yLastCursor and fLastCursorVisible are set to report the first update.
    6600      */
    6601     uint32_t RT_UNTRUSTED_VOLATILE_GUEST * const pFIFO = pThisCC->svga.pau32FIFO;
    6602     pThis->svga.uLastCursorUpdateCount = pFIFO[SVGA_FIFO_CURSOR_COUNT];
    6603     uint32_t xLastCursor        = ~pFIFO[SVGA_FIFO_CURSOR_X];
    6604     uint32_t yLastCursor        = ~pFIFO[SVGA_FIFO_CURSOR_Y];
    6605     uint32_t fLastCursorVisible = ~pFIFO[SVGA_FIFO_CURSOR_ON];
    6606 
    6607     /*
    6608      * The FIFO loop.
    6609      */
    6610     LogFlow(("vmsvgaR3FifoLoop: started loop\n"));
    6611     bool fBadOrDisabledFifo = false;
    6612     while (pThread->enmState == PDMTHREADSTATE_RUNNING)
    6613     {
    6614 # if defined(RT_OS_DARWIN) && defined(VBOX_WITH_VMSVGA3D)
    6615         /*
    6616          * Should service the run loop every so often.
    6617          */
    6618         if (pThis->svga.f3DEnabled)
    6619             vmsvga3dCocoaServiceRunLoop();
    6620 # endif
    6621 
    6622         /* First check any pending actions. */
    6623         vmsvgaR3FifoPendingActions(pDevIns, pThis, pThisCC);
    6624 
    6625         /*
    6626          * Unless there's already work pending, go to sleep for a short while.
    6627          * (See polling/sleep interval config above.)
    6628          */
    6629         if (   fBadOrDisabledFifo
    6630             || !vmsvgaR3FifoHasWork(pThisCC, pThis->svga.uLastCursorUpdateCount))
    6631         {
    6632             ASMAtomicWriteBool(&pThis->svga.fFIFOThreadSleeping, true);
    6633             Assert(pThis->cMilliesRefreshInterval > 0);
    6634             if (cMsSleep < pThis->cMilliesRefreshInterval)
    6635                 rc = PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pThis->svga.hFIFORequestSem, cMsSleep);
    6636             else
    6637             {
    6638 # ifdef VMSVGA_USE_FIFO_ACCESS_HANDLER
    6639                 int rc2 = PGMHandlerPhysicalReset(PDMDevHlpGetVM(pDevIns), pThis->svga.GCPhysFIFO);
    6640                 AssertRC(rc2); /* No break. Racing EMTs unmapping and remapping the region. */
    6641 # endif
    6642                 if (   !fBadOrDisabledFifo
    6643                     && vmsvgaR3FifoHasWork(pThisCC, pThis->svga.uLastCursorUpdateCount))
    6644                     rc = VINF_SUCCESS;
    6645                 else
    6646                 {
    6647                     STAM_REL_PROFILE_START(&pSVGAState->StatFifoExtendedSleep, Acc);
    6648                     rc = PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pThis->svga.hFIFORequestSem, cMsExtendedSleep);
    6649                     STAM_REL_PROFILE_STOP(&pSVGAState->StatFifoExtendedSleep, Acc);
    6650                 }
    6651             }
    6652             ASMAtomicWriteBool(&pThis->svga.fFIFOThreadSleeping, false);
    6653             AssertBreak(RT_SUCCESS(rc) || rc == VERR_TIMEOUT || rc == VERR_INTERRUPTED);
    6654             if (pThread->enmState != PDMTHREADSTATE_RUNNING)
    6655             {
    6656                 LogFlow(("vmsvgaR3FifoLoop: thread state %x\n", pThread->enmState));
    6657                 break;
    6658             }
    6659         }
    6660         else
    6661             rc = VINF_SUCCESS;
    6662         fBadOrDisabledFifo = false;
    6663         if (rc == VERR_TIMEOUT)
    6664         {
    6665             if (!vmsvgaR3FifoHasWork(pThisCC, pThis->svga.uLastCursorUpdateCount))
    6666             {
    6667                 cMsSleep = RT_MIN(cMsSleep + cMsIncSleep, cMsMaxSleep);
    6668                 continue;
    6669             }
    6670             STAM_REL_COUNTER_INC(&pSVGAState->StatFifoTodoTimeout);
    6671 
    6672             Log(("vmsvgaR3FifoLoop: timeout\n"));
    6673         }
    6674         else if (vmsvgaR3FifoHasWork(pThisCC, pThis->svga.uLastCursorUpdateCount))
    6675             STAM_REL_COUNTER_INC(&pSVGAState->StatFifoTodoWoken);
    6676         cMsSleep = cMsMinSleep;
    6677 
    6678         Log(("vmsvgaR3FifoLoop: enabled=%d configured=%d busy=%d\n", pThis->svga.fEnabled, pThis->svga.fConfigured, pFIFO[SVGA_FIFO_BUSY]));
    6679         Log(("vmsvgaR3FifoLoop: min  %x max  %x\n", pFIFO[SVGA_FIFO_MIN], pFIFO[SVGA_FIFO_MAX]));
    6680         Log(("vmsvgaR3FifoLoop: next %x stop %x\n", pFIFO[SVGA_FIFO_NEXT_CMD], pFIFO[SVGA_FIFO_STOP]));
    6681 
    6682         /*
    6683          * Handle external commands (currently only reset).
    6684          */
    6685         if (pThis->svga.u8FIFOExtCommand != VMSVGA_FIFO_EXTCMD_NONE)
    6686         {
    6687             vmsvgaR3FifoHandleExtCmd(pDevIns, pThis, pThisCC);
    6688             continue;
    6689         }
    6690 
    6691         /*
    6692          * The device must be enabled and configured.
    6693          */
    6694         if (   !pThis->svga.fEnabled
    6695             || !pThis->svga.fConfigured)
    6696         {
    6697             vmsvgaR3FifoSetNotBusy(pDevIns, pThis, pThisCC, pSVGAState, pFIFO[SVGA_FIFO_MIN]);
    6698             fBadOrDisabledFifo = true;
    6699             cMsSleep           = cMsMaxSleep; /* cheat */
    6700             continue;
    6701         }
    6702 
    6703         /*
    6704          * Get and check the min/max values.  We ASSUME that they will remain
    6705          * unchanged while we process requests.  A further ASSUMPTION is that
    6706          * the guest won't mess with SVGA_FIFO_NEXT_CMD while we're busy, so
    6707          * we don't read it back while in the loop.
    6708          */
    6709         uint32_t const offFifoMin    = pFIFO[SVGA_FIFO_MIN];
    6710         uint32_t const offFifoMax    = pFIFO[SVGA_FIFO_MAX];
    6711         uint32_t       offCurrentCmd = pFIFO[SVGA_FIFO_STOP];
    6712         RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
    6713         if (RT_UNLIKELY(   !VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_STOP, offFifoMin)
    6714                         || offFifoMax <= offFifoMin
    6715                         || offFifoMax > pThis->svga.cbFIFO
    6716                         || (offFifoMax & 3) != 0
    6717                         || (offFifoMin & 3) != 0
    6718                         || offCurrentCmd < offFifoMin
    6719                         || offCurrentCmd > offFifoMax))
    6720         {
    6721             STAM_REL_COUNTER_INC(&pSVGAState->StatFifoErrors);
    6722             LogRelMax(8, ("vmsvgaR3FifoLoop: Bad fifo: min=%#x stop=%#x max=%#x\n", offFifoMin, offCurrentCmd, offFifoMax));
    6723             vmsvgaR3FifoSetNotBusy(pDevIns, pThis, pThisCC, pSVGAState, offFifoMin);
    6724             fBadOrDisabledFifo = true;
    6725             continue;
    6726         }
    6727         RT_UNTRUSTED_VALIDATED_FENCE();
    6728         if (RT_UNLIKELY(offCurrentCmd & 3))
    6729         {
    6730             STAM_REL_COUNTER_INC(&pSVGAState->StatFifoErrors);
    6731             LogRelMax(8, ("vmsvgaR3FifoLoop: Misaligned offCurrentCmd=%#x?\n", offCurrentCmd));
    6732             offCurrentCmd &= ~UINT32_C(3);
    6733         }
    6734 
    6735         /*
    6736          * Update the cursor position before we start on the FIFO commands.
    6737          */
    6738         /** @todo do we need to check whether the guest disabled the SVGA_FIFO_CAP_CURSOR_BYPASS_3 capability here? */
    6739         if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_CURSOR_LAST_UPDATED, offFifoMin))
    6740         {
    6741             uint32_t const uCursorUpdateCount = pFIFO[SVGA_FIFO_CURSOR_COUNT];
    6742             if (uCursorUpdateCount == pThis->svga.uLastCursorUpdateCount)
    6743             { /* halfways likely */ }
    6744             else
    6745             {
    6746                 uint32_t const uNewCount = vmsvgaR3FifoUpdateCursor(pThisCC, pSVGAState, pFIFO, offFifoMin, uCursorUpdateCount,
    6747                                                                     &xLastCursor, &yLastCursor, &fLastCursorVisible);
    6748                 ASMAtomicWriteU32(&pThis->svga.uLastCursorUpdateCount, uNewCount);
    6749             }
    6750         }
    6751 
    6752         /*
    6753          * Mark the FIFO as busy.
    6754          */
    6755         ASMAtomicWriteU32(&pThis->svga.fBusy, VMSVGA_BUSY_F_FIFO);  // Clears VMSVGA_BUSY_F_EMT_FORCE!
    6756         if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_BUSY, offFifoMin))
    6757             ASMAtomicWriteU32(&pFIFO[SVGA_FIFO_BUSY], true);
    6758 
    6759         /*
    6760          * Process all submitted command buffers.
    6761          */
    6762         vmsvgaR3CmdBufProcessBuffers(pDevIns, pThis, pThisCC, pThread);
    6763 
    6764         /*
    6765          * Execute all queued FIFO commands.
    6766          * Quit if pending external command or changes in the thread state.
    6767          */
    6768         bool fDone = false;
    6769         while (   !(fDone = (pFIFO[SVGA_FIFO_NEXT_CMD] == offCurrentCmd))
    6770                && pThread->enmState == PDMTHREADSTATE_RUNNING)
    6771         {
    6772             uint32_t cbPayload = 0;
    6773             uint32_t u32IrqStatus = 0;
    6774 
    6775             Assert(offCurrentCmd < offFifoMax && offCurrentCmd >= offFifoMin);
    6776 
    6777             /* First check any pending actions. */
    6778             vmsvgaR3FifoPendingActions(pDevIns, pThis, pThisCC);
    6779 
    6780             /* Check for pending external commands (reset). */
    6781             if (pThis->svga.u8FIFOExtCommand != VMSVGA_FIFO_EXTCMD_NONE)
    6782                 break;
    6783 
    6784             /*
    6785              * Process the command.
    6786              */
    6787             /* 'enmCmdId' is actually a SVGAFifoCmdId. It is treated as uint32_t in order to avoid a compiler
    6788              * warning. Because we implement some obsolete and deprecated commands, which are not included in
    6789              * the SVGAFifoCmdId enum in the VMSVGA headers anymore.
    6790              */
    6791             uint32_t const enmCmdId = pFIFO[offCurrentCmd / sizeof(uint32_t)];
    6792             RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
    6793             LogFlow(("vmsvgaR3FifoLoop: FIFO command (iCmd=0x%x) %s %d\n",
    6794                      offCurrentCmd / sizeof(uint32_t), vmsvgaR3FifoCmdToString(enmCmdId), enmCmdId));
    6795             switch (enmCmdId)
    6796             {
    6797             case SVGA_CMD_INVALID_CMD:
    6798                 /* Nothing to do. */
    6799                 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdInvalidCmd);
    6800                 break;
    6801 
    6802             case SVGA_CMD_FENCE:
    6803             {
    6804                 SVGAFifoCmdFence *pCmdFence;
    6805                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmdFence, SVGAFifoCmdFence, sizeof(*pCmdFence));
    6806                 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdFence);
    6807                 if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_FENCE, offFifoMin))
    6808                 {
    6809                     Log(("vmsvgaR3FifoLoop: SVGA_CMD_FENCE %#x\n", pCmdFence->fence));
    6810                     pFIFO[SVGA_FIFO_FENCE] = pCmdFence->fence;
    6811 
    6812                     if (pThis->svga.u32IrqMask & SVGA_IRQFLAG_ANY_FENCE)
    6813                     {
    6814                         Log(("vmsvgaR3FifoLoop: any fence irq\n"));
    6815                         u32IrqStatus |= SVGA_IRQFLAG_ANY_FENCE;
    6816                     }
    6817                     else
    6818                     if (    VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_FENCE_GOAL, offFifoMin)
    6819                         &&  (pThis->svga.u32IrqMask & SVGA_IRQFLAG_FENCE_GOAL)
    6820                         &&  pFIFO[SVGA_FIFO_FENCE_GOAL] == pCmdFence->fence)
    6821                     {
    6822                         Log(("vmsvgaR3FifoLoop: fence goal reached irq (fence=%#x)\n", pCmdFence->fence));
    6823                         u32IrqStatus |= SVGA_IRQFLAG_FENCE_GOAL;
    6824                     }
    6825                 }
    6826                 else
    6827                     Log(("SVGA_CMD_FENCE is bogus when offFifoMin is %#x!\n", offFifoMin));
    6828                 break;
    6829             }
    6830 
    6831             case SVGA_CMD_UPDATE:
    6832             {
    6833                 SVGAFifoCmdUpdate *pCmd;
    6834                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdUpdate, sizeof(*pCmd));
    6835                 vmsvgaR3CmdUpdate(pThis, pThisCC, pCmd);
    6836                 break;
    6837             }
    6838 
    6839             case SVGA_CMD_UPDATE_VERBOSE:
    6840             {
    6841                 SVGAFifoCmdUpdateVerbose *pCmd;
    6842                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdUpdateVerbose, sizeof(*pCmd));
    6843                 vmsvgaR3CmdUpdateVerbose(pThis, pThisCC, pCmd);
    6844                 break;
    6845             }
    6846 
    6847             case SVGA_CMD_DEFINE_CURSOR:
    6848             {
    6849                 /* Followed by bitmap data. */
    6850                 SVGAFifoCmdDefineCursor *pCmd;
    6851                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineCursor, sizeof(*pCmd));
    6852 
    6853                 /* Figure out the size of the bitmap data. */
    6854                 ASSERT_GUEST_BREAK(pCmd->height < 2048 && pCmd->width < 2048);
    6855                 ASSERT_GUEST_BREAK(pCmd->andMaskDepth <= 32);
    6856                 ASSERT_GUEST_BREAK(pCmd->xorMaskDepth <= 32);
    6857                 RT_UNTRUSTED_VALIDATED_FENCE();
    6858 
    6859                 uint32_t const cbAndLine = RT_ALIGN_32(pCmd->width * (pCmd->andMaskDepth + (pCmd->andMaskDepth == 15)), 32) / 8;
    6860                 uint32_t const cbAndMask = cbAndLine * pCmd->height;
    6861                 uint32_t const cbXorLine = RT_ALIGN_32(pCmd->width * (pCmd->xorMaskDepth + (pCmd->xorMaskDepth == 15)), 32) / 8;
    6862                 uint32_t const cbXorMask = cbXorLine * pCmd->height;
    6863 
    6864                 uint32_t const cbCmd = sizeof(SVGAFifoCmdDefineCursor) + cbAndMask + cbXorMask;
    6865                 VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineCursor, cbCmd);
    6866                 vmsvgaR3CmdDefineCursor(pThis, pThisCC, pCmd);
    6867                 break;
    6868             }
    6869 
    6870             case SVGA_CMD_DEFINE_ALPHA_CURSOR:
    6871             {
    6872                 /* Followed by bitmap data. */
    6873                 SVGAFifoCmdDefineAlphaCursor *pCmd;
    6874                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineAlphaCursor, sizeof(*pCmd));
    6875 
    6876                 /* Figure out the size of the bitmap data. */
    6877                 ASSERT_GUEST_BREAK(pCmd->height < 2048 && pCmd->width < 2048);
    6878 
    6879                 uint32_t const cbCmd = sizeof(SVGAFifoCmdDefineAlphaCursor) + pCmd->width * pCmd->height * sizeof(uint32_t) /* 32-bit BRGA format */;
    6880                 VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineAlphaCursor, cbCmd);
    6881                 vmsvgaR3CmdDefineAlphaCursor(pThis, pThisCC, pCmd);
    6882                 break;
    6883             }
    6884 
    6885             case SVGA_CMD_MOVE_CURSOR:
    6886             {
    6887                 /* Deprecated; there should be no driver which *requires* this command. However, if
    6888                  * we do ecncounter this command, it might be useful to not get the FIFO completely out of
    6889                  * alignment.
    6890                  * May be issued by guest if SVGA_CAP_CURSOR_BYPASS is missing.
    6891                  */
    6892                 SVGAFifoCmdMoveCursor *pCmd;
    6893                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdMoveCursor, sizeof(*pCmd));
    6894                 vmsvgaR3CmdMoveCursor(pThis, pThisCC, pCmd);
    6895                 break;
    6896             }
    6897 
    6898             case SVGA_CMD_DISPLAY_CURSOR:
    6899             {
    6900                 /* Deprecated; there should be no driver which *requires* this command. However, if
    6901                  * we do ecncounter this command, it might be useful to not get the FIFO completely out of
    6902                  * alignment.
    6903                  * May be issued by guest if SVGA_CAP_CURSOR_BYPASS is missing.
    6904                  */
    6905                 SVGAFifoCmdDisplayCursor *pCmd;
    6906                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDisplayCursor, sizeof(*pCmd));
    6907                 vmsvgaR3CmdDisplayCursor(pThis, pThisCC, pCmd);
    6908                 break;
    6909             }
    6910 
    6911             case SVGA_CMD_RECT_FILL:
    6912             {
    6913                 SVGAFifoCmdRectFill *pCmd;
    6914                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdRectFill, sizeof(*pCmd));
    6915                 vmsvgaR3CmdRectFill(pThis, pThisCC, pCmd);
    6916                 break;
    6917             }
    6918 
    6919             case SVGA_CMD_RECT_COPY:
    6920             {
    6921                 SVGAFifoCmdRectCopy *pCmd;
    6922                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdRectCopy, sizeof(*pCmd));
    6923                 vmsvgaR3CmdRectCopy(pThis, pThisCC, pCmd);
    6924                 break;
    6925             }
    6926 
    6927             case SVGA_CMD_RECT_ROP_COPY:
    6928             {
    6929                 SVGAFifoCmdRectRopCopy *pCmd;
    6930                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdRectRopCopy, sizeof(*pCmd));
    6931                 vmsvgaR3CmdRectRopCopy(pThis, pThisCC, pCmd);
    6932                 break;
    6933             }
    6934 
    6935             case SVGA_CMD_ESCAPE:
    6936             {
    6937                 /* Followed by 'size' bytes of data. */
    6938                 SVGAFifoCmdEscape *pCmd;
    6939                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdEscape, sizeof(*pCmd));
    6940 
    6941                 ASSERT_GUEST_BREAK(pCmd->size < pThis->svga.cbFIFO - sizeof(SVGAFifoCmdEscape));
    6942                 RT_UNTRUSTED_VALIDATED_FENCE();
    6943 
    6944                 uint32_t const cbCmd = sizeof(SVGAFifoCmdEscape) + pCmd->size;
    6945                 VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdEscape, cbCmd);
    6946                 vmsvgaR3CmdEscape(pThis, pThisCC, pCmd);
    6947                 break;
    6948             }
    6949 # ifdef VBOX_WITH_VMSVGA3D
    6950             case SVGA_CMD_DEFINE_GMR2:
    6951             {
    6952                 SVGAFifoCmdDefineGMR2 *pCmd;
    6953                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineGMR2, sizeof(*pCmd));
    6954                 vmsvgaR3CmdDefineGMR2(pThis, pThisCC, pCmd);
    6955                 break;
    6956             }
    6957 
    6958             case SVGA_CMD_REMAP_GMR2:
    6959             {
    6960                 /* Followed by page descriptors or guest ptr. */
    6961                 SVGAFifoCmdRemapGMR2 *pCmd;
    6962                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdRemapGMR2, sizeof(*pCmd));
    6963 
    6964                 /* Calculate the size of what comes after next and fetch it. */
    6965                 uint32_t cbCmd = sizeof(SVGAFifoCmdRemapGMR2);
    6966                 if (pCmd->flags & SVGA_REMAP_GMR2_VIA_GMR)
    6967                     cbCmd += sizeof(SVGAGuestPtr);
    6968                 else
    6969                 {
    6970                     uint32_t const cbPageDesc = (pCmd->flags & SVGA_REMAP_GMR2_PPN64) ? sizeof(uint64_t) : sizeof(uint32_t);
    6971                     if (pCmd->flags & SVGA_REMAP_GMR2_SINGLE_PPN)
    6972                     {
    6973                         cbCmd         += cbPageDesc;
    6974                         pCmd->numPages = 1;
    6975                     }
    6976                     else
    6977                     {
    6978                         ASSERT_GUEST_BREAK(pCmd->numPages <= pThis->svga.cbFIFO / cbPageDesc);
    6979                         cbCmd += cbPageDesc * pCmd->numPages;
    6980                     }
    6981                 }
    6982                 VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdRemapGMR2, cbCmd);
    6983                 vmsvgaR3CmdRemapGMR2(pThis, pThisCC, pCmd);
    6984 #  ifdef DEBUG_GMR_ACCESS
    6985                 VMR3ReqCallWaitU(PDMDevHlpGetUVM(pDevIns), VMCPUID_ANY, (PFNRT)vmsvgaR3RegisterGmr, 2, pDevIns, pCmd->gmrId);
    6986 #  endif
    6987                 break;
    6988             }
    6989 # endif // VBOX_WITH_VMSVGA3D
    6990             case SVGA_CMD_DEFINE_SCREEN:
    6991             {
    6992                 /* The size of this command is specified by the guest and depends on capabilities. */
    6993                 Assert(pFIFO[SVGA_FIFO_CAPABILITIES] & SVGA_FIFO_CAP_SCREEN_OBJECT_2);
    6994 
    6995                 SVGAFifoCmdDefineScreen *pCmd;
    6996                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineScreen, sizeof(pCmd->screen.structSize));
    6997                 AssertBreak(pCmd->screen.structSize < pThis->svga.cbFIFO);
    6998                 RT_UNTRUSTED_VALIDATED_FENCE();
    6999 
    7000                 RT_BZERO(&pCmd->screen.id, sizeof(*pCmd) - RT_OFFSETOF(SVGAFifoCmdDefineScreen, screen.id));
    7001                 VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineScreen, RT_MAX(sizeof(pCmd->screen.structSize), pCmd->screen.structSize));
    7002                 vmsvgaR3CmdDefineScreen(pThis, pThisCC, pCmd);
    7003                 break;
    7004             }
    7005 
    7006             case SVGA_CMD_DESTROY_SCREEN:
    7007             {
    7008                 SVGAFifoCmdDestroyScreen *pCmd;
    7009                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDestroyScreen, sizeof(*pCmd));
    7010                 vmsvgaR3CmdDestroyScreen(pThis, pThisCC, pCmd);
    7011                 break;
    7012             }
    7013 
    7014             case SVGA_CMD_DEFINE_GMRFB:
    7015             {
    7016                 SVGAFifoCmdDefineGMRFB *pCmd;
    7017                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineGMRFB, sizeof(*pCmd));
    7018                 vmsvgaR3CmdDefineGMRFB(pThis, pThisCC, pCmd);
    7019                 break;
    7020             }
    7021 
    7022             case SVGA_CMD_BLIT_GMRFB_TO_SCREEN:
    7023             {
    7024                 SVGAFifoCmdBlitGMRFBToScreen *pCmd;
    7025                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdBlitGMRFBToScreen, sizeof(*pCmd));
    7026                 vmsvgaR3CmdBlitGMRFBToScreen(pThis, pThisCC, pCmd);
    7027                 break;
    7028             }
    7029 
    7030             case SVGA_CMD_BLIT_SCREEN_TO_GMRFB:
    7031             {
    7032                 SVGAFifoCmdBlitScreenToGMRFB *pCmd;
    7033                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdBlitScreenToGMRFB, sizeof(*pCmd));
    7034                 vmsvgaR3CmdBlitScreenToGMRFB(pThis, pThisCC, pCmd);
    7035                 break;
    7036             }
    7037 
    7038             case SVGA_CMD_ANNOTATION_FILL:
    7039             {
    7040                 SVGAFifoCmdAnnotationFill *pCmd;
    7041                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdAnnotationFill, sizeof(*pCmd));
    7042                 vmsvgaR3CmdAnnotationFill(pThis, pThisCC, pCmd);
    7043                 break;
    7044             }
    7045 
    7046             case SVGA_CMD_ANNOTATION_COPY:
    7047             {
    7048                 SVGAFifoCmdAnnotationCopy *pCmd;
    7049                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdAnnotationCopy, sizeof(*pCmd));
    7050                 vmsvgaR3CmdAnnotationCopy(pThis, pThisCC, pCmd);
    7051                 break;
    7052             }
    7053 
    7054             default:
    7055 # ifdef VBOX_WITH_VMSVGA3D
    7056                 if (    (int)enmCmdId >= SVGA_3D_CMD_BASE
    7057                     &&  (int)enmCmdId <  SVGA_3D_CMD_MAX)
    7058                 {
    7059                     RT_UNTRUSTED_VALIDATED_FENCE();
    7060 
    7061                     /* All 3d commands start with a common header, which defines the identifier and the size
    7062                      * of the command. The identifier has been already read from FIFO. Fetch the size.
    7063                      */
    7064                     uint32_t *pcbCmd;
    7065                     VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pcbCmd, uint32_t, sizeof(*pcbCmd));
    7066                     uint32_t const cbCmd = *pcbCmd;
    7067                     AssertBreak(cbCmd < pThis->svga.cbFIFO);
    7068                     uint32_t *pu32Cmd;
    7069                     VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pu32Cmd, uint32_t, sizeof(*pcbCmd) + cbCmd);
    7070                     pu32Cmd++; /* Skip the command size. */
    7071 
    7072                     if (RT_LIKELY(pThis->svga.f3DEnabled))
    7073                     { /* likely */ }
    7074                     else
    7075                     {
    7076                         LogRelMax(8, ("VMSVGA: 3D disabled, command %d skipped\n", enmCmdId));
    7077                         break;
    7078                     }
    7079 
    7080                     vmsvgaR3Process3dCmd(pThis, pThisCC, (SVGAFifo3dCmdId)enmCmdId, cbCmd, pu32Cmd);
    7081                 }
    7082                 else
    7083 # endif // VBOX_WITH_VMSVGA3D
    7084                 {
    7085                     STAM_REL_COUNTER_INC(&pSVGAState->StatFifoUnkCmds);
    7086                     AssertMsgFailed(("enmCmdId=%d\n", enmCmdId));
    7087                 }
    7088             }
    7089 
    7090             /* Go to the next slot */
    7091             Assert(cbPayload + sizeof(uint32_t) <= offFifoMax - offFifoMin);
    7092             offCurrentCmd += RT_ALIGN_32(cbPayload + sizeof(uint32_t), sizeof(uint32_t));
    7093             if (offCurrentCmd >= offFifoMax)
    7094             {
    7095                 offCurrentCmd -= offFifoMax - offFifoMin;
    7096                 Assert(offCurrentCmd >= offFifoMin);
    7097                 Assert(offCurrentCmd <  offFifoMax);
    7098             }
    7099             ASMAtomicWriteU32(&pFIFO[SVGA_FIFO_STOP], offCurrentCmd);
    7100             STAM_REL_COUNTER_INC(&pSVGAState->StatFifoCommands);
    7101 
    7102             /*
    7103              * Raise IRQ if required.  Must enter the critical section here
    7104              * before making final decisions here, otherwise cubebench and
    7105              * others may end up waiting forever.
    7106              */
    7107             if (   u32IrqStatus
    7108                 || (pThis->svga.u32IrqMask & SVGA_IRQFLAG_FIFO_PROGRESS))
    7109             {
    7110                 int rc2 = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VERR_IGNORED);
    7111                 AssertRC(rc2);
    7112 
    7113                 /* FIFO progress might trigger an interrupt. */
    7114                 if (pThis->svga.u32IrqMask & SVGA_IRQFLAG_FIFO_PROGRESS)
    7115                 {
    7116                     Log(("vmsvgaR3FifoLoop: fifo progress irq\n"));
    7117                     u32IrqStatus |= SVGA_IRQFLAG_FIFO_PROGRESS;
    7118                 }
    7119 
    7120                 /* Unmasked IRQ pending? */
    7121                 if (pThis->svga.u32IrqMask & u32IrqStatus)
    7122                 {
    7123                     Log(("vmsvgaR3FifoLoop: Trigger interrupt with status %x\n", u32IrqStatus));
    7124                     ASMAtomicOrU32(&pThis->svga.u32IrqStatus, u32IrqStatus);
    7125                     PDMDevHlpPCISetIrq(pDevIns, 0, 1);
    7126                 }
    7127 
    7128                 PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect);
    7129             }
    7130         }
    7131 
    7132         /* If really done, clear the busy flag. */
    7133         if (fDone)
    7134         {
    7135             Log(("vmsvgaR3FifoLoop: emptied the FIFO next=%x stop=%x\n", pFIFO[SVGA_FIFO_NEXT_CMD], offCurrentCmd));
    7136             vmsvgaR3FifoSetNotBusy(pDevIns, pThis, pThisCC, pSVGAState, offFifoMin);
    7137         }
    7138     }
    7139 
    7140     /*
    7141      * Free the bounce buffer. (There are no returns above!)
    7142      */
    7143     RTMemFree(pbBounceBuf);
    7144 
    7145     return VINF_SUCCESS;
    7146 }
    7147 
    7148 #undef VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK
    7149 #undef VMSVGAFIFO_GET_CMD_BUFFER_BREAK
    7150 
    7151 #ifdef VBOX_WITH_VMSVGA3D
     2290
     2291
    71522292/**
    71532293 * Free the specified GMR
     
    71562296 * @param   idGMR           GMR id
    71572297 */
    7158 static void vmsvgaR3GmrFree(PVGASTATECC pThisCC, uint32_t idGMR)
     2298void vmsvgaR3GmrFree(PVGASTATECC pThisCC, uint32_t idGMR)
    71592299{
    71602300    PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
     
    71802320}
    71812321#endif /* VBOX_WITH_VMSVGA3D */
     2322
    71822323
    71832324/**
     
    74802621}
    74812622
     2623
    74822624/**
    74832625 * Unsigned coordinates in pBox. Clip to [0; pSize).
     
    75072649}
    75082650
     2651
    75092652/**
    75102653 * Clip.
     
    75692712}
    75702713
    7571 /**
    7572  * @callback_method_impl{PFNPDMTHREADWAKEUPDEV,
    7573  * Unblock the FIFO I/O thread so it can respond to a state change.}
    7574  */
    7575 static DECLCALLBACK(int) vmsvgaR3FifoLoopWakeUp(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
    7576 {
    7577     RT_NOREF(pDevIns);
    7578     PVGASTATE pThis = (PVGASTATE)pThread->pvUser;
    7579     Log(("vmsvgaR3FifoLoopWakeUp\n"));
    7580     return PDMDevHlpSUPSemEventSignal(pDevIns, pThis->svga.hFIFORequestSem);
    7581 }
    7582 
    7583 /**
    7584  * Enables or disables dirty page tracking for the framebuffer
    7585  *
    7586  * @param   pDevIns         The device instance.
    7587  * @param   pThis           The shared VGA/VMSVGA instance data.
    7588  * @param   fTraces         Enable/disable traces
    7589  */
    7590 static void vmsvgaR3SetTraces(PPDMDEVINS pDevIns, PVGASTATE pThis, bool fTraces)
    7591 {
    7592     if (    (!pThis->svga.fConfigured || !pThis->svga.fEnabled)
    7593         &&  !fTraces)
    7594     {
    7595         //Assert(pThis->svga.fTraces);
    7596         Log(("vmsvgaR3SetTraces: *not* allowed to disable dirty page tracking when the device is in legacy mode.\n"));
    7597         return;
    7598     }
    7599 
    7600     pThis->svga.fTraces = fTraces;
    7601     if (pThis->svga.fTraces)
    7602     {
    7603         unsigned cbFrameBuffer = pThis->vram_size;
    7604 
    7605         Log(("vmsvgaR3SetTraces: enable dirty page handling for the frame buffer only (%x bytes)\n", 0));
    7606         /** @todo How does this work with screens? */
    7607         if (pThis->svga.uHeight != VMSVGA_VAL_UNINITIALIZED)
    7608         {
    7609 # ifndef DEBUG_bird /* BB-10.3.1 triggers this as it initializes everything to zero. Better just ignore it. */
    7610             Assert(pThis->svga.cbScanline);
    7611 # endif
    7612             /* Hardware enabled; return real framebuffer size .*/
    7613             cbFrameBuffer = (uint32_t)pThis->svga.uHeight * pThis->svga.cbScanline;
    7614             cbFrameBuffer = RT_ALIGN(cbFrameBuffer, PAGE_SIZE);
    7615         }
    7616 
    7617         if (!pThis->svga.fVRAMTracking)
    7618         {
    7619             Log(("vmsvgaR3SetTraces: enable frame buffer dirty page tracking. (%x bytes; vram %x)\n", cbFrameBuffer, pThis->vram_size));
    7620             vgaR3RegisterVRAMHandler(pDevIns, pThis, cbFrameBuffer);
    7621             pThis->svga.fVRAMTracking = true;
    7622         }
    7623     }
    7624     else
    7625     {
    7626         if (pThis->svga.fVRAMTracking)
    7627         {
    7628             Log(("vmsvgaR3SetTraces: disable frame buffer dirty page tracking\n"));
    7629             vgaR3UnregisterVRAMHandler(pDevIns, pThis);
    7630             pThis->svga.fVRAMTracking = false;
    7631         }
    7632     }
    7633 }
    7634 
    7635 /**
    7636  * @callback_method_impl{FNPCIIOREGIONMAP}
    7637  */
    7638 DECLCALLBACK(int) vmsvgaR3PciIORegionFifoMapUnmap(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion,
    7639                                                   RTGCPHYS GCPhysAddress, RTGCPHYS cb, PCIADDRESSSPACE enmType)
    7640 {
    7641     PVGASTATE   pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
    7642     int         rc;
    7643     RT_NOREF(pPciDev);
    7644     Assert(pPciDev == pDevIns->apPciDevs[0]);
    7645 
    7646     Log(("vmsvgaR3PciIORegionFifoMapUnmap: iRegion=%d GCPhysAddress=%RGp cb=%RGp enmType=%d\n", iRegion, GCPhysAddress, cb, enmType));
    7647     AssertReturn(   iRegion == pThis->pciRegions.iFIFO
    7648                  && (   enmType == PCI_ADDRESS_SPACE_MEM
    7649                      || (enmType == PCI_ADDRESS_SPACE_MEM_PREFETCH /* got wrong in 6.1.0RC1 */ && pThis->fStateLoaded))
    7650                  , VERR_INTERNAL_ERROR);
    7651     if (GCPhysAddress != NIL_RTGCPHYS)
    7652     {
    7653         /*
    7654          * Mapping the FIFO RAM.
    7655          */
    7656         AssertLogRelMsg(cb == pThis->svga.cbFIFO, ("cb=%#RGp cbFIFO=%#x\n", cb, pThis->svga.cbFIFO));
    7657         rc = PDMDevHlpMmio2Map(pDevIns, pThis->hMmio2VmSvgaFifo, GCPhysAddress);
    7658         AssertRC(rc);
    7659 
    7660 # if defined(VMSVGA_USE_FIFO_ACCESS_HANDLER) || defined(DEBUG_FIFO_ACCESS)
    7661         if (RT_SUCCESS(rc))
    7662         {
    7663             rc = PGMHandlerPhysicalRegister(PDMDevHlpGetVM(pDevIns), GCPhysAddress,
    7664 #  ifdef DEBUG_FIFO_ACCESS
    7665                                             GCPhysAddress + (pThis->svga.cbFIFO - 1),
    7666 #  else
    7667                                             GCPhysAddress + PAGE_SIZE - 1,
    7668 #  endif
    7669                                             pThis->svga.hFifoAccessHandlerType, pThis, NIL_RTR0PTR, NIL_RTRCPTR,
    7670                                             "VMSVGA FIFO");
    7671             AssertRC(rc);
    7672         }
    7673 # endif
    7674         if (RT_SUCCESS(rc))
    7675         {
    7676             pThis->svga.GCPhysFIFO = GCPhysAddress;
    7677             Log(("vmsvgaR3IORegionMap: GCPhysFIFO=%RGp cbFIFO=%#x\n", GCPhysAddress, pThis->svga.cbFIFO));
    7678         }
    7679         rc = VINF_PCI_MAPPING_DONE; /* caller only cares about this status, so it is okay that we overwrite errors here. */
    7680     }
    7681     else
    7682     {
    7683         Assert(pThis->svga.GCPhysFIFO);
    7684 # if defined(VMSVGA_USE_FIFO_ACCESS_HANDLER) || defined(DEBUG_FIFO_ACCESS)
    7685         rc = PGMHandlerPhysicalDeregister(PDMDevHlpGetVM(pDevIns), pThis->svga.GCPhysFIFO);
    7686         AssertRC(rc);
    7687 # else
    7688         rc = VINF_SUCCESS;
    7689 # endif
    7690         pThis->svga.GCPhysFIFO = 0;
    7691     }
    7692     return rc;
    7693 }
    7694 
    7695 # ifdef VBOX_WITH_VMSVGA3D
    7696 
    7697 /**
    7698  * Used by vmsvga3dInfoSurfaceWorker to make the FIFO thread to save one or all
    7699  * surfaces to VMSVGA3DMIPMAPLEVEL::pSurfaceData heap buffers.
    7700  *
    7701  * @param   pDevIns     The device instance.
    7702  * @param   pThis       The The shared VGA/VMSVGA instance data.
    7703  * @param   pThisCC     The VGA/VMSVGA state for ring-3.
    7704  * @param   sid         Either UINT32_MAX or the ID of a specific surface.  If
    7705  *                      UINT32_MAX is used, all surfaces are processed.
    7706  */
    7707 void vmsvgaR33dSurfaceUpdateHeapBuffersOnFifoThread(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, uint32_t sid)
    7708 {
    7709     vmsvgaR3RunExtCmdOnFifoThread(pDevIns, pThis, pThisCC, VMSVGA_FIFO_EXTCMD_UPDATE_SURFACE_HEAP_BUFFERS, (void *)(uintptr_t)sid,
    7710                                   sid == UINT32_MAX ? 10 * RT_MS_1SEC : RT_MS_1MIN);
    7711 }
    7712 
    7713 
    7714 /**
    7715  * @callback_method_impl{FNDBGFHANDLERDEV, "vmsvga3dsfc"}
    7716  */
    7717 DECLCALLBACK(void) vmsvgaR3Info3dSurface(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
    7718 {
    7719     /* There might be a specific surface ID at the start of the
    7720        arguments, if not show all surfaces. */
    7721     uint32_t sid = UINT32_MAX;
    7722     if (pszArgs)
    7723         pszArgs = RTStrStripL(pszArgs);
    7724     if (pszArgs && RT_C_IS_DIGIT(*pszArgs))
    7725         sid = RTStrToUInt32(pszArgs);
    7726 
    7727     /* Verbose or terse display, we default to verbose. */
    7728     bool fVerbose = true;
    7729     if (RTStrIStr(pszArgs, "terse"))
    7730         fVerbose = false;
    7731 
    7732     /* The size of the ascii art (x direction, y is 3/4 of x). */
    7733     uint32_t cxAscii = 80;
    7734     if (RTStrIStr(pszArgs, "gigantic"))
    7735         cxAscii = 300;
    7736     else if (RTStrIStr(pszArgs, "huge"))
    7737         cxAscii = 180;
    7738     else if (RTStrIStr(pszArgs, "big"))
    7739         cxAscii = 132;
    7740     else if (RTStrIStr(pszArgs, "normal"))
    7741         cxAscii = 80;
    7742     else if (RTStrIStr(pszArgs, "medium"))
    7743         cxAscii = 64;
    7744     else if (RTStrIStr(pszArgs, "small"))
    7745         cxAscii = 48;
    7746     else if (RTStrIStr(pszArgs, "tiny"))
    7747         cxAscii = 24;
    7748 
    7749     /* Y invert the image when producing the ASCII art. */
    7750     bool fInvY = false;
    7751     if (RTStrIStr(pszArgs, "invy"))
    7752         fInvY = true;
    7753 
    7754     vmsvga3dInfoSurfaceWorker(pDevIns, PDMDEVINS_2_DATA(pDevIns, PVGASTATE), PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC),
    7755                               pHlp, sid, fVerbose, cxAscii, fInvY, NULL);
    7756 }
    7757 
    7758 
    7759 /**
    7760  * @callback_method_impl{FNDBGFHANDLERDEV, "vmsvga3dsurf"}
    7761  */
    7762 DECLCALLBACK(void) vmsvgaR3Info3dSurfaceBmp(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
    7763 {
    7764     /* pszArg = "sid[>dir]"
    7765      * Writes %dir%/info-S-sidI.bmp, where S - sequential bitmap number, I - decimal surface id.
    7766      */
    7767     char *pszBitmapPath = NULL;
    7768     uint32_t sid = UINT32_MAX;
    7769     if (pszArgs)
    7770         pszArgs = RTStrStripL(pszArgs);
    7771     if (pszArgs && RT_C_IS_DIGIT(*pszArgs))
    7772         RTStrToUInt32Ex(pszArgs, &pszBitmapPath, 0, &sid);
    7773     if (   pszBitmapPath
    7774         && *pszBitmapPath == '>')
    7775         ++pszBitmapPath;
    7776 
    7777     const bool fVerbose = true;
    7778     const uint32_t cxAscii = 0; /* No ASCII */
    7779     const bool fInvY = false;   /* Do not invert. */
    7780     vmsvga3dInfoSurfaceWorker(pDevIns, PDMDEVINS_2_DATA(pDevIns, PVGASTATE), PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC),
    7781                               pHlp, sid, fVerbose, cxAscii, fInvY, pszBitmapPath);
    7782 }
    7783 
    7784 /**
    7785  * @callback_method_impl{FNDBGFHANDLERDEV, "vmsvga3dctx"}
    7786  */
    7787 DECLCALLBACK(void) vmsvgaR3Info3dContext(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
    7788 {
    7789     /* There might be a specific surface ID at the start of the
    7790        arguments, if not show all contexts. */
    7791     uint32_t sid = UINT32_MAX;
    7792     if (pszArgs)
    7793         pszArgs = RTStrStripL(pszArgs);
    7794     if (pszArgs && RT_C_IS_DIGIT(*pszArgs))
    7795         sid = RTStrToUInt32(pszArgs);
    7796 
    7797     /* Verbose or terse display, we default to verbose. */
    7798     bool fVerbose = true;
    7799     if (RTStrIStr(pszArgs, "terse"))
    7800         fVerbose = false;
    7801 
    7802     vmsvga3dInfoContextWorker(PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC), pHlp, sid, fVerbose);
    7803 }
    7804 # endif /* VBOX_WITH_VMSVGA3D */
    7805 
    7806 /**
    7807  * @callback_method_impl{FNDBGFHANDLERDEV, "vmsvga"}
    7808  */
    7809 static DECLCALLBACK(void) vmsvgaR3Info(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
    7810 {
    7811     PVGASTATE       pThis      = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
    7812     PVGASTATECC     pThisCC    = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
    7813     PVMSVGAR3STATE  pSVGAState = pThisCC->svga.pSvgaR3State;
    7814     uint32_t RT_UNTRUSTED_VOLATILE_GUEST *pFIFO = pThisCC->svga.pau32FIFO;
    7815     RT_NOREF(pszArgs);
    7816 
    7817     pHlp->pfnPrintf(pHlp, "Extension enabled:  %RTbool\n", pThis->svga.fEnabled);
    7818     pHlp->pfnPrintf(pHlp, "Configured:         %RTbool\n", pThis->svga.fConfigured);
    7819     pHlp->pfnPrintf(pHlp, "Base I/O port:      %#x\n",
    7820                     pThis->hIoPortVmSvga != NIL_IOMIOPORTHANDLE
    7821                     ? PDMDevHlpIoPortGetMappingAddress(pDevIns, pThis->hIoPortVmSvga) : UINT32_MAX);
    7822     pHlp->pfnPrintf(pHlp, "FIFO address:       %RGp\n", pThis->svga.GCPhysFIFO);
    7823     pHlp->pfnPrintf(pHlp, "FIFO size:          %u (%#x)\n", pThis->svga.cbFIFO, pThis->svga.cbFIFO);
    7824     pHlp->pfnPrintf(pHlp, "FIFO external cmd:  %#x\n", pThis->svga.u8FIFOExtCommand);
    7825     pHlp->pfnPrintf(pHlp, "FIFO extcmd wakeup: %u\n", pThis->svga.fFifoExtCommandWakeup);
    7826     pHlp->pfnPrintf(pHlp, "FIFO min/max:       %u/%u\n", pFIFO[SVGA_FIFO_MIN], pFIFO[SVGA_FIFO_MAX]);
    7827     pHlp->pfnPrintf(pHlp, "Busy:               %#x\n", pThis->svga.fBusy);
    7828     pHlp->pfnPrintf(pHlp, "Traces:             %RTbool (effective: %RTbool)\n", pThis->svga.fTraces, pThis->svga.fVRAMTracking);
    7829     pHlp->pfnPrintf(pHlp, "Guest ID:           %#x (%d)\n", pThis->svga.u32GuestId, pThis->svga.u32GuestId);
    7830     pHlp->pfnPrintf(pHlp, "IRQ status:         %#x\n", pThis->svga.u32IrqStatus);
    7831     pHlp->pfnPrintf(pHlp, "IRQ mask:           %#x\n", pThis->svga.u32IrqMask);
    7832     pHlp->pfnPrintf(pHlp, "Pitch lock:         %#x (FIFO:%#x)\n", pThis->svga.u32PitchLock, pFIFO[SVGA_FIFO_PITCHLOCK]);
    7833     pHlp->pfnPrintf(pHlp, "Current GMR ID:     %#x\n", pThis->svga.u32CurrentGMRId);
    7834     pHlp->pfnPrintf(pHlp, "Device Capabilites: %#x\n", pThis->svga.u32DeviceCaps);
    7835     pHlp->pfnPrintf(pHlp, "Index reg:          %#x\n", pThis->svga.u32IndexReg);
    7836     pHlp->pfnPrintf(pHlp, "Action flags:       %#x\n", pThis->svga.u32ActionFlags);
    7837     pHlp->pfnPrintf(pHlp, "Max display size:   %ux%u\n", pThis->svga.u32MaxWidth, pThis->svga.u32MaxHeight);
    7838     pHlp->pfnPrintf(pHlp, "Display size:       %ux%u %ubpp\n", pThis->svga.uWidth, pThis->svga.uHeight, pThis->svga.uBpp);
    7839     pHlp->pfnPrintf(pHlp, "Scanline:           %u (%#x)\n", pThis->svga.cbScanline, pThis->svga.cbScanline);
    7840     pHlp->pfnPrintf(pHlp, "Viewport position:  %ux%u\n", pThis->svga.viewport.x, pThis->svga.viewport.y);
    7841     pHlp->pfnPrintf(pHlp, "Viewport size:      %ux%u\n", pThis->svga.viewport.cx, pThis->svga.viewport.cy);
    7842 
    7843     pHlp->pfnPrintf(pHlp, "Cursor active:      %RTbool\n", pSVGAState->Cursor.fActive);
    7844     pHlp->pfnPrintf(pHlp, "Cursor hotspot:     %ux%u\n", pSVGAState->Cursor.xHotspot, pSVGAState->Cursor.yHotspot);
    7845     pHlp->pfnPrintf(pHlp, "Cursor size:        %ux%u\n", pSVGAState->Cursor.width, pSVGAState->Cursor.height);
    7846     pHlp->pfnPrintf(pHlp, "Cursor byte size:   %u (%#x)\n", pSVGAState->Cursor.cbData, pSVGAState->Cursor.cbData);
    7847 
    7848     pHlp->pfnPrintf(pHlp, "FIFO cursor:        state %u, screen %d\n", pFIFO[SVGA_FIFO_CURSOR_ON], pFIFO[SVGA_FIFO_CURSOR_SCREEN_ID]);
    7849     pHlp->pfnPrintf(pHlp, "FIFO cursor at:     %u,%u\n", pFIFO[SVGA_FIFO_CURSOR_X], pFIFO[SVGA_FIFO_CURSOR_Y]);
    7850 
    7851     pHlp->pfnPrintf(pHlp, "Legacy cursor:      ID %u, state %u\n", pThis->svga.uCursorID, pThis->svga.uCursorOn);
    7852     pHlp->pfnPrintf(pHlp, "Legacy cursor at:   %u,%u\n", pThis->svga.uCursorX, pThis->svga.uCursorY);
    7853 
    7854 # ifdef VBOX_WITH_VMSVGA3D
    7855     pHlp->pfnPrintf(pHlp, "3D enabled:         %RTbool\n", pThis->svga.f3DEnabled);
    7856 # endif
    7857     if (pThisCC->pDrv)
    7858     {
    7859         pHlp->pfnPrintf(pHlp, "Driver mode:        %ux%u %ubpp\n", pThisCC->pDrv->cx, pThisCC->pDrv->cy, pThisCC->pDrv->cBits);
    7860         pHlp->pfnPrintf(pHlp, "Driver pitch:       %u (%#x)\n", pThisCC->pDrv->cbScanline, pThisCC->pDrv->cbScanline);
    7861     }
    7862 
    7863     /* Dump screen information. */
    7864     for (unsigned iScreen = 0; iScreen < RT_ELEMENTS(pSVGAState->aScreens); ++iScreen)
    7865     {
    7866         VMSVGASCREENOBJECT *pScreen = vmsvgaR3GetScreenObject(pThisCC, iScreen);
    7867         if (pScreen)
    7868         {
    7869             pHlp->pfnPrintf(pHlp, "Screen %u defined (ID %u):\n", iScreen, pScreen->idScreen);
    7870             pHlp->pfnPrintf(pHlp, "  %u x %u x %ubpp @ %u, %u\n", pScreen->cWidth, pScreen->cHeight,
    7871                             pScreen->cBpp, pScreen->xOrigin, pScreen->yOrigin);
    7872             pHlp->pfnPrintf(pHlp, "  Pitch %u bytes, VRAM offset %X\n", pScreen->cbPitch, pScreen->offVRAM);
    7873             pHlp->pfnPrintf(pHlp, "  Flags %X", pScreen->fuScreen);
    7874             if (pScreen->fuScreen != SVGA_SCREEN_MUST_BE_SET)
    7875             {
    7876                 pHlp->pfnPrintf(pHlp, " (");
    7877                 if (pScreen->fuScreen & SVGA_SCREEN_IS_PRIMARY)
    7878                     pHlp->pfnPrintf(pHlp, " IS_PRIMARY");
    7879                 if (pScreen->fuScreen & SVGA_SCREEN_FULLSCREEN_HINT)
    7880                     pHlp->pfnPrintf(pHlp, " FULLSCREEN_HINT");
    7881                 if (pScreen->fuScreen & SVGA_SCREEN_DEACTIVATE)
    7882                     pHlp->pfnPrintf(pHlp, " DEACTIVATE");
    7883                 if (pScreen->fuScreen & SVGA_SCREEN_BLANKING)
    7884                     pHlp->pfnPrintf(pHlp, " BLANKING");
    7885                 pHlp->pfnPrintf(pHlp, " )");
    7886             }
    7887             pHlp->pfnPrintf(pHlp, ", %smodified\n", pScreen->fModified ? "" : "not ");
    7888         }
    7889     }
    7890 
    7891 }
    7892 
    7893 /**
    7894  * Portion of VMSVGA state which must be loaded oin the FIFO thread.
    7895  */
    7896 static int vmsvgaR3LoadExecFifo(PCPDMDEVHLPR3 pHlp, PVGASTATE pThis, PVGASTATECC pThisCC,
    7897                                 PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
    7898 {
    7899     RT_NOREF(uPass);
    7900 
    7901     PVMSVGAR3STATE  pSVGAState = pThisCC->svga.pSvgaR3State;
    7902     int rc;
    7903 
    7904     if (uVersion >= VGA_SAVEDSTATE_VERSION_VMSVGA_SCREENS)
    7905     {
    7906         uint32_t cScreens = 0;
    7907         rc = pHlp->pfnSSMGetU32(pSSM, &cScreens);
    7908         AssertRCReturn(rc, rc);
    7909         AssertLogRelMsgReturn(cScreens <= _64K, /* big enough */
    7910                               ("cScreens=%#x\n", cScreens),
    7911                               VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
    7912 
    7913         for (uint32_t i = 0; i < cScreens; ++i)
    7914         {
    7915             VMSVGASCREENOBJECT screen;
    7916             RT_ZERO(screen);
    7917 
    7918             rc = pHlp->pfnSSMGetStructEx(pSSM, &screen, sizeof(screen), 0, g_aVMSVGASCREENOBJECTFields, NULL);
    7919             AssertLogRelRCReturn(rc, rc);
    7920 
    7921             if (screen.idScreen < RT_ELEMENTS(pSVGAState->aScreens))
    7922             {
    7923                 VMSVGASCREENOBJECT *pScreen = &pSVGAState->aScreens[screen.idScreen];
    7924                 *pScreen = screen;
    7925                 pScreen->fModified = true;
    7926             }
    7927             else
    7928             {
    7929                 LogRel(("VGA: ignored screen object %d\n", screen.idScreen));
    7930             }
    7931         }
    7932     }
    7933     else
    7934     {
    7935         /* Try to setup at least the first screen. */
    7936         VMSVGASCREENOBJECT *pScreen = &pSVGAState->aScreens[0];
    7937         pScreen->fDefined  = true;
    7938         pScreen->fModified = true;
    7939         pScreen->fuScreen  = SVGA_SCREEN_MUST_BE_SET | SVGA_SCREEN_IS_PRIMARY;
    7940         pScreen->idScreen  = 0;
    7941         pScreen->xOrigin   = 0;
    7942         pScreen->yOrigin   = 0;
    7943         pScreen->offVRAM   = pThis->svga.uScreenOffset;
    7944         pScreen->cbPitch   = pThis->svga.cbScanline;
    7945         pScreen->cWidth    = pThis->svga.uWidth;
    7946         pScreen->cHeight   = pThis->svga.uHeight;
    7947         pScreen->cBpp      = pThis->svga.uBpp;
    7948     }
    7949 
    7950     return VINF_SUCCESS;
    7951 }
    7952 
    7953 /**
    7954  * @copydoc FNSSMDEVLOADEXEC
    7955  */
    7956 int vmsvgaR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
    7957 {
    7958     RT_NOREF(uPass);
    7959     PVGASTATE       pThis      = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
    7960     PVGASTATECC     pThisCC    = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
    7961     PVMSVGAR3STATE  pSVGAState = pThisCC->svga.pSvgaR3State;
    7962     PCPDMDEVHLPR3   pHlp       = pDevIns->pHlpR3;
    7963     int             rc;
    7964 
    7965     /* Load our part of the VGAState */
    7966     rc = pHlp->pfnSSMGetStructEx(pSSM, &pThis->svga, sizeof(pThis->svga), 0, g_aVGAStateSVGAFields, NULL);
    7967     AssertRCReturn(rc, rc);
    7968 
    7969     /* Load the VGA framebuffer. */
    7970     AssertCompile(VMSVGA_VGA_FB_BACKUP_SIZE >= _32K);
    7971     uint32_t cbVgaFramebuffer = _32K;
    7972     if (uVersion >= VGA_SAVEDSTATE_VERSION_VMSVGA_VGA_FB_FIX)
    7973     {
    7974         rc = pHlp->pfnSSMGetU32(pSSM, &cbVgaFramebuffer);
    7975         AssertRCReturn(rc, rc);
    7976         AssertLogRelMsgReturn(cbVgaFramebuffer <= _4M && cbVgaFramebuffer >= _32K && RT_IS_POWER_OF_TWO(cbVgaFramebuffer),
    7977                               ("cbVgaFramebuffer=%#x - expected 32KB..4MB, power of two\n", cbVgaFramebuffer),
    7978                               VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
    7979         AssertCompile(VMSVGA_VGA_FB_BACKUP_SIZE <= _4M);
    7980         AssertCompile(RT_IS_POWER_OF_TWO(VMSVGA_VGA_FB_BACKUP_SIZE));
    7981     }
    7982     rc = pHlp->pfnSSMGetMem(pSSM, pThisCC->svga.pbVgaFrameBufferR3, RT_MIN(cbVgaFramebuffer, VMSVGA_VGA_FB_BACKUP_SIZE));
    7983     AssertRCReturn(rc, rc);
    7984     if (cbVgaFramebuffer > VMSVGA_VGA_FB_BACKUP_SIZE)
    7985         pHlp->pfnSSMSkip(pSSM, cbVgaFramebuffer - VMSVGA_VGA_FB_BACKUP_SIZE);
    7986     else if (cbVgaFramebuffer < VMSVGA_VGA_FB_BACKUP_SIZE)
    7987         RT_BZERO(&pThisCC->svga.pbVgaFrameBufferR3[cbVgaFramebuffer], VMSVGA_VGA_FB_BACKUP_SIZE - cbVgaFramebuffer);
    7988 
    7989     /* Load the VMSVGA state. */
    7990     rc = pHlp->pfnSSMGetStructEx(pSSM, pSVGAState, sizeof(*pSVGAState), 0, g_aVMSVGAR3STATEFields, NULL);
    7991     AssertRCReturn(rc, rc);
    7992 
    7993     /* Load the active cursor bitmaps. */
    7994     if (pSVGAState->Cursor.fActive)
    7995     {
    7996         pSVGAState->Cursor.pData = RTMemAlloc(pSVGAState->Cursor.cbData);
    7997         AssertReturn(pSVGAState->Cursor.pData, VERR_NO_MEMORY);
    7998 
    7999         rc = pHlp->pfnSSMGetMem(pSSM, pSVGAState->Cursor.pData, pSVGAState->Cursor.cbData);
    8000         AssertRCReturn(rc, rc);
    8001     }
    8002 
    8003     /* Load the GMR state. */
    8004     uint32_t cGMR = 256; /* Hardcoded in previous saved state versions. */
    8005     if (uVersion >= VGA_SAVEDSTATE_VERSION_VMSVGA_GMR_COUNT)
    8006     {
    8007         rc = pHlp->pfnSSMGetU32(pSSM, &cGMR);
    8008         AssertRCReturn(rc, rc);
    8009         /* Numbers of GMRs was never less than 256. 1MB is a large arbitrary limit. */
    8010         AssertLogRelMsgReturn(cGMR <= _1M && cGMR >= 256,
    8011                               ("cGMR=%#x - expected 256B..1MB\n", cGMR),
    8012                               VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
    8013     }
    8014 
    8015     if (pThis->svga.cGMR != cGMR)
    8016     {
    8017         /* Reallocate GMR array. */
    8018         Assert(pSVGAState->paGMR != NULL);
    8019         RTMemFree(pSVGAState->paGMR);
    8020         pSVGAState->paGMR = (PGMR)RTMemAllocZ(cGMR * sizeof(GMR));
    8021         AssertReturn(pSVGAState->paGMR, VERR_NO_MEMORY);
    8022         pThis->svga.cGMR = cGMR;
    8023     }
    8024 
    8025     for (uint32_t i = 0; i < cGMR; ++i)
    8026     {
    8027         PGMR pGMR = &pSVGAState->paGMR[i];
    8028 
    8029         rc = pHlp->pfnSSMGetStructEx(pSSM, pGMR, sizeof(*pGMR), 0, g_aGMRFields, NULL);
    8030         AssertRCReturn(rc, rc);
    8031 
    8032         if (pGMR->numDescriptors)
    8033         {
    8034             Assert(pGMR->cMaxPages || pGMR->cbTotal);
    8035             pGMR->paDesc = (PVMSVGAGMRDESCRIPTOR)RTMemAllocZ(pGMR->numDescriptors * sizeof(VMSVGAGMRDESCRIPTOR));
    8036             AssertReturn(pGMR->paDesc, VERR_NO_MEMORY);
    8037 
    8038             for (uint32_t j = 0; j < pGMR->numDescriptors; ++j)
    8039             {
    8040                 rc = pHlp->pfnSSMGetStructEx(pSSM, &pGMR->paDesc[j], sizeof(pGMR->paDesc[j]), 0, g_aVMSVGAGMRDESCRIPTORFields, NULL);
    8041                 AssertRCReturn(rc, rc);
    8042             }
    8043         }
    8044     }
    8045 
    8046 #  ifdef RT_OS_DARWIN  /** @todo r=bird: this is normally done on the EMT, so for DARWIN we do that when loading saved state too now. See DevVGA-SVGA3d-shared.h. */
    8047     vmsvga3dPowerOn(pDevIns, pThis, PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC));
    8048 #  endif
    8049 
    8050     VMSVGA_STATE_LOAD LoadState;
    8051     LoadState.pSSM     = pSSM;
    8052     LoadState.uVersion = uVersion;
    8053     LoadState.uPass    = uPass;
    8054     rc = vmsvgaR3RunExtCmdOnFifoThread(pDevIns, pThis, pThisCC, VMSVGA_FIFO_EXTCMD_LOADSTATE, &LoadState, RT_INDEFINITE_WAIT);
    8055     AssertLogRelRCReturn(rc, rc);
    8056 
    8057     return VINF_SUCCESS;
    8058 }
    8059 
    8060 /**
    8061  * Reinit the video mode after the state has been loaded.
    8062  */
    8063 int vmsvgaR3LoadDone(PPDMDEVINS pDevIns)
    8064 {
    8065     PVGASTATE       pThis      = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
    8066     PVGASTATECC     pThisCC    = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
    8067     PVMSVGAR3STATE  pSVGAState = pThisCC->svga.pSvgaR3State;
    8068 
    8069     /* Set the active cursor. */
    8070     if (pSVGAState->Cursor.fActive)
    8071     {
    8072         /* We don't store the alpha flag, but we can take a guess that if
    8073          * the old register interface was used, the cursor was B&W.
    8074          */
    8075         bool    fAlpha = pThis->svga.uCursorOn ? false : true;
    8076 
    8077         int rc = pThisCC->pDrv->pfnVBVAMousePointerShape(pThisCC->pDrv,
    8078                                                          true /*fVisible*/,
    8079                                                          fAlpha,
    8080                                                          pSVGAState->Cursor.xHotspot,
    8081                                                          pSVGAState->Cursor.yHotspot,
    8082                                                          pSVGAState->Cursor.width,
    8083                                                          pSVGAState->Cursor.height,
    8084                                                          pSVGAState->Cursor.pData);
    8085         AssertRC(rc);
    8086 
    8087         if (pThis->svga.uCursorOn)
    8088             pThisCC->pDrv->pfnVBVAReportCursorPosition(pThisCC->pDrv, VBVA_CURSOR_VALID_DATA, SVGA_ID_INVALID, pThis->svga.uCursorX, pThis->svga.uCursorY);
    8089     }
    8090 
    8091     /* If the VRAM handler should not be registered, we have to explicitly
    8092      * unregister it here!
    8093      */
    8094     if (!pThis->svga.fVRAMTracking)
    8095     {
    8096         vgaR3UnregisterVRAMHandler(pDevIns, pThis);
    8097     }
    8098 
    8099     /* Let the FIFO thread deal with changing the mode. */
    8100     ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE);
    8101 
    8102     return VINF_SUCCESS;
    8103 }
    8104 
    8105 /**
    8106  * Portion of SVGA state which must be saved in the FIFO thread.
    8107  */
    8108 static int vmsvgaR3SaveExecFifo(PCPDMDEVHLPR3 pHlp, PVGASTATECC pThisCC, PSSMHANDLE pSSM)
    8109 {
    8110     PVMSVGAR3STATE  pSVGAState = pThisCC->svga.pSvgaR3State;
    8111     int             rc;
    8112 
    8113     /* Save the screen objects. */
    8114     /* Count defined screen object. */
    8115     uint32_t cScreens = 0;
    8116     for (uint32_t i = 0; i < RT_ELEMENTS(pSVGAState->aScreens); ++i)
    8117     {
    8118          if (pSVGAState->aScreens[i].fDefined)
    8119              ++cScreens;
    8120     }
    8121 
    8122     rc = pHlp->pfnSSMPutU32(pSSM, cScreens);
    8123     AssertLogRelRCReturn(rc, rc);
    8124 
    8125     for (uint32_t i = 0; i < cScreens; ++i)
    8126     {
    8127         VMSVGASCREENOBJECT *pScreen = &pSVGAState->aScreens[i];
    8128 
    8129         rc = pHlp->pfnSSMPutStructEx(pSSM, pScreen, sizeof(*pScreen), 0, g_aVMSVGASCREENOBJECTFields, NULL);
    8130         AssertLogRelRCReturn(rc, rc);
    8131     }
    8132     return VINF_SUCCESS;
    8133 }
    8134 
    8135 /**
    8136  * @copydoc FNSSMDEVSAVEEXEC
    8137  */
    8138 int vmsvgaR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
    8139 {
    8140     PVGASTATE       pThis      = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
    8141     PVGASTATECC     pThisCC    = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
    8142     PVMSVGAR3STATE  pSVGAState = pThisCC->svga.pSvgaR3State;
    8143     PCPDMDEVHLPR3   pHlp       = pDevIns->pHlpR3;
    8144     int             rc;
    8145 
    8146     /* Save our part of the VGAState */
    8147     rc = pHlp->pfnSSMPutStructEx(pSSM, &pThis->svga, sizeof(pThis->svga), 0, g_aVGAStateSVGAFields, NULL);
    8148     AssertLogRelRCReturn(rc, rc);
    8149 
    8150     /* Save the framebuffer backup. */
    8151     rc = pHlp->pfnSSMPutU32(pSSM, VMSVGA_VGA_FB_BACKUP_SIZE);
    8152     rc = pHlp->pfnSSMPutMem(pSSM, pThisCC->svga.pbVgaFrameBufferR3, VMSVGA_VGA_FB_BACKUP_SIZE);
    8153     AssertLogRelRCReturn(rc, rc);
    8154 
    8155     /* Save the VMSVGA state. */
    8156     rc = pHlp->pfnSSMPutStructEx(pSSM, pSVGAState, sizeof(*pSVGAState), 0, g_aVMSVGAR3STATEFields, NULL);
    8157     AssertLogRelRCReturn(rc, rc);
    8158 
    8159     /* Save the active cursor bitmaps. */
    8160     if (pSVGAState->Cursor.fActive)
    8161     {
    8162         rc = pHlp->pfnSSMPutMem(pSSM, pSVGAState->Cursor.pData, pSVGAState->Cursor.cbData);
    8163         AssertLogRelRCReturn(rc, rc);
    8164     }
    8165 
    8166     /* Save the GMR state */
    8167     rc = pHlp->pfnSSMPutU32(pSSM, pThis->svga.cGMR);
    8168     AssertLogRelRCReturn(rc, rc);
    8169     for (uint32_t i = 0; i < pThis->svga.cGMR; ++i)
    8170     {
    8171         PGMR pGMR = &pSVGAState->paGMR[i];
    8172 
    8173         rc = pHlp->pfnSSMPutStructEx(pSSM, pGMR, sizeof(*pGMR), 0, g_aGMRFields, NULL);
    8174         AssertLogRelRCReturn(rc, rc);
    8175 
    8176         for (uint32_t j = 0; j < pGMR->numDescriptors; ++j)
    8177         {
    8178             rc = pHlp->pfnSSMPutStructEx(pSSM, &pGMR->paDesc[j], sizeof(pGMR->paDesc[j]), 0, g_aVMSVGAGMRDESCRIPTORFields, NULL);
    8179             AssertLogRelRCReturn(rc, rc);
    8180         }
    8181     }
    8182 
    8183     /*
    8184      * Must save some state (3D in particular) in the FIFO thread.
    8185      */
    8186     rc = vmsvgaR3RunExtCmdOnFifoThread(pDevIns, pThis, pThisCC, VMSVGA_FIFO_EXTCMD_SAVESTATE, pSSM, RT_INDEFINITE_WAIT);
    8187     AssertLogRelRCReturn(rc, rc);
    8188 
    8189     return VINF_SUCCESS;
    8190 }
    8191 
    8192 /**
    8193  * Destructor for PVMSVGAR3STATE structure.
    8194  *
    8195  * @param   pThis          The shared VGA/VMSVGA instance data.
    8196  * @param   pSVGAState     Pointer to the structure. It is not deallocated.
    8197  */
    8198 static void vmsvgaR3StateTerm(PVGASTATE pThis, PVMSVGAR3STATE pSVGAState)
    8199 {
    8200 # ifndef VMSVGA_USE_EMT_HALT_CODE
    8201     if (pSVGAState->hBusyDelayedEmts != NIL_RTSEMEVENTMULTI)
    8202     {
    8203         RTSemEventMultiDestroy(pSVGAState->hBusyDelayedEmts);
    8204         pSVGAState->hBusyDelayedEmts = NIL_RTSEMEVENT;
    8205     }
    8206 # endif
    8207 
    8208     if (pSVGAState->Cursor.fActive)
    8209     {
    8210         RTMemFreeZ(pSVGAState->Cursor.pData, pSVGAState->Cursor.cbData);
    8211         pSVGAState->Cursor.pData = NULL;
    8212         pSVGAState->Cursor.fActive = false;
    8213     }
    8214 
    8215     if (pSVGAState->paGMR)
    8216     {
    8217         for (unsigned i = 0; i < pThis->svga.cGMR; ++i)
    8218             if (pSVGAState->paGMR[i].paDesc)
    8219                 RTMemFree(pSVGAState->paGMR[i].paDesc);
    8220 
    8221         RTMemFree(pSVGAState->paGMR);
    8222         pSVGAState->paGMR = NULL;
    8223     }
    8224 
    8225     if (RTCritSectIsInitialized(&pSVGAState->CritSectCmdBuf))
    8226     {
    8227         RTCritSectEnter(&pSVGAState->CritSectCmdBuf);
    8228         for (unsigned i = 0; i < RT_ELEMENTS(pSVGAState->apCmdBufCtxs); ++i)
    8229         {
    8230             vmsvgaR3CmdBufCtxTerm(pSVGAState->apCmdBufCtxs[i]);
    8231             pSVGAState->apCmdBufCtxs[i] = NULL;
    8232         }
    8233         vmsvgaR3CmdBufCtxTerm(&pSVGAState->CmdBufCtxDC);
    8234         RTCritSectLeave(&pSVGAState->CritSectCmdBuf);
    8235         RTCritSectDelete(&pSVGAState->CritSectCmdBuf);
    8236     }
    8237 }
    8238 
    8239 /**
    8240  * Constructor for PVMSVGAR3STATE structure.
    8241  *
    8242  * @returns VBox status code.
    8243  * @param   pThis          The shared VGA/VMSVGA instance data.
    8244  * @param   pSVGAState     Pointer to the structure. It is already allocated.
    8245  */
    8246 static int vmsvgaR3StateInit(PVGASTATE pThis, PVMSVGAR3STATE pSVGAState)
    8247 {
    8248     int rc = VINF_SUCCESS;
    8249     RT_ZERO(*pSVGAState);
    8250 
    8251     pSVGAState->paGMR = (PGMR)RTMemAllocZ(pThis->svga.cGMR * sizeof(GMR));
    8252     AssertReturn(pSVGAState->paGMR, VERR_NO_MEMORY);
    8253 
    8254 # ifndef VMSVGA_USE_EMT_HALT_CODE
    8255     /* Create semaphore for delaying EMTs wait for the FIFO to stop being busy. */
    8256     rc = RTSemEventMultiCreate(&pSVGAState->hBusyDelayedEmts);
    8257     AssertRCReturn(rc, rc);
    8258 # endif
    8259 
    8260     rc = RTCritSectInit(&pSVGAState->CritSectCmdBuf);
    8261     AssertRCReturn(rc, rc);
    8262 
    8263     vmsvgaR3CmdBufCtxInit(&pSVGAState->CmdBufCtxDC);
    8264     return rc;
    8265 }
    8266 
    8267 /**
    8268  * Initializes the host capabilities: device and FIFO.
    8269  *
    8270  * @returns VBox status code.
    8271  * @param   pThis     The shared VGA/VMSVGA instance data.
    8272  * @param   pThisCC   The VGA/VMSVGA state for ring-3.
    8273  */
    8274 static void vmsvgaR3InitCaps(PVGASTATE pThis, PVGASTATECC pThisCC)
    8275 {
    8276     /* Device caps. */
    8277     pThis->svga.u32DeviceCaps = SVGA_CAP_GMR
    8278                               | SVGA_CAP_GMR2
    8279                               | SVGA_CAP_CURSOR
    8280                               | SVGA_CAP_CURSOR_BYPASS
    8281                               | SVGA_CAP_CURSOR_BYPASS_2
    8282                               | SVGA_CAP_EXTENDED_FIFO
    8283                               | SVGA_CAP_IRQMASK
    8284                               | SVGA_CAP_PITCHLOCK
    8285                               | SVGA_CAP_RECT_COPY
    8286                               | SVGA_CAP_TRACES
    8287                               | SVGA_CAP_SCREEN_OBJECT_2
    8288                               | SVGA_CAP_ALPHA_CURSOR;
    8289 
    8290     /* VGPU10 capabilities. */
    8291     if (pThis->fVMSVGA10)
    8292     {
    8293         pThis->svga.u32DeviceCaps |= SVGA_CAP_COMMAND_BUFFERS /* Enable register based command buffer submission. */
    8294 //                                  |  SVGA_CAP_CMD_BUFFERS_2   /* Support for SVGA_REG_CMD_PREPEND_LOW/HIGH */
    8295 //                                  |  SVGA_CAP_GBOBJECTS       /* Enable guest-backed objects and surfaces. */
    8296 //                                  |  SVGA_CAP_CMD_BUFFERS_3   /* AKA SVGA_CAP_DX. Enable support for DX commands, and command buffers in a mob. */
    8297                                   ;
    8298     }
    8299 
    8300 # ifdef VBOX_WITH_VMSVGA3D
    8301     pThis->svga.u32DeviceCaps |= SVGA_CAP_3D;
    8302 # endif
    8303 
    8304     /* Clear the FIFO. */
    8305     RT_BZERO(pThisCC->svga.pau32FIFO, pThis->svga.cbFIFO);
    8306 
    8307     /* Setup FIFO capabilities. */
    8308     pThisCC->svga.pau32FIFO[SVGA_FIFO_CAPABILITIES] = SVGA_FIFO_CAP_FENCE
    8309                                                     | SVGA_FIFO_CAP_PITCHLOCK
    8310                                                     | SVGA_FIFO_CAP_CURSOR_BYPASS_3
    8311                                                     | SVGA_FIFO_CAP_RESERVE
    8312                                                     | SVGA_FIFO_CAP_GMR2
    8313                                                     | SVGA_FIFO_CAP_3D_HWVERSION_REVISED
    8314                                                     | SVGA_FIFO_CAP_SCREEN_OBJECT_2;
    8315 
    8316     /* Valid with SVGA_FIFO_CAP_SCREEN_OBJECT_2 */
    8317     pThisCC->svga.pau32FIFO[SVGA_FIFO_CURSOR_SCREEN_ID] = SVGA_ID_INVALID;
    8318 }
    8319 
    8320 # ifdef VBOX_WITH_VMSVGA3D
    8321 /** Names for the vmsvga 3d capabilities, prefixed with format type hint char. */
    8322 static const char * const g_apszVmSvgaDevCapNames[] =
    8323 {
    8324     "x3D",                           /* = 0 */
    8325     "xMAX_LIGHTS",
    8326     "xMAX_TEXTURES",
    8327     "xMAX_CLIP_PLANES",
    8328     "xVERTEX_SHADER_VERSION",
    8329     "xVERTEX_SHADER",
    8330     "xFRAGMENT_SHADER_VERSION",
    8331     "xFRAGMENT_SHADER",
    8332     "xMAX_RENDER_TARGETS",
    8333     "xS23E8_TEXTURES",
    8334     "xS10E5_TEXTURES",
    8335     "xMAX_FIXED_VERTEXBLEND",
    8336     "xD16_BUFFER_FORMAT",
    8337     "xD24S8_BUFFER_FORMAT",
    8338     "xD24X8_BUFFER_FORMAT",
    8339     "xQUERY_TYPES",
    8340     "xTEXTURE_GRADIENT_SAMPLING",
    8341     "rMAX_POINT_SIZE",
    8342     "xMAX_SHADER_TEXTURES",
    8343     "xMAX_TEXTURE_WIDTH",
    8344     "xMAX_TEXTURE_HEIGHT",
    8345     "xMAX_VOLUME_EXTENT",
    8346     "xMAX_TEXTURE_REPEAT",
    8347     "xMAX_TEXTURE_ASPECT_RATIO",
    8348     "xMAX_TEXTURE_ANISOTROPY",
    8349     "xMAX_PRIMITIVE_COUNT",
    8350     "xMAX_VERTEX_INDEX",
    8351     "xMAX_VERTEX_SHADER_INSTRUCTIONS",
    8352     "xMAX_FRAGMENT_SHADER_INSTRUCTIONS",
    8353     "xMAX_VERTEX_SHADER_TEMPS",
    8354     "xMAX_FRAGMENT_SHADER_TEMPS",
    8355     "xTEXTURE_OPS",
    8356     "xSURFACEFMT_X8R8G8B8",
    8357     "xSURFACEFMT_A8R8G8B8",
    8358     "xSURFACEFMT_A2R10G10B10",
    8359     "xSURFACEFMT_X1R5G5B5",
    8360     "xSURFACEFMT_A1R5G5B5",
    8361     "xSURFACEFMT_A4R4G4B4",
    8362     "xSURFACEFMT_R5G6B5",
    8363     "xSURFACEFMT_LUMINANCE16",
    8364     "xSURFACEFMT_LUMINANCE8_ALPHA8",
    8365     "xSURFACEFMT_ALPHA8",
    8366     "xSURFACEFMT_LUMINANCE8",
    8367     "xSURFACEFMT_Z_D16",
    8368     "xSURFACEFMT_Z_D24S8",
    8369     "xSURFACEFMT_Z_D24X8",
    8370     "xSURFACEFMT_DXT1",
    8371     "xSURFACEFMT_DXT2",
    8372     "xSURFACEFMT_DXT3",
    8373     "xSURFACEFMT_DXT4",
    8374     "xSURFACEFMT_DXT5",
    8375     "xSURFACEFMT_BUMPX8L8V8U8",
    8376     "xSURFACEFMT_A2W10V10U10",
    8377     "xSURFACEFMT_BUMPU8V8",
    8378     "xSURFACEFMT_Q8W8V8U8",
    8379     "xSURFACEFMT_CxV8U8",
    8380     "xSURFACEFMT_R_S10E5",
    8381     "xSURFACEFMT_R_S23E8",
    8382     "xSURFACEFMT_RG_S10E5",
    8383     "xSURFACEFMT_RG_S23E8",
    8384     "xSURFACEFMT_ARGB_S10E5",
    8385     "xSURFACEFMT_ARGB_S23E8",
    8386     "xMISSING62",
    8387     "xMAX_VERTEX_SHADER_TEXTURES",
    8388     "xMAX_SIMULTANEOUS_RENDER_TARGETS",
    8389     "xSURFACEFMT_V16U16",
    8390     "xSURFACEFMT_G16R16",
    8391     "xSURFACEFMT_A16B16G16R16",
    8392     "xSURFACEFMT_UYVY",
    8393     "xSURFACEFMT_YUY2",
    8394     "xMULTISAMPLE_NONMASKABLESAMPLES",
    8395     "xMULTISAMPLE_MASKABLESAMPLES",
    8396     "xALPHATOCOVERAGE",
    8397     "xSUPERSAMPLE",
    8398     "xAUTOGENMIPMAPS",
    8399     "xSURFACEFMT_NV12",
    8400     "xSURFACEFMT_AYUV",
    8401     "xMAX_CONTEXT_IDS",
    8402     "xMAX_SURFACE_IDS",
    8403     "xSURFACEFMT_Z_DF16",
    8404     "xSURFACEFMT_Z_DF24",
    8405     "xSURFACEFMT_Z_D24S8_INT",
    8406     "xSURFACEFMT_ATI1",
    8407     "xSURFACEFMT_ATI2", /* 83 */
    8408     "xDEAD1",
    8409     "xVIDEO_DECODE",
    8410     "xVIDEO_PROCESS",
    8411     "xLINE_AA",
    8412     "xLINE_STIPPLE",
    8413     "rMAX_LINE_WIDTH",
    8414     "rMAX_AA_LINE_WIDTH",
    8415     "xSURFACEFMT_YV12",
    8416     "xLOGICOPS",
    8417     "xTS_COLOR_KEY",
    8418     "xDEAD2",
    8419     "xDX",
    8420     "xMAX_TEXTURE_ARRAY_SIZE",
    8421     "xDX_MAX_VERTEXBUFFERS",
    8422     "xDX_MAX_CONSTANT_BUFFERS",
    8423     "xDX_PROVOKING_VERTEX",
    8424     "xDXFMT_X8R8G8B8",
    8425     "xDXFMT_A8R8G8B8",
    8426     "xDXFMT_R5G6B5",
    8427     "xDXFMT_X1R5G5B5",
    8428     "xDXFMT_A1R5G5B5",
    8429     "xDXFMT_A4R4G4B4",
    8430     "xDXFMT_Z_D32",
    8431     "xDXFMT_Z_D16",
    8432     "xDXFMT_Z_D24S8",
    8433     "xDXFMT_Z_D15S1",
    8434     "xDXFMT_LUMINANCE8",
    8435     "xDXFMT_LUMINANCE4_ALPHA4",
    8436     "xDXFMT_LUMINANCE16",
    8437     "xDXFMT_LUMINANCE8_ALPHA8",
    8438     "xDXFMT_DXT1",
    8439     "xDXFMT_DXT2",
    8440     "xDXFMT_DXT3",
    8441     "xDXFMT_DXT4",
    8442     "xDXFMT_DXT5",
    8443     "xDXFMT_BUMPU8V8",
    8444     "xDXFMT_BUMPL6V5U5",
    8445     "xDXFMT_BUMPX8L8V8U8",
    8446     "xDXFMT_FORMAT_DEAD1",
    8447     "xDXFMT_ARGB_S10E5",
    8448     "xDXFMT_ARGB_S23E8",
    8449     "xDXFMT_A2R10G10B10",
    8450     "xDXFMT_V8U8",
    8451     "xDXFMT_Q8W8V8U8",
    8452     "xDXFMT_CxV8U8",
    8453     "xDXFMT_X8L8V8U8",
    8454     "xDXFMT_A2W10V10U10",
    8455     "xDXFMT_ALPHA8",
    8456     "xDXFMT_R_S10E5",
    8457     "xDXFMT_R_S23E8",
    8458     "xDXFMT_RG_S10E5",
    8459     "xDXFMT_RG_S23E8",
    8460     "xDXFMT_BUFFER",
    8461     "xDXFMT_Z_D24X8",
    8462     "xDXFMT_V16U16",
    8463     "xDXFMT_G16R16",
    8464     "xDXFMT_A16B16G16R16",
    8465     "xDXFMT_UYVY",
    8466     "xDXFMT_YUY2",
    8467     "xDXFMT_NV12",
    8468     "xDXFMT_AYUV",
    8469     "xDXFMT_R32G32B32A32_TYPELESS",
    8470     "xDXFMT_R32G32B32A32_UINT",
    8471     "xDXFMT_R32G32B32A32_SINT",
    8472     "xDXFMT_R32G32B32_TYPELESS",
    8473     "xDXFMT_R32G32B32_FLOAT",
    8474     "xDXFMT_R32G32B32_UINT",
    8475     "xDXFMT_R32G32B32_SINT",
    8476     "xDXFMT_R16G16B16A16_TYPELESS",
    8477     "xDXFMT_R16G16B16A16_UINT",
    8478     "xDXFMT_R16G16B16A16_SNORM",
    8479     "xDXFMT_R16G16B16A16_SINT",
    8480     "xDXFMT_R32G32_TYPELESS",
    8481     "xDXFMT_R32G32_UINT",
    8482     "xDXFMT_R32G32_SINT",
    8483     "xDXFMT_R32G8X24_TYPELESS",
    8484     "xDXFMT_D32_FLOAT_S8X24_UINT",
    8485     "xDXFMT_R32_FLOAT_X8X24_TYPELESS",
    8486     "xDXFMT_X32_TYPELESS_G8X24_UINT",
    8487     "xDXFMT_R10G10B10A2_TYPELESS",
    8488     "xDXFMT_R10G10B10A2_UINT",
    8489     "xDXFMT_R11G11B10_FLOAT",
    8490     "xDXFMT_R8G8B8A8_TYPELESS",
    8491     "xDXFMT_R8G8B8A8_UNORM",
    8492     "xDXFMT_R8G8B8A8_UNORM_SRGB",
    8493     "xDXFMT_R8G8B8A8_UINT",
    8494     "xDXFMT_R8G8B8A8_SINT",
    8495     "xDXFMT_R16G16_TYPELESS",
    8496     "xDXFMT_R16G16_UINT",
    8497     "xDXFMT_R16G16_SINT",
    8498     "xDXFMT_R32_TYPELESS",
    8499     "xDXFMT_D32_FLOAT",
    8500     "xDXFMT_R32_UINT",
    8501     "xDXFMT_R32_SINT",
    8502     "xDXFMT_R24G8_TYPELESS",
    8503     "xDXFMT_D24_UNORM_S8_UINT",
    8504     "xDXFMT_R24_UNORM_X8_TYPELESS",
    8505     "xDXFMT_X24_TYPELESS_G8_UINT",
    8506     "xDXFMT_R8G8_TYPELESS",
    8507     "xDXFMT_R8G8_UNORM",
    8508     "xDXFMT_R8G8_UINT",
    8509     "xDXFMT_R8G8_SINT",
    8510     "xDXFMT_R16_TYPELESS",
    8511     "xDXFMT_R16_UNORM",
    8512     "xDXFMT_R16_UINT",
    8513     "xDXFMT_R16_SNORM",
    8514     "xDXFMT_R16_SINT",
    8515     "xDXFMT_R8_TYPELESS",
    8516     "xDXFMT_R8_UNORM",
    8517     "xDXFMT_R8_UINT",
    8518     "xDXFMT_R8_SNORM",
    8519     "xDXFMT_R8_SINT",
    8520     "xDXFMT_P8",
    8521     "xDXFMT_R9G9B9E5_SHAREDEXP",
    8522     "xDXFMT_R8G8_B8G8_UNORM",
    8523     "xDXFMT_G8R8_G8B8_UNORM",
    8524     "xDXFMT_BC1_TYPELESS",
    8525     "xDXFMT_BC1_UNORM_SRGB",
    8526     "xDXFMT_BC2_TYPELESS",
    8527     "xDXFMT_BC2_UNORM_SRGB",
    8528     "xDXFMT_BC3_TYPELESS",
    8529     "xDXFMT_BC3_UNORM_SRGB",
    8530     "xDXFMT_BC4_TYPELESS",
    8531     "xDXFMT_ATI1",
    8532     "xDXFMT_BC4_SNORM",
    8533     "xDXFMT_BC5_TYPELESS",
    8534     "xDXFMT_ATI2",
    8535     "xDXFMT_BC5_SNORM",
    8536     "xDXFMT_R10G10B10_XR_BIAS_A2_UNORM",
    8537     "xDXFMT_B8G8R8A8_TYPELESS",
    8538     "xDXFMT_B8G8R8A8_UNORM_SRGB",
    8539     "xDXFMT_B8G8R8X8_TYPELESS",
    8540     "xDXFMT_B8G8R8X8_UNORM_SRGB",
    8541     "xDXFMT_Z_DF16",
    8542     "xDXFMT_Z_DF24",
    8543     "xDXFMT_Z_D24S8_INT",
    8544     "xDXFMT_YV12",
    8545     "xDXFMT_R32G32B32A32_FLOAT",
    8546     "xDXFMT_R16G16B16A16_FLOAT",
    8547     "xDXFMT_R16G16B16A16_UNORM",
    8548     "xDXFMT_R32G32_FLOAT",
    8549     "xDXFMT_R10G10B10A2_UNORM",
    8550     "xDXFMT_R8G8B8A8_SNORM",
    8551     "xDXFMT_R16G16_FLOAT",
    8552     "xDXFMT_R16G16_UNORM",
    8553     "xDXFMT_R16G16_SNORM",
    8554     "xDXFMT_R32_FLOAT",
    8555     "xDXFMT_R8G8_SNORM",
    8556     "xDXFMT_R16_FLOAT",
    8557     "xDXFMT_D16_UNORM",
    8558     "xDXFMT_A8_UNORM",
    8559     "xDXFMT_BC1_UNORM",
    8560     "xDXFMT_BC2_UNORM",
    8561     "xDXFMT_BC3_UNORM",
    8562     "xDXFMT_B5G6R5_UNORM",
    8563     "xDXFMT_B5G5R5A1_UNORM",
    8564     "xDXFMT_B8G8R8A8_UNORM",
    8565     "xDXFMT_B8G8R8X8_UNORM",
    8566     "xDXFMT_BC4_UNORM",
    8567     "xDXFMT_BC5_UNORM",
    8568 };
    8569 
    8570 /**
    8571  * Initializes the host 3D capabilities and writes them to FIFO memory.
    8572  *
    8573  * @returns VBox status code.
    8574  * @param   pThis     The shared VGA/VMSVGA instance data.
    8575  * @param   pThisCC   The VGA/VMSVGA state for ring-3.
    8576  */
    8577 static void vmsvgaR3InitFifo3DCaps(PVGASTATE pThis, PVGASTATECC pThisCC)
    8578 {
    8579     /* Query the capabilities and store them in the pThis->svga.au32DevCaps array. */
    8580     bool const fSavedBuffering = RTLogRelSetBuffering(true);
    8581 
    8582     for (unsigned i = 0; i < RT_ELEMENTS(pThis->svga.au32DevCaps); ++i)
    8583     {
    8584         uint32_t val = 0;
    8585         int rc = vmsvga3dQueryCaps(pThisCC, i, &val);
    8586         if (RT_SUCCESS(rc))
    8587             pThis->svga.au32DevCaps[i] = val;
    8588         else
    8589             pThis->svga.au32DevCaps[i] = 0;
    8590 
    8591         /* LogRel the capability value. */
    8592         if (i < RT_ELEMENTS(g_apszVmSvgaDevCapNames))
    8593         {
    8594             if (RT_SUCCESS(rc))
    8595             {
    8596                 if (g_apszVmSvgaDevCapNames[i][0] == 'x')
    8597                     LogRel(("VMSVGA3d: cap[%u]=%#010x {%s}\n", i, val, &g_apszVmSvgaDevCapNames[i][1]));
    8598                 else
    8599                 {
    8600                     float const fval = *(float *)&val;
    8601                     LogRel(("VMSVGA3d: cap[%u]=" FLOAT_FMT_STR " {%s}\n", i, FLOAT_FMT_ARGS(fval), &g_apszVmSvgaDevCapNames[i][1]));
    8602                 }
    8603             }
    8604             else
    8605                 LogRel(("VMSVGA3d: cap[%u]=failed rc=%Rrc {%s}\n", i, rc, &g_apszVmSvgaDevCapNames[i][1]));
    8606         }
    8607         else
    8608             LogRel(("VMSVGA3d: new cap[%u]=%#010x rc=%Rrc\n", i, val, rc));
    8609     }
    8610 
    8611     RTLogRelSetBuffering(fSavedBuffering);
    8612 
    8613     /* 3d hardware version; latest and greatest */
    8614     pThisCC->svga.pau32FIFO[SVGA_FIFO_3D_HWVERSION_REVISED] = SVGA3D_HWVERSION_CURRENT;
    8615     pThisCC->svga.pau32FIFO[SVGA_FIFO_3D_HWVERSION]         = SVGA3D_HWVERSION_CURRENT;
    8616 
    8617     /* Fill out 3d capabilities up to SVGA3D_DEVCAP_SURFACEFMT_ATI2 in the FIFO memory.
    8618      * SVGA3D_DEVCAP_SURFACEFMT_ATI2 is the last capabiltiy for pre-SVGA_CAP_GBOBJECTS hardware.
    8619      * If the VMSVGA device supports SVGA_CAP_GBOBJECTS capability, then the guest has to use SVGA_REG_DEV_CAP
    8620      * register to query the devcaps. Older guests will still try to read the devcaps from FIFO.
    8621      */
    8622     SVGA3dCapsRecord *pCaps;
    8623     SVGA3dCapPair    *pData;
    8624 
    8625     pCaps = (SVGA3dCapsRecord *)&pThisCC->svga.pau32FIFO[SVGA_FIFO_3D_CAPS];
    8626     pCaps->header.type   = SVGA3DCAPS_RECORD_DEVCAPS;
    8627     pData = (SVGA3dCapPair *)&pCaps->data;
    8628 
    8629     AssertCompile(SVGA3D_DEVCAP_DEAD1 == SVGA3D_DEVCAP_SURFACEFMT_ATI2 + 1);
    8630     for (unsigned i = 0; i < SVGA3D_DEVCAP_DEAD1; ++i)
    8631     {
    8632         pData[i][0] = i;
    8633         pData[i][1] = pThis->svga.au32DevCaps[i];
    8634     }
    8635     pCaps->header.length = (sizeof(pCaps->header) + SVGA3D_DEVCAP_DEAD1 * sizeof(SVGA3dCapPair)) / sizeof(uint32_t);
    8636     pCaps = (SVGA3dCapsRecord *)((uint32_t *)pCaps + pCaps->header.length);
    8637 
    8638     /* Mark end of record array (a zero word). */
    8639     pCaps->header.length = 0;
    8640 }
    8641 
    8642 # endif
    8643 
    8644 /**
    8645  * Resets the SVGA hardware state
    8646  *
    8647  * @returns VBox status code.
    8648  * @param   pDevIns     The device instance.
    8649  */
    8650 int vmsvgaR3Reset(PPDMDEVINS pDevIns)
    8651 {
    8652     PVGASTATE       pThis      = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
    8653     PVGASTATECC     pThisCC    = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
    8654     PVMSVGAR3STATE  pSVGAState = pThisCC->svga.pSvgaR3State;
    8655 
    8656     /* Reset before init? */
    8657     if (!pSVGAState)
    8658         return VINF_SUCCESS;
    8659 
    8660     Log(("vmsvgaR3Reset\n"));
    8661 
    8662     /* Reset the FIFO processing as well as the 3d state (if we have one). */
    8663     pThisCC->svga.pau32FIFO[SVGA_FIFO_NEXT_CMD] = pThisCC->svga.pau32FIFO[SVGA_FIFO_STOP] = 0; /** @todo should probably let the FIFO thread do this ... */
    8664     int rc = vmsvgaR3RunExtCmdOnFifoThread(pDevIns, pThis, pThisCC, VMSVGA_FIFO_EXTCMD_RESET, NULL /*pvParam*/, 10000 /*ms*/);
    8665 
    8666     /* Reset other stuff. */
    8667     pThis->svga.cScratchRegion = VMSVGA_SCRATCH_SIZE;
    8668     RT_ZERO(pThis->svga.au32ScratchRegion);
    8669 
    8670     vmsvgaR3StateTerm(pThis, pThisCC->svga.pSvgaR3State);
    8671     vmsvgaR3StateInit(pThis, pThisCC->svga.pSvgaR3State);
    8672 
    8673     RT_BZERO(pThisCC->svga.pbVgaFrameBufferR3, VMSVGA_VGA_FB_BACKUP_SIZE);
    8674 
    8675     /* Initialize FIFO and register capabilities. */
    8676     vmsvgaR3InitCaps(pThis, pThisCC);
    8677 
    8678 # ifdef VBOX_WITH_VMSVGA3D
    8679     if (pThis->svga.f3DEnabled)
    8680         vmsvgaR3InitFifo3DCaps(pThis, pThisCC);
    8681 # endif
    8682 
    8683     /* VRAM tracking is enabled by default during bootup. */
    8684     pThis->svga.fVRAMTracking = true;
    8685     pThis->svga.fEnabled      = false;
    8686 
    8687     /* Invalidate current settings. */
    8688     pThis->svga.uWidth       = VMSVGA_VAL_UNINITIALIZED;
    8689     pThis->svga.uHeight      = VMSVGA_VAL_UNINITIALIZED;
    8690     pThis->svga.uBpp         = pThis->svga.uHostBpp;
    8691     pThis->svga.cbScanline   = 0;
    8692     pThis->svga.u32PitchLock = 0;
    8693 
    8694     return rc;
    8695 }
    8696 
    8697 /**
    8698  * Cleans up the SVGA hardware state
    8699  *
    8700  * @returns VBox status code.
    8701  * @param   pDevIns     The device instance.
    8702  */
    8703 int vmsvgaR3Destruct(PPDMDEVINS pDevIns)
    8704 {
    8705     PVGASTATE   pThis   = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
    8706     PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
    8707 
    8708     /*
    8709      * Ask the FIFO thread to terminate the 3d state and then terminate it.
    8710      */
    8711     if (pThisCC->svga.pFIFOIOThread)
    8712     {
    8713         int rc = vmsvgaR3RunExtCmdOnFifoThread(pDevIns, pThis, pThisCC,  VMSVGA_FIFO_EXTCMD_TERMINATE,
    8714                                                NULL /*pvParam*/, 30000 /*ms*/);
    8715         AssertLogRelRC(rc);
    8716 
    8717         rc = PDMDevHlpThreadDestroy(pDevIns, pThisCC->svga.pFIFOIOThread, NULL);
    8718         AssertLogRelRC(rc);
    8719         pThisCC->svga.pFIFOIOThread = NULL;
    8720     }
    8721 
    8722     /*
    8723      * Destroy the special SVGA state.
    8724      */
    8725     if (pThisCC->svga.pSvgaR3State)
    8726     {
    8727         vmsvgaR3StateTerm(pThis, pThisCC->svga.pSvgaR3State);
    8728 
    8729         RTMemFree(pThisCC->svga.pSvgaR3State);
    8730         pThisCC->svga.pSvgaR3State = NULL;
    8731     }
    8732 
    8733     /*
    8734      * Free our resources residing in the VGA state.
    8735      */
    8736     if (pThisCC->svga.pbVgaFrameBufferR3)
    8737     {
    8738         RTMemFree(pThisCC->svga.pbVgaFrameBufferR3);
    8739         pThisCC->svga.pbVgaFrameBufferR3 = NULL;
    8740     }
    8741     if (pThisCC->svga.hFIFOExtCmdSem != NIL_RTSEMEVENT)
    8742     {
    8743         RTSemEventDestroy(pThisCC->svga.hFIFOExtCmdSem);
    8744         pThisCC->svga.hFIFOExtCmdSem = NIL_RTSEMEVENT;
    8745     }
    8746     if (pThis->svga.hFIFORequestSem != NIL_SUPSEMEVENT)
    8747     {
    8748         PDMDevHlpSUPSemEventClose(pDevIns, pThis->svga.hFIFORequestSem);
    8749         pThis->svga.hFIFORequestSem = NIL_SUPSEMEVENT;
    8750     }
    8751 
    8752     return VINF_SUCCESS;
    8753 }
    8754 
    8755 /**
    8756  * Initialize the SVGA hardware state
    8757  *
    8758  * @returns VBox status code.
    8759  * @param   pDevIns     The device instance.
    8760  */
    8761 int vmsvgaR3Init(PPDMDEVINS pDevIns)
    8762 {
    8763     PVGASTATE       pThis   = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
    8764     PVGASTATECC     pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
    8765     PVMSVGAR3STATE  pSVGAState;
    8766     int             rc;
    8767 
    8768     pThis->svga.cScratchRegion = VMSVGA_SCRATCH_SIZE;
    8769     memset(pThis->svga.au32ScratchRegion, 0, sizeof(pThis->svga.au32ScratchRegion));
    8770 
    8771     pThis->svga.cGMR = VMSVGA_MAX_GMR_IDS;
    8772 
    8773     /* Necessary for creating a backup of the text mode frame buffer when switching into svga mode. */
    8774     pThisCC->svga.pbVgaFrameBufferR3 = (uint8_t *)RTMemAllocZ(VMSVGA_VGA_FB_BACKUP_SIZE);
    8775     AssertReturn(pThisCC->svga.pbVgaFrameBufferR3, VERR_NO_MEMORY);
    8776 
    8777     /* Create event semaphore. */
    8778     rc = PDMDevHlpSUPSemEventCreate(pDevIns, &pThis->svga.hFIFORequestSem);
    8779     AssertRCReturn(rc, rc);
    8780 
    8781     /* Create event semaphore. */
    8782     rc = RTSemEventCreate(&pThisCC->svga.hFIFOExtCmdSem);
    8783     AssertRCReturn(rc, rc);
    8784 
    8785     pThisCC->svga.pSvgaR3State = (PVMSVGAR3STATE)RTMemAlloc(sizeof(VMSVGAR3STATE));
    8786     AssertReturn(pThisCC->svga.pSvgaR3State, VERR_NO_MEMORY);
    8787 
    8788     rc = vmsvgaR3StateInit(pThis, pThisCC->svga.pSvgaR3State);
    8789     AssertMsgRCReturn(rc, ("Failed to create pSvgaR3State.\n"), rc);
    8790 
    8791     pSVGAState = pThisCC->svga.pSvgaR3State;
    8792 
    8793     /* Initialize FIFO and register capabilities. */
    8794     vmsvgaR3InitCaps(pThis, pThisCC);
    8795 
    8796 # ifdef VBOX_WITH_VMSVGA3D
    8797     if (pThis->svga.f3DEnabled)
    8798     {
    8799         rc = vmsvga3dInit(pDevIns, pThis, pThisCC);
    8800         if (RT_FAILURE(rc))
    8801         {
    8802             LogRel(("VMSVGA3d: 3D support disabled! (vmsvga3dInit -> %Rrc)\n", rc));
    8803             pThis->svga.f3DEnabled = false;
    8804         }
    8805     }
    8806 # endif
    8807     /* VRAM tracking is enabled by default during bootup. */
    8808     pThis->svga.fVRAMTracking = true;
    8809 
    8810     /* Set up the host bpp. This value is as a default for the programmable
    8811      * bpp value. On old implementations, SVGA_REG_HOST_BITS_PER_PIXEL did not
    8812      * exist and SVGA_REG_BITS_PER_PIXEL was read-only, returning what was later
    8813      * separated as SVGA_REG_HOST_BITS_PER_PIXEL.
    8814      *
    8815      * NB: The driver cBits value is currently constant for the lifetime of the
    8816      * VM. If that changes, the host bpp logic might need revisiting.
    8817      */
    8818     pThis->svga.uHostBpp = (pThisCC->pDrv->cBits + 7) & ~7;
    8819 
    8820     /* Invalidate current settings. */
    8821     pThis->svga.uWidth     = VMSVGA_VAL_UNINITIALIZED;
    8822     pThis->svga.uHeight    = VMSVGA_VAL_UNINITIALIZED;
    8823     pThis->svga.uBpp       = pThis->svga.uHostBpp;
    8824     pThis->svga.cbScanline = 0;
    8825 
    8826     pThis->svga.u32MaxWidth  = VBE_DISPI_MAX_YRES;
    8827     pThis->svga.u32MaxHeight = VBE_DISPI_MAX_XRES;
    8828     while (pThis->svga.u32MaxWidth * pThis->svga.u32MaxHeight * 4 /* 32 bpp */ > pThis->vram_size)
    8829     {
    8830         pThis->svga.u32MaxWidth  -= 256;
    8831         pThis->svga.u32MaxHeight -= 256;
    8832     }
    8833     Log(("VMSVGA: Maximum size (%d,%d)\n", pThis->svga.u32MaxWidth, pThis->svga.u32MaxHeight));
    8834 
    8835 # ifdef DEBUG_GMR_ACCESS
    8836     /* Register the GMR access handler type. */
    8837     rc = PGMR3HandlerPhysicalTypeRegister(PDMDevHlpGetVM(pDevIns), PGMPHYSHANDLERKIND_WRITE,
    8838                                           vmsvgaR3GmrAccessHandler,
    8839                                           NULL, NULL, NULL,
    8840                                           NULL, NULL, NULL,
    8841                                           "VMSVGA GMR", &pThis->svga.hGmrAccessHandlerType);
    8842     AssertRCReturn(rc, rc);
    8843 # endif
    8844 
    8845 # if defined(VMSVGA_USE_FIFO_ACCESS_HANDLER) || defined(DEBUG_FIFO_ACCESS)
    8846     /* Register the FIFO access handler type.  In addition to
    8847        debugging FIFO access, this is also used to facilitate
    8848        extended fifo thread sleeps. */
    8849     rc = PGMR3HandlerPhysicalTypeRegister(PDMDevHlpGetVM(pDevIns),
    8850 #  ifdef DEBUG_FIFO_ACCESS
    8851                                           PGMPHYSHANDLERKIND_ALL,
    8852 #  else
    8853                                           PGMPHYSHANDLERKIND_WRITE,
    8854 #  endif
    8855                                           vmsvgaR3FifoAccessHandler,
    8856                                           NULL, NULL, NULL,
    8857                                           NULL, NULL, NULL,
    8858                                           "VMSVGA FIFO", &pThis->svga.hFifoAccessHandlerType);
    8859     AssertRCReturn(rc, rc);
    8860 # endif
    8861 
    8862     /* Create the async IO thread. */
    8863     rc = PDMDevHlpThreadCreate(pDevIns, &pThisCC->svga.pFIFOIOThread, pThis, vmsvgaR3FifoLoop, vmsvgaR3FifoLoopWakeUp, 0,
    8864                                RTTHREADTYPE_IO, "VMSVGA FIFO");
    8865     if (RT_FAILURE(rc))
    8866     {
    8867         AssertMsgFailed(("%s: Async IO Thread creation for FIFO handling failed rc=%d\n", __FUNCTION__, rc));
    8868         return rc;
    8869     }
    8870 
    8871     /*
    8872      * Statistics.
    8873      */
    8874 # define REG_CNT(a_pvSample, a_pszName, a_pszDesc) \
    8875         PDMDevHlpSTAMRegister(pDevIns, (a_pvSample), STAMTYPE_COUNTER, a_pszName, STAMUNIT_OCCURENCES, a_pszDesc)
    8876 # define REG_PRF(a_pvSample, a_pszName, a_pszDesc) \
    8877         PDMDevHlpSTAMRegister(pDevIns, (a_pvSample), STAMTYPE_PROFILE, a_pszName, STAMUNIT_TICKS_PER_CALL, a_pszDesc)
    8878 # ifdef VBOX_WITH_STATISTICS
    8879     REG_PRF(&pSVGAState->StatR3Cmd3dDrawPrimitivesProf,   "VMSVGA/Cmd/3dDrawPrimitivesProf",       "Profiling of SVGA_3D_CMD_DRAW_PRIMITIVES.");
    8880     REG_PRF(&pSVGAState->StatR3Cmd3dPresentProf,          "VMSVGA/Cmd/3dPresentProfBoth",          "Profiling of SVGA_3D_CMD_PRESENT and SVGA_3D_CMD_PRESENT_READBACK.");
    8881     REG_PRF(&pSVGAState->StatR3Cmd3dSurfaceDmaProf,       "VMSVGA/Cmd/3dSurfaceDmaProf",           "Profiling of SVGA_3D_CMD_SURFACE_DMA.");
    8882 # endif
    8883     REG_PRF(&pSVGAState->StatR3Cmd3dBlitSurfaceToScreenProf, "VMSVGA/Cmd/3dBlitSurfaceToScreenProf", "Profiling of SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN.");
    8884     REG_CNT(&pSVGAState->StatR3Cmd3dActivateSurface,      "VMSVGA/Cmd/3dActivateSurface",          "SVGA_3D_CMD_ACTIVATE_SURFACE");
    8885     REG_CNT(&pSVGAState->StatR3Cmd3dBeginQuery,           "VMSVGA/Cmd/3dBeginQuery",               "SVGA_3D_CMD_BEGIN_QUERY");
    8886     REG_CNT(&pSVGAState->StatR3Cmd3dClear,                "VMSVGA/Cmd/3dClear",                    "SVGA_3D_CMD_CLEAR");
    8887     REG_CNT(&pSVGAState->StatR3Cmd3dContextDefine,        "VMSVGA/Cmd/3dContextDefine",            "SVGA_3D_CMD_CONTEXT_DEFINE");
    8888     REG_CNT(&pSVGAState->StatR3Cmd3dContextDestroy,       "VMSVGA/Cmd/3dContextDestroy",           "SVGA_3D_CMD_CONTEXT_DESTROY");
    8889     REG_CNT(&pSVGAState->StatR3Cmd3dDeactivateSurface,    "VMSVGA/Cmd/3dDeactivateSurface",        "SVGA_3D_CMD_DEACTIVATE_SURFACE");
    8890     REG_CNT(&pSVGAState->StatR3Cmd3dDrawPrimitives,       "VMSVGA/Cmd/3dDrawPrimitives",           "SVGA_3D_CMD_DRAW_PRIMITIVES");
    8891     REG_CNT(&pSVGAState->StatR3Cmd3dEndQuery,             "VMSVGA/Cmd/3dEndQuery",                 "SVGA_3D_CMD_END_QUERY");
    8892     REG_CNT(&pSVGAState->StatR3Cmd3dGenerateMipmaps,      "VMSVGA/Cmd/3dGenerateMipmaps",          "SVGA_3D_CMD_GENERATE_MIPMAPS");
    8893     REG_CNT(&pSVGAState->StatR3Cmd3dPresent,              "VMSVGA/Cmd/3dPresent",                  "SVGA_3D_CMD_PRESENT");
    8894     REG_CNT(&pSVGAState->StatR3Cmd3dPresentReadBack,      "VMSVGA/Cmd/3dPresentReadBack",          "SVGA_3D_CMD_PRESENT_READBACK");
    8895     REG_CNT(&pSVGAState->StatR3Cmd3dSetClipPlane,         "VMSVGA/Cmd/3dSetClipPlane",             "SVGA_3D_CMD_SETCLIPPLANE");
    8896     REG_CNT(&pSVGAState->StatR3Cmd3dSetLightData,         "VMSVGA/Cmd/3dSetLightData",             "SVGA_3D_CMD_SETLIGHTDATA");
    8897     REG_CNT(&pSVGAState->StatR3Cmd3dSetLightEnable,       "VMSVGA/Cmd/3dSetLightEnable",           "SVGA_3D_CMD_SETLIGHTENABLE");
    8898     REG_CNT(&pSVGAState->StatR3Cmd3dSetMaterial,          "VMSVGA/Cmd/3dSetMaterial",              "SVGA_3D_CMD_SETMATERIAL");
    8899     REG_CNT(&pSVGAState->StatR3Cmd3dSetRenderState,       "VMSVGA/Cmd/3dSetRenderState",           "SVGA_3D_CMD_SETRENDERSTATE");
    8900     REG_CNT(&pSVGAState->StatR3Cmd3dSetRenderTarget,      "VMSVGA/Cmd/3dSetRenderTarget",          "SVGA_3D_CMD_SETRENDERTARGET");
    8901     REG_CNT(&pSVGAState->StatR3Cmd3dSetScissorRect,       "VMSVGA/Cmd/3dSetScissorRect",           "SVGA_3D_CMD_SETSCISSORRECT");
    8902     REG_CNT(&pSVGAState->StatR3Cmd3dSetShader,            "VMSVGA/Cmd/3dSetShader",                "SVGA_3D_CMD_SET_SHADER");
    8903     REG_CNT(&pSVGAState->StatR3Cmd3dSetShaderConst,       "VMSVGA/Cmd/3dSetShaderConst",           "SVGA_3D_CMD_SET_SHADER_CONST");
    8904     REG_CNT(&pSVGAState->StatR3Cmd3dSetTextureState,      "VMSVGA/Cmd/3dSetTextureState",          "SVGA_3D_CMD_SETTEXTURESTATE");
    8905     REG_CNT(&pSVGAState->StatR3Cmd3dSetTransform,         "VMSVGA/Cmd/3dSetTransform",             "SVGA_3D_CMD_SETTRANSFORM");
    8906     REG_CNT(&pSVGAState->StatR3Cmd3dSetViewPort,          "VMSVGA/Cmd/3dSetViewPort",              "SVGA_3D_CMD_SETVIEWPORT");
    8907     REG_CNT(&pSVGAState->StatR3Cmd3dSetZRange,            "VMSVGA/Cmd/3dSetZRange",                "SVGA_3D_CMD_SETZRANGE");
    8908     REG_CNT(&pSVGAState->StatR3Cmd3dShaderDefine,         "VMSVGA/Cmd/3dShaderDefine",             "SVGA_3D_CMD_SHADER_DEFINE");
    8909     REG_CNT(&pSVGAState->StatR3Cmd3dShaderDestroy,        "VMSVGA/Cmd/3dShaderDestroy",            "SVGA_3D_CMD_SHADER_DESTROY");
    8910     REG_CNT(&pSVGAState->StatR3Cmd3dSurfaceCopy,          "VMSVGA/Cmd/3dSurfaceCopy",              "SVGA_3D_CMD_SURFACE_COPY");
    8911     REG_CNT(&pSVGAState->StatR3Cmd3dSurfaceDefine,        "VMSVGA/Cmd/3dSurfaceDefine",            "SVGA_3D_CMD_SURFACE_DEFINE");
    8912     REG_CNT(&pSVGAState->StatR3Cmd3dSurfaceDefineV2,      "VMSVGA/Cmd/3dSurfaceDefineV2",          "SVGA_3D_CMD_SURFACE_DEFINE_V2");
    8913     REG_CNT(&pSVGAState->StatR3Cmd3dSurfaceDestroy,       "VMSVGA/Cmd/3dSurfaceDestroy",           "SVGA_3D_CMD_SURFACE_DESTROY");
    8914     REG_CNT(&pSVGAState->StatR3Cmd3dSurfaceDma,           "VMSVGA/Cmd/3dSurfaceDma",               "SVGA_3D_CMD_SURFACE_DMA");
    8915     REG_CNT(&pSVGAState->StatR3Cmd3dSurfaceScreen,        "VMSVGA/Cmd/3dSurfaceScreen",            "SVGA_3D_CMD_SURFACE_SCREEN");
    8916     REG_CNT(&pSVGAState->StatR3Cmd3dSurfaceStretchBlt,    "VMSVGA/Cmd/3dSurfaceStretchBlt",        "SVGA_3D_CMD_SURFACE_STRETCHBLT");
    8917     REG_CNT(&pSVGAState->StatR3Cmd3dWaitForQuery,         "VMSVGA/Cmd/3dWaitForQuery",             "SVGA_3D_CMD_WAIT_FOR_QUERY");
    8918     REG_CNT(&pSVGAState->StatR3CmdAnnotationCopy,         "VMSVGA/Cmd/AnnotationCopy",             "SVGA_CMD_ANNOTATION_COPY");
    8919     REG_CNT(&pSVGAState->StatR3CmdAnnotationFill,         "VMSVGA/Cmd/AnnotationFill",             "SVGA_CMD_ANNOTATION_FILL");
    8920     REG_CNT(&pSVGAState->StatR3CmdBlitGmrFbToScreen,      "VMSVGA/Cmd/BlitGmrFbToScreen",          "SVGA_CMD_BLIT_GMRFB_TO_SCREEN");
    8921     REG_CNT(&pSVGAState->StatR3CmdBlitScreentoGmrFb,      "VMSVGA/Cmd/BlitScreentoGmrFb",          "SVGA_CMD_BLIT_SCREEN_TO_GMRFB");
    8922     REG_CNT(&pSVGAState->StatR3CmdDefineAlphaCursor,      "VMSVGA/Cmd/DefineAlphaCursor",          "SVGA_CMD_DEFINE_ALPHA_CURSOR");
    8923     REG_CNT(&pSVGAState->StatR3CmdDefineCursor,           "VMSVGA/Cmd/DefineCursor",               "SVGA_CMD_DEFINE_CURSOR");
    8924     REG_CNT(&pSVGAState->StatR3CmdMoveCursor,             "VMSVGA/Cmd/MoveCursor",                 "SVGA_CMD_MOVE_CURSOR");
    8925     REG_CNT(&pSVGAState->StatR3CmdDisplayCursor,          "VMSVGA/Cmd/DisplayCursor",              "SVGA_CMD_DISPLAY_CURSOR");
    8926     REG_CNT(&pSVGAState->StatR3CmdRectFill,               "VMSVGA/Cmd/RectFill",                   "SVGA_CMD_RECT_FILL");
    8927     REG_CNT(&pSVGAState->StatR3CmdRectCopy,               "VMSVGA/Cmd/RectCopy",                   "SVGA_CMD_RECT_COPY");
    8928     REG_CNT(&pSVGAState->StatR3CmdRectRopCopy,            "VMSVGA/Cmd/RectRopCopy",                "SVGA_CMD_RECT_ROP_COPY");
    8929     REG_CNT(&pSVGAState->StatR3CmdDefineGmr2,             "VMSVGA/Cmd/DefineGmr2",                 "SVGA_CMD_DEFINE_GMR2");
    8930     REG_CNT(&pSVGAState->StatR3CmdDefineGmr2Free,         "VMSVGA/Cmd/DefineGmr2/Free",            "Number of SVGA_CMD_DEFINE_GMR2 commands that only frees.");
    8931     REG_CNT(&pSVGAState->StatR3CmdDefineGmr2Modify,       "VMSVGA/Cmd/DefineGmr2/Modify",          "Number of SVGA_CMD_DEFINE_GMR2 commands that redefines a non-free GMR.");
    8932     REG_CNT(&pSVGAState->StatR3CmdDefineGmrFb,            "VMSVGA/Cmd/DefineGmrFb",                "SVGA_CMD_DEFINE_GMRFB");
    8933     REG_CNT(&pSVGAState->StatR3CmdDefineScreen,           "VMSVGA/Cmd/DefineScreen",               "SVGA_CMD_DEFINE_SCREEN");
    8934     REG_CNT(&pSVGAState->StatR3CmdDestroyScreen,          "VMSVGA/Cmd/DestroyScreen",              "SVGA_CMD_DESTROY_SCREEN");
    8935     REG_CNT(&pSVGAState->StatR3CmdEscape,                 "VMSVGA/Cmd/Escape",                     "SVGA_CMD_ESCAPE");
    8936     REG_CNT(&pSVGAState->StatR3CmdFence,                  "VMSVGA/Cmd/Fence",                      "SVGA_CMD_FENCE");
    8937     REG_CNT(&pSVGAState->StatR3CmdInvalidCmd,             "VMSVGA/Cmd/InvalidCmd",                 "SVGA_CMD_INVALID_CMD");
    8938     REG_CNT(&pSVGAState->StatR3CmdRemapGmr2,              "VMSVGA/Cmd/RemapGmr2",                  "SVGA_CMD_REMAP_GMR2");
    8939     REG_CNT(&pSVGAState->StatR3CmdRemapGmr2Modify,        "VMSVGA/Cmd/RemapGmr2/Modify",           "Number of SVGA_CMD_REMAP_GMR2 commands that modifies rather than complete the definition of a GMR.");
    8940     REG_CNT(&pSVGAState->StatR3CmdUpdate,                 "VMSVGA/Cmd/Update",                     "SVGA_CMD_UPDATE");
    8941     REG_CNT(&pSVGAState->StatR3CmdUpdateVerbose,          "VMSVGA/Cmd/UpdateVerbose",              "SVGA_CMD_UPDATE_VERBOSE");
    8942 
    8943     REG_CNT(&pSVGAState->StatR3RegConfigDoneWr,           "VMSVGA/Reg/ConfigDoneWrite",            "SVGA_REG_CONFIG_DONE writes");
    8944     REG_CNT(&pSVGAState->StatR3RegGmrDescriptorWr,        "VMSVGA/Reg/GmrDescriptorWrite",         "SVGA_REG_GMR_DESCRIPTOR writes");
    8945     REG_CNT(&pSVGAState->StatR3RegGmrDescriptorWrErrors,  "VMSVGA/Reg/GmrDescriptorWrite/Errors",  "Number of erroneous SVGA_REG_GMR_DESCRIPTOR commands.");
    8946     REG_CNT(&pSVGAState->StatR3RegGmrDescriptorWrFree,    "VMSVGA/Reg/GmrDescriptorWrite/Free",    "Number of SVGA_REG_GMR_DESCRIPTOR commands only freeing the GMR.");
    8947     REG_CNT(&pThis->svga.StatRegBitsPerPixelWr,           "VMSVGA/Reg/BitsPerPixelWrite",          "SVGA_REG_BITS_PER_PIXEL writes.");
    8948     REG_CNT(&pThis->svga.StatRegBusyWr,                   "VMSVGA/Reg/BusyWrite",                  "SVGA_REG_BUSY writes.");
    8949     REG_CNT(&pThis->svga.StatRegCursorXWr,                "VMSVGA/Reg/CursorXWrite",               "SVGA_REG_CURSOR_X writes.");
    8950     REG_CNT(&pThis->svga.StatRegCursorYWr,                "VMSVGA/Reg/CursorYWrite",               "SVGA_REG_CURSOR_Y writes.");
    8951     REG_CNT(&pThis->svga.StatRegCursorIdWr,               "VMSVGA/Reg/CursorIdWrite",              "SVGA_REG_CURSOR_ID writes.");
    8952     REG_CNT(&pThis->svga.StatRegCursorOnWr,               "VMSVGA/Reg/CursorOnWrite",              "SVGA_REG_CURSOR_ON writes.");
    8953     REG_CNT(&pThis->svga.StatRegDepthWr,                  "VMSVGA/Reg/DepthWrite",                 "SVGA_REG_DEPTH writes.");
    8954     REG_CNT(&pThis->svga.StatRegDisplayHeightWr,          "VMSVGA/Reg/DisplayHeightWrite",         "SVGA_REG_DISPLAY_HEIGHT writes.");
    8955     REG_CNT(&pThis->svga.StatRegDisplayIdWr,              "VMSVGA/Reg/DisplayIdWrite",             "SVGA_REG_DISPLAY_ID writes.");
    8956     REG_CNT(&pThis->svga.StatRegDisplayIsPrimaryWr,       "VMSVGA/Reg/DisplayIsPrimaryWrite",      "SVGA_REG_DISPLAY_IS_PRIMARY writes.");
    8957     REG_CNT(&pThis->svga.StatRegDisplayPositionXWr,       "VMSVGA/Reg/DisplayPositionXWrite",      "SVGA_REG_DISPLAY_POSITION_X writes.");
    8958     REG_CNT(&pThis->svga.StatRegDisplayPositionYWr,       "VMSVGA/Reg/DisplayPositionYWrite",      "SVGA_REG_DISPLAY_POSITION_Y writes.");
    8959     REG_CNT(&pThis->svga.StatRegDisplayWidthWr,           "VMSVGA/Reg/DisplayWidthWrite",          "SVGA_REG_DISPLAY_WIDTH writes.");
    8960     REG_CNT(&pThis->svga.StatRegEnableWr,                 "VMSVGA/Reg/EnableWrite",                "SVGA_REG_ENABLE writes.");
    8961     REG_CNT(&pThis->svga.StatRegGmrIdWr,                  "VMSVGA/Reg/GmrIdWrite",                 "SVGA_REG_GMR_ID writes.");
    8962     REG_CNT(&pThis->svga.StatRegGuestIdWr,                "VMSVGA/Reg/GuestIdWrite",               "SVGA_REG_GUEST_ID writes.");
    8963     REG_CNT(&pThis->svga.StatRegHeightWr,                 "VMSVGA/Reg/HeightWrite",                "SVGA_REG_HEIGHT writes.");
    8964     REG_CNT(&pThis->svga.StatRegIdWr,                     "VMSVGA/Reg/IdWrite",                    "SVGA_REG_ID writes.");
    8965     REG_CNT(&pThis->svga.StatRegIrqMaskWr,                "VMSVGA/Reg/IrqMaskWrite",               "SVGA_REG_IRQMASK writes.");
    8966     REG_CNT(&pThis->svga.StatRegNumDisplaysWr,            "VMSVGA/Reg/NumDisplaysWrite",           "SVGA_REG_NUM_DISPLAYS writes.");
    8967     REG_CNT(&pThis->svga.StatRegNumGuestDisplaysWr,       "VMSVGA/Reg/NumGuestDisplaysWrite",      "SVGA_REG_NUM_GUEST_DISPLAYS writes.");
    8968     REG_CNT(&pThis->svga.StatRegPaletteWr,                "VMSVGA/Reg/PaletteWrite",               "SVGA_PALETTE_XXXX writes.");
    8969     REG_CNT(&pThis->svga.StatRegPitchLockWr,              "VMSVGA/Reg/PitchLockWrite",             "SVGA_REG_PITCHLOCK writes.");
    8970     REG_CNT(&pThis->svga.StatRegPseudoColorWr,            "VMSVGA/Reg/PseudoColorWrite",           "SVGA_REG_PSEUDOCOLOR writes.");
    8971     REG_CNT(&pThis->svga.StatRegReadOnlyWr,               "VMSVGA/Reg/ReadOnlyWrite",              "Read-only SVGA_REG_XXXX writes.");
    8972     REG_CNT(&pThis->svga.StatRegScratchWr,                "VMSVGA/Reg/ScratchWrite",               "SVGA_REG_SCRATCH_XXXX writes.");
    8973     REG_CNT(&pThis->svga.StatRegSyncWr,                   "VMSVGA/Reg/SyncWrite",                  "SVGA_REG_SYNC writes.");
    8974     REG_CNT(&pThis->svga.StatRegTopWr,                    "VMSVGA/Reg/TopWrite",                   "SVGA_REG_TOP writes.");
    8975     REG_CNT(&pThis->svga.StatRegTracesWr,                 "VMSVGA/Reg/TracesWrite",                "SVGA_REG_TRACES writes.");
    8976     REG_CNT(&pThis->svga.StatRegUnknownWr,                "VMSVGA/Reg/UnknownWrite",               "Writes to unknown register.");
    8977     REG_CNT(&pThis->svga.StatRegWidthWr,                  "VMSVGA/Reg/WidthWrite",                 "SVGA_REG_WIDTH writes.");
    8978     REG_CNT(&pThis->svga.StatRegCommandLowWr,             "VMSVGA/Reg/CommandLowWrite",            "SVGA_REG_COMMAND_LOW writes.");
    8979     REG_CNT(&pThis->svga.StatRegCommandHighWr,            "VMSVGA/Reg/CommandHighWrite",           "SVGA_REG_COMMAND_HIGH writes.");
    8980     REG_CNT(&pThis->svga.StatRegDevCapWr,                 "VMSVGA/Reg/DevCapWrite",                "SVGA_REG_DEV_CAP writes.");
    8981     REG_CNT(&pThis->svga.StatRegCmdPrependLowWr,          "VMSVGA/Reg/CmdPrependLowWrite",         "SVGA_REG_CMD_PREPEND_LOW writes.");
    8982     REG_CNT(&pThis->svga.StatRegCmdPrependHighWr,         "VMSVGA/Reg/CmdPrependHighWrite",        "SVGA_REG_iCMD_PREPEND_HIGH writes.");
    8983 
    8984     REG_CNT(&pThis->svga.StatRegBitsPerPixelRd,           "VMSVGA/Reg/BitsPerPixelRead",           "SVGA_REG_BITS_PER_PIXEL reads.");
    8985     REG_CNT(&pThis->svga.StatRegBlueMaskRd,               "VMSVGA/Reg/BlueMaskRead",               "SVGA_REG_BLUE_MASK reads.");
    8986     REG_CNT(&pThis->svga.StatRegBusyRd,                   "VMSVGA/Reg/BusyRead",                   "SVGA_REG_BUSY reads.");
    8987     REG_CNT(&pThis->svga.StatRegBytesPerLineRd,           "VMSVGA/Reg/BytesPerLineRead",           "SVGA_REG_BYTES_PER_LINE reads.");
    8988     REG_CNT(&pThis->svga.StatRegCapabilitesRd,            "VMSVGA/Reg/CapabilitesRead",            "SVGA_REG_CAPABILITIES reads.");
    8989     REG_CNT(&pThis->svga.StatRegConfigDoneRd,             "VMSVGA/Reg/ConfigDoneRead",             "SVGA_REG_CONFIG_DONE reads.");
    8990     REG_CNT(&pThis->svga.StatRegCursorXRd,                "VMSVGA/Reg/CursorXRead",                "SVGA_REG_CURSOR_X reads.");
    8991     REG_CNT(&pThis->svga.StatRegCursorYRd,                "VMSVGA/Reg/CursorYRead",                "SVGA_REG_CURSOR_Y reads.");
    8992     REG_CNT(&pThis->svga.StatRegCursorIdRd,               "VMSVGA/Reg/CursorIdRead",               "SVGA_REG_CURSOR_ID reads.");
    8993     REG_CNT(&pThis->svga.StatRegCursorOnRd,               "VMSVGA/Reg/CursorOnRead",               "SVGA_REG_CURSOR_ON reads.");
    8994     REG_CNT(&pThis->svga.StatRegDepthRd,                  "VMSVGA/Reg/DepthRead",                  "SVGA_REG_DEPTH reads.");
    8995     REG_CNT(&pThis->svga.StatRegDisplayHeightRd,          "VMSVGA/Reg/DisplayHeightRead",          "SVGA_REG_DISPLAY_HEIGHT reads.");
    8996     REG_CNT(&pThis->svga.StatRegDisplayIdRd,              "VMSVGA/Reg/DisplayIdRead",              "SVGA_REG_DISPLAY_ID reads.");
    8997     REG_CNT(&pThis->svga.StatRegDisplayIsPrimaryRd,       "VMSVGA/Reg/DisplayIsPrimaryRead",       "SVGA_REG_DISPLAY_IS_PRIMARY reads.");
    8998     REG_CNT(&pThis->svga.StatRegDisplayPositionXRd,       "VMSVGA/Reg/DisplayPositionXRead",       "SVGA_REG_DISPLAY_POSITION_X reads.");
    8999     REG_CNT(&pThis->svga.StatRegDisplayPositionYRd,       "VMSVGA/Reg/DisplayPositionYRead",       "SVGA_REG_DISPLAY_POSITION_Y reads.");
    9000     REG_CNT(&pThis->svga.StatRegDisplayWidthRd,           "VMSVGA/Reg/DisplayWidthRead",           "SVGA_REG_DISPLAY_WIDTH reads.");
    9001     REG_CNT(&pThis->svga.StatRegEnableRd,                 "VMSVGA/Reg/EnableRead",                 "SVGA_REG_ENABLE reads.");
    9002     REG_CNT(&pThis->svga.StatRegFbOffsetRd,               "VMSVGA/Reg/FbOffsetRead",               "SVGA_REG_FB_OFFSET reads.");
    9003     REG_CNT(&pThis->svga.StatRegFbSizeRd,                 "VMSVGA/Reg/FbSizeRead",                 "SVGA_REG_FB_SIZE reads.");
    9004     REG_CNT(&pThis->svga.StatRegFbStartRd,                "VMSVGA/Reg/FbStartRead",                "SVGA_REG_FB_START reads.");
    9005     REG_CNT(&pThis->svga.StatRegGmrIdRd,                  "VMSVGA/Reg/GmrIdRead",                  "SVGA_REG_GMR_ID reads.");
    9006     REG_CNT(&pThis->svga.StatRegGmrMaxDescriptorLengthRd, "VMSVGA/Reg/GmrMaxDescriptorLengthRead", "SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH reads.");
    9007     REG_CNT(&pThis->svga.StatRegGmrMaxIdsRd,              "VMSVGA/Reg/GmrMaxIdsRead",              "SVGA_REG_GMR_MAX_IDS reads.");
    9008     REG_CNT(&pThis->svga.StatRegGmrsMaxPagesRd,           "VMSVGA/Reg/GmrsMaxPagesRead",           "SVGA_REG_GMRS_MAX_PAGES reads.");
    9009     REG_CNT(&pThis->svga.StatRegGreenMaskRd,              "VMSVGA/Reg/GreenMaskRead",              "SVGA_REG_GREEN_MASK reads.");
    9010     REG_CNT(&pThis->svga.StatRegGuestIdRd,                "VMSVGA/Reg/GuestIdRead",                "SVGA_REG_GUEST_ID reads.");
    9011     REG_CNT(&pThis->svga.StatRegHeightRd,                 "VMSVGA/Reg/HeightRead",                 "SVGA_REG_HEIGHT reads.");
    9012     REG_CNT(&pThis->svga.StatRegHostBitsPerPixelRd,       "VMSVGA/Reg/HostBitsPerPixelRead",       "SVGA_REG_HOST_BITS_PER_PIXEL reads.");
    9013     REG_CNT(&pThis->svga.StatRegIdRd,                     "VMSVGA/Reg/IdRead",                     "SVGA_REG_ID reads.");
    9014     REG_CNT(&pThis->svga.StatRegIrqMaskRd,                "VMSVGA/Reg/IrqMaskRead",                "SVGA_REG_IRQ_MASK reads.");
    9015     REG_CNT(&pThis->svga.StatRegMaxHeightRd,              "VMSVGA/Reg/MaxHeightRead",              "SVGA_REG_MAX_HEIGHT reads.");
    9016     REG_CNT(&pThis->svga.StatRegMaxWidthRd,               "VMSVGA/Reg/MaxWidthRead",               "SVGA_REG_MAX_WIDTH reads.");
    9017     REG_CNT(&pThis->svga.StatRegMemorySizeRd,             "VMSVGA/Reg/MemorySizeRead",             "SVGA_REG_MEMORY_SIZE reads.");
    9018     REG_CNT(&pThis->svga.StatRegMemRegsRd,                "VMSVGA/Reg/MemRegsRead",                "SVGA_REG_MEM_REGS reads.");
    9019     REG_CNT(&pThis->svga.StatRegMemSizeRd,                "VMSVGA/Reg/MemSizeRead",                "SVGA_REG_MEM_SIZE reads.");
    9020     REG_CNT(&pThis->svga.StatRegMemStartRd,               "VMSVGA/Reg/MemStartRead",               "SVGA_REG_MEM_START reads.");
    9021     REG_CNT(&pThis->svga.StatRegNumDisplaysRd,            "VMSVGA/Reg/NumDisplaysRead",            "SVGA_REG_NUM_DISPLAYS reads.");
    9022     REG_CNT(&pThis->svga.StatRegNumGuestDisplaysRd,       "VMSVGA/Reg/NumGuestDisplaysRead",       "SVGA_REG_NUM_GUEST_DISPLAYS reads.");
    9023     REG_CNT(&pThis->svga.StatRegPaletteRd,                "VMSVGA/Reg/PaletteRead",                "SVGA_REG_PLAETTE_XXXX reads.");
    9024     REG_CNT(&pThis->svga.StatRegPitchLockRd,              "VMSVGA/Reg/PitchLockRead",              "SVGA_REG_PITCHLOCK reads.");
    9025     REG_CNT(&pThis->svga.StatRegPsuedoColorRd,            "VMSVGA/Reg/PsuedoColorRead",            "SVGA_REG_PSEUDOCOLOR reads.");
    9026     REG_CNT(&pThis->svga.StatRegRedMaskRd,                "VMSVGA/Reg/RedMaskRead",                "SVGA_REG_RED_MASK reads.");
    9027     REG_CNT(&pThis->svga.StatRegScratchRd,                "VMSVGA/Reg/ScratchRead",                "SVGA_REG_SCRATCH reads.");
    9028     REG_CNT(&pThis->svga.StatRegScratchSizeRd,            "VMSVGA/Reg/ScratchSizeRead",            "SVGA_REG_SCRATCH_SIZE reads.");
    9029     REG_CNT(&pThis->svga.StatRegSyncRd,                   "VMSVGA/Reg/SyncRead",                   "SVGA_REG_SYNC reads.");
    9030     REG_CNT(&pThis->svga.StatRegTopRd,                    "VMSVGA/Reg/TopRead",                    "SVGA_REG_TOP reads.");
    9031     REG_CNT(&pThis->svga.StatRegTracesRd,                 "VMSVGA/Reg/TracesRead",                 "SVGA_REG_TRACES reads.");
    9032     REG_CNT(&pThis->svga.StatRegUnknownRd,                "VMSVGA/Reg/UnknownRead",                "SVGA_REG_UNKNOWN reads.");
    9033     REG_CNT(&pThis->svga.StatRegVramSizeRd,               "VMSVGA/Reg/VramSizeRead",               "SVGA_REG_VRAM_SIZE reads.");
    9034     REG_CNT(&pThis->svga.StatRegWidthRd,                  "VMSVGA/Reg/WidthRead",                  "SVGA_REG_WIDTH reads.");
    9035     REG_CNT(&pThis->svga.StatRegWriteOnlyRd,              "VMSVGA/Reg/WriteOnlyRead",              "Write-only SVGA_REG_XXXX reads.");
    9036     REG_CNT(&pThis->svga.StatRegCommandLowRd,             "VMSVGA/Reg/CommandLowRead",             "SVGA_REG_COMMAND_LOW reads.");
    9037     REG_CNT(&pThis->svga.StatRegCommandHighRd,            "VMSVGA/Reg/CommandHighRead",            "SVGA_REG_COMMAND_HIGH reads.");
    9038     REG_CNT(&pThis->svga.StatRegMaxPrimBBMemRd,           "VMSVGA/Reg/MaxPrimBBMemRead",           "SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM reads.");
    9039     REG_CNT(&pThis->svga.StatRegGBMemSizeRd,              "VMSVGA/Reg/GBMemSizeRead",              "SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB reads.");
    9040     REG_CNT(&pThis->svga.StatRegDevCapRd,                 "VMSVGA/Reg/DevCapRead",                 "SVGA_REG_DEV_CAP reads.");
    9041     REG_CNT(&pThis->svga.StatRegCmdPrependLowRd,          "VMSVGA/Reg/CmdPrependLowRead",          "SVGA_REG_CMD_PREPEND_LOW reads.");
    9042     REG_CNT(&pThis->svga.StatRegCmdPrependHighRd,         "VMSVGA/Reg/CmdPrependHighRead",         "SVGA_REG_iCMD_PREPEND_HIGH reads.");
    9043     REG_CNT(&pThis->svga.StatRegScrnTgtMaxWidthRd,        "VMSVGA/Reg/ScrnTgtMaxWidthRead",        "SVGA_REG_SCREENTARGET_MAX_WIDTH reads.");
    9044     REG_CNT(&pThis->svga.StatRegScrnTgtMaxHeightRd,       "VMSVGA/Reg/ScrnTgtMaxHeightRead",       "SVGA_REG_SCREENTARGET_MAX_HEIGHT reads.");
    9045     REG_CNT(&pThis->svga.StatRegMobMaxSizeRd,             "VMSVGA/Reg/MobMaxSizeRead",             "SVGA_REG_MOB_MAX_SIZE reads.");
    9046 
    9047     REG_PRF(&pSVGAState->StatBusyDelayEmts,               "VMSVGA/EmtDelayOnBusyFifo",             "Time we've delayed EMTs because of busy FIFO thread.");
    9048     REG_CNT(&pSVGAState->StatFifoCommands,                "VMSVGA/FifoCommands",                   "FIFO command counter.");
    9049     REG_CNT(&pSVGAState->StatFifoErrors,                  "VMSVGA/FifoErrors",                     "FIFO error counter.");
    9050     REG_CNT(&pSVGAState->StatFifoUnkCmds,                 "VMSVGA/FifoUnknownCommands",            "FIFO unknown command counter.");
    9051     REG_CNT(&pSVGAState->StatFifoTodoTimeout,             "VMSVGA/FifoTodoTimeout",                "Number of times we discovered pending work after a wait timeout.");
    9052     REG_CNT(&pSVGAState->StatFifoTodoWoken,               "VMSVGA/FifoTodoWoken",                  "Number of times we discovered pending work after being woken up.");
    9053     REG_PRF(&pSVGAState->StatFifoStalls,                  "VMSVGA/FifoStalls",                     "Profiling of FIFO stalls (waiting for guest to finish copying data).");
    9054     REG_PRF(&pSVGAState->StatFifoExtendedSleep,           "VMSVGA/FifoExtendedSleep",              "Profiling FIFO sleeps relying on the refresh timer and/or access handler.");
    9055 # if defined(VMSVGA_USE_FIFO_ACCESS_HANDLER) || defined(DEBUG_FIFO_ACCESS)
    9056     REG_CNT(&pSVGAState->StatFifoAccessHandler,           "VMSVGA/FifoAccessHandler",              "Number of times the FIFO access handler triggered.");
    9057 # endif
    9058     REG_CNT(&pSVGAState->StatFifoCursorFetchAgain,        "VMSVGA/FifoCursorFetchAgain",           "Times the cursor update counter changed while reading.");
    9059     REG_CNT(&pSVGAState->StatFifoCursorNoChange,          "VMSVGA/FifoCursorNoChange",             "No cursor position change event though the update counter was modified.");
    9060     REG_CNT(&pSVGAState->StatFifoCursorPosition,          "VMSVGA/FifoCursorPosition",             "Cursor position and visibility changes.");
    9061     REG_CNT(&pSVGAState->StatFifoCursorVisiblity,         "VMSVGA/FifoCursorVisiblity",            "Cursor visibility changes.");
    9062     REG_CNT(&pSVGAState->StatFifoWatchdogWakeUps,         "VMSVGA/FifoWatchdogWakeUps",            "Number of times the FIFO refresh poller/watchdog woke up the FIFO thread.");
    9063 
    9064 # undef REG_CNT
    9065 # undef REG_PRF
    9066 
    9067     /*
    9068      * Info handlers.
    9069      */
    9070     PDMDevHlpDBGFInfoRegister(pDevIns, "vmsvga", "Basic VMSVGA device state details", vmsvgaR3Info);
    9071 # ifdef VBOX_WITH_VMSVGA3D
    9072     PDMDevHlpDBGFInfoRegister(pDevIns, "vmsvga3dctx", "VMSVGA 3d context details. Accepts 'terse'.", vmsvgaR3Info3dContext);
    9073     PDMDevHlpDBGFInfoRegister(pDevIns, "vmsvga3dsfc",
    9074                               "VMSVGA 3d surface details. "
    9075                               "Accepts 'terse', 'invy', and one of 'tiny', 'medium', 'normal', 'big', 'huge', or 'gigantic'.",
    9076                               vmsvgaR3Info3dSurface);
    9077     PDMDevHlpDBGFInfoRegister(pDevIns, "vmsvga3dsurf",
    9078                               "VMSVGA 3d surface details and bitmap: "
    9079                               "sid[>dir]",
    9080                               vmsvgaR3Info3dSurfaceBmp);
    9081 # endif
    9082 
    9083     return VINF_SUCCESS;
    9084 }
    9085 
    9086 /**
    9087  * Power On notification.
    9088  *
    9089  * @returns VBox status code.
    9090  * @param   pDevIns     The device instance data.
    9091  *
    9092  * @remarks Caller enters the device critical section.
    9093  */
    9094 DECLCALLBACK(void) vmsvgaR3PowerOn(PPDMDEVINS pDevIns)
    9095 {
    9096 # ifdef VBOX_WITH_VMSVGA3D
    9097     PVGASTATE   pThis   = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
    9098     PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
    9099     if (pThis->svga.f3DEnabled)
    9100     {
    9101         int rc = vmsvga3dPowerOn(pDevIns, pThis, pThisCC);
    9102         if (RT_SUCCESS(rc))
    9103         {
    9104             /* Initialize FIFO 3D capabilities. */
    9105             vmsvgaR3InitFifo3DCaps(pThis, pThisCC);
    9106         }
    9107     }
    9108 # else  /* !VBOX_WITH_VMSVGA3D */
    9109     RT_NOREF(pDevIns);
    9110 # endif /* !VBOX_WITH_VMSVGA3D */
    9111 }
    9112 
    9113 /**
    9114  * Power Off notification.
    9115  *
    9116  * @param   pDevIns     The device instance data.
    9117  *
    9118  * @remarks Caller enters the device critical section.
    9119  */
    9120 DECLCALLBACK(void) vmsvgaR3PowerOff(PPDMDEVINS pDevIns)
    9121 {
    9122     PVGASTATE   pThis   = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
    9123     PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
    9124 
    9125     /*
    9126      * Notify the FIFO thread.
    9127      */
    9128     if (pThisCC->svga.pFIFOIOThread)
    9129     {
    9130         int rc = vmsvgaR3RunExtCmdOnFifoThread(pDevIns, pThis, pThisCC,  VMSVGA_FIFO_EXTCMD_POWEROFF,
    9131                                                NULL /*pvParam*/, 30000 /*ms*/);
    9132         AssertLogRelRC(rc);
    9133     }
    9134 }
    9135 
    9136 #endif /* IN_RING3 */
  • trunk/src/VBox/Devices/Graphics/DevVGA-SVGA-internal.h

    r86252 r86265  
    11/* $Id$ */
    22/** @file
    3  * VMware SVGA device.
    4  *
    5  * Logging levels guidelines for this and related files:
    6  *  - Log() for normal bits.
    7  *  - LogFlow() for more info.
    8  *  - Log2 for hex dump of cursor data.
    9  *  - Log3 for hex dump of shader code.
    10  *  - Log4 for hex dumps of 3D data.
    11  *  - Log5 for info about GMR pages.
    12  *  - LogRel for the usual important stuff.
    13  *  - LogRel2 for cursor.
    14  *  - LogRel3 for 3D performance data.
    15  *  - LogRel4 for HW accelerated graphics output.
     3 * VMWare SVGA device - internal header for DevVGA-SVGA* source files.
    164 */
    175
     
    2816 */
    2917
    30 
    31 /** @page pg_dev_vmsvga     VMSVGA - VMware SVGA II Device Emulation
    32  *
    33  * This device emulation was contributed by trivirt AG.  It offers an
    34  * alternative to our Bochs based VGA graphics and 3d emulations.  This is
    35  * valuable for Xorg based guests, as there is driver support shipping with Xorg
    36  * since it forked from XFree86.
    37  *
    38  *
    39  * @section sec_dev_vmsvga_sdk  The VMware SDK
    40  *
    41  * This is officially deprecated now, however it's still quite useful,
    42  * especially for getting the old features working:
    43  * http://vmware-svga.sourceforge.net/
    44  *
    45  * They currently point developers at the following resources.
    46  *  - http://cgit.freedesktop.org/xorg/driver/xf86-video-vmware/
    47  *  - http://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/svga/
    48  *  - http://cgit.freedesktop.org/mesa/vmwgfx/
    49  *
    50  * @subsection subsec_dev_vmsvga_sdk_results  Test results
    51  *
    52  * Test results:
    53  *  - 2dmark.img:
    54  *       + todo
    55  *  - backdoor-tclo.img:
    56  *       + todo
    57  *  - blit-cube.img:
    58  *       + todo
    59  *  - bunnies.img:
    60  *       + todo
    61  *  - cube.img:
    62  *       + todo
    63  *  - cubemark.img:
    64  *       + todo
    65  *  - dynamic-vertex-stress.img:
    66  *       + todo
    67  *  - dynamic-vertex.img:
    68  *       + todo
    69  *  - fence-stress.img:
    70  *       + todo
    71  *  - gmr-test.img:
    72  *       + todo
    73  *  - half-float-test.img:
    74  *       + todo
    75  *  - noscreen-cursor.img:
    76  *       - The CURSOR I/O and FIFO registers are not implemented, so the mouse
    77  *         cursor doesn't show. (Hacking the GUI a little, would make the cursor
    78  *         visible though.)
    79  *       - Cursor animation via the palette doesn't work.
    80  *       - During debugging, it turns out that the framebuffer content seems to
    81  *         be halfways ignore or something (memset(fb, 0xcc, lots)).
    82  *       - Trouble with way to small FIFO and the 256x256 cursor fails. Need to
    83  *         grow it 0x10 fold (128KB -> 2MB like in WS10).
    84  *  - null.img:
    85  *       + todo
    86  *  - pong.img:
    87  *       + todo
    88  *  - presentReadback.img:
    89  *       + todo
    90  *  - resolution-set.img:
    91  *       + todo
    92  *  - rt-gamma-test.img:
    93  *       + todo
    94  *  - screen-annotation.img:
    95  *       + todo
    96  *  - screen-cursor.img:
    97  *       + todo
    98  *  - screen-dma-coalesce.img:
    99  *       + todo
    100  *  - screen-gmr-discontig.img:
    101  *       + todo
    102  *  - screen-gmr-remap.img:
    103  *       + todo
    104  *  - screen-multimon.img:
    105  *       + todo
    106  *  - screen-present-clip.img:
    107  *       + todo
    108  *  - screen-render-test.img:
    109  *       + todo
    110  *  - screen-simple.img:
    111  *       + todo
    112  *  - screen-text.img:
    113  *       + todo
    114  *  - simple-shaders.img:
    115  *       + todo
    116  *  - simple_blit.img:
    117  *       + todo
    118  *  - tiny-2d-updates.img:
    119  *       + todo
    120  *  - video-formats.img:
    121  *       + todo
    122  *  - video-sync.img:
    123  *       + todo
    124  *
    125  */
    126 
    127 
    128 /*********************************************************************************************************************************
    129 *   Header Files                                                                                                                 *
    130 *********************************************************************************************************************************/
    131 #define LOG_GROUP LOG_GROUP_DEV_VMSVGA
    132 #define VMSVGA_USE_EMT_HALT_CODE
    133 #include <VBox/vmm/pdmdev.h>
    134 #include <VBox/version.h>
    135 #include <VBox/err.h>
    136 #include <VBox/log.h>
    137 #include <VBox/vmm/pgm.h>
    138 #ifdef VMSVGA_USE_EMT_HALT_CODE
    139 # include <VBox/vmm/vmapi.h>
    140 # include <VBox/vmm/vmcpuset.h>
    141 #endif
    142 #include <VBox/sup.h>
    143 
    144 #include <iprt/assert.h>
    145 #include <iprt/semaphore.h>
    146 #include <iprt/uuid.h>
    147 #ifdef IN_RING3
    148 # include <iprt/ctype.h>
    149 # include <iprt/mem.h>
    150 # ifdef VBOX_STRICT
    151 #  include <iprt/time.h>
    152 # endif
    153 #endif
    154 
    155 #include <VBox/AssertGuest.h>
    156 #include <VBox/VMMDev.h>
    157 #include <VBoxVideo.h>
    158 #include <VBox/bioslogo.h>
    159 
    160 /* should go BEFORE any other DevVGA include to make all DevVGA.h config defines be visible */
    161 #include "DevVGA.h"
    162 
    163 #include "DevVGA-SVGA.h"
    164 #ifdef VBOX_WITH_VMSVGA3D
    165 # include "DevVGA-SVGA3d.h"
    166 # ifdef RT_OS_DARWIN
    167 #  include "DevVGA-SVGA3d-cocoa.h"
    168 # endif
    169 # ifdef RT_OS_LINUX
    170 #  ifdef IN_RING3
    171 #   include "DevVGA-SVGA3d-glLdr.h"
    172 #  endif
    173 # endif
    174 #endif
    175 
    176 
    177 /*********************************************************************************************************************************
    178 *   Defined Constants And Macros                                                                                                 *
    179 *********************************************************************************************************************************/
    180 /**
    181  * Macro for checking if a fixed FIFO register is valid according to the
    182  * current FIFO configuration.
    183  *
    184  * @returns true / false.
    185  * @param   a_iIndex        The fifo register index (like SVGA_FIFO_CAPABILITIES).
    186  * @param   a_offFifoMin    A valid SVGA_FIFO_MIN value.
    187  */
    188 #define VMSVGA_IS_VALID_FIFO_REG(a_iIndex, a_offFifoMin) ( ((a_iIndex) + 1) * sizeof(uint32_t) <= (a_offFifoMin) )
     18#ifndef VBOX_INCLUDED_SRC_Graphics_DevVGA_SVGA_internal_h
     19#define VBOX_INCLUDED_SRC_Graphics_DevVGA_SVGA_internal_h
     20#ifndef RT_WITHOUT_PRAGMA_ONCE
     21# pragma once
     22#endif
     23
     24/*
     25 * Assert sane compilation environment.
     26 */
     27#ifndef IN_RING3
     28# error "DevVGA-SVGA-internal.h is only for ring-3 code"
     29#endif
    18930
    19031
     
    21253} GMR, *PGMR;
    21354
    214 #ifdef IN_RING3
    21555typedef struct VMSVGACMDBUF *PVMSVGACMDBUF;
    21656typedef struct VMSVGACMDBUFCTX *PVMSVGACMDBUFCTX;
     
    375215    STAMCOUNTER             StatFifoWatchdogWakeUps;
    376216} VMSVGAR3STATE, *PVMSVGAR3STATE;
    377 #endif /* IN_RING3 */
    378217
    379218
    380219/*********************************************************************************************************************************
    381 *   Internal Functions                                                                                                           *
     220*   Functions                                                                                                                    *
    382221*********************************************************************************************************************************/
    383 #ifdef IN_RING3
    384 # if defined(VMSVGA_USE_FIFO_ACCESS_HANDLER) || defined(DEBUG_FIFO_ACCESS)
    385 static FNPGMPHYSHANDLER vmsvgaR3FifoAccessHandler;
    386 # endif
    387 # ifdef DEBUG_GMR_ACCESS
    388 static FNPGMPHYSHANDLER vmsvgaR3GmrAccessHandler;
    389 # endif
    390 #endif
    391 
    392 
    393 /*********************************************************************************************************************************
    394 *   Global Variables                                                                                                             *
    395 *********************************************************************************************************************************/
    396 #ifdef IN_RING3
    397 
    398 /**
    399  * SSM descriptor table for the VMSVGAGMRDESCRIPTOR structure.
    400  */
    401 static SSMFIELD const g_aVMSVGAGMRDESCRIPTORFields[] =
    402 {
    403     SSMFIELD_ENTRY_GCPHYS(      VMSVGAGMRDESCRIPTOR,     GCPhys),
    404     SSMFIELD_ENTRY(             VMSVGAGMRDESCRIPTOR,     numPages),
    405     SSMFIELD_ENTRY_TERM()
    406 };
    407 
    408 /**
    409  * SSM descriptor table for the GMR structure.
    410  */
    411 static SSMFIELD const g_aGMRFields[] =
    412 {
    413     SSMFIELD_ENTRY(             GMR, cMaxPages),
    414     SSMFIELD_ENTRY(             GMR, cbTotal),
    415     SSMFIELD_ENTRY(             GMR, numDescriptors),
    416     SSMFIELD_ENTRY_IGN_HCPTR(   GMR, paDesc),
    417     SSMFIELD_ENTRY_TERM()
    418 };
    419 
    420 /**
    421  * SSM descriptor table for the VMSVGASCREENOBJECT structure.
    422  */
    423 static SSMFIELD const g_aVMSVGASCREENOBJECTFields[] =
    424 {
    425     SSMFIELD_ENTRY(             VMSVGASCREENOBJECT, fuScreen),
    426     SSMFIELD_ENTRY(             VMSVGASCREENOBJECT, idScreen),
    427     SSMFIELD_ENTRY(             VMSVGASCREENOBJECT, xOrigin),
    428     SSMFIELD_ENTRY(             VMSVGASCREENOBJECT, yOrigin),
    429     SSMFIELD_ENTRY(             VMSVGASCREENOBJECT, cWidth),
    430     SSMFIELD_ENTRY(             VMSVGASCREENOBJECT, cHeight),
    431     SSMFIELD_ENTRY(             VMSVGASCREENOBJECT, offVRAM),
    432     SSMFIELD_ENTRY(             VMSVGASCREENOBJECT, cbPitch),
    433     SSMFIELD_ENTRY(             VMSVGASCREENOBJECT, cBpp),
    434     SSMFIELD_ENTRY(             VMSVGASCREENOBJECT, fDefined),
    435     SSMFIELD_ENTRY(             VMSVGASCREENOBJECT, fModified),
    436     SSMFIELD_ENTRY_TERM()
    437 };
    438 
    439 /**
    440  * SSM descriptor table for the VMSVGAR3STATE structure.
    441  */
    442 static SSMFIELD const g_aVMSVGAR3STATEFields[] =
    443 {
    444     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, paGMR),
    445     SSMFIELD_ENTRY(             VMSVGAR3STATE, GMRFB),
    446     SSMFIELD_ENTRY(             VMSVGAR3STATE, Cursor.fActive),
    447     SSMFIELD_ENTRY(             VMSVGAR3STATE, Cursor.xHotspot),
    448     SSMFIELD_ENTRY(             VMSVGAR3STATE, Cursor.yHotspot),
    449     SSMFIELD_ENTRY(             VMSVGAR3STATE, Cursor.width),
    450     SSMFIELD_ENTRY(             VMSVGAR3STATE, Cursor.height),
    451     SSMFIELD_ENTRY(             VMSVGAR3STATE, Cursor.cbData),
    452     SSMFIELD_ENTRY_IGN_HCPTR(   VMSVGAR3STATE, Cursor.pData),
    453     SSMFIELD_ENTRY(             VMSVGAR3STATE, colorAnnotation),
    454     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, cBusyDelayedEmts),
    455 #ifdef VMSVGA_USE_EMT_HALT_CODE
    456     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, BusyDelayedEmts),
    457 #else
    458     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, hBusyDelayedEmts),
    459 #endif
    460     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatBusyDelayEmts),
    461     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dPresentProf),
    462     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dDrawPrimitivesProf),
    463     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSurfaceDmaProf),
    464     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dBlitSurfaceToScreenProf),
    465     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdDefineGmr2),
    466     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdDefineGmr2Free),
    467     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdDefineGmr2Modify),
    468     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdRemapGmr2),
    469     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdRemapGmr2Modify),
    470     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdInvalidCmd),
    471     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdFence),
    472     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdUpdate),
    473     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdUpdateVerbose),
    474     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdDefineCursor),
    475     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdDefineAlphaCursor),
    476     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdMoveCursor),
    477     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdDisplayCursor),
    478     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdRectFill),
    479     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdRectCopy),
    480     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdRectRopCopy),
    481     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdEscape),
    482     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdDefineScreen),
    483     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdDestroyScreen),
    484     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdDefineGmrFb),
    485     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdBlitGmrFbToScreen),
    486     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdBlitScreentoGmrFb),
    487     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdAnnotationFill),
    488     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3CmdAnnotationCopy),
    489     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSurfaceDefine),
    490     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSurfaceDefineV2),
    491     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSurfaceDestroy),
    492     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSurfaceCopy),
    493     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSurfaceStretchBlt),
    494     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSurfaceDma),
    495     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSurfaceScreen),
    496     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dContextDefine),
    497     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dContextDestroy),
    498     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSetTransform),
    499     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSetZRange),
    500     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSetRenderState),
    501     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSetRenderTarget),
    502     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSetTextureState),
    503     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSetMaterial),
    504     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSetLightData),
    505     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSetLightEnable),
    506     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSetViewPort),
    507     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSetClipPlane),
    508     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dClear),
    509     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dPresent),
    510     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dPresentReadBack),
    511     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dShaderDefine),
    512     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dShaderDestroy),
    513     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSetShader),
    514     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSetShaderConst),
    515     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dDrawPrimitives),
    516     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dSetScissorRect),
    517     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dBeginQuery),
    518     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dEndQuery),
    519     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dWaitForQuery),
    520     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dGenerateMipmaps),
    521     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dActivateSurface),
    522     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3Cmd3dDeactivateSurface),
    523 
    524     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3RegConfigDoneWr),
    525     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3RegGmrDescriptorWr),
    526     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3RegGmrDescriptorWrErrors),
    527     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatR3RegGmrDescriptorWrFree),
    528 
    529     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatFifoCommands),
    530     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatFifoErrors),
    531     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatFifoUnkCmds),
    532     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatFifoTodoTimeout),
    533     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatFifoTodoWoken),
    534     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatFifoStalls),
    535     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatFifoExtendedSleep),
    536 # if defined(VMSVGA_USE_FIFO_ACCESS_HANDLER) || defined(DEBUG_FIFO_ACCESS)
    537     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatFifoAccessHandler),
    538 # endif
    539     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatFifoCursorFetchAgain),
    540     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatFifoCursorNoChange),
    541     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatFifoCursorPosition),
    542     SSMFIELD_ENTRY_IGNORE(      VMSVGAR3STATE, StatFifoCursorVisiblity),
    543 
    544     SSMFIELD_ENTRY_TERM()
    545 };
    546 
    547 /**
    548  * SSM descriptor table for the VGAState.svga structure.
    549  */
    550 static SSMFIELD const g_aVGAStateSVGAFields[] =
    551 {
    552     SSMFIELD_ENTRY_IGN_GCPHYS(      VMSVGAState, GCPhysFIFO),
    553     SSMFIELD_ENTRY_IGNORE(          VMSVGAState, cbFIFO),
    554     SSMFIELD_ENTRY_IGNORE(          VMSVGAState, cbFIFOConfig),
    555     SSMFIELD_ENTRY(                 VMSVGAState, u32SVGAId),
    556     SSMFIELD_ENTRY(                 VMSVGAState, fEnabled),
    557     SSMFIELD_ENTRY(                 VMSVGAState, fConfigured),
    558     SSMFIELD_ENTRY(                 VMSVGAState, fBusy),
    559     SSMFIELD_ENTRY(                 VMSVGAState, fTraces),
    560     SSMFIELD_ENTRY(                 VMSVGAState, u32GuestId),
    561     SSMFIELD_ENTRY(                 VMSVGAState, cScratchRegion),
    562     SSMFIELD_ENTRY(                 VMSVGAState, au32ScratchRegion),
    563     SSMFIELD_ENTRY(                 VMSVGAState, u32IrqStatus),
    564     SSMFIELD_ENTRY(                 VMSVGAState, u32IrqMask),
    565     SSMFIELD_ENTRY(                 VMSVGAState, u32PitchLock),
    566     SSMFIELD_ENTRY(                 VMSVGAState, u32CurrentGMRId),
    567     SSMFIELD_ENTRY(                 VMSVGAState, u32DeviceCaps),
    568     SSMFIELD_ENTRY(                 VMSVGAState, u32IndexReg),
    569     SSMFIELD_ENTRY_IGNORE(          VMSVGAState, hFIFORequestSem),
    570     SSMFIELD_ENTRY_IGNORE(          VMSVGAState, uLastCursorUpdateCount),
    571     SSMFIELD_ENTRY_IGNORE(          VMSVGAState, fFIFOThreadSleeping),
    572     SSMFIELD_ENTRY_VER(             VMSVGAState, fGFBRegisters, VGA_SAVEDSTATE_VERSION_VMSVGA_SCREENS),
    573     SSMFIELD_ENTRY(                 VMSVGAState, uWidth),
    574     SSMFIELD_ENTRY(                 VMSVGAState, uHeight),
    575     SSMFIELD_ENTRY(                 VMSVGAState, uBpp),
    576     SSMFIELD_ENTRY(                 VMSVGAState, cbScanline),
    577     SSMFIELD_ENTRY_VER(             VMSVGAState, uScreenOffset, VGA_SAVEDSTATE_VERSION_VMSVGA),
    578     SSMFIELD_ENTRY_VER(             VMSVGAState, uCursorX, VGA_SAVEDSTATE_VERSION_VMSVGA_CURSOR),
    579     SSMFIELD_ENTRY_VER(             VMSVGAState, uCursorY, VGA_SAVEDSTATE_VERSION_VMSVGA_CURSOR),
    580     SSMFIELD_ENTRY_VER(             VMSVGAState, uCursorID, VGA_SAVEDSTATE_VERSION_VMSVGA_CURSOR),
    581     SSMFIELD_ENTRY_VER(             VMSVGAState, uCursorOn, VGA_SAVEDSTATE_VERSION_VMSVGA_CURSOR),
    582     SSMFIELD_ENTRY(                 VMSVGAState, u32MaxWidth),
    583     SSMFIELD_ENTRY(                 VMSVGAState, u32MaxHeight),
    584     SSMFIELD_ENTRY(                 VMSVGAState, u32ActionFlags),
    585     SSMFIELD_ENTRY(                 VMSVGAState, f3DEnabled),
    586     SSMFIELD_ENTRY(                 VMSVGAState, fVRAMTracking),
    587     SSMFIELD_ENTRY_IGNORE(          VMSVGAState, u8FIFOExtCommand),
    588     SSMFIELD_ENTRY_IGNORE(          VMSVGAState, fFifoExtCommandWakeup),
    589     SSMFIELD_ENTRY_IGNORE(          VMSVGAState, cGMR),
    590     SSMFIELD_ENTRY_TERM()
    591 };
    592 #endif /* IN_RING3 */
    593 
    594 
    595 /*********************************************************************************************************************************
    596 *   Internal Functions                                                                                                           *
    597 *********************************************************************************************************************************/
    598 #ifdef IN_RING3
    599 static void vmsvgaR3SetTraces(PPDMDEVINS pDevIns, PVGASTATE pThis, bool fTraces);
    600 static int vmsvgaR3LoadExecFifo(PCPDMDEVHLPR3 pHlp, PVGASTATE pThis, PVGASTATECC pThisCC, PSSMHANDLE pSSM,
    601                                 uint32_t uVersion, uint32_t uPass);
    602 static int vmsvgaR3SaveExecFifo(PCPDMDEVHLPR3 pHlp, PVGASTATECC pThisCC, PSSMHANDLE pSSM);
    603 static void vmsvgaR3CmdBufSubmit(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, RTGCPHYS GCPhysCB, SVGACBContext CBCtx);
    604 # ifdef VBOX_WITH_VMSVGA3D
    605 static void vmsvgaR3GmrFree(PVGASTATECC pThisCC, uint32_t idGMR);
    606 # endif /* VBOX_WITH_VMSVGA3D */
    607 #endif /* IN_RING3 */
    608 
    609 
    610 
    611 #ifdef IN_RING3
    612 VMSVGASCREENOBJECT *vmsvgaR3GetScreenObject(PVGASTATECC pThisCC, uint32_t idScreen)
    613 {
    614     PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
    615     if (   idScreen < (uint32_t)RT_ELEMENTS(pSVGAState->aScreens)
    616         && pSVGAState
    617         && pSVGAState->aScreens[idScreen].fDefined)
    618     {
    619         return &pSVGAState->aScreens[idScreen];
    620     }
    621     return NULL;
    622 }
    623 
    624 void vmsvgaR3ResetScreens(PVGASTATE pThis, PVGASTATECC pThisCC)
    625 {
    626 # ifdef VBOX_WITH_VMSVGA3D
    627     if (pThis->svga.f3DEnabled)
    628     {
    629         for (uint32_t idScreen = 0; idScreen < (uint32_t)RT_ELEMENTS(pThisCC->svga.pSvgaR3State->aScreens); ++idScreen)
    630         {
    631             VMSVGASCREENOBJECT *pScreen = vmsvgaR3GetScreenObject(pThisCC, idScreen);
    632             if (pScreen)
    633                 vmsvga3dDestroyScreen(pThisCC, pScreen);
    634         }
    635     }
    636 # else
    637     RT_NOREF(pThis, pThisCC);
    638 # endif
    639 }
    640 #endif /* IN_RING3 */
    641 
    642 #define SVGA_CASE_ID2STR(idx) case idx: return #idx
    643 
    644 #if defined(LOG_ENABLED)
    645 /**
    646  * Index register string name lookup
    647  *
    648  * @returns Index register string or "UNKNOWN"
    649  * @param   pThis       The shared VGA/VMSVGA state.
    650  * @param   idxReg      The index register.
    651  */
    652 static const char *vmsvgaIndexToString(PVGASTATE pThis, uint32_t idxReg)
    653 {
    654     switch (idxReg)
    655     {
    656         SVGA_CASE_ID2STR(SVGA_REG_ID);
    657         SVGA_CASE_ID2STR(SVGA_REG_ENABLE);
    658         SVGA_CASE_ID2STR(SVGA_REG_WIDTH);
    659         SVGA_CASE_ID2STR(SVGA_REG_HEIGHT);
    660         SVGA_CASE_ID2STR(SVGA_REG_MAX_WIDTH);
    661         SVGA_CASE_ID2STR(SVGA_REG_MAX_HEIGHT);
    662         SVGA_CASE_ID2STR(SVGA_REG_DEPTH);
    663         SVGA_CASE_ID2STR(SVGA_REG_BITS_PER_PIXEL);       /* Current bpp in the guest */
    664         SVGA_CASE_ID2STR(SVGA_REG_PSEUDOCOLOR);
    665         SVGA_CASE_ID2STR(SVGA_REG_RED_MASK);
    666         SVGA_CASE_ID2STR(SVGA_REG_GREEN_MASK);
    667         SVGA_CASE_ID2STR(SVGA_REG_BLUE_MASK);
    668         SVGA_CASE_ID2STR(SVGA_REG_BYTES_PER_LINE);
    669         SVGA_CASE_ID2STR(SVGA_REG_FB_START);            /* (Deprecated) */
    670         SVGA_CASE_ID2STR(SVGA_REG_FB_OFFSET);
    671         SVGA_CASE_ID2STR(SVGA_REG_VRAM_SIZE);
    672         SVGA_CASE_ID2STR(SVGA_REG_FB_SIZE);
    673 
    674         /* ID 0 implementation only had the above registers, then the palette */
    675         SVGA_CASE_ID2STR(SVGA_REG_CAPABILITIES);
    676         SVGA_CASE_ID2STR(SVGA_REG_MEM_START);           /* (Deprecated) */
    677         SVGA_CASE_ID2STR(SVGA_REG_MEM_SIZE);
    678         SVGA_CASE_ID2STR(SVGA_REG_CONFIG_DONE);         /* Set when memory area configured */
    679         SVGA_CASE_ID2STR(SVGA_REG_SYNC);                /* See "FIFO Synchronization Registers" */
    680         SVGA_CASE_ID2STR(SVGA_REG_BUSY);                /* See "FIFO Synchronization Registers" */
    681         SVGA_CASE_ID2STR(SVGA_REG_GUEST_ID);            /* Set guest OS identifier */
    682         SVGA_CASE_ID2STR(SVGA_REG_CURSOR_ID);           /* (Deprecated) */
    683         SVGA_CASE_ID2STR(SVGA_REG_CURSOR_X);            /* (Deprecated) */
    684         SVGA_CASE_ID2STR(SVGA_REG_CURSOR_Y);            /* (Deprecated) */
    685         SVGA_CASE_ID2STR(SVGA_REG_CURSOR_ON);           /* (Deprecated) */
    686         SVGA_CASE_ID2STR(SVGA_REG_HOST_BITS_PER_PIXEL); /* (Deprecated) */
    687         SVGA_CASE_ID2STR(SVGA_REG_SCRATCH_SIZE);        /* Number of scratch registers */
    688         SVGA_CASE_ID2STR(SVGA_REG_MEM_REGS);            /* Number of FIFO registers */
    689         SVGA_CASE_ID2STR(SVGA_REG_NUM_DISPLAYS);        /* (Deprecated) */
    690         SVGA_CASE_ID2STR(SVGA_REG_PITCHLOCK);           /* Fixed pitch for all modes */
    691         SVGA_CASE_ID2STR(SVGA_REG_IRQMASK);             /* Interrupt mask */
    692 
    693         /* Legacy multi-monitor support */
    694         SVGA_CASE_ID2STR(SVGA_REG_NUM_GUEST_DISPLAYS); /* Number of guest displays in X/Y direction */
    695         SVGA_CASE_ID2STR(SVGA_REG_DISPLAY_ID);         /* Display ID for the following display attributes */
    696         SVGA_CASE_ID2STR(SVGA_REG_DISPLAY_IS_PRIMARY); /* Whether this is a primary display */
    697         SVGA_CASE_ID2STR(SVGA_REG_DISPLAY_POSITION_X); /* The display position x */
    698         SVGA_CASE_ID2STR(SVGA_REG_DISPLAY_POSITION_Y); /* The display position y */
    699         SVGA_CASE_ID2STR(SVGA_REG_DISPLAY_WIDTH);      /* The display's width */
    700         SVGA_CASE_ID2STR(SVGA_REG_DISPLAY_HEIGHT);     /* The display's height */
    701 
    702         SVGA_CASE_ID2STR(SVGA_REG_GMR_ID);
    703         SVGA_CASE_ID2STR(SVGA_REG_GMR_DESCRIPTOR);
    704         SVGA_CASE_ID2STR(SVGA_REG_GMR_MAX_IDS);
    705         SVGA_CASE_ID2STR(SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH);
    706 
    707         SVGA_CASE_ID2STR(SVGA_REG_TRACES);             /* Enable trace-based updates even when FIFO is on */
    708         SVGA_CASE_ID2STR(SVGA_REG_GMRS_MAX_PAGES);     /* Maximum number of 4KB pages for all GMRs */
    709         SVGA_CASE_ID2STR(SVGA_REG_MEMORY_SIZE);        /* Total dedicated device memory excluding FIFO */
    710         SVGA_CASE_ID2STR(SVGA_REG_COMMAND_LOW);        /* Lower 32 bits and submits commands */
    711         SVGA_CASE_ID2STR(SVGA_REG_COMMAND_HIGH);       /* Upper 32 bits of command buffer PA */
    712         SVGA_CASE_ID2STR(SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM);   /* Max primary memory */
    713         SVGA_CASE_ID2STR(SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB); /* Suggested limit on mob mem */
    714         SVGA_CASE_ID2STR(SVGA_REG_DEV_CAP);            /* Write dev cap index, read value */
    715         SVGA_CASE_ID2STR(SVGA_REG_CMD_PREPEND_LOW);
    716         SVGA_CASE_ID2STR(SVGA_REG_iCMD_PREPEND_HIGH);
    717         SVGA_CASE_ID2STR(SVGA_REG_SCREENTARGET_MAX_WIDTH);
    718         SVGA_CASE_ID2STR(SVGA_REG_SCREENTARGET_MAX_HEIGHT);
    719         SVGA_CASE_ID2STR(SVGA_REG_MOB_MAX_SIZE);
    720         SVGA_CASE_ID2STR(SVGA_REG_TOP);                /* Must be 1 more than the last register */
    721 
    722         default:
    723             if (idxReg - (uint32_t)SVGA_SCRATCH_BASE < pThis->svga.cScratchRegion)
    724                 return "SVGA_SCRATCH_BASE reg";
    725             if (idxReg - (uint32_t)SVGA_PALETTE_BASE < (uint32_t)SVGA_NUM_PALETTE_REGS)
    726                 return "SVGA_PALETTE_BASE reg";
    727             return "UNKNOWN";
    728     }
    729 }
    730 #endif /* LOG_ENABLED */
    731 
    732 #if defined(IN_RING3) && (defined(LOG_ENABLED) || defined(VBOX_STRICT))
    733 /**
    734  * FIFO command name lookup
    735  *
    736  * @returns FIFO command string or "UNKNOWN"
    737  * @param   u32Cmd      FIFO command
    738  */
    739 static const char *vmsvgaR3FifoCmdToString(uint32_t u32Cmd)
    740 {
    741     switch (u32Cmd)
    742     {
    743         SVGA_CASE_ID2STR(SVGA_CMD_INVALID_CMD);
    744         SVGA_CASE_ID2STR(SVGA_CMD_UPDATE);
    745         SVGA_CASE_ID2STR(SVGA_CMD_RECT_FILL);
    746         SVGA_CASE_ID2STR(SVGA_CMD_RECT_COPY);
    747         SVGA_CASE_ID2STR(SVGA_CMD_RECT_ROP_COPY);
    748         SVGA_CASE_ID2STR(SVGA_CMD_DEFINE_CURSOR);
    749         SVGA_CASE_ID2STR(SVGA_CMD_DISPLAY_CURSOR);
    750         SVGA_CASE_ID2STR(SVGA_CMD_MOVE_CURSOR);
    751         SVGA_CASE_ID2STR(SVGA_CMD_DEFINE_ALPHA_CURSOR);
    752         SVGA_CASE_ID2STR(SVGA_CMD_UPDATE_VERBOSE);
    753         SVGA_CASE_ID2STR(SVGA_CMD_FRONT_ROP_FILL);
    754         SVGA_CASE_ID2STR(SVGA_CMD_FENCE);
    755         SVGA_CASE_ID2STR(SVGA_CMD_ESCAPE);
    756         SVGA_CASE_ID2STR(SVGA_CMD_DEFINE_SCREEN);
    757         SVGA_CASE_ID2STR(SVGA_CMD_DESTROY_SCREEN);
    758         SVGA_CASE_ID2STR(SVGA_CMD_DEFINE_GMRFB);
    759         SVGA_CASE_ID2STR(SVGA_CMD_BLIT_GMRFB_TO_SCREEN);
    760         SVGA_CASE_ID2STR(SVGA_CMD_BLIT_SCREEN_TO_GMRFB);
    761         SVGA_CASE_ID2STR(SVGA_CMD_ANNOTATION_FILL);
    762         SVGA_CASE_ID2STR(SVGA_CMD_ANNOTATION_COPY);
    763         SVGA_CASE_ID2STR(SVGA_CMD_DEFINE_GMR2);
    764         SVGA_CASE_ID2STR(SVGA_CMD_REMAP_GMR2);
    765         SVGA_CASE_ID2STR(SVGA_CMD_DEAD);
    766         SVGA_CASE_ID2STR(SVGA_CMD_DEAD_2);
    767         SVGA_CASE_ID2STR(SVGA_CMD_NOP);
    768         SVGA_CASE_ID2STR(SVGA_CMD_NOP_ERROR);
    769         SVGA_CASE_ID2STR(SVGA_CMD_MAX);
    770         SVGA_CASE_ID2STR(SVGA_3D_CMD_SURFACE_DEFINE);
    771         SVGA_CASE_ID2STR(SVGA_3D_CMD_SURFACE_DESTROY);
    772         SVGA_CASE_ID2STR(SVGA_3D_CMD_SURFACE_COPY);
    773         SVGA_CASE_ID2STR(SVGA_3D_CMD_SURFACE_STRETCHBLT);
    774         SVGA_CASE_ID2STR(SVGA_3D_CMD_SURFACE_DMA);
    775         SVGA_CASE_ID2STR(SVGA_3D_CMD_CONTEXT_DEFINE);
    776         SVGA_CASE_ID2STR(SVGA_3D_CMD_CONTEXT_DESTROY);
    777         SVGA_CASE_ID2STR(SVGA_3D_CMD_SETTRANSFORM);
    778         SVGA_CASE_ID2STR(SVGA_3D_CMD_SETZRANGE);
    779         SVGA_CASE_ID2STR(SVGA_3D_CMD_SETRENDERSTATE);
    780         SVGA_CASE_ID2STR(SVGA_3D_CMD_SETRENDERTARGET);
    781         SVGA_CASE_ID2STR(SVGA_3D_CMD_SETTEXTURESTATE);
    782         SVGA_CASE_ID2STR(SVGA_3D_CMD_SETMATERIAL);
    783         SVGA_CASE_ID2STR(SVGA_3D_CMD_SETLIGHTDATA);
    784         SVGA_CASE_ID2STR(SVGA_3D_CMD_SETLIGHTENABLED);
    785         SVGA_CASE_ID2STR(SVGA_3D_CMD_SETVIEWPORT);
    786         SVGA_CASE_ID2STR(SVGA_3D_CMD_SETCLIPPLANE);
    787         SVGA_CASE_ID2STR(SVGA_3D_CMD_CLEAR);
    788         SVGA_CASE_ID2STR(SVGA_3D_CMD_PRESENT);
    789         SVGA_CASE_ID2STR(SVGA_3D_CMD_SHADER_DEFINE);
    790         SVGA_CASE_ID2STR(SVGA_3D_CMD_SHADER_DESTROY);
    791         SVGA_CASE_ID2STR(SVGA_3D_CMD_SET_SHADER);
    792         SVGA_CASE_ID2STR(SVGA_3D_CMD_SET_SHADER_CONST);
    793         SVGA_CASE_ID2STR(SVGA_3D_CMD_DRAW_PRIMITIVES);
    794         SVGA_CASE_ID2STR(SVGA_3D_CMD_SETSCISSORRECT);
    795         SVGA_CASE_ID2STR(SVGA_3D_CMD_BEGIN_QUERY);
    796         SVGA_CASE_ID2STR(SVGA_3D_CMD_END_QUERY);
    797         SVGA_CASE_ID2STR(SVGA_3D_CMD_WAIT_FOR_QUERY);
    798         SVGA_CASE_ID2STR(SVGA_3D_CMD_PRESENT_READBACK);
    799         SVGA_CASE_ID2STR(SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN);
    800         SVGA_CASE_ID2STR(SVGA_3D_CMD_SURFACE_DEFINE_V2);
    801         SVGA_CASE_ID2STR(SVGA_3D_CMD_GENERATE_MIPMAPS);
    802         SVGA_CASE_ID2STR(SVGA_3D_CMD_VIDEO_CREATE_DECODER);
    803         SVGA_CASE_ID2STR(SVGA_3D_CMD_VIDEO_DESTROY_DECODER);
    804         SVGA_CASE_ID2STR(SVGA_3D_CMD_VIDEO_CREATE_PROCESSOR);
    805         SVGA_CASE_ID2STR(SVGA_3D_CMD_VIDEO_DESTROY_PROCESSOR);
    806         SVGA_CASE_ID2STR(SVGA_3D_CMD_VIDEO_DECODE_START_FRAME);
    807         SVGA_CASE_ID2STR(SVGA_3D_CMD_VIDEO_DECODE_RENDER);
    808         SVGA_CASE_ID2STR(SVGA_3D_CMD_VIDEO_DECODE_END_FRAME);
    809         SVGA_CASE_ID2STR(SVGA_3D_CMD_VIDEO_PROCESS_FRAME);
    810         SVGA_CASE_ID2STR(SVGA_3D_CMD_ACTIVATE_SURFACE);
    811         SVGA_CASE_ID2STR(SVGA_3D_CMD_DEACTIVATE_SURFACE);
    812         SVGA_CASE_ID2STR(SVGA_3D_CMD_SCREEN_DMA);
    813         SVGA_CASE_ID2STR(SVGA_3D_CMD_DEAD1);
    814         SVGA_CASE_ID2STR(SVGA_3D_CMD_DEAD2);
    815         SVGA_CASE_ID2STR(SVGA_3D_CMD_LOGICOPS_BITBLT);
    816         SVGA_CASE_ID2STR(SVGA_3D_CMD_LOGICOPS_TRANSBLT);
    817         SVGA_CASE_ID2STR(SVGA_3D_CMD_LOGICOPS_STRETCHBLT);
    818         SVGA_CASE_ID2STR(SVGA_3D_CMD_LOGICOPS_COLORFILL);
    819         SVGA_CASE_ID2STR(SVGA_3D_CMD_LOGICOPS_ALPHABLEND);
    820         SVGA_CASE_ID2STR(SVGA_3D_CMD_LOGICOPS_CLEARTYPEBLEND);
    821         SVGA_CASE_ID2STR(SVGA_3D_CMD_SET_OTABLE_BASE);
    822         SVGA_CASE_ID2STR(SVGA_3D_CMD_READBACK_OTABLE);
    823         SVGA_CASE_ID2STR(SVGA_3D_CMD_DEFINE_GB_MOB);
    824         SVGA_CASE_ID2STR(SVGA_3D_CMD_DESTROY_GB_MOB);
    825         SVGA_CASE_ID2STR(SVGA_3D_CMD_DEAD3);
    826         SVGA_CASE_ID2STR(SVGA_3D_CMD_UPDATE_GB_MOB_MAPPING);
    827         SVGA_CASE_ID2STR(SVGA_3D_CMD_DEFINE_GB_SURFACE);
    828         SVGA_CASE_ID2STR(SVGA_3D_CMD_DESTROY_GB_SURFACE);
    829         SVGA_CASE_ID2STR(SVGA_3D_CMD_BIND_GB_SURFACE);
    830         SVGA_CASE_ID2STR(SVGA_3D_CMD_COND_BIND_GB_SURFACE);
    831         SVGA_CASE_ID2STR(SVGA_3D_CMD_UPDATE_GB_IMAGE);
    832         SVGA_CASE_ID2STR(SVGA_3D_CMD_UPDATE_GB_SURFACE);
    833         SVGA_CASE_ID2STR(SVGA_3D_CMD_READBACK_GB_IMAGE);
    834         SVGA_CASE_ID2STR(SVGA_3D_CMD_READBACK_GB_SURFACE);
    835         SVGA_CASE_ID2STR(SVGA_3D_CMD_INVALIDATE_GB_IMAGE);
    836         SVGA_CASE_ID2STR(SVGA_3D_CMD_INVALIDATE_GB_SURFACE);
    837         SVGA_CASE_ID2STR(SVGA_3D_CMD_DEFINE_GB_CONTEXT);
    838         SVGA_CASE_ID2STR(SVGA_3D_CMD_DESTROY_GB_CONTEXT);
    839         SVGA_CASE_ID2STR(SVGA_3D_CMD_BIND_GB_CONTEXT);
    840         SVGA_CASE_ID2STR(SVGA_3D_CMD_READBACK_GB_CONTEXT);
    841         SVGA_CASE_ID2STR(SVGA_3D_CMD_INVALIDATE_GB_CONTEXT);
    842         SVGA_CASE_ID2STR(SVGA_3D_CMD_DEFINE_GB_SHADER);
    843         SVGA_CASE_ID2STR(SVGA_3D_CMD_DESTROY_GB_SHADER);
    844         SVGA_CASE_ID2STR(SVGA_3D_CMD_BIND_GB_SHADER);
    845         SVGA_CASE_ID2STR(SVGA_3D_CMD_SET_OTABLE_BASE64);
    846         SVGA_CASE_ID2STR(SVGA_3D_CMD_BEGIN_GB_QUERY);
    847         SVGA_CASE_ID2STR(SVGA_3D_CMD_END_GB_QUERY);
    848         SVGA_CASE_ID2STR(SVGA_3D_CMD_WAIT_FOR_GB_QUERY);
    849         SVGA_CASE_ID2STR(SVGA_3D_CMD_NOP);
    850         SVGA_CASE_ID2STR(SVGA_3D_CMD_ENABLE_GART);
    851         SVGA_CASE_ID2STR(SVGA_3D_CMD_DISABLE_GART);
    852         SVGA_CASE_ID2STR(SVGA_3D_CMD_MAP_MOB_INTO_GART);
    853         SVGA_CASE_ID2STR(SVGA_3D_CMD_UNMAP_GART_RANGE);
    854         SVGA_CASE_ID2STR(SVGA_3D_CMD_DEFINE_GB_SCREENTARGET);
    855         SVGA_CASE_ID2STR(SVGA_3D_CMD_DESTROY_GB_SCREENTARGET);
    856         SVGA_CASE_ID2STR(SVGA_3D_CMD_BIND_GB_SCREENTARGET);
    857         SVGA_CASE_ID2STR(SVGA_3D_CMD_UPDATE_GB_SCREENTARGET);
    858         SVGA_CASE_ID2STR(SVGA_3D_CMD_READBACK_GB_IMAGE_PARTIAL);
    859         SVGA_CASE_ID2STR(SVGA_3D_CMD_INVALIDATE_GB_IMAGE_PARTIAL);
    860         SVGA_CASE_ID2STR(SVGA_3D_CMD_SET_GB_SHADERCONSTS_INLINE);
    861         SVGA_CASE_ID2STR(SVGA_3D_CMD_GB_SCREEN_DMA);
    862         SVGA_CASE_ID2STR(SVGA_3D_CMD_BIND_GB_SURFACE_WITH_PITCH);
    863         SVGA_CASE_ID2STR(SVGA_3D_CMD_GB_MOB_FENCE);
    864         SVGA_CASE_ID2STR(SVGA_3D_CMD_DEFINE_GB_SURFACE_V2);
    865         SVGA_CASE_ID2STR(SVGA_3D_CMD_DEFINE_GB_MOB64);
    866         SVGA_CASE_ID2STR(SVGA_3D_CMD_REDEFINE_GB_MOB64);
    867         SVGA_CASE_ID2STR(SVGA_3D_CMD_NOP_ERROR);
    868         SVGA_CASE_ID2STR(SVGA_3D_CMD_SET_VERTEX_STREAMS);
    869         SVGA_CASE_ID2STR(SVGA_3D_CMD_SET_VERTEX_DECLS);
    870         SVGA_CASE_ID2STR(SVGA_3D_CMD_SET_VERTEX_DIVISORS);
    871         SVGA_CASE_ID2STR(SVGA_3D_CMD_DRAW);
    872         SVGA_CASE_ID2STR(SVGA_3D_CMD_DRAW_INDEXED);
    873         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_CONTEXT);
    874         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_CONTEXT);
    875         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_BIND_CONTEXT);
    876         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_READBACK_CONTEXT);
    877         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_INVALIDATE_CONTEXT);
    878         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_SINGLE_CONSTANT_BUFFER);
    879         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_SHADER_RESOURCES);
    880         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_SHADER);
    881         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_SAMPLERS);
    882         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DRAW);
    883         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DRAW_INDEXED);
    884         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DRAW_INSTANCED);
    885         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DRAW_INDEXED_INSTANCED);
    886         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DRAW_AUTO);
    887         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_INPUT_LAYOUT);
    888         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_VERTEX_BUFFERS);
    889         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_INDEX_BUFFER);
    890         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_TOPOLOGY);
    891         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_RENDERTARGETS);
    892         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_BLEND_STATE);
    893         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_DEPTHSTENCIL_STATE);
    894         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_RASTERIZER_STATE);
    895         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_QUERY);
    896         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_QUERY);
    897         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_BIND_QUERY);
    898         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_QUERY_OFFSET);
    899         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_BEGIN_QUERY);
    900         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_END_QUERY);
    901         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_READBACK_QUERY);
    902         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_PREDICATION);
    903         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_SOTARGETS);
    904         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_VIEWPORTS);
    905         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_SCISSORRECTS);
    906         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_CLEAR_RENDERTARGET_VIEW);
    907         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_CLEAR_DEPTHSTENCIL_VIEW);
    908         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_PRED_COPY_REGION);
    909         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_PRED_COPY);
    910         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_STRETCHBLT);
    911         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_GENMIPS);
    912         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_UPDATE_SUBRESOURCE);
    913         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_READBACK_SUBRESOURCE);
    914         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_INVALIDATE_SUBRESOURCE);
    915         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_SHADERRESOURCE_VIEW);
    916         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_SHADERRESOURCE_VIEW);
    917         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_RENDERTARGET_VIEW);
    918         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_RENDERTARGET_VIEW);
    919         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_DEPTHSTENCIL_VIEW);
    920         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_DEPTHSTENCIL_VIEW);
    921         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_ELEMENTLAYOUT);
    922         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_ELEMENTLAYOUT);
    923         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_BLEND_STATE);
    924         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_BLEND_STATE);
    925         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_DEPTHSTENCIL_STATE);
    926         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_DEPTHSTENCIL_STATE);
    927         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_RASTERIZER_STATE);
    928         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_RASTERIZER_STATE);
    929         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_SAMPLER_STATE);
    930         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_SAMPLER_STATE);
    931         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_SHADER);
    932         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_SHADER);
    933         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_BIND_SHADER);
    934         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_STREAMOUTPUT);
    935         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_STREAMOUTPUT);
    936         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_STREAMOUTPUT);
    937         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_COTABLE);
    938         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_READBACK_COTABLE);
    939         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_BUFFER_COPY);
    940         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_TRANSFER_FROM_BUFFER);
    941         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SURFACE_COPY_AND_READBACK);
    942         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_MOVE_QUERY);
    943         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_BIND_ALL_QUERY);
    944         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_READBACK_ALL_QUERY);
    945         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_PRED_TRANSFER_FROM_BUFFER);
    946         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_MOB_FENCE_64);
    947         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_BIND_ALL_SHADER);
    948         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_HINT);
    949         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_BUFFER_UPDATE);
    950         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_VS_CONSTANT_BUFFER_OFFSET);
    951         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_PS_CONSTANT_BUFFER_OFFSET);
    952         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_GS_CONSTANT_BUFFER_OFFSET);
    953         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_RESERVED1);
    954         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_RESERVED2);
    955         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_RESERVED3);
    956         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_COND_BIND_ALL_SHADER);
    957         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_MAX);
    958         default: return "UNKNOWN";
    959     }
    960 }
    961 #endif /* IN_RING3 && (LOG_ENABLED || VBOX_STRICT) */
    962 
    963 #ifdef IN_RING3
    964 
    965 /**
    966  * @interface_method_impl{PDMIDISPLAYPORT,pfnSetViewport}
    967  */
    968 DECLCALLBACK(void) vmsvgaR3PortSetViewport(PPDMIDISPLAYPORT pInterface, uint32_t idScreen, uint32_t x, uint32_t y, uint32_t cx, uint32_t cy)
    969 {
    970     PVGASTATECC pThisCC = RT_FROM_MEMBER(pInterface, VGASTATECC, IPort);
    971     PVGASTATE   pThis   = PDMDEVINS_2_DATA(pThisCC->pDevIns, PVGASTATE);
    972 
    973     Log(("vmsvgaPortSetViewPort: screen %d (%d,%d)(%d,%d)\n", idScreen, x, y, cx, cy));
    974     VMSVGAVIEWPORT const OldViewport = pThis->svga.viewport;
    975 
    976     /** @todo Test how it interacts with multiple screen objects. */
    977     VMSVGASCREENOBJECT *pScreen = vmsvgaR3GetScreenObject(pThisCC, idScreen);
    978     uint32_t const uWidth = pScreen ? pScreen->cWidth : 0;
    979     uint32_t const uHeight = pScreen ? pScreen->cHeight : 0;
    980 
    981     if (x < uWidth)
    982     {
    983         pThis->svga.viewport.x      = x;
    984         pThis->svga.viewport.cx     = RT_MIN(cx, uWidth - x);
    985         pThis->svga.viewport.xRight = x + pThis->svga.viewport.cx;
    986     }
    987     else
    988     {
    989         pThis->svga.viewport.x      = uWidth;
    990         pThis->svga.viewport.cx     = 0;
    991         pThis->svga.viewport.xRight = uWidth;
    992     }
    993     if (y < uHeight)
    994     {
    995         pThis->svga.viewport.y       = y;
    996         pThis->svga.viewport.cy      = RT_MIN(cy, uHeight - y);
    997         pThis->svga.viewport.yLowWC  = uHeight - y - pThis->svga.viewport.cy;
    998         pThis->svga.viewport.yHighWC = uHeight - y;
    999     }
    1000     else
    1001     {
    1002         pThis->svga.viewport.y       = uHeight;
    1003         pThis->svga.viewport.cy      = 0;
    1004         pThis->svga.viewport.yLowWC  = 0;
    1005         pThis->svga.viewport.yHighWC = 0;
    1006     }
    1007 
    1008 # ifdef VBOX_WITH_VMSVGA3D
    1009     /*
    1010      * Now inform the 3D backend.
    1011      */
    1012     if (pThis->svga.f3DEnabled)
    1013         vmsvga3dUpdateHostScreenViewport(pThisCC, idScreen, &OldViewport);
    1014 # else
    1015     RT_NOREF(OldViewport);
    1016 # endif
    1017 }
    1018 
    1019 
    1020 /**
    1021  * Updating screen information in API
    1022  *
    1023  * @param   pThis       The The shared VGA/VMSVGA instance data.
    1024  * @param   pThisCC     The VGA/VMSVGA state for ring-3.
    1025  */
    1026 void vmsvgaR3VBVAResize(PVGASTATE pThis, PVGASTATECC pThisCC)
    1027 {
    1028     int rc;
    1029 
    1030     PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
    1031 
    1032     for (unsigned iScreen = 0; iScreen < RT_ELEMENTS(pSVGAState->aScreens); ++iScreen)
    1033     {
    1034         VMSVGASCREENOBJECT *pScreen = &pSVGAState->aScreens[iScreen];
    1035         if (!pScreen->fModified)
    1036             continue;
    1037 
    1038         pScreen->fModified = false;
    1039 
    1040         VBVAINFOVIEW view;
    1041         RT_ZERO(view);
    1042         view.u32ViewIndex     = pScreen->idScreen;
    1043         // view.u32ViewOffset    = 0;
    1044         view.u32ViewSize      = pThis->vram_size;
    1045         view.u32MaxScreenSize = pThis->vram_size;
    1046 
    1047         VBVAINFOSCREEN screen;
    1048         RT_ZERO(screen);
    1049         screen.u32ViewIndex   = pScreen->idScreen;
    1050 
    1051         if (pScreen->fDefined)
    1052         {
    1053             if (   pScreen->cWidth  == VMSVGA_VAL_UNINITIALIZED
    1054                 || pScreen->cHeight == VMSVGA_VAL_UNINITIALIZED
    1055                 || pScreen->cBpp    == VMSVGA_VAL_UNINITIALIZED)
    1056             {
    1057                 Assert(pThis->svga.fGFBRegisters);
    1058                 continue;
    1059             }
    1060 
    1061             screen.i32OriginX      = pScreen->xOrigin;
    1062             screen.i32OriginY      = pScreen->yOrigin;
    1063             screen.u32StartOffset  = pScreen->offVRAM;
    1064             screen.u32LineSize     = pScreen->cbPitch;
    1065             screen.u32Width        = pScreen->cWidth;
    1066             screen.u32Height       = pScreen->cHeight;
    1067             screen.u16BitsPerPixel = pScreen->cBpp;
    1068             if (!(pScreen->fuScreen & SVGA_SCREEN_DEACTIVATE))
    1069                 screen.u16Flags    = VBVA_SCREEN_F_ACTIVE;
    1070             if (pScreen->fuScreen & SVGA_SCREEN_BLANKING)
    1071                 screen.u16Flags   |= VBVA_SCREEN_F_BLANK2;
    1072         }
    1073         else
    1074         {
    1075             /* Screen is destroyed. */
    1076             screen.u16Flags        = VBVA_SCREEN_F_DISABLED;
    1077         }
    1078 
    1079         rc = pThisCC->pDrv->pfnVBVAResize(pThisCC->pDrv, &view, &screen, pThisCC->pbVRam, /*fResetInputMapping=*/ true);
    1080         AssertRC(rc);
    1081     }
    1082 }
    1083 
    1084 
    1085 /**
    1086  * @interface_method_impl{PDMIDISPLAYPORT,pfnReportMonitorPositions}
    1087  *
    1088  * Used to update screen offsets (positions) since appearently vmwgfx fails to
    1089  * pass correct offsets thru FIFO.
    1090  */
    1091 DECLCALLBACK(void) vmsvgaR3PortReportMonitorPositions(PPDMIDISPLAYPORT pInterface, uint32_t cPositions, PCRTPOINT paPositions)
    1092 {
    1093     PVGASTATECC         pThisCC    = RT_FROM_MEMBER(pInterface, VGASTATECC, IPort);
    1094     PVGASTATE           pThis      = PDMDEVINS_2_DATA(pThisCC->pDevIns, PVGASTATE);
    1095     PVMSVGAR3STATE      pSVGAState = pThisCC->svga.pSvgaR3State;
    1096 
    1097     AssertReturnVoid(pSVGAState);
    1098 
    1099     /* We assume cPositions is the # of outputs Xserver reports and paPositions is (-1, -1) for disabled monitors. */
    1100     cPositions = RT_MIN(cPositions, RT_ELEMENTS(pSVGAState->aScreens));
    1101     for (uint32_t i = 0; i < cPositions; ++i)
    1102     {
    1103         if (   pSVGAState->aScreens[i].xOrigin == paPositions[i].x
    1104             && pSVGAState->aScreens[i].yOrigin == paPositions[i].y)
    1105             continue;
    1106 
    1107         if (pSVGAState->aScreens[i].xOrigin == -1)
    1108             continue;
    1109         if (pSVGAState->aScreens[i].yOrigin == -1)
    1110             continue;
    1111 
    1112         pSVGAState->aScreens[i].xOrigin = paPositions[i].x;
    1113         pSVGAState->aScreens[i].yOrigin = paPositions[i].y;
    1114         pSVGAState->aScreens[i].fModified = true;
    1115     }
    1116 
    1117     vmsvgaR3VBVAResize(pThis, pThisCC);
    1118 }
    1119 
    1120 #endif /* IN_RING3 */
    1121 
    1122 /**
    1123  * Read port register
    1124  *
    1125  * @returns VBox status code.
    1126  * @param   pDevIns     The device instance.
    1127  * @param   pThis       The shared VGA/VMSVGA state.
    1128  * @param   pu32        Where to store the read value
    1129  */
    1130 static int vmsvgaReadPort(PPDMDEVINS pDevIns, PVGASTATE pThis, uint32_t *pu32)
    1131 {
    1132 #ifdef IN_RING3
    1133     PVGASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
    1134 #endif
    1135     int rc = VINF_SUCCESS;
    1136     *pu32 = 0;
    1137 
    1138     /* Rough index register validation. */
    1139     uint32_t idxReg = pThis->svga.u32IndexReg;
    1140 #if !defined(IN_RING3) && defined(VBOX_STRICT)
    1141     ASSERT_GUEST_MSG_RETURN(idxReg < SVGA_SCRATCH_BASE + pThis->svga.cScratchRegion, ("idxReg=%#x\n", idxReg),
    1142                             VINF_IOM_R3_IOPORT_READ);
    1143 #else
    1144     ASSERT_GUEST_MSG_STMT_RETURN(idxReg < SVGA_SCRATCH_BASE + pThis->svga.cScratchRegion, ("idxReg=%#x\n", idxReg),
    1145                                  STAM_REL_COUNTER_INC(&pThis->svga.StatRegUnknownRd),
    1146                                  VINF_SUCCESS);
    1147 #endif
    1148     RT_UNTRUSTED_VALIDATED_FENCE();
    1149 
    1150     /* We must adjust the register number if we're in SVGA_ID_0 mode because the PALETTE range moved. */
    1151     if (   idxReg >= SVGA_REG_ID_0_TOP
    1152         && pThis->svga.u32SVGAId == SVGA_ID_0)
    1153     {
    1154         idxReg += SVGA_PALETTE_BASE - SVGA_REG_ID_0_TOP;
    1155         Log(("vmsvgaWritePort: SVGA_ID_0 reg adj %#x -> %#x\n", pThis->svga.u32IndexReg, idxReg));
    1156     }
    1157 
    1158     switch (idxReg)
    1159     {
    1160         case SVGA_REG_ID:
    1161             STAM_REL_COUNTER_INC(&pThis->svga.StatRegIdRd);
    1162             *pu32 = pThis->svga.u32SVGAId;
    1163             break;
    1164 
    1165         case SVGA_REG_ENABLE:
    1166             STAM_REL_COUNTER_INC(&pThis->svga.StatRegEnableRd);
    1167             *pu32 = pThis->svga.fEnabled;
    1168             break;
    1169 
    1170         case SVGA_REG_WIDTH:
    1171         {
    1172             STAM_REL_COUNTER_INC(&pThis->svga.StatRegWidthRd);
    1173             if (    pThis->svga.fEnabled
    1174                 &&  pThis->svga.uWidth != VMSVGA_VAL_UNINITIALIZED)
    1175                 *pu32 = pThis->svga.uWidth;
    1176             else
    1177             {
    1178 #ifndef IN_RING3
    1179                 rc = VINF_IOM_R3_IOPORT_READ;
    1180 #else
    1181                 *pu32 = pThisCC->pDrv->cx;
    1182 #endif
    1183             }
    1184             break;
    1185         }
    1186 
    1187         case SVGA_REG_HEIGHT:
    1188         {
    1189             STAM_REL_COUNTER_INC(&pThis->svga.StatRegHeightRd);
    1190             if (    pThis->svga.fEnabled
    1191                 &&  pThis->svga.uHeight != VMSVGA_VAL_UNINITIALIZED)
    1192                 *pu32 = pThis->svga.uHeight;
    1193             else
    1194             {
    1195 #ifndef IN_RING3
    1196                 rc = VINF_IOM_R3_IOPORT_READ;
    1197 #else
    1198                 *pu32 = pThisCC->pDrv->cy;
    1199 #endif
    1200             }
    1201             break;
    1202         }
    1203 
    1204         case SVGA_REG_MAX_WIDTH:
    1205             STAM_REL_COUNTER_INC(&pThis->svga.StatRegMaxWidthRd);
    1206             *pu32 = pThis->svga.u32MaxWidth;
    1207             break;
    1208 
    1209         case SVGA_REG_MAX_HEIGHT:
    1210             STAM_REL_COUNTER_INC(&pThis->svga.StatRegMaxHeightRd);
    1211             *pu32 = pThis->svga.u32MaxHeight;
    1212             break;
    1213 
    1214         case SVGA_REG_DEPTH:
    1215             /* This returns the color depth of the current mode. */
    1216             STAM_REL_COUNTER_INC(&pThis->svga.StatRegDepthRd);
    1217             switch (pThis->svga.uBpp)
    1218             {
    1219                 case 15:
    1220                 case 16:
    1221                 case 24:
    1222                     *pu32 = pThis->svga.uBpp;
    1223                     break;
    1224 
    1225                 default:
    1226                 case 32:
    1227                     *pu32 = 24; /* The upper 8 bits are either alpha bits or not used. */
    1228                     break;
    1229             }
    1230             break;
    1231 
    1232         case SVGA_REG_HOST_BITS_PER_PIXEL: /* (Deprecated) */
    1233             STAM_REL_COUNTER_INC(&pThis->svga.StatRegHostBitsPerPixelRd);
    1234             *pu32 = pThis->svga.uHostBpp;
    1235             break;
    1236 
    1237         case SVGA_REG_BITS_PER_PIXEL:      /* Current bpp in the guest */
    1238             STAM_REL_COUNTER_INC(&pThis->svga.StatRegBitsPerPixelRd);
    1239             *pu32 = pThis->svga.uBpp;
    1240             break;
    1241 
    1242         case SVGA_REG_PSEUDOCOLOR:
    1243             STAM_REL_COUNTER_INC(&pThis->svga.StatRegPsuedoColorRd);
    1244             *pu32 = pThis->svga.uBpp == 8; /* See section 6 "Pseudocolor" in svga_interface.txt. */
    1245             break;
    1246 
    1247         case SVGA_REG_RED_MASK:
    1248         case SVGA_REG_GREEN_MASK:
    1249         case SVGA_REG_BLUE_MASK:
    1250         {
    1251             uint32_t uBpp;
    1252 
    1253             if (pThis->svga.fEnabled)
    1254                 uBpp = pThis->svga.uBpp;
    1255             else
    1256                 uBpp = pThis->svga.uHostBpp;
    1257 
    1258             uint32_t u32RedMask, u32GreenMask, u32BlueMask;
    1259             switch (uBpp)
    1260             {
    1261                 case 8:
    1262                     u32RedMask   = 0x07;
    1263                     u32GreenMask = 0x38;
    1264                     u32BlueMask  = 0xc0;
    1265                     break;
    1266 
    1267                 case 15:
    1268                     u32RedMask   = 0x0000001f;
    1269                     u32GreenMask = 0x000003e0;
    1270                     u32BlueMask  = 0x00007c00;
    1271                     break;
    1272 
    1273                 case 16:
    1274                     u32RedMask   = 0x0000001f;
    1275                     u32GreenMask = 0x000007e0;
    1276                     u32BlueMask  = 0x0000f800;
    1277                     break;
    1278 
    1279                 case 24:
    1280                 case 32:
    1281                 default:
    1282                     u32RedMask   = 0x00ff0000;
    1283                     u32GreenMask = 0x0000ff00;
    1284                     u32BlueMask  = 0x000000ff;
    1285                     break;
    1286             }
    1287             switch (idxReg)
    1288             {
    1289                 case SVGA_REG_RED_MASK:
    1290                     STAM_REL_COUNTER_INC(&pThis->svga.StatRegRedMaskRd);
    1291                     *pu32 = u32RedMask;
    1292                     break;
    1293 
    1294                 case SVGA_REG_GREEN_MASK:
    1295                     STAM_REL_COUNTER_INC(&pThis->svga.StatRegGreenMaskRd);
    1296                     *pu32 = u32GreenMask;
    1297                     break;
    1298 
    1299                 case SVGA_REG_BLUE_MASK:
    1300                     STAM_REL_COUNTER_INC(&pThis->svga.StatRegBlueMaskRd);
    1301                     *pu32 = u32BlueMask;
    1302                     break;
    1303             }
    1304             break;
    1305         }
    1306 
    1307         case SVGA_REG_BYTES_PER_LINE:
    1308         {
    1309             STAM_REL_COUNTER_INC(&pThis->svga.StatRegBytesPerLineRd);
    1310             if (    pThis->svga.fEnabled
    1311                 &&  pThis->svga.cbScanline)
    1312                 *pu32 = pThis->svga.cbScanline;
    1313             else
    1314             {
    1315 #ifndef IN_RING3
    1316                 rc = VINF_IOM_R3_IOPORT_READ;
    1317 #else
    1318                 *pu32 = pThisCC->pDrv->cbScanline;
    1319 #endif
    1320             }
    1321             break;
    1322         }
    1323 
    1324         case SVGA_REG_VRAM_SIZE:            /* VRAM size */
    1325             STAM_REL_COUNTER_INC(&pThis->svga.StatRegVramSizeRd);
    1326             *pu32 = pThis->vram_size;
    1327             break;
    1328 
    1329         case SVGA_REG_FB_START:             /* Frame buffer physical address. */
    1330             STAM_REL_COUNTER_INC(&pThis->svga.StatRegFbStartRd);
    1331             Assert(pThis->GCPhysVRAM <= 0xffffffff);
    1332             *pu32 = pThis->GCPhysVRAM;
    1333             break;
    1334 
    1335         case SVGA_REG_FB_OFFSET:            /* Offset of the frame buffer in VRAM */
    1336             STAM_REL_COUNTER_INC(&pThis->svga.StatRegFbOffsetRd);
    1337             /* Always zero in our case. */
    1338             *pu32 = 0;
    1339             break;
    1340 
    1341         case SVGA_REG_FB_SIZE:              /* Frame buffer size */
    1342         {
    1343 #ifndef IN_RING3
    1344             rc = VINF_IOM_R3_IOPORT_READ;
    1345 #else
    1346             STAM_REL_COUNTER_INC(&pThis->svga.StatRegFbSizeRd);
    1347 
    1348             /* VMWare testcases want at least 4 MB in case the hardware is disabled. */
    1349             if (    pThis->svga.fEnabled
    1350                 &&  pThis->svga.uHeight != VMSVGA_VAL_UNINITIALIZED)
    1351             {
    1352                 /* Hardware enabled; return real framebuffer size .*/
    1353                 *pu32 = (uint32_t)pThis->svga.uHeight * pThis->svga.cbScanline;
    1354             }
    1355             else
    1356                 *pu32 = RT_MAX(0x100000, (uint32_t)pThisCC->pDrv->cy * pThisCC->pDrv->cbScanline);
    1357 
    1358             *pu32 = RT_MIN(pThis->vram_size, *pu32);
    1359             Log(("h=%d w=%d bpp=%d\n", pThisCC->pDrv->cy, pThisCC->pDrv->cx, pThisCC->pDrv->cBits));
    1360 #endif
    1361             break;
    1362         }
    1363 
    1364         case SVGA_REG_CAPABILITIES:
    1365             STAM_REL_COUNTER_INC(&pThis->svga.StatRegCapabilitesRd);
    1366             *pu32 = pThis->svga.u32DeviceCaps;
    1367             break;
    1368 
    1369         case SVGA_REG_MEM_START:           /* FIFO start */
    1370             STAM_REL_COUNTER_INC(&pThis->svga.StatRegMemStartRd);
    1371             Assert(pThis->svga.GCPhysFIFO <= 0xffffffff);
    1372             *pu32 = pThis->svga.GCPhysFIFO;
    1373             break;
    1374 
    1375         case SVGA_REG_MEM_SIZE:            /* FIFO size */
    1376             STAM_REL_COUNTER_INC(&pThis->svga.StatRegMemSizeRd);
    1377             *pu32 = pThis->svga.cbFIFO;
    1378             break;
    1379 
    1380         case SVGA_REG_CONFIG_DONE:         /* Set when memory area configured */
    1381             STAM_REL_COUNTER_INC(&pThis->svga.StatRegConfigDoneRd);
    1382             *pu32 = pThis->svga.fConfigured;
    1383             break;
    1384 
    1385         case SVGA_REG_SYNC:                /* See "FIFO Synchronization Registers" */
    1386             STAM_REL_COUNTER_INC(&pThis->svga.StatRegSyncRd);
    1387             *pu32 = 0;
    1388             break;
    1389 
    1390         case SVGA_REG_BUSY:                /* See "FIFO Synchronization Registers" */
    1391             STAM_REL_COUNTER_INC(&pThis->svga.StatRegBusyRd);
    1392             if (pThis->svga.fBusy)
    1393             {
    1394 #ifndef IN_RING3
    1395                 /* Go to ring-3 and halt the CPU. */
    1396                 rc = VINF_IOM_R3_IOPORT_READ;
    1397                 RT_NOREF(pDevIns);
    1398                 break;
    1399 #else
    1400 # if defined(VMSVGA_USE_EMT_HALT_CODE)
    1401                 /* The guest is basically doing a HLT via the device here, but with
    1402                    a special wake up condition on FIFO completion. */
    1403                 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
    1404                 STAM_REL_PROFILE_START(&pSVGAState->StatBusyDelayEmts, EmtDelay);
    1405                 PVM         pVM   = PDMDevHlpGetVM(pDevIns);
    1406                 VMCPUID     idCpu = PDMDevHlpGetCurrentCpuId(pDevIns);
    1407                 VMCPUSET_ATOMIC_ADD(&pSVGAState->BusyDelayedEmts, idCpu);
    1408                 ASMAtomicIncU32(&pSVGAState->cBusyDelayedEmts);
    1409                 if (pThis->svga.fBusy)
    1410                 {
    1411                     PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect); /* hack around lock order issue. */
    1412                     rc = VMR3WaitForDeviceReady(pVM, idCpu);
    1413                     PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VERR_IGNORED);
    1414                 }
    1415                 ASMAtomicDecU32(&pSVGAState->cBusyDelayedEmts);
    1416                 VMCPUSET_ATOMIC_DEL(&pSVGAState->BusyDelayedEmts, idCpu);
    1417 # else
    1418 
    1419                 /* Delay the EMT a bit so the FIFO and others can get some work done.
    1420                    This used to be a crude 50 ms sleep. The current code tries to be
    1421                    more efficient, but the consept is still very crude. */
    1422                 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
    1423                 STAM_REL_PROFILE_START(&pSVGAState->StatBusyDelayEmts, EmtDelay);
    1424                 RTThreadYield();
    1425                 if (pThis->svga.fBusy)
    1426                 {
    1427                     uint32_t cRefs = ASMAtomicIncU32(&pSVGAState->cBusyDelayedEmts);
    1428 
    1429                     if (pThis->svga.fBusy && cRefs == 1)
    1430                         RTSemEventMultiReset(pSVGAState->hBusyDelayedEmts);
    1431                     if (pThis->svga.fBusy)
    1432                     {
    1433                         /** @todo If this code is going to stay, we need to call into the halt/wait
    1434                          *        code in VMEmt.cpp here, otherwise all kind of EMT interaction will
    1435                          *        suffer when the guest is polling on a busy FIFO. */
    1436                         uint64_t cNsMaxWait = TMVirtualSyncGetNsToDeadline(PDMDevHlpGetVM(pDevIns));
    1437                         if (cNsMaxWait >= RT_NS_100US)
    1438                             RTSemEventMultiWaitEx(pSVGAState->hBusyDelayedEmts,
    1439                                                   RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_NORESUME,
    1440                                                   RT_MIN(cNsMaxWait, RT_NS_10MS));
    1441                     }
    1442 
    1443                     ASMAtomicDecU32(&pSVGAState->cBusyDelayedEmts);
    1444                 }
    1445                 STAM_REL_PROFILE_STOP(&pSVGAState->StatBusyDelayEmts, EmtDelay);
    1446 # endif
    1447                 *pu32 = pThis->svga.fBusy != 0;
    1448 #endif
    1449             }
    1450             else
    1451                 *pu32 = false;
    1452             break;
    1453 
    1454         case SVGA_REG_GUEST_ID:            /* Set guest OS identifier */
    1455             STAM_REL_COUNTER_INC(&pThis->svga.StatRegGuestIdRd);
    1456             *pu32 = pThis->svga.u32GuestId;
    1457             break;
    1458 
    1459         case SVGA_REG_SCRATCH_SIZE:        /* Number of scratch registers */
    1460             STAM_REL_COUNTER_INC(&pThis->svga.StatRegScratchSizeRd);
    1461             *pu32 = pThis->svga.cScratchRegion;
    1462             break;
    1463 
    1464         case SVGA_REG_MEM_REGS:            /* Number of FIFO registers */
    1465             STAM_REL_COUNTER_INC(&pThis->svga.StatRegMemRegsRd);
    1466             *pu32 = SVGA_FIFO_NUM_REGS;
    1467             break;
    1468 
    1469         case SVGA_REG_PITCHLOCK:           /* Fixed pitch for all modes */
    1470             STAM_REL_COUNTER_INC(&pThis->svga.StatRegPitchLockRd);
    1471             *pu32 = pThis->svga.u32PitchLock;
    1472             break;
    1473 
    1474         case SVGA_REG_IRQMASK:             /* Interrupt mask */
    1475             STAM_REL_COUNTER_INC(&pThis->svga.StatRegIrqMaskRd);
    1476             *pu32 = pThis->svga.u32IrqMask;
    1477             break;
    1478 
    1479         /* See "Guest memory regions" below. */
    1480         case SVGA_REG_GMR_ID:
    1481             STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrIdRd);
    1482             *pu32 = pThis->svga.u32CurrentGMRId;
    1483             break;
    1484 
    1485         case SVGA_REG_GMR_DESCRIPTOR:
    1486             STAM_REL_COUNTER_INC(&pThis->svga.StatRegWriteOnlyRd);
    1487             /* Write only */
    1488             *pu32 = 0;
    1489             break;
    1490 
    1491         case SVGA_REG_GMR_MAX_IDS:
    1492             STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrMaxIdsRd);
    1493             *pu32 = pThis->svga.cGMR;
    1494             break;
    1495 
    1496         case SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH:
    1497             STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrMaxDescriptorLengthRd);
    1498             *pu32 = VMSVGA_MAX_GMR_PAGES;
    1499             break;
    1500 
    1501         case SVGA_REG_TRACES:            /* Enable trace-based updates even when FIFO is on */
    1502             STAM_REL_COUNTER_INC(&pThis->svga.StatRegTracesRd);
    1503             *pu32 = pThis->svga.fTraces;
    1504             break;
    1505 
    1506         case SVGA_REG_GMRS_MAX_PAGES:    /* Maximum number of 4KB pages for all GMRs */
    1507             STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrsMaxPagesRd);
    1508             *pu32 = VMSVGA_MAX_GMR_PAGES;
    1509             break;
    1510 
    1511         case SVGA_REG_MEMORY_SIZE:       /* Total dedicated device memory excluding FIFO */
    1512             STAM_REL_COUNTER_INC(&pThis->svga.StatRegMemorySizeRd);
    1513             *pu32 = VMSVGA_SURFACE_SIZE;
    1514             break;
    1515 
    1516         case SVGA_REG_TOP:               /* Must be 1 more than the last register */
    1517             STAM_REL_COUNTER_INC(&pThis->svga.StatRegTopRd);
    1518             break;
    1519 
    1520         /* Mouse cursor support. */
    1521         case SVGA_REG_CURSOR_ID:
    1522             STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorIdRd);
    1523             *pu32 = pThis->svga.uCursorID;
    1524             break;
    1525 
    1526         case SVGA_REG_CURSOR_X:
    1527             STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorXRd);
    1528             *pu32 = pThis->svga.uCursorX;
    1529             break;
    1530 
    1531         case SVGA_REG_CURSOR_Y:
    1532             STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorYRd);
    1533             *pu32 = pThis->svga.uCursorY;
    1534             break;
    1535 
    1536         case SVGA_REG_CURSOR_ON:
    1537             STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorOnRd);
    1538             *pu32 = pThis->svga.uCursorOn;
    1539             break;
    1540 
    1541         /* Legacy multi-monitor support */
    1542         case SVGA_REG_NUM_GUEST_DISPLAYS:/* Number of guest displays in X/Y direction */
    1543             STAM_REL_COUNTER_INC(&pThis->svga.StatRegNumGuestDisplaysRd);
    1544             *pu32 = 1;
    1545             break;
    1546 
    1547         case SVGA_REG_DISPLAY_ID:        /* Display ID for the following display attributes */
    1548             STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayIdRd);
    1549             *pu32 = 0;
    1550             break;
    1551 
    1552         case SVGA_REG_DISPLAY_IS_PRIMARY:/* Whether this is a primary display */
    1553             STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayIsPrimaryRd);
    1554             *pu32 = 0;
    1555             break;
    1556 
    1557         case SVGA_REG_DISPLAY_POSITION_X:/* The display position x */
    1558             STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayPositionXRd);
    1559             *pu32 = 0;
    1560             break;
    1561 
    1562         case SVGA_REG_DISPLAY_POSITION_Y:/* The display position y */
    1563             STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayPositionYRd);
    1564             *pu32 = 0;
    1565             break;
    1566 
    1567         case SVGA_REG_DISPLAY_WIDTH:     /* The display's width */
    1568             STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayWidthRd);
    1569             *pu32 = pThis->svga.uWidth;
    1570             break;
    1571 
    1572         case SVGA_REG_DISPLAY_HEIGHT:    /* The display's height */
    1573             STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayHeightRd);
    1574             *pu32 = pThis->svga.uHeight;
    1575             break;
    1576 
    1577         case SVGA_REG_NUM_DISPLAYS:        /* (Deprecated) */
    1578             STAM_REL_COUNTER_INC(&pThis->svga.StatRegNumDisplaysRd);
    1579             /* We must return something sensible here otherwise the Linux driver
    1580                will take a legacy code path without 3d support.  This number also
    1581                limits how many screens Linux guests will allow. */
    1582             *pu32 = pThis->cMonitors;
    1583             break;
    1584 
    1585         /*
    1586          * SVGA_CAP_GBOBJECTS+ registers.
    1587          */
    1588         case SVGA_REG_COMMAND_LOW:
    1589             /* Lower 32 bits of command buffer physical address. */
    1590             STAM_REL_COUNTER_INC(&pThis->svga.StatRegCommandLowRd);
    1591             *pu32 = pThis->svga.u32RegCommandLow;
    1592             break;
    1593 
    1594         case SVGA_REG_COMMAND_HIGH:
    1595             /* Upper 32 bits of command buffer PA. */
    1596             STAM_REL_COUNTER_INC(&pThis->svga.StatRegCommandHighRd);
    1597             *pu32 = pThis->svga.u32RegCommandHigh;
    1598             break;
    1599 
    1600         case SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM:
    1601             /* Max primary (screen) memory. */
    1602             STAM_REL_COUNTER_INC(&pThis->svga.StatRegMaxPrimBBMemRd);
    1603             *pu32 = pThis->vram_size; /** @todo Maybe half VRAM? */
    1604             break;
    1605 
    1606         case SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB:
    1607             /* Suggested limit on mob mem (i.e. size of the guest mapped VRAM in KB) */
    1608             STAM_REL_COUNTER_INC(&pThis->svga.StatRegGBMemSizeRd);
    1609             *pu32 = pThis->vram_size / 1024;
    1610             break;
    1611 
    1612         case SVGA_REG_DEV_CAP:
    1613             /* Write dev cap index, read value */
    1614             STAM_REL_COUNTER_INC(&pThis->svga.StatRegDevCapRd);
    1615             if (pThis->svga.u32DevCapIndex < RT_ELEMENTS(pThis->svga.au32DevCaps))
    1616             {
    1617                 RT_UNTRUSTED_VALIDATED_FENCE();
    1618                 *pu32 = pThis->svga.au32DevCaps[pThis->svga.u32DevCapIndex];
    1619             }
    1620             else
    1621                 *pu32 = 0;
    1622             break;
    1623 
    1624         case SVGA_REG_CMD_PREPEND_LOW:
    1625             STAM_REL_COUNTER_INC(&pThis->svga.StatRegCmdPrependLowRd);
    1626             *pu32 = 0; /* Not supported. */
    1627             break;
    1628 
    1629         case SVGA_REG_iCMD_PREPEND_HIGH:
    1630             STAM_REL_COUNTER_INC(&pThis->svga.StatRegCmdPrependHighRd);
    1631             *pu32 = 0; /* Not supported. */
    1632             break;
    1633 
    1634         case SVGA_REG_SCREENTARGET_MAX_WIDTH:
    1635             STAM_REL_COUNTER_INC(&pThis->svga.StatRegScrnTgtMaxWidthRd);
    1636             *pu32 = pThis->svga.u32MaxWidth;
    1637             break;
    1638 
    1639         case SVGA_REG_SCREENTARGET_MAX_HEIGHT:
    1640             STAM_REL_COUNTER_INC(&pThis->svga.StatRegScrnTgtMaxHeightRd);
    1641             *pu32 = pThis->svga.u32MaxHeight;
    1642             break;
    1643 
    1644         case SVGA_REG_MOB_MAX_SIZE:
    1645             /* Essentially the max texture size */
    1646             STAM_REL_COUNTER_INC(&pThis->svga.StatRegMobMaxSizeRd);
    1647             *pu32 = _128M; /** @todo Some actual value. Probably the mapped VRAM size. */
    1648             break;
    1649 
    1650         default:
    1651         {
    1652             uint32_t offReg;
    1653             if ((offReg = idxReg - SVGA_SCRATCH_BASE) < pThis->svga.cScratchRegion)
    1654             {
    1655                 STAM_REL_COUNTER_INC(&pThis->svga.StatRegScratchRd);
    1656                 RT_UNTRUSTED_VALIDATED_FENCE();
    1657                 *pu32 = pThis->svga.au32ScratchRegion[offReg];
    1658             }
    1659             else if ((offReg = idxReg - SVGA_PALETTE_BASE) < (uint32_t)SVGA_NUM_PALETTE_REGS)
    1660             {
    1661                 /* Note! Using last_palette rather than palette here to preserve the VGA one. */
    1662                 STAM_REL_COUNTER_INC(&pThis->svga.StatRegPaletteRd);
    1663                 RT_UNTRUSTED_VALIDATED_FENCE();
    1664                 uint32_t u32 = pThis->last_palette[offReg / 3];
    1665                 switch (offReg % 3)
    1666                 {
    1667                     case 0: *pu32 = (u32 >> 16) & 0xff; break; /* red */
    1668                     case 1: *pu32 = (u32 >>  8) & 0xff; break; /* green */
    1669                     case 2: *pu32 =  u32        & 0xff; break; /* blue */
    1670                 }
    1671             }
    1672             else
    1673             {
    1674 #if !defined(IN_RING3) && defined(VBOX_STRICT)
    1675                 rc = VINF_IOM_R3_IOPORT_READ;
    1676 #else
    1677                 STAM_REL_COUNTER_INC(&pThis->svga.StatRegUnknownRd);
    1678 
    1679                 /* Do not assert. The guest might be reading all registers. */
    1680                 LogFunc(("Unknown reg=%#x\n", idxReg));
    1681 #endif
    1682             }
    1683             break;
    1684         }
    1685     }
    1686     Log(("vmsvgaReadPort index=%s (%d) val=%#x rc=%x\n", vmsvgaIndexToString(pThis, idxReg), idxReg, *pu32, rc));
    1687     return rc;
    1688 }
    1689 
    1690 #ifdef IN_RING3
    1691 /**
    1692  * Apply the current resolution settings to change the video mode.
    1693  *
    1694  * @returns VBox status code.
    1695  * @param   pThis       The shared VGA state.
    1696  * @param   pThisCC     The ring-3 VGA state.
    1697  */
    1698 static int vmsvgaR3ChangeMode(PVGASTATE pThis, PVGASTATECC pThisCC)
    1699 {
    1700     /* Always do changemode on FIFO thread. */
    1701     Assert(RTThreadSelf() == pThisCC->svga.pFIFOIOThread->Thread);
    1702 
    1703     PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
    1704 
    1705     pThisCC->pDrv->pfnLFBModeChange(pThisCC->pDrv, true);
    1706 
    1707     if (pThis->svga.fGFBRegisters)
    1708     {
    1709         /* "For backwards compatibility, when the GFB mode registers (WIDTH,
    1710          * HEIGHT, PITCHLOCK, BITS_PER_PIXEL) are modified, the SVGA device
    1711          * deletes all screens other than screen #0, and redefines screen
    1712          * #0 according to the specified mode. Drivers that use
    1713          * SVGA_CMD_DEFINE_SCREEN should destroy or redefine screen #0."
    1714          */
    1715 
    1716         VMSVGASCREENOBJECT *pScreen = &pSVGAState->aScreens[0];
    1717         pScreen->fDefined  = true;
    1718         pScreen->fModified = true;
    1719         pScreen->fuScreen  = SVGA_SCREEN_MUST_BE_SET | SVGA_SCREEN_IS_PRIMARY;
    1720         pScreen->idScreen  = 0;
    1721         pScreen->xOrigin   = 0;
    1722         pScreen->yOrigin   = 0;
    1723         pScreen->offVRAM   = 0;
    1724         pScreen->cbPitch   = pThis->svga.cbScanline;
    1725         pScreen->cWidth    = pThis->svga.uWidth;
    1726         pScreen->cHeight   = pThis->svga.uHeight;
    1727         pScreen->cBpp      = pThis->svga.uBpp;
    1728 
    1729         for (unsigned iScreen = 1; iScreen < RT_ELEMENTS(pSVGAState->aScreens); ++iScreen)
    1730         {
    1731             /* Delete screen. */
    1732             pScreen = &pSVGAState->aScreens[iScreen];
    1733             if (pScreen->fDefined)
    1734             {
    1735                 pScreen->fModified = true;
    1736                 pScreen->fDefined = false;
    1737             }
    1738         }
    1739     }
    1740     else
    1741     {
    1742         /* "If Screen Objects are supported, they can be used to fully
    1743          * replace the functionality provided by the framebuffer registers
    1744          * (SVGA_REG_WIDTH, HEIGHT, etc.) and by SVGA_CAP_DISPLAY_TOPOLOGY."
    1745          */
    1746         pThis->svga.uWidth  = VMSVGA_VAL_UNINITIALIZED;
    1747         pThis->svga.uHeight = VMSVGA_VAL_UNINITIALIZED;
    1748         pThis->svga.uBpp    = pThis->svga.uHostBpp;
    1749     }
    1750 
    1751     vmsvgaR3VBVAResize(pThis, pThisCC);
    1752 
    1753     /* Last stuff. For the VGA device screenshot. */
    1754     pThis->last_bpp        = pSVGAState->aScreens[0].cBpp;
    1755     pThis->last_scr_width  = pSVGAState->aScreens[0].cWidth;
    1756     pThis->last_scr_height = pSVGAState->aScreens[0].cHeight;
    1757     pThis->last_width      = pSVGAState->aScreens[0].cWidth;
    1758     pThis->last_height     = pSVGAState->aScreens[0].cHeight;
    1759 
    1760     /* vmsvgaPortSetViewPort not called after state load; set sensible defaults. */
    1761     if (    pThis->svga.viewport.cx == 0
    1762         &&  pThis->svga.viewport.cy == 0)
    1763     {
    1764         pThis->svga.viewport.cx      = pSVGAState->aScreens[0].cWidth;
    1765         pThis->svga.viewport.xRight  = pSVGAState->aScreens[0].cWidth;
    1766         pThis->svga.viewport.cy      = pSVGAState->aScreens[0].cHeight;
    1767         pThis->svga.viewport.yHighWC = pSVGAState->aScreens[0].cHeight;
    1768         pThis->svga.viewport.yLowWC  = 0;
    1769     }
    1770 
    1771     return VINF_SUCCESS;
    1772 }
    1773 
    1774 int vmsvgaR3UpdateScreen(PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen, int x, int y, int w, int h)
    1775 {
    1776     VBVACMDHDR cmd;
    1777     cmd.x = (int16_t)(pScreen->xOrigin + x);
    1778     cmd.y = (int16_t)(pScreen->yOrigin + y);
    1779     cmd.w = (uint16_t)w;
    1780     cmd.h = (uint16_t)h;
    1781 
    1782     pThisCC->pDrv->pfnVBVAUpdateBegin(pThisCC->pDrv, pScreen->idScreen);
    1783     pThisCC->pDrv->pfnVBVAUpdateProcess(pThisCC->pDrv, pScreen->idScreen, &cmd, sizeof(cmd));
    1784     pThisCC->pDrv->pfnVBVAUpdateEnd(pThisCC->pDrv, pScreen->idScreen,
    1785                                     pScreen->xOrigin + x, pScreen->yOrigin + y, w, h);
    1786 
    1787     return VINF_SUCCESS;
    1788 }
    1789 
    1790 #endif /* IN_RING3 */
    1791 #if defined(IN_RING0) || defined(IN_RING3)
    1792 
    1793 /**
    1794  * Safely updates the SVGA_FIFO_BUSY register (in shared memory).
    1795  *
    1796  * @param   pThis       The shared VGA/VMSVGA instance data.
    1797  * @param   pThisCC     The VGA/VMSVGA state for the current context.
    1798  * @param   fState      The busy state.
    1799  */
    1800 DECLINLINE(void) vmsvgaHCSafeFifoBusyRegUpdate(PVGASTATE pThis, PVGASTATECC pThisCC, bool fState)
    1801 {
    1802     ASMAtomicWriteU32(&pThisCC->svga.pau32FIFO[SVGA_FIFO_BUSY], fState);
    1803 
    1804     if (RT_UNLIKELY(fState != (pThis->svga.fBusy != 0)))
    1805     {
    1806         /* Race / unfortunately scheduling. Highly unlikly. */
    1807         uint32_t cLoops = 64;
    1808         do
    1809         {
    1810             ASMNopPause();
    1811             fState = (pThis->svga.fBusy != 0);
    1812             ASMAtomicWriteU32(&pThisCC->svga.pau32FIFO[SVGA_FIFO_BUSY], fState != 0);
    1813         } while (cLoops-- > 0 && fState != (pThis->svga.fBusy != 0));
    1814     }
    1815 }
    1816 
    1817 
    1818 /**
    1819  * Update the scanline pitch in response to the guest changing mode
    1820  * width/bpp.
    1821  *
    1822  * @param   pThis       The shared VGA/VMSVGA state.
    1823  * @param   pThisCC     The VGA/VMSVGA state for the current context.
    1824  */
    1825 DECLINLINE(void) vmsvgaHCUpdatePitch(PVGASTATE pThis, PVGASTATECC pThisCC)
    1826 {
    1827     uint32_t RT_UNTRUSTED_VOLATILE_GUEST *pFIFO = pThisCC->svga.pau32FIFO;
    1828     uint32_t uFifoPitchLock = pFIFO[SVGA_FIFO_PITCHLOCK];
    1829     uint32_t uRegPitchLock  = pThis->svga.u32PitchLock;
    1830     uint32_t uFifoMin       = pFIFO[SVGA_FIFO_MIN];
    1831 
    1832     /* The SVGA_FIFO_PITCHLOCK register is only valid if SVGA_FIFO_MIN points past
    1833      * it. If SVGA_FIFO_MIN is small, there may well be data at the SVGA_FIFO_PITCHLOCK
    1834      * location but it has a different meaning.
    1835      */
    1836     if ((uFifoMin / sizeof(uint32_t)) <= SVGA_FIFO_PITCHLOCK)
    1837         uFifoPitchLock = 0;
    1838 
    1839     /* Sanitize values. */
    1840     if ((uFifoPitchLock < 200) || (uFifoPitchLock > 32768))
    1841         uFifoPitchLock = 0;
    1842     if ((uRegPitchLock  < 200) || (uRegPitchLock  > 32768))
    1843         uRegPitchLock = 0;
    1844 
    1845     /* Prefer the register value to the FIFO value.*/
    1846     if (uRegPitchLock)
    1847         pThis->svga.cbScanline = uRegPitchLock;
    1848     else if (uFifoPitchLock)
    1849         pThis->svga.cbScanline = uFifoPitchLock;
    1850     else
    1851         pThis->svga.cbScanline = pThis->svga.uWidth * (RT_ALIGN(pThis->svga.uBpp, 8) / 8);
    1852 
    1853     if ((uFifoMin / sizeof(uint32_t)) <= SVGA_FIFO_PITCHLOCK)
    1854         pThis->svga.u32PitchLock = pThis->svga.cbScanline;
    1855 }
    1856 
    1857 #endif /* IN_RING0 || IN_RING3 */
    1858 
    1859 #ifdef IN_RING3
    1860 
    1861 /**
    1862  * Sends cursor position and visibility information from legacy
    1863  * SVGA registers to the front-end.
    1864  */
    1865 static void vmsvgaR3RegUpdateCursor(PVGASTATECC pThisCC, PVGASTATE pThis, uint32_t uCursorOn)
    1866 {
    1867     /*
    1868      * Writing the X/Y/ID registers does not trigger changes; only writing the
    1869      * SVGA_REG_CURSOR_ON register does. That minimizes the overhead.
    1870      * We boldly assume that guests aren't stupid and aren't writing the CURSOR_ON
    1871      * register if they don't have to.
    1872      */
    1873     uint32_t x, y, idScreen;
    1874     uint32_t fFlags = VBVA_CURSOR_VALID_DATA;
    1875 
    1876     x = pThis->svga.uCursorX;
    1877     y = pThis->svga.uCursorY;
    1878     idScreen = SVGA_ID_INVALID; /* The old register interface is single screen only. */
    1879 
    1880     /* The original values for SVGA_REG_CURSOR_ON were off (0) and on (1); later, the values
    1881      * were extended as follows:
    1882      *
    1883      *   SVGA_CURSOR_ON_HIDE               0
    1884      *   SVGA_CURSOR_ON_SHOW               1
    1885      *   SVGA_CURSOR_ON_REMOVE_FROM_FB     2 - cursor on but not in the framebuffer
    1886      *   SVGA_CURSOR_ON_RESTORE_TO_FB      3 - cursor on, possibly in the framebuffer
    1887      *
    1888      * Since we never draw the cursor into the guest's framebuffer, we do not need to
    1889      * distinguish between the non-zero values but still remember them.
    1890      */
    1891     if (RT_BOOL(pThis->svga.uCursorOn) != RT_BOOL(uCursorOn))
    1892     {
    1893         LogRel2(("vmsvgaR3RegUpdateCursor: uCursorOn %d prev CursorOn %d (%d,%d)\n", uCursorOn, pThis->svga.uCursorOn, x, y));
    1894         pThisCC->pDrv->pfnVBVAMousePointerShape(pThisCC->pDrv, RT_BOOL(uCursorOn), false, 0, 0, 0, 0, NULL);
    1895     }
    1896     pThis->svga.uCursorOn = uCursorOn;
    1897     pThisCC->pDrv->pfnVBVAReportCursorPosition(pThisCC->pDrv, fFlags, idScreen, x, y);
    1898 }
    1899 
    1900 
    1901 /**
    1902  * Copy a rectangle of pixels within guest VRAM.
    1903  */
    1904 static void vmsvgaR3RectCopy(PVGASTATECC pThisCC, VMSVGASCREENOBJECT const *pScreen, uint32_t srcX, uint32_t srcY,
    1905                              uint32_t dstX, uint32_t dstY, uint32_t width, uint32_t height, unsigned cbFrameBuffer)
    1906 {
    1907     if (!width || !height)
    1908         return; /* Nothing to do, don't even bother. */
    1909 
    1910     /*
    1911      * The guest VRAM (aka GFB) is considered to be a bitmap in the format
    1912      * corresponding to the current display mode.
    1913      */
    1914     uint32_t const  cbPixel = RT_ALIGN(pScreen->cBpp, 8) / 8;
    1915     uint32_t const  cbScanline = pScreen->cbPitch ? pScreen->cbPitch : width * cbPixel;
    1916     uint8_t const   *pSrc;
    1917     uint8_t         *pDst;
    1918     unsigned const  cbRectWidth = width * cbPixel;
    1919     unsigned        uMaxOffset;
    1920 
    1921     uMaxOffset = (RT_MAX(srcY, dstY) + height) * cbScanline + (RT_MAX(srcX, dstX) + width) * cbPixel;
    1922     if (uMaxOffset >= cbFrameBuffer)
    1923     {
    1924         Log(("Max offset (%u) too big for framebuffer (%u bytes), ignoring!\n", uMaxOffset, cbFrameBuffer));
    1925         return; /* Just don't listen to a bad guest. */
    1926     }
    1927 
    1928     pSrc = pDst = pThisCC->pbVRam;
    1929     pSrc += srcY * cbScanline + srcX * cbPixel;
    1930     pDst += dstY * cbScanline + dstX * cbPixel;
    1931 
    1932     if (srcY >= dstY)
    1933     {
    1934         /* Source below destination, copy top to bottom. */
    1935         for (; height > 0; height--)
    1936         {
    1937             memmove(pDst, pSrc, cbRectWidth);
    1938             pSrc += cbScanline;
    1939             pDst += cbScanline;
    1940         }
    1941     }
    1942     else
    1943     {
    1944         /* Source above destination, copy bottom to top. */
    1945         pSrc += cbScanline * (height - 1);
    1946         pDst += cbScanline * (height - 1);
    1947         for (; height > 0; height--)
    1948         {
    1949             memmove(pDst, pSrc, cbRectWidth);
    1950             pSrc -= cbScanline;
    1951             pDst -= cbScanline;
    1952         }
    1953     }
    1954 }
    1955 
    1956 #endif /* IN_RING3 */
    1957 
    1958 
    1959 /**
    1960  * Write port register
    1961  *
    1962  * @returns Strict VBox status code.
    1963  * @param   pDevIns     The device instance.
    1964  * @param   pThis       The shared VGA/VMSVGA state.
    1965  * @param   pThisCC     The VGA/VMSVGA state for the current context.
    1966  * @param   u32         Value to write
    1967  */
    1968 static VBOXSTRICTRC vmsvgaWritePort(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, uint32_t u32)
    1969 {
    1970 #ifdef IN_RING3
    1971     PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
    1972 #endif
    1973     VBOXSTRICTRC rc = VINF_SUCCESS;
    1974     RT_NOREF(pThisCC);
    1975 
    1976     /* Rough index register validation. */
    1977     uint32_t idxReg = pThis->svga.u32IndexReg;
    1978 #if !defined(IN_RING3) && defined(VBOX_STRICT)
    1979     ASSERT_GUEST_MSG_RETURN(idxReg < SVGA_SCRATCH_BASE + pThis->svga.cScratchRegion, ("idxReg=%#x\n", idxReg),
    1980                             VINF_IOM_R3_IOPORT_WRITE);
    1981 #else
    1982     ASSERT_GUEST_MSG_STMT_RETURN(idxReg < SVGA_SCRATCH_BASE + pThis->svga.cScratchRegion, ("idxReg=%#x\n", idxReg),
    1983                                  STAM_REL_COUNTER_INC(&pThis->svga.StatRegUnknownWr),
    1984                                  VINF_SUCCESS);
    1985 #endif
    1986     RT_UNTRUSTED_VALIDATED_FENCE();
    1987 
    1988     /* We must adjust the register number if we're in SVGA_ID_0 mode because the PALETTE range moved. */
    1989     if (   idxReg >= SVGA_REG_ID_0_TOP
    1990         && pThis->svga.u32SVGAId == SVGA_ID_0)
    1991     {
    1992         idxReg += SVGA_PALETTE_BASE - SVGA_REG_ID_0_TOP;
    1993         Log(("vmsvgaWritePort: SVGA_ID_0 reg adj %#x -> %#x\n", pThis->svga.u32IndexReg, idxReg));
    1994     }
    1995     Log(("vmsvgaWritePort index=%s (%d) val=%#x\n", vmsvgaIndexToString(pThis, idxReg), idxReg, u32));
    1996     /* Check if the guest uses legacy registers. See vmsvgaR3ChangeMode */
    1997     switch (idxReg)
    1998     {
    1999         case SVGA_REG_WIDTH:
    2000         case SVGA_REG_HEIGHT:
    2001         case SVGA_REG_PITCHLOCK:
    2002         case SVGA_REG_BITS_PER_PIXEL:
    2003             pThis->svga.fGFBRegisters = true;
    2004             break;
    2005         default:
    2006             break;
    2007     }
    2008 
    2009     switch (idxReg)
    2010     {
    2011         case SVGA_REG_ID:
    2012             STAM_REL_COUNTER_INC(&pThis->svga.StatRegIdWr);
    2013             if (   u32 == SVGA_ID_0
    2014                 || u32 == SVGA_ID_1
    2015                 || u32 == SVGA_ID_2)
    2016                 pThis->svga.u32SVGAId = u32;
    2017             else
    2018                 PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "Trying to set SVGA_REG_ID to %#x (%d)\n", u32, u32);
    2019             break;
    2020 
    2021         case SVGA_REG_ENABLE:
    2022             STAM_REL_COUNTER_INC(&pThis->svga.StatRegEnableWr);
    2023 #ifdef IN_RING3
    2024             if (    (u32 & SVGA_REG_ENABLE_ENABLE)
    2025                 &&  pThis->svga.fEnabled == false)
    2026             {
    2027                 /* Make a backup copy of the first 512kb in order to save font data etc. */
    2028                 /** @todo should probably swap here, rather than copy + zero */
    2029                 memcpy(pThisCC->svga.pbVgaFrameBufferR3, pThisCC->pbVRam, VMSVGA_VGA_FB_BACKUP_SIZE);
    2030                 memset(pThisCC->pbVRam, 0, VMSVGA_VGA_FB_BACKUP_SIZE);
    2031             }
    2032 
    2033             pThis->svga.fEnabled = u32;
    2034             if (pThis->svga.fEnabled)
    2035             {
    2036                 if (    pThis->svga.uWidth  == VMSVGA_VAL_UNINITIALIZED
    2037                     &&  pThis->svga.uHeight == VMSVGA_VAL_UNINITIALIZED)
    2038                 {
    2039                     /* Keep the current mode. */
    2040                     pThis->svga.uWidth  = pThisCC->pDrv->cx;
    2041                     pThis->svga.uHeight = pThisCC->pDrv->cy;
    2042                     pThis->svga.uBpp    = (pThisCC->pDrv->cBits + 7) & ~7;
    2043                 }
    2044 
    2045                 if (    pThis->svga.uWidth  != VMSVGA_VAL_UNINITIALIZED
    2046                     &&  pThis->svga.uHeight != VMSVGA_VAL_UNINITIALIZED)
    2047                     ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE);
    2048 # ifdef LOG_ENABLED
    2049                 uint32_t *pFIFO = pThisCC->svga.pau32FIFO;
    2050                 Log(("configured=%d busy=%d\n", pThis->svga.fConfigured, pFIFO[SVGA_FIFO_BUSY]));
    2051                 Log(("next %x stop %x\n", pFIFO[SVGA_FIFO_NEXT_CMD], pFIFO[SVGA_FIFO_STOP]));
    2052 # endif
    2053 
    2054                 /* Disable or enable dirty page tracking according to the current fTraces value. */
    2055                 vmsvgaR3SetTraces(pDevIns, pThis, !!pThis->svga.fTraces);
    2056 
    2057                 /* bird: Whatever this is was added to make screenshot work, ask sunlover should explain... */
    2058                 for (uint32_t idScreen = 0; idScreen < pThis->cMonitors; ++idScreen)
    2059                     pThisCC->pDrv->pfnVBVAEnable(pThisCC->pDrv, idScreen, NULL /*pHostFlags*/);
    2060 
    2061                 /* Make the cursor visible again as needed. */
    2062                 if (pSVGAState->Cursor.fActive)
    2063                     pThisCC->pDrv->pfnVBVAMousePointerShape(pThisCC->pDrv, true /*fVisible*/, false, 0, 0, 0, 0, NULL);
    2064             }
    2065             else
    2066             {
    2067                 /* Make sure the cursor is off. */
    2068                 if (pSVGAState->Cursor.fActive)
    2069                     pThisCC->pDrv->pfnVBVAMousePointerShape(pThisCC->pDrv, false /*fVisible*/, false, 0, 0, 0, 0, NULL);
    2070 
    2071                 /* Restore the text mode backup. */
    2072                 memcpy(pThisCC->pbVRam, pThisCC->svga.pbVgaFrameBufferR3, VMSVGA_VGA_FB_BACKUP_SIZE);
    2073 
    2074                 pThisCC->pDrv->pfnLFBModeChange(pThisCC->pDrv, false);
    2075 
    2076                 /* Enable dirty page tracking again when going into legacy mode. */
    2077                 vmsvgaR3SetTraces(pDevIns, pThis, true);
    2078 
    2079                 /* bird: Whatever this is was added to make screenshot work, ask sunlover should explain... */
    2080                 for (uint32_t idScreen = 0; idScreen < pThis->cMonitors; ++idScreen)
    2081                     pThisCC->pDrv->pfnVBVADisable(pThisCC->pDrv, idScreen);
    2082 
    2083                 /* Clear the pitch lock. */
    2084                 pThis->svga.u32PitchLock = 0;
    2085             }
    2086 #else  /* !IN_RING3 */
    2087             rc = VINF_IOM_R3_IOPORT_WRITE;
    2088 #endif /* !IN_RING3 */
    2089             break;
    2090 
    2091         case SVGA_REG_WIDTH:
    2092             STAM_REL_COUNTER_INC(&pThis->svga.StatRegWidthWr);
    2093             if (pThis->svga.uWidth != u32)
    2094             {
    2095 #if defined(IN_RING3) || defined(IN_RING0)
    2096                 pThis->svga.uWidth = u32;
    2097                 vmsvgaHCUpdatePitch(pThis, pThisCC);
    2098                 if (pThis->svga.fEnabled)
    2099                     ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE);
    2100 #else
    2101                 rc = VINF_IOM_R3_IOPORT_WRITE;
    2102 #endif
    2103             }
    2104             /* else: nop */
    2105             break;
    2106 
    2107         case SVGA_REG_HEIGHT:
    2108             STAM_REL_COUNTER_INC(&pThis->svga.StatRegHeightWr);
    2109             if (pThis->svga.uHeight != u32)
    2110             {
    2111                 pThis->svga.uHeight = u32;
    2112                 if (pThis->svga.fEnabled)
    2113                     ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE);
    2114             }
    2115             /* else: nop */
    2116             break;
    2117 
    2118         case SVGA_REG_DEPTH:
    2119             STAM_REL_COUNTER_INC(&pThis->svga.StatRegDepthWr);
    2120             /** @todo read-only?? */
    2121             break;
    2122 
    2123         case SVGA_REG_BITS_PER_PIXEL:      /* Current bpp in the guest */
    2124             STAM_REL_COUNTER_INC(&pThis->svga.StatRegBitsPerPixelWr);
    2125             if (pThis->svga.uBpp != u32)
    2126             {
    2127 #if defined(IN_RING3) || defined(IN_RING0)
    2128                 pThis->svga.uBpp = u32;
    2129                 vmsvgaHCUpdatePitch(pThis, pThisCC);
    2130                 if (pThis->svga.fEnabled)
    2131                     ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE);
    2132 #else
    2133                 rc = VINF_IOM_R3_IOPORT_WRITE;
    2134 #endif
    2135             }
    2136             /* else: nop */
    2137             break;
    2138 
    2139         case SVGA_REG_PSEUDOCOLOR:
    2140             STAM_REL_COUNTER_INC(&pThis->svga.StatRegPseudoColorWr);
    2141             break;
    2142 
    2143         case SVGA_REG_CONFIG_DONE:         /* Set when memory area configured */
    2144 #ifdef IN_RING3
    2145             STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegConfigDoneWr);
    2146             pThis->svga.fConfigured = u32;
    2147             /* Disabling the FIFO enables tracing (dirty page detection) by default. */
    2148             if (!pThis->svga.fConfigured)
    2149                 pThis->svga.fTraces = true;
    2150             vmsvgaR3SetTraces(pDevIns, pThis, !!pThis->svga.fTraces);
    2151 #else
    2152             rc = VINF_IOM_R3_IOPORT_WRITE;
    2153 #endif
    2154             break;
    2155 
    2156         case SVGA_REG_SYNC:                /* See "FIFO Synchronization Registers" */
    2157             STAM_REL_COUNTER_INC(&pThis->svga.StatRegSyncWr);
    2158             if (    pThis->svga.fEnabled
    2159                 &&  pThis->svga.fConfigured)
    2160             {
    2161 #if defined(IN_RING3) || defined(IN_RING0)
    2162                 Log(("SVGA_REG_SYNC: SVGA_FIFO_BUSY=%d\n", pThisCC->svga.pau32FIFO[SVGA_FIFO_BUSY]));
    2163                 /*
    2164                  * The VMSVGA_BUSY_F_EMT_FORCE flag makes sure we will check if the FIFO is empty
    2165                  * at least once; VMSVGA_BUSY_F_FIFO alone does not ensure that.
    2166                  */
    2167                 ASMAtomicWriteU32(&pThis->svga.fBusy, VMSVGA_BUSY_F_EMT_FORCE | VMSVGA_BUSY_F_FIFO);
    2168                 if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_BUSY, pThisCC->svga.pau32FIFO[SVGA_FIFO_MIN]))
    2169                     vmsvgaHCSafeFifoBusyRegUpdate(pThis, pThisCC, true);
    2170 
    2171                 /* Kick the FIFO thread to start processing commands again. */
    2172                 PDMDevHlpSUPSemEventSignal(pDevIns, pThis->svga.hFIFORequestSem);
    2173 #else
    2174                 rc = VINF_IOM_R3_IOPORT_WRITE;
    2175 #endif
    2176             }
    2177             /* else nothing to do. */
    2178             else
    2179                 Log(("Sync ignored enabled=%d configured=%d\n", pThis->svga.fEnabled, pThis->svga.fConfigured));
    2180 
    2181             break;
    2182 
    2183         case SVGA_REG_BUSY:                /* See "FIFO Synchronization Registers" (read-only) */
    2184             STAM_REL_COUNTER_INC(&pThis->svga.StatRegBusyWr);
    2185             break;
    2186 
    2187         case SVGA_REG_GUEST_ID:            /* Set guest OS identifier */
    2188             STAM_REL_COUNTER_INC(&pThis->svga.StatRegGuestIdWr);
    2189             pThis->svga.u32GuestId = u32;
    2190             break;
    2191 
    2192         case SVGA_REG_PITCHLOCK:           /* Fixed pitch for all modes */
    2193             STAM_REL_COUNTER_INC(&pThis->svga.StatRegPitchLockWr);
    2194             pThis->svga.u32PitchLock = u32;
    2195             /* Should this also update the FIFO pitch lock? Unclear. */
    2196             break;
    2197 
    2198         case SVGA_REG_IRQMASK:             /* Interrupt mask */
    2199             STAM_REL_COUNTER_INC(&pThis->svga.StatRegIrqMaskWr);
    2200             pThis->svga.u32IrqMask = u32;
    2201 
    2202             /* Irq pending after the above change? */
    2203             if (pThis->svga.u32IrqStatus & u32)
    2204             {
    2205                 Log(("SVGA_REG_IRQMASK: Trigger interrupt with status %x\n", pThis->svga.u32IrqStatus));
    2206                 PDMDevHlpPCISetIrqNoWait(pDevIns, 0, 1);
    2207             }
    2208             else
    2209                 PDMDevHlpPCISetIrqNoWait(pDevIns, 0, 0);
    2210             break;
    2211 
    2212         /* Mouse cursor support */
    2213         case SVGA_REG_CURSOR_ID:
    2214             STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorIdWr);
    2215             pThis->svga.uCursorID = u32;
    2216             break;
    2217 
    2218         case SVGA_REG_CURSOR_X:
    2219             STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorXWr);
    2220             pThis->svga.uCursorX = u32;
    2221             break;
    2222 
    2223         case SVGA_REG_CURSOR_Y:
    2224             STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorYWr);
    2225             pThis->svga.uCursorY = u32;
    2226             break;
    2227 
    2228         case SVGA_REG_CURSOR_ON:
    2229 #ifdef IN_RING3
    2230             /* The cursor is only updated when SVGA_REG_CURSOR_ON is written. */
    2231             STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorOnWr);
    2232             vmsvgaR3RegUpdateCursor(pThisCC, pThis, u32);
    2233 #else
    2234             rc = VINF_IOM_R3_IOPORT_WRITE;
    2235 #endif
    2236             break;
    2237 
    2238         /* Legacy multi-monitor support */
    2239         case SVGA_REG_NUM_GUEST_DISPLAYS:/* Number of guest displays in X/Y direction */
    2240             STAM_REL_COUNTER_INC(&pThis->svga.StatRegNumGuestDisplaysWr);
    2241             break;
    2242         case SVGA_REG_DISPLAY_ID:        /* Display ID for the following display attributes */
    2243             STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayIdWr);
    2244             break;
    2245         case SVGA_REG_DISPLAY_IS_PRIMARY:/* Whether this is a primary display */
    2246             STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayIsPrimaryWr);
    2247             break;
    2248         case SVGA_REG_DISPLAY_POSITION_X:/* The display position x */
    2249             STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayPositionXWr);
    2250             break;
    2251         case SVGA_REG_DISPLAY_POSITION_Y:/* The display position y */
    2252             STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayPositionYWr);
    2253             break;
    2254         case SVGA_REG_DISPLAY_WIDTH:     /* The display's width */
    2255             STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayWidthWr);
    2256             break;
    2257         case SVGA_REG_DISPLAY_HEIGHT:    /* The display's height */
    2258             STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayHeightWr);
    2259             break;
    2260 #ifdef VBOX_WITH_VMSVGA3D
    2261         /* See "Guest memory regions" below. */
    2262         case SVGA_REG_GMR_ID:
    2263             STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrIdWr);
    2264             pThis->svga.u32CurrentGMRId = u32;
    2265             break;
    2266 
    2267         case SVGA_REG_GMR_DESCRIPTOR:
    2268 # ifndef IN_RING3
    2269             rc = VINF_IOM_R3_IOPORT_WRITE;
    2270             break;
    2271 # else /* IN_RING3 */
    2272         {
    2273             STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegGmrDescriptorWr);
    2274 
    2275             /* Validate current GMR id. */
    2276             uint32_t idGMR = pThis->svga.u32CurrentGMRId;
    2277             AssertBreak(idGMR < pThis->svga.cGMR);
    2278             RT_UNTRUSTED_VALIDATED_FENCE();
    2279 
    2280             /* Free the old GMR if present. */
    2281             vmsvgaR3GmrFree(pThisCC, idGMR);
    2282 
    2283             /* Just undefine the GMR? */
    2284             RTGCPHYS GCPhys = (RTGCPHYS)u32 << PAGE_SHIFT;
    2285             if (GCPhys == 0)
    2286             {
    2287                 STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegGmrDescriptorWrFree);
    2288                 break;
    2289             }
    2290 
    2291 
    2292             /* Never cross a page boundary automatically. */
    2293             const uint32_t          cMaxPages   = RT_MIN(VMSVGA_MAX_GMR_PAGES, UINT32_MAX / X86_PAGE_SIZE);
    2294             uint32_t                cPagesTotal = 0;
    2295             uint32_t                iDesc       = 0;
    2296             PVMSVGAGMRDESCRIPTOR    paDescs     = NULL;
    2297             uint32_t                cLoops      = 0;
    2298             RTGCPHYS                GCPhysBase  = GCPhys;
    2299             while (PHYS_PAGE_ADDRESS(GCPhys) == PHYS_PAGE_ADDRESS(GCPhysBase))
    2300             {
    2301                 /* Read descriptor. */
    2302                 SVGAGuestMemDescriptor desc;
    2303                 rc = PDMDevHlpPhysRead(pDevIns, GCPhys, &desc, sizeof(desc));
    2304                 AssertRCBreak(VBOXSTRICTRC_VAL(rc));
    2305 
    2306                 if (desc.numPages != 0)
    2307                 {
    2308                     AssertBreakStmt(desc.numPages <= cMaxPages, rc = VERR_OUT_OF_RANGE);
    2309                     cPagesTotal += desc.numPages;
    2310                     AssertBreakStmt(cPagesTotal   <= cMaxPages, rc = VERR_OUT_OF_RANGE);
    2311 
    2312                     if ((iDesc & 15) == 0)
    2313                     {
    2314                         void *pvNew = RTMemRealloc(paDescs, (iDesc + 16) * sizeof(VMSVGAGMRDESCRIPTOR));
    2315                         AssertBreakStmt(pvNew, rc = VERR_NO_MEMORY);
    2316                         paDescs = (PVMSVGAGMRDESCRIPTOR)pvNew;
    2317                     }
    2318 
    2319                     paDescs[iDesc].GCPhys     = (RTGCPHYS)desc.ppn << PAGE_SHIFT;
    2320                     paDescs[iDesc++].numPages = desc.numPages;
    2321 
    2322                     /* Continue with the next descriptor. */
    2323                     GCPhys += sizeof(desc);
    2324                 }
    2325                 else if (desc.ppn == 0)
    2326                     break;  /* terminator */
    2327                 else /* Pointer to the next physical page of descriptors. */
    2328                     GCPhys = GCPhysBase = (RTGCPHYS)desc.ppn << PAGE_SHIFT;
    2329 
    2330                 cLoops++;
    2331                 AssertBreakStmt(cLoops < VMSVGA_MAX_GMR_DESC_LOOP_COUNT, rc = VERR_OUT_OF_RANGE);
    2332             }
    2333 
    2334             AssertStmt(iDesc > 0 || RT_FAILURE_NP(rc), rc = VERR_OUT_OF_RANGE);
    2335             if (RT_SUCCESS(rc))
    2336             {
    2337                 /* Commit the GMR. */
    2338                 pSVGAState->paGMR[idGMR].paDesc         = paDescs;
    2339                 pSVGAState->paGMR[idGMR].numDescriptors = iDesc;
    2340                 pSVGAState->paGMR[idGMR].cMaxPages      = cPagesTotal;
    2341                 pSVGAState->paGMR[idGMR].cbTotal        = cPagesTotal * PAGE_SIZE;
    2342                 Assert((pSVGAState->paGMR[idGMR].cbTotal >> PAGE_SHIFT) == cPagesTotal);
    2343                 Log(("Defined new gmr %x numDescriptors=%d cbTotal=%x (%#x pages)\n",
    2344                      idGMR, iDesc, pSVGAState->paGMR[idGMR].cbTotal, cPagesTotal));
    2345             }
    2346             else
    2347             {
    2348                 RTMemFree(paDescs);
    2349                 STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegGmrDescriptorWrErrors);
    2350             }
    2351             break;
    2352         }
    2353 # endif /* IN_RING3 */
    2354 #endif // VBOX_WITH_VMSVGA3D
    2355 
    2356         case SVGA_REG_TRACES:            /* Enable trace-based updates even when FIFO is on */
    2357             STAM_REL_COUNTER_INC(&pThis->svga.StatRegTracesWr);
    2358             if (pThis->svga.fTraces == u32)
    2359                 break; /* nothing to do */
    2360 
    2361 #ifdef IN_RING3
    2362             vmsvgaR3SetTraces(pDevIns, pThis, !!u32);
    2363 #else
    2364             rc = VINF_IOM_R3_IOPORT_WRITE;
    2365 #endif
    2366             break;
    2367 
    2368         case SVGA_REG_TOP:               /* Must be 1 more than the last register */
    2369             STAM_REL_COUNTER_INC(&pThis->svga.StatRegTopWr);
    2370             break;
    2371 
    2372         case SVGA_REG_NUM_DISPLAYS:        /* (Deprecated) */
    2373             STAM_REL_COUNTER_INC(&pThis->svga.StatRegNumDisplaysWr);
    2374             Log(("Write to deprecated register %x - val %x ignored\n", idxReg, u32));
    2375             break;
    2376 
    2377         /*
    2378          * SVGA_CAP_GBOBJECTS+ registers.
    2379          */
    2380         case SVGA_REG_COMMAND_LOW:
    2381         {
    2382             /* Lower 32 bits of command buffer physical address and submit the command buffer. */
    2383 #ifdef IN_RING3
    2384             STAM_REL_COUNTER_INC(&pThis->svga.StatRegCommandLowWr);
    2385             pThis->svga.u32RegCommandLow = u32;
    2386 
    2387             /* "lower 6 bits are used for the SVGACBContext" */
    2388             RTGCPHYS GCPhysCB = pThis->svga.u32RegCommandHigh;
    2389             GCPhysCB <<= 32;
    2390             GCPhysCB |= pThis->svga.u32RegCommandLow & ~SVGA_CB_CONTEXT_MASK;
    2391             SVGACBContext const CBCtx = (SVGACBContext)(pThis->svga.u32RegCommandLow & SVGA_CB_CONTEXT_MASK);
    2392             vmsvgaR3CmdBufSubmit(pDevIns, pThis, pThisCC, GCPhysCB, CBCtx);
    2393 #else
    2394             rc = VINF_IOM_R3_IOPORT_WRITE;
    2395 #endif
    2396             break;
    2397         }
    2398 
    2399         case SVGA_REG_COMMAND_HIGH:
    2400             /* Upper 32 bits of command buffer PA. */
    2401             STAM_REL_COUNTER_INC(&pThis->svga.StatRegCommandHighWr);
    2402             pThis->svga.u32RegCommandHigh = u32;
    2403             break;
    2404 
    2405         case SVGA_REG_DEV_CAP:
    2406             /* Write dev cap index, read value */
    2407             STAM_REL_COUNTER_INC(&pThis->svga.StatRegDevCapWr);
    2408             pThis->svga.u32DevCapIndex = u32;
    2409             break;
    2410 
    2411         case SVGA_REG_CMD_PREPEND_LOW:
    2412             STAM_REL_COUNTER_INC(&pThis->svga.StatRegCmdPrependLowWr);
    2413             /* Not supported. */
    2414             break;
    2415 
    2416         case SVGA_REG_iCMD_PREPEND_HIGH:
    2417             STAM_REL_COUNTER_INC(&pThis->svga.StatRegCmdPrependHighWr);
    2418             /* Not supported. */
    2419             break;
    2420 
    2421         case SVGA_REG_FB_START:
    2422         case SVGA_REG_MEM_START:
    2423         case SVGA_REG_HOST_BITS_PER_PIXEL:
    2424         case SVGA_REG_MAX_WIDTH:
    2425         case SVGA_REG_MAX_HEIGHT:
    2426         case SVGA_REG_VRAM_SIZE:
    2427         case SVGA_REG_FB_SIZE:
    2428         case SVGA_REG_CAPABILITIES:
    2429         case SVGA_REG_MEM_SIZE:
    2430         case SVGA_REG_SCRATCH_SIZE:        /* Number of scratch registers */
    2431         case SVGA_REG_MEM_REGS:            /* Number of FIFO registers */
    2432         case SVGA_REG_BYTES_PER_LINE:
    2433         case SVGA_REG_FB_OFFSET:
    2434         case SVGA_REG_RED_MASK:
    2435         case SVGA_REG_GREEN_MASK:
    2436         case SVGA_REG_BLUE_MASK:
    2437         case SVGA_REG_GMRS_MAX_PAGES:    /* Maximum number of 4KB pages for all GMRs */
    2438         case SVGA_REG_MEMORY_SIZE:       /* Total dedicated device memory excluding FIFO */
    2439         case SVGA_REG_GMR_MAX_IDS:
    2440         case SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH:
    2441         case SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM:
    2442         case SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB:
    2443         case SVGA_REG_SCREENTARGET_MAX_WIDTH:
    2444         case SVGA_REG_SCREENTARGET_MAX_HEIGHT:
    2445         case SVGA_REG_MOB_MAX_SIZE:
    2446             /* Read only - ignore. */
    2447             Log(("Write to R/O register %x - val %x ignored\n", idxReg, u32));
    2448             STAM_REL_COUNTER_INC(&pThis->svga.StatRegReadOnlyWr);
    2449             break;
    2450 
    2451         default:
    2452         {
    2453             uint32_t offReg;
    2454             if ((offReg = idxReg - SVGA_SCRATCH_BASE) < pThis->svga.cScratchRegion)
    2455             {
    2456                 RT_UNTRUSTED_VALIDATED_FENCE();
    2457                 pThis->svga.au32ScratchRegion[offReg] = u32;
    2458                 STAM_REL_COUNTER_INC(&pThis->svga.StatRegScratchWr);
    2459             }
    2460             else if ((offReg = idxReg - SVGA_PALETTE_BASE) < (uint32_t)SVGA_NUM_PALETTE_REGS)
    2461             {
    2462                 /* Note! Using last_palette rather than palette here to preserve the VGA one.
    2463                          Btw, see rgb_to_pixel32.  */
    2464                 STAM_REL_COUNTER_INC(&pThis->svga.StatRegPaletteWr);
    2465                 u32 &= 0xff;
    2466                 RT_UNTRUSTED_VALIDATED_FENCE();
    2467                 uint32_t uRgb = pThis->last_palette[offReg / 3];
    2468                 switch (offReg % 3)
    2469                 {
    2470                     case 0: uRgb = (uRgb & UINT32_C(0x0000ffff)) | (u32 << 16); break; /* red */
    2471                     case 1: uRgb = (uRgb & UINT32_C(0x00ff00ff)) | (u32 <<  8); break; /* green */
    2472                     case 2: uRgb = (uRgb & UINT32_C(0x00ffff00)) |  u32       ; break; /* blue */
    2473                 }
    2474                 pThis->last_palette[offReg / 3] = uRgb;
    2475             }
    2476             else
    2477             {
    2478 #if !defined(IN_RING3) && defined(VBOX_STRICT)
    2479                 rc = VINF_IOM_R3_IOPORT_WRITE;
    2480 #else
    2481                 STAM_REL_COUNTER_INC(&pThis->svga.StatRegUnknownWr);
    2482                 AssertMsgFailed(("reg=%#x u32=%#x\n", idxReg, u32));
    2483 #endif
    2484             }
    2485             break;
    2486         }
    2487     }
    2488     return rc;
    2489 }
    2490 
    2491 /**
    2492  * @callback_method_impl{FNIOMIOPORTNEWIN}
    2493  */
    2494 DECLCALLBACK(VBOXSTRICTRC) vmsvgaIORead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb)
    2495 {
    2496     PVGASTATE   pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
    2497     RT_NOREF_PV(pvUser);
    2498 
    2499     /* Only dword accesses. */
    2500     if (cb == 4)
    2501     {
    2502         switch (offPort)
    2503         {
    2504             case SVGA_INDEX_PORT:
    2505                 *pu32 = pThis->svga.u32IndexReg;
    2506                 break;
    2507 
    2508             case SVGA_VALUE_PORT:
    2509                 return vmsvgaReadPort(pDevIns, pThis, pu32);
    2510 
    2511             case SVGA_BIOS_PORT:
    2512                 Log(("Ignoring BIOS port read\n"));
    2513                 *pu32 = 0;
    2514                 break;
    2515 
    2516             case SVGA_IRQSTATUS_PORT:
    2517                 LogFlow(("vmsvgaIORead: SVGA_IRQSTATUS_PORT %x\n", pThis->svga.u32IrqStatus));
    2518                 *pu32 = pThis->svga.u32IrqStatus;
    2519                 break;
    2520 
    2521             default:
    2522                 ASSERT_GUEST_MSG_FAILED(("vmsvgaIORead: Unknown register %u was read from.\n", offPort));
    2523                 *pu32 = UINT32_MAX;
    2524                 break;
    2525         }
    2526     }
    2527     else
    2528     {
    2529         Log(("Ignoring non-dword I/O port read at %x cb=%d\n", offPort, cb));
    2530         *pu32 = UINT32_MAX;
    2531     }
    2532     return VINF_SUCCESS;
    2533 }
    2534 
    2535 /**
    2536  * @callback_method_impl{FNIOMIOPORTNEWOUT}
    2537  */
    2538 DECLCALLBACK(VBOXSTRICTRC) vmsvgaIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb)
    2539 {
    2540     PVGASTATE   pThis   = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
    2541     PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
    2542     RT_NOREF_PV(pvUser);
    2543 
    2544     /* Only dword accesses. */
    2545     if (cb == 4)
    2546         switch (offPort)
    2547         {
    2548             case SVGA_INDEX_PORT:
    2549                 pThis->svga.u32IndexReg = u32;
    2550                 break;
    2551 
    2552             case SVGA_VALUE_PORT:
    2553                 return vmsvgaWritePort(pDevIns, pThis, pThisCC, u32);
    2554 
    2555             case SVGA_BIOS_PORT:
    2556                 Log(("Ignoring BIOS port write (val=%x)\n", u32));
    2557                 break;
    2558 
    2559             case SVGA_IRQSTATUS_PORT:
    2560                 Log(("vmsvgaIOWrite SVGA_IRQSTATUS_PORT %x: status %x -> %x\n", u32, pThis->svga.u32IrqStatus, pThis->svga.u32IrqStatus & ~u32));
    2561                 ASMAtomicAndU32(&pThis->svga.u32IrqStatus, ~u32);
    2562                 /* Clear the irq in case all events have been cleared. */
    2563                 if (!(pThis->svga.u32IrqStatus & pThis->svga.u32IrqMask))
    2564                 {
    2565                     Log(("vmsvgaIOWrite SVGA_IRQSTATUS_PORT: clearing IRQ\n"));
    2566                     PDMDevHlpPCISetIrqNoWait(pDevIns, 0, 0);
    2567                 }
    2568                 break;
    2569 
    2570             default:
    2571                 ASSERT_GUEST_MSG_FAILED(("vmsvgaIOWrite: Unknown register %u was written to, value %#x LB %u.\n", offPort, u32, cb));
    2572                 break;
    2573         }
    2574     else
    2575         Log(("Ignoring non-dword write at %x val=%x cb=%d\n", offPort, u32, cb));
    2576 
    2577     return VINF_SUCCESS;
    2578 }
    2579 
    2580 #ifdef IN_RING3
    2581 
    2582 # ifdef DEBUG_FIFO_ACCESS
    2583 /**
    2584  * Handle FIFO memory access.
    2585  * @returns VBox status code.
    2586  * @param   pVM             VM handle.
    2587  * @param   pThis           The shared VGA/VMSVGA instance data.
    2588  * @param   GCPhys          The access physical address.
    2589  * @param   fWriteAccess    Read or write access
    2590  */
    2591 static int vmsvgaR3DebugFifoAccess(PVM pVM, PVGASTATE pThis, RTGCPHYS GCPhys, bool fWriteAccess)
    2592 {
    2593     RT_NOREF(pVM);
    2594     RTGCPHYS GCPhysOffset = GCPhys - pThis->svga.GCPhysFIFO;
    2595     uint32_t *pFIFO = pThisCC->svga.pau32FIFO;
    2596 
    2597     switch (GCPhysOffset >> 2)
    2598     {
    2599     case SVGA_FIFO_MIN:
    2600         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_MIN = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2601         break;
    2602     case SVGA_FIFO_MAX:
    2603         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_MAX = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2604         break;
    2605     case SVGA_FIFO_NEXT_CMD:
    2606         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_NEXT_CMD = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2607         break;
    2608     case SVGA_FIFO_STOP:
    2609         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_STOP = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2610         break;
    2611     case SVGA_FIFO_CAPABILITIES:
    2612         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CAPABILITIES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2613         break;
    2614     case SVGA_FIFO_FLAGS:
    2615         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_FLAGS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2616         break;
    2617     case SVGA_FIFO_FENCE:
    2618         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_FENCE = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2619         break;
    2620     case SVGA_FIFO_3D_HWVERSION:
    2621         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_HWVERSION = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2622         break;
    2623     case SVGA_FIFO_PITCHLOCK:
    2624         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_PITCHLOCK = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2625         break;
    2626     case SVGA_FIFO_CURSOR_ON:
    2627         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_ON = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2628         break;
    2629     case SVGA_FIFO_CURSOR_X:
    2630         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_X = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2631         break;
    2632     case SVGA_FIFO_CURSOR_Y:
    2633         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_Y = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2634         break;
    2635     case SVGA_FIFO_CURSOR_COUNT:
    2636         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_COUNT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2637         break;
    2638     case SVGA_FIFO_CURSOR_LAST_UPDATED:
    2639         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_LAST_UPDATED = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2640         break;
    2641     case SVGA_FIFO_RESERVED:
    2642         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_RESERVED = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2643         break;
    2644     case SVGA_FIFO_CURSOR_SCREEN_ID:
    2645         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_SCREEN_ID = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2646         break;
    2647     case SVGA_FIFO_DEAD:
    2648         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_DEAD = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2649         break;
    2650     case SVGA_FIFO_3D_HWVERSION_REVISED:
    2651         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_HWVERSION_REVISED = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2652         break;
    2653     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_3D:
    2654         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_3D = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2655         break;
    2656     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_LIGHTS:
    2657         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_LIGHTS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2658         break;
    2659     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURES:
    2660         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2661         break;
    2662     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_CLIP_PLANES:
    2663         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_CLIP_PLANES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2664         break;
    2665     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_VERTEX_SHADER_VERSION:
    2666         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_VERTEX_SHADER_VERSION = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2667         break;
    2668     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_VERTEX_SHADER:
    2669         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_VERTEX_SHADER = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2670         break;
    2671     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_FRAGMENT_SHADER_VERSION:
    2672         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_FRAGMENT_SHADER_VERSION = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2673         break;
    2674     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_FRAGMENT_SHADER:
    2675         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_FRAGMENT_SHADER = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2676         break;
    2677     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_RENDER_TARGETS:
    2678         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_RENDER_TARGETS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2679         break;
    2680     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_S23E8_TEXTURES:
    2681         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_S23E8_TEXTURES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2682         break;
    2683     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_S10E5_TEXTURES:
    2684         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_S10E5_TEXTURES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2685         break;
    2686     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_FIXED_VERTEXBLEND:
    2687         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_FIXED_VERTEXBLEND = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2688         break;
    2689     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_D16_BUFFER_FORMAT:
    2690         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_D16_BUFFER_FORMAT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2691         break;
    2692     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_D24S8_BUFFER_FORMAT:
    2693         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_D24S8_BUFFER_FORMAT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2694         break;
    2695     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_D24X8_BUFFER_FORMAT:
    2696         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_D24X8_BUFFER_FORMAT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2697         break;
    2698     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_QUERY_TYPES:
    2699         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_QUERY_TYPES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2700         break;
    2701     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_TEXTURE_GRADIENT_SAMPLING:
    2702         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_TEXTURE_GRADIENT_SAMPLING = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2703         break;
    2704     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_POINT_SIZE:
    2705         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_POINT_SIZE = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2706         break;
    2707     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_SHADER_TEXTURES:
    2708         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_SHADER_TEXTURES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2709         break;
    2710     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURE_WIDTH:
    2711         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURE_WIDTH = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2712         break;
    2713     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURE_HEIGHT:
    2714         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURE_HEIGHT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2715         break;
    2716     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_VOLUME_EXTENT:
    2717         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_VOLUME_EXTENT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2718         break;
    2719     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURE_REPEAT:
    2720         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURE_REPEAT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2721         break;
    2722     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURE_ASPECT_RATIO:
    2723         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURE_ASPECT_RATIO = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2724         break;
    2725     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURE_ANISOTROPY:
    2726         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURE_ANISOTROPY = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2727         break;
    2728     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_PRIMITIVE_COUNT:
    2729         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_PRIMITIVE_COUNT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2730         break;
    2731     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_VERTEX_INDEX:
    2732         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_VERTEX_INDEX = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2733         break;
    2734     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_VERTEX_SHADER_INSTRUCTIONS:
    2735         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_VERTEX_SHADER_INSTRUCTIONS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2736         break;
    2737     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_INSTRUCTIONS:
    2738         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_INSTRUCTIONS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2739         break;
    2740     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEMPS:
    2741         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEMPS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2742         break;
    2743     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_TEMPS:
    2744         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_TEMPS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2745         break;
    2746     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_TEXTURE_OPS:
    2747         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_TEXTURE_OPS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2748         break;
    2749     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8:
    2750         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2751         break;
    2752     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8:
    2753         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2754         break;
    2755     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10:
    2756         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2757         break;
    2758     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5:
    2759         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2760         break;
    2761     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5:
    2762         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2763         break;
    2764     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4:
    2765         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2766         break;
    2767     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_R5G6B5:
    2768         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_R5G6B5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2769         break;
    2770     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE16:
    2771         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2772         break;
    2773     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8:
    2774         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2775         break;
    2776     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_ALPHA8:
    2777         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_ALPHA8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2778         break;
    2779     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8:
    2780         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2781         break;
    2782     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_D16:
    2783         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_D16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2784         break;
    2785     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8:
    2786         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2787         break;
    2788     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8:
    2789         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2790         break;
    2791     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_DXT1:
    2792         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_DXT1 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2793         break;
    2794     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_DXT2:
    2795         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_DXT2 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2796         break;
    2797     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_DXT3:
    2798         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_DXT3 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2799         break;
    2800     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_DXT4:
    2801         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_DXT4 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2802         break;
    2803     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_DXT5:
    2804         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_DXT5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2805         break;
    2806     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_BUMPX8L8V8U8:
    2807         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_BUMPX8L8V8U8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2808         break;
    2809     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A2W10V10U10:
    2810         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A2W10V10U10 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2811         break;
    2812     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_BUMPU8V8:
    2813         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_BUMPU8V8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2814         break;
    2815     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Q8W8V8U8:
    2816         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Q8W8V8U8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2817         break;
    2818     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_CxV8U8:
    2819         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_CxV8U8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2820         break;
    2821     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_R_S10E5:
    2822         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_R_S10E5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2823         break;
    2824     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_R_S23E8:
    2825         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_R_S23E8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2826         break;
    2827     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_RG_S10E5:
    2828         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_RG_S10E5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2829         break;
    2830     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_RG_S23E8:
    2831         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_RG_S23E8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2832         break;
    2833     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_ARGB_S10E5:
    2834         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_ARGB_S10E5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2835         break;
    2836     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_ARGB_S23E8:
    2837         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_ARGB_S23E8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2838         break;
    2839     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEXTURES:
    2840         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEXTURES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2841         break;
    2842     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_SIMULTANEOUS_RENDER_TARGETS:
    2843         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_SIMULTANEOUS_RENDER_TARGETS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2844         break;
    2845     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_V16U16:
    2846         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_V16U16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2847         break;
    2848     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_G16R16:
    2849         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_G16R16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2850         break;
    2851     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16:
    2852         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2853         break;
    2854     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_UYVY:
    2855         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_UYVY = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2856         break;
    2857     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_YUY2:
    2858         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_YUY2 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2859         break;
    2860     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MULTISAMPLE_NONMASKABLESAMPLES:
    2861         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MULTISAMPLE_NONMASKABLESAMPLES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2862         break;
    2863     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MULTISAMPLE_MASKABLESAMPLES:
    2864         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MULTISAMPLE_MASKABLESAMPLES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2865         break;
    2866     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_ALPHATOCOVERAGE:
    2867         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_ALPHATOCOVERAGE = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2868         break;
    2869     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SUPERSAMPLE:
    2870         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SUPERSAMPLE = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2871         break;
    2872     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_AUTOGENMIPMAPS:
    2873         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_AUTOGENMIPMAPS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2874         break;
    2875     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_NV12:
    2876         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_NV12 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2877         break;
    2878     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_AYUV:
    2879         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_AYUV = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2880         break;
    2881     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_CONTEXT_IDS:
    2882         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_CONTEXT_IDS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2883         break;
    2884     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_SURFACE_IDS:
    2885         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_SURFACE_IDS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2886         break;
    2887     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_DF16:
    2888         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_DF16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2889         break;
    2890     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_DF24:
    2891         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_DF24 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2892         break;
    2893     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8_INT:
    2894         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8_INT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2895         break;
    2896     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_ATI1:
    2897         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_ATI1 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2898         break;
    2899     case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_ATI2:
    2900         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_ATI2 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2901         break;
    2902     case SVGA_FIFO_3D_CAPS_LAST:
    2903         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS_LAST = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2904         break;
    2905     case SVGA_FIFO_GUEST_3D_HWVERSION:
    2906         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_GUEST_3D_HWVERSION = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2907         break;
    2908     case SVGA_FIFO_FENCE_GOAL:
    2909         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_FENCE_GOAL = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2910         break;
    2911     case SVGA_FIFO_BUSY:
    2912         Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_BUSY = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
    2913         break;
    2914     default:
    2915         Log(("vmsvgaFIFOAccess [0x%x]: %s access at offset %x = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", GCPhysOffset, pFIFO[GCPhysOffset >> 2]));
    2916         break;
    2917     }
    2918 
    2919     return VINF_EM_RAW_EMULATE_INSTR;
    2920 }
    2921 # endif /* DEBUG_FIFO_ACCESS */
    2922 
    2923 # if defined(VMSVGA_USE_FIFO_ACCESS_HANDLER) || defined(DEBUG_FIFO_ACCESS)
    2924 /**
    2925  * HC access handler for the FIFO.
    2926  *
    2927  * @returns VINF_SUCCESS if the handler have carried out the operation.
    2928  * @returns VINF_PGM_HANDLER_DO_DEFAULT if the caller should carry out the access operation.
    2929  * @param   pVM             VM Handle.
    2930  * @param   pVCpu           The cross context CPU structure for the calling EMT.
    2931  * @param   GCPhys          The physical address the guest is writing to.
    2932  * @param   pvPhys          The HC mapping of that address.
    2933  * @param   pvBuf           What the guest is reading/writing.
    2934  * @param   cbBuf           How much it's reading/writing.
    2935  * @param   enmAccessType   The access type.
    2936  * @param   enmOrigin       Who is making the access.
    2937  * @param   pvUser          User argument.
    2938  */
    2939 static DECLCALLBACK(VBOXSTRICTRC)
    2940 vmsvgaR3FifoAccessHandler(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf,
    2941                           PGMACCESSTYPE enmAccessType, PGMACCESSORIGIN enmOrigin, void *pvUser)
    2942 {
    2943     NOREF(pVCpu); NOREF(pvPhys); NOREF(pvBuf); NOREF(cbBuf); NOREF(enmOrigin); NOREF(enmAccessType); NOREF(GCPhys);
    2944     PVGASTATE pThis = (PVGASTATE)pvUser;
    2945     AssertPtr(pThis);
    2946 
    2947 # ifdef VMSVGA_USE_FIFO_ACCESS_HANDLER
    2948     /*
    2949      * Wake up the FIFO thread as it might have work to do now.
    2950      */
    2951     int rc = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->svga.hFIFORequestSem);
    2952     AssertLogRelRC(rc);
    2953 # endif
    2954 
    2955 # ifdef DEBUG_FIFO_ACCESS
    2956     /*
    2957      * When in debug-fifo-access mode, we do not disable the access handler,
    2958      * but leave it on as we wish to catch all access.
    2959      */
    2960     Assert(GCPhys >= pThis->svga.GCPhysFIFO);
    2961     rc = vmsvgaR3DebugFifoAccess(pVM, pThis, GCPhys, enmAccessType == PGMACCESSTYPE_WRITE);
    2962 # elif defined(VMSVGA_USE_FIFO_ACCESS_HANDLER)
    2963     /*
    2964      * Temporarily disable the access handler now that we've kicked the FIFO thread.
    2965      */
    2966     STAM_REL_COUNTER_INC(&pThisCC->svga.pSvgaR3State->StatFifoAccessHandler);
    2967     rc = PGMHandlerPhysicalPageTempOff(pVM, pThis->svga.GCPhysFIFO, pThis->svga.GCPhysFIFO);
    2968 # endif
    2969     if (RT_SUCCESS(rc))
    2970         return VINF_PGM_HANDLER_DO_DEFAULT;
    2971     AssertMsg(rc <= VINF_SUCCESS, ("rc=%Rrc\n", rc));
    2972     return rc;
    2973 }
    2974 # endif /* VMSVGA_USE_FIFO_ACCESS_HANDLER || DEBUG_FIFO_ACCESS */
    2975 
    2976 #endif /* IN_RING3 */
    2977 
    2978222#ifdef DEBUG_GMR_ACCESS
    2979 # ifdef IN_RING3
    2980 
    2981 /**
    2982  * HC access handler for the FIFO.
    2983  *
    2984  * @returns VINF_SUCCESS if the handler have carried out the operation.
    2985  * @returns VINF_PGM_HANDLER_DO_DEFAULT if the caller should carry out the access operation.
    2986  * @param   pVM             VM Handle.
    2987  * @param   pVCpu           The cross context CPU structure for the calling EMT.
    2988  * @param   GCPhys          The physical address the guest is writing to.
    2989  * @param   pvPhys          The HC mapping of that address.
    2990  * @param   pvBuf           What the guest is reading/writing.
    2991  * @param   cbBuf           How much it's reading/writing.
    2992  * @param   enmAccessType   The access type.
    2993  * @param   enmOrigin       Who is making the access.
    2994  * @param   pvUser          User argument.
    2995  */
    2996 static DECLCALLBACK(VBOXSTRICTRC)
    2997 vmsvgaR3GmrAccessHandler(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf,
    2998                          PGMACCESSTYPE enmAccessType, PGMACCESSORIGIN enmOrigin, void *pvUser)
    2999 {
    3000     PVGASTATE   pThis = (PVGASTATE)pvUser;
    3001     Assert(pThis);
    3002     PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
    3003     NOREF(pVCpu); NOREF(pvPhys); NOREF(pvBuf); NOREF(cbBuf); NOREF(enmAccessType); NOREF(enmOrigin);
    3004 
    3005     Log(("vmsvgaR3GmrAccessHandler: GMR access to page %RGp\n", GCPhys));
    3006 
    3007     for (uint32_t i = 0; i < pThis->svga.cGMR; ++i)
    3008     {
    3009         PGMR pGMR = &pSVGAState->paGMR[i];
    3010 
    3011         if (pGMR->numDescriptors)
    3012         {
    3013             for (uint32_t j = 0; j < pGMR->numDescriptors; j++)
    3014             {
    3015                 if (    GCPhys >= pGMR->paDesc[j].GCPhys
    3016                     &&  GCPhys < pGMR->paDesc[j].GCPhys + pGMR->paDesc[j].numPages * PAGE_SIZE)
    3017                 {
    3018                     /*
    3019                      * Turn off the write handler for this particular page and make it R/W.
    3020                      * Then return telling the caller to restart the guest instruction.
    3021                      */
    3022                     int rc = PGMHandlerPhysicalPageTempOff(pVM, pGMR->paDesc[j].GCPhys, GCPhys);
    3023                     AssertRC(rc);
    3024                     return VINF_PGM_HANDLER_DO_DEFAULT;
    3025                 }
    3026             }
    3027         }
    3028     }
    3029 
    3030     return VINF_PGM_HANDLER_DO_DEFAULT;
    3031 }
    3032 
    3033 /** Callback handler for VMR3ReqCallWaitU */
    3034 static DECLCALLBACK(int) vmsvgaR3RegisterGmr(PPDMDEVINS pDevIns, uint32_t gmrId)
    3035 {
    3036     PVGASTATE       pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
    3037     PVMSVGAR3STATE  pSVGAState = pThisCC->svga.pSvgaR3State;
    3038     PGMR pGMR = &pSVGAState->paGMR[gmrId];
    3039     int rc;
    3040 
    3041     for (uint32_t i = 0; i < pGMR->numDescriptors; i++)
    3042     {
    3043         rc = PGMHandlerPhysicalRegister(PDMDevHlpGetVM(pDevIns),
    3044                                         pGMR->paDesc[i].GCPhys, pGMR->paDesc[i].GCPhys + pGMR->paDesc[i].numPages * PAGE_SIZE - 1,
    3045                                         pThis->svga.hGmrAccessHandlerType, pThis, NIL_RTR0PTR, NIL_RTRCPTR, "VMSVGA GMR");
    3046         AssertRC(rc);
    3047     }
    3048     return VINF_SUCCESS;
    3049 }
    3050 
    3051 /** Callback handler for VMR3ReqCallWaitU */
    3052 static DECLCALLBACK(int) vmsvgaR3DeregisterGmr(PPDMDEVINS pDevIns, uint32_t gmrId)
    3053 {
    3054     PVGASTATE       pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
    3055     PVMSVGAR3STATE  pSVGAState = pThisCC->svga.pSvgaR3State;
    3056     PGMR pGMR = &pSVGAState->paGMR[gmrId];
    3057 
    3058     for (uint32_t i = 0; i < pGMR->numDescriptors; i++)
    3059     {
    3060         int rc = PGMHandlerPhysicalDeregister(PDMDevHlpGetVM(pDevIns), pGMR->paDesc[i].GCPhys);
    3061         AssertRC(rc);
    3062     }
    3063     return VINF_SUCCESS;
    3064 }
    3065 
    3066 /** Callback handler for VMR3ReqCallWaitU */
    3067 static DECLCALLBACK(int) vmsvgaR3ResetGmrHandlers(PVGASTATE pThis)
    3068 {
    3069     PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
    3070 
    3071     for (uint32_t i = 0; i < pThis->svga.cGMR; ++i)
    3072     {
    3073         PGMR pGMR = &pSVGAState->paGMR[i];
    3074 
    3075         if (pGMR->numDescriptors)
    3076         {
    3077             for (uint32_t j = 0; j < pGMR->numDescriptors; j++)
    3078             {
    3079                 int rc = PGMHandlerPhysicalReset(PDMDevHlpGetVM(pDevIns), pGMR->paDesc[j].GCPhys);
    3080                 AssertRC(rc);
    3081             }
    3082         }
    3083     }
    3084     return VINF_SUCCESS;
    3085 }
    3086 
    3087 # endif /* IN_RING3 */
    3088 #endif /* DEBUG_GMR_ACCESS */
    3089 
    3090 /* -=-=-=-=-=- Ring 3 -=-=-=-=-=- */
    3091 
    3092 #ifdef IN_RING3
    3093 
    3094 
    3095 /**
    3096  * Common worker for changing the pointer shape.
    3097  *
    3098  * @param   pThisCC             The VGA/VMSVGA state for ring-3.
    3099  * @param   pSVGAState          The VMSVGA ring-3 instance data.
    3100  * @param   fAlpha              Whether there is alpha or not.
    3101  * @param   xHot                Hotspot x coordinate.
    3102  * @param   yHot                Hotspot y coordinate.
    3103  * @param   cx                  Width.
    3104  * @param   cy                  Height.
    3105  * @param   pbData              Heap copy of the cursor data.  Consumed.
    3106  * @param   cbData              The size of the data.
    3107  */
    3108 static void vmsvgaR3InstallNewCursor(PVGASTATECC pThisCC, PVMSVGAR3STATE pSVGAState, bool fAlpha,
    3109                                      uint32_t xHot, uint32_t yHot, uint32_t cx, uint32_t cy, uint8_t *pbData, uint32_t cbData)
    3110 {
    3111     LogRel2(("vmsvgaR3InstallNewCursor: cx=%d cy=%d xHot=%d yHot=%d fAlpha=%d cbData=%#x\n", cx, cy, xHot, yHot, fAlpha, cbData));
    3112 # ifdef LOG_ENABLED
    3113     if (LogIs2Enabled())
    3114     {
    3115         uint32_t cbAndLine = RT_ALIGN(cx, 8) / 8;
    3116         if (!fAlpha)
    3117         {
    3118             Log2(("VMSVGA Cursor AND mask (%d,%d):\n", cx, cy));
    3119             for (uint32_t y = 0; y < cy; y++)
    3120             {
    3121                 Log2(("%3u:", y));
    3122                 uint8_t const *pbLine = &pbData[y * cbAndLine];
    3123                 for (uint32_t x = 0; x < cx; x += 8)
    3124                 {
    3125                     uint8_t   b = pbLine[x / 8];
    3126                     char      szByte[12];
    3127                     szByte[0] = b & 0x80 ? '*' : ' '; /* most significant bit first */
    3128                     szByte[1] = b & 0x40 ? '*' : ' ';
    3129                     szByte[2] = b & 0x20 ? '*' : ' ';
    3130                     szByte[3] = b & 0x10 ? '*' : ' ';
    3131                     szByte[4] = b & 0x08 ? '*' : ' ';
    3132                     szByte[5] = b & 0x04 ? '*' : ' ';
    3133                     szByte[6] = b & 0x02 ? '*' : ' ';
    3134                     szByte[7] = b & 0x01 ? '*' : ' ';
    3135                     szByte[8] = '\0';
    3136                     Log2(("%s", szByte));
    3137                 }
    3138                 Log2(("\n"));
    3139             }
    3140         }
    3141 
    3142         Log2(("VMSVGA Cursor XOR mask (%d,%d):\n", cx, cy));
    3143         uint32_t const *pu32Xor = (uint32_t const *)&pbData[RT_ALIGN_32(cbAndLine * cy, 4)];
    3144         for (uint32_t y = 0; y < cy; y++)
    3145         {
    3146             Log2(("%3u:", y));
    3147             uint32_t const *pu32Line = &pu32Xor[y * cx];
    3148             for (uint32_t x = 0; x < cx; x++)
    3149                 Log2((" %08x", pu32Line[x]));
    3150             Log2(("\n"));
    3151         }
    3152     }
    3153 # endif
    3154 
    3155     int rc = pThisCC->pDrv->pfnVBVAMousePointerShape(pThisCC->pDrv, true /*fVisible*/, fAlpha, xHot, yHot, cx, cy, pbData);
    3156     AssertRC(rc);
    3157 
    3158     if (pSVGAState->Cursor.fActive)
    3159         RTMemFreeZ(pSVGAState->Cursor.pData, pSVGAState->Cursor.cbData);
    3160 
    3161     pSVGAState->Cursor.fActive  = true;
    3162     pSVGAState->Cursor.xHotspot = xHot;
    3163     pSVGAState->Cursor.yHotspot = yHot;
    3164     pSVGAState->Cursor.width    = cx;
    3165     pSVGAState->Cursor.height   = cy;
    3166     pSVGAState->Cursor.cbData   = cbData;
    3167     pSVGAState->Cursor.pData    = pbData;
    3168 }
    3169 
    3170 
    3171 # ifdef VBOX_WITH_VMSVGA3D
    3172 /** @def VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK
    3173  * Check that the 3D command has at least a_cbMin of payload bytes after the
    3174  * header.  Will break out of the switch if it doesn't.
    3175  */
    3176 #  define VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(a_cbMin) \
    3177      if (1) { \
    3178           AssertMsgBreak(cbCmd >= (a_cbMin), ("size=%#x a_cbMin=%#zx\n", cbCmd, (size_t)(a_cbMin))); \
    3179           RT_UNTRUSTED_VALIDATED_FENCE(); \
    3180      } else do {} while (0)
    3181 
    3182 #  define VMSVGA_3D_CMD_NOTIMPL() \
    3183      if (1) { \
    3184           AssertMsgFailed(("Not implemented %d %s\n", enmCmdId, vmsvgaR3FifoCmdToString(enmCmdId))); \
    3185      } else do {} while (0)
    3186 
    3187 /** SVGA_3D_CMD_* handler.
    3188  * This function parses the command and calls the corresponding command handler.
    3189  *
    3190  * @param   pThis       The shared VGA/VMSVGA state.
    3191  * @param   pThisCC     The VGA/VMSVGA state for the current context.
    3192  * @param   enmCmdId    SVGA_3D_CMD_* command identifier.
    3193  * @param   cbCmd       Size of the command in bytes.
    3194  * @param   pvCmd       Pointer to the command.
    3195  * @returns VBox status code if an error was detected parsing a command.
    3196  */
    3197 static int vmsvgaR3Process3dCmd(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifo3dCmdId enmCmdId, uint32_t cbCmd, void const *pvCmd)
    3198 {
    3199     int rcParse = VINF_SUCCESS;
    3200     PVMSVGAR3STATE pSvgaR3State = pThisCC->svga.pSvgaR3State;
    3201 
    3202     switch (enmCmdId)
    3203     {
    3204     case SVGA_3D_CMD_SURFACE_DEFINE:
    3205     {
    3206         SVGA3dCmdDefineSurface *pCmd = (SVGA3dCmdDefineSurface *)pvCmd;
    3207         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3208         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSurfaceDefine);
    3209 
    3210         uint32_t const cMipLevels = (cbCmd - sizeof(*pCmd)) / sizeof(SVGA3dSize);
    3211         vmsvga3dSurfaceDefine(pThisCC, pCmd->sid, (uint32_t)pCmd->surfaceFlags, pCmd->format, pCmd->face, 0,
    3212                               SVGA3D_TEX_FILTER_NONE, cMipLevels, (SVGA3dSize *)(pCmd + 1));
    3213 #  ifdef DEBUG_GMR_ACCESS
    3214         VMR3ReqCallWaitU(PDMDevHlpGetUVM(pDevIns), VMCPUID_ANY, (PFNRT)vmsvgaR3ResetGmrHandlers, 1, pThis);
    3215 #  endif
    3216         break;
    3217     }
    3218 
    3219     case SVGA_3D_CMD_SURFACE_DEFINE_V2:
    3220     {
    3221         SVGA3dCmdDefineSurface_v2 *pCmd = (SVGA3dCmdDefineSurface_v2 *)pvCmd;
    3222         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3223         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSurfaceDefineV2);
    3224 
    3225         uint32_t const cMipLevels = (cbCmd - sizeof(*pCmd)) / sizeof(SVGA3dSize);
    3226         vmsvga3dSurfaceDefine(pThisCC, pCmd->sid, pCmd->surfaceFlags, pCmd->format, pCmd->face,
    3227                               pCmd->multisampleCount, pCmd->autogenFilter,
    3228                               cMipLevels, (SVGA3dSize *)(pCmd + 1));
    3229         break;
    3230     }
    3231 
    3232     case SVGA_3D_CMD_SURFACE_DESTROY:
    3233     {
    3234         SVGA3dCmdDestroySurface *pCmd = (SVGA3dCmdDestroySurface *)pvCmd;
    3235         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3236         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSurfaceDestroy);
    3237 
    3238         vmsvga3dSurfaceDestroy(pThisCC, pCmd->sid);
    3239         break;
    3240     }
    3241 
    3242     case SVGA_3D_CMD_SURFACE_COPY:
    3243     {
    3244         SVGA3dCmdSurfaceCopy *pCmd = (SVGA3dCmdSurfaceCopy *)pvCmd;
    3245         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3246         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSurfaceCopy);
    3247 
    3248         uint32_t const cCopyBoxes = (cbCmd - sizeof(pCmd)) / sizeof(SVGA3dCopyBox);
    3249         vmsvga3dSurfaceCopy(pThisCC, pCmd->dest, pCmd->src, cCopyBoxes, (SVGA3dCopyBox *)(pCmd + 1));
    3250         break;
    3251     }
    3252 
    3253     case SVGA_3D_CMD_SURFACE_STRETCHBLT:
    3254     {
    3255         SVGA3dCmdSurfaceStretchBlt *pCmd = (SVGA3dCmdSurfaceStretchBlt *)pvCmd;
    3256         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3257         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSurfaceStretchBlt);
    3258 
    3259         vmsvga3dSurfaceStretchBlt(pThis, pThisCC, &pCmd->dest, &pCmd->boxDest,
    3260                                   &pCmd->src, &pCmd->boxSrc, pCmd->mode);
    3261         break;
    3262     }
    3263 
    3264     case SVGA_3D_CMD_SURFACE_DMA:
    3265     {
    3266         SVGA3dCmdSurfaceDMA *pCmd = (SVGA3dCmdSurfaceDMA *)pvCmd;
    3267         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3268         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSurfaceDma);
    3269 
    3270         uint64_t u64NanoTS = 0;
    3271         if (LogRelIs3Enabled())
    3272             u64NanoTS = RTTimeNanoTS();
    3273         uint32_t const cCopyBoxes = (cbCmd - sizeof(*pCmd)) / sizeof(SVGA3dCopyBox);
    3274         STAM_PROFILE_START(&pSvgaR3State->StatR3Cmd3dSurfaceDmaProf, a);
    3275         vmsvga3dSurfaceDMA(pThis, pThisCC, pCmd->guest, pCmd->host, pCmd->transfer,
    3276                            cCopyBoxes, (SVGA3dCopyBox *)(pCmd + 1));
    3277         STAM_PROFILE_STOP(&pSvgaR3State->StatR3Cmd3dSurfaceDmaProf, a);
    3278         if (LogRelIs3Enabled())
    3279         {
    3280             if (cCopyBoxes)
    3281             {
    3282                 SVGA3dCopyBox *pFirstBox = (SVGA3dCopyBox *)(pCmd + 1);
    3283                 LogRel3(("VMSVGA: SURFACE_DMA: %d us %d boxes %d,%d %dx%d%s\n",
    3284                          (RTTimeNanoTS() - u64NanoTS) / 1000ULL, cCopyBoxes,
    3285                          pFirstBox->x, pFirstBox->y, pFirstBox->w, pFirstBox->h,
    3286                          pCmd->transfer == SVGA3D_READ_HOST_VRAM ? " readback!!!" : ""));
    3287             }
    3288         }
    3289         break;
    3290     }
    3291 
    3292     case SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN:
    3293     {
    3294         SVGA3dCmdBlitSurfaceToScreen *pCmd = (SVGA3dCmdBlitSurfaceToScreen *)pvCmd;
    3295         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3296         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSurfaceScreen);
    3297 
    3298         static uint64_t u64FrameStartNanoTS = 0;
    3299         static uint64_t u64ElapsedPerSecNano = 0;
    3300         static int cFrames = 0;
    3301         uint64_t u64NanoTS = 0;
    3302         if (LogRelIs3Enabled())
    3303             u64NanoTS = RTTimeNanoTS();
    3304         uint32_t const cRects = (cbCmd - sizeof(*pCmd)) / sizeof(SVGASignedRect);
    3305         STAM_REL_PROFILE_START(&pSvgaR3State->StatR3Cmd3dBlitSurfaceToScreenProf, a);
    3306         vmsvga3dSurfaceBlitToScreen(pThis, pThisCC, pCmd->destScreenId, pCmd->destRect, pCmd->srcImage,
    3307                                     pCmd->srcRect, cRects, (SVGASignedRect *)(pCmd + 1));
    3308         STAM_REL_PROFILE_STOP(&pSvgaR3State->StatR3Cmd3dBlitSurfaceToScreenProf, a);
    3309         if (LogRelIs3Enabled())
    3310         {
    3311             uint64_t u64ElapsedNano = RTTimeNanoTS() - u64NanoTS;
    3312             u64ElapsedPerSecNano += u64ElapsedNano;
    3313 
    3314             SVGASignedRect *pFirstRect = cRects ? (SVGASignedRect *)(pCmd + 1) : &pCmd->destRect;
    3315             LogRel3(("VMSVGA: SURFACE_TO_SCREEN: %d us %d rects %d,%d %dx%d\n",
    3316                      (u64ElapsedNano) / 1000ULL, cRects,
    3317                      pFirstRect->left, pFirstRect->top,
    3318                      pFirstRect->right - pFirstRect->left, pFirstRect->bottom - pFirstRect->top));
    3319 
    3320             ++cFrames;
    3321             if (u64NanoTS - u64FrameStartNanoTS >= UINT64_C(1000000000))
    3322             {
    3323                 LogRel3(("VMSVGA: SURFACE_TO_SCREEN: FPS %d, elapsed %llu us\n",
    3324                          cFrames, u64ElapsedPerSecNano / 1000ULL));
    3325                 u64FrameStartNanoTS = u64NanoTS;
    3326                 cFrames = 0;
    3327                 u64ElapsedPerSecNano = 0;
    3328             }
    3329         }
    3330         break;
    3331     }
    3332 
    3333     case SVGA_3D_CMD_CONTEXT_DEFINE:
    3334     {
    3335         SVGA3dCmdDefineContext *pCmd = (SVGA3dCmdDefineContext *)pvCmd;
    3336         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3337         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dContextDefine);
    3338 
    3339         vmsvga3dContextDefine(pThisCC, pCmd->cid);
    3340         break;
    3341     }
    3342 
    3343     case SVGA_3D_CMD_CONTEXT_DESTROY:
    3344     {
    3345         SVGA3dCmdDestroyContext *pCmd = (SVGA3dCmdDestroyContext *)pvCmd;
    3346         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3347         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dContextDestroy);
    3348 
    3349         vmsvga3dContextDestroy(pThisCC, pCmd->cid);
    3350         break;
    3351     }
    3352 
    3353     case SVGA_3D_CMD_SETTRANSFORM:
    3354     {
    3355         SVGA3dCmdSetTransform *pCmd = (SVGA3dCmdSetTransform *)pvCmd;
    3356         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3357         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSetTransform);
    3358 
    3359         vmsvga3dSetTransform(pThisCC, pCmd->cid, pCmd->type, pCmd->matrix);
    3360         break;
    3361     }
    3362 
    3363     case SVGA_3D_CMD_SETZRANGE:
    3364     {
    3365         SVGA3dCmdSetZRange *pCmd = (SVGA3dCmdSetZRange *)pvCmd;
    3366         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3367         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSetZRange);
    3368 
    3369         vmsvga3dSetZRange(pThisCC, pCmd->cid, pCmd->zRange);
    3370         break;
    3371     }
    3372 
    3373     case SVGA_3D_CMD_SETRENDERSTATE:
    3374     {
    3375         SVGA3dCmdSetRenderState *pCmd = (SVGA3dCmdSetRenderState *)pvCmd;
    3376         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3377         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSetRenderState);
    3378 
    3379         uint32_t const cRenderStates = (cbCmd - sizeof(*pCmd)) / sizeof(SVGA3dRenderState);
    3380         vmsvga3dSetRenderState(pThisCC, pCmd->cid, cRenderStates, (SVGA3dRenderState *)(pCmd + 1));
    3381         break;
    3382     }
    3383 
    3384     case SVGA_3D_CMD_SETRENDERTARGET:
    3385     {
    3386         SVGA3dCmdSetRenderTarget *pCmd = (SVGA3dCmdSetRenderTarget *)pvCmd;
    3387         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3388         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSetRenderTarget);
    3389 
    3390         vmsvga3dSetRenderTarget(pThisCC, pCmd->cid, pCmd->type, pCmd->target);
    3391         break;
    3392     }
    3393 
    3394     case SVGA_3D_CMD_SETTEXTURESTATE:
    3395     {
    3396         SVGA3dCmdSetTextureState *pCmd = (SVGA3dCmdSetTextureState *)pvCmd;
    3397         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3398         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSetTextureState);
    3399 
    3400         uint32_t const cTextureStates = (cbCmd - sizeof(*pCmd)) / sizeof(SVGA3dTextureState);
    3401         vmsvga3dSetTextureState(pThisCC, pCmd->cid, cTextureStates, (SVGA3dTextureState *)(pCmd + 1));
    3402         break;
    3403     }
    3404 
    3405     case SVGA_3D_CMD_SETMATERIAL:
    3406     {
    3407         SVGA3dCmdSetMaterial *pCmd = (SVGA3dCmdSetMaterial *)pvCmd;
    3408         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3409         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSetMaterial);
    3410 
    3411         vmsvga3dSetMaterial(pThisCC, pCmd->cid, pCmd->face, &pCmd->material);
    3412         break;
    3413     }
    3414 
    3415     case SVGA_3D_CMD_SETLIGHTDATA:
    3416     {
    3417         SVGA3dCmdSetLightData *pCmd = (SVGA3dCmdSetLightData *)pvCmd;
    3418         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3419         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSetLightData);
    3420 
    3421         vmsvga3dSetLightData(pThisCC, pCmd->cid, pCmd->index, &pCmd->data);
    3422         break;
    3423     }
    3424 
    3425     case SVGA_3D_CMD_SETLIGHTENABLED:
    3426     {
    3427         SVGA3dCmdSetLightEnabled *pCmd = (SVGA3dCmdSetLightEnabled *)pvCmd;
    3428         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3429         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSetLightEnable);
    3430 
    3431         vmsvga3dSetLightEnabled(pThisCC, pCmd->cid, pCmd->index, pCmd->enabled);
    3432         break;
    3433     }
    3434 
    3435     case SVGA_3D_CMD_SETVIEWPORT:
    3436     {
    3437         SVGA3dCmdSetViewport *pCmd = (SVGA3dCmdSetViewport *)pvCmd;
    3438         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3439         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSetViewPort);
    3440 
    3441         vmsvga3dSetViewPort(pThisCC, pCmd->cid, &pCmd->rect);
    3442         break;
    3443     }
    3444 
    3445     case SVGA_3D_CMD_SETCLIPPLANE:
    3446     {
    3447         SVGA3dCmdSetClipPlane *pCmd = (SVGA3dCmdSetClipPlane *)pvCmd;
    3448         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3449         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSetClipPlane);
    3450 
    3451         vmsvga3dSetClipPlane(pThisCC, pCmd->cid, pCmd->index, pCmd->plane);
    3452         break;
    3453     }
    3454 
    3455     case SVGA_3D_CMD_CLEAR:
    3456     {
    3457         SVGA3dCmdClear  *pCmd = (SVGA3dCmdClear *)pvCmd;
    3458         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3459         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dClear);
    3460 
    3461         uint32_t const cRects = (cbCmd - sizeof(*pCmd)) / sizeof(SVGA3dRect);
    3462         vmsvga3dCommandClear(pThisCC, pCmd->cid, pCmd->clearFlag, pCmd->color, pCmd->depth, pCmd->stencil, cRects, (SVGA3dRect *)(pCmd + 1));
    3463         break;
    3464     }
    3465 
    3466     case SVGA_3D_CMD_PRESENT:
    3467     case SVGA_3D_CMD_PRESENT_READBACK: /** @todo SVGA_3D_CMD_PRESENT_READBACK isn't quite the same as present... */
    3468     {
    3469         SVGA3dCmdPresent *pCmd = (SVGA3dCmdPresent *)pvCmd;
    3470         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3471         if (enmCmdId == SVGA_3D_CMD_PRESENT)
    3472             STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dPresent);
    3473         else
    3474             STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dPresentReadBack);
    3475 
    3476         uint32_t const cRects = (cbCmd - sizeof(*pCmd)) / sizeof(SVGA3dCopyRect);
    3477         STAM_PROFILE_START(&pSvgaR3State->StatR3Cmd3dPresentProf, a);
    3478         vmsvga3dCommandPresent(pThis, pThisCC, pCmd->sid, cRects, (SVGA3dCopyRect *)(pCmd + 1));
    3479         STAM_PROFILE_STOP(&pSvgaR3State->StatR3Cmd3dPresentProf, a);
    3480         break;
    3481     }
    3482 
    3483     case SVGA_3D_CMD_SHADER_DEFINE:
    3484     {
    3485         SVGA3dCmdDefineShader *pCmd = (SVGA3dCmdDefineShader *)pvCmd;
    3486         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3487         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dShaderDefine);
    3488 
    3489         uint32_t const cbData = (cbCmd - sizeof(*pCmd));
    3490         vmsvga3dShaderDefine(pThisCC, pCmd->cid, pCmd->shid, pCmd->type, cbData, (uint32_t *)(pCmd + 1));
    3491         break;
    3492     }
    3493 
    3494     case SVGA_3D_CMD_SHADER_DESTROY:
    3495     {
    3496         SVGA3dCmdDestroyShader *pCmd = (SVGA3dCmdDestroyShader *)pvCmd;
    3497         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3498         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dShaderDestroy);
    3499 
    3500         vmsvga3dShaderDestroy(pThisCC, pCmd->cid, pCmd->shid, pCmd->type);
    3501         break;
    3502     }
    3503 
    3504     case SVGA_3D_CMD_SET_SHADER:
    3505     {
    3506         SVGA3dCmdSetShader *pCmd = (SVGA3dCmdSetShader *)pvCmd;
    3507         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3508         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSetShader);
    3509 
    3510         vmsvga3dShaderSet(pThisCC, NULL, pCmd->cid, pCmd->type, pCmd->shid);
    3511         break;
    3512     }
    3513 
    3514     case SVGA_3D_CMD_SET_SHADER_CONST:
    3515     {
    3516         SVGA3dCmdSetShaderConst *pCmd = (SVGA3dCmdSetShaderConst *)pvCmd;
    3517         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3518         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSetShaderConst);
    3519 
    3520         uint32_t const cRegisters = (cbCmd - sizeof(*pCmd)) / sizeof(pCmd->values) + 1;
    3521         vmsvga3dShaderSetConst(pThisCC, pCmd->cid, pCmd->reg, pCmd->type, pCmd->ctype, cRegisters, pCmd->values);
    3522         break;
    3523     }
    3524 
    3525     case SVGA_3D_CMD_DRAW_PRIMITIVES:
    3526     {
    3527         SVGA3dCmdDrawPrimitives *pCmd = (SVGA3dCmdDrawPrimitives *)pvCmd;
    3528         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3529         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dDrawPrimitives);
    3530 
    3531         ASSERT_GUEST_STMT_BREAK(pCmd->numRanges <= SVGA3D_MAX_DRAW_PRIMITIVE_RANGES, rcParse = VERR_INVALID_PARAMETER);
    3532         ASSERT_GUEST_STMT_BREAK(pCmd->numVertexDecls <= SVGA3D_MAX_VERTEX_ARRAYS, rcParse = VERR_INVALID_PARAMETER);
    3533         uint32_t const cbRangesAndVertexDecls = pCmd->numVertexDecls * sizeof(SVGA3dVertexDecl)
    3534                                               + pCmd->numRanges * sizeof(SVGA3dPrimitiveRange);
    3535         ASSERT_GUEST_STMT_BREAK(cbRangesAndVertexDecls <= cbCmd - sizeof(*pCmd), rcParse = VERR_INVALID_PARAMETER);
    3536 
    3537         uint32_t const cVertexDivisor = (cbCmd - sizeof(*pCmd) - cbRangesAndVertexDecls) / sizeof(uint32_t);
    3538         ASSERT_GUEST_STMT_BREAK(!cVertexDivisor || cVertexDivisor == pCmd->numVertexDecls, rcParse = VERR_INVALID_PARAMETER);
    3539         RT_UNTRUSTED_VALIDATED_FENCE();
    3540 
    3541         SVGA3dVertexDecl     *pVertexDecl    = (SVGA3dVertexDecl *)(pCmd + 1);
    3542         SVGA3dPrimitiveRange *pNumRange      = (SVGA3dPrimitiveRange *)&pVertexDecl[pCmd->numVertexDecls];
    3543         SVGA3dVertexDivisor  *pVertexDivisor = cVertexDivisor ? (SVGA3dVertexDivisor *)&pNumRange[pCmd->numRanges] : NULL;
    3544 
    3545         STAM_PROFILE_START(&pSvgaR3State->StatR3Cmd3dDrawPrimitivesProf, a);
    3546         vmsvga3dDrawPrimitives(pThisCC, pCmd->cid, pCmd->numVertexDecls, pVertexDecl, pCmd->numRanges,
    3547                                pNumRange, cVertexDivisor, pVertexDivisor);
    3548         STAM_PROFILE_STOP(&pSvgaR3State->StatR3Cmd3dDrawPrimitivesProf, a);
    3549         break;
    3550     }
    3551 
    3552     case SVGA_3D_CMD_SETSCISSORRECT:
    3553     {
    3554         SVGA3dCmdSetScissorRect *pCmd = (SVGA3dCmdSetScissorRect *)pvCmd;
    3555         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3556         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSetScissorRect);
    3557 
    3558         vmsvga3dSetScissorRect(pThisCC, pCmd->cid, &pCmd->rect);
    3559         break;
    3560     }
    3561 
    3562     case SVGA_3D_CMD_BEGIN_QUERY:
    3563     {
    3564         SVGA3dCmdBeginQuery *pCmd = (SVGA3dCmdBeginQuery *)pvCmd;
    3565         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3566         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dBeginQuery);
    3567 
    3568         vmsvga3dQueryBegin(pThisCC, pCmd->cid, pCmd->type);
    3569         break;
    3570     }
    3571 
    3572     case SVGA_3D_CMD_END_QUERY:
    3573     {
    3574         SVGA3dCmdEndQuery *pCmd = (SVGA3dCmdEndQuery *)pvCmd;
    3575         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3576         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dEndQuery);
    3577 
    3578         vmsvga3dQueryEnd(pThisCC, pCmd->cid, pCmd->type, pCmd->guestResult);
    3579         break;
    3580     }
    3581 
    3582     case SVGA_3D_CMD_WAIT_FOR_QUERY:
    3583     {
    3584         SVGA3dCmdWaitForQuery *pCmd = (SVGA3dCmdWaitForQuery *)pvCmd;
    3585         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3586         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dWaitForQuery);
    3587 
    3588         vmsvga3dQueryWait(pThis, pThisCC, pCmd->cid, pCmd->type, pCmd->guestResult);
    3589         break;
    3590     }
    3591 
    3592     case SVGA_3D_CMD_GENERATE_MIPMAPS:
    3593     {
    3594         SVGA3dCmdGenerateMipmaps *pCmd = (SVGA3dCmdGenerateMipmaps *)pvCmd;
    3595         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3596         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dGenerateMipmaps);
    3597 
    3598         vmsvga3dGenerateMipmaps(pThisCC, pCmd->sid, pCmd->filter);
    3599         break;
    3600     }
    3601 
    3602     case SVGA_3D_CMD_ACTIVATE_SURFACE:
    3603         /* context id + surface id? */
    3604         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dActivateSurface);
    3605         break;
    3606 
    3607     case SVGA_3D_CMD_DEACTIVATE_SURFACE:
    3608         /* context id + surface id? */
    3609         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dDeactivateSurface);
    3610         break;
    3611 
    3612     /*
    3613      *
    3614      * VPGU10: SVGA_CAP_GBOBJECTS+ commands.
    3615      *
    3616      */
    3617     case SVGA_3D_CMD_SCREEN_DMA:
    3618     {
    3619         SVGA3dCmdScreenDMA *pCmd = (SVGA3dCmdScreenDMA *)pvCmd;
    3620         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3621         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3622         break;
    3623     }
    3624 
    3625     case SVGA_3D_CMD_DEAD1:
    3626     case SVGA_3D_CMD_DEAD2:
    3627     {
    3628         VMSVGA_3D_CMD_NOTIMPL();
    3629         break;
    3630     }
    3631 
    3632     case SVGA_3D_CMD_LOGICOPS_BITBLT:
    3633     {
    3634         SVGA3dCmdLogicOpsBitBlt *pCmd = (SVGA3dCmdLogicOpsBitBlt *)pvCmd;
    3635         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3636         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3637         break;
    3638     }
    3639 
    3640     case SVGA_3D_CMD_LOGICOPS_TRANSBLT:
    3641     {
    3642         SVGA3dCmdLogicOpsTransBlt *pCmd = (SVGA3dCmdLogicOpsTransBlt *)pvCmd;
    3643         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3644         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3645         break;
    3646     }
    3647 
    3648     case SVGA_3D_CMD_LOGICOPS_STRETCHBLT:
    3649     {
    3650         SVGA3dCmdLogicOpsStretchBlt *pCmd = (SVGA3dCmdLogicOpsStretchBlt *)pvCmd;
    3651         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3652         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3653         break;
    3654     }
    3655 
    3656     case SVGA_3D_CMD_LOGICOPS_COLORFILL:
    3657     {
    3658         SVGA3dCmdLogicOpsColorFill *pCmd = (SVGA3dCmdLogicOpsColorFill *)pvCmd;
    3659         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3660         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3661         break;
    3662     }
    3663 
    3664     case SVGA_3D_CMD_LOGICOPS_ALPHABLEND:
    3665     {
    3666         SVGA3dCmdLogicOpsAlphaBlend *pCmd = (SVGA3dCmdLogicOpsAlphaBlend *)pvCmd;
    3667         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3668         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3669         break;
    3670     }
    3671 
    3672     case SVGA_3D_CMD_LOGICOPS_CLEARTYPEBLEND:
    3673     {
    3674         SVGA3dCmdLogicOpsClearTypeBlend *pCmd = (SVGA3dCmdLogicOpsClearTypeBlend *)pvCmd;
    3675         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3676         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3677         break;
    3678     }
    3679 
    3680     case SVGA_3D_CMD_SET_OTABLE_BASE:
    3681     {
    3682         SVGA3dCmdSetOTableBase *pCmd = (SVGA3dCmdSetOTableBase *)pvCmd;
    3683         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3684         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3685         break;
    3686     }
    3687 
    3688     case SVGA_3D_CMD_READBACK_OTABLE:
    3689     {
    3690         SVGA3dCmdReadbackOTable *pCmd = (SVGA3dCmdReadbackOTable *)pvCmd;
    3691         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3692         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3693         break;
    3694     }
    3695 
    3696     case SVGA_3D_CMD_DEFINE_GB_MOB:
    3697     {
    3698         SVGA3dCmdDefineGBMob *pCmd = (SVGA3dCmdDefineGBMob *)pvCmd;
    3699         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3700         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3701         break;
    3702     }
    3703 
    3704     case SVGA_3D_CMD_DESTROY_GB_MOB:
    3705     {
    3706         SVGA3dCmdDestroyGBMob *pCmd = (SVGA3dCmdDestroyGBMob *)pvCmd;
    3707         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3708         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3709         break;
    3710     }
    3711 
    3712     case SVGA_3D_CMD_DEAD3:
    3713     {
    3714         VMSVGA_3D_CMD_NOTIMPL();
    3715         break;
    3716     }
    3717 
    3718     case SVGA_3D_CMD_UPDATE_GB_MOB_MAPPING:
    3719     {
    3720         SVGA3dCmdUpdateGBMobMapping *pCmd = (SVGA3dCmdUpdateGBMobMapping *)pvCmd;
    3721         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3722         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3723         break;
    3724     }
    3725 
    3726     case SVGA_3D_CMD_DEFINE_GB_SURFACE:
    3727     {
    3728         SVGA3dCmdDefineGBSurface *pCmd = (SVGA3dCmdDefineGBSurface *)pvCmd;
    3729         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3730         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3731         break;
    3732     }
    3733 
    3734     case SVGA_3D_CMD_DESTROY_GB_SURFACE:
    3735     {
    3736         SVGA3dCmdDestroyGBSurface *pCmd = (SVGA3dCmdDestroyGBSurface *)pvCmd;
    3737         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3738         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3739         break;
    3740     }
    3741 
    3742     case SVGA_3D_CMD_BIND_GB_SURFACE:
    3743     {
    3744         SVGA3dCmdBindGBSurface *pCmd = (SVGA3dCmdBindGBSurface *)pvCmd;
    3745         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3746         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3747         break;
    3748     }
    3749 
    3750     case SVGA_3D_CMD_COND_BIND_GB_SURFACE:
    3751     {
    3752         SVGA3dCmdCondBindGBSurface *pCmd = (SVGA3dCmdCondBindGBSurface *)pvCmd;
    3753         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3754         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3755         break;
    3756     }
    3757 
    3758     case SVGA_3D_CMD_UPDATE_GB_IMAGE:
    3759     {
    3760         SVGA3dCmdUpdateGBImage *pCmd = (SVGA3dCmdUpdateGBImage *)pvCmd;
    3761         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3762         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3763         break;
    3764     }
    3765 
    3766     case SVGA_3D_CMD_UPDATE_GB_SURFACE:
    3767     {
    3768         SVGA3dCmdUpdateGBSurface *pCmd = (SVGA3dCmdUpdateGBSurface *)pvCmd;
    3769         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3770         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3771         break;
    3772     }
    3773 
    3774     case SVGA_3D_CMD_READBACK_GB_IMAGE:
    3775     {
    3776         SVGA3dCmdReadbackGBImage *pCmd = (SVGA3dCmdReadbackGBImage *)pvCmd;
    3777         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3778         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3779         break;
    3780     }
    3781 
    3782     case SVGA_3D_CMD_READBACK_GB_SURFACE:
    3783     {
    3784         SVGA3dCmdReadbackGBSurface *pCmd = (SVGA3dCmdReadbackGBSurface *)pvCmd;
    3785         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3786         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3787         break;
    3788     }
    3789 
    3790     case SVGA_3D_CMD_INVALIDATE_GB_IMAGE:
    3791     {
    3792         SVGA3dCmdInvalidateGBImage *pCmd = (SVGA3dCmdInvalidateGBImage *)pvCmd;
    3793         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3794         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3795         break;
    3796     }
    3797 
    3798     case SVGA_3D_CMD_INVALIDATE_GB_SURFACE:
    3799     {
    3800         SVGA3dCmdInvalidateGBSurface *pCmd = (SVGA3dCmdInvalidateGBSurface *)pvCmd;
    3801         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3802         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3803         break;
    3804     }
    3805 
    3806     case SVGA_3D_CMD_DEFINE_GB_CONTEXT:
    3807     {
    3808         SVGA3dCmdDefineGBContext *pCmd = (SVGA3dCmdDefineGBContext *)pvCmd;
    3809         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3810         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3811         break;
    3812     }
    3813 
    3814     case SVGA_3D_CMD_DESTROY_GB_CONTEXT:
    3815     {
    3816         SVGA3dCmdDestroyGBContext *pCmd = (SVGA3dCmdDestroyGBContext *)pvCmd;
    3817         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3818         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3819         break;
    3820     }
    3821 
    3822     case SVGA_3D_CMD_BIND_GB_CONTEXT:
    3823     {
    3824         SVGA3dCmdBindGBContext *pCmd = (SVGA3dCmdBindGBContext *)pvCmd;
    3825         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3826         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3827         break;
    3828     }
    3829 
    3830     case SVGA_3D_CMD_READBACK_GB_CONTEXT:
    3831     {
    3832         SVGA3dCmdReadbackGBContext *pCmd = (SVGA3dCmdReadbackGBContext *)pvCmd;
    3833         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3834         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3835         break;
    3836     }
    3837 
    3838     case SVGA_3D_CMD_INVALIDATE_GB_CONTEXT:
    3839     {
    3840         SVGA3dCmdInvalidateGBContext *pCmd = (SVGA3dCmdInvalidateGBContext *)pvCmd;
    3841         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3842         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3843         break;
    3844     }
    3845 
    3846     case SVGA_3D_CMD_DEFINE_GB_SHADER:
    3847     {
    3848         SVGA3dCmdDefineGBShader *pCmd = (SVGA3dCmdDefineGBShader *)pvCmd;
    3849         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3850         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3851         break;
    3852     }
    3853 
    3854     case SVGA_3D_CMD_DESTROY_GB_SHADER:
    3855     {
    3856         SVGA3dCmdDestroyGBShader *pCmd = (SVGA3dCmdDestroyGBShader *)pvCmd;
    3857         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3858         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3859         break;
    3860     }
    3861 
    3862     case SVGA_3D_CMD_BIND_GB_SHADER:
    3863     {
    3864         SVGA3dCmdBindGBShader *pCmd = (SVGA3dCmdBindGBShader *)pvCmd;
    3865         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3866         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3867         break;
    3868     }
    3869 
    3870     case SVGA_3D_CMD_SET_OTABLE_BASE64:
    3871     {
    3872         SVGA3dCmdSetOTableBase64 *pCmd = (SVGA3dCmdSetOTableBase64 *)pvCmd;
    3873         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3874         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3875         break;
    3876     }
    3877 
    3878     case SVGA_3D_CMD_BEGIN_GB_QUERY:
    3879     {
    3880         SVGA3dCmdBeginGBQuery *pCmd = (SVGA3dCmdBeginGBQuery *)pvCmd;
    3881         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3882         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3883         break;
    3884     }
    3885 
    3886     case SVGA_3D_CMD_END_GB_QUERY:
    3887     {
    3888         SVGA3dCmdEndGBQuery *pCmd = (SVGA3dCmdEndGBQuery *)pvCmd;
    3889         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3890         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3891         break;
    3892     }
    3893 
    3894     case SVGA_3D_CMD_WAIT_FOR_GB_QUERY:
    3895     {
    3896         SVGA3dCmdWaitForGBQuery *pCmd = (SVGA3dCmdWaitForGBQuery *)pvCmd;
    3897         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3898         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3899         break;
    3900     }
    3901 
    3902     case SVGA_3D_CMD_NOP:
    3903     {
    3904         /* Apparently there is nothing to do. */
    3905         break;
    3906     }
    3907 
    3908     case SVGA_3D_CMD_ENABLE_GART:
    3909     {
    3910         SVGA3dCmdEnableGart *pCmd = (SVGA3dCmdEnableGart *)pvCmd;
    3911         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3912         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3913         break;
    3914     }
    3915 
    3916     case SVGA_3D_CMD_DISABLE_GART:
    3917     {
    3918         /* No corresponding SVGA3dCmd structure. */
    3919         VMSVGA_3D_CMD_NOTIMPL();
    3920         break;
    3921     }
    3922 
    3923     case SVGA_3D_CMD_MAP_MOB_INTO_GART:
    3924     {
    3925         SVGA3dCmdMapMobIntoGart *pCmd = (SVGA3dCmdMapMobIntoGart *)pvCmd;
    3926         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3927         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3928         break;
    3929     }
    3930 
    3931     case SVGA_3D_CMD_UNMAP_GART_RANGE:
    3932     {
    3933         SVGA3dCmdUnmapGartRange *pCmd = (SVGA3dCmdUnmapGartRange *)pvCmd;
    3934         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3935         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3936         break;
    3937     }
    3938 
    3939     case SVGA_3D_CMD_DEFINE_GB_SCREENTARGET:
    3940     {
    3941         SVGA3dCmdDefineGBScreenTarget *pCmd = (SVGA3dCmdDefineGBScreenTarget *)pvCmd;
    3942         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3943         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3944         break;
    3945     }
    3946 
    3947     case SVGA_3D_CMD_DESTROY_GB_SCREENTARGET:
    3948     {
    3949         SVGA3dCmdDestroyGBScreenTarget *pCmd = (SVGA3dCmdDestroyGBScreenTarget *)pvCmd;
    3950         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3951         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3952         break;
    3953     }
    3954 
    3955     case SVGA_3D_CMD_BIND_GB_SCREENTARGET:
    3956     {
    3957         SVGA3dCmdBindGBScreenTarget *pCmd = (SVGA3dCmdBindGBScreenTarget *)pvCmd;
    3958         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3959         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3960         break;
    3961     }
    3962 
    3963     case SVGA_3D_CMD_UPDATE_GB_SCREENTARGET:
    3964     {
    3965         SVGA3dCmdUpdateGBScreenTarget *pCmd = (SVGA3dCmdUpdateGBScreenTarget *)pvCmd;
    3966         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3967         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3968         break;
    3969     }
    3970 
    3971     case SVGA_3D_CMD_READBACK_GB_IMAGE_PARTIAL:
    3972     {
    3973         SVGA3dCmdReadbackGBImagePartial *pCmd = (SVGA3dCmdReadbackGBImagePartial *)pvCmd;
    3974         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3975         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3976         break;
    3977     }
    3978 
    3979     case SVGA_3D_CMD_INVALIDATE_GB_IMAGE_PARTIAL:
    3980     {
    3981         SVGA3dCmdInvalidateGBImagePartial *pCmd = (SVGA3dCmdInvalidateGBImagePartial *)pvCmd;
    3982         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3983         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3984         break;
    3985     }
    3986 
    3987     case SVGA_3D_CMD_SET_GB_SHADERCONSTS_INLINE:
    3988     {
    3989         SVGA3dCmdSetGBShaderConstInline *pCmd = (SVGA3dCmdSetGBShaderConstInline *)pvCmd;
    3990         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3991         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3992         break;
    3993     }
    3994 
    3995     case SVGA_3D_CMD_GB_SCREEN_DMA:
    3996     {
    3997         SVGA3dCmdGBScreenDMA *pCmd = (SVGA3dCmdGBScreenDMA *)pvCmd;
    3998         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3999         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    4000         break;
    4001     }
    4002 
    4003     case SVGA_3D_CMD_BIND_GB_SURFACE_WITH_PITCH:
    4004     {
    4005         SVGA3dCmdBindGBSurfaceWithPitch *pCmd = (SVGA3dCmdBindGBSurfaceWithPitch *)pvCmd;
    4006         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    4007         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    4008         break;
    4009     }
    4010 
    4011     case SVGA_3D_CMD_GB_MOB_FENCE:
    4012     {
    4013         SVGA3dCmdGBMobFence *pCmd = (SVGA3dCmdGBMobFence *)pvCmd;
    4014         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    4015         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    4016         break;
    4017     }
    4018 
    4019     case SVGA_3D_CMD_DEFINE_GB_SURFACE_V2:
    4020     {
    4021         /// @todo SVGA3dCmdDefineGBSurface_v2 is not defined in Mesa 17 header. Mesa 20 has it.
    4022         //SVGA3dCmdDefineGBSurface_v2 *pCmd = (SVGA3dCmdDefineGBSurface_v2 *)pvCmd;
    4023         //VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    4024         VMSVGA_3D_CMD_NOTIMPL();
    4025         break;
    4026     }
    4027 
    4028     case SVGA_3D_CMD_DEFINE_GB_MOB64:
    4029     {
    4030         SVGA3dCmdDefineGBMob64 *pCmd = (SVGA3dCmdDefineGBMob64 *)pvCmd;
    4031         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    4032         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    4033         break;
    4034     }
    4035 
    4036     case SVGA_3D_CMD_REDEFINE_GB_MOB64:
    4037     {
    4038         SVGA3dCmdRedefineGBMob64 *pCmd = (SVGA3dCmdRedefineGBMob64 *)pvCmd;
    4039         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    4040         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    4041         break;
    4042     }
    4043 
    4044     case SVGA_3D_CMD_NOP_ERROR:
    4045     {
    4046         /* Apparently there is nothing to do. */
    4047         break;
    4048     }
    4049 
    4050     case SVGA_3D_CMD_SET_VERTEX_STREAMS:
    4051     {
    4052         SVGA3dCmdSetVertexStreams *pCmd = (SVGA3dCmdSetVertexStreams *)pvCmd;
    4053         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    4054         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    4055         break;
    4056     }
    4057 
    4058     case SVGA_3D_CMD_SET_VERTEX_DECLS:
    4059     {
    4060         SVGA3dCmdSetVertexDecls *pCmd = (SVGA3dCmdSetVertexDecls *)pvCmd;
    4061         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    4062         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    4063         break;
    4064     }
    4065 
    4066     case SVGA_3D_CMD_SET_VERTEX_DIVISORS:
    4067     {
    4068         SVGA3dCmdSetVertexDivisors *pCmd = (SVGA3dCmdSetVertexDivisors *)pvCmd;
    4069         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    4070         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    4071         break;
    4072     }
    4073 
    4074     case SVGA_3D_CMD_DRAW:
    4075     {
    4076         /* No corresponding SVGA3dCmd structure. */
    4077         VMSVGA_3D_CMD_NOTIMPL();
    4078         break;
    4079     }
    4080 
    4081     case SVGA_3D_CMD_DRAW_INDEXED:
    4082     {
    4083         /* No corresponding SVGA3dCmd structure. */
    4084         VMSVGA_3D_CMD_NOTIMPL();
    4085         break;
    4086     }
    4087 
    4088     default:
    4089         STAM_REL_COUNTER_INC(&pSvgaR3State->StatFifoUnkCmds);
    4090         ASSERT_GUEST_MSG_FAILED(("enmCmdId=%d\n", enmCmdId));
    4091         rcParse = VERR_NOT_IMPLEMENTED;
    4092         break;
    4093     }
    4094 
    4095     return rcParse;
    4096 }
    4097 #  undef VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK
    4098 # endif // VBOX_WITH_VMSVGA3D
    4099 
    4100 
    4101 /*
    4102  *
    4103  * Handlers for FIFO commands.
    4104  *
    4105  * Every handler takes the following parameters:
    4106  *
    4107  *    pThis               The shared VGA/VMSVGA state.
    4108  *    pThisCC             The VGA/VMSVGA state for ring-3.
    4109  *    pCmd                The command data.
    4110  */
    4111 
    4112 
    4113 /* SVGA_CMD_UPDATE */
    4114 static void vmsvgaR3CmdUpdate(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdUpdate const *pCmd)
    4115 {
    4116     RT_NOREF(pThis);
    4117     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    4118 
    4119     STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdUpdate);
    4120     Log(("SVGA_CMD_UPDATE %d,%d %dx%d\n", pCmd->x, pCmd->y, pCmd->width, pCmd->height));
    4121 
    4122     /** @todo Multiple screens? */
    4123     VMSVGASCREENOBJECT *pScreen = vmsvgaR3GetScreenObject(pThisCC, 0);
    4124     if (!pScreen) /* Can happen if screen is not defined (aScreens[idScreen].fDefined == false) yet. */
    4125         return;
    4126 
    4127     vmsvgaR3UpdateScreen(pThisCC, pScreen, pCmd->x, pCmd->y, pCmd->width, pCmd->height);
    4128 }
    4129 
    4130 
    4131 /* SVGA_CMD_UPDATE_VERBOSE */
    4132 static void vmsvgaR3CmdUpdateVerbose(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdUpdateVerbose const *pCmd)
    4133 {
    4134     RT_NOREF(pThis);
    4135     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    4136 
    4137     STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdUpdateVerbose);
    4138     Log(("SVGA_CMD_UPDATE_VERBOSE %d,%d %dx%d reason %#x\n", pCmd->x, pCmd->y, pCmd->width, pCmd->height, pCmd->reason));
    4139 
    4140     /** @todo Multiple screens? */
    4141     VMSVGASCREENOBJECT *pScreen = vmsvgaR3GetScreenObject(pThisCC, 0);
    4142     if (!pScreen) /* Can happen if screen is not defined (aScreens[idScreen].fDefined == false) yet. */
    4143         return;
    4144 
    4145     vmsvgaR3UpdateScreen(pThisCC, pScreen, pCmd->x, pCmd->y, pCmd->width, pCmd->height);
    4146 }
    4147 
    4148 
    4149 /* SVGA_CMD_RECT_FILL */
    4150 static void vmsvgaR3CmdRectFill(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdRectFill const *pCmd)
    4151 {
    4152     RT_NOREF(pThis, pCmd);
    4153     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    4154 
    4155     STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdRectFill);
    4156     Log(("SVGA_CMD_RECT_FILL %08X @ %d,%d (%dx%d)\n", pCmd->pixel, pCmd->destX, pCmd->destY, pCmd->width, pCmd->height));
    4157     LogRelMax(4, ("VMSVGA: Unsupported SVGA_CMD_RECT_FILL command ignored.\n"));
    4158 }
    4159 
    4160 
    4161 /* SVGA_CMD_RECT_COPY */
    4162 static void vmsvgaR3CmdRectCopy(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdRectCopy const *pCmd)
    4163 {
    4164     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    4165 
    4166     STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdRectCopy);
    4167     Log(("SVGA_CMD_RECT_COPY %d,%d -> %d,%d %dx%d\n", pCmd->srcX, pCmd->srcY, pCmd->destX, pCmd->destY, pCmd->width, pCmd->height));
    4168 
    4169     VMSVGASCREENOBJECT *pScreen = vmsvgaR3GetScreenObject(pThisCC, 0);
    4170     AssertPtrReturnVoid(pScreen);
    4171 
    4172     /* Check that arguments aren't complete junk. A precise check is done in vmsvgaR3RectCopy(). */
    4173     ASSERT_GUEST_RETURN_VOID(pCmd->srcX < pThis->svga.u32MaxWidth);
    4174     ASSERT_GUEST_RETURN_VOID(pCmd->destX < pThis->svga.u32MaxWidth);
    4175     ASSERT_GUEST_RETURN_VOID(pCmd->width < pThis->svga.u32MaxWidth);
    4176     ASSERT_GUEST_RETURN_VOID(pCmd->srcY < pThis->svga.u32MaxHeight);
    4177     ASSERT_GUEST_RETURN_VOID(pCmd->destY < pThis->svga.u32MaxHeight);
    4178     ASSERT_GUEST_RETURN_VOID(pCmd->height < pThis->svga.u32MaxHeight);
    4179 
    4180     vmsvgaR3RectCopy(pThisCC, pScreen, pCmd->srcX, pCmd->srcY, pCmd->destX, pCmd->destY,
    4181                      pCmd->width, pCmd->height, pThis->vram_size);
    4182     vmsvgaR3UpdateScreen(pThisCC, pScreen, pCmd->destX, pCmd->destY, pCmd->width, pCmd->height);
    4183 }
    4184 
    4185 
    4186 /* SVGA_CMD_RECT_ROP_COPY */
    4187 static void vmsvgaR3CmdRectRopCopy(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdRectRopCopy const *pCmd)
    4188 {
    4189     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    4190 
    4191     STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdRectRopCopy);
    4192     Log(("SVGA_CMD_RECT_ROP_COPY %d,%d -> %d,%d %dx%d ROP %#X\n", pCmd->srcX, pCmd->srcY, pCmd->destX, pCmd->destY, pCmd->width, pCmd->height, pCmd->rop));
    4193 
    4194     if (pCmd->rop != SVGA_ROP_COPY)
    4195     {
    4196         /* We only support the plain copy ROP which makes SVGA_CMD_RECT_ROP_COPY exactly the same
    4197          * as SVGA_CMD_RECT_COPY. XFree86 4.1.0 and 4.2.0 drivers (driver version 10.4.0 and 10.7.0,
    4198          * respectively) issue SVGA_CMD_RECT_ROP_COPY when SVGA_CAP_RECT_COPY is present even when
    4199          * SVGA_CAP_RASTER_OP is not. However, the ROP will always be SVGA_ROP_COPY.
    4200          */
    4201         LogRelMax(4, ("VMSVGA: SVGA_CMD_RECT_ROP_COPY %d,%d -> %d,%d (%dx%d) ROP %X unsupported\n",
    4202                       pCmd->srcX, pCmd->srcY, pCmd->destX, pCmd->destY, pCmd->width, pCmd->height, pCmd->rop));
    4203         return;
    4204     }
    4205 
    4206     VMSVGASCREENOBJECT *pScreen = vmsvgaR3GetScreenObject(pThisCC, 0);
    4207     AssertPtrReturnVoid(pScreen);
    4208 
    4209     /* Check that arguments aren't complete junk. A precise check is done in vmsvgaR3RectCopy(). */
    4210     ASSERT_GUEST_RETURN_VOID(pCmd->srcX < pThis->svga.u32MaxWidth);
    4211     ASSERT_GUEST_RETURN_VOID(pCmd->destX < pThis->svga.u32MaxWidth);
    4212     ASSERT_GUEST_RETURN_VOID(pCmd->width < pThis->svga.u32MaxWidth);
    4213     ASSERT_GUEST_RETURN_VOID(pCmd->srcY < pThis->svga.u32MaxHeight);
    4214     ASSERT_GUEST_RETURN_VOID(pCmd->destY < pThis->svga.u32MaxHeight);
    4215     ASSERT_GUEST_RETURN_VOID(pCmd->height < pThis->svga.u32MaxHeight);
    4216 
    4217     vmsvgaR3RectCopy(pThisCC, pScreen, pCmd->srcX, pCmd->srcY, pCmd->destX, pCmd->destY,
    4218                      pCmd->width, pCmd->height, pThis->vram_size);
    4219     vmsvgaR3UpdateScreen(pThisCC, pScreen, pCmd->destX, pCmd->destY, pCmd->width, pCmd->height);
    4220 }
    4221 
    4222 
    4223 /* SVGA_CMD_DISPLAY_CURSOR */
    4224 static void vmsvgaR3CmdDisplayCursor(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDisplayCursor const *pCmd)
    4225 {
    4226     RT_NOREF(pThis, pCmd);
    4227     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    4228 
    4229     STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdDisplayCursor);
    4230     Log(("SVGA_CMD_DISPLAY_CURSOR id=%d state=%d\n", pCmd->id, pCmd->state));
    4231     LogRelMax(4, ("VMSVGA: Unsupported SVGA_CMD_DISPLAY_CURSOR command ignored.\n"));
    4232 }
    4233 
    4234 
    4235 /* SVGA_CMD_MOVE_CURSOR */
    4236 static void vmsvgaR3CmdMoveCursor(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdMoveCursor const *pCmd)
    4237 {
    4238     RT_NOREF(pThis, pCmd);
    4239     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    4240 
    4241     STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdMoveCursor);
    4242     Log(("SVGA_CMD_MOVE_CURSOR to %d,%d\n", pCmd->pos.x, pCmd->pos.y));
    4243     LogRelMax(4, ("VMSVGA: Unsupported SVGA_CMD_MOVE_CURSOR command ignored.\n"));
    4244 }
    4245 
    4246 
    4247 /* SVGA_CMD_DEFINE_CURSOR */
    4248 static void vmsvgaR3CmdDefineCursor(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineCursor const *pCmd)
    4249 {
    4250     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    4251 
    4252     STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdDefineCursor);
    4253     Log(("SVGA_CMD_DEFINE_CURSOR id=%d size (%dx%d) hotspot (%d,%d) andMaskDepth=%d xorMaskDepth=%d\n",
    4254              pCmd->id, pCmd->width, pCmd->height, pCmd->hotspotX, pCmd->hotspotY, pCmd->andMaskDepth, pCmd->xorMaskDepth));
    4255 
    4256     ASSERT_GUEST_RETURN_VOID(pCmd->height < 2048 && pCmd->width < 2048);
    4257     ASSERT_GUEST_RETURN_VOID(pCmd->andMaskDepth <= 32);
    4258     ASSERT_GUEST_RETURN_VOID(pCmd->xorMaskDepth <= 32);
    4259     RT_UNTRUSTED_VALIDATED_FENCE();
    4260 
    4261     uint32_t const cbSrcAndLine = RT_ALIGN_32(pCmd->width * (pCmd->andMaskDepth + (pCmd->andMaskDepth == 15)), 32) / 8;
    4262     uint32_t const cbSrcAndMask = cbSrcAndLine * pCmd->height;
    4263     uint32_t const cbSrcXorLine = RT_ALIGN_32(pCmd->width * (pCmd->xorMaskDepth + (pCmd->xorMaskDepth == 15)), 32) / 8;
    4264 
    4265     uint8_t const *pbSrcAndMask = (uint8_t const *)(pCmd + 1);
    4266     uint8_t const *pbSrcXorMask = (uint8_t const *)(pCmd + 1) + cbSrcAndMask;
    4267 
    4268     uint32_t const cx = pCmd->width;
    4269     uint32_t const cy = pCmd->height;
    4270 
    4271     /*
    4272      * Convert the input to 1-bit AND mask and a 32-bit BRGA XOR mask.
    4273      * The AND data uses 8-bit aligned scanlines.
    4274      * The XOR data must be starting on a 32-bit boundrary.
    4275      */
    4276     uint32_t cbDstAndLine = RT_ALIGN_32(cx, 8) / 8;
    4277     uint32_t cbDstAndMask = cbDstAndLine          * cy;
    4278     uint32_t cbDstXorMask = cx * sizeof(uint32_t) * cy;
    4279     uint32_t cbCopy = RT_ALIGN_32(cbDstAndMask, 4) + cbDstXorMask;
    4280 
    4281     uint8_t *pbCopy = (uint8_t *)RTMemAlloc(cbCopy);
    4282     AssertReturnVoid(pbCopy);
    4283 
    4284     /* Convert the AND mask. */
    4285     uint8_t       *pbDst     = pbCopy;
    4286     uint8_t const *pbSrc     = pbSrcAndMask;
    4287     switch (pCmd->andMaskDepth)
    4288     {
    4289         case 1:
    4290             if (cbSrcAndLine == cbDstAndLine)
    4291                 memcpy(pbDst, pbSrc, cbSrcAndLine * cy);
    4292             else
    4293             {
    4294                 Assert(cbSrcAndLine > cbDstAndLine); /* lines are dword alined in source, but only byte in destination. */
    4295                 for (uint32_t y = 0; y < cy; y++)
    4296                 {
    4297                     memcpy(pbDst, pbSrc, cbDstAndLine);
    4298                     pbDst += cbDstAndLine;
    4299                     pbSrc += cbSrcAndLine;
    4300                 }
    4301             }
    4302             break;
    4303         /* Should take the XOR mask into account for the multi-bit AND mask. */
    4304         case 8:
    4305             for (uint32_t y = 0; y < cy; y++)
    4306             {
    4307                 for (uint32_t x = 0; x < cx; )
    4308                 {
    4309                     uint8_t bDst = 0;
    4310                     uint8_t fBit = 0x80;
    4311                     do
    4312                     {
    4313                         uintptr_t const idxPal = pbSrc[x] * 3;
    4314                         if (((   pThis->last_palette[idxPal]
    4315                               | (pThis->last_palette[idxPal] >>  8)
    4316                               | (pThis->last_palette[idxPal] >> 16)) & 0xff) > 0xfc)
    4317                             bDst |= fBit;
    4318                         fBit >>= 1;
    4319                         x++;
    4320                     } while (x < cx && (x & 7));
    4321                     pbDst[(x - 1) / 8] = bDst;
    4322                 }
    4323                 pbDst += cbDstAndLine;
    4324                 pbSrc += cbSrcAndLine;
    4325             }
    4326             break;
    4327         case 15:
    4328             for (uint32_t y = 0; y < cy; y++)
    4329             {
    4330                 for (uint32_t x = 0; x < cx; )
    4331                 {
    4332                     uint8_t bDst = 0;
    4333                     uint8_t fBit = 0x80;
    4334                     do
    4335                     {
    4336                         if ((pbSrc[x * 2] | (pbSrc[x * 2 + 1] & 0x7f)) >= 0xfc)
    4337                             bDst |= fBit;
    4338                         fBit >>= 1;
    4339                         x++;
    4340                     } while (x < cx && (x & 7));
    4341                     pbDst[(x - 1) / 8] = bDst;
    4342                 }
    4343                 pbDst += cbDstAndLine;
    4344                 pbSrc += cbSrcAndLine;
    4345             }
    4346             break;
    4347         case 16:
    4348             for (uint32_t y = 0; y < cy; y++)
    4349             {
    4350                 for (uint32_t x = 0; x < cx; )
    4351                 {
    4352                     uint8_t bDst = 0;
    4353                     uint8_t fBit = 0x80;
    4354                     do
    4355                     {
    4356                         if ((pbSrc[x * 2] | pbSrc[x * 2 + 1]) >= 0xfc)
    4357                             bDst |= fBit;
    4358                         fBit >>= 1;
    4359                         x++;
    4360                     } while (x < cx && (x & 7));
    4361                     pbDst[(x - 1) / 8] = bDst;
    4362                 }
    4363                 pbDst += cbDstAndLine;
    4364                 pbSrc += cbSrcAndLine;
    4365             }
    4366             break;
    4367         case 24:
    4368             for (uint32_t y = 0; y < cy; y++)
    4369             {
    4370                 for (uint32_t x = 0; x < cx; )
    4371                 {
    4372                     uint8_t bDst = 0;
    4373                     uint8_t fBit = 0x80;
    4374                     do
    4375                     {
    4376                         if ((pbSrc[x * 3] | pbSrc[x * 3 + 1] | pbSrc[x * 3 + 2]) >= 0xfc)
    4377                             bDst |= fBit;
    4378                         fBit >>= 1;
    4379                         x++;
    4380                     } while (x < cx && (x & 7));
    4381                     pbDst[(x - 1) / 8] = bDst;
    4382                 }
    4383                 pbDst += cbDstAndLine;
    4384                 pbSrc += cbSrcAndLine;
    4385             }
    4386             break;
    4387         case 32:
    4388             for (uint32_t y = 0; y < cy; y++)
    4389             {
    4390                 for (uint32_t x = 0; x < cx; )
    4391                 {
    4392                     uint8_t bDst = 0;
    4393                     uint8_t fBit = 0x80;
    4394                     do
    4395                     {
    4396                         if ((pbSrc[x * 4] | pbSrc[x * 4 + 1] | pbSrc[x * 4 + 2] | pbSrc[x * 4 + 3]) >= 0xfc)
    4397                             bDst |= fBit;
    4398                         fBit >>= 1;
    4399                         x++;
    4400                     } while (x < cx && (x & 7));
    4401                     pbDst[(x - 1) / 8] = bDst;
    4402                 }
    4403                 pbDst += cbDstAndLine;
    4404                 pbSrc += cbSrcAndLine;
    4405             }
    4406             break;
    4407         default:
    4408             RTMemFreeZ(pbCopy, cbCopy);
    4409             AssertFailedReturnVoid();
    4410     }
    4411 
    4412     /* Convert the XOR mask. */
    4413     uint32_t *pu32Dst = (uint32_t *)(pbCopy + RT_ALIGN_32(cbDstAndMask, 4));
    4414     pbSrc  = pbSrcXorMask;
    4415     switch (pCmd->xorMaskDepth)
    4416     {
    4417         case 1:
    4418             for (uint32_t y = 0; y < cy; y++)
    4419             {
    4420                 for (uint32_t x = 0; x < cx; )
    4421                 {
    4422                     /* most significant bit is the left most one. */
    4423                     uint8_t bSrc = pbSrc[x / 8];
    4424                     do
    4425                     {
    4426                         *pu32Dst++ = bSrc & 0x80 ? UINT32_C(0x00ffffff) : 0;
    4427                         bSrc <<= 1;
    4428                         x++;
    4429                     } while ((x & 7) && x < cx);
    4430                 }
    4431                 pbSrc += cbSrcXorLine;
    4432             }
    4433             break;
    4434         case 8:
    4435             for (uint32_t y = 0; y < cy; y++)
    4436             {
    4437                 for (uint32_t x = 0; x < cx; x++)
    4438                 {
    4439                     uint32_t u = pThis->last_palette[pbSrc[x]];
    4440                     *pu32Dst++ = u;//RT_MAKE_U32_FROM_U8(RT_BYTE1(u), RT_BYTE2(u), RT_BYTE3(u), 0);
    4441                 }
    4442                 pbSrc += cbSrcXorLine;
    4443             }
    4444             break;
    4445         case 15: /* Src: RGB-5-5-5 */
    4446             for (uint32_t y = 0; y < cy; y++)
    4447             {
    4448                 for (uint32_t x = 0; x < cx; x++)
    4449                 {
    4450                     uint32_t const uValue = RT_MAKE_U16(pbSrc[x * 2], pbSrc[x * 2 + 1]);
    4451                     *pu32Dst++ = RT_MAKE_U32_FROM_U8(( uValue        & 0x1f) << 3,
    4452                                                      ((uValue >>  5) & 0x1f) << 3,
    4453                                                      ((uValue >> 10) & 0x1f) << 3, 0);
    4454                 }
    4455                 pbSrc += cbSrcXorLine;
    4456             }
    4457             break;
    4458         case 16: /* Src: RGB-5-6-5 */
    4459             for (uint32_t y = 0; y < cy; y++)
    4460             {
    4461                 for (uint32_t x = 0; x < cx; x++)
    4462                 {
    4463                     uint32_t const uValue = RT_MAKE_U16(pbSrc[x * 2], pbSrc[x * 2 + 1]);
    4464                     *pu32Dst++ = RT_MAKE_U32_FROM_U8(( uValue        & 0x1f) << 3,
    4465                                                      ((uValue >>  5) & 0x3f) << 2,
    4466                                                      ((uValue >> 11) & 0x1f) << 3, 0);
    4467                 }
    4468                 pbSrc += cbSrcXorLine;
    4469             }
    4470             break;
    4471         case 24:
    4472             for (uint32_t y = 0; y < cy; y++)
    4473             {
    4474                 for (uint32_t x = 0; x < cx; x++)
    4475                     *pu32Dst++ = RT_MAKE_U32_FROM_U8(pbSrc[x*3], pbSrc[x*3 + 1], pbSrc[x*3 + 2], 0);
    4476                 pbSrc += cbSrcXorLine;
    4477             }
    4478             break;
    4479         case 32:
    4480             for (uint32_t y = 0; y < cy; y++)
    4481             {
    4482                 for (uint32_t x = 0; x < cx; x++)
    4483                     *pu32Dst++ = RT_MAKE_U32_FROM_U8(pbSrc[x*4], pbSrc[x*4 + 1], pbSrc[x*4 + 2], 0);
    4484                 pbSrc += cbSrcXorLine;
    4485             }
    4486             break;
    4487         default:
    4488             RTMemFreeZ(pbCopy, cbCopy);
    4489             AssertFailedReturnVoid();
    4490     }
    4491 
    4492     /*
    4493      * Pass it to the frontend/whatever.
    4494      */
    4495     vmsvgaR3InstallNewCursor(pThisCC, pSvgaR3State, false /*fAlpha*/, pCmd->hotspotX, pCmd->hotspotY,
    4496                              cx, cy, pbCopy, cbCopy);
    4497 }
    4498 
    4499 
    4500 /* SVGA_CMD_DEFINE_ALPHA_CURSOR */
    4501 static void vmsvgaR3CmdDefineAlphaCursor(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineAlphaCursor const *pCmd)
    4502 {
    4503     RT_NOREF(pThis);
    4504     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    4505 
    4506     STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdDefineAlphaCursor);
    4507     Log(("VMSVGA cmd: SVGA_CMD_DEFINE_ALPHA_CURSOR id=%d size (%dx%d) hotspot (%d,%d)\n", pCmd->id, pCmd->width, pCmd->height, pCmd->hotspotX, pCmd->hotspotY));
    4508 
    4509     /* Check against a reasonable upper limit to prevent integer overflows in the sanity checks below. */
    4510     ASSERT_GUEST_RETURN_VOID(pCmd->height < 2048 && pCmd->width < 2048);
    4511     RT_UNTRUSTED_VALIDATED_FENCE();
    4512 
    4513     /* The mouse pointer interface always expects an AND mask followed by the color data (XOR mask). */
    4514     uint32_t cbAndMask     = (pCmd->width + 7) / 8 * pCmd->height;          /* size of the AND mask */
    4515     cbAndMask              = ((cbAndMask + 3) & ~3);                        /* + gap for alignment */
    4516     uint32_t cbXorMask     = pCmd->width * sizeof(uint32_t) * pCmd->height; /* + size of the XOR mask (32-bit BRGA format) */
    4517     uint32_t cbCursorShape = cbAndMask + cbXorMask;
    4518 
    4519     uint8_t *pCursorCopy = (uint8_t *)RTMemAlloc(cbCursorShape);
    4520     AssertPtrReturnVoid(pCursorCopy);
    4521 
    4522     /* Transparency is defined by the alpha bytes, so make the whole bitmap visible. */
    4523     memset(pCursorCopy, 0xff, cbAndMask);
    4524     /* Colour data */
    4525     memcpy(pCursorCopy + cbAndMask, pCmd + 1, cbXorMask);
    4526 
    4527     vmsvgaR3InstallNewCursor(pThisCC, pSvgaR3State, true /*fAlpha*/, pCmd->hotspotX, pCmd->hotspotY,
    4528                              pCmd->width, pCmd->height, pCursorCopy, cbCursorShape);
    4529 }
    4530 
    4531 
    4532 /* SVGA_CMD_ESCAPE */
    4533 static void vmsvgaR3CmdEscape(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdEscape const *pCmd)
    4534 {
    4535     RT_NOREF(pThis);
    4536     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    4537 
    4538     STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdEscape);
    4539 
    4540     if (pCmd->nsid == SVGA_ESCAPE_NSID_VMWARE)
    4541     {
    4542         ASSERT_GUEST_RETURN_VOID(pCmd->size >= sizeof(uint32_t));
    4543         RT_UNTRUSTED_VALIDATED_FENCE();
    4544 
    4545         uint32_t const cmd = *(uint32_t *)(pCmd + 1);
    4546         Log(("SVGA_CMD_ESCAPE (%#x %#x) VMWARE cmd=%#x\n", pCmd->nsid, pCmd->size, cmd));
    4547 
    4548         switch (cmd)
    4549         {
    4550             case SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS:
    4551             {
    4552                 SVGAEscapeVideoSetRegs *pVideoCmd = (SVGAEscapeVideoSetRegs *)(pCmd + 1);
    4553                 ASSERT_GUEST_RETURN_VOID(pCmd->size >= sizeof(pVideoCmd->header));
    4554                 RT_UNTRUSTED_VALIDATED_FENCE();
    4555 
    4556                 uint32_t const cRegs = (pCmd->size - sizeof(pVideoCmd->header)) / sizeof(pVideoCmd->items[0]);
    4557 
    4558                 Log(("SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS: stream %#x\n", pVideoCmd->header.streamId));
    4559                 for (uint32_t iReg = 0; iReg < cRegs; iReg++)
    4560                     Log(("SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS: reg %#x val %#x\n", pVideoCmd->items[iReg].registerId, pVideoCmd->items[iReg].value));
    4561                 RT_NOREF_PV(pVideoCmd);
    4562                 break;
    4563             }
    4564 
    4565             case SVGA_ESCAPE_VMWARE_VIDEO_FLUSH:
    4566             {
    4567                 SVGAEscapeVideoFlush *pVideoCmd = (SVGAEscapeVideoFlush *)(pCmd + 1);
    4568                 ASSERT_GUEST_RETURN_VOID(pCmd->size >= sizeof(*pVideoCmd));
    4569                 Log(("SVGA_ESCAPE_VMWARE_VIDEO_FLUSH: stream %#x\n", pVideoCmd->streamId));
    4570                 RT_NOREF_PV(pVideoCmd);
    4571                 break;
    4572             }
    4573 
    4574             default:
    4575                 Log(("SVGA_CMD_ESCAPE: Unknown vmware escape: %#x\n", cmd));
    4576                 break;
    4577         }
    4578     }
    4579     else
    4580         Log(("SVGA_CMD_ESCAPE %#x %#x\n", pCmd->nsid, pCmd->size));
    4581 }
    4582 
    4583 
    4584 /* SVGA_CMD_DEFINE_SCREEN */
    4585 static void vmsvgaR3CmdDefineScreen(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineScreen const *pCmd)
    4586 {
    4587     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    4588 
    4589     STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdDefineScreen);
    4590     Log(("SVGA_CMD_DEFINE_SCREEN id=%x flags=%x size=(%d,%d) root=(%d,%d) %d:0x%x 0x%x\n",
    4591              pCmd->screen.id, pCmd->screen.flags, pCmd->screen.size.width, pCmd->screen.size.height, pCmd->screen.root.x, pCmd->screen.root.y,
    4592              pCmd->screen.backingStore.ptr.gmrId, pCmd->screen.backingStore.ptr.offset, pCmd->screen.backingStore.pitch));
    4593 
    4594     uint32_t const idScreen = pCmd->screen.id;
    4595     ASSERT_GUEST_RETURN_VOID(idScreen < RT_ELEMENTS(pSvgaR3State->aScreens));
    4596 
    4597     uint32_t const uWidth = pCmd->screen.size.width;
    4598     ASSERT_GUEST_RETURN_VOID(uWidth <= pThis->svga.u32MaxWidth);
    4599 
    4600     uint32_t const uHeight = pCmd->screen.size.height;
    4601     ASSERT_GUEST_RETURN_VOID(uHeight <= pThis->svga.u32MaxHeight);
    4602 
    4603     uint32_t const cbWidth = uWidth * ((32 + 7) / 8); /** @todo 32? */
    4604     uint32_t const cbPitch = pCmd->screen.backingStore.pitch ? pCmd->screen.backingStore.pitch : cbWidth;
    4605     ASSERT_GUEST_RETURN_VOID(cbWidth <= cbPitch);
    4606 
    4607     uint32_t const uScreenOffset = pCmd->screen.backingStore.ptr.offset;
    4608     ASSERT_GUEST_RETURN_VOID(uScreenOffset < pThis->vram_size);
    4609 
    4610     uint32_t const cbVram = pThis->vram_size - uScreenOffset;
    4611     /* If we have a not zero pitch, then height can't exceed the available VRAM. */
    4612     ASSERT_GUEST_RETURN_VOID(   (uHeight == 0 && cbPitch == 0)
    4613                              || (cbPitch > 0 && uHeight <= cbVram / cbPitch));
    4614     RT_UNTRUSTED_VALIDATED_FENCE();
    4615 
    4616     VMSVGASCREENOBJECT *pScreen = &pSvgaR3State->aScreens[idScreen];
    4617     pScreen->fDefined  = true;
    4618     pScreen->fModified = true;
    4619     pScreen->fuScreen  = pCmd->screen.flags;
    4620     pScreen->idScreen  = idScreen;
    4621     if (!RT_BOOL(pCmd->screen.flags & (SVGA_SCREEN_DEACTIVATE | SVGA_SCREEN_BLANKING)))
    4622     {
    4623         /* Not blanked. */
    4624         ASSERT_GUEST_RETURN_VOID(uWidth > 0 && uHeight > 0);
    4625         RT_UNTRUSTED_VALIDATED_FENCE();
    4626 
    4627         pScreen->xOrigin = pCmd->screen.root.x;
    4628         pScreen->yOrigin = pCmd->screen.root.y;
    4629         pScreen->cWidth  = uWidth;
    4630         pScreen->cHeight = uHeight;
    4631         pScreen->offVRAM = uScreenOffset;
    4632         pScreen->cbPitch = cbPitch;
    4633         pScreen->cBpp    = 32;
    4634     }
    4635     else
    4636     {
    4637         /* Screen blanked. Keep old values. */
    4638     }
    4639 
    4640     pThis->svga.fGFBRegisters = false;
    4641     vmsvgaR3ChangeMode(pThis, pThisCC);
    4642 
    4643 # ifdef VBOX_WITH_VMSVGA3D
    4644     if (RT_LIKELY(pThis->svga.f3DEnabled))
    4645         vmsvga3dDefineScreen(pThis, pThisCC, pScreen);
    4646 # endif
    4647 }
    4648 
    4649 
    4650 /* SVGA_CMD_DESTROY_SCREEN */
    4651 static void vmsvgaR3CmdDestroyScreen(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDestroyScreen const *pCmd)
    4652 {
    4653     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    4654 
    4655     STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdDestroyScreen);
    4656     Log(("SVGA_CMD_DESTROY_SCREEN id=%x\n", pCmd->screenId));
    4657 
    4658     uint32_t const idScreen = pCmd->screenId;
    4659     ASSERT_GUEST_RETURN_VOID(idScreen < RT_ELEMENTS(pSvgaR3State->aScreens));
    4660     RT_UNTRUSTED_VALIDATED_FENCE();
    4661 
    4662     VMSVGASCREENOBJECT *pScreen = &pSvgaR3State->aScreens[idScreen];
    4663     pScreen->fModified = true;
    4664     pScreen->fDefined  = false;
    4665     pScreen->idScreen  = idScreen;
    4666 
    4667 # ifdef VBOX_WITH_VMSVGA3D
    4668     if (RT_LIKELY(pThis->svga.f3DEnabled))
    4669         vmsvga3dDestroyScreen(pThisCC, pScreen);
    4670 # endif
    4671     vmsvgaR3ChangeMode(pThis, pThisCC);
    4672 }
    4673 
    4674 
    4675 /* SVGA_CMD_DEFINE_GMRFB */
    4676 static void vmsvgaR3CmdDefineGMRFB(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineGMRFB const *pCmd)
    4677 {
    4678     RT_NOREF(pThis);
    4679     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    4680 
    4681     STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdDefineGmrFb);
    4682     Log(("SVGA_CMD_DEFINE_GMRFB gmr=%x offset=%x bytesPerLine=%x bpp=%d color depth=%d\n",
    4683              pCmd->ptr.gmrId, pCmd->ptr.offset, pCmd->bytesPerLine, pCmd->format.bitsPerPixel, pCmd->format.colorDepth));
    4684 
    4685     pSvgaR3State->GMRFB.ptr          = pCmd->ptr;
    4686     pSvgaR3State->GMRFB.bytesPerLine = pCmd->bytesPerLine;
    4687     pSvgaR3State->GMRFB.format       = pCmd->format;
    4688 }
    4689 
    4690 
    4691 /* SVGA_CMD_BLIT_GMRFB_TO_SCREEN */
    4692 static void vmsvgaR3CmdBlitGMRFBToScreen(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdBlitGMRFBToScreen const *pCmd)
    4693 {
    4694     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    4695 
    4696     STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdBlitGmrFbToScreen);
    4697     Log(("SVGA_CMD_BLIT_GMRFB_TO_SCREEN src=(%d,%d) dest id=%d (%d,%d)(%d,%d)\n",
    4698              pCmd->srcOrigin.x, pCmd->srcOrigin.y, pCmd->destScreenId, pCmd->destRect.left, pCmd->destRect.top, pCmd->destRect.right, pCmd->destRect.bottom));
    4699 
    4700     ASSERT_GUEST_RETURN_VOID(pCmd->destScreenId < RT_ELEMENTS(pSvgaR3State->aScreens));
    4701     RT_UNTRUSTED_VALIDATED_FENCE();
    4702 
    4703     VMSVGASCREENOBJECT *pScreen = vmsvgaR3GetScreenObject(pThisCC, pCmd->destScreenId);
    4704     AssertPtrReturnVoid(pScreen);
    4705 
    4706     /** @todo Support GMRFB.format.s.bitsPerPixel != pThis->svga.uBpp ?  */
    4707     AssertReturnVoid(pSvgaR3State->GMRFB.format.bitsPerPixel == pScreen->cBpp);
    4708 
    4709     /* Clip destRect to the screen dimensions. */
    4710     SVGASignedRect screenRect;
    4711     screenRect.left   = 0;
    4712     screenRect.top    = 0;
    4713     screenRect.right  = pScreen->cWidth;
    4714     screenRect.bottom = pScreen->cHeight;
    4715     SVGASignedRect clipRect = pCmd->destRect;
    4716     vmsvgaR3ClipRect(&screenRect, &clipRect);
    4717     RT_UNTRUSTED_VALIDATED_FENCE();
    4718 
    4719     uint32_t const width  = clipRect.right - clipRect.left;
    4720     uint32_t const height = clipRect.bottom - clipRect.top;
    4721 
    4722     if (   width == 0
    4723         || height == 0)
    4724         return;  /* Nothing to do. */
    4725 
    4726     int32_t const srcx = pCmd->srcOrigin.x + (clipRect.left - pCmd->destRect.left);
    4727     int32_t const srcy = pCmd->srcOrigin.y + (clipRect.top - pCmd->destRect.top);
    4728 
    4729     /* Copy the defined by GMRFB image to the screen 0 VRAM area.
    4730      * Prepare parameters for vmsvgaR3GmrTransfer.
    4731      */
    4732     AssertReturnVoid(pScreen->offVRAM < pThis->vram_size); /* Paranoia. Ensured by SVGA_CMD_DEFINE_SCREEN. */
    4733 
    4734     /* Destination: host buffer which describes the screen 0 VRAM.
    4735      * Important are pbHstBuf and cbHstBuf. offHst and cbHstPitch are verified by vmsvgaR3GmrTransfer.
    4736      */
    4737     uint8_t * const pbHstBuf = (uint8_t *)pThisCC->pbVRam + pScreen->offVRAM;
    4738     uint32_t const cbScanline = pScreen->cbPitch ? pScreen->cbPitch :
    4739                                                    width * (RT_ALIGN(pScreen->cBpp, 8) / 8);
    4740     uint32_t cbHstBuf = cbScanline * pScreen->cHeight;
    4741     if (cbHstBuf > pThis->vram_size - pScreen->offVRAM)
    4742        cbHstBuf = pThis->vram_size - pScreen->offVRAM; /* Paranoia. */
    4743     uint32_t const offHst =   (clipRect.left * RT_ALIGN(pScreen->cBpp, 8)) / 8
    4744                             + cbScanline * clipRect.top;
    4745     int32_t const cbHstPitch = cbScanline;
    4746 
    4747     /* Source: GMRFB. vmsvgaR3GmrTransfer ensures that no memory outside the GMR is read. */
    4748     SVGAGuestPtr const gstPtr = pSvgaR3State->GMRFB.ptr;
    4749     uint32_t const offGst =  (srcx * RT_ALIGN(pSvgaR3State->GMRFB.format.bitsPerPixel, 8)) / 8
    4750                            + pSvgaR3State->GMRFB.bytesPerLine * srcy;
    4751     int32_t const cbGstPitch = pSvgaR3State->GMRFB.bytesPerLine;
    4752 
    4753     int rc = vmsvgaR3GmrTransfer(pThis, pThisCC, SVGA3D_WRITE_HOST_VRAM,
    4754                                  pbHstBuf, cbHstBuf, offHst, cbHstPitch,
    4755                                  gstPtr, offGst, cbGstPitch,
    4756                                  (width * RT_ALIGN(pScreen->cBpp, 8)) / 8, height);
    4757     AssertRC(rc);
    4758     vmsvgaR3UpdateScreen(pThisCC, pScreen, clipRect.left, clipRect.top, width, height);
    4759 }
    4760 
    4761 
    4762 /* SVGA_CMD_BLIT_SCREEN_TO_GMRFB */
    4763 static void vmsvgaR3CmdBlitScreenToGMRFB(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdBlitScreenToGMRFB const *pCmd)
    4764 {
    4765     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    4766 
    4767     STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdBlitScreentoGmrFb);
    4768     /* Note! This can fetch 3d render results as well!! */
    4769     Log(("SVGA_CMD_BLIT_SCREEN_TO_GMRFB dest=(%d,%d) src id=%d (%d,%d)(%d,%d)\n",
    4770              pCmd->destOrigin.x, pCmd->destOrigin.y, pCmd->srcScreenId, pCmd->srcRect.left, pCmd->srcRect.top, pCmd->srcRect.right, pCmd->srcRect.bottom));
    4771 
    4772     ASSERT_GUEST_RETURN_VOID(pCmd->srcScreenId < RT_ELEMENTS(pSvgaR3State->aScreens));
    4773     RT_UNTRUSTED_VALIDATED_FENCE();
    4774 
    4775     VMSVGASCREENOBJECT *pScreen = vmsvgaR3GetScreenObject(pThisCC, pCmd->srcScreenId);
    4776     AssertPtrReturnVoid(pScreen);
    4777 
    4778     /** @todo Support GMRFB.format.bitsPerPixel != pThis->svga.uBpp ? */
    4779     AssertReturnVoid(pSvgaR3State->GMRFB.format.bitsPerPixel == pScreen->cBpp);
    4780 
    4781     /* Clip destRect to the screen dimensions. */
    4782     SVGASignedRect screenRect;
    4783     screenRect.left   = 0;
    4784     screenRect.top    = 0;
    4785     screenRect.right  = pScreen->cWidth;
    4786     screenRect.bottom = pScreen->cHeight;
    4787     SVGASignedRect clipRect = pCmd->srcRect;
    4788     vmsvgaR3ClipRect(&screenRect, &clipRect);
    4789     RT_UNTRUSTED_VALIDATED_FENCE();
    4790 
    4791     uint32_t const width  = clipRect.right - clipRect.left;
    4792     uint32_t const height = clipRect.bottom - clipRect.top;
    4793 
    4794     if (   width == 0
    4795         || height == 0)
    4796         return;  /* Nothing to do. */
    4797 
    4798     int32_t const dstx = pCmd->destOrigin.x + (clipRect.left - pCmd->srcRect.left);
    4799     int32_t const dsty = pCmd->destOrigin.y + (clipRect.top - pCmd->srcRect.top);
    4800 
    4801     /* Copy the defined by GMRFB image to the screen 0 VRAM area.
    4802      * Prepare parameters for vmsvgaR3GmrTransfer.
    4803      */
    4804     AssertReturnVoid(pScreen->offVRAM < pThis->vram_size); /* Paranoia. Ensured by SVGA_CMD_DEFINE_SCREEN. */
    4805 
    4806     /* Source: host buffer which describes the screen 0 VRAM.
    4807      * Important are pbHstBuf and cbHstBuf. offHst and cbHstPitch are verified by vmsvgaR3GmrTransfer.
    4808      */
    4809     uint8_t * const pbHstBuf = (uint8_t *)pThisCC->pbVRam + pScreen->offVRAM;
    4810     uint32_t const cbScanline = pScreen->cbPitch ? pScreen->cbPitch :
    4811                                                    width * (RT_ALIGN(pScreen->cBpp, 8) / 8);
    4812     uint32_t cbHstBuf = cbScanline * pScreen->cHeight;
    4813     if (cbHstBuf > pThis->vram_size - pScreen->offVRAM)
    4814        cbHstBuf = pThis->vram_size - pScreen->offVRAM; /* Paranoia. */
    4815     uint32_t const offHst =   (clipRect.left * RT_ALIGN(pScreen->cBpp, 8)) / 8
    4816                             + cbScanline * clipRect.top;
    4817     int32_t const cbHstPitch = cbScanline;
    4818 
    4819     /* Destination: GMRFB. vmsvgaR3GmrTransfer ensures that no memory outside the GMR is read. */
    4820     SVGAGuestPtr const gstPtr = pSvgaR3State->GMRFB.ptr;
    4821     uint32_t const offGst =  (dstx * RT_ALIGN(pSvgaR3State->GMRFB.format.bitsPerPixel, 8)) / 8
    4822                            + pSvgaR3State->GMRFB.bytesPerLine * dsty;
    4823     int32_t const cbGstPitch = pSvgaR3State->GMRFB.bytesPerLine;
    4824 
    4825     int rc = vmsvgaR3GmrTransfer(pThis, pThisCC, SVGA3D_READ_HOST_VRAM,
    4826                                  pbHstBuf, cbHstBuf, offHst, cbHstPitch,
    4827                                  gstPtr, offGst, cbGstPitch,
    4828                                  (width * RT_ALIGN(pScreen->cBpp, 8)) / 8, height);
    4829     AssertRC(rc);
    4830 }
    4831 
    4832 
    4833 /* SVGA_CMD_ANNOTATION_FILL */
    4834 static void vmsvgaR3CmdAnnotationFill(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdAnnotationFill const *pCmd)
    4835 {
    4836     RT_NOREF(pThis);
    4837     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    4838 
    4839     STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdAnnotationFill);
    4840     Log(("SVGA_CMD_ANNOTATION_FILL red=%x green=%x blue=%x\n", pCmd->color.r, pCmd->color.g, pCmd->color.b));
    4841 
    4842     pSvgaR3State->colorAnnotation = pCmd->color;
    4843 }
    4844 
    4845 
    4846 /* SVGA_CMD_ANNOTATION_COPY */
    4847 static void vmsvgaR3CmdAnnotationCopy(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdAnnotationCopy const *pCmd)
    4848 {
    4849     RT_NOREF(pThis, pCmd);
    4850     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    4851 
    4852     STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdAnnotationCopy);
    4853     Log(("SVGA_CMD_ANNOTATION_COPY srcOrigin %d,%d, srcScreenId %u\n", pCmd->srcOrigin.x, pCmd->srcOrigin.y, pCmd->srcScreenId));
    4854 
    4855     AssertFailed();
    4856 }
    4857 
    4858 
    4859 # ifdef VBOX_WITH_VMSVGA3D
    4860 /* SVGA_CMD_DEFINE_GMR2 */
    4861 static void vmsvgaR3CmdDefineGMR2(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineGMR2 const *pCmd)
    4862 {
    4863     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    4864 
    4865     STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdDefineGmr2);
    4866     Log(("SVGA_CMD_DEFINE_GMR2 id=%#x %#x pages\n", pCmd->gmrId, pCmd->numPages));
    4867 
    4868     /* Validate current GMR id. */
    4869     ASSERT_GUEST_RETURN_VOID(pCmd->gmrId < pThis->svga.cGMR);
    4870     ASSERT_GUEST_RETURN_VOID(pCmd->numPages <= VMSVGA_MAX_GMR_PAGES);
    4871     RT_UNTRUSTED_VALIDATED_FENCE();
    4872 
    4873     if (!pCmd->numPages)
    4874     {
    4875         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdDefineGmr2Free);
    4876         vmsvgaR3GmrFree(pThisCC, pCmd->gmrId);
    4877     }
    4878     else
    4879     {
    4880         PGMR pGMR = &pSvgaR3State->paGMR[pCmd->gmrId];
    4881         if (pGMR->cMaxPages)
    4882             STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdDefineGmr2Modify);
    4883 
    4884         /* Not sure if we should always free the descriptor, but for simplicity
    4885            we do so if the new size is smaller than the current. */
    4886         /** @todo always free the descriptor in SVGA_CMD_DEFINE_GMR2? */
    4887         if (pGMR->cbTotal / X86_PAGE_SIZE > pGMR->cMaxPages)
    4888             vmsvgaR3GmrFree(pThisCC, pCmd->gmrId);
    4889 
    4890         pGMR->cMaxPages = pCmd->numPages;
    4891         /* The rest is done by the REMAP_GMR2 command. */
    4892     }
    4893 }
    4894 
    4895 
    4896 /* SVGA_CMD_REMAP_GMR2 */
    4897 static void vmsvgaR3CmdRemapGMR2(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdRemapGMR2 const *pCmd)
    4898 {
    4899     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    4900 
    4901     STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdRemapGmr2);
    4902     Log(("SVGA_CMD_REMAP_GMR2 id=%#x flags=%#x offset=%#x npages=%#x\n", pCmd->gmrId, pCmd->flags, pCmd->offsetPages, pCmd->numPages));
    4903 
    4904     /* Validate current GMR id and size. */
    4905     ASSERT_GUEST_RETURN_VOID(pCmd->gmrId < pThis->svga.cGMR);
    4906     RT_UNTRUSTED_VALIDATED_FENCE();
    4907     PGMR pGMR = &pSvgaR3State->paGMR[pCmd->gmrId];
    4908     ASSERT_GUEST_RETURN_VOID(   (uint64_t)pCmd->offsetPages + pCmd->numPages
    4909                              <= RT_MIN(pGMR->cMaxPages, RT_MIN(VMSVGA_MAX_GMR_PAGES, UINT32_MAX / X86_PAGE_SIZE)));
    4910     ASSERT_GUEST_RETURN_VOID(!pCmd->offsetPages || pGMR->paDesc); /** @todo */
    4911 
    4912     if (pCmd->numPages == 0)
    4913         return;
    4914     RT_UNTRUSTED_VALIDATED_FENCE();
    4915 
    4916     /* Calc new total page count so we can use it instead of cMaxPages for allocations below. */
    4917     uint32_t const cNewTotalPages = RT_MAX(pGMR->cbTotal >> X86_PAGE_SHIFT, pCmd->offsetPages + pCmd->numPages);
    4918 
    4919     /*
    4920      * We flatten the existing descriptors into a page array, overwrite the
    4921      * pages specified in this command and then recompress the descriptor.
    4922      */
    4923     /** @todo Optimize the GMR remap algorithm! */
    4924 
    4925     /* Save the old page descriptors as an array of page frame numbers (address >> X86_PAGE_SHIFT) */
    4926     uint64_t *paNewPage64 = NULL;
    4927     if (pGMR->paDesc)
    4928     {
    4929         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdRemapGmr2Modify);
    4930 
    4931         paNewPage64 = (uint64_t *)RTMemAllocZ(cNewTotalPages * sizeof(uint64_t));
    4932         AssertPtrReturnVoid(paNewPage64);
    4933 
    4934         uint32_t idxPage = 0;
    4935         for (uint32_t i = 0; i < pGMR->numDescriptors; i++)
    4936             for (uint32_t j = 0; j < pGMR->paDesc[i].numPages; j++)
    4937                 paNewPage64[idxPage++] = (pGMR->paDesc[i].GCPhys + j * X86_PAGE_SIZE) >> X86_PAGE_SHIFT;
    4938         AssertReturnVoidStmt(idxPage == pGMR->cbTotal >> X86_PAGE_SHIFT, RTMemFree(paNewPage64));
    4939         RT_UNTRUSTED_VALIDATED_FENCE();
    4940     }
    4941 
    4942     /* Free the old GMR if present. */
    4943     if (pGMR->paDesc)
    4944         RTMemFree(pGMR->paDesc);
    4945 
    4946     /* Allocate the maximum amount possible (everything non-continuous) */
    4947     PVMSVGAGMRDESCRIPTOR paDescs;
    4948     pGMR->paDesc = paDescs = (PVMSVGAGMRDESCRIPTOR)RTMemAllocZ(cNewTotalPages * sizeof(VMSVGAGMRDESCRIPTOR));
    4949     AssertReturnVoidStmt(paDescs, RTMemFree(paNewPage64));
    4950 
    4951     if (pCmd->flags & SVGA_REMAP_GMR2_VIA_GMR)
    4952     {
    4953         /** @todo */
    4954         AssertFailed();
    4955         pGMR->numDescriptors = 0;
    4956     }
    4957     else
    4958     {
    4959         uint32_t  *paPages32 = (uint32_t *)(pCmd + 1);
    4960         uint64_t  *paPages64 = (uint64_t *)(pCmd + 1);
    4961         bool       fGCPhys64 = RT_BOOL(pCmd->flags & SVGA_REMAP_GMR2_PPN64);
    4962 
    4963         uint32_t cPages;
    4964         if (paNewPage64)
    4965         {
    4966             /* Overwrite the old page array with the new page values. */
    4967             if (fGCPhys64)
    4968                 for (uint32_t i = pCmd->offsetPages; i < pCmd->offsetPages + pCmd->numPages; i++)
    4969                     paNewPage64[i] = paPages64[i - pCmd->offsetPages];
    4970             else
    4971                 for (uint32_t i = pCmd->offsetPages; i < pCmd->offsetPages + pCmd->numPages; i++)
    4972                     paNewPage64[i] = paPages32[i - pCmd->offsetPages];
    4973 
    4974             /* Use the updated page array instead of the command data. */
    4975             fGCPhys64      = true;
    4976             paPages64      = paNewPage64;
    4977             cPages = cNewTotalPages;
    4978         }
    4979         else
    4980             cPages = pCmd->numPages;
    4981 
    4982         /* The first page. */
    4983         /** @todo The 0x00000FFFFFFFFFFF mask limits to 44 bits and should not be
    4984          *        applied to paNewPage64. */
    4985         RTGCPHYS GCPhys;
    4986         if (fGCPhys64)
    4987             GCPhys = (paPages64[0] << X86_PAGE_SHIFT) & UINT64_C(0x00000FFFFFFFFFFF); /* Seeing rubbish in the top bits with certain linux guests. */
    4988         else
    4989             GCPhys = (RTGCPHYS)paPages32[0] << PAGE_SHIFT;
    4990         paDescs[0].GCPhys    = GCPhys;
    4991         paDescs[0].numPages  = 1;
    4992 
    4993         /* Subsequent pages. */
    4994         uint32_t iDescriptor = 0;
    4995         for (uint32_t i = 1; i < cPages; i++)
    4996         {
    4997             if (pCmd->flags & SVGA_REMAP_GMR2_PPN64)
    4998                 GCPhys = (paPages64[i] << X86_PAGE_SHIFT) & UINT64_C(0x00000FFFFFFFFFFF); /* Seeing rubbish in the top bits with certain linux guests. */
    4999             else
    5000                 GCPhys = (RTGCPHYS)paPages32[i] << X86_PAGE_SHIFT;
    5001 
    5002             /* Continuous physical memory? */
    5003             if (GCPhys == paDescs[iDescriptor].GCPhys + paDescs[iDescriptor].numPages * X86_PAGE_SIZE)
    5004             {
    5005                 Assert(paDescs[iDescriptor].numPages);
    5006                 paDescs[iDescriptor].numPages++;
    5007                 Log5Func(("Page %x GCPhys=%RGp successor\n", i, GCPhys));
    5008             }
    5009             else
    5010             {
    5011                 iDescriptor++;
    5012                 paDescs[iDescriptor].GCPhys   = GCPhys;
    5013                 paDescs[iDescriptor].numPages = 1;
    5014                 Log5Func(("Page %x GCPhys=%RGp\n", i, paDescs[iDescriptor].GCPhys));
    5015             }
    5016         }
    5017 
    5018         pGMR->cbTotal = cNewTotalPages << X86_PAGE_SHIFT;
    5019         Log5Func(("Nr of descriptors %x; cbTotal=%#x\n", iDescriptor + 1, cNewTotalPages));
    5020         pGMR->numDescriptors = iDescriptor + 1;
    5021     }
    5022 
    5023     if (paNewPage64)
    5024         RTMemFree(paNewPage64);
    5025 }
    5026 # endif // VBOX_WITH_VMSVGA3D
    5027 
    5028 
    5029 /*
    5030  *
    5031  * Command buffer submission.
    5032  *
    5033  * Guest submits a buffer by writing to SVGA_REG_COMMAND_LOW register.
    5034  *
    5035  * EMT thread appends a command buffer to the context queue (VMSVGACMDBUFCTX::listSubmitted)
    5036  * and wakes up the FIFO thread.
    5037  *
    5038  * FIFO thread fetches the command buffer from the queue, processes the commands and writes
    5039  * the buffer header back to the guest memory.
    5040  *
    5041  * If buffers are preempted, then the EMT thread removes all buffers from the context queue.
    5042  *
    5043  */
    5044 
    5045 
    5046 /** Update a command buffer header 'status' and 'errorOffset' fields in the guest memory.
    5047  *
    5048  * @param pDevIns     The device instance.
    5049  * @param GCPhysCB    Guest physical address of the command buffer header.
    5050  * @param status      Command buffer status (SVGA_CB_STATUS_*).
    5051  * @param errorOffset Offset to the first byte of the failing command for SVGA_CB_STATUS_COMMAND_ERROR.
    5052  *                    errorOffset is ignored if the status is not SVGA_CB_STATUS_COMMAND_ERROR.
    5053  * @thread FIFO or EMT.
    5054  */
    5055 static void vmsvgaR3CmdBufWriteStatus(PPDMDEVINS pDevIns, RTGCPHYS GCPhysCB, SVGACBStatus status, uint32_t errorOffset)
    5056 {
    5057     SVGACBHeader hdr;
    5058     hdr.status = status;
    5059     hdr.errorOffset = errorOffset;
    5060     AssertCompile(   RT_OFFSETOF(SVGACBHeader, status) == 0
    5061                   && RT_OFFSETOF(SVGACBHeader, errorOffset) == 4
    5062                   && RT_OFFSETOF(SVGACBHeader, id) == 8);
    5063     size_t const cbWrite = status == SVGA_CB_STATUS_COMMAND_ERROR
    5064                          ? RT_UOFFSET_AFTER(SVGACBHeader, errorOffset)  /* Both 'status' and 'errorOffset' fields. */
    5065                          : RT_UOFFSET_AFTER(SVGACBHeader, status);      /* Only 'status' field. */
    5066     PDMDevHlpPhysWrite(pDevIns, GCPhysCB, &hdr, cbWrite);
    5067 }
    5068 
    5069 
    5070 /** Raise an IRQ.
    5071  *
    5072  * @param pDevIns     The device instance.
    5073  * @param pThis       The shared VGA/VMSVGA state.
    5074  * @param fIRQ        SVGA_IRQFLAG_* bits.
    5075  * @thread FIFO or EMT.
    5076  */
    5077 static void vmsvgaR3CmdBufRaiseIRQ(PPDMDEVINS pDevIns, PVGASTATE pThis, uint32_t fIRQ)
    5078 {
    5079     int rc = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VERR_IGNORED);
    5080     AssertRC(rc);
    5081 
    5082     if (pThis->svga.u32IrqMask & fIRQ)
    5083     {
    5084         LogFunc(("Trigger interrupt with status %#x\n", fIRQ));
    5085         ASMAtomicOrU32(&pThis->svga.u32IrqStatus, fIRQ);
    5086         PDMDevHlpPCISetIrq(pDevIns, 0, 1);
    5087     }
    5088 
    5089     PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect);
    5090 }
    5091 
    5092 
    5093 /** Allocate a command buffer structure.
    5094  *
    5095  * @param pCmdBufCtx  The command buffer context which must allocate the buffer.
    5096  * @return Pointer to the allocated command buffer structure.
    5097  */
    5098 static PVMSVGACMDBUF vmsvgaR3CmdBufAlloc(PVMSVGACMDBUFCTX pCmdBufCtx)
    5099 {
    5100     if (!pCmdBufCtx)
    5101         return NULL;
    5102 
    5103     PVMSVGACMDBUF pCmdBuf = (PVMSVGACMDBUF)RTMemAllocZ(sizeof(*pCmdBuf));
    5104     if (pCmdBuf)
    5105     {
    5106         // RT_ZERO(pCmdBuf->nodeBuffer);
    5107         pCmdBuf->pCmdBufCtx = pCmdBufCtx;
    5108         // pCmdBuf->GCPhysCB = 0;
    5109         // RT_ZERO(pCmdBuf->hdr);
    5110         // pCmdBuf->pvCommands = NULL;
    5111     }
    5112 
    5113     return pCmdBuf;
    5114 }
    5115 
    5116 
    5117 /** Free a command buffer structure.
    5118  *
    5119  * @param pCmdBuf  The command buffer pointer.
    5120  */
    5121 static void vmsvgaR3CmdBufFree(PVMSVGACMDBUF pCmdBuf)
    5122 {
    5123     if (pCmdBuf)
    5124         RTMemFree(pCmdBuf->pvCommands);
    5125     RTMemFree(pCmdBuf);
    5126 }
    5127 
    5128 
    5129 /** Initialize a command buffer context.
    5130  *
    5131  * @param pCmdBufCtx  The command buffer context.
    5132  */
    5133 static void vmsvgaR3CmdBufCtxInit(PVMSVGACMDBUFCTX pCmdBufCtx)
    5134 {
    5135     RTListInit(&pCmdBufCtx->listSubmitted);
    5136     pCmdBufCtx->cSubmitted = 0;
    5137 }
    5138 
    5139 
    5140 /** Destroy a command buffer context.
    5141  *
    5142  * @param pCmdBufCtx  The command buffer context pointer.
    5143  */
    5144 static void vmsvgaR3CmdBufCtxTerm(PVMSVGACMDBUFCTX pCmdBufCtx)
    5145 {
    5146     if (!pCmdBufCtx)
    5147         return;
    5148 
    5149     if (pCmdBufCtx->listSubmitted.pNext)
    5150     {
    5151         /* If the list has been initialized. */
    5152         PVMSVGACMDBUF pIter, pNext;
    5153         RTListForEachSafe(&pCmdBufCtx->listSubmitted, pIter, pNext, VMSVGACMDBUF, nodeBuffer)
    5154         {
    5155             RTListNodeRemove(&pIter->nodeBuffer);
    5156             --pCmdBufCtx->cSubmitted;
    5157             vmsvgaR3CmdBufFree(pIter);
    5158         }
    5159     }
    5160     Assert(pCmdBufCtx->cSubmitted == 0);
    5161     pCmdBufCtx->cSubmitted = 0;
    5162 }
    5163 
    5164 
    5165 /** Handles SVGA_DC_CMD_START_STOP_CONTEXT command.
    5166  *
    5167  * @param pSvgaR3State VMSVGA R3 state.
    5168  * @param pCmd         The command data.
    5169  * @return SVGACBStatus code.
    5170  * @thread EMT
    5171  */
    5172 static SVGACBStatus vmsvgaR3CmdBufDCStartStop(PVMSVGAR3STATE pSvgaR3State, SVGADCCmdStartStop const *pCmd)
    5173 {
    5174     /* Create or destroy a regular command buffer context. */
    5175     if (pCmd->context >= RT_ELEMENTS(pSvgaR3State->apCmdBufCtxs))
    5176         return SVGA_CB_STATUS_COMMAND_ERROR;
    5177     RT_UNTRUSTED_VALIDATED_FENCE();
    5178 
    5179     SVGACBStatus CBStatus = SVGA_CB_STATUS_COMPLETED;
    5180 
    5181     int rc = RTCritSectEnter(&pSvgaR3State->CritSectCmdBuf);
    5182     AssertRC(rc);
    5183     if (pCmd->enable)
    5184     {
    5185         pSvgaR3State->apCmdBufCtxs[pCmd->context] = (PVMSVGACMDBUFCTX)RTMemAlloc(sizeof(VMSVGACMDBUFCTX));
    5186         if (pSvgaR3State->apCmdBufCtxs[pCmd->context])
    5187             vmsvgaR3CmdBufCtxInit(pSvgaR3State->apCmdBufCtxs[pCmd->context]);
    5188         else
    5189             CBStatus = SVGA_CB_STATUS_QUEUE_FULL;
    5190     }
    5191     else
    5192     {
    5193         vmsvgaR3CmdBufCtxTerm(pSvgaR3State->apCmdBufCtxs[pCmd->context]);
    5194         pSvgaR3State->apCmdBufCtxs[pCmd->context] = NULL;
    5195     }
    5196     RTCritSectLeave(&pSvgaR3State->CritSectCmdBuf);
    5197 
    5198     return CBStatus;
    5199 }
    5200 
    5201 
    5202 /** Handles SVGA_DC_CMD_PREEMPT command.
    5203  *
    5204  * @param pDevIns      The device instance.
    5205  * @param pSvgaR3State VMSVGA R3 state.
    5206  * @param pCmd         The command data.
    5207  * @return SVGACBStatus code.
    5208  * @thread EMT
    5209  */
    5210 static SVGACBStatus vmsvgaR3CmdBufDCPreempt(PPDMDEVINS pDevIns, PVMSVGAR3STATE pSvgaR3State, SVGADCCmdPreempt const *pCmd)
    5211 {
    5212     /* Remove buffers from the processing queue of the specified context. */
    5213     if (pCmd->context >= RT_ELEMENTS(pSvgaR3State->apCmdBufCtxs))
    5214         return SVGA_CB_STATUS_COMMAND_ERROR;
    5215     RT_UNTRUSTED_VALIDATED_FENCE();
    5216 
    5217     PVMSVGACMDBUFCTX const pCmdBufCtx = pSvgaR3State->apCmdBufCtxs[pCmd->context];
    5218     RTLISTANCHOR listPreempted;
    5219 
    5220     int rc = RTCritSectEnter(&pSvgaR3State->CritSectCmdBuf);
    5221     AssertRC(rc);
    5222     if (pCmd->ignoreIDZero)
    5223     {
    5224         RTListInit(&listPreempted);
    5225 
    5226         PVMSVGACMDBUF pIter, pNext;
    5227         RTListForEachSafe(&pCmdBufCtx->listSubmitted, pIter, pNext, VMSVGACMDBUF, nodeBuffer)
    5228         {
    5229             if (pIter->hdr.id == 0)
    5230                 continue;
    5231 
    5232             RTListNodeRemove(&pIter->nodeBuffer);
    5233             --pCmdBufCtx->cSubmitted;
    5234             RTListAppend(&listPreempted, &pIter->nodeBuffer);
    5235         }
    5236     }
    5237     else
    5238     {
    5239         RTListMove(&listPreempted, &pCmdBufCtx->listSubmitted);
    5240     }
    5241     RTCritSectLeave(&pSvgaR3State->CritSectCmdBuf);
    5242 
    5243     PVMSVGACMDBUF pIter, pNext;
    5244     RTListForEachSafe(&listPreempted, pIter, pNext, VMSVGACMDBUF, nodeBuffer)
    5245     {
    5246         RTListNodeRemove(&pIter->nodeBuffer);
    5247         vmsvgaR3CmdBufWriteStatus(pDevIns, pIter->GCPhysCB, SVGA_CB_STATUS_PREEMPTED, 0);
    5248         vmsvgaR3CmdBufFree(pIter);
    5249     }
    5250 
    5251     return SVGA_CB_STATUS_COMPLETED;
    5252 }
    5253 
    5254 
    5255 /** @def VMSVGA_INC_CMD_SIZE_BREAK
    5256  * Increments the size of the command cbCmd by a_cbMore.
    5257  * Checks that the command buffer has at least cbCmd bytes. Will break out of the switch if it doesn't.
    5258  * Used by vmsvgaR3CmdBufProcessDC and vmsvgaR3CmdBufProcessCommands.
    5259  */
    5260 #define VMSVGA_INC_CMD_SIZE_BREAK(a_cbMore) \
    5261      if (1) { \
    5262           cbCmd += (a_cbMore); \
    5263           ASSERT_GUEST_MSG_STMT_BREAK(cbRemain >= cbCmd, ("size=%#x remain=%#zx\n", cbCmd, (size_t)cbRemain), CBstatus = SVGA_CB_STATUS_COMMAND_ERROR); \
    5264           RT_UNTRUSTED_VALIDATED_FENCE(); \
    5265      } else do {} while (0)
    5266 
    5267 
    5268 /** Processes Device Context command buffer.
    5269  *
    5270  * @param pDevIns      The device instance.
    5271  * @param pSvgaR3State VMSVGA R3 state.
    5272  * @param pvCommands   Pointer to the command buffer.
    5273  * @param cbCommands   Size of the command buffer.
    5274  * @param poffNextCmd  Where to store the offset of the first unprocessed command.
    5275  * @return SVGACBStatus code.
    5276  * @thread EMT
    5277  */
    5278 static SVGACBStatus vmsvgaR3CmdBufProcessDC(PPDMDEVINS pDevIns, PVMSVGAR3STATE pSvgaR3State, void const *pvCommands, uint32_t cbCommands, uint32_t *poffNextCmd)
    5279 {
    5280     SVGACBStatus CBstatus = SVGA_CB_STATUS_COMPLETED;
    5281 
    5282     uint8_t const *pu8Cmd = (uint8_t *)pvCommands;
    5283     uint32_t cbRemain = cbCommands;
    5284     while (cbRemain)
    5285     {
    5286         /* Command identifier is a 32 bit value. */
    5287         if (cbRemain < sizeof(uint32_t))
    5288         {
    5289             CBstatus = SVGA_CB_STATUS_COMMAND_ERROR;
    5290             break;
    5291         }
    5292 
    5293          /* Fetch the command id. */
    5294         uint32_t const cmdId = *(uint32_t *)pu8Cmd;
    5295         uint32_t cbCmd = sizeof(uint32_t);
    5296         switch (cmdId)
    5297         {
    5298             case SVGA_DC_CMD_NOP:
    5299             {
    5300                 /* NOP */
    5301                 break;
    5302             }
    5303 
    5304             case SVGA_DC_CMD_START_STOP_CONTEXT:
    5305             {
    5306                 SVGADCCmdStartStop *pCmd = (SVGADCCmdStartStop *)&pu8Cmd[cbCmd];
    5307                 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
    5308                 CBstatus = vmsvgaR3CmdBufDCStartStop(pSvgaR3State, pCmd);
    5309                 break;
    5310             }
    5311 
    5312             case SVGA_DC_CMD_PREEMPT:
    5313             {
    5314                 SVGADCCmdPreempt *pCmd = (SVGADCCmdPreempt *)&pu8Cmd[cbCmd];
    5315                 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
    5316                 CBstatus = vmsvgaR3CmdBufDCPreempt(pDevIns, pSvgaR3State, pCmd);
    5317                 break;
    5318             }
    5319 
    5320             default:
    5321             {
    5322                 /* Unsupported command. */
    5323                 CBstatus = SVGA_CB_STATUS_COMMAND_ERROR;
    5324                 break;
    5325             }
    5326         }
    5327 
    5328         if (CBstatus != SVGA_CB_STATUS_COMPLETED)
    5329             break;
    5330 
    5331         pu8Cmd += cbCmd;
    5332         cbRemain -= cbCmd;
    5333     }
    5334 
    5335     Assert(cbRemain <= cbCommands);
    5336     *poffNextCmd = cbCommands - cbRemain;
    5337     return CBstatus;
    5338 }
    5339 
    5340 
    5341 /** Submits a device context command buffer for synchronous processing.
    5342  *
    5343  * @param pDevIns      The device instance.
    5344  * @param pThisCC      The VGA/VMSVGA state for the current context.
    5345  * @param ppCmdBuf     Pointer to the command buffer pointer.
    5346  *                     The function can set the command buffer pointer to NULL to prevent deallocation by the caller.
    5347  * @param poffNextCmd  Where to store the offset of the first unprocessed command.
    5348  * @return SVGACBStatus code.
    5349  * @thread EMT
    5350  */
    5351 static SVGACBStatus vmsvgaR3CmdBufSubmitDC(PPDMDEVINS pDevIns, PVGASTATECC pThisCC, PVMSVGACMDBUF *ppCmdBuf, uint32_t *poffNextCmd)
    5352 {
    5353     /* Synchronously process the device context commands. */
    5354     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    5355     return vmsvgaR3CmdBufProcessDC(pDevIns, pSvgaR3State, (*ppCmdBuf)->pvCommands, (*ppCmdBuf)->hdr.length, poffNextCmd);
    5356 }
    5357 
    5358 /** Submits a command buffer for asynchronous processing by the FIFO thread.
    5359  *
    5360  * @param pDevIns      The device instance.
    5361  * @param pThis        The shared VGA/VMSVGA state.
    5362  * @param pThisCC      The VGA/VMSVGA state for the current context.
    5363  * @param ppCmdBuf     Pointer to the command buffer pointer.
    5364  *                     The function can set the command buffer pointer to NULL to prevent deallocation by the caller.
    5365  * @return SVGACBStatus code.
    5366  * @thread EMT
    5367  */
    5368 static SVGACBStatus vmsvgaR3CmdBufSubmit(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, PVMSVGACMDBUF *ppCmdBuf)
    5369 {
    5370     /* Command buffer submission. */
    5371     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    5372 
    5373     SVGACBStatus CBstatus = SVGA_CB_STATUS_NONE;
    5374 
    5375     PVMSVGACMDBUF const pCmdBuf = *ppCmdBuf;
    5376     PVMSVGACMDBUFCTX const pCmdBufCtx = pCmdBuf->pCmdBufCtx;
    5377 
    5378     int rc = RTCritSectEnter(&pSvgaR3State->CritSectCmdBuf);
    5379     AssertRC(rc);
    5380 
    5381     if (RT_LIKELY(pCmdBufCtx->cSubmitted < SVGA_CB_MAX_QUEUED_PER_CONTEXT))
    5382     {
    5383         RTListAppend(&pCmdBufCtx->listSubmitted, &pCmdBuf->nodeBuffer);
    5384         ++pCmdBufCtx->cSubmitted;
    5385         *ppCmdBuf = NULL; /* Consume the buffer. */
    5386         ASMAtomicWriteU32(&pThisCC->svga.pSvgaR3State->fCmdBuf, 1);
    5387     }
    5388     else
    5389         CBstatus = SVGA_CB_STATUS_QUEUE_FULL;
    5390 
    5391     RTCritSectLeave(&pSvgaR3State->CritSectCmdBuf);
    5392 
    5393     /* Inform the FIFO thread. */
    5394     if (*ppCmdBuf == NULL)
    5395         PDMDevHlpSUPSemEventSignal(pDevIns, pThis->svga.hFIFORequestSem);
    5396 
    5397     return CBstatus;
    5398 }
    5399 
    5400 
    5401 /** SVGA_REG_COMMAND_LOW write handler.
    5402  * Submits a command buffer to the FIFO thread or processes a device context command.
    5403  *
    5404  * @param pDevIns     The device instance.
    5405  * @param pThis       The shared VGA/VMSVGA state.
    5406  * @param pThisCC     The VGA/VMSVGA state for the current context.
    5407  * @param GCPhysCB    Guest physical address of the command buffer header.
    5408  * @param CBCtx       Context the command buffer is submitted to.
    5409  * @thread EMT
    5410  */
    5411 static void vmsvgaR3CmdBufSubmit(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, RTGCPHYS GCPhysCB, SVGACBContext CBCtx)
    5412 {
    5413     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    5414 
    5415     SVGACBStatus CBstatus = SVGA_CB_STATUS_NONE;
    5416     uint32_t offNextCmd = 0;
    5417     uint32_t fIRQ = 0;
    5418 
    5419     /* Get the context if the device has the capability. */
    5420     PVMSVGACMDBUFCTX pCmdBufCtx = NULL;
    5421     if (pThis->svga.u32DeviceCaps & SVGA_CAP_COMMAND_BUFFERS)
    5422     {
    5423         if (RT_LIKELY(CBCtx < RT_ELEMENTS(pSvgaR3State->apCmdBufCtxs)))
    5424             pCmdBufCtx = pSvgaR3State->apCmdBufCtxs[CBCtx];
    5425         else if (CBCtx == SVGA_CB_CONTEXT_DEVICE)
    5426             pCmdBufCtx = &pSvgaR3State->CmdBufCtxDC;
    5427         RT_UNTRUSTED_VALIDATED_FENCE();
    5428     }
    5429 
    5430     /* Allocate a new command buffer. */
    5431     PVMSVGACMDBUF pCmdBuf = vmsvgaR3CmdBufAlloc(pCmdBufCtx);
    5432     if (RT_LIKELY(pCmdBuf))
    5433     {
    5434         pCmdBuf->GCPhysCB = GCPhysCB;
    5435 
    5436         int rc = PDMDevHlpPhysRead(pDevIns, GCPhysCB, &pCmdBuf->hdr, sizeof(pCmdBuf->hdr));
    5437         if (RT_SUCCESS(rc))
    5438         {
    5439             /* Verify the command buffer header. */
    5440             if (RT_LIKELY(   pCmdBuf->hdr.status == SVGA_CB_STATUS_NONE
    5441                           && (pCmdBuf->hdr.flags & ~(SVGA_CB_FLAG_NO_IRQ)) == 0 /* No unexpected flags. */
    5442                           && pCmdBuf->hdr.length <= SVGA_CB_MAX_SIZE))
    5443             {
    5444                 RT_UNTRUSTED_VALIDATED_FENCE();
    5445 
    5446                 /* Read the command buffer content. */
    5447                 pCmdBuf->pvCommands = RTMemAlloc(pCmdBuf->hdr.length);
    5448                 if (pCmdBuf->pvCommands)
    5449                 {
    5450                     RTGCPHYS const GCPhysCmd = (RTGCPHYS)pCmdBuf->hdr.ptr.pa;
    5451                     rc = PDMDevHlpPhysRead(pDevIns, GCPhysCmd, pCmdBuf->pvCommands, pCmdBuf->hdr.length);
    5452                     if (RT_SUCCESS(rc))
    5453                     {
    5454                         /* Submit the buffer. Device context buffers will be processed synchronously. */
    5455                         if (RT_LIKELY(CBCtx < RT_ELEMENTS(pSvgaR3State->apCmdBufCtxs)))
    5456                             /* This usually processes the CB async and sets pCmbBuf to NULL. */
    5457                             CBstatus = vmsvgaR3CmdBufSubmit(pDevIns, pThis, pThisCC, &pCmdBuf);
    5458                         else
    5459                             CBstatus = vmsvgaR3CmdBufSubmitDC(pDevIns, pThisCC, &pCmdBuf, &offNextCmd);
    5460                     }
    5461                     else
    5462                     {
    5463                         ASSERT_GUEST_MSG_FAILED(("Failed to read commands at %RGp\n", GCPhysCmd));
    5464                         CBstatus = SVGA_CB_STATUS_CB_HEADER_ERROR;
    5465                         fIRQ = SVGA_IRQFLAG_ERROR | SVGA_IRQFLAG_COMMAND_BUFFER;
    5466                     }
    5467                 }
    5468                 else
    5469                 {
    5470                     /* No memory for commands. */
    5471                     CBstatus = SVGA_CB_STATUS_QUEUE_FULL;
    5472                 }
    5473             }
    5474             else
    5475             {
    5476                 ASSERT_GUEST_MSG_FAILED(("Invalid buffer header\n"));
    5477                 CBstatus = SVGA_CB_STATUS_CB_HEADER_ERROR;
    5478                 fIRQ = SVGA_IRQFLAG_ERROR | SVGA_IRQFLAG_COMMAND_BUFFER;
    5479             }
    5480         }
    5481         else
    5482         {
    5483             LogFunc(("Failed to read buffer header at %RGp\n", GCPhysCB));
    5484             ASSERT_GUEST_FAILED();
    5485             /* Do not attempt to write the status. */
    5486         }
    5487 
    5488         /* Free the buffer if pfnCmdBufSubmit did not consume it. */
    5489         vmsvgaR3CmdBufFree(pCmdBuf);
    5490     }
    5491     else
    5492     {
    5493         LogFunc(("Can't allocate buffer for context id %#x\n", CBCtx));
    5494         ASSERT_GUEST_FAILED();
    5495         CBstatus = SVGA_CB_STATUS_QUEUE_FULL;
    5496     }
    5497 
    5498     if (CBstatus != SVGA_CB_STATUS_NONE)
    5499     {
    5500         LogFunc(("Write status %#x, offNextCmd %#x (of %#x), fIRQ %#x\n", CBstatus, offNextCmd, pCmdBuf->hdr.length, fIRQ));
    5501         vmsvgaR3CmdBufWriteStatus(pDevIns, GCPhysCB, CBstatus, offNextCmd);
    5502         if (fIRQ)
    5503             vmsvgaR3CmdBufRaiseIRQ(pDevIns, pThis, fIRQ);
    5504     }
    5505 }
    5506 
    5507 
    5508 /** Checks if there are some buffers to be processed.
    5509  *
    5510  * @param pThisCC     The VGA/VMSVGA state for the current context.
    5511  * @return true if buffers must be processed.
    5512  * @thread FIFO
    5513  */
    5514 static bool vmsvgaR3CmdBufHasWork(PVGASTATECC pThisCC)
    5515 {
    5516     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    5517     return RT_BOOL(ASMAtomicReadU32(&pSvgaR3State->fCmdBuf));
    5518 }
    5519 
    5520 
    5521 /** Processes a command buffer.
    5522  *
    5523  * @param pDevIns      The device instance.
    5524  * @param pThis        The shared VGA/VMSVGA state.
    5525  * @param pThisCC      The VGA/VMSVGA state for the current context.
    5526  * @param pvCommands   Pointer to the command buffer.
    5527  * @param cbCommands   Size of the command buffer.
    5528  * @param poffNextCmd  Where to store the offset of the first unprocessed command.
    5529  * @return SVGACBStatus code.
    5530  * @thread FIFO
    5531  */
    5532 static SVGACBStatus vmsvgaR3CmdBufProcessCommands(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, void const *pvCommands, uint32_t cbCommands, uint32_t *poffNextCmd)
    5533 {
    5534     SVGACBStatus CBstatus = SVGA_CB_STATUS_COMPLETED;
    5535     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    5536 
    5537     uint32_t RT_UNTRUSTED_VOLATILE_GUEST * const pFIFO = pThisCC->svga.pau32FIFO;
    5538 
    5539     uint8_t const *pu8Cmd = (uint8_t *)pvCommands;
    5540     uint32_t cbRemain = cbCommands;
    5541     while (cbRemain)
    5542     {
    5543         /* Command identifier is a 32 bit value. */
    5544         if (cbRemain < sizeof(uint32_t))
    5545         {
    5546             CBstatus = SVGA_CB_STATUS_COMMAND_ERROR;
    5547             break;
    5548         }
    5549 
    5550         /* Fetch the command id.
    5551          * 'cmdId' is actually a SVGAFifoCmdId. It is treated as uint32_t in order to avoid a compiler
    5552          * warning. Because we support some obsolete and deprecated commands, which are not included in
    5553          * the SVGAFifoCmdId enum in the VMSVGA headers anymore.
    5554          */
    5555         uint32_t const cmdId = *(uint32_t *)pu8Cmd;
    5556         uint32_t cbCmd = sizeof(uint32_t);
    5557 
    5558         LogFlowFunc(("%s %d\n", vmsvgaR3FifoCmdToString(cmdId), cmdId));
    5559 
    5560         /* At the end of the switch cbCmd is equal to the total length of the command including the cmdId.
    5561          * I.e. pu8Cmd + cbCmd must point to the next command.
    5562          * However if CBstatus is set to anything but SVGA_CB_STATUS_COMPLETED in the switch, then
    5563          * the cbCmd value is ignored (and pu8Cmd still points to the failed command).
    5564          */
    5565         /** @todo This code is very similar to the FIFO loop command processing. Think about merging. */
    5566         switch (cmdId)
    5567         {
    5568             case SVGA_CMD_INVALID_CMD:
    5569             {
    5570                 /* Nothing to do. */
    5571                 STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdInvalidCmd);
    5572                 break;
    5573             }
    5574 
    5575             case SVGA_CMD_FENCE:
    5576             {
    5577                 SVGAFifoCmdFence *pCmd = (SVGAFifoCmdFence *)&pu8Cmd[cbCmd];
    5578                 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
    5579                 STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdFence);
    5580                 Log(("SVGA_CMD_FENCE %#x\n", pCmd->fence));
    5581 
    5582                 uint32_t const offFifoMin = pFIFO[SVGA_FIFO_MIN];
    5583                 if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_FENCE, offFifoMin))
    5584                 {
    5585                     pFIFO[SVGA_FIFO_FENCE] = pCmd->fence;
    5586 
    5587                     uint32_t u32IrqStatus = 0;
    5588                     if (pThis->svga.u32IrqMask & SVGA_IRQFLAG_ANY_FENCE)
    5589                     {
    5590                         Log(("any fence irq\n"));
    5591                         u32IrqStatus |= SVGA_IRQFLAG_ANY_FENCE;
    5592                     }
    5593                     else if (    VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_FENCE_GOAL, offFifoMin)
    5594                              &&  (pThis->svga.u32IrqMask & SVGA_IRQFLAG_FENCE_GOAL)
    5595                              &&  pFIFO[SVGA_FIFO_FENCE_GOAL] == pCmd->fence)
    5596                     {
    5597                         Log(("fence goal reached irq (fence=%#x)\n", pCmd->fence));
    5598                         u32IrqStatus |= SVGA_IRQFLAG_FENCE_GOAL;
    5599                     }
    5600 
    5601                     if (u32IrqStatus)
    5602                         vmsvgaR3CmdBufRaiseIRQ(pDevIns, pThis, u32IrqStatus);
    5603                 }
    5604                 else
    5605                     Log(("SVGA_CMD_FENCE is bogus when offFifoMin is %#x!\n", offFifoMin));
    5606                 break;
    5607             }
    5608 
    5609             case SVGA_CMD_UPDATE:
    5610             {
    5611                 SVGAFifoCmdUpdate *pCmd = (SVGAFifoCmdUpdate *)&pu8Cmd[cbCmd];
    5612                 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
    5613                 vmsvgaR3CmdUpdate(pThis, pThisCC, pCmd);
    5614                 break;
    5615             }
    5616 
    5617             case SVGA_CMD_UPDATE_VERBOSE:
    5618             {
    5619                 SVGAFifoCmdUpdateVerbose *pCmd = (SVGAFifoCmdUpdateVerbose *)&pu8Cmd[cbCmd];
    5620                 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
    5621                 vmsvgaR3CmdUpdateVerbose(pThis, pThisCC, pCmd);
    5622                 break;
    5623             }
    5624 
    5625             case SVGA_CMD_DEFINE_CURSOR:
    5626             {
    5627                 /* Followed by bitmap data. */
    5628                 SVGAFifoCmdDefineCursor *pCmd = (SVGAFifoCmdDefineCursor *)&pu8Cmd[cbCmd];
    5629                 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
    5630 
    5631                 /* Figure out the size of the bitmap data. */
    5632                 ASSERT_GUEST_STMT_BREAK(pCmd->height < 2048 && pCmd->width < 2048, CBstatus = SVGA_CB_STATUS_COMMAND_ERROR);
    5633                 ASSERT_GUEST_STMT_BREAK(pCmd->andMaskDepth <= 32, CBstatus = SVGA_CB_STATUS_COMMAND_ERROR);
    5634                 ASSERT_GUEST_STMT_BREAK(pCmd->xorMaskDepth <= 32, CBstatus = SVGA_CB_STATUS_COMMAND_ERROR);
    5635                 RT_UNTRUSTED_VALIDATED_FENCE();
    5636 
    5637                 uint32_t const cbAndLine = RT_ALIGN_32(pCmd->width * (pCmd->andMaskDepth + (pCmd->andMaskDepth == 15)), 32) / 8;
    5638                 uint32_t const cbAndMask = cbAndLine * pCmd->height;
    5639                 uint32_t const cbXorLine = RT_ALIGN_32(pCmd->width * (pCmd->xorMaskDepth + (pCmd->xorMaskDepth == 15)), 32) / 8;
    5640                 uint32_t const cbXorMask = cbXorLine * pCmd->height;
    5641 
    5642                 VMSVGA_INC_CMD_SIZE_BREAK(cbAndMask + cbXorMask);
    5643                 vmsvgaR3CmdDefineCursor(pThis, pThisCC, pCmd);
    5644                 break;
    5645             }
    5646 
    5647             case SVGA_CMD_DEFINE_ALPHA_CURSOR:
    5648             {
    5649                 /* Followed by bitmap data. */
    5650                 SVGAFifoCmdDefineAlphaCursor *pCmd = (SVGAFifoCmdDefineAlphaCursor *)&pu8Cmd[cbCmd];
    5651                 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
    5652 
    5653                 /* Figure out the size of the bitmap data. */
    5654                 ASSERT_GUEST_STMT_BREAK(pCmd->height < 2048 && pCmd->width < 2048, CBstatus = SVGA_CB_STATUS_COMMAND_ERROR);
    5655 
    5656                 VMSVGA_INC_CMD_SIZE_BREAK(pCmd->width * pCmd->height * sizeof(uint32_t)); /* 32-bit BRGA format */
    5657                 vmsvgaR3CmdDefineAlphaCursor(pThis, pThisCC, pCmd);
    5658                 break;
    5659             }
    5660 
    5661             case SVGA_CMD_MOVE_CURSOR:
    5662             {
    5663                 /* Deprecated; there should be no driver which *requires* this command. However, if
    5664                  * we do ecncounter this command, it might be useful to not get the FIFO completely out of
    5665                  * alignment.
    5666                  * May be issued by guest if SVGA_CAP_CURSOR_BYPASS is missing.
    5667                  */
    5668                 SVGAFifoCmdMoveCursor *pCmd = (SVGAFifoCmdMoveCursor *)&pu8Cmd[cbCmd];
    5669                 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
    5670                 vmsvgaR3CmdMoveCursor(pThis, pThisCC, pCmd);
    5671                 break;
    5672             }
    5673 
    5674             case SVGA_CMD_DISPLAY_CURSOR:
    5675             {
    5676                 /* Deprecated; there should be no driver which *requires* this command. However, if
    5677                  * we do ecncounter this command, it might be useful to not get the FIFO completely out of
    5678                  * alignment.
    5679                  * May be issued by guest if SVGA_CAP_CURSOR_BYPASS is missing.
    5680                  */
    5681                 SVGAFifoCmdDisplayCursor *pCmd = (SVGAFifoCmdDisplayCursor *)&pu8Cmd[cbCmd];
    5682                 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
    5683                 vmsvgaR3CmdDisplayCursor(pThis, pThisCC, pCmd);
    5684                 break;
    5685             }
    5686 
    5687             case SVGA_CMD_RECT_FILL:
    5688             {
    5689                 SVGAFifoCmdRectFill *pCmd = (SVGAFifoCmdRectFill *)&pu8Cmd[cbCmd];
    5690                 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
    5691                 vmsvgaR3CmdRectFill(pThis, pThisCC, pCmd);
    5692                 break;
    5693             }
    5694 
    5695             case SVGA_CMD_RECT_COPY:
    5696             {
    5697                 SVGAFifoCmdRectCopy *pCmd = (SVGAFifoCmdRectCopy *)&pu8Cmd[cbCmd];
    5698                 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
    5699                 vmsvgaR3CmdRectCopy(pThis, pThisCC, pCmd);
    5700                 break;
    5701             }
    5702 
    5703             case SVGA_CMD_RECT_ROP_COPY:
    5704             {
    5705                 SVGAFifoCmdRectRopCopy *pCmd = (SVGAFifoCmdRectRopCopy *)&pu8Cmd[cbCmd];
    5706                 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
    5707                 vmsvgaR3CmdRectRopCopy(pThis, pThisCC, pCmd);
    5708                 break;
    5709             }
    5710 
    5711             case SVGA_CMD_ESCAPE:
    5712             {
    5713                 /* Followed by 'size' bytes of data. */
    5714                 SVGAFifoCmdEscape *pCmd = (SVGAFifoCmdEscape *)&pu8Cmd[cbCmd];
    5715                 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
    5716 
    5717                 ASSERT_GUEST_STMT_BREAK(pCmd->size < pThis->svga.cbFIFO - sizeof(SVGAFifoCmdEscape), CBstatus = SVGA_CB_STATUS_COMMAND_ERROR);
    5718                 RT_UNTRUSTED_VALIDATED_FENCE();
    5719 
    5720                 VMSVGA_INC_CMD_SIZE_BREAK(pCmd->size);
    5721                 vmsvgaR3CmdEscape(pThis, pThisCC, pCmd);
    5722                 break;
    5723             }
    5724 # ifdef VBOX_WITH_VMSVGA3D
    5725             case SVGA_CMD_DEFINE_GMR2:
    5726             {
    5727                 SVGAFifoCmdDefineGMR2 *pCmd = (SVGAFifoCmdDefineGMR2 *)&pu8Cmd[cbCmd];
    5728                 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
    5729                 vmsvgaR3CmdDefineGMR2(pThis, pThisCC, pCmd);
    5730                 break;
    5731             }
    5732 
    5733             case SVGA_CMD_REMAP_GMR2:
    5734             {
    5735                 /* Followed by page descriptors or guest ptr. */
    5736                 SVGAFifoCmdRemapGMR2 *pCmd = (SVGAFifoCmdRemapGMR2 *)&pu8Cmd[cbCmd];
    5737                 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
    5738 
    5739                 /* Calculate the size of what comes after next and fetch it. */
    5740                 uint32_t cbMore = 0;
    5741                 if (pCmd->flags & SVGA_REMAP_GMR2_VIA_GMR)
    5742                     cbMore = sizeof(SVGAGuestPtr);
    5743                 else
    5744                 {
    5745                     uint32_t const cbPageDesc = (pCmd->flags & SVGA_REMAP_GMR2_PPN64) ? sizeof(uint64_t) : sizeof(uint32_t);
    5746                     if (pCmd->flags & SVGA_REMAP_GMR2_SINGLE_PPN)
    5747                     {
    5748                         cbMore         = cbPageDesc;
    5749                         pCmd->numPages = 1;
    5750                     }
    5751                     else
    5752                     {
    5753                         ASSERT_GUEST_STMT_BREAK(pCmd->numPages <= pThis->svga.cbFIFO / cbPageDesc, CBstatus = SVGA_CB_STATUS_COMMAND_ERROR);
    5754                         cbMore = cbPageDesc * pCmd->numPages;
    5755                     }
    5756                 }
    5757                 VMSVGA_INC_CMD_SIZE_BREAK(cbMore);
    5758                 vmsvgaR3CmdRemapGMR2(pThis, pThisCC, pCmd);
    5759 #  ifdef DEBUG_GMR_ACCESS
    5760                 VMR3ReqCallWaitU(PDMDevHlpGetUVM(pDevIns), VMCPUID_ANY, (PFNRT)vmsvgaR3RegisterGmr, 2, pDevIns, pCmd->gmrId);
    5761 #  endif
    5762                 break;
    5763             }
    5764 # endif // VBOX_WITH_VMSVGA3D
    5765             case SVGA_CMD_DEFINE_SCREEN:
    5766             {
    5767                 /* The size of this command is specified by the guest and depends on capabilities. */
    5768                 SVGAFifoCmdDefineScreen *pCmd = (SVGAFifoCmdDefineScreen *)&pu8Cmd[cbCmd];
    5769                 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(pCmd->screen.structSize));
    5770                 ASSERT_GUEST_STMT_BREAK(pCmd->screen.structSize < pThis->svga.cbFIFO, CBstatus = SVGA_CB_STATUS_COMMAND_ERROR);
    5771                 RT_UNTRUSTED_VALIDATED_FENCE();
    5772 
    5773                 VMSVGA_INC_CMD_SIZE_BREAK(RT_MAX(sizeof(pCmd->screen.structSize), pCmd->screen.structSize) - sizeof(pCmd->screen.structSize));
    5774                 vmsvgaR3CmdDefineScreen(pThis, pThisCC, pCmd);
    5775                 break;
    5776             }
    5777 
    5778             case SVGA_CMD_DESTROY_SCREEN:
    5779             {
    5780                 SVGAFifoCmdDestroyScreen *pCmd = (SVGAFifoCmdDestroyScreen *)&pu8Cmd[cbCmd];
    5781                 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
    5782                 vmsvgaR3CmdDestroyScreen(pThis, pThisCC, pCmd);
    5783                 break;
    5784             }
    5785 
    5786             case SVGA_CMD_DEFINE_GMRFB:
    5787             {
    5788                 SVGAFifoCmdDefineGMRFB *pCmd = (SVGAFifoCmdDefineGMRFB *)&pu8Cmd[cbCmd];
    5789                 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
    5790                 vmsvgaR3CmdDefineGMRFB(pThis, pThisCC, pCmd);
    5791                 break;
    5792             }
    5793 
    5794             case SVGA_CMD_BLIT_GMRFB_TO_SCREEN:
    5795             {
    5796                 SVGAFifoCmdBlitGMRFBToScreen *pCmd = (SVGAFifoCmdBlitGMRFBToScreen *)&pu8Cmd[cbCmd];
    5797                 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
    5798                 vmsvgaR3CmdBlitGMRFBToScreen(pThis, pThisCC, pCmd);
    5799                 break;
    5800             }
    5801 
    5802             case SVGA_CMD_BLIT_SCREEN_TO_GMRFB:
    5803             {
    5804                 SVGAFifoCmdBlitScreenToGMRFB *pCmd = (SVGAFifoCmdBlitScreenToGMRFB *)&pu8Cmd[cbCmd];
    5805                 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
    5806                 vmsvgaR3CmdBlitScreenToGMRFB(pThis, pThisCC, pCmd);
    5807                 break;
    5808             }
    5809 
    5810             case SVGA_CMD_ANNOTATION_FILL:
    5811             {
    5812                 SVGAFifoCmdAnnotationFill *pCmd = (SVGAFifoCmdAnnotationFill *)&pu8Cmd[cbCmd];
    5813                 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
    5814                 vmsvgaR3CmdAnnotationFill(pThis, pThisCC, pCmd);
    5815                 break;
    5816             }
    5817 
    5818             case SVGA_CMD_ANNOTATION_COPY:
    5819             {
    5820                 SVGAFifoCmdAnnotationCopy *pCmd = (SVGAFifoCmdAnnotationCopy *)&pu8Cmd[cbCmd];
    5821                 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
    5822                 vmsvgaR3CmdAnnotationCopy(pThis, pThisCC, pCmd);
    5823                 break;
    5824             }
    5825 
    5826             default:
    5827             {
    5828 # ifdef VBOX_WITH_VMSVGA3D
    5829                 if (   cmdId >= SVGA_3D_CMD_BASE
    5830                     && cmdId <  SVGA_3D_CMD_MAX)
    5831                 {
    5832                     RT_UNTRUSTED_VALIDATED_FENCE();
    5833 
    5834                     /* All 3d commands start with a common header, which defines the identifier and the size
    5835                      * of the command. The identifier has been already read. Fetch the size.
    5836                      */
    5837                     uint32_t const *pcbMore = (uint32_t const *)&pu8Cmd[cbCmd];
    5838                     VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pcbMore));
    5839                     VMSVGA_INC_CMD_SIZE_BREAK(*pcbMore);
    5840                     if (RT_LIKELY(pThis->svga.f3DEnabled))
    5841                     { /* likely */ }
    5842                     else
    5843                     {
    5844                         LogRelMax(8, ("VMSVGA: 3D disabled, command %d skipped\n", cmdId));
    5845                         break;
    5846                     }
    5847 
    5848                     /* Command data begins after the 32 bit command length. */
    5849                     int rc = vmsvgaR3Process3dCmd(pThis, pThisCC, (SVGAFifo3dCmdId)cmdId, *pcbMore, pcbMore + 1);
    5850                     if (RT_SUCCESS(rc))
    5851                     { /* likely */ }
    5852                     else
    5853                     {
    5854                         CBstatus = SVGA_CB_STATUS_COMMAND_ERROR;
    5855                         break;
    5856                     }
    5857                 }
    5858                 else
    5859 # endif // VBOX_WITH_VMSVGA3D
    5860                 {
    5861                     /* Unsupported command. */
    5862                     STAM_REL_COUNTER_INC(&pSvgaR3State->StatFifoUnkCmds);
    5863                     ASSERT_GUEST_MSG_FAILED(("cmdId=%d\n", cmdId));
    5864                     CBstatus = SVGA_CB_STATUS_COMMAND_ERROR;
    5865                     break;
    5866                 }
    5867             }
    5868         }
    5869 
    5870         if (CBstatus != SVGA_CB_STATUS_COMPLETED)
    5871             break;
    5872 
    5873         pu8Cmd += cbCmd;
    5874         cbRemain -= cbCmd;
    5875     }
    5876 
    5877     Assert(cbRemain <= cbCommands);
    5878     *poffNextCmd = cbCommands - cbRemain;
    5879     return CBstatus;
    5880 }
    5881 
    5882 
    5883 /** Process command buffers.
    5884  *
    5885  * @param pDevIns     The device instance.
    5886  * @param pThis       The shared VGA/VMSVGA state.
    5887  * @param pThisCC     The VGA/VMSVGA state for the current context.
    5888  * @param pThread     Handle of the FIFO thread.
    5889  * @thread FIFO
    5890  */
    5891 static void vmsvgaR3CmdBufProcessBuffers(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, PPDMTHREAD pThread)
    5892 {
    5893     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    5894 
    5895     for (;;)
    5896     {
    5897         if (pThread->enmState != PDMTHREADSTATE_RUNNING)
    5898             break;
    5899 
    5900         /* See if there is a submitted buffer. */
    5901         PVMSVGACMDBUF pCmdBuf = NULL;
    5902 
    5903         int rc = RTCritSectEnter(&pSvgaR3State->CritSectCmdBuf);
    5904         AssertRC(rc);
    5905 
    5906         /* It seems that a higher queue index has a higher priority.
    5907          * See SVGACBContext in svga_reg.h from latest vmwgfx Linux driver.
    5908          */
    5909         for (unsigned i = RT_ELEMENTS(pSvgaR3State->apCmdBufCtxs); i > 0; --i)
    5910         {
    5911             PVMSVGACMDBUFCTX pCmdBufCtx = pSvgaR3State->apCmdBufCtxs[i - 1];
    5912             if (pCmdBufCtx)
    5913             {
    5914                 pCmdBuf = RTListRemoveFirst(&pCmdBufCtx->listSubmitted, VMSVGACMDBUF, nodeBuffer);
    5915                 if (pCmdBuf)
    5916                 {
    5917                     Assert(pCmdBufCtx->cSubmitted > 0);
    5918                     --pCmdBufCtx->cSubmitted;
    5919                     break;
    5920                 }
    5921             }
    5922         }
    5923 
    5924         if (!pCmdBuf)
    5925         {
    5926             ASMAtomicWriteU32(&pSvgaR3State->fCmdBuf, 0);
    5927             RTCritSectLeave(&pSvgaR3State->CritSectCmdBuf);
    5928             break;
    5929         }
    5930 
    5931         RTCritSectLeave(&pSvgaR3State->CritSectCmdBuf);
    5932 
    5933         SVGACBStatus CBstatus = SVGA_CB_STATUS_NONE;
    5934         uint32_t offNextCmd = 0;
    5935 
    5936         /* Process one buffer. */
    5937         CBstatus = vmsvgaR3CmdBufProcessCommands(pDevIns, pThis, pThisCC, pCmdBuf->pvCommands, pCmdBuf->hdr.length, &offNextCmd);
    5938 
    5939         uint32_t fIRQ = 0;
    5940         if (!RT_BOOL(pCmdBuf->hdr.flags & SVGA_CB_FLAG_NO_IRQ))
    5941             fIRQ |= SVGA_IRQFLAG_COMMAND_BUFFER;
    5942         if (CBstatus == SVGA_CB_STATUS_COMMAND_ERROR)
    5943             fIRQ |= SVGA_IRQFLAG_ERROR;
    5944 
    5945         vmsvgaR3CmdBufWriteStatus(pDevIns, pCmdBuf->GCPhysCB, CBstatus, offNextCmd);
    5946         if (fIRQ)
    5947             vmsvgaR3CmdBufRaiseIRQ(pDevIns, pThis, fIRQ);
    5948 
    5949         vmsvgaR3CmdBufFree(pCmdBuf);
    5950     }
    5951 }
    5952 
    5953 
    5954 /**
    5955  * Worker for vmsvgaR3FifoThread that handles an external command.
    5956  *
    5957  * @param   pDevIns         The device instance.
    5958  * @param   pThis           The shared VGA/VMSVGA instance data.
    5959  * @param   pThisCC         The VGA/VMSVGA state for ring-3.
    5960  */
    5961 static void vmsvgaR3FifoHandleExtCmd(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC)
    5962 {
    5963     uint8_t uExtCmd = pThis->svga.u8FIFOExtCommand;
    5964     switch (pThis->svga.u8FIFOExtCommand)
    5965     {
    5966         case VMSVGA_FIFO_EXTCMD_RESET:
    5967             Log(("vmsvgaR3FifoLoop: reset the fifo thread.\n"));
    5968             Assert(pThisCC->svga.pvFIFOExtCmdParam == NULL);
    5969 
    5970             vmsvgaR3ResetScreens(pThis, pThisCC);
    5971 # ifdef VBOX_WITH_VMSVGA3D
    5972             if (pThis->svga.f3DEnabled)
    5973             {
    5974                 /* The 3d subsystem must be reset from the fifo thread. */
    5975                 vmsvga3dReset(pThisCC);
    5976             }
    5977 # endif
    5978             break;
    5979 
    5980         case VMSVGA_FIFO_EXTCMD_POWEROFF:
    5981             Log(("vmsvgaR3FifoLoop: power off.\n"));
    5982             Assert(pThisCC->svga.pvFIFOExtCmdParam == NULL);
    5983 
    5984             /* The screens must be reset on the FIFO thread, because they may use 3D resources. */
    5985             vmsvgaR3ResetScreens(pThis, pThisCC);
    5986             break;
    5987 
    5988         case VMSVGA_FIFO_EXTCMD_TERMINATE:
    5989             Log(("vmsvgaR3FifoLoop: terminate the fifo thread.\n"));
    5990             Assert(pThisCC->svga.pvFIFOExtCmdParam == NULL);
    5991 # ifdef VBOX_WITH_VMSVGA3D
    5992             if (pThis->svga.f3DEnabled)
    5993             {
    5994                 /* The 3d subsystem must be shut down from the fifo thread. */
    5995                 vmsvga3dTerminate(pThisCC);
    5996             }
    5997 # endif
    5998             break;
    5999 
    6000         case VMSVGA_FIFO_EXTCMD_SAVESTATE:
    6001         {
    6002             Log(("vmsvgaR3FifoLoop: VMSVGA_FIFO_EXTCMD_SAVESTATE.\n"));
    6003             PSSMHANDLE pSSM = (PSSMHANDLE)pThisCC->svga.pvFIFOExtCmdParam;
    6004             AssertLogRelMsgBreak(RT_VALID_PTR(pSSM), ("pSSM=%p\n", pSSM));
    6005             vmsvgaR3SaveExecFifo(pDevIns->pHlpR3, pThisCC, pSSM);
    6006 # ifdef VBOX_WITH_VMSVGA3D
    6007             if (pThis->svga.f3DEnabled)
    6008                 vmsvga3dSaveExec(pDevIns, pThisCC, pSSM);
    6009 # endif
    6010             break;
    6011         }
    6012 
    6013         case VMSVGA_FIFO_EXTCMD_LOADSTATE:
    6014         {
    6015             Log(("vmsvgaR3FifoLoop: VMSVGA_FIFO_EXTCMD_LOADSTATE.\n"));
    6016             PVMSVGA_STATE_LOAD pLoadState = (PVMSVGA_STATE_LOAD)pThisCC->svga.pvFIFOExtCmdParam;
    6017             AssertLogRelMsgBreak(RT_VALID_PTR(pLoadState), ("pLoadState=%p\n", pLoadState));
    6018             vmsvgaR3LoadExecFifo(pDevIns->pHlpR3, pThis, pThisCC, pLoadState->pSSM, pLoadState->uVersion, pLoadState->uPass);
    6019 # ifdef VBOX_WITH_VMSVGA3D
    6020             if (pThis->svga.f3DEnabled)
    6021                 vmsvga3dLoadExec(pDevIns, pThis, pThisCC, pLoadState->pSSM, pLoadState->uVersion, pLoadState->uPass);
    6022 # endif
    6023             break;
    6024         }
    6025 
    6026         case VMSVGA_FIFO_EXTCMD_UPDATE_SURFACE_HEAP_BUFFERS:
    6027         {
    6028 # ifdef VBOX_WITH_VMSVGA3D
    6029             uint32_t sid = (uint32_t)(uintptr_t)pThisCC->svga.pvFIFOExtCmdParam;
    6030             Log(("vmsvgaR3FifoLoop: VMSVGA_FIFO_EXTCMD_UPDATE_SURFACE_HEAP_BUFFERS sid=%#x\n", sid));
    6031             vmsvga3dUpdateHeapBuffersForSurfaces(pThisCC, sid);
    6032 # endif
    6033             break;
    6034         }
    6035 
    6036 
    6037         default:
    6038             AssertLogRelMsgFailed(("uExtCmd=%#x pvFIFOExtCmdParam=%p\n", uExtCmd, pThisCC->svga.pvFIFOExtCmdParam));
    6039             break;
    6040     }
    6041 
    6042     /*
    6043      * Signal the end of the external command.
    6044      */
    6045     pThisCC->svga.pvFIFOExtCmdParam = NULL;
    6046     pThis->svga.u8FIFOExtCommand  = VMSVGA_FIFO_EXTCMD_NONE;
    6047     ASMMemoryFence(); /* paranoia^2 */
    6048     int rc = RTSemEventSignal(pThisCC->svga.hFIFOExtCmdSem);
    6049     AssertLogRelRC(rc);
    6050 }
    6051 
    6052 /**
    6053  * Worker for vmsvgaR3Destruct, vmsvgaR3Reset, vmsvgaR3Save and vmsvgaR3Load for
    6054  * doing a job on the FIFO thread (even when it's officially suspended).
    6055  *
    6056  * @returns VBox status code (fully asserted).
    6057  * @param   pDevIns         The device instance.
    6058  * @param   pThis           The shared VGA/VMSVGA instance data.
    6059  * @param   pThisCC         The VGA/VMSVGA state for ring-3.
    6060  * @param   uExtCmd         The command to execute on the FIFO thread.
    6061  * @param   pvParam         Pointer to command parameters.
    6062  * @param   cMsWait         The time to wait for the command, given in
    6063  *                          milliseconds.
    6064  */
    6065 static int vmsvgaR3RunExtCmdOnFifoThread(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC,
    6066                                          uint8_t uExtCmd, void *pvParam, RTMSINTERVAL cMsWait)
    6067 {
    6068     Assert(cMsWait >= RT_MS_1SEC * 5);
    6069     AssertLogRelMsg(pThis->svga.u8FIFOExtCommand == VMSVGA_FIFO_EXTCMD_NONE,
    6070                     ("old=%d new=%d\n", pThis->svga.u8FIFOExtCommand, uExtCmd));
    6071 
    6072     int rc;
    6073     PPDMTHREAD      pThread  = pThisCC->svga.pFIFOIOThread;
    6074     PDMTHREADSTATE  enmState = pThread->enmState;
    6075     if (enmState == PDMTHREADSTATE_SUSPENDED)
    6076     {
    6077         /*
    6078          * The thread is suspended, we have to temporarily wake it up so it can
    6079          * perform the task.
    6080          * (We ASSUME not racing code here, both wrt thread state and ext commands.)
    6081          */
    6082         Log(("vmsvgaR3RunExtCmdOnFifoThread: uExtCmd=%d enmState=SUSPENDED\n", uExtCmd));
    6083         /* Post the request. */
    6084         pThis->svga.fFifoExtCommandWakeup = true;
    6085         pThisCC->svga.pvFIFOExtCmdParam     = pvParam;
    6086         pThis->svga.u8FIFOExtCommand      = uExtCmd;
    6087         ASMMemoryFence(); /* paranoia^3 */
    6088 
    6089         /* Resume the thread. */
    6090         rc = PDMDevHlpThreadResume(pDevIns, pThread);
    6091         AssertLogRelRC(rc);
    6092         if (RT_SUCCESS(rc))
    6093         {
    6094             /* Wait. Take care in case the semaphore was already posted (same as below). */
    6095             rc = RTSemEventWait(pThisCC->svga.hFIFOExtCmdSem, cMsWait);
    6096             if (   rc == VINF_SUCCESS
    6097                 && pThis->svga.u8FIFOExtCommand == uExtCmd)
    6098                 rc = RTSemEventWait(pThisCC->svga.hFIFOExtCmdSem, cMsWait);
    6099             AssertLogRelMsg(pThis->svga.u8FIFOExtCommand != uExtCmd || RT_FAILURE_NP(rc),
    6100                             ("%#x %Rrc\n", pThis->svga.u8FIFOExtCommand, rc));
    6101 
    6102             /* suspend the thread */
    6103             pThis->svga.fFifoExtCommandWakeup = false;
    6104             int rc2 = PDMDevHlpThreadSuspend(pDevIns, pThread);
    6105             AssertLogRelRC(rc2);
    6106             if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
    6107                 rc = rc2;
    6108         }
    6109         pThis->svga.fFifoExtCommandWakeup = false;
    6110         pThisCC->svga.pvFIFOExtCmdParam     = NULL;
    6111     }
    6112     else if (enmState == PDMTHREADSTATE_RUNNING)
    6113     {
    6114         /*
    6115          * The thread is running, should only happen during reset and vmsvga3dsfc.
    6116          * We ASSUME not racing code here, both wrt thread state and ext commands.
    6117          */
    6118         Log(("vmsvgaR3RunExtCmdOnFifoThread: uExtCmd=%d enmState=RUNNING\n", uExtCmd));
    6119         Assert(uExtCmd == VMSVGA_FIFO_EXTCMD_RESET || uExtCmd == VMSVGA_FIFO_EXTCMD_UPDATE_SURFACE_HEAP_BUFFERS || uExtCmd == VMSVGA_FIFO_EXTCMD_POWEROFF);
    6120 
    6121         /* Post the request. */
    6122         pThisCC->svga.pvFIFOExtCmdParam = pvParam;
    6123         pThis->svga.u8FIFOExtCommand  = uExtCmd;
    6124         ASMMemoryFence(); /* paranoia^2 */
    6125         rc = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->svga.hFIFORequestSem);
    6126         AssertLogRelRC(rc);
    6127 
    6128         /* Wait. Take care in case the semaphore was already posted (same as above). */
    6129         rc = RTSemEventWait(pThisCC->svga.hFIFOExtCmdSem, cMsWait);
    6130         if (   rc == VINF_SUCCESS
    6131             && pThis->svga.u8FIFOExtCommand == uExtCmd)
    6132             rc = RTSemEventWait(pThisCC->svga.hFIFOExtCmdSem, cMsWait); /* it was already posted, retry the wait. */
    6133         AssertLogRelMsg(pThis->svga.u8FIFOExtCommand != uExtCmd || RT_FAILURE_NP(rc),
    6134                         ("%#x %Rrc\n", pThis->svga.u8FIFOExtCommand, rc));
    6135 
    6136         pThisCC->svga.pvFIFOExtCmdParam = NULL;
    6137     }
    6138     else
    6139     {
    6140         /*
    6141          * Something is wrong with the thread!
    6142          */
    6143         AssertLogRelMsgFailed(("uExtCmd=%d enmState=%d\n", uExtCmd, enmState));
    6144         rc = VERR_INVALID_STATE;
    6145     }
    6146     return rc;
    6147 }
    6148 
    6149 
    6150 /**
    6151  * Marks the FIFO non-busy, notifying any waiting EMTs.
    6152  *
    6153  * @param   pDevIns         The device instance.
    6154  * @param   pThis           The shared VGA/VMSVGA instance data.
    6155  * @param   pThisCC         The VGA/VMSVGA state for ring-3.
    6156  * @param   pSVGAState      Pointer to the ring-3 only SVGA state data.
    6157  * @param   offFifoMin      The start byte offset of the command FIFO.
    6158  */
    6159 static void vmsvgaR3FifoSetNotBusy(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, PVMSVGAR3STATE pSVGAState, uint32_t offFifoMin)
    6160 {
    6161     ASMAtomicAndU32(&pThis->svga.fBusy, ~(VMSVGA_BUSY_F_FIFO | VMSVGA_BUSY_F_EMT_FORCE));
    6162     if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_BUSY, offFifoMin))
    6163         vmsvgaHCSafeFifoBusyRegUpdate(pThis, pThisCC, pThis->svga.fBusy != 0);
    6164 
    6165     /* Wake up any waiting EMTs. */
    6166     if (pSVGAState->cBusyDelayedEmts > 0)
    6167     {
    6168 # ifdef VMSVGA_USE_EMT_HALT_CODE
    6169         PVM pVM = PDMDevHlpGetVM(pDevIns);
    6170         VMCPUID idCpu = VMCpuSetFindLastPresentInternal(&pSVGAState->BusyDelayedEmts);
    6171         if (idCpu != NIL_VMCPUID)
    6172         {
    6173             VMR3NotifyCpuDeviceReady(pVM, idCpu);
    6174             while (idCpu-- > 0)
    6175                 if (VMCPUSET_IS_PRESENT(&pSVGAState->BusyDelayedEmts, idCpu))
    6176                     VMR3NotifyCpuDeviceReady(pVM, idCpu);
    6177         }
    6178 # else
    6179         int rc2 = RTSemEventMultiSignal(pSVGAState->hBusyDelayedEmts);
    6180         AssertRC(rc2);
    6181 # endif
    6182     }
    6183 }
    6184 
    6185 /**
    6186  * Reads (more) payload into the command buffer.
    6187  *
    6188  * @returns pbBounceBuf on success
    6189  * @retval  (void *)1 if the thread was requested to stop.
    6190  * @retval  NULL on FIFO error.
    6191  *
    6192  * @param   cbPayloadReq    The number of bytes of payload requested.
    6193  * @param   pFIFO           The FIFO.
    6194  * @param   offCurrentCmd   The FIFO byte offset of the current command.
    6195  * @param   offFifoMin      The start byte offset of the command FIFO.
    6196  * @param   offFifoMax      The end byte offset of the command FIFO.
    6197  * @param   pbBounceBuf     The bounch buffer. Same size as the entire FIFO, so
    6198  *                          always sufficient size.
    6199  * @param   pcbAlreadyRead  How much payload we've already read into the bounce
    6200  *                          buffer. (We will NEVER re-read anything.)
    6201  * @param   pThread         The calling PDM thread handle.
    6202  * @param   pThis           The shared VGA/VMSVGA instance data.
    6203  * @param   pSVGAState      Pointer to the ring-3 only SVGA state data. For
    6204  *                          statistics collection.
    6205  * @param   pDevIns         The device instance.
    6206  */
    6207 static void *vmsvgaR3FifoGetCmdPayload(uint32_t cbPayloadReq, uint32_t RT_UNTRUSTED_VOLATILE_GUEST *pFIFO,
    6208                                        uint32_t offCurrentCmd, uint32_t offFifoMin, uint32_t offFifoMax,
    6209                                        uint8_t *pbBounceBuf, uint32_t *pcbAlreadyRead,
    6210                                        PPDMTHREAD pThread, PVGASTATE pThis, PVMSVGAR3STATE pSVGAState, PPDMDEVINS pDevIns)
    6211 {
    6212     Assert(pbBounceBuf);
    6213     Assert(pcbAlreadyRead);
    6214     Assert(offFifoMin < offFifoMax);
    6215     Assert(offCurrentCmd >= offFifoMin && offCurrentCmd < offFifoMax);
    6216     Assert(offFifoMax <= pThis->svga.cbFIFO);
    6217 
    6218     /*
    6219      * Check if the requested payload size has already been satisfied                                                                                                .
    6220      *                                                                                                                                                       .
    6221      * When called to read more, the caller is responsible for making sure the                                                                               .
    6222      * new command size (cbRequsted) never is smaller than what has already                                                                                  .
    6223      * been read.
    6224      */
    6225     uint32_t cbAlreadyRead = *pcbAlreadyRead;
    6226     if (cbPayloadReq <= cbAlreadyRead)
    6227     {
    6228         AssertLogRelReturn(cbPayloadReq == cbAlreadyRead, NULL);
    6229         return pbBounceBuf;
    6230     }
    6231 
    6232     /*
    6233      * Commands bigger than the fifo buffer are invalid.
    6234      */
    6235     uint32_t const cbFifoCmd = offFifoMax - offFifoMin;
    6236     AssertMsgReturnStmt(cbPayloadReq <= cbFifoCmd, ("cbPayloadReq=%#x cbFifoCmd=%#x\n", cbPayloadReq, cbFifoCmd),
    6237                         STAM_REL_COUNTER_INC(&pSVGAState->StatFifoErrors),
    6238                         NULL);
    6239 
    6240     /*
    6241      * Move offCurrentCmd past the command dword.
    6242      */
    6243     offCurrentCmd += sizeof(uint32_t);
    6244     if (offCurrentCmd >= offFifoMax)
    6245         offCurrentCmd = offFifoMin;
    6246 
    6247     /*
    6248      * Do we have sufficient payload data available already?
    6249      * The host should not read beyond [SVGA_FIFO_NEXT_CMD], therefore '>=' in the condition below.
    6250      */
    6251     uint32_t cbAfter, cbBefore;
    6252     uint32_t offNextCmd = pFIFO[SVGA_FIFO_NEXT_CMD];
    6253     RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
    6254     if (offNextCmd >= offCurrentCmd)
    6255     {
    6256         if (RT_LIKELY(offNextCmd < offFifoMax))
    6257             cbAfter = offNextCmd - offCurrentCmd;
    6258         else
    6259         {
    6260             STAM_REL_COUNTER_INC(&pSVGAState->StatFifoErrors);
    6261             LogRelMax(16, ("vmsvgaR3FifoGetCmdPayload: Invalid offNextCmd=%#x (offFifoMin=%#x offFifoMax=%#x)\n",
    6262                            offNextCmd, offFifoMin, offFifoMax));
    6263             cbAfter = offFifoMax - offCurrentCmd;
    6264         }
    6265         cbBefore = 0;
    6266     }
    6267     else
    6268     {
    6269         cbAfter  = offFifoMax - offCurrentCmd;
    6270         if (offNextCmd >= offFifoMin)
    6271             cbBefore = offNextCmd - offFifoMin;
    6272         else
    6273         {
    6274             STAM_REL_COUNTER_INC(&pSVGAState->StatFifoErrors);
    6275             LogRelMax(16, ("vmsvgaR3FifoGetCmdPayload: Invalid offNextCmd=%#x (offFifoMin=%#x offFifoMax=%#x)\n",
    6276                            offNextCmd, offFifoMin, offFifoMax));
    6277             cbBefore = 0;
    6278         }
    6279     }
    6280     if (cbAfter + cbBefore < cbPayloadReq)
    6281     {
    6282         /*
    6283          * Insufficient, must wait for it to arrive.
    6284          */
    6285 /** @todo Should clear the busy flag here to maybe encourage the guest to wake us up. */
    6286         STAM_REL_PROFILE_START(&pSVGAState->StatFifoStalls, Stall);
    6287         for (uint32_t i = 0;; i++)
    6288         {
    6289             if (pThread->enmState != PDMTHREADSTATE_RUNNING)
    6290             {
    6291                 STAM_REL_PROFILE_STOP(&pSVGAState->StatFifoStalls, Stall);
    6292                 return (void *)(uintptr_t)1;
    6293             }
    6294             Log(("Guest still copying (%x vs %x) current %x next %x stop %x loop %u; sleep a bit\n",
    6295                  cbPayloadReq, cbAfter + cbBefore, offCurrentCmd, offNextCmd, pFIFO[SVGA_FIFO_STOP], i));
    6296 
    6297             PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pThis->svga.hFIFORequestSem, i < 16 ? 1 : 2);
    6298 
    6299             offNextCmd = pFIFO[SVGA_FIFO_NEXT_CMD];
    6300             RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
    6301             if (offNextCmd >= offCurrentCmd)
    6302             {
    6303                 cbAfter = RT_MIN(offNextCmd, offFifoMax) - offCurrentCmd;
    6304                 cbBefore = 0;
    6305             }
    6306             else
    6307             {
    6308                 cbAfter  = offFifoMax - offCurrentCmd;
    6309                 cbBefore = RT_MAX(offNextCmd, offFifoMin) - offFifoMin;
    6310             }
    6311 
    6312             if (cbAfter + cbBefore >= cbPayloadReq)
    6313                 break;
    6314         }
    6315         STAM_REL_PROFILE_STOP(&pSVGAState->StatFifoStalls, Stall);
    6316     }
    6317 
    6318     /*
    6319      * Copy out the memory and update what pcbAlreadyRead points to.
    6320      */
    6321     if (cbAfter >= cbPayloadReq)
    6322         memcpy(pbBounceBuf + cbAlreadyRead,
    6323                (uint8_t *)pFIFO + offCurrentCmd + cbAlreadyRead,
    6324                cbPayloadReq - cbAlreadyRead);
    6325     else
    6326     {
    6327         LogFlow(("Split data buffer at %x (%u-%u)\n", offCurrentCmd, cbAfter, cbBefore));
    6328         if (cbAlreadyRead < cbAfter)
    6329         {
    6330             memcpy(pbBounceBuf + cbAlreadyRead,
    6331                    (uint8_t *)pFIFO + offCurrentCmd + cbAlreadyRead,
    6332                    cbAfter - cbAlreadyRead);
    6333             cbAlreadyRead = cbAfter;
    6334         }
    6335         memcpy(pbBounceBuf + cbAlreadyRead,
    6336                (uint8_t *)pFIFO + offFifoMin + cbAlreadyRead - cbAfter,
    6337                cbPayloadReq - cbAlreadyRead);
    6338     }
    6339     *pcbAlreadyRead = cbPayloadReq;
    6340     RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
    6341     return pbBounceBuf;
    6342 }
    6343 
    6344 
    6345 /**
    6346  * Sends cursor position and visibility information from the FIFO to the front-end.
    6347  * @returns SVGA_FIFO_CURSOR_COUNT value used.
    6348  */
    6349 static uint32_t
    6350 vmsvgaR3FifoUpdateCursor(PVGASTATECC pThisCC, PVMSVGAR3STATE  pSVGAState, uint32_t RT_UNTRUSTED_VOLATILE_GUEST *pFIFO,
    6351                          uint32_t offFifoMin,  uint32_t uCursorUpdateCount,
    6352                          uint32_t *pxLast, uint32_t *pyLast, uint32_t *pfLastVisible)
    6353 {
    6354     /*
    6355      * Check if the cursor update counter has changed and try get a stable
    6356      * set of values if it has.  This is race-prone, especially consindering
    6357      * the screen ID, but little we can do about that.
    6358      */
    6359     uint32_t x, y, fVisible, idScreen;
    6360     for (uint32_t i = 0; ; i++)
    6361     {
    6362         x        = pFIFO[SVGA_FIFO_CURSOR_X];
    6363         y        = pFIFO[SVGA_FIFO_CURSOR_Y];
    6364         fVisible = pFIFO[SVGA_FIFO_CURSOR_ON];
    6365         idScreen = VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_CURSOR_SCREEN_ID, offFifoMin)
    6366                  ? pFIFO[SVGA_FIFO_CURSOR_SCREEN_ID] : SVGA_ID_INVALID;
    6367         if (   uCursorUpdateCount == pFIFO[SVGA_FIFO_CURSOR_COUNT]
    6368             || i > 3)
    6369             break;
    6370         if (i == 0)
    6371             STAM_REL_COUNTER_INC(&pSVGAState->StatFifoCursorFetchAgain);
    6372         ASMNopPause();
    6373         uCursorUpdateCount = pFIFO[SVGA_FIFO_CURSOR_COUNT];
    6374     }
    6375 
    6376     /*
    6377      * Check if anything has changed, as calling into pDrv is not light-weight.
    6378      */
    6379     if (   *pxLast == x
    6380         && *pyLast == y
    6381         && (idScreen != SVGA_ID_INVALID || *pfLastVisible == fVisible))
    6382         STAM_REL_COUNTER_INC(&pSVGAState->StatFifoCursorNoChange);
    6383     else
    6384     {
    6385         /*
    6386          * Detected changes.
    6387          *
    6388          * We handle global, not per-screen visibility information by sending
    6389          * pfnVBVAMousePointerShape without shape data.
    6390          */
    6391         *pxLast = x;
    6392         *pyLast = y;
    6393         uint32_t fFlags = VBVA_CURSOR_VALID_DATA;
    6394         if (idScreen != SVGA_ID_INVALID)
    6395             fFlags |= VBVA_CURSOR_SCREEN_RELATIVE;
    6396         else if (*pfLastVisible != fVisible)
    6397         {
    6398             LogRel2(("vmsvgaR3FifoUpdateCursor: fVisible %d fLastVisible %d (%d,%d)\n", fVisible, *pfLastVisible, x, y));
    6399             *pfLastVisible = fVisible;
    6400             pThisCC->pDrv->pfnVBVAMousePointerShape(pThisCC->pDrv, RT_BOOL(fVisible), false, 0, 0, 0, 0, NULL);
    6401             STAM_REL_COUNTER_INC(&pSVGAState->StatFifoCursorVisiblity);
    6402         }
    6403         pThisCC->pDrv->pfnVBVAReportCursorPosition(pThisCC->pDrv, fFlags, idScreen, x, y);
    6404         STAM_REL_COUNTER_INC(&pSVGAState->StatFifoCursorPosition);
    6405     }
    6406 
    6407     /*
    6408      * Update done.  Signal this to the guest.
    6409      */
    6410     pFIFO[SVGA_FIFO_CURSOR_LAST_UPDATED] = uCursorUpdateCount;
    6411 
    6412     return uCursorUpdateCount;
    6413 }
    6414 
    6415 
    6416 /**
    6417  * Checks if there is work to be done, either cursor updating or FIFO commands.
    6418  *
    6419  * @returns true if pending work, false if not.
    6420  * @param   pThisCC             The VGA/VMSVGA state for ring-3.
    6421  * @param   uLastCursorCount    The last cursor update counter value.
    6422  */
    6423 DECLINLINE(bool) vmsvgaR3FifoHasWork(PVGASTATECC pThisCC, uint32_t uLastCursorCount)
    6424 {
    6425     /* If FIFO does not exist than there is nothing to do. Command buffers also require the enabled FIFO. */
    6426     uint32_t RT_UNTRUSTED_VOLATILE_GUEST * const pFIFO = pThisCC->svga.pau32FIFO;
    6427     AssertReturn(pFIFO, false);
    6428 
    6429     if (vmsvgaR3CmdBufHasWork(pThisCC))
    6430         return true;
    6431 
    6432     if (pFIFO[SVGA_FIFO_NEXT_CMD] != pFIFO[SVGA_FIFO_STOP])
    6433         return true;
    6434 
    6435     if (   uLastCursorCount != pFIFO[SVGA_FIFO_CURSOR_COUNT]
    6436         && VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_CURSOR_LAST_UPDATED, pFIFO[SVGA_FIFO_MIN]))
    6437         return true;
    6438 
    6439     return false;
    6440 }
    6441 
    6442 
    6443 /**
    6444  * Called by the VGA refresh timer to wake up the FIFO thread when needed.
    6445  *
    6446  * @param   pDevIns     The device instance.
    6447  * @param   pThis       The shared VGA/VMSVGA instance data.
    6448  * @param   pThisCC     The VGA/VMSVGA state for ring-3.
    6449  */
    6450 void vmsvgaR3FifoWatchdogTimer(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC)
    6451 {
    6452     /* Caller already checked pThis->svga.fFIFOThreadSleeping, so we only have
    6453        to recheck it before doing the signalling. */
    6454     if (   vmsvgaR3FifoHasWork(pThisCC, ASMAtomicReadU32(&pThis->svga.uLastCursorUpdateCount))
    6455         && pThis->svga.fFIFOThreadSleeping)
    6456     {
    6457         int rc = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->svga.hFIFORequestSem);
    6458         AssertRC(rc);
    6459         STAM_REL_COUNTER_INC(&pThisCC->svga.pSvgaR3State->StatFifoWatchdogWakeUps);
    6460     }
    6461 }
    6462 
    6463 
    6464 /**
    6465  * Called by the FIFO thread to process pending actions.
    6466  *
    6467  * @param   pDevIns     The device instance.
    6468  * @param   pThis       The shared VGA/VMSVGA instance data.
    6469  * @param   pThisCC     The VGA/VMSVGA state for ring-3.
    6470  */
    6471 void vmsvgaR3FifoPendingActions(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC)
    6472 {
    6473     RT_NOREF(pDevIns);
    6474 
    6475     /* Currently just mode changes. */
    6476     if (ASMBitTestAndClear(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE_BIT))
    6477     {
    6478         vmsvgaR3ChangeMode(pThis, pThisCC);
    6479 # ifdef VBOX_WITH_VMSVGA3D
    6480         if (pThisCC->svga.p3dState != NULL)
    6481             vmsvga3dChangeMode(pThisCC);
    6482 # endif
    6483     }
    6484 }
    6485 
    6486 
    6487 /*
    6488  * These two macros are put outside vmsvgaR3FifoLoop because doxygen gets confused,
    6489  * even the latest version, and thinks we're documenting vmsvgaR3FifoLoop. Sigh.
    6490  */
    6491 /** @def VMSVGAFIFO_GET_CMD_BUFFER_BREAK
    6492  * Macro for shortening calls to vmsvgaR3FifoGetCmdPayload.
    6493  *
    6494  * Will break out of the switch on failure.
    6495  * Will restart and quit the loop if the thread was requested to stop.
    6496  *
    6497  * @param   a_PtrVar        Request variable pointer.
    6498  * @param   a_Type          Request typedef (not pointer) for casting.
    6499  * @param   a_cbPayloadReq  How much payload to fetch.
    6500  * @remarks Accesses a bunch of variables in the current scope!
    6501  */
    6502 # define VMSVGAFIFO_GET_CMD_BUFFER_BREAK(a_PtrVar, a_Type, a_cbPayloadReq) \
    6503             if (1) { \
    6504                 (a_PtrVar) = (a_Type *)vmsvgaR3FifoGetCmdPayload((a_cbPayloadReq), pFIFO, offCurrentCmd, offFifoMin, offFifoMax, \
    6505                                                                  pbBounceBuf, &cbPayload, pThread, pThis, pSVGAState, pDevIns); \
    6506                 if (RT_UNLIKELY((uintptr_t)(a_PtrVar) < 2)) { if ((uintptr_t)(a_PtrVar) == 1) continue; break; } \
    6507                 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE(); \
    6508             } else do {} while (0)
    6509 /* @def VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK
    6510  * Macro for shortening calls to vmsvgaR3FifoGetCmdPayload for refetching the
    6511  * buffer after figuring out the actual command size.
    6512  *
    6513  * Will break out of the switch on failure.
    6514  *
    6515  * @param   a_PtrVar        Request variable pointer.
    6516  * @param   a_Type          Request typedef (not pointer) for casting.
    6517  * @param   a_cbPayloadReq  How much payload to fetch.
    6518  * @remarks Accesses a bunch of variables in the current scope!
    6519  */
    6520 # define VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(a_PtrVar, a_Type, a_cbPayloadReq) \
    6521             if (1) { \
    6522                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(a_PtrVar, a_Type, a_cbPayloadReq); \
    6523             } else do {} while (0)
    6524 
    6525 /**
    6526  * @callback_method_impl{PFNPDMTHREADDEV, The async FIFO handling thread.}
    6527  */
    6528 static DECLCALLBACK(int) vmsvgaR3FifoLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
    6529 {
    6530     PVGASTATE       pThis      = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
    6531     PVGASTATER3     pThisCC    = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
    6532     PVMSVGAR3STATE  pSVGAState = pThisCC->svga.pSvgaR3State;
    6533     int             rc;
    6534 
    6535 # if defined(VBOX_WITH_VMSVGA3D) && defined(RT_OS_LINUX)
    6536     if (pThis->svga.f3DEnabled)
    6537     {
    6538         /* The FIFO thread may use X API for accelerated screen output. */
    6539         XInitThreads();
    6540     }
    6541 # endif
    6542 
    6543     if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
    6544         return VINF_SUCCESS;
    6545 
    6546     /*
    6547      * Special mode where we only execute an external command and the go back
    6548      * to being suspended.  Currently, all ext cmds ends up here, with the reset
    6549      * one also being eligble for runtime execution further down as well.
    6550      */
    6551     if (pThis->svga.fFifoExtCommandWakeup)
    6552     {
    6553         vmsvgaR3FifoHandleExtCmd(pDevIns, pThis, pThisCC);
    6554         while (pThread->enmState == PDMTHREADSTATE_RUNNING)
    6555             if (pThis->svga.u8FIFOExtCommand == VMSVGA_FIFO_EXTCMD_NONE)
    6556                 PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pThis->svga.hFIFORequestSem, RT_MS_1MIN);
    6557             else
    6558                 vmsvgaR3FifoHandleExtCmd(pDevIns, pThis, pThisCC);
    6559         return VINF_SUCCESS;
    6560     }
    6561 
    6562 
    6563     /*
    6564      * Signal the semaphore to make sure we don't wait for 250ms after a
    6565      * suspend & resume scenario (see vmsvgaR3FifoGetCmdPayload).
    6566      */
    6567     PDMDevHlpSUPSemEventSignal(pDevIns, pThis->svga.hFIFORequestSem);
    6568 
    6569     /*
    6570      * Allocate a bounce buffer for command we get from the FIFO.
    6571      * (All code must return via the end of the function to free this buffer.)
    6572      */
    6573     uint8_t *pbBounceBuf = (uint8_t *)RTMemAllocZ(pThis->svga.cbFIFO);
    6574     AssertReturn(pbBounceBuf, VERR_NO_MEMORY);
    6575 
    6576     /*
    6577      * Polling/sleep interval config.
    6578      *
    6579      * We wait for an a short interval if the guest has recently given us work
    6580      * to do, but the interval increases the longer we're kept idle.  Once we've
    6581      * reached the refresh timer interval, we'll switch to extended waits,
    6582      * depending on it or the guest to kick us into action when needed.
    6583      *
    6584      * Should the refresh time go fishing, we'll just continue increasing the
    6585      * sleep length till we reaches the 250 ms max after about 16 seconds.
    6586      */
    6587     RTMSINTERVAL const  cMsMinSleep           = 16;
    6588     RTMSINTERVAL const  cMsIncSleep           = 2;
    6589     RTMSINTERVAL const  cMsMaxSleep           = 250;
    6590     RTMSINTERVAL const  cMsExtendedSleep      = 15 * RT_MS_1SEC; /* Regular paranoia dictates that this cannot be indefinite. */
    6591     RTMSINTERVAL        cMsSleep              = cMsMaxSleep;
    6592 
    6593     /*
    6594      * Cursor update state (SVGA_FIFO_CAP_CURSOR_BYPASS_3).
    6595      *
    6596      * Initialize with values that will detect an update from the guest.
    6597      * Make sure that if the guest never updates the cursor position, then the device does not report it.
    6598      * The guest has to change the value of uLastCursorUpdateCount, when the cursor position is actually updated.
    6599      * xLastCursor, yLastCursor and fLastCursorVisible are set to report the first update.
    6600      */
    6601     uint32_t RT_UNTRUSTED_VOLATILE_GUEST * const pFIFO = pThisCC->svga.pau32FIFO;
    6602     pThis->svga.uLastCursorUpdateCount = pFIFO[SVGA_FIFO_CURSOR_COUNT];
    6603     uint32_t xLastCursor        = ~pFIFO[SVGA_FIFO_CURSOR_X];
    6604     uint32_t yLastCursor        = ~pFIFO[SVGA_FIFO_CURSOR_Y];
    6605     uint32_t fLastCursorVisible = ~pFIFO[SVGA_FIFO_CURSOR_ON];
    6606 
    6607     /*
    6608      * The FIFO loop.
    6609      */
    6610     LogFlow(("vmsvgaR3FifoLoop: started loop\n"));
    6611     bool fBadOrDisabledFifo = false;
    6612     while (pThread->enmState == PDMTHREADSTATE_RUNNING)
    6613     {
    6614 # if defined(RT_OS_DARWIN) && defined(VBOX_WITH_VMSVGA3D)
    6615         /*
    6616          * Should service the run loop every so often.
    6617          */
    6618         if (pThis->svga.f3DEnabled)
    6619             vmsvga3dCocoaServiceRunLoop();
    6620 # endif
    6621 
    6622         /* First check any pending actions. */
    6623         vmsvgaR3FifoPendingActions(pDevIns, pThis, pThisCC);
    6624 
    6625         /*
    6626          * Unless there's already work pending, go to sleep for a short while.
    6627          * (See polling/sleep interval config above.)
    6628          */
    6629         if (   fBadOrDisabledFifo
    6630             || !vmsvgaR3FifoHasWork(pThisCC, pThis->svga.uLastCursorUpdateCount))
    6631         {
    6632             ASMAtomicWriteBool(&pThis->svga.fFIFOThreadSleeping, true);
    6633             Assert(pThis->cMilliesRefreshInterval > 0);
    6634             if (cMsSleep < pThis->cMilliesRefreshInterval)
    6635                 rc = PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pThis->svga.hFIFORequestSem, cMsSleep);
    6636             else
    6637             {
    6638 # ifdef VMSVGA_USE_FIFO_ACCESS_HANDLER
    6639                 int rc2 = PGMHandlerPhysicalReset(PDMDevHlpGetVM(pDevIns), pThis->svga.GCPhysFIFO);
    6640                 AssertRC(rc2); /* No break. Racing EMTs unmapping and remapping the region. */
    6641 # endif
    6642                 if (   !fBadOrDisabledFifo
    6643                     && vmsvgaR3FifoHasWork(pThisCC, pThis->svga.uLastCursorUpdateCount))
    6644                     rc = VINF_SUCCESS;
    6645                 else
    6646                 {
    6647                     STAM_REL_PROFILE_START(&pSVGAState->StatFifoExtendedSleep, Acc);
    6648                     rc = PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pThis->svga.hFIFORequestSem, cMsExtendedSleep);
    6649                     STAM_REL_PROFILE_STOP(&pSVGAState->StatFifoExtendedSleep, Acc);
    6650                 }
    6651             }
    6652             ASMAtomicWriteBool(&pThis->svga.fFIFOThreadSleeping, false);
    6653             AssertBreak(RT_SUCCESS(rc) || rc == VERR_TIMEOUT || rc == VERR_INTERRUPTED);
    6654             if (pThread->enmState != PDMTHREADSTATE_RUNNING)
    6655             {
    6656                 LogFlow(("vmsvgaR3FifoLoop: thread state %x\n", pThread->enmState));
    6657                 break;
    6658             }
    6659         }
    6660         else
    6661             rc = VINF_SUCCESS;
    6662         fBadOrDisabledFifo = false;
    6663         if (rc == VERR_TIMEOUT)
    6664         {
    6665             if (!vmsvgaR3FifoHasWork(pThisCC, pThis->svga.uLastCursorUpdateCount))
    6666             {
    6667                 cMsSleep = RT_MIN(cMsSleep + cMsIncSleep, cMsMaxSleep);
    6668                 continue;
    6669             }
    6670             STAM_REL_COUNTER_INC(&pSVGAState->StatFifoTodoTimeout);
    6671 
    6672             Log(("vmsvgaR3FifoLoop: timeout\n"));
    6673         }
    6674         else if (vmsvgaR3FifoHasWork(pThisCC, pThis->svga.uLastCursorUpdateCount))
    6675             STAM_REL_COUNTER_INC(&pSVGAState->StatFifoTodoWoken);
    6676         cMsSleep = cMsMinSleep;
    6677 
    6678         Log(("vmsvgaR3FifoLoop: enabled=%d configured=%d busy=%d\n", pThis->svga.fEnabled, pThis->svga.fConfigured, pFIFO[SVGA_FIFO_BUSY]));
    6679         Log(("vmsvgaR3FifoLoop: min  %x max  %x\n", pFIFO[SVGA_FIFO_MIN], pFIFO[SVGA_FIFO_MAX]));
    6680         Log(("vmsvgaR3FifoLoop: next %x stop %x\n", pFIFO[SVGA_FIFO_NEXT_CMD], pFIFO[SVGA_FIFO_STOP]));
    6681 
    6682         /*
    6683          * Handle external commands (currently only reset).
    6684          */
    6685         if (pThis->svga.u8FIFOExtCommand != VMSVGA_FIFO_EXTCMD_NONE)
    6686         {
    6687             vmsvgaR3FifoHandleExtCmd(pDevIns, pThis, pThisCC);
    6688             continue;
    6689         }
    6690 
    6691         /*
    6692          * The device must be enabled and configured.
    6693          */
    6694         if (   !pThis->svga.fEnabled
    6695             || !pThis->svga.fConfigured)
    6696         {
    6697             vmsvgaR3FifoSetNotBusy(pDevIns, pThis, pThisCC, pSVGAState, pFIFO[SVGA_FIFO_MIN]);
    6698             fBadOrDisabledFifo = true;
    6699             cMsSleep           = cMsMaxSleep; /* cheat */
    6700             continue;
    6701         }
    6702 
    6703         /*
    6704          * Get and check the min/max values.  We ASSUME that they will remain
    6705          * unchanged while we process requests.  A further ASSUMPTION is that
    6706          * the guest won't mess with SVGA_FIFO_NEXT_CMD while we're busy, so
    6707          * we don't read it back while in the loop.
    6708          */
    6709         uint32_t const offFifoMin    = pFIFO[SVGA_FIFO_MIN];
    6710         uint32_t const offFifoMax    = pFIFO[SVGA_FIFO_MAX];
    6711         uint32_t       offCurrentCmd = pFIFO[SVGA_FIFO_STOP];
    6712         RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
    6713         if (RT_UNLIKELY(   !VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_STOP, offFifoMin)
    6714                         || offFifoMax <= offFifoMin
    6715                         || offFifoMax > pThis->svga.cbFIFO
    6716                         || (offFifoMax & 3) != 0
    6717                         || (offFifoMin & 3) != 0
    6718                         || offCurrentCmd < offFifoMin
    6719                         || offCurrentCmd > offFifoMax))
    6720         {
    6721             STAM_REL_COUNTER_INC(&pSVGAState->StatFifoErrors);
    6722             LogRelMax(8, ("vmsvgaR3FifoLoop: Bad fifo: min=%#x stop=%#x max=%#x\n", offFifoMin, offCurrentCmd, offFifoMax));
    6723             vmsvgaR3FifoSetNotBusy(pDevIns, pThis, pThisCC, pSVGAState, offFifoMin);
    6724             fBadOrDisabledFifo = true;
    6725             continue;
    6726         }
    6727         RT_UNTRUSTED_VALIDATED_FENCE();
    6728         if (RT_UNLIKELY(offCurrentCmd & 3))
    6729         {
    6730             STAM_REL_COUNTER_INC(&pSVGAState->StatFifoErrors);
    6731             LogRelMax(8, ("vmsvgaR3FifoLoop: Misaligned offCurrentCmd=%#x?\n", offCurrentCmd));
    6732             offCurrentCmd &= ~UINT32_C(3);
    6733         }
    6734 
    6735         /*
    6736          * Update the cursor position before we start on the FIFO commands.
    6737          */
    6738         /** @todo do we need to check whether the guest disabled the SVGA_FIFO_CAP_CURSOR_BYPASS_3 capability here? */
    6739         if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_CURSOR_LAST_UPDATED, offFifoMin))
    6740         {
    6741             uint32_t const uCursorUpdateCount = pFIFO[SVGA_FIFO_CURSOR_COUNT];
    6742             if (uCursorUpdateCount == pThis->svga.uLastCursorUpdateCount)
    6743             { /* halfways likely */ }
    6744             else
    6745             {
    6746                 uint32_t const uNewCount = vmsvgaR3FifoUpdateCursor(pThisCC, pSVGAState, pFIFO, offFifoMin, uCursorUpdateCount,
    6747                                                                     &xLastCursor, &yLastCursor, &fLastCursorVisible);
    6748                 ASMAtomicWriteU32(&pThis->svga.uLastCursorUpdateCount, uNewCount);
    6749             }
    6750         }
    6751 
    6752         /*
    6753          * Mark the FIFO as busy.
    6754          */
    6755         ASMAtomicWriteU32(&pThis->svga.fBusy, VMSVGA_BUSY_F_FIFO);  // Clears VMSVGA_BUSY_F_EMT_FORCE!
    6756         if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_BUSY, offFifoMin))
    6757             ASMAtomicWriteU32(&pFIFO[SVGA_FIFO_BUSY], true);
    6758 
    6759         /*
    6760          * Process all submitted command buffers.
    6761          */
    6762         vmsvgaR3CmdBufProcessBuffers(pDevIns, pThis, pThisCC, pThread);
    6763 
    6764         /*
    6765          * Execute all queued FIFO commands.
    6766          * Quit if pending external command or changes in the thread state.
    6767          */
    6768         bool fDone = false;
    6769         while (   !(fDone = (pFIFO[SVGA_FIFO_NEXT_CMD] == offCurrentCmd))
    6770                && pThread->enmState == PDMTHREADSTATE_RUNNING)
    6771         {
    6772             uint32_t cbPayload = 0;
    6773             uint32_t u32IrqStatus = 0;
    6774 
    6775             Assert(offCurrentCmd < offFifoMax && offCurrentCmd >= offFifoMin);
    6776 
    6777             /* First check any pending actions. */
    6778             vmsvgaR3FifoPendingActions(pDevIns, pThis, pThisCC);
    6779 
    6780             /* Check for pending external commands (reset). */
    6781             if (pThis->svga.u8FIFOExtCommand != VMSVGA_FIFO_EXTCMD_NONE)
    6782                 break;
    6783 
    6784             /*
    6785              * Process the command.
    6786              */
    6787             /* 'enmCmdId' is actually a SVGAFifoCmdId. It is treated as uint32_t in order to avoid a compiler
    6788              * warning. Because we implement some obsolete and deprecated commands, which are not included in
    6789              * the SVGAFifoCmdId enum in the VMSVGA headers anymore.
    6790              */
    6791             uint32_t const enmCmdId = pFIFO[offCurrentCmd / sizeof(uint32_t)];
    6792             RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
    6793             LogFlow(("vmsvgaR3FifoLoop: FIFO command (iCmd=0x%x) %s %d\n",
    6794                      offCurrentCmd / sizeof(uint32_t), vmsvgaR3FifoCmdToString(enmCmdId), enmCmdId));
    6795             switch (enmCmdId)
    6796             {
    6797             case SVGA_CMD_INVALID_CMD:
    6798                 /* Nothing to do. */
    6799                 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdInvalidCmd);
    6800                 break;
    6801 
    6802             case SVGA_CMD_FENCE:
    6803             {
    6804                 SVGAFifoCmdFence *pCmdFence;
    6805                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmdFence, SVGAFifoCmdFence, sizeof(*pCmdFence));
    6806                 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdFence);
    6807                 if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_FENCE, offFifoMin))
    6808                 {
    6809                     Log(("vmsvgaR3FifoLoop: SVGA_CMD_FENCE %#x\n", pCmdFence->fence));
    6810                     pFIFO[SVGA_FIFO_FENCE] = pCmdFence->fence;
    6811 
    6812                     if (pThis->svga.u32IrqMask & SVGA_IRQFLAG_ANY_FENCE)
    6813                     {
    6814                         Log(("vmsvgaR3FifoLoop: any fence irq\n"));
    6815                         u32IrqStatus |= SVGA_IRQFLAG_ANY_FENCE;
    6816                     }
    6817                     else
    6818                     if (    VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_FENCE_GOAL, offFifoMin)
    6819                         &&  (pThis->svga.u32IrqMask & SVGA_IRQFLAG_FENCE_GOAL)
    6820                         &&  pFIFO[SVGA_FIFO_FENCE_GOAL] == pCmdFence->fence)
    6821                     {
    6822                         Log(("vmsvgaR3FifoLoop: fence goal reached irq (fence=%#x)\n", pCmdFence->fence));
    6823                         u32IrqStatus |= SVGA_IRQFLAG_FENCE_GOAL;
    6824                     }
    6825                 }
    6826                 else
    6827                     Log(("SVGA_CMD_FENCE is bogus when offFifoMin is %#x!\n", offFifoMin));
    6828                 break;
    6829             }
    6830 
    6831             case SVGA_CMD_UPDATE:
    6832             {
    6833                 SVGAFifoCmdUpdate *pCmd;
    6834                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdUpdate, sizeof(*pCmd));
    6835                 vmsvgaR3CmdUpdate(pThis, pThisCC, pCmd);
    6836                 break;
    6837             }
    6838 
    6839             case SVGA_CMD_UPDATE_VERBOSE:
    6840             {
    6841                 SVGAFifoCmdUpdateVerbose *pCmd;
    6842                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdUpdateVerbose, sizeof(*pCmd));
    6843                 vmsvgaR3CmdUpdateVerbose(pThis, pThisCC, pCmd);
    6844                 break;
    6845             }
    6846 
    6847             case SVGA_CMD_DEFINE_CURSOR:
    6848             {
    6849                 /* Followed by bitmap data. */
    6850                 SVGAFifoCmdDefineCursor *pCmd;
    6851                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineCursor, sizeof(*pCmd));
    6852 
    6853                 /* Figure out the size of the bitmap data. */
    6854                 ASSERT_GUEST_BREAK(pCmd->height < 2048 && pCmd->width < 2048);
    6855                 ASSERT_GUEST_BREAK(pCmd->andMaskDepth <= 32);
    6856                 ASSERT_GUEST_BREAK(pCmd->xorMaskDepth <= 32);
    6857                 RT_UNTRUSTED_VALIDATED_FENCE();
    6858 
    6859                 uint32_t const cbAndLine = RT_ALIGN_32(pCmd->width * (pCmd->andMaskDepth + (pCmd->andMaskDepth == 15)), 32) / 8;
    6860                 uint32_t const cbAndMask = cbAndLine * pCmd->height;
    6861                 uint32_t const cbXorLine = RT_ALIGN_32(pCmd->width * (pCmd->xorMaskDepth + (pCmd->xorMaskDepth == 15)), 32) / 8;
    6862                 uint32_t const cbXorMask = cbXorLine * pCmd->height;
    6863 
    6864                 uint32_t const cbCmd = sizeof(SVGAFifoCmdDefineCursor) + cbAndMask + cbXorMask;
    6865                 VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineCursor, cbCmd);
    6866                 vmsvgaR3CmdDefineCursor(pThis, pThisCC, pCmd);
    6867                 break;
    6868             }
    6869 
    6870             case SVGA_CMD_DEFINE_ALPHA_CURSOR:
    6871             {
    6872                 /* Followed by bitmap data. */
    6873                 SVGAFifoCmdDefineAlphaCursor *pCmd;
    6874                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineAlphaCursor, sizeof(*pCmd));
    6875 
    6876                 /* Figure out the size of the bitmap data. */
    6877                 ASSERT_GUEST_BREAK(pCmd->height < 2048 && pCmd->width < 2048);
    6878 
    6879                 uint32_t const cbCmd = sizeof(SVGAFifoCmdDefineAlphaCursor) + pCmd->width * pCmd->height * sizeof(uint32_t) /* 32-bit BRGA format */;
    6880                 VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineAlphaCursor, cbCmd);
    6881                 vmsvgaR3CmdDefineAlphaCursor(pThis, pThisCC, pCmd);
    6882                 break;
    6883             }
    6884 
    6885             case SVGA_CMD_MOVE_CURSOR:
    6886             {
    6887                 /* Deprecated; there should be no driver which *requires* this command. However, if
    6888                  * we do ecncounter this command, it might be useful to not get the FIFO completely out of
    6889                  * alignment.
    6890                  * May be issued by guest if SVGA_CAP_CURSOR_BYPASS is missing.
    6891                  */
    6892                 SVGAFifoCmdMoveCursor *pCmd;
    6893                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdMoveCursor, sizeof(*pCmd));
    6894                 vmsvgaR3CmdMoveCursor(pThis, pThisCC, pCmd);
    6895                 break;
    6896             }
    6897 
    6898             case SVGA_CMD_DISPLAY_CURSOR:
    6899             {
    6900                 /* Deprecated; there should be no driver which *requires* this command. However, if
    6901                  * we do ecncounter this command, it might be useful to not get the FIFO completely out of
    6902                  * alignment.
    6903                  * May be issued by guest if SVGA_CAP_CURSOR_BYPASS is missing.
    6904                  */
    6905                 SVGAFifoCmdDisplayCursor *pCmd;
    6906                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDisplayCursor, sizeof(*pCmd));
    6907                 vmsvgaR3CmdDisplayCursor(pThis, pThisCC, pCmd);
    6908                 break;
    6909             }
    6910 
    6911             case SVGA_CMD_RECT_FILL:
    6912             {
    6913                 SVGAFifoCmdRectFill *pCmd;
    6914                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdRectFill, sizeof(*pCmd));
    6915                 vmsvgaR3CmdRectFill(pThis, pThisCC, pCmd);
    6916                 break;
    6917             }
    6918 
    6919             case SVGA_CMD_RECT_COPY:
    6920             {
    6921                 SVGAFifoCmdRectCopy *pCmd;
    6922                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdRectCopy, sizeof(*pCmd));
    6923                 vmsvgaR3CmdRectCopy(pThis, pThisCC, pCmd);
    6924                 break;
    6925             }
    6926 
    6927             case SVGA_CMD_RECT_ROP_COPY:
    6928             {
    6929                 SVGAFifoCmdRectRopCopy *pCmd;
    6930                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdRectRopCopy, sizeof(*pCmd));
    6931                 vmsvgaR3CmdRectRopCopy(pThis, pThisCC, pCmd);
    6932                 break;
    6933             }
    6934 
    6935             case SVGA_CMD_ESCAPE:
    6936             {
    6937                 /* Followed by 'size' bytes of data. */
    6938                 SVGAFifoCmdEscape *pCmd;
    6939                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdEscape, sizeof(*pCmd));
    6940 
    6941                 ASSERT_GUEST_BREAK(pCmd->size < pThis->svga.cbFIFO - sizeof(SVGAFifoCmdEscape));
    6942                 RT_UNTRUSTED_VALIDATED_FENCE();
    6943 
    6944                 uint32_t const cbCmd = sizeof(SVGAFifoCmdEscape) + pCmd->size;
    6945                 VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdEscape, cbCmd);
    6946                 vmsvgaR3CmdEscape(pThis, pThisCC, pCmd);
    6947                 break;
    6948             }
    6949 # ifdef VBOX_WITH_VMSVGA3D
    6950             case SVGA_CMD_DEFINE_GMR2:
    6951             {
    6952                 SVGAFifoCmdDefineGMR2 *pCmd;
    6953                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineGMR2, sizeof(*pCmd));
    6954                 vmsvgaR3CmdDefineGMR2(pThis, pThisCC, pCmd);
    6955                 break;
    6956             }
    6957 
    6958             case SVGA_CMD_REMAP_GMR2:
    6959             {
    6960                 /* Followed by page descriptors or guest ptr. */
    6961                 SVGAFifoCmdRemapGMR2 *pCmd;
    6962                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdRemapGMR2, sizeof(*pCmd));
    6963 
    6964                 /* Calculate the size of what comes after next and fetch it. */
    6965                 uint32_t cbCmd = sizeof(SVGAFifoCmdRemapGMR2);
    6966                 if (pCmd->flags & SVGA_REMAP_GMR2_VIA_GMR)
    6967                     cbCmd += sizeof(SVGAGuestPtr);
    6968                 else
    6969                 {
    6970                     uint32_t const cbPageDesc = (pCmd->flags & SVGA_REMAP_GMR2_PPN64) ? sizeof(uint64_t) : sizeof(uint32_t);
    6971                     if (pCmd->flags & SVGA_REMAP_GMR2_SINGLE_PPN)
    6972                     {
    6973                         cbCmd         += cbPageDesc;
    6974                         pCmd->numPages = 1;
    6975                     }
    6976                     else
    6977                     {
    6978                         ASSERT_GUEST_BREAK(pCmd->numPages <= pThis->svga.cbFIFO / cbPageDesc);
    6979                         cbCmd += cbPageDesc * pCmd->numPages;
    6980                     }
    6981                 }
    6982                 VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdRemapGMR2, cbCmd);
    6983                 vmsvgaR3CmdRemapGMR2(pThis, pThisCC, pCmd);
    6984 #  ifdef DEBUG_GMR_ACCESS
    6985                 VMR3ReqCallWaitU(PDMDevHlpGetUVM(pDevIns), VMCPUID_ANY, (PFNRT)vmsvgaR3RegisterGmr, 2, pDevIns, pCmd->gmrId);
    6986 #  endif
    6987                 break;
    6988             }
    6989 # endif // VBOX_WITH_VMSVGA3D
    6990             case SVGA_CMD_DEFINE_SCREEN:
    6991             {
    6992                 /* The size of this command is specified by the guest and depends on capabilities. */
    6993                 Assert(pFIFO[SVGA_FIFO_CAPABILITIES] & SVGA_FIFO_CAP_SCREEN_OBJECT_2);
    6994 
    6995                 SVGAFifoCmdDefineScreen *pCmd;
    6996                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineScreen, sizeof(pCmd->screen.structSize));
    6997                 AssertBreak(pCmd->screen.structSize < pThis->svga.cbFIFO);
    6998                 RT_UNTRUSTED_VALIDATED_FENCE();
    6999 
    7000                 RT_BZERO(&pCmd->screen.id, sizeof(*pCmd) - RT_OFFSETOF(SVGAFifoCmdDefineScreen, screen.id));
    7001                 VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineScreen, RT_MAX(sizeof(pCmd->screen.structSize), pCmd->screen.structSize));
    7002                 vmsvgaR3CmdDefineScreen(pThis, pThisCC, pCmd);
    7003                 break;
    7004             }
    7005 
    7006             case SVGA_CMD_DESTROY_SCREEN:
    7007             {
    7008                 SVGAFifoCmdDestroyScreen *pCmd;
    7009                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDestroyScreen, sizeof(*pCmd));
    7010                 vmsvgaR3CmdDestroyScreen(pThis, pThisCC, pCmd);
    7011                 break;
    7012             }
    7013 
    7014             case SVGA_CMD_DEFINE_GMRFB:
    7015             {
    7016                 SVGAFifoCmdDefineGMRFB *pCmd;
    7017                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineGMRFB, sizeof(*pCmd));
    7018                 vmsvgaR3CmdDefineGMRFB(pThis, pThisCC, pCmd);
    7019                 break;
    7020             }
    7021 
    7022             case SVGA_CMD_BLIT_GMRFB_TO_SCREEN:
    7023             {
    7024                 SVGAFifoCmdBlitGMRFBToScreen *pCmd;
    7025                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdBlitGMRFBToScreen, sizeof(*pCmd));
    7026                 vmsvgaR3CmdBlitGMRFBToScreen(pThis, pThisCC, pCmd);
    7027                 break;
    7028             }
    7029 
    7030             case SVGA_CMD_BLIT_SCREEN_TO_GMRFB:
    7031             {
    7032                 SVGAFifoCmdBlitScreenToGMRFB *pCmd;
    7033                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdBlitScreenToGMRFB, sizeof(*pCmd));
    7034                 vmsvgaR3CmdBlitScreenToGMRFB(pThis, pThisCC, pCmd);
    7035                 break;
    7036             }
    7037 
    7038             case SVGA_CMD_ANNOTATION_FILL:
    7039             {
    7040                 SVGAFifoCmdAnnotationFill *pCmd;
    7041                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdAnnotationFill, sizeof(*pCmd));
    7042                 vmsvgaR3CmdAnnotationFill(pThis, pThisCC, pCmd);
    7043                 break;
    7044             }
    7045 
    7046             case SVGA_CMD_ANNOTATION_COPY:
    7047             {
    7048                 SVGAFifoCmdAnnotationCopy *pCmd;
    7049                 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdAnnotationCopy, sizeof(*pCmd));
    7050                 vmsvgaR3CmdAnnotationCopy(pThis, pThisCC, pCmd);
    7051                 break;
    7052             }
    7053 
    7054             default:
    7055 # ifdef VBOX_WITH_VMSVGA3D
    7056                 if (    (int)enmCmdId >= SVGA_3D_CMD_BASE
    7057                     &&  (int)enmCmdId <  SVGA_3D_CMD_MAX)
    7058                 {
    7059                     RT_UNTRUSTED_VALIDATED_FENCE();
    7060 
    7061                     /* All 3d commands start with a common header, which defines the identifier and the size
    7062                      * of the command. The identifier has been already read from FIFO. Fetch the size.
    7063                      */
    7064                     uint32_t *pcbCmd;
    7065                     VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pcbCmd, uint32_t, sizeof(*pcbCmd));
    7066                     uint32_t const cbCmd = *pcbCmd;
    7067                     AssertBreak(cbCmd < pThis->svga.cbFIFO);
    7068                     uint32_t *pu32Cmd;
    7069                     VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pu32Cmd, uint32_t, sizeof(*pcbCmd) + cbCmd);
    7070                     pu32Cmd++; /* Skip the command size. */
    7071 
    7072                     if (RT_LIKELY(pThis->svga.f3DEnabled))
    7073                     { /* likely */ }
    7074                     else
    7075                     {
    7076                         LogRelMax(8, ("VMSVGA: 3D disabled, command %d skipped\n", enmCmdId));
    7077                         break;
    7078                     }
    7079 
    7080                     vmsvgaR3Process3dCmd(pThis, pThisCC, (SVGAFifo3dCmdId)enmCmdId, cbCmd, pu32Cmd);
    7081                 }
    7082                 else
    7083 # endif // VBOX_WITH_VMSVGA3D
    7084                 {
    7085                     STAM_REL_COUNTER_INC(&pSVGAState->StatFifoUnkCmds);
    7086                     AssertMsgFailed(("enmCmdId=%d\n", enmCmdId));
    7087                 }
    7088             }
    7089 
    7090             /* Go to the next slot */
    7091             Assert(cbPayload + sizeof(uint32_t) <= offFifoMax - offFifoMin);
    7092             offCurrentCmd += RT_ALIGN_32(cbPayload + sizeof(uint32_t), sizeof(uint32_t));
    7093             if (offCurrentCmd >= offFifoMax)
    7094             {
    7095                 offCurrentCmd -= offFifoMax - offFifoMin;
    7096                 Assert(offCurrentCmd >= offFifoMin);
    7097                 Assert(offCurrentCmd <  offFifoMax);
    7098             }
    7099             ASMAtomicWriteU32(&pFIFO[SVGA_FIFO_STOP], offCurrentCmd);
    7100             STAM_REL_COUNTER_INC(&pSVGAState->StatFifoCommands);
    7101 
    7102             /*
    7103              * Raise IRQ if required.  Must enter the critical section here
    7104              * before making final decisions here, otherwise cubebench and
    7105              * others may end up waiting forever.
    7106              */
    7107             if (   u32IrqStatus
    7108                 || (pThis->svga.u32IrqMask & SVGA_IRQFLAG_FIFO_PROGRESS))
    7109             {
    7110                 int rc2 = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VERR_IGNORED);
    7111                 AssertRC(rc2);
    7112 
    7113                 /* FIFO progress might trigger an interrupt. */
    7114                 if (pThis->svga.u32IrqMask & SVGA_IRQFLAG_FIFO_PROGRESS)
    7115                 {
    7116                     Log(("vmsvgaR3FifoLoop: fifo progress irq\n"));
    7117                     u32IrqStatus |= SVGA_IRQFLAG_FIFO_PROGRESS;
    7118                 }
    7119 
    7120                 /* Unmasked IRQ pending? */
    7121                 if (pThis->svga.u32IrqMask & u32IrqStatus)
    7122                 {
    7123                     Log(("vmsvgaR3FifoLoop: Trigger interrupt with status %x\n", u32IrqStatus));
    7124                     ASMAtomicOrU32(&pThis->svga.u32IrqStatus, u32IrqStatus);
    7125                     PDMDevHlpPCISetIrq(pDevIns, 0, 1);
    7126                 }
    7127 
    7128                 PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect);
    7129             }
    7130         }
    7131 
    7132         /* If really done, clear the busy flag. */
    7133         if (fDone)
    7134         {
    7135             Log(("vmsvgaR3FifoLoop: emptied the FIFO next=%x stop=%x\n", pFIFO[SVGA_FIFO_NEXT_CMD], offCurrentCmd));
    7136             vmsvgaR3FifoSetNotBusy(pDevIns, pThis, pThisCC, pSVGAState, offFifoMin);
    7137         }
    7138     }
    7139 
    7140     /*
    7141      * Free the bounce buffer. (There are no returns above!)
    7142      */
    7143     RTMemFree(pbBounceBuf);
    7144 
    7145     return VINF_SUCCESS;
    7146 }
    7147 
    7148 #undef VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK
    7149 #undef VMSVGAFIFO_GET_CMD_BUFFER_BREAK
    7150 
    7151 #ifdef VBOX_WITH_VMSVGA3D
    7152 /**
    7153  * Free the specified GMR
    7154  *
    7155  * @param   pThisCC         The VGA/VMSVGA state for ring-3.
    7156  * @param   idGMR           GMR id
    7157  */
    7158 static void vmsvgaR3GmrFree(PVGASTATECC pThisCC, uint32_t idGMR)
    7159 {
    7160     PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
    7161 
    7162     /* Free the old descriptor if present. */
    7163     PGMR pGMR = &pSVGAState->paGMR[idGMR];
    7164     if (   pGMR->numDescriptors
    7165         || pGMR->paDesc /* needed till we implement SVGA_REMAP_GMR2_VIA_GMR */)
    7166     {
    7167 # ifdef DEBUG_GMR_ACCESS
    7168         VMR3ReqCallWaitU(PDMDevHlpGetUVM(pThisCC->pDevIns), VMCPUID_ANY, (PFNRT)vmsvgaR3DeregisterGmr, 2, pDevIns, idGMR);
    7169 # endif
    7170 
    7171         Assert(pGMR->paDesc);
    7172         RTMemFree(pGMR->paDesc);
    7173         pGMR->paDesc         = NULL;
    7174         pGMR->numDescriptors = 0;
    7175         pGMR->cbTotal        = 0;
    7176         pGMR->cMaxPages      = 0;
    7177     }
    7178     Assert(!pGMR->cMaxPages);
    7179     Assert(!pGMR->cbTotal);
    7180 }
    7181 #endif /* VBOX_WITH_VMSVGA3D */
    7182 
    7183 /**
    7184  * Copy between a GMR and a host memory buffer.
    7185  *
    7186  * @returns VBox status code.
    7187  * @param   pThis           The shared VGA/VMSVGA instance data.
    7188  * @param   pThisCC         The VGA/VMSVGA state for ring-3.
    7189  * @param   enmTransferType Transfer type (read/write)
    7190  * @param   pbHstBuf        Host buffer pointer (valid)
    7191  * @param   cbHstBuf        Size of host buffer (valid)
    7192  * @param   offHst          Host buffer offset of the first scanline
    7193  * @param   cbHstPitch      Destination buffer pitch
    7194  * @param   gstPtr          GMR description
    7195  * @param   offGst          Guest buffer offset of the first scanline
    7196  * @param   cbGstPitch      Guest buffer pitch
    7197  * @param   cbWidth         Width in bytes to copy
    7198  * @param   cHeight         Number of scanllines to copy
    7199  */
     223DECLCALLBACK(int) vmsvgaR3ResetGmrHandlers(PVGASTATE pThis);
     224DECLCALLBACK(int) vmsvgaR3DeregisterGmr(PPDMDEVINS pDevIns, uint32_t gmrId);
     225#endif
     226
     227void vmsvgaR3ResetScreens(PVGASTATE pThis, PVGASTATECC pThisCC);
     228
     229int vmsvgaR3ChangeMode(PVGASTATE pThis, PVGASTATECC pThisCC);
     230int vmsvgaR3UpdateScreen(PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen, int x, int y, int w, int h);
     231
    7200232int vmsvgaR3GmrTransfer(PVGASTATE pThis, PVGASTATECC pThisCC, const SVGA3dTransferType enmTransferType,
    7201233                        uint8_t *pbHstBuf, uint32_t cbHstBuf, uint32_t offHst, int32_t cbHstPitch,
    7202234                        SVGAGuestPtr gstPtr, uint32_t offGst, int32_t cbGstPitch,
    7203                         uint32_t cbWidth, uint32_t cHeight)
    7204 {
    7205     PVMSVGAR3STATE  pSVGAState = pThisCC->svga.pSvgaR3State;
    7206     PPDMDEVINS      pDevIns = pThisCC->pDevIns; /* simpler */
    7207     int             rc;
    7208 
    7209     LogFunc(("%s host %p size=%d offset %d pitch=%d; guest gmr=%#x:%#x offset=%d pitch=%d cbWidth=%d cHeight=%d\n",
    7210              enmTransferType == SVGA3D_READ_HOST_VRAM ? "WRITE" : "READ", /* GMR op: READ host VRAM means WRITE GMR */
    7211              pbHstBuf, cbHstBuf, offHst, cbHstPitch,
    7212              gstPtr.gmrId, gstPtr.offset, offGst, cbGstPitch, cbWidth, cHeight));
    7213     AssertReturn(cbWidth && cHeight, VERR_INVALID_PARAMETER);
    7214 
    7215     PGMR pGMR;
    7216     uint32_t cbGmr; /* The GMR size in bytes. */
    7217     if (gstPtr.gmrId == SVGA_GMR_FRAMEBUFFER)
    7218     {
    7219         pGMR = NULL;
    7220         cbGmr = pThis->vram_size;
    7221     }
    7222     else
    7223     {
    7224         AssertReturn(gstPtr.gmrId < pThis->svga.cGMR, VERR_INVALID_PARAMETER);
    7225         RT_UNTRUSTED_VALIDATED_FENCE();
    7226         pGMR = &pSVGAState->paGMR[gstPtr.gmrId];
    7227         cbGmr = pGMR->cbTotal;
    7228     }
    7229 
    7230     /*
    7231      * GMR
    7232      */
    7233     /* Calculate GMR offset of the data to be copied. */
    7234     AssertMsgReturn(gstPtr.offset < cbGmr,
    7235                     ("gmr=%#x:%#x offGst=%#x cbGstPitch=%#x cHeight=%#x cbWidth=%#x cbGmr=%#x\n",
    7236                      gstPtr.gmrId, gstPtr.offset, offGst, cbGstPitch, cHeight, cbWidth, cbGmr),
    7237                     VERR_INVALID_PARAMETER);
    7238     RT_UNTRUSTED_VALIDATED_FENCE();
    7239     AssertMsgReturn(offGst < cbGmr - gstPtr.offset,
    7240                     ("gmr=%#x:%#x offGst=%#x cbGstPitch=%#x cHeight=%#x cbWidth=%#x cbGmr=%#x\n",
    7241                      gstPtr.gmrId, gstPtr.offset, offGst, cbGstPitch, cHeight, cbWidth, cbGmr),
    7242                     VERR_INVALID_PARAMETER);
    7243     RT_UNTRUSTED_VALIDATED_FENCE();
    7244     uint32_t const offGmr = offGst + gstPtr.offset; /* Offset in the GMR, where the first scanline is located. */
    7245 
    7246     /* Verify that cbWidth is less than scanline and fits into the GMR. */
    7247     uint32_t const cbGmrScanline = cbGstPitch > 0 ? cbGstPitch : -cbGstPitch;
    7248     AssertMsgReturn(cbGmrScanline != 0,
    7249                     ("gmr=%#x:%#x offGst=%#x cbGstPitch=%#x cHeight=%#x cbWidth=%#x cbGmr=%#x\n",
    7250                      gstPtr.gmrId, gstPtr.offset, offGst, cbGstPitch, cHeight, cbWidth, cbGmr),
    7251                     VERR_INVALID_PARAMETER);
    7252     RT_UNTRUSTED_VALIDATED_FENCE();
    7253     AssertMsgReturn(cbWidth <= cbGmrScanline,
    7254                     ("gmr=%#x:%#x offGst=%#x cbGstPitch=%#x cHeight=%#x cbWidth=%#x cbGmr=%#x\n",
    7255                      gstPtr.gmrId, gstPtr.offset, offGst, cbGstPitch, cHeight, cbWidth, cbGmr),
    7256                     VERR_INVALID_PARAMETER);
    7257     AssertMsgReturn(cbWidth <= cbGmr - offGmr,
    7258                     ("gmr=%#x:%#x offGst=%#x cbGstPitch=%#x cHeight=%#x cbWidth=%#x cbGmr=%#x\n",
    7259                      gstPtr.gmrId, gstPtr.offset, offGst, cbGstPitch, cHeight, cbWidth, cbGmr),
    7260                     VERR_INVALID_PARAMETER);
    7261     RT_UNTRUSTED_VALIDATED_FENCE();
    7262 
    7263     /* How many bytes are available for the data in the GMR. */
    7264     uint32_t const cbGmrLeft = cbGstPitch > 0 ? cbGmr - offGmr : offGmr + cbWidth;
    7265 
    7266     /* How many scanlines would fit into the available data. */
    7267     uint32_t cGmrScanlines = cbGmrLeft / cbGmrScanline;
    7268     uint32_t const cbGmrLastScanline = cbGmrLeft - cGmrScanlines * cbGmrScanline; /* Slack space. */
    7269     if (cbWidth <= cbGmrLastScanline)
    7270         ++cGmrScanlines;
    7271 
    7272     if (cHeight > cGmrScanlines)
    7273         cHeight = cGmrScanlines;
    7274 
    7275     AssertMsgReturn(cHeight > 0,
    7276                     ("gmr=%#x:%#x offGst=%#x cbGstPitch=%#x cHeight=%#x cbWidth=%#x cbGmr=%#x\n",
    7277                      gstPtr.gmrId, gstPtr.offset, offGst, cbGstPitch, cHeight, cbWidth, cbGmr),
    7278                     VERR_INVALID_PARAMETER);
    7279     RT_UNTRUSTED_VALIDATED_FENCE();
    7280 
    7281     /*
    7282      * Host buffer.
    7283      */
    7284     AssertMsgReturn(offHst < cbHstBuf,
    7285                     ("buffer=%p size %d offHst=%d cbHstPitch=%d cHeight=%d cbWidth=%d\n",
    7286                      pbHstBuf, cbHstBuf, offHst, cbHstPitch, cHeight, cbWidth),
    7287                     VERR_INVALID_PARAMETER);
    7288 
    7289     /* Verify that cbWidth is less than scanline and fits into the buffer. */
    7290     uint32_t const cbHstScanline = cbHstPitch > 0 ? cbHstPitch : -cbHstPitch;
    7291     AssertMsgReturn(cbHstScanline != 0,
    7292                     ("buffer=%p size %d offHst=%d cbHstPitch=%d cHeight=%d cbWidth=%d\n",
    7293                      pbHstBuf, cbHstBuf, offHst, cbHstPitch, cHeight, cbWidth),
    7294                     VERR_INVALID_PARAMETER);
    7295     AssertMsgReturn(cbWidth <= cbHstScanline,
    7296                     ("buffer=%p size %d offHst=%d cbHstPitch=%d cHeight=%d cbWidth=%d\n",
    7297                      pbHstBuf, cbHstBuf, offHst, cbHstPitch, cHeight, cbWidth),
    7298                     VERR_INVALID_PARAMETER);
    7299     AssertMsgReturn(cbWidth <= cbHstBuf - offHst,
    7300                     ("buffer=%p size %d offHst=%d cbHstPitch=%d cHeight=%d cbWidth=%d\n",
    7301                      pbHstBuf, cbHstBuf, offHst, cbHstPitch, cHeight, cbWidth),
    7302                     VERR_INVALID_PARAMETER);
    7303 
    7304     /* How many bytes are available for the data in the buffer. */
    7305     uint32_t const cbHstLeft = cbHstPitch > 0 ? cbHstBuf - offHst : offHst + cbWidth;
    7306 
    7307     /* How many scanlines would fit into the available data. */
    7308     uint32_t cHstScanlines = cbHstLeft / cbHstScanline;
    7309     uint32_t const cbHstLastScanline = cbHstLeft - cHstScanlines * cbHstScanline; /* Slack space. */
    7310     if (cbWidth <= cbHstLastScanline)
    7311         ++cHstScanlines;
    7312 
    7313     if (cHeight > cHstScanlines)
    7314         cHeight = cHstScanlines;
    7315 
    7316     AssertMsgReturn(cHeight > 0,
    7317                     ("buffer=%p size %d offHst=%d cbHstPitch=%d cHeight=%d cbWidth=%d\n",
    7318                      pbHstBuf, cbHstBuf, offHst, cbHstPitch, cHeight, cbWidth),
    7319                     VERR_INVALID_PARAMETER);
    7320 
    7321     uint8_t *pbHst = pbHstBuf + offHst;
    7322 
    7323     /* Shortcut for the framebuffer. */
    7324     if (gstPtr.gmrId == SVGA_GMR_FRAMEBUFFER)
    7325     {
    7326         uint8_t *pbGst = pThisCC->pbVRam + offGmr;
    7327 
    7328         uint8_t const *pbSrc;
    7329         int32_t cbSrcPitch;
    7330         uint8_t *pbDst;
    7331         int32_t cbDstPitch;
    7332 
    7333         if (enmTransferType == SVGA3D_READ_HOST_VRAM)
    7334         {
    7335             pbSrc      = pbHst;
    7336             cbSrcPitch = cbHstPitch;
    7337             pbDst      = pbGst;
    7338             cbDstPitch = cbGstPitch;
    7339         }
    7340         else
    7341         {
    7342             pbSrc      = pbGst;
    7343             cbSrcPitch = cbGstPitch;
    7344             pbDst      = pbHst;
    7345             cbDstPitch = cbHstPitch;
    7346         }
    7347 
    7348         if (   cbWidth == (uint32_t)cbGstPitch
    7349             && cbGstPitch == cbHstPitch)
    7350         {
    7351             /* Entire scanlines, positive pitch. */
    7352             memcpy(pbDst, pbSrc, cbWidth * cHeight);
    7353         }
    7354         else
    7355         {
    7356             for (uint32_t i = 0; i < cHeight; ++i)
    7357             {
    7358                 memcpy(pbDst, pbSrc, cbWidth);
    7359 
    7360                 pbDst += cbDstPitch;
    7361                 pbSrc += cbSrcPitch;
    7362             }
    7363         }
    7364         return VINF_SUCCESS;
    7365     }
    7366 
    7367     AssertPtrReturn(pGMR, VERR_INVALID_PARAMETER);
    7368     AssertReturn(pGMR->numDescriptors > 0, VERR_INVALID_PARAMETER);
    7369 
    7370     PVMSVGAGMRDESCRIPTOR const paDesc = pGMR->paDesc; /* Local copy of the pointer. */
    7371     uint32_t iDesc = 0;                               /* Index in the descriptor array. */
    7372     uint32_t offDesc = 0;                             /* GMR offset of the current descriptor. */
    7373     uint32_t offGmrScanline = offGmr;                 /* GMR offset of the scanline which is being copied. */
    7374     uint8_t *pbHstScanline = pbHst;                   /* Host address of the scanline which is being copied. */
    7375     for (uint32_t i = 0; i < cHeight; ++i)
    7376     {
    7377         uint32_t cbCurrentWidth = cbWidth;
    7378         uint32_t offGmrCurrent  = offGmrScanline;
    7379         uint8_t *pbCurrentHost  = pbHstScanline;
    7380 
    7381         /* Find the right descriptor */
    7382         while (offDesc + paDesc[iDesc].numPages * PAGE_SIZE <= offGmrCurrent)
    7383         {
    7384             offDesc += paDesc[iDesc].numPages * PAGE_SIZE;
    7385             AssertReturn(offDesc < pGMR->cbTotal, VERR_INTERNAL_ERROR); /* overflow protection */
    7386             ++iDesc;
    7387             AssertReturn(iDesc < pGMR->numDescriptors, VERR_INTERNAL_ERROR);
    7388         }
    7389 
    7390         while (cbCurrentWidth)
    7391         {
    7392             uint32_t cbToCopy;
    7393 
    7394             if (offGmrCurrent + cbCurrentWidth <= offDesc + paDesc[iDesc].numPages * PAGE_SIZE)
    7395             {
    7396                 cbToCopy = cbCurrentWidth;
    7397             }
    7398             else
    7399             {
    7400                 cbToCopy = (offDesc + paDesc[iDesc].numPages * PAGE_SIZE - offGmrCurrent);
    7401                 AssertReturn(cbToCopy <= cbCurrentWidth, VERR_INVALID_PARAMETER);
    7402             }
    7403 
    7404             RTGCPHYS const GCPhys = paDesc[iDesc].GCPhys + offGmrCurrent - offDesc;
    7405 
    7406             Log5Func(("%s phys=%RGp\n", (enmTransferType == SVGA3D_WRITE_HOST_VRAM) ? "READ" : "WRITE", GCPhys));
    7407 
    7408             if (enmTransferType == SVGA3D_WRITE_HOST_VRAM)
    7409                 rc = PDMDevHlpPhysRead(pDevIns, GCPhys, pbCurrentHost, cbToCopy);
    7410             else
    7411                 rc = PDMDevHlpPhysWrite(pDevIns, GCPhys, pbCurrentHost, cbToCopy);
    7412             AssertRCBreak(rc);
    7413 
    7414             cbCurrentWidth -= cbToCopy;
    7415             offGmrCurrent  += cbToCopy;
    7416             pbCurrentHost  += cbToCopy;
    7417 
    7418             /* Go to the next descriptor if there's anything left. */
    7419             if (cbCurrentWidth)
    7420             {
    7421                 offDesc += paDesc[iDesc].numPages * PAGE_SIZE;
    7422                 AssertReturn(offDesc < pGMR->cbTotal, VERR_INTERNAL_ERROR);
    7423                 ++iDesc;
    7424                 AssertReturn(iDesc < pGMR->numDescriptors, VERR_INTERNAL_ERROR);
    7425             }
    7426         }
    7427 
    7428         offGmrScanline += cbGstPitch;
    7429         pbHstScanline  += cbHstPitch;
    7430     }
    7431 
    7432     return VINF_SUCCESS;
    7433 }
    7434 
    7435 
    7436 /**
    7437  * Unsigned coordinates in pBox. Clip to [0; pSizeSrc), [0; pSizeDest).
    7438  *
    7439  * @param   pSizeSrc    Source surface dimensions.
    7440  * @param   pSizeDest   Destination surface dimensions.
    7441  * @param   pBox        Coordinates to be clipped.
    7442  */
    7443 void vmsvgaR3ClipCopyBox(const SVGA3dSize *pSizeSrc, const SVGA3dSize *pSizeDest, SVGA3dCopyBox *pBox)
    7444 {
    7445     /* Src x, w */
    7446     if (pBox->srcx > pSizeSrc->width)
    7447         pBox->srcx = pSizeSrc->width;
    7448     if (pBox->w > pSizeSrc->width - pBox->srcx)
    7449         pBox->w = pSizeSrc->width - pBox->srcx;
    7450 
    7451     /* Src y, h */
    7452     if (pBox->srcy > pSizeSrc->height)
    7453         pBox->srcy = pSizeSrc->height;
    7454     if (pBox->h > pSizeSrc->height - pBox->srcy)
    7455         pBox->h = pSizeSrc->height - pBox->srcy;
    7456 
    7457     /* Src z, d */
    7458     if (pBox->srcz > pSizeSrc->depth)
    7459         pBox->srcz = pSizeSrc->depth;
    7460     if (pBox->d > pSizeSrc->depth - pBox->srcz)
    7461         pBox->d = pSizeSrc->depth - pBox->srcz;
    7462 
    7463     /* Dest x, w */
    7464     if (pBox->x > pSizeDest->width)
    7465         pBox->x = pSizeDest->width;
    7466     if (pBox->w > pSizeDest->width - pBox->x)
    7467         pBox->w = pSizeDest->width - pBox->x;
    7468 
    7469     /* Dest y, h */
    7470     if (pBox->y > pSizeDest->height)
    7471         pBox->y = pSizeDest->height;
    7472     if (pBox->h > pSizeDest->height - pBox->y)
    7473         pBox->h = pSizeDest->height - pBox->y;
    7474 
    7475     /* Dest z, d */
    7476     if (pBox->z > pSizeDest->depth)
    7477         pBox->z = pSizeDest->depth;
    7478     if (pBox->d > pSizeDest->depth - pBox->z)
    7479         pBox->d = pSizeDest->depth - pBox->z;
    7480 }
    7481 
    7482 /**
    7483  * Unsigned coordinates in pBox. Clip to [0; pSize).
    7484  *
    7485  * @param   pSize   Source surface dimensions.
    7486  * @param   pBox    Coordinates to be clipped.
    7487  */
    7488 void vmsvgaR3ClipBox(const SVGA3dSize *pSize, SVGA3dBox *pBox)
    7489 {
    7490     /* x, w */
    7491     if (pBox->x > pSize->width)
    7492         pBox->x = pSize->width;
    7493     if (pBox->w > pSize->width - pBox->x)
    7494         pBox->w = pSize->width - pBox->x;
    7495 
    7496     /* y, h */
    7497     if (pBox->y > pSize->height)
    7498         pBox->y = pSize->height;
    7499     if (pBox->h > pSize->height - pBox->y)
    7500         pBox->h = pSize->height - pBox->y;
    7501 
    7502     /* z, d */
    7503     if (pBox->z > pSize->depth)
    7504         pBox->z = pSize->depth;
    7505     if (pBox->d > pSize->depth - pBox->z)
    7506         pBox->d = pSize->depth - pBox->z;
    7507 }
    7508 
    7509 /**
    7510  * Clip.
    7511  *
    7512  * @param   pBound  Bounding rectangle.
    7513  * @param   pRect   Rectangle to be clipped.
    7514  */
    7515 void vmsvgaR3ClipRect(SVGASignedRect const *pBound, SVGASignedRect *pRect)
    7516 {
    7517     int32_t left;
    7518     int32_t top;
    7519     int32_t right;
    7520     int32_t bottom;
    7521 
    7522     /* Right order. */
    7523     Assert(pBound->left <= pBound->right && pBound->top <= pBound->bottom);
    7524     if (pRect->left < pRect->right)
    7525     {
    7526         left = pRect->left;
    7527         right = pRect->right;
    7528     }
    7529     else
    7530     {
    7531         left = pRect->right;
    7532         right = pRect->left;
    7533     }
    7534     if (pRect->top < pRect->bottom)
    7535     {
    7536         top = pRect->top;
    7537         bottom = pRect->bottom;
    7538     }
    7539     else
    7540     {
    7541         top = pRect->bottom;
    7542         bottom = pRect->top;
    7543     }
    7544 
    7545     if (left < pBound->left)
    7546         left = pBound->left;
    7547     if (right < pBound->left)
    7548         right = pBound->left;
    7549 
    7550     if (left > pBound->right)
    7551         left = pBound->right;
    7552     if (right > pBound->right)
    7553         right = pBound->right;
    7554 
    7555     if (top < pBound->top)
    7556         top = pBound->top;
    7557     if (bottom < pBound->top)
    7558         bottom = pBound->top;
    7559 
    7560     if (top > pBound->bottom)
    7561         top = pBound->bottom;
    7562     if (bottom > pBound->bottom)
    7563         bottom = pBound->bottom;
    7564 
    7565     pRect->left = left;
    7566     pRect->right = right;
    7567     pRect->top = top;
    7568     pRect->bottom = bottom;
    7569 }
    7570 
    7571 /**
    7572  * @callback_method_impl{PFNPDMTHREADWAKEUPDEV,
    7573  * Unblock the FIFO I/O thread so it can respond to a state change.}
    7574  */
    7575 static DECLCALLBACK(int) vmsvgaR3FifoLoopWakeUp(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
    7576 {
    7577     RT_NOREF(pDevIns);
    7578     PVGASTATE pThis = (PVGASTATE)pThread->pvUser;
    7579     Log(("vmsvgaR3FifoLoopWakeUp\n"));
    7580     return PDMDevHlpSUPSemEventSignal(pDevIns, pThis->svga.hFIFORequestSem);
    7581 }
    7582 
    7583 /**
    7584  * Enables or disables dirty page tracking for the framebuffer
    7585  *
    7586  * @param   pDevIns         The device instance.
    7587  * @param   pThis           The shared VGA/VMSVGA instance data.
    7588  * @param   fTraces         Enable/disable traces
    7589  */
    7590 static void vmsvgaR3SetTraces(PPDMDEVINS pDevIns, PVGASTATE pThis, bool fTraces)
    7591 {
    7592     if (    (!pThis->svga.fConfigured || !pThis->svga.fEnabled)
    7593         &&  !fTraces)
    7594     {
    7595         //Assert(pThis->svga.fTraces);
    7596         Log(("vmsvgaR3SetTraces: *not* allowed to disable dirty page tracking when the device is in legacy mode.\n"));
    7597         return;
    7598     }
    7599 
    7600     pThis->svga.fTraces = fTraces;
    7601     if (pThis->svga.fTraces)
    7602     {
    7603         unsigned cbFrameBuffer = pThis->vram_size;
    7604 
    7605         Log(("vmsvgaR3SetTraces: enable dirty page handling for the frame buffer only (%x bytes)\n", 0));
    7606         /** @todo How does this work with screens? */
    7607         if (pThis->svga.uHeight != VMSVGA_VAL_UNINITIALIZED)
    7608         {
    7609 # ifndef DEBUG_bird /* BB-10.3.1 triggers this as it initializes everything to zero. Better just ignore it. */
    7610             Assert(pThis->svga.cbScanline);
    7611 # endif
    7612             /* Hardware enabled; return real framebuffer size .*/
    7613             cbFrameBuffer = (uint32_t)pThis->svga.uHeight * pThis->svga.cbScanline;
    7614             cbFrameBuffer = RT_ALIGN(cbFrameBuffer, PAGE_SIZE);
    7615         }
    7616 
    7617         if (!pThis->svga.fVRAMTracking)
    7618         {
    7619             Log(("vmsvgaR3SetTraces: enable frame buffer dirty page tracking. (%x bytes; vram %x)\n", cbFrameBuffer, pThis->vram_size));
    7620             vgaR3RegisterVRAMHandler(pDevIns, pThis, cbFrameBuffer);
    7621             pThis->svga.fVRAMTracking = true;
    7622         }
    7623     }
    7624     else
    7625     {
    7626         if (pThis->svga.fVRAMTracking)
    7627         {
    7628             Log(("vmsvgaR3SetTraces: disable frame buffer dirty page tracking\n"));
    7629             vgaR3UnregisterVRAMHandler(pDevIns, pThis);
    7630             pThis->svga.fVRAMTracking = false;
    7631         }
    7632     }
    7633 }
    7634 
    7635 /**
    7636  * @callback_method_impl{FNPCIIOREGIONMAP}
    7637  */
    7638 DECLCALLBACK(int) vmsvgaR3PciIORegionFifoMapUnmap(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion,
    7639                                                   RTGCPHYS GCPhysAddress, RTGCPHYS cb, PCIADDRESSSPACE enmType)
    7640 {
    7641     PVGASTATE   pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
    7642     int         rc;
    7643     RT_NOREF(pPciDev);
    7644     Assert(pPciDev == pDevIns->apPciDevs[0]);
    7645 
    7646     Log(("vmsvgaR3PciIORegionFifoMapUnmap: iRegion=%d GCPhysAddress=%RGp cb=%RGp enmType=%d\n", iRegion, GCPhysAddress, cb, enmType));
    7647     AssertReturn(   iRegion == pThis->pciRegions.iFIFO
    7648                  && (   enmType == PCI_ADDRESS_SPACE_MEM
    7649                      || (enmType == PCI_ADDRESS_SPACE_MEM_PREFETCH /* got wrong in 6.1.0RC1 */ && pThis->fStateLoaded))
    7650                  , VERR_INTERNAL_ERROR);
    7651     if (GCPhysAddress != NIL_RTGCPHYS)
    7652     {
    7653         /*
    7654          * Mapping the FIFO RAM.
    7655          */
    7656         AssertLogRelMsg(cb == pThis->svga.cbFIFO, ("cb=%#RGp cbFIFO=%#x\n", cb, pThis->svga.cbFIFO));
    7657         rc = PDMDevHlpMmio2Map(pDevIns, pThis->hMmio2VmSvgaFifo, GCPhysAddress);
    7658         AssertRC(rc);
    7659 
    7660 # if defined(VMSVGA_USE_FIFO_ACCESS_HANDLER) || defined(DEBUG_FIFO_ACCESS)
    7661         if (RT_SUCCESS(rc))
    7662         {
    7663             rc = PGMHandlerPhysicalRegister(PDMDevHlpGetVM(pDevIns), GCPhysAddress,
    7664 #  ifdef DEBUG_FIFO_ACCESS
    7665                                             GCPhysAddress + (pThis->svga.cbFIFO - 1),
    7666 #  else
    7667                                             GCPhysAddress + PAGE_SIZE - 1,
    7668 #  endif
    7669                                             pThis->svga.hFifoAccessHandlerType, pThis, NIL_RTR0PTR, NIL_RTRCPTR,
    7670                                             "VMSVGA FIFO");
    7671             AssertRC(rc);
    7672         }
    7673 # endif
    7674         if (RT_SUCCESS(rc))
    7675         {
    7676             pThis->svga.GCPhysFIFO = GCPhysAddress;
    7677             Log(("vmsvgaR3IORegionMap: GCPhysFIFO=%RGp cbFIFO=%#x\n", GCPhysAddress, pThis->svga.cbFIFO));
    7678         }
    7679         rc = VINF_PCI_MAPPING_DONE; /* caller only cares about this status, so it is okay that we overwrite errors here. */
    7680     }
    7681     else
    7682     {
    7683         Assert(pThis->svga.GCPhysFIFO);
    7684 # if defined(VMSVGA_USE_FIFO_ACCESS_HANDLER) || defined(DEBUG_FIFO_ACCESS)
    7685         rc = PGMHandlerPhysicalDeregister(PDMDevHlpGetVM(pDevIns), pThis->svga.GCPhysFIFO);
    7686         AssertRC(rc);
    7687 # else
    7688         rc = VINF_SUCCESS;
    7689 # endif
    7690         pThis->svga.GCPhysFIFO = 0;
    7691     }
    7692     return rc;
    7693 }
    7694 
    7695 # ifdef VBOX_WITH_VMSVGA3D
    7696 
    7697 /**
    7698  * Used by vmsvga3dInfoSurfaceWorker to make the FIFO thread to save one or all
    7699  * surfaces to VMSVGA3DMIPMAPLEVEL::pSurfaceData heap buffers.
    7700  *
    7701  * @param   pDevIns     The device instance.
    7702  * @param   pThis       The The shared VGA/VMSVGA instance data.
    7703  * @param   pThisCC     The VGA/VMSVGA state for ring-3.
    7704  * @param   sid         Either UINT32_MAX or the ID of a specific surface.  If
    7705  *                      UINT32_MAX is used, all surfaces are processed.
    7706  */
    7707 void vmsvgaR33dSurfaceUpdateHeapBuffersOnFifoThread(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, uint32_t sid)
    7708 {
    7709     vmsvgaR3RunExtCmdOnFifoThread(pDevIns, pThis, pThisCC, VMSVGA_FIFO_EXTCMD_UPDATE_SURFACE_HEAP_BUFFERS, (void *)(uintptr_t)sid,
    7710                                   sid == UINT32_MAX ? 10 * RT_MS_1SEC : RT_MS_1MIN);
    7711 }
    7712 
    7713 
    7714 /**
    7715  * @callback_method_impl{FNDBGFHANDLERDEV, "vmsvga3dsfc"}
    7716  */
    7717 DECLCALLBACK(void) vmsvgaR3Info3dSurface(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
    7718 {
    7719     /* There might be a specific surface ID at the start of the
    7720        arguments, if not show all surfaces. */
    7721     uint32_t sid = UINT32_MAX;
    7722     if (pszArgs)
    7723         pszArgs = RTStrStripL(pszArgs);
    7724     if (pszArgs && RT_C_IS_DIGIT(*pszArgs))
    7725         sid = RTStrToUInt32(pszArgs);
    7726 
    7727     /* Verbose or terse display, we default to verbose. */
    7728     bool fVerbose = true;
    7729     if (RTStrIStr(pszArgs, "terse"))
    7730         fVerbose = false;
    7731 
    7732     /* The size of the ascii art (x direction, y is 3/4 of x). */
    7733     uint32_t cxAscii = 80;
    7734     if (RTStrIStr(pszArgs, "gigantic"))
    7735         cxAscii = 300;
    7736     else if (RTStrIStr(pszArgs, "huge"))
    7737         cxAscii = 180;
    7738     else if (RTStrIStr(pszArgs, "big"))
    7739         cxAscii = 132;
    7740     else if (RTStrIStr(pszArgs, "normal"))
    7741         cxAscii = 80;
    7742     else if (RTStrIStr(pszArgs, "medium"))
    7743         cxAscii = 64;
    7744     else if (RTStrIStr(pszArgs, "small"))
    7745         cxAscii = 48;
    7746     else if (RTStrIStr(pszArgs, "tiny"))
    7747         cxAscii = 24;
    7748 
    7749     /* Y invert the image when producing the ASCII art. */
    7750     bool fInvY = false;
    7751     if (RTStrIStr(pszArgs, "invy"))
    7752         fInvY = true;
    7753 
    7754     vmsvga3dInfoSurfaceWorker(pDevIns, PDMDEVINS_2_DATA(pDevIns, PVGASTATE), PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC),
    7755                               pHlp, sid, fVerbose, cxAscii, fInvY, NULL);
    7756 }
    7757 
    7758 
    7759 /**
    7760  * @callback_method_impl{FNDBGFHANDLERDEV, "vmsvga3dsurf"}
    7761  */
    7762 DECLCALLBACK(void) vmsvgaR3Info3dSurfaceBmp(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
    7763 {
    7764     /* pszArg = "sid[>dir]"
    7765      * Writes %dir%/info-S-sidI.bmp, where S - sequential bitmap number, I - decimal surface id.
    7766      */
    7767     char *pszBitmapPath = NULL;
    7768     uint32_t sid = UINT32_MAX;
    7769     if (pszArgs)
    7770         pszArgs = RTStrStripL(pszArgs);
    7771     if (pszArgs && RT_C_IS_DIGIT(*pszArgs))
    7772         RTStrToUInt32Ex(pszArgs, &pszBitmapPath, 0, &sid);
    7773     if (   pszBitmapPath
    7774         && *pszBitmapPath == '>')
    7775         ++pszBitmapPath;
    7776 
    7777     const bool fVerbose = true;
    7778     const uint32_t cxAscii = 0; /* No ASCII */
    7779     const bool fInvY = false;   /* Do not invert. */
    7780     vmsvga3dInfoSurfaceWorker(pDevIns, PDMDEVINS_2_DATA(pDevIns, PVGASTATE), PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC),
    7781                               pHlp, sid, fVerbose, cxAscii, fInvY, pszBitmapPath);
    7782 }
    7783 
    7784 /**
    7785  * @callback_method_impl{FNDBGFHANDLERDEV, "vmsvga3dctx"}
    7786  */
    7787 DECLCALLBACK(void) vmsvgaR3Info3dContext(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
    7788 {
    7789     /* There might be a specific surface ID at the start of the
    7790        arguments, if not show all contexts. */
    7791     uint32_t sid = UINT32_MAX;
    7792     if (pszArgs)
    7793         pszArgs = RTStrStripL(pszArgs);
    7794     if (pszArgs && RT_C_IS_DIGIT(*pszArgs))
    7795         sid = RTStrToUInt32(pszArgs);
    7796 
    7797     /* Verbose or terse display, we default to verbose. */
    7798     bool fVerbose = true;
    7799     if (RTStrIStr(pszArgs, "terse"))
    7800         fVerbose = false;
    7801 
    7802     vmsvga3dInfoContextWorker(PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC), pHlp, sid, fVerbose);
    7803 }
    7804 # endif /* VBOX_WITH_VMSVGA3D */
    7805 
    7806 /**
    7807  * @callback_method_impl{FNDBGFHANDLERDEV, "vmsvga"}
    7808  */
    7809 static DECLCALLBACK(void) vmsvgaR3Info(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
    7810 {
    7811     PVGASTATE       pThis      = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
    7812     PVGASTATECC     pThisCC    = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
    7813     PVMSVGAR3STATE  pSVGAState = pThisCC->svga.pSvgaR3State;
    7814     uint32_t RT_UNTRUSTED_VOLATILE_GUEST *pFIFO = pThisCC->svga.pau32FIFO;
    7815     RT_NOREF(pszArgs);
    7816 
    7817     pHlp->pfnPrintf(pHlp, "Extension enabled:  %RTbool\n", pThis->svga.fEnabled);
    7818     pHlp->pfnPrintf(pHlp, "Configured:         %RTbool\n", pThis->svga.fConfigured);
    7819     pHlp->pfnPrintf(pHlp, "Base I/O port:      %#x\n",
    7820                     pThis->hIoPortVmSvga != NIL_IOMIOPORTHANDLE
    7821                     ? PDMDevHlpIoPortGetMappingAddress(pDevIns, pThis->hIoPortVmSvga) : UINT32_MAX);
    7822     pHlp->pfnPrintf(pHlp, "FIFO address:       %RGp\n", pThis->svga.GCPhysFIFO);
    7823     pHlp->pfnPrintf(pHlp, "FIFO size:          %u (%#x)\n", pThis->svga.cbFIFO, pThis->svga.cbFIFO);
    7824     pHlp->pfnPrintf(pHlp, "FIFO external cmd:  %#x\n", pThis->svga.u8FIFOExtCommand);
    7825     pHlp->pfnPrintf(pHlp, "FIFO extcmd wakeup: %u\n", pThis->svga.fFifoExtCommandWakeup);
    7826     pHlp->pfnPrintf(pHlp, "FIFO min/max:       %u/%u\n", pFIFO[SVGA_FIFO_MIN], pFIFO[SVGA_FIFO_MAX]);
    7827     pHlp->pfnPrintf(pHlp, "Busy:               %#x\n", pThis->svga.fBusy);
    7828     pHlp->pfnPrintf(pHlp, "Traces:             %RTbool (effective: %RTbool)\n", pThis->svga.fTraces, pThis->svga.fVRAMTracking);
    7829     pHlp->pfnPrintf(pHlp, "Guest ID:           %#x (%d)\n", pThis->svga.u32GuestId, pThis->svga.u32GuestId);
    7830     pHlp->pfnPrintf(pHlp, "IRQ status:         %#x\n", pThis->svga.u32IrqStatus);
    7831     pHlp->pfnPrintf(pHlp, "IRQ mask:           %#x\n", pThis->svga.u32IrqMask);
    7832     pHlp->pfnPrintf(pHlp, "Pitch lock:         %#x (FIFO:%#x)\n", pThis->svga.u32PitchLock, pFIFO[SVGA_FIFO_PITCHLOCK]);
    7833     pHlp->pfnPrintf(pHlp, "Current GMR ID:     %#x\n", pThis->svga.u32CurrentGMRId);
    7834     pHlp->pfnPrintf(pHlp, "Device Capabilites: %#x\n", pThis->svga.u32DeviceCaps);
    7835     pHlp->pfnPrintf(pHlp, "Index reg:          %#x\n", pThis->svga.u32IndexReg);
    7836     pHlp->pfnPrintf(pHlp, "Action flags:       %#x\n", pThis->svga.u32ActionFlags);
    7837     pHlp->pfnPrintf(pHlp, "Max display size:   %ux%u\n", pThis->svga.u32MaxWidth, pThis->svga.u32MaxHeight);
    7838     pHlp->pfnPrintf(pHlp, "Display size:       %ux%u %ubpp\n", pThis->svga.uWidth, pThis->svga.uHeight, pThis->svga.uBpp);
    7839     pHlp->pfnPrintf(pHlp, "Scanline:           %u (%#x)\n", pThis->svga.cbScanline, pThis->svga.cbScanline);
    7840     pHlp->pfnPrintf(pHlp, "Viewport position:  %ux%u\n", pThis->svga.viewport.x, pThis->svga.viewport.y);
    7841     pHlp->pfnPrintf(pHlp, "Viewport size:      %ux%u\n", pThis->svga.viewport.cx, pThis->svga.viewport.cy);
    7842 
    7843     pHlp->pfnPrintf(pHlp, "Cursor active:      %RTbool\n", pSVGAState->Cursor.fActive);
    7844     pHlp->pfnPrintf(pHlp, "Cursor hotspot:     %ux%u\n", pSVGAState->Cursor.xHotspot, pSVGAState->Cursor.yHotspot);
    7845     pHlp->pfnPrintf(pHlp, "Cursor size:        %ux%u\n", pSVGAState->Cursor.width, pSVGAState->Cursor.height);
    7846     pHlp->pfnPrintf(pHlp, "Cursor byte size:   %u (%#x)\n", pSVGAState->Cursor.cbData, pSVGAState->Cursor.cbData);
    7847 
    7848     pHlp->pfnPrintf(pHlp, "FIFO cursor:        state %u, screen %d\n", pFIFO[SVGA_FIFO_CURSOR_ON], pFIFO[SVGA_FIFO_CURSOR_SCREEN_ID]);
    7849     pHlp->pfnPrintf(pHlp, "FIFO cursor at:     %u,%u\n", pFIFO[SVGA_FIFO_CURSOR_X], pFIFO[SVGA_FIFO_CURSOR_Y]);
    7850 
    7851     pHlp->pfnPrintf(pHlp, "Legacy cursor:      ID %u, state %u\n", pThis->svga.uCursorID, pThis->svga.uCursorOn);
    7852     pHlp->pfnPrintf(pHlp, "Legacy cursor at:   %u,%u\n", pThis->svga.uCursorX, pThis->svga.uCursorY);
    7853 
    7854 # ifdef VBOX_WITH_VMSVGA3D
    7855     pHlp->pfnPrintf(pHlp, "3D enabled:         %RTbool\n", pThis->svga.f3DEnabled);
    7856 # endif
    7857     if (pThisCC->pDrv)
    7858     {
    7859         pHlp->pfnPrintf(pHlp, "Driver mode:        %ux%u %ubpp\n", pThisCC->pDrv->cx, pThisCC->pDrv->cy, pThisCC->pDrv->cBits);
    7860         pHlp->pfnPrintf(pHlp, "Driver pitch:       %u (%#x)\n", pThisCC->pDrv->cbScanline, pThisCC->pDrv->cbScanline);
    7861     }
    7862 
    7863     /* Dump screen information. */
    7864     for (unsigned iScreen = 0; iScreen < RT_ELEMENTS(pSVGAState->aScreens); ++iScreen)
    7865     {
    7866         VMSVGASCREENOBJECT *pScreen = vmsvgaR3GetScreenObject(pThisCC, iScreen);
    7867         if (pScreen)
    7868         {
    7869             pHlp->pfnPrintf(pHlp, "Screen %u defined (ID %u):\n", iScreen, pScreen->idScreen);
    7870             pHlp->pfnPrintf(pHlp, "  %u x %u x %ubpp @ %u, %u\n", pScreen->cWidth, pScreen->cHeight,
    7871                             pScreen->cBpp, pScreen->xOrigin, pScreen->yOrigin);
    7872             pHlp->pfnPrintf(pHlp, "  Pitch %u bytes, VRAM offset %X\n", pScreen->cbPitch, pScreen->offVRAM);
    7873             pHlp->pfnPrintf(pHlp, "  Flags %X", pScreen->fuScreen);
    7874             if (pScreen->fuScreen != SVGA_SCREEN_MUST_BE_SET)
    7875             {
    7876                 pHlp->pfnPrintf(pHlp, " (");
    7877                 if (pScreen->fuScreen & SVGA_SCREEN_IS_PRIMARY)
    7878                     pHlp->pfnPrintf(pHlp, " IS_PRIMARY");
    7879                 if (pScreen->fuScreen & SVGA_SCREEN_FULLSCREEN_HINT)
    7880                     pHlp->pfnPrintf(pHlp, " FULLSCREEN_HINT");
    7881                 if (pScreen->fuScreen & SVGA_SCREEN_DEACTIVATE)
    7882                     pHlp->pfnPrintf(pHlp, " DEACTIVATE");
    7883                 if (pScreen->fuScreen & SVGA_SCREEN_BLANKING)
    7884                     pHlp->pfnPrintf(pHlp, " BLANKING");
    7885                 pHlp->pfnPrintf(pHlp, " )");
    7886             }
    7887             pHlp->pfnPrintf(pHlp, ", %smodified\n", pScreen->fModified ? "" : "not ");
    7888         }
    7889     }
    7890 
    7891 }
    7892 
    7893 /**
    7894  * Portion of VMSVGA state which must be loaded oin the FIFO thread.
    7895  */
    7896 static int vmsvgaR3LoadExecFifo(PCPDMDEVHLPR3 pHlp, PVGASTATE pThis, PVGASTATECC pThisCC,
    7897                                 PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
    7898 {
    7899     RT_NOREF(uPass);
    7900 
    7901     PVMSVGAR3STATE  pSVGAState = pThisCC->svga.pSvgaR3State;
    7902     int rc;
    7903 
    7904     if (uVersion >= VGA_SAVEDSTATE_VERSION_VMSVGA_SCREENS)
    7905     {
    7906         uint32_t cScreens = 0;
    7907         rc = pHlp->pfnSSMGetU32(pSSM, &cScreens);
    7908         AssertRCReturn(rc, rc);
    7909         AssertLogRelMsgReturn(cScreens <= _64K, /* big enough */
    7910                               ("cScreens=%#x\n", cScreens),
    7911                               VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
    7912 
    7913         for (uint32_t i = 0; i < cScreens; ++i)
    7914         {
    7915             VMSVGASCREENOBJECT screen;
    7916             RT_ZERO(screen);
    7917 
    7918             rc = pHlp->pfnSSMGetStructEx(pSSM, &screen, sizeof(screen), 0, g_aVMSVGASCREENOBJECTFields, NULL);
    7919             AssertLogRelRCReturn(rc, rc);
    7920 
    7921             if (screen.idScreen < RT_ELEMENTS(pSVGAState->aScreens))
    7922             {
    7923                 VMSVGASCREENOBJECT *pScreen = &pSVGAState->aScreens[screen.idScreen];
    7924                 *pScreen = screen;
    7925                 pScreen->fModified = true;
    7926             }
    7927             else
    7928             {
    7929                 LogRel(("VGA: ignored screen object %d\n", screen.idScreen));
    7930             }
    7931         }
    7932     }
    7933     else
    7934     {
    7935         /* Try to setup at least the first screen. */
    7936         VMSVGASCREENOBJECT *pScreen = &pSVGAState->aScreens[0];
    7937         pScreen->fDefined  = true;
    7938         pScreen->fModified = true;
    7939         pScreen->fuScreen  = SVGA_SCREEN_MUST_BE_SET | SVGA_SCREEN_IS_PRIMARY;
    7940         pScreen->idScreen  = 0;
    7941         pScreen->xOrigin   = 0;
    7942         pScreen->yOrigin   = 0;
    7943         pScreen->offVRAM   = pThis->svga.uScreenOffset;
    7944         pScreen->cbPitch   = pThis->svga.cbScanline;
    7945         pScreen->cWidth    = pThis->svga.uWidth;
    7946         pScreen->cHeight   = pThis->svga.uHeight;
    7947         pScreen->cBpp      = pThis->svga.uBpp;
    7948     }
    7949 
    7950     return VINF_SUCCESS;
    7951 }
    7952 
    7953 /**
    7954  * @copydoc FNSSMDEVLOADEXEC
    7955  */
    7956 int vmsvgaR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
    7957 {
    7958     RT_NOREF(uPass);
    7959     PVGASTATE       pThis      = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
    7960     PVGASTATECC     pThisCC    = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
    7961     PVMSVGAR3STATE  pSVGAState = pThisCC->svga.pSvgaR3State;
    7962     PCPDMDEVHLPR3   pHlp       = pDevIns->pHlpR3;
    7963     int             rc;
    7964 
    7965     /* Load our part of the VGAState */
    7966     rc = pHlp->pfnSSMGetStructEx(pSSM, &pThis->svga, sizeof(pThis->svga), 0, g_aVGAStateSVGAFields, NULL);
    7967     AssertRCReturn(rc, rc);
    7968 
    7969     /* Load the VGA framebuffer. */
    7970     AssertCompile(VMSVGA_VGA_FB_BACKUP_SIZE >= _32K);
    7971     uint32_t cbVgaFramebuffer = _32K;
    7972     if (uVersion >= VGA_SAVEDSTATE_VERSION_VMSVGA_VGA_FB_FIX)
    7973     {
    7974         rc = pHlp->pfnSSMGetU32(pSSM, &cbVgaFramebuffer);
    7975         AssertRCReturn(rc, rc);
    7976         AssertLogRelMsgReturn(cbVgaFramebuffer <= _4M && cbVgaFramebuffer >= _32K && RT_IS_POWER_OF_TWO(cbVgaFramebuffer),
    7977                               ("cbVgaFramebuffer=%#x - expected 32KB..4MB, power of two\n", cbVgaFramebuffer),
    7978                               VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
    7979         AssertCompile(VMSVGA_VGA_FB_BACKUP_SIZE <= _4M);
    7980         AssertCompile(RT_IS_POWER_OF_TWO(VMSVGA_VGA_FB_BACKUP_SIZE));
    7981     }
    7982     rc = pHlp->pfnSSMGetMem(pSSM, pThisCC->svga.pbVgaFrameBufferR3, RT_MIN(cbVgaFramebuffer, VMSVGA_VGA_FB_BACKUP_SIZE));
    7983     AssertRCReturn(rc, rc);
    7984     if (cbVgaFramebuffer > VMSVGA_VGA_FB_BACKUP_SIZE)
    7985         pHlp->pfnSSMSkip(pSSM, cbVgaFramebuffer - VMSVGA_VGA_FB_BACKUP_SIZE);
    7986     else if (cbVgaFramebuffer < VMSVGA_VGA_FB_BACKUP_SIZE)
    7987         RT_BZERO(&pThisCC->svga.pbVgaFrameBufferR3[cbVgaFramebuffer], VMSVGA_VGA_FB_BACKUP_SIZE - cbVgaFramebuffer);
    7988 
    7989     /* Load the VMSVGA state. */
    7990     rc = pHlp->pfnSSMGetStructEx(pSSM, pSVGAState, sizeof(*pSVGAState), 0, g_aVMSVGAR3STATEFields, NULL);
    7991     AssertRCReturn(rc, rc);
    7992 
    7993     /* Load the active cursor bitmaps. */
    7994     if (pSVGAState->Cursor.fActive)
    7995     {
    7996         pSVGAState->Cursor.pData = RTMemAlloc(pSVGAState->Cursor.cbData);
    7997         AssertReturn(pSVGAState->Cursor.pData, VERR_NO_MEMORY);
    7998 
    7999         rc = pHlp->pfnSSMGetMem(pSSM, pSVGAState->Cursor.pData, pSVGAState->Cursor.cbData);
    8000         AssertRCReturn(rc, rc);
    8001     }
    8002 
    8003     /* Load the GMR state. */
    8004     uint32_t cGMR = 256; /* Hardcoded in previous saved state versions. */
    8005     if (uVersion >= VGA_SAVEDSTATE_VERSION_VMSVGA_GMR_COUNT)
    8006     {
    8007         rc = pHlp->pfnSSMGetU32(pSSM, &cGMR);
    8008         AssertRCReturn(rc, rc);
    8009         /* Numbers of GMRs was never less than 256. 1MB is a large arbitrary limit. */
    8010         AssertLogRelMsgReturn(cGMR <= _1M && cGMR >= 256,
    8011                               ("cGMR=%#x - expected 256B..1MB\n", cGMR),
    8012                               VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
    8013     }
    8014 
    8015     if (pThis->svga.cGMR != cGMR)
    8016     {
    8017         /* Reallocate GMR array. */
    8018         Assert(pSVGAState->paGMR != NULL);
    8019         RTMemFree(pSVGAState->paGMR);
    8020         pSVGAState->paGMR = (PGMR)RTMemAllocZ(cGMR * sizeof(GMR));
    8021         AssertReturn(pSVGAState->paGMR, VERR_NO_MEMORY);
    8022         pThis->svga.cGMR = cGMR;
    8023     }
    8024 
    8025     for (uint32_t i = 0; i < cGMR; ++i)
    8026     {
    8027         PGMR pGMR = &pSVGAState->paGMR[i];
    8028 
    8029         rc = pHlp->pfnSSMGetStructEx(pSSM, pGMR, sizeof(*pGMR), 0, g_aGMRFields, NULL);
    8030         AssertRCReturn(rc, rc);
    8031 
    8032         if (pGMR->numDescriptors)
    8033         {
    8034             Assert(pGMR->cMaxPages || pGMR->cbTotal);
    8035             pGMR->paDesc = (PVMSVGAGMRDESCRIPTOR)RTMemAllocZ(pGMR->numDescriptors * sizeof(VMSVGAGMRDESCRIPTOR));
    8036             AssertReturn(pGMR->paDesc, VERR_NO_MEMORY);
    8037 
    8038             for (uint32_t j = 0; j < pGMR->numDescriptors; ++j)
    8039             {
    8040                 rc = pHlp->pfnSSMGetStructEx(pSSM, &pGMR->paDesc[j], sizeof(pGMR->paDesc[j]), 0, g_aVMSVGAGMRDESCRIPTORFields, NULL);
    8041                 AssertRCReturn(rc, rc);
    8042             }
    8043         }
    8044     }
    8045 
    8046 #  ifdef RT_OS_DARWIN  /** @todo r=bird: this is normally done on the EMT, so for DARWIN we do that when loading saved state too now. See DevVGA-SVGA3d-shared.h. */
    8047     vmsvga3dPowerOn(pDevIns, pThis, PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC));
    8048 #  endif
    8049 
    8050     VMSVGA_STATE_LOAD LoadState;
    8051     LoadState.pSSM     = pSSM;
    8052     LoadState.uVersion = uVersion;
    8053     LoadState.uPass    = uPass;
    8054     rc = vmsvgaR3RunExtCmdOnFifoThread(pDevIns, pThis, pThisCC, VMSVGA_FIFO_EXTCMD_LOADSTATE, &LoadState, RT_INDEFINITE_WAIT);
    8055     AssertLogRelRCReturn(rc, rc);
    8056 
    8057     return VINF_SUCCESS;
    8058 }
    8059 
    8060 /**
    8061  * Reinit the video mode after the state has been loaded.
    8062  */
    8063 int vmsvgaR3LoadDone(PPDMDEVINS pDevIns)
    8064 {
    8065     PVGASTATE       pThis      = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
    8066     PVGASTATECC     pThisCC    = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
    8067     PVMSVGAR3STATE  pSVGAState = pThisCC->svga.pSvgaR3State;
    8068 
    8069     /* Set the active cursor. */
    8070     if (pSVGAState->Cursor.fActive)
    8071     {
    8072         /* We don't store the alpha flag, but we can take a guess that if
    8073          * the old register interface was used, the cursor was B&W.
    8074          */
    8075         bool    fAlpha = pThis->svga.uCursorOn ? false : true;
    8076 
    8077         int rc = pThisCC->pDrv->pfnVBVAMousePointerShape(pThisCC->pDrv,
    8078                                                          true /*fVisible*/,
    8079                                                          fAlpha,
    8080                                                          pSVGAState->Cursor.xHotspot,
    8081                                                          pSVGAState->Cursor.yHotspot,
    8082                                                          pSVGAState->Cursor.width,
    8083                                                          pSVGAState->Cursor.height,
    8084                                                          pSVGAState->Cursor.pData);
    8085         AssertRC(rc);
    8086 
    8087         if (pThis->svga.uCursorOn)
    8088             pThisCC->pDrv->pfnVBVAReportCursorPosition(pThisCC->pDrv, VBVA_CURSOR_VALID_DATA, SVGA_ID_INVALID, pThis->svga.uCursorX, pThis->svga.uCursorY);
    8089     }
    8090 
    8091     /* If the VRAM handler should not be registered, we have to explicitly
    8092      * unregister it here!
    8093      */
    8094     if (!pThis->svga.fVRAMTracking)
    8095     {
    8096         vgaR3UnregisterVRAMHandler(pDevIns, pThis);
    8097     }
    8098 
    8099     /* Let the FIFO thread deal with changing the mode. */
    8100     ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE);
    8101 
    8102     return VINF_SUCCESS;
    8103 }
    8104 
    8105 /**
    8106  * Portion of SVGA state which must be saved in the FIFO thread.
    8107  */
    8108 static int vmsvgaR3SaveExecFifo(PCPDMDEVHLPR3 pHlp, PVGASTATECC pThisCC, PSSMHANDLE pSSM)
    8109 {
    8110     PVMSVGAR3STATE  pSVGAState = pThisCC->svga.pSvgaR3State;
    8111     int             rc;
    8112 
    8113     /* Save the screen objects. */
    8114     /* Count defined screen object. */
    8115     uint32_t cScreens = 0;
    8116     for (uint32_t i = 0; i < RT_ELEMENTS(pSVGAState->aScreens); ++i)
    8117     {
    8118          if (pSVGAState->aScreens[i].fDefined)
    8119              ++cScreens;
    8120     }
    8121 
    8122     rc = pHlp->pfnSSMPutU32(pSSM, cScreens);
    8123     AssertLogRelRCReturn(rc, rc);
    8124 
    8125     for (uint32_t i = 0; i < cScreens; ++i)
    8126     {
    8127         VMSVGASCREENOBJECT *pScreen = &pSVGAState->aScreens[i];
    8128 
    8129         rc = pHlp->pfnSSMPutStructEx(pSSM, pScreen, sizeof(*pScreen), 0, g_aVMSVGASCREENOBJECTFields, NULL);
    8130         AssertLogRelRCReturn(rc, rc);
    8131     }
    8132     return VINF_SUCCESS;
    8133 }
    8134 
    8135 /**
    8136  * @copydoc FNSSMDEVSAVEEXEC
    8137  */
    8138 int vmsvgaR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
    8139 {
    8140     PVGASTATE       pThis      = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
    8141     PVGASTATECC     pThisCC    = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
    8142     PVMSVGAR3STATE  pSVGAState = pThisCC->svga.pSvgaR3State;
    8143     PCPDMDEVHLPR3   pHlp       = pDevIns->pHlpR3;
    8144     int             rc;
    8145 
    8146     /* Save our part of the VGAState */
    8147     rc = pHlp->pfnSSMPutStructEx(pSSM, &pThis->svga, sizeof(pThis->svga), 0, g_aVGAStateSVGAFields, NULL);
    8148     AssertLogRelRCReturn(rc, rc);
    8149 
    8150     /* Save the framebuffer backup. */
    8151     rc = pHlp->pfnSSMPutU32(pSSM, VMSVGA_VGA_FB_BACKUP_SIZE);
    8152     rc = pHlp->pfnSSMPutMem(pSSM, pThisCC->svga.pbVgaFrameBufferR3, VMSVGA_VGA_FB_BACKUP_SIZE);
    8153     AssertLogRelRCReturn(rc, rc);
    8154 
    8155     /* Save the VMSVGA state. */
    8156     rc = pHlp->pfnSSMPutStructEx(pSSM, pSVGAState, sizeof(*pSVGAState), 0, g_aVMSVGAR3STATEFields, NULL);
    8157     AssertLogRelRCReturn(rc, rc);
    8158 
    8159     /* Save the active cursor bitmaps. */
    8160     if (pSVGAState->Cursor.fActive)
    8161     {
    8162         rc = pHlp->pfnSSMPutMem(pSSM, pSVGAState->Cursor.pData, pSVGAState->Cursor.cbData);
    8163         AssertLogRelRCReturn(rc, rc);
    8164     }
    8165 
    8166     /* Save the GMR state */
    8167     rc = pHlp->pfnSSMPutU32(pSSM, pThis->svga.cGMR);
    8168     AssertLogRelRCReturn(rc, rc);
    8169     for (uint32_t i = 0; i < pThis->svga.cGMR; ++i)
    8170     {
    8171         PGMR pGMR = &pSVGAState->paGMR[i];
    8172 
    8173         rc = pHlp->pfnSSMPutStructEx(pSSM, pGMR, sizeof(*pGMR), 0, g_aGMRFields, NULL);
    8174         AssertLogRelRCReturn(rc, rc);
    8175 
    8176         for (uint32_t j = 0; j < pGMR->numDescriptors; ++j)
    8177         {
    8178             rc = pHlp->pfnSSMPutStructEx(pSSM, &pGMR->paDesc[j], sizeof(pGMR->paDesc[j]), 0, g_aVMSVGAGMRDESCRIPTORFields, NULL);
    8179             AssertLogRelRCReturn(rc, rc);
    8180         }
    8181     }
    8182 
    8183     /*
    8184      * Must save some state (3D in particular) in the FIFO thread.
    8185      */
    8186     rc = vmsvgaR3RunExtCmdOnFifoThread(pDevIns, pThis, pThisCC, VMSVGA_FIFO_EXTCMD_SAVESTATE, pSSM, RT_INDEFINITE_WAIT);
    8187     AssertLogRelRCReturn(rc, rc);
    8188 
    8189     return VINF_SUCCESS;
    8190 }
    8191 
    8192 /**
    8193  * Destructor for PVMSVGAR3STATE structure.
    8194  *
    8195  * @param   pThis          The shared VGA/VMSVGA instance data.
    8196  * @param   pSVGAState     Pointer to the structure. It is not deallocated.
    8197  */
    8198 static void vmsvgaR3StateTerm(PVGASTATE pThis, PVMSVGAR3STATE pSVGAState)
    8199 {
    8200 # ifndef VMSVGA_USE_EMT_HALT_CODE
    8201     if (pSVGAState->hBusyDelayedEmts != NIL_RTSEMEVENTMULTI)
    8202     {
    8203         RTSemEventMultiDestroy(pSVGAState->hBusyDelayedEmts);
    8204         pSVGAState->hBusyDelayedEmts = NIL_RTSEMEVENT;
    8205     }
    8206 # endif
    8207 
    8208     if (pSVGAState->Cursor.fActive)
    8209     {
    8210         RTMemFreeZ(pSVGAState->Cursor.pData, pSVGAState->Cursor.cbData);
    8211         pSVGAState->Cursor.pData = NULL;
    8212         pSVGAState->Cursor.fActive = false;
    8213     }
    8214 
    8215     if (pSVGAState->paGMR)
    8216     {
    8217         for (unsigned i = 0; i < pThis->svga.cGMR; ++i)
    8218             if (pSVGAState->paGMR[i].paDesc)
    8219                 RTMemFree(pSVGAState->paGMR[i].paDesc);
    8220 
    8221         RTMemFree(pSVGAState->paGMR);
    8222         pSVGAState->paGMR = NULL;
    8223     }
    8224 
    8225     if (RTCritSectIsInitialized(&pSVGAState->CritSectCmdBuf))
    8226     {
    8227         RTCritSectEnter(&pSVGAState->CritSectCmdBuf);
    8228         for (unsigned i = 0; i < RT_ELEMENTS(pSVGAState->apCmdBufCtxs); ++i)
    8229         {
    8230             vmsvgaR3CmdBufCtxTerm(pSVGAState->apCmdBufCtxs[i]);
    8231             pSVGAState->apCmdBufCtxs[i] = NULL;
    8232         }
    8233         vmsvgaR3CmdBufCtxTerm(&pSVGAState->CmdBufCtxDC);
    8234         RTCritSectLeave(&pSVGAState->CritSectCmdBuf);
    8235         RTCritSectDelete(&pSVGAState->CritSectCmdBuf);
    8236     }
    8237 }
    8238 
    8239 /**
    8240  * Constructor for PVMSVGAR3STATE structure.
    8241  *
    8242  * @returns VBox status code.
    8243  * @param   pThis          The shared VGA/VMSVGA instance data.
    8244  * @param   pSVGAState     Pointer to the structure. It is already allocated.
    8245  */
    8246 static int vmsvgaR3StateInit(PVGASTATE pThis, PVMSVGAR3STATE pSVGAState)
    8247 {
    8248     int rc = VINF_SUCCESS;
    8249     RT_ZERO(*pSVGAState);
    8250 
    8251     pSVGAState->paGMR = (PGMR)RTMemAllocZ(pThis->svga.cGMR * sizeof(GMR));
    8252     AssertReturn(pSVGAState->paGMR, VERR_NO_MEMORY);
    8253 
    8254 # ifndef VMSVGA_USE_EMT_HALT_CODE
    8255     /* Create semaphore for delaying EMTs wait for the FIFO to stop being busy. */
    8256     rc = RTSemEventMultiCreate(&pSVGAState->hBusyDelayedEmts);
    8257     AssertRCReturn(rc, rc);
    8258 # endif
    8259 
    8260     rc = RTCritSectInit(&pSVGAState->CritSectCmdBuf);
    8261     AssertRCReturn(rc, rc);
    8262 
    8263     vmsvgaR3CmdBufCtxInit(&pSVGAState->CmdBufCtxDC);
    8264     return rc;
    8265 }
    8266 
    8267 /**
    8268  * Initializes the host capabilities: device and FIFO.
    8269  *
    8270  * @returns VBox status code.
    8271  * @param   pThis     The shared VGA/VMSVGA instance data.
    8272  * @param   pThisCC   The VGA/VMSVGA state for ring-3.
    8273  */
    8274 static void vmsvgaR3InitCaps(PVGASTATE pThis, PVGASTATECC pThisCC)
    8275 {
    8276     /* Device caps. */
    8277     pThis->svga.u32DeviceCaps = SVGA_CAP_GMR
    8278                               | SVGA_CAP_GMR2
    8279                               | SVGA_CAP_CURSOR
    8280                               | SVGA_CAP_CURSOR_BYPASS
    8281                               | SVGA_CAP_CURSOR_BYPASS_2
    8282                               | SVGA_CAP_EXTENDED_FIFO
    8283                               | SVGA_CAP_IRQMASK
    8284                               | SVGA_CAP_PITCHLOCK
    8285                               | SVGA_CAP_RECT_COPY
    8286                               | SVGA_CAP_TRACES
    8287                               | SVGA_CAP_SCREEN_OBJECT_2
    8288                               | SVGA_CAP_ALPHA_CURSOR;
    8289 
    8290     /* VGPU10 capabilities. */
    8291     if (pThis->fVMSVGA10)
    8292     {
    8293         pThis->svga.u32DeviceCaps |= SVGA_CAP_COMMAND_BUFFERS /* Enable register based command buffer submission. */
    8294 //                                  |  SVGA_CAP_CMD_BUFFERS_2   /* Support for SVGA_REG_CMD_PREPEND_LOW/HIGH */
    8295 //                                  |  SVGA_CAP_GBOBJECTS       /* Enable guest-backed objects and surfaces. */
    8296 //                                  |  SVGA_CAP_CMD_BUFFERS_3   /* AKA SVGA_CAP_DX. Enable support for DX commands, and command buffers in a mob. */
    8297                                   ;
    8298     }
    8299 
    8300 # ifdef VBOX_WITH_VMSVGA3D
    8301     pThis->svga.u32DeviceCaps |= SVGA_CAP_3D;
    8302 # endif
    8303 
    8304     /* Clear the FIFO. */
    8305     RT_BZERO(pThisCC->svga.pau32FIFO, pThis->svga.cbFIFO);
    8306 
    8307     /* Setup FIFO capabilities. */
    8308     pThisCC->svga.pau32FIFO[SVGA_FIFO_CAPABILITIES] = SVGA_FIFO_CAP_FENCE
    8309                                                     | SVGA_FIFO_CAP_PITCHLOCK
    8310                                                     | SVGA_FIFO_CAP_CURSOR_BYPASS_3
    8311                                                     | SVGA_FIFO_CAP_RESERVE
    8312                                                     | SVGA_FIFO_CAP_GMR2
    8313                                                     | SVGA_FIFO_CAP_3D_HWVERSION_REVISED
    8314                                                     | SVGA_FIFO_CAP_SCREEN_OBJECT_2;
    8315 
    8316     /* Valid with SVGA_FIFO_CAP_SCREEN_OBJECT_2 */
    8317     pThisCC->svga.pau32FIFO[SVGA_FIFO_CURSOR_SCREEN_ID] = SVGA_ID_INVALID;
    8318 }
    8319 
    8320 # ifdef VBOX_WITH_VMSVGA3D
    8321 /** Names for the vmsvga 3d capabilities, prefixed with format type hint char. */
    8322 static const char * const g_apszVmSvgaDevCapNames[] =
    8323 {
    8324     "x3D",                           /* = 0 */
    8325     "xMAX_LIGHTS",
    8326     "xMAX_TEXTURES",
    8327     "xMAX_CLIP_PLANES",
    8328     "xVERTEX_SHADER_VERSION",
    8329     "xVERTEX_SHADER",
    8330     "xFRAGMENT_SHADER_VERSION",
    8331     "xFRAGMENT_SHADER",
    8332     "xMAX_RENDER_TARGETS",
    8333     "xS23E8_TEXTURES",
    8334     "xS10E5_TEXTURES",
    8335     "xMAX_FIXED_VERTEXBLEND",
    8336     "xD16_BUFFER_FORMAT",
    8337     "xD24S8_BUFFER_FORMAT",
    8338     "xD24X8_BUFFER_FORMAT",
    8339     "xQUERY_TYPES",
    8340     "xTEXTURE_GRADIENT_SAMPLING",
    8341     "rMAX_POINT_SIZE",
    8342     "xMAX_SHADER_TEXTURES",
    8343     "xMAX_TEXTURE_WIDTH",
    8344     "xMAX_TEXTURE_HEIGHT",
    8345     "xMAX_VOLUME_EXTENT",
    8346     "xMAX_TEXTURE_REPEAT",
    8347     "xMAX_TEXTURE_ASPECT_RATIO",
    8348     "xMAX_TEXTURE_ANISOTROPY",
    8349     "xMAX_PRIMITIVE_COUNT",
    8350     "xMAX_VERTEX_INDEX",
    8351     "xMAX_VERTEX_SHADER_INSTRUCTIONS",
    8352     "xMAX_FRAGMENT_SHADER_INSTRUCTIONS",
    8353     "xMAX_VERTEX_SHADER_TEMPS",
    8354     "xMAX_FRAGMENT_SHADER_TEMPS",
    8355     "xTEXTURE_OPS",
    8356     "xSURFACEFMT_X8R8G8B8",
    8357     "xSURFACEFMT_A8R8G8B8",
    8358     "xSURFACEFMT_A2R10G10B10",
    8359     "xSURFACEFMT_X1R5G5B5",
    8360     "xSURFACEFMT_A1R5G5B5",
    8361     "xSURFACEFMT_A4R4G4B4",
    8362     "xSURFACEFMT_R5G6B5",
    8363     "xSURFACEFMT_LUMINANCE16",
    8364     "xSURFACEFMT_LUMINANCE8_ALPHA8",
    8365     "xSURFACEFMT_ALPHA8",
    8366     "xSURFACEFMT_LUMINANCE8",
    8367     "xSURFACEFMT_Z_D16",
    8368     "xSURFACEFMT_Z_D24S8",
    8369     "xSURFACEFMT_Z_D24X8",
    8370     "xSURFACEFMT_DXT1",
    8371     "xSURFACEFMT_DXT2",
    8372     "xSURFACEFMT_DXT3",
    8373     "xSURFACEFMT_DXT4",
    8374     "xSURFACEFMT_DXT5",
    8375     "xSURFACEFMT_BUMPX8L8V8U8",
    8376     "xSURFACEFMT_A2W10V10U10",
    8377     "xSURFACEFMT_BUMPU8V8",
    8378     "xSURFACEFMT_Q8W8V8U8",
    8379     "xSURFACEFMT_CxV8U8",
    8380     "xSURFACEFMT_R_S10E5",
    8381     "xSURFACEFMT_R_S23E8",
    8382     "xSURFACEFMT_RG_S10E5",
    8383     "xSURFACEFMT_RG_S23E8",
    8384     "xSURFACEFMT_ARGB_S10E5",
    8385     "xSURFACEFMT_ARGB_S23E8",
    8386     "xMISSING62",
    8387     "xMAX_VERTEX_SHADER_TEXTURES",
    8388     "xMAX_SIMULTANEOUS_RENDER_TARGETS",
    8389     "xSURFACEFMT_V16U16",
    8390     "xSURFACEFMT_G16R16",
    8391     "xSURFACEFMT_A16B16G16R16",
    8392     "xSURFACEFMT_UYVY",
    8393     "xSURFACEFMT_YUY2",
    8394     "xMULTISAMPLE_NONMASKABLESAMPLES",
    8395     "xMULTISAMPLE_MASKABLESAMPLES",
    8396     "xALPHATOCOVERAGE",
    8397     "xSUPERSAMPLE",
    8398     "xAUTOGENMIPMAPS",
    8399     "xSURFACEFMT_NV12",
    8400     "xSURFACEFMT_AYUV",
    8401     "xMAX_CONTEXT_IDS",
    8402     "xMAX_SURFACE_IDS",
    8403     "xSURFACEFMT_Z_DF16",
    8404     "xSURFACEFMT_Z_DF24",
    8405     "xSURFACEFMT_Z_D24S8_INT",
    8406     "xSURFACEFMT_ATI1",
    8407     "xSURFACEFMT_ATI2", /* 83 */
    8408     "xDEAD1",
    8409     "xVIDEO_DECODE",
    8410     "xVIDEO_PROCESS",
    8411     "xLINE_AA",
    8412     "xLINE_STIPPLE",
    8413     "rMAX_LINE_WIDTH",
    8414     "rMAX_AA_LINE_WIDTH",
    8415     "xSURFACEFMT_YV12",
    8416     "xLOGICOPS",
    8417     "xTS_COLOR_KEY",
    8418     "xDEAD2",
    8419     "xDX",
    8420     "xMAX_TEXTURE_ARRAY_SIZE",
    8421     "xDX_MAX_VERTEXBUFFERS",
    8422     "xDX_MAX_CONSTANT_BUFFERS",
    8423     "xDX_PROVOKING_VERTEX",
    8424     "xDXFMT_X8R8G8B8",
    8425     "xDXFMT_A8R8G8B8",
    8426     "xDXFMT_R5G6B5",
    8427     "xDXFMT_X1R5G5B5",
    8428     "xDXFMT_A1R5G5B5",
    8429     "xDXFMT_A4R4G4B4",
    8430     "xDXFMT_Z_D32",
    8431     "xDXFMT_Z_D16",
    8432     "xDXFMT_Z_D24S8",
    8433     "xDXFMT_Z_D15S1",
    8434     "xDXFMT_LUMINANCE8",
    8435     "xDXFMT_LUMINANCE4_ALPHA4",
    8436     "xDXFMT_LUMINANCE16",
    8437     "xDXFMT_LUMINANCE8_ALPHA8",
    8438     "xDXFMT_DXT1",
    8439     "xDXFMT_DXT2",
    8440     "xDXFMT_DXT3",
    8441     "xDXFMT_DXT4",
    8442     "xDXFMT_DXT5",
    8443     "xDXFMT_BUMPU8V8",
    8444     "xDXFMT_BUMPL6V5U5",
    8445     "xDXFMT_BUMPX8L8V8U8",
    8446     "xDXFMT_FORMAT_DEAD1",
    8447     "xDXFMT_ARGB_S10E5",
    8448     "xDXFMT_ARGB_S23E8",
    8449     "xDXFMT_A2R10G10B10",
    8450     "xDXFMT_V8U8",
    8451     "xDXFMT_Q8W8V8U8",
    8452     "xDXFMT_CxV8U8",
    8453     "xDXFMT_X8L8V8U8",
    8454     "xDXFMT_A2W10V10U10",
    8455     "xDXFMT_ALPHA8",
    8456     "xDXFMT_R_S10E5",
    8457     "xDXFMT_R_S23E8",
    8458     "xDXFMT_RG_S10E5",
    8459     "xDXFMT_RG_S23E8",
    8460     "xDXFMT_BUFFER",
    8461     "xDXFMT_Z_D24X8",
    8462     "xDXFMT_V16U16",
    8463     "xDXFMT_G16R16",
    8464     "xDXFMT_A16B16G16R16",
    8465     "xDXFMT_UYVY",
    8466     "xDXFMT_YUY2",
    8467     "xDXFMT_NV12",
    8468     "xDXFMT_AYUV",
    8469     "xDXFMT_R32G32B32A32_TYPELESS",
    8470     "xDXFMT_R32G32B32A32_UINT",
    8471     "xDXFMT_R32G32B32A32_SINT",
    8472     "xDXFMT_R32G32B32_TYPELESS",
    8473     "xDXFMT_R32G32B32_FLOAT",
    8474     "xDXFMT_R32G32B32_UINT",
    8475     "xDXFMT_R32G32B32_SINT",
    8476     "xDXFMT_R16G16B16A16_TYPELESS",
    8477     "xDXFMT_R16G16B16A16_UINT",
    8478     "xDXFMT_R16G16B16A16_SNORM",
    8479     "xDXFMT_R16G16B16A16_SINT",
    8480     "xDXFMT_R32G32_TYPELESS",
    8481     "xDXFMT_R32G32_UINT",
    8482     "xDXFMT_R32G32_SINT",
    8483     "xDXFMT_R32G8X24_TYPELESS",
    8484     "xDXFMT_D32_FLOAT_S8X24_UINT",
    8485     "xDXFMT_R32_FLOAT_X8X24_TYPELESS",
    8486     "xDXFMT_X32_TYPELESS_G8X24_UINT",
    8487     "xDXFMT_R10G10B10A2_TYPELESS",
    8488     "xDXFMT_R10G10B10A2_UINT",
    8489     "xDXFMT_R11G11B10_FLOAT",
    8490     "xDXFMT_R8G8B8A8_TYPELESS",
    8491     "xDXFMT_R8G8B8A8_UNORM",
    8492     "xDXFMT_R8G8B8A8_UNORM_SRGB",
    8493     "xDXFMT_R8G8B8A8_UINT",
    8494     "xDXFMT_R8G8B8A8_SINT",
    8495     "xDXFMT_R16G16_TYPELESS",
    8496     "xDXFMT_R16G16_UINT",
    8497     "xDXFMT_R16G16_SINT",
    8498     "xDXFMT_R32_TYPELESS",
    8499     "xDXFMT_D32_FLOAT",
    8500     "xDXFMT_R32_UINT",
    8501     "xDXFMT_R32_SINT",
    8502     "xDXFMT_R24G8_TYPELESS",
    8503     "xDXFMT_D24_UNORM_S8_UINT",
    8504     "xDXFMT_R24_UNORM_X8_TYPELESS",
    8505     "xDXFMT_X24_TYPELESS_G8_UINT",
    8506     "xDXFMT_R8G8_TYPELESS",
    8507     "xDXFMT_R8G8_UNORM",
    8508     "xDXFMT_R8G8_UINT",
    8509     "xDXFMT_R8G8_SINT",
    8510     "xDXFMT_R16_TYPELESS",
    8511     "xDXFMT_R16_UNORM",
    8512     "xDXFMT_R16_UINT",
    8513     "xDXFMT_R16_SNORM",
    8514     "xDXFMT_R16_SINT",
    8515     "xDXFMT_R8_TYPELESS",
    8516     "xDXFMT_R8_UNORM",
    8517     "xDXFMT_R8_UINT",
    8518     "xDXFMT_R8_SNORM",
    8519     "xDXFMT_R8_SINT",
    8520     "xDXFMT_P8",
    8521     "xDXFMT_R9G9B9E5_SHAREDEXP",
    8522     "xDXFMT_R8G8_B8G8_UNORM",
    8523     "xDXFMT_G8R8_G8B8_UNORM",
    8524     "xDXFMT_BC1_TYPELESS",
    8525     "xDXFMT_BC1_UNORM_SRGB",
    8526     "xDXFMT_BC2_TYPELESS",
    8527     "xDXFMT_BC2_UNORM_SRGB",
    8528     "xDXFMT_BC3_TYPELESS",
    8529     "xDXFMT_BC3_UNORM_SRGB",
    8530     "xDXFMT_BC4_TYPELESS",
    8531     "xDXFMT_ATI1",
    8532     "xDXFMT_BC4_SNORM",
    8533     "xDXFMT_BC5_TYPELESS",
    8534     "xDXFMT_ATI2",
    8535     "xDXFMT_BC5_SNORM",
    8536     "xDXFMT_R10G10B10_XR_BIAS_A2_UNORM",
    8537     "xDXFMT_B8G8R8A8_TYPELESS",
    8538     "xDXFMT_B8G8R8A8_UNORM_SRGB",
    8539     "xDXFMT_B8G8R8X8_TYPELESS",
    8540     "xDXFMT_B8G8R8X8_UNORM_SRGB",
    8541     "xDXFMT_Z_DF16",
    8542     "xDXFMT_Z_DF24",
    8543     "xDXFMT_Z_D24S8_INT",
    8544     "xDXFMT_YV12",
    8545     "xDXFMT_R32G32B32A32_FLOAT",
    8546     "xDXFMT_R16G16B16A16_FLOAT",
    8547     "xDXFMT_R16G16B16A16_UNORM",
    8548     "xDXFMT_R32G32_FLOAT",
    8549     "xDXFMT_R10G10B10A2_UNORM",
    8550     "xDXFMT_R8G8B8A8_SNORM",
    8551     "xDXFMT_R16G16_FLOAT",
    8552     "xDXFMT_R16G16_UNORM",
    8553     "xDXFMT_R16G16_SNORM",
    8554     "xDXFMT_R32_FLOAT",
    8555     "xDXFMT_R8G8_SNORM",
    8556     "xDXFMT_R16_FLOAT",
    8557     "xDXFMT_D16_UNORM",
    8558     "xDXFMT_A8_UNORM",
    8559     "xDXFMT_BC1_UNORM",
    8560     "xDXFMT_BC2_UNORM",
    8561     "xDXFMT_BC3_UNORM",
    8562     "xDXFMT_B5G6R5_UNORM",
    8563     "xDXFMT_B5G5R5A1_UNORM",
    8564     "xDXFMT_B8G8R8A8_UNORM",
    8565     "xDXFMT_B8G8R8X8_UNORM",
    8566     "xDXFMT_BC4_UNORM",
    8567     "xDXFMT_BC5_UNORM",
    8568 };
    8569 
    8570 /**
    8571  * Initializes the host 3D capabilities and writes them to FIFO memory.
    8572  *
    8573  * @returns VBox status code.
    8574  * @param   pThis     The shared VGA/VMSVGA instance data.
    8575  * @param   pThisCC   The VGA/VMSVGA state for ring-3.
    8576  */
    8577 static void vmsvgaR3InitFifo3DCaps(PVGASTATE pThis, PVGASTATECC pThisCC)
    8578 {
    8579     /* Query the capabilities and store them in the pThis->svga.au32DevCaps array. */
    8580     bool const fSavedBuffering = RTLogRelSetBuffering(true);
    8581 
    8582     for (unsigned i = 0; i < RT_ELEMENTS(pThis->svga.au32DevCaps); ++i)
    8583     {
    8584         uint32_t val = 0;
    8585         int rc = vmsvga3dQueryCaps(pThisCC, i, &val);
    8586         if (RT_SUCCESS(rc))
    8587             pThis->svga.au32DevCaps[i] = val;
    8588         else
    8589             pThis->svga.au32DevCaps[i] = 0;
    8590 
    8591         /* LogRel the capability value. */
    8592         if (i < RT_ELEMENTS(g_apszVmSvgaDevCapNames))
    8593         {
    8594             if (RT_SUCCESS(rc))
    8595             {
    8596                 if (g_apszVmSvgaDevCapNames[i][0] == 'x')
    8597                     LogRel(("VMSVGA3d: cap[%u]=%#010x {%s}\n", i, val, &g_apszVmSvgaDevCapNames[i][1]));
    8598                 else
    8599                 {
    8600                     float const fval = *(float *)&val;
    8601                     LogRel(("VMSVGA3d: cap[%u]=" FLOAT_FMT_STR " {%s}\n", i, FLOAT_FMT_ARGS(fval), &g_apszVmSvgaDevCapNames[i][1]));
    8602                 }
    8603             }
    8604             else
    8605                 LogRel(("VMSVGA3d: cap[%u]=failed rc=%Rrc {%s}\n", i, rc, &g_apszVmSvgaDevCapNames[i][1]));
    8606         }
    8607         else
    8608             LogRel(("VMSVGA3d: new cap[%u]=%#010x rc=%Rrc\n", i, val, rc));
    8609     }
    8610 
    8611     RTLogRelSetBuffering(fSavedBuffering);
    8612 
    8613     /* 3d hardware version; latest and greatest */
    8614     pThisCC->svga.pau32FIFO[SVGA_FIFO_3D_HWVERSION_REVISED] = SVGA3D_HWVERSION_CURRENT;
    8615     pThisCC->svga.pau32FIFO[SVGA_FIFO_3D_HWVERSION]         = SVGA3D_HWVERSION_CURRENT;
    8616 
    8617     /* Fill out 3d capabilities up to SVGA3D_DEVCAP_SURFACEFMT_ATI2 in the FIFO memory.
    8618      * SVGA3D_DEVCAP_SURFACEFMT_ATI2 is the last capabiltiy for pre-SVGA_CAP_GBOBJECTS hardware.
    8619      * If the VMSVGA device supports SVGA_CAP_GBOBJECTS capability, then the guest has to use SVGA_REG_DEV_CAP
    8620      * register to query the devcaps. Older guests will still try to read the devcaps from FIFO.
    8621      */
    8622     SVGA3dCapsRecord *pCaps;
    8623     SVGA3dCapPair    *pData;
    8624 
    8625     pCaps = (SVGA3dCapsRecord *)&pThisCC->svga.pau32FIFO[SVGA_FIFO_3D_CAPS];
    8626     pCaps->header.type   = SVGA3DCAPS_RECORD_DEVCAPS;
    8627     pData = (SVGA3dCapPair *)&pCaps->data;
    8628 
    8629     AssertCompile(SVGA3D_DEVCAP_DEAD1 == SVGA3D_DEVCAP_SURFACEFMT_ATI2 + 1);
    8630     for (unsigned i = 0; i < SVGA3D_DEVCAP_DEAD1; ++i)
    8631     {
    8632         pData[i][0] = i;
    8633         pData[i][1] = pThis->svga.au32DevCaps[i];
    8634     }
    8635     pCaps->header.length = (sizeof(pCaps->header) + SVGA3D_DEVCAP_DEAD1 * sizeof(SVGA3dCapPair)) / sizeof(uint32_t);
    8636     pCaps = (SVGA3dCapsRecord *)((uint32_t *)pCaps + pCaps->header.length);
    8637 
    8638     /* Mark end of record array (a zero word). */
    8639     pCaps->header.length = 0;
    8640 }
    8641 
    8642 # endif
    8643 
    8644 /**
    8645  * Resets the SVGA hardware state
    8646  *
    8647  * @returns VBox status code.
    8648  * @param   pDevIns     The device instance.
    8649  */
    8650 int vmsvgaR3Reset(PPDMDEVINS pDevIns)
    8651 {
    8652     PVGASTATE       pThis      = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
    8653     PVGASTATECC     pThisCC    = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
    8654     PVMSVGAR3STATE  pSVGAState = pThisCC->svga.pSvgaR3State;
    8655 
    8656     /* Reset before init? */
    8657     if (!pSVGAState)
    8658         return VINF_SUCCESS;
    8659 
    8660     Log(("vmsvgaR3Reset\n"));
    8661 
    8662     /* Reset the FIFO processing as well as the 3d state (if we have one). */
    8663     pThisCC->svga.pau32FIFO[SVGA_FIFO_NEXT_CMD] = pThisCC->svga.pau32FIFO[SVGA_FIFO_STOP] = 0; /** @todo should probably let the FIFO thread do this ... */
    8664     int rc = vmsvgaR3RunExtCmdOnFifoThread(pDevIns, pThis, pThisCC, VMSVGA_FIFO_EXTCMD_RESET, NULL /*pvParam*/, 10000 /*ms*/);
    8665 
    8666     /* Reset other stuff. */
    8667     pThis->svga.cScratchRegion = VMSVGA_SCRATCH_SIZE;
    8668     RT_ZERO(pThis->svga.au32ScratchRegion);
    8669 
    8670     vmsvgaR3StateTerm(pThis, pThisCC->svga.pSvgaR3State);
    8671     vmsvgaR3StateInit(pThis, pThisCC->svga.pSvgaR3State);
    8672 
    8673     RT_BZERO(pThisCC->svga.pbVgaFrameBufferR3, VMSVGA_VGA_FB_BACKUP_SIZE);
    8674 
    8675     /* Initialize FIFO and register capabilities. */
    8676     vmsvgaR3InitCaps(pThis, pThisCC);
    8677 
    8678 # ifdef VBOX_WITH_VMSVGA3D
    8679     if (pThis->svga.f3DEnabled)
    8680         vmsvgaR3InitFifo3DCaps(pThis, pThisCC);
    8681 # endif
    8682 
    8683     /* VRAM tracking is enabled by default during bootup. */
    8684     pThis->svga.fVRAMTracking = true;
    8685     pThis->svga.fEnabled      = false;
    8686 
    8687     /* Invalidate current settings. */
    8688     pThis->svga.uWidth       = VMSVGA_VAL_UNINITIALIZED;
    8689     pThis->svga.uHeight      = VMSVGA_VAL_UNINITIALIZED;
    8690     pThis->svga.uBpp         = pThis->svga.uHostBpp;
    8691     pThis->svga.cbScanline   = 0;
    8692     pThis->svga.u32PitchLock = 0;
    8693 
    8694     return rc;
    8695 }
    8696 
    8697 /**
    8698  * Cleans up the SVGA hardware state
    8699  *
    8700  * @returns VBox status code.
    8701  * @param   pDevIns     The device instance.
    8702  */
    8703 int vmsvgaR3Destruct(PPDMDEVINS pDevIns)
    8704 {
    8705     PVGASTATE   pThis   = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
    8706     PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
    8707 
    8708     /*
    8709      * Ask the FIFO thread to terminate the 3d state and then terminate it.
    8710      */
    8711     if (pThisCC->svga.pFIFOIOThread)
    8712     {
    8713         int rc = vmsvgaR3RunExtCmdOnFifoThread(pDevIns, pThis, pThisCC,  VMSVGA_FIFO_EXTCMD_TERMINATE,
    8714                                                NULL /*pvParam*/, 30000 /*ms*/);
    8715         AssertLogRelRC(rc);
    8716 
    8717         rc = PDMDevHlpThreadDestroy(pDevIns, pThisCC->svga.pFIFOIOThread, NULL);
    8718         AssertLogRelRC(rc);
    8719         pThisCC->svga.pFIFOIOThread = NULL;
    8720     }
    8721 
    8722     /*
    8723      * Destroy the special SVGA state.
    8724      */
    8725     if (pThisCC->svga.pSvgaR3State)
    8726     {
    8727         vmsvgaR3StateTerm(pThis, pThisCC->svga.pSvgaR3State);
    8728 
    8729         RTMemFree(pThisCC->svga.pSvgaR3State);
    8730         pThisCC->svga.pSvgaR3State = NULL;
    8731     }
    8732 
    8733     /*
    8734      * Free our resources residing in the VGA state.
    8735      */
    8736     if (pThisCC->svga.pbVgaFrameBufferR3)
    8737     {
    8738         RTMemFree(pThisCC->svga.pbVgaFrameBufferR3);
    8739         pThisCC->svga.pbVgaFrameBufferR3 = NULL;
    8740     }
    8741     if (pThisCC->svga.hFIFOExtCmdSem != NIL_RTSEMEVENT)
    8742     {
    8743         RTSemEventDestroy(pThisCC->svga.hFIFOExtCmdSem);
    8744         pThisCC->svga.hFIFOExtCmdSem = NIL_RTSEMEVENT;
    8745     }
    8746     if (pThis->svga.hFIFORequestSem != NIL_SUPSEMEVENT)
    8747     {
    8748         PDMDevHlpSUPSemEventClose(pDevIns, pThis->svga.hFIFORequestSem);
    8749         pThis->svga.hFIFORequestSem = NIL_SUPSEMEVENT;
    8750     }
    8751 
    8752     return VINF_SUCCESS;
    8753 }
    8754 
    8755 /**
    8756  * Initialize the SVGA hardware state
    8757  *
    8758  * @returns VBox status code.
    8759  * @param   pDevIns     The device instance.
    8760  */
    8761 int vmsvgaR3Init(PPDMDEVINS pDevIns)
    8762 {
    8763     PVGASTATE       pThis   = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
    8764     PVGASTATECC     pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
    8765     PVMSVGAR3STATE  pSVGAState;
    8766     int             rc;
    8767 
    8768     pThis->svga.cScratchRegion = VMSVGA_SCRATCH_SIZE;
    8769     memset(pThis->svga.au32ScratchRegion, 0, sizeof(pThis->svga.au32ScratchRegion));
    8770 
    8771     pThis->svga.cGMR = VMSVGA_MAX_GMR_IDS;
    8772 
    8773     /* Necessary for creating a backup of the text mode frame buffer when switching into svga mode. */
    8774     pThisCC->svga.pbVgaFrameBufferR3 = (uint8_t *)RTMemAllocZ(VMSVGA_VGA_FB_BACKUP_SIZE);
    8775     AssertReturn(pThisCC->svga.pbVgaFrameBufferR3, VERR_NO_MEMORY);
    8776 
    8777     /* Create event semaphore. */
    8778     rc = PDMDevHlpSUPSemEventCreate(pDevIns, &pThis->svga.hFIFORequestSem);
    8779     AssertRCReturn(rc, rc);
    8780 
    8781     /* Create event semaphore. */
    8782     rc = RTSemEventCreate(&pThisCC->svga.hFIFOExtCmdSem);
    8783     AssertRCReturn(rc, rc);
    8784 
    8785     pThisCC->svga.pSvgaR3State = (PVMSVGAR3STATE)RTMemAlloc(sizeof(VMSVGAR3STATE));
    8786     AssertReturn(pThisCC->svga.pSvgaR3State, VERR_NO_MEMORY);
    8787 
    8788     rc = vmsvgaR3StateInit(pThis, pThisCC->svga.pSvgaR3State);
    8789     AssertMsgRCReturn(rc, ("Failed to create pSvgaR3State.\n"), rc);
    8790 
    8791     pSVGAState = pThisCC->svga.pSvgaR3State;
    8792 
    8793     /* Initialize FIFO and register capabilities. */
    8794     vmsvgaR3InitCaps(pThis, pThisCC);
    8795 
    8796 # ifdef VBOX_WITH_VMSVGA3D
    8797     if (pThis->svga.f3DEnabled)
    8798     {
    8799         rc = vmsvga3dInit(pDevIns, pThis, pThisCC);
    8800         if (RT_FAILURE(rc))
    8801         {
    8802             LogRel(("VMSVGA3d: 3D support disabled! (vmsvga3dInit -> %Rrc)\n", rc));
    8803             pThis->svga.f3DEnabled = false;
    8804         }
    8805     }
    8806 # endif
    8807     /* VRAM tracking is enabled by default during bootup. */
    8808     pThis->svga.fVRAMTracking = true;
    8809 
    8810     /* Set up the host bpp. This value is as a default for the programmable
    8811      * bpp value. On old implementations, SVGA_REG_HOST_BITS_PER_PIXEL did not
    8812      * exist and SVGA_REG_BITS_PER_PIXEL was read-only, returning what was later
    8813      * separated as SVGA_REG_HOST_BITS_PER_PIXEL.
    8814      *
    8815      * NB: The driver cBits value is currently constant for the lifetime of the
    8816      * VM. If that changes, the host bpp logic might need revisiting.
    8817      */
    8818     pThis->svga.uHostBpp = (pThisCC->pDrv->cBits + 7) & ~7;
    8819 
    8820     /* Invalidate current settings. */
    8821     pThis->svga.uWidth     = VMSVGA_VAL_UNINITIALIZED;
    8822     pThis->svga.uHeight    = VMSVGA_VAL_UNINITIALIZED;
    8823     pThis->svga.uBpp       = pThis->svga.uHostBpp;
    8824     pThis->svga.cbScanline = 0;
    8825 
    8826     pThis->svga.u32MaxWidth  = VBE_DISPI_MAX_YRES;
    8827     pThis->svga.u32MaxHeight = VBE_DISPI_MAX_XRES;
    8828     while (pThis->svga.u32MaxWidth * pThis->svga.u32MaxHeight * 4 /* 32 bpp */ > pThis->vram_size)
    8829     {
    8830         pThis->svga.u32MaxWidth  -= 256;
    8831         pThis->svga.u32MaxHeight -= 256;
    8832     }
    8833     Log(("VMSVGA: Maximum size (%d,%d)\n", pThis->svga.u32MaxWidth, pThis->svga.u32MaxHeight));
    8834 
    8835 # ifdef DEBUG_GMR_ACCESS
    8836     /* Register the GMR access handler type. */
    8837     rc = PGMR3HandlerPhysicalTypeRegister(PDMDevHlpGetVM(pDevIns), PGMPHYSHANDLERKIND_WRITE,
    8838                                           vmsvgaR3GmrAccessHandler,
    8839                                           NULL, NULL, NULL,
    8840                                           NULL, NULL, NULL,
    8841                                           "VMSVGA GMR", &pThis->svga.hGmrAccessHandlerType);
    8842     AssertRCReturn(rc, rc);
    8843 # endif
    8844 
    8845 # if defined(VMSVGA_USE_FIFO_ACCESS_HANDLER) || defined(DEBUG_FIFO_ACCESS)
    8846     /* Register the FIFO access handler type.  In addition to
    8847        debugging FIFO access, this is also used to facilitate
    8848        extended fifo thread sleeps. */
    8849     rc = PGMR3HandlerPhysicalTypeRegister(PDMDevHlpGetVM(pDevIns),
    8850 #  ifdef DEBUG_FIFO_ACCESS
    8851                                           PGMPHYSHANDLERKIND_ALL,
    8852 #  else
    8853                                           PGMPHYSHANDLERKIND_WRITE,
    8854 #  endif
    8855                                           vmsvgaR3FifoAccessHandler,
    8856                                           NULL, NULL, NULL,
    8857                                           NULL, NULL, NULL,
    8858                                           "VMSVGA FIFO", &pThis->svga.hFifoAccessHandlerType);
    8859     AssertRCReturn(rc, rc);
    8860 # endif
    8861 
    8862     /* Create the async IO thread. */
    8863     rc = PDMDevHlpThreadCreate(pDevIns, &pThisCC->svga.pFIFOIOThread, pThis, vmsvgaR3FifoLoop, vmsvgaR3FifoLoopWakeUp, 0,
    8864                                RTTHREADTYPE_IO, "VMSVGA FIFO");
    8865     if (RT_FAILURE(rc))
    8866     {
    8867         AssertMsgFailed(("%s: Async IO Thread creation for FIFO handling failed rc=%d\n", __FUNCTION__, rc));
    8868         return rc;
    8869     }
    8870 
    8871     /*
    8872      * Statistics.
    8873      */
    8874 # define REG_CNT(a_pvSample, a_pszName, a_pszDesc) \
    8875         PDMDevHlpSTAMRegister(pDevIns, (a_pvSample), STAMTYPE_COUNTER, a_pszName, STAMUNIT_OCCURENCES, a_pszDesc)
    8876 # define REG_PRF(a_pvSample, a_pszName, a_pszDesc) \
    8877         PDMDevHlpSTAMRegister(pDevIns, (a_pvSample), STAMTYPE_PROFILE, a_pszName, STAMUNIT_TICKS_PER_CALL, a_pszDesc)
    8878 # ifdef VBOX_WITH_STATISTICS
    8879     REG_PRF(&pSVGAState->StatR3Cmd3dDrawPrimitivesProf,   "VMSVGA/Cmd/3dDrawPrimitivesProf",       "Profiling of SVGA_3D_CMD_DRAW_PRIMITIVES.");
    8880     REG_PRF(&pSVGAState->StatR3Cmd3dPresentProf,          "VMSVGA/Cmd/3dPresentProfBoth",          "Profiling of SVGA_3D_CMD_PRESENT and SVGA_3D_CMD_PRESENT_READBACK.");
    8881     REG_PRF(&pSVGAState->StatR3Cmd3dSurfaceDmaProf,       "VMSVGA/Cmd/3dSurfaceDmaProf",           "Profiling of SVGA_3D_CMD_SURFACE_DMA.");
    8882 # endif
    8883     REG_PRF(&pSVGAState->StatR3Cmd3dBlitSurfaceToScreenProf, "VMSVGA/Cmd/3dBlitSurfaceToScreenProf", "Profiling of SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN.");
    8884     REG_CNT(&pSVGAState->StatR3Cmd3dActivateSurface,      "VMSVGA/Cmd/3dActivateSurface",          "SVGA_3D_CMD_ACTIVATE_SURFACE");
    8885     REG_CNT(&pSVGAState->StatR3Cmd3dBeginQuery,           "VMSVGA/Cmd/3dBeginQuery",               "SVGA_3D_CMD_BEGIN_QUERY");
    8886     REG_CNT(&pSVGAState->StatR3Cmd3dClear,                "VMSVGA/Cmd/3dClear",                    "SVGA_3D_CMD_CLEAR");
    8887     REG_CNT(&pSVGAState->StatR3Cmd3dContextDefine,        "VMSVGA/Cmd/3dContextDefine",            "SVGA_3D_CMD_CONTEXT_DEFINE");
    8888     REG_CNT(&pSVGAState->StatR3Cmd3dContextDestroy,       "VMSVGA/Cmd/3dContextDestroy",           "SVGA_3D_CMD_CONTEXT_DESTROY");
    8889     REG_CNT(&pSVGAState->StatR3Cmd3dDeactivateSurface,    "VMSVGA/Cmd/3dDeactivateSurface",        "SVGA_3D_CMD_DEACTIVATE_SURFACE");
    8890     REG_CNT(&pSVGAState->StatR3Cmd3dDrawPrimitives,       "VMSVGA/Cmd/3dDrawPrimitives",           "SVGA_3D_CMD_DRAW_PRIMITIVES");
    8891     REG_CNT(&pSVGAState->StatR3Cmd3dEndQuery,             "VMSVGA/Cmd/3dEndQuery",                 "SVGA_3D_CMD_END_QUERY");
    8892     REG_CNT(&pSVGAState->StatR3Cmd3dGenerateMipmaps,      "VMSVGA/Cmd/3dGenerateMipmaps",          "SVGA_3D_CMD_GENERATE_MIPMAPS");
    8893     REG_CNT(&pSVGAState->StatR3Cmd3dPresent,              "VMSVGA/Cmd/3dPresent",                  "SVGA_3D_CMD_PRESENT");
    8894     REG_CNT(&pSVGAState->StatR3Cmd3dPresentReadBack,      "VMSVGA/Cmd/3dPresentReadBack",          "SVGA_3D_CMD_PRESENT_READBACK");
    8895     REG_CNT(&pSVGAState->StatR3Cmd3dSetClipPlane,         "VMSVGA/Cmd/3dSetClipPlane",             "SVGA_3D_CMD_SETCLIPPLANE");
    8896     REG_CNT(&pSVGAState->StatR3Cmd3dSetLightData,         "VMSVGA/Cmd/3dSetLightData",             "SVGA_3D_CMD_SETLIGHTDATA");
    8897     REG_CNT(&pSVGAState->StatR3Cmd3dSetLightEnable,       "VMSVGA/Cmd/3dSetLightEnable",           "SVGA_3D_CMD_SETLIGHTENABLE");
    8898     REG_CNT(&pSVGAState->StatR3Cmd3dSetMaterial,          "VMSVGA/Cmd/3dSetMaterial",              "SVGA_3D_CMD_SETMATERIAL");
    8899     REG_CNT(&pSVGAState->StatR3Cmd3dSetRenderState,       "VMSVGA/Cmd/3dSetRenderState",           "SVGA_3D_CMD_SETRENDERSTATE");
    8900     REG_CNT(&pSVGAState->StatR3Cmd3dSetRenderTarget,      "VMSVGA/Cmd/3dSetRenderTarget",          "SVGA_3D_CMD_SETRENDERTARGET");
    8901     REG_CNT(&pSVGAState->StatR3Cmd3dSetScissorRect,       "VMSVGA/Cmd/3dSetScissorRect",           "SVGA_3D_CMD_SETSCISSORRECT");
    8902     REG_CNT(&pSVGAState->StatR3Cmd3dSetShader,            "VMSVGA/Cmd/3dSetShader",                "SVGA_3D_CMD_SET_SHADER");
    8903     REG_CNT(&pSVGAState->StatR3Cmd3dSetShaderConst,       "VMSVGA/Cmd/3dSetShaderConst",           "SVGA_3D_CMD_SET_SHADER_CONST");
    8904     REG_CNT(&pSVGAState->StatR3Cmd3dSetTextureState,      "VMSVGA/Cmd/3dSetTextureState",          "SVGA_3D_CMD_SETTEXTURESTATE");
    8905     REG_CNT(&pSVGAState->StatR3Cmd3dSetTransform,         "VMSVGA/Cmd/3dSetTransform",             "SVGA_3D_CMD_SETTRANSFORM");
    8906     REG_CNT(&pSVGAState->StatR3Cmd3dSetViewPort,          "VMSVGA/Cmd/3dSetViewPort",              "SVGA_3D_CMD_SETVIEWPORT");
    8907     REG_CNT(&pSVGAState->StatR3Cmd3dSetZRange,            "VMSVGA/Cmd/3dSetZRange",                "SVGA_3D_CMD_SETZRANGE");
    8908     REG_CNT(&pSVGAState->StatR3Cmd3dShaderDefine,         "VMSVGA/Cmd/3dShaderDefine",             "SVGA_3D_CMD_SHADER_DEFINE");
    8909     REG_CNT(&pSVGAState->StatR3Cmd3dShaderDestroy,        "VMSVGA/Cmd/3dShaderDestroy",            "SVGA_3D_CMD_SHADER_DESTROY");
    8910     REG_CNT(&pSVGAState->StatR3Cmd3dSurfaceCopy,          "VMSVGA/Cmd/3dSurfaceCopy",              "SVGA_3D_CMD_SURFACE_COPY");
    8911     REG_CNT(&pSVGAState->StatR3Cmd3dSurfaceDefine,        "VMSVGA/Cmd/3dSurfaceDefine",            "SVGA_3D_CMD_SURFACE_DEFINE");
    8912     REG_CNT(&pSVGAState->StatR3Cmd3dSurfaceDefineV2,      "VMSVGA/Cmd/3dSurfaceDefineV2",          "SVGA_3D_CMD_SURFACE_DEFINE_V2");
    8913     REG_CNT(&pSVGAState->StatR3Cmd3dSurfaceDestroy,       "VMSVGA/Cmd/3dSurfaceDestroy",           "SVGA_3D_CMD_SURFACE_DESTROY");
    8914     REG_CNT(&pSVGAState->StatR3Cmd3dSurfaceDma,           "VMSVGA/Cmd/3dSurfaceDma",               "SVGA_3D_CMD_SURFACE_DMA");
    8915     REG_CNT(&pSVGAState->StatR3Cmd3dSurfaceScreen,        "VMSVGA/Cmd/3dSurfaceScreen",            "SVGA_3D_CMD_SURFACE_SCREEN");
    8916     REG_CNT(&pSVGAState->StatR3Cmd3dSurfaceStretchBlt,    "VMSVGA/Cmd/3dSurfaceStretchBlt",        "SVGA_3D_CMD_SURFACE_STRETCHBLT");
    8917     REG_CNT(&pSVGAState->StatR3Cmd3dWaitForQuery,         "VMSVGA/Cmd/3dWaitForQuery",             "SVGA_3D_CMD_WAIT_FOR_QUERY");
    8918     REG_CNT(&pSVGAState->StatR3CmdAnnotationCopy,         "VMSVGA/Cmd/AnnotationCopy",             "SVGA_CMD_ANNOTATION_COPY");
    8919     REG_CNT(&pSVGAState->StatR3CmdAnnotationFill,         "VMSVGA/Cmd/AnnotationFill",             "SVGA_CMD_ANNOTATION_FILL");
    8920     REG_CNT(&pSVGAState->StatR3CmdBlitGmrFbToScreen,      "VMSVGA/Cmd/BlitGmrFbToScreen",          "SVGA_CMD_BLIT_GMRFB_TO_SCREEN");
    8921     REG_CNT(&pSVGAState->StatR3CmdBlitScreentoGmrFb,      "VMSVGA/Cmd/BlitScreentoGmrFb",          "SVGA_CMD_BLIT_SCREEN_TO_GMRFB");
    8922     REG_CNT(&pSVGAState->StatR3CmdDefineAlphaCursor,      "VMSVGA/Cmd/DefineAlphaCursor",          "SVGA_CMD_DEFINE_ALPHA_CURSOR");
    8923     REG_CNT(&pSVGAState->StatR3CmdDefineCursor,           "VMSVGA/Cmd/DefineCursor",               "SVGA_CMD_DEFINE_CURSOR");
    8924     REG_CNT(&pSVGAState->StatR3CmdMoveCursor,             "VMSVGA/Cmd/MoveCursor",                 "SVGA_CMD_MOVE_CURSOR");
    8925     REG_CNT(&pSVGAState->StatR3CmdDisplayCursor,          "VMSVGA/Cmd/DisplayCursor",              "SVGA_CMD_DISPLAY_CURSOR");
    8926     REG_CNT(&pSVGAState->StatR3CmdRectFill,               "VMSVGA/Cmd/RectFill",                   "SVGA_CMD_RECT_FILL");
    8927     REG_CNT(&pSVGAState->StatR3CmdRectCopy,               "VMSVGA/Cmd/RectCopy",                   "SVGA_CMD_RECT_COPY");
    8928     REG_CNT(&pSVGAState->StatR3CmdRectRopCopy,            "VMSVGA/Cmd/RectRopCopy",                "SVGA_CMD_RECT_ROP_COPY");
    8929     REG_CNT(&pSVGAState->StatR3CmdDefineGmr2,             "VMSVGA/Cmd/DefineGmr2",                 "SVGA_CMD_DEFINE_GMR2");
    8930     REG_CNT(&pSVGAState->StatR3CmdDefineGmr2Free,         "VMSVGA/Cmd/DefineGmr2/Free",            "Number of SVGA_CMD_DEFINE_GMR2 commands that only frees.");
    8931     REG_CNT(&pSVGAState->StatR3CmdDefineGmr2Modify,       "VMSVGA/Cmd/DefineGmr2/Modify",          "Number of SVGA_CMD_DEFINE_GMR2 commands that redefines a non-free GMR.");
    8932     REG_CNT(&pSVGAState->StatR3CmdDefineGmrFb,            "VMSVGA/Cmd/DefineGmrFb",                "SVGA_CMD_DEFINE_GMRFB");
    8933     REG_CNT(&pSVGAState->StatR3CmdDefineScreen,           "VMSVGA/Cmd/DefineScreen",               "SVGA_CMD_DEFINE_SCREEN");
    8934     REG_CNT(&pSVGAState->StatR3CmdDestroyScreen,          "VMSVGA/Cmd/DestroyScreen",              "SVGA_CMD_DESTROY_SCREEN");
    8935     REG_CNT(&pSVGAState->StatR3CmdEscape,                 "VMSVGA/Cmd/Escape",                     "SVGA_CMD_ESCAPE");
    8936     REG_CNT(&pSVGAState->StatR3CmdFence,                  "VMSVGA/Cmd/Fence",                      "SVGA_CMD_FENCE");
    8937     REG_CNT(&pSVGAState->StatR3CmdInvalidCmd,             "VMSVGA/Cmd/InvalidCmd",                 "SVGA_CMD_INVALID_CMD");
    8938     REG_CNT(&pSVGAState->StatR3CmdRemapGmr2,              "VMSVGA/Cmd/RemapGmr2",                  "SVGA_CMD_REMAP_GMR2");
    8939     REG_CNT(&pSVGAState->StatR3CmdRemapGmr2Modify,        "VMSVGA/Cmd/RemapGmr2/Modify",           "Number of SVGA_CMD_REMAP_GMR2 commands that modifies rather than complete the definition of a GMR.");
    8940     REG_CNT(&pSVGAState->StatR3CmdUpdate,                 "VMSVGA/Cmd/Update",                     "SVGA_CMD_UPDATE");
    8941     REG_CNT(&pSVGAState->StatR3CmdUpdateVerbose,          "VMSVGA/Cmd/UpdateVerbose",              "SVGA_CMD_UPDATE_VERBOSE");
    8942 
    8943     REG_CNT(&pSVGAState->StatR3RegConfigDoneWr,           "VMSVGA/Reg/ConfigDoneWrite",            "SVGA_REG_CONFIG_DONE writes");
    8944     REG_CNT(&pSVGAState->StatR3RegGmrDescriptorWr,        "VMSVGA/Reg/GmrDescriptorWrite",         "SVGA_REG_GMR_DESCRIPTOR writes");
    8945     REG_CNT(&pSVGAState->StatR3RegGmrDescriptorWrErrors,  "VMSVGA/Reg/GmrDescriptorWrite/Errors",  "Number of erroneous SVGA_REG_GMR_DESCRIPTOR commands.");
    8946     REG_CNT(&pSVGAState->StatR3RegGmrDescriptorWrFree,    "VMSVGA/Reg/GmrDescriptorWrite/Free",    "Number of SVGA_REG_GMR_DESCRIPTOR commands only freeing the GMR.");
    8947     REG_CNT(&pThis->svga.StatRegBitsPerPixelWr,           "VMSVGA/Reg/BitsPerPixelWrite",          "SVGA_REG_BITS_PER_PIXEL writes.");
    8948     REG_CNT(&pThis->svga.StatRegBusyWr,                   "VMSVGA/Reg/BusyWrite",                  "SVGA_REG_BUSY writes.");
    8949     REG_CNT(&pThis->svga.StatRegCursorXWr,                "VMSVGA/Reg/CursorXWrite",               "SVGA_REG_CURSOR_X writes.");
    8950     REG_CNT(&pThis->svga.StatRegCursorYWr,                "VMSVGA/Reg/CursorYWrite",               "SVGA_REG_CURSOR_Y writes.");
    8951     REG_CNT(&pThis->svga.StatRegCursorIdWr,               "VMSVGA/Reg/CursorIdWrite",              "SVGA_REG_CURSOR_ID writes.");
    8952     REG_CNT(&pThis->svga.StatRegCursorOnWr,               "VMSVGA/Reg/CursorOnWrite",              "SVGA_REG_CURSOR_ON writes.");
    8953     REG_CNT(&pThis->svga.StatRegDepthWr,                  "VMSVGA/Reg/DepthWrite",                 "SVGA_REG_DEPTH writes.");
    8954     REG_CNT(&pThis->svga.StatRegDisplayHeightWr,          "VMSVGA/Reg/DisplayHeightWrite",         "SVGA_REG_DISPLAY_HEIGHT writes.");
    8955     REG_CNT(&pThis->svga.StatRegDisplayIdWr,              "VMSVGA/Reg/DisplayIdWrite",             "SVGA_REG_DISPLAY_ID writes.");
    8956     REG_CNT(&pThis->svga.StatRegDisplayIsPrimaryWr,       "VMSVGA/Reg/DisplayIsPrimaryWrite",      "SVGA_REG_DISPLAY_IS_PRIMARY writes.");
    8957     REG_CNT(&pThis->svga.StatRegDisplayPositionXWr,       "VMSVGA/Reg/DisplayPositionXWrite",      "SVGA_REG_DISPLAY_POSITION_X writes.");
    8958     REG_CNT(&pThis->svga.StatRegDisplayPositionYWr,       "VMSVGA/Reg/DisplayPositionYWrite",      "SVGA_REG_DISPLAY_POSITION_Y writes.");
    8959     REG_CNT(&pThis->svga.StatRegDisplayWidthWr,           "VMSVGA/Reg/DisplayWidthWrite",          "SVGA_REG_DISPLAY_WIDTH writes.");
    8960     REG_CNT(&pThis->svga.StatRegEnableWr,                 "VMSVGA/Reg/EnableWrite",                "SVGA_REG_ENABLE writes.");
    8961     REG_CNT(&pThis->svga.StatRegGmrIdWr,                  "VMSVGA/Reg/GmrIdWrite",                 "SVGA_REG_GMR_ID writes.");
    8962     REG_CNT(&pThis->svga.StatRegGuestIdWr,                "VMSVGA/Reg/GuestIdWrite",               "SVGA_REG_GUEST_ID writes.");
    8963     REG_CNT(&pThis->svga.StatRegHeightWr,                 "VMSVGA/Reg/HeightWrite",                "SVGA_REG_HEIGHT writes.");
    8964     REG_CNT(&pThis->svga.StatRegIdWr,                     "VMSVGA/Reg/IdWrite",                    "SVGA_REG_ID writes.");
    8965     REG_CNT(&pThis->svga.StatRegIrqMaskWr,                "VMSVGA/Reg/IrqMaskWrite",               "SVGA_REG_IRQMASK writes.");
    8966     REG_CNT(&pThis->svga.StatRegNumDisplaysWr,            "VMSVGA/Reg/NumDisplaysWrite",           "SVGA_REG_NUM_DISPLAYS writes.");
    8967     REG_CNT(&pThis->svga.StatRegNumGuestDisplaysWr,       "VMSVGA/Reg/NumGuestDisplaysWrite",      "SVGA_REG_NUM_GUEST_DISPLAYS writes.");
    8968     REG_CNT(&pThis->svga.StatRegPaletteWr,                "VMSVGA/Reg/PaletteWrite",               "SVGA_PALETTE_XXXX writes.");
    8969     REG_CNT(&pThis->svga.StatRegPitchLockWr,              "VMSVGA/Reg/PitchLockWrite",             "SVGA_REG_PITCHLOCK writes.");
    8970     REG_CNT(&pThis->svga.StatRegPseudoColorWr,            "VMSVGA/Reg/PseudoColorWrite",           "SVGA_REG_PSEUDOCOLOR writes.");
    8971     REG_CNT(&pThis->svga.StatRegReadOnlyWr,               "VMSVGA/Reg/ReadOnlyWrite",              "Read-only SVGA_REG_XXXX writes.");
    8972     REG_CNT(&pThis->svga.StatRegScratchWr,                "VMSVGA/Reg/ScratchWrite",               "SVGA_REG_SCRATCH_XXXX writes.");
    8973     REG_CNT(&pThis->svga.StatRegSyncWr,                   "VMSVGA/Reg/SyncWrite",                  "SVGA_REG_SYNC writes.");
    8974     REG_CNT(&pThis->svga.StatRegTopWr,                    "VMSVGA/Reg/TopWrite",                   "SVGA_REG_TOP writes.");
    8975     REG_CNT(&pThis->svga.StatRegTracesWr,                 "VMSVGA/Reg/TracesWrite",                "SVGA_REG_TRACES writes.");
    8976     REG_CNT(&pThis->svga.StatRegUnknownWr,                "VMSVGA/Reg/UnknownWrite",               "Writes to unknown register.");
    8977     REG_CNT(&pThis->svga.StatRegWidthWr,                  "VMSVGA/Reg/WidthWrite",                 "SVGA_REG_WIDTH writes.");
    8978     REG_CNT(&pThis->svga.StatRegCommandLowWr,             "VMSVGA/Reg/CommandLowWrite",            "SVGA_REG_COMMAND_LOW writes.");
    8979     REG_CNT(&pThis->svga.StatRegCommandHighWr,            "VMSVGA/Reg/CommandHighWrite",           "SVGA_REG_COMMAND_HIGH writes.");
    8980     REG_CNT(&pThis->svga.StatRegDevCapWr,                 "VMSVGA/Reg/DevCapWrite",                "SVGA_REG_DEV_CAP writes.");
    8981     REG_CNT(&pThis->svga.StatRegCmdPrependLowWr,          "VMSVGA/Reg/CmdPrependLowWrite",         "SVGA_REG_CMD_PREPEND_LOW writes.");
    8982     REG_CNT(&pThis->svga.StatRegCmdPrependHighWr,         "VMSVGA/Reg/CmdPrependHighWrite",        "SVGA_REG_iCMD_PREPEND_HIGH writes.");
    8983 
    8984     REG_CNT(&pThis->svga.StatRegBitsPerPixelRd,           "VMSVGA/Reg/BitsPerPixelRead",           "SVGA_REG_BITS_PER_PIXEL reads.");
    8985     REG_CNT(&pThis->svga.StatRegBlueMaskRd,               "VMSVGA/Reg/BlueMaskRead",               "SVGA_REG_BLUE_MASK reads.");
    8986     REG_CNT(&pThis->svga.StatRegBusyRd,                   "VMSVGA/Reg/BusyRead",                   "SVGA_REG_BUSY reads.");
    8987     REG_CNT(&pThis->svga.StatRegBytesPerLineRd,           "VMSVGA/Reg/BytesPerLineRead",           "SVGA_REG_BYTES_PER_LINE reads.");
    8988     REG_CNT(&pThis->svga.StatRegCapabilitesRd,            "VMSVGA/Reg/CapabilitesRead",            "SVGA_REG_CAPABILITIES reads.");
    8989     REG_CNT(&pThis->svga.StatRegConfigDoneRd,             "VMSVGA/Reg/ConfigDoneRead",             "SVGA_REG_CONFIG_DONE reads.");
    8990     REG_CNT(&pThis->svga.StatRegCursorXRd,                "VMSVGA/Reg/CursorXRead",                "SVGA_REG_CURSOR_X reads.");
    8991     REG_CNT(&pThis->svga.StatRegCursorYRd,                "VMSVGA/Reg/CursorYRead",                "SVGA_REG_CURSOR_Y reads.");
    8992     REG_CNT(&pThis->svga.StatRegCursorIdRd,               "VMSVGA/Reg/CursorIdRead",               "SVGA_REG_CURSOR_ID reads.");
    8993     REG_CNT(&pThis->svga.StatRegCursorOnRd,               "VMSVGA/Reg/CursorOnRead",               "SVGA_REG_CURSOR_ON reads.");
    8994     REG_CNT(&pThis->svga.StatRegDepthRd,                  "VMSVGA/Reg/DepthRead",                  "SVGA_REG_DEPTH reads.");
    8995     REG_CNT(&pThis->svga.StatRegDisplayHeightRd,          "VMSVGA/Reg/DisplayHeightRead",          "SVGA_REG_DISPLAY_HEIGHT reads.");
    8996     REG_CNT(&pThis->svga.StatRegDisplayIdRd,              "VMSVGA/Reg/DisplayIdRead",              "SVGA_REG_DISPLAY_ID reads.");
    8997     REG_CNT(&pThis->svga.StatRegDisplayIsPrimaryRd,       "VMSVGA/Reg/DisplayIsPrimaryRead",       "SVGA_REG_DISPLAY_IS_PRIMARY reads.");
    8998     REG_CNT(&pThis->svga.StatRegDisplayPositionXRd,       "VMSVGA/Reg/DisplayPositionXRead",       "SVGA_REG_DISPLAY_POSITION_X reads.");
    8999     REG_CNT(&pThis->svga.StatRegDisplayPositionYRd,       "VMSVGA/Reg/DisplayPositionYRead",       "SVGA_REG_DISPLAY_POSITION_Y reads.");
    9000     REG_CNT(&pThis->svga.StatRegDisplayWidthRd,           "VMSVGA/Reg/DisplayWidthRead",           "SVGA_REG_DISPLAY_WIDTH reads.");
    9001     REG_CNT(&pThis->svga.StatRegEnableRd,                 "VMSVGA/Reg/EnableRead",                 "SVGA_REG_ENABLE reads.");
    9002     REG_CNT(&pThis->svga.StatRegFbOffsetRd,               "VMSVGA/Reg/FbOffsetRead",               "SVGA_REG_FB_OFFSET reads.");
    9003     REG_CNT(&pThis->svga.StatRegFbSizeRd,                 "VMSVGA/Reg/FbSizeRead",                 "SVGA_REG_FB_SIZE reads.");
    9004     REG_CNT(&pThis->svga.StatRegFbStartRd,                "VMSVGA/Reg/FbStartRead",                "SVGA_REG_FB_START reads.");
    9005     REG_CNT(&pThis->svga.StatRegGmrIdRd,                  "VMSVGA/Reg/GmrIdRead",                  "SVGA_REG_GMR_ID reads.");
    9006     REG_CNT(&pThis->svga.StatRegGmrMaxDescriptorLengthRd, "VMSVGA/Reg/GmrMaxDescriptorLengthRead", "SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH reads.");
    9007     REG_CNT(&pThis->svga.StatRegGmrMaxIdsRd,              "VMSVGA/Reg/GmrMaxIdsRead",              "SVGA_REG_GMR_MAX_IDS reads.");
    9008     REG_CNT(&pThis->svga.StatRegGmrsMaxPagesRd,           "VMSVGA/Reg/GmrsMaxPagesRead",           "SVGA_REG_GMRS_MAX_PAGES reads.");
    9009     REG_CNT(&pThis->svga.StatRegGreenMaskRd,              "VMSVGA/Reg/GreenMaskRead",              "SVGA_REG_GREEN_MASK reads.");
    9010     REG_CNT(&pThis->svga.StatRegGuestIdRd,                "VMSVGA/Reg/GuestIdRead",                "SVGA_REG_GUEST_ID reads.");
    9011     REG_CNT(&pThis->svga.StatRegHeightRd,                 "VMSVGA/Reg/HeightRead",                 "SVGA_REG_HEIGHT reads.");
    9012     REG_CNT(&pThis->svga.StatRegHostBitsPerPixelRd,       "VMSVGA/Reg/HostBitsPerPixelRead",       "SVGA_REG_HOST_BITS_PER_PIXEL reads.");
    9013     REG_CNT(&pThis->svga.StatRegIdRd,                     "VMSVGA/Reg/IdRead",                     "SVGA_REG_ID reads.");
    9014     REG_CNT(&pThis->svga.StatRegIrqMaskRd,                "VMSVGA/Reg/IrqMaskRead",                "SVGA_REG_IRQ_MASK reads.");
    9015     REG_CNT(&pThis->svga.StatRegMaxHeightRd,              "VMSVGA/Reg/MaxHeightRead",              "SVGA_REG_MAX_HEIGHT reads.");
    9016     REG_CNT(&pThis->svga.StatRegMaxWidthRd,               "VMSVGA/Reg/MaxWidthRead",               "SVGA_REG_MAX_WIDTH reads.");
    9017     REG_CNT(&pThis->svga.StatRegMemorySizeRd,             "VMSVGA/Reg/MemorySizeRead",             "SVGA_REG_MEMORY_SIZE reads.");
    9018     REG_CNT(&pThis->svga.StatRegMemRegsRd,                "VMSVGA/Reg/MemRegsRead",                "SVGA_REG_MEM_REGS reads.");
    9019     REG_CNT(&pThis->svga.StatRegMemSizeRd,                "VMSVGA/Reg/MemSizeRead",                "SVGA_REG_MEM_SIZE reads.");
    9020     REG_CNT(&pThis->svga.StatRegMemStartRd,               "VMSVGA/Reg/MemStartRead",               "SVGA_REG_MEM_START reads.");
    9021     REG_CNT(&pThis->svga.StatRegNumDisplaysRd,            "VMSVGA/Reg/NumDisplaysRead",            "SVGA_REG_NUM_DISPLAYS reads.");
    9022     REG_CNT(&pThis->svga.StatRegNumGuestDisplaysRd,       "VMSVGA/Reg/NumGuestDisplaysRead",       "SVGA_REG_NUM_GUEST_DISPLAYS reads.");
    9023     REG_CNT(&pThis->svga.StatRegPaletteRd,                "VMSVGA/Reg/PaletteRead",                "SVGA_REG_PLAETTE_XXXX reads.");
    9024     REG_CNT(&pThis->svga.StatRegPitchLockRd,              "VMSVGA/Reg/PitchLockRead",              "SVGA_REG_PITCHLOCK reads.");
    9025     REG_CNT(&pThis->svga.StatRegPsuedoColorRd,            "VMSVGA/Reg/PsuedoColorRead",            "SVGA_REG_PSEUDOCOLOR reads.");
    9026     REG_CNT(&pThis->svga.StatRegRedMaskRd,                "VMSVGA/Reg/RedMaskRead",                "SVGA_REG_RED_MASK reads.");
    9027     REG_CNT(&pThis->svga.StatRegScratchRd,                "VMSVGA/Reg/ScratchRead",                "SVGA_REG_SCRATCH reads.");
    9028     REG_CNT(&pThis->svga.StatRegScratchSizeRd,            "VMSVGA/Reg/ScratchSizeRead",            "SVGA_REG_SCRATCH_SIZE reads.");
    9029     REG_CNT(&pThis->svga.StatRegSyncRd,                   "VMSVGA/Reg/SyncRead",                   "SVGA_REG_SYNC reads.");
    9030     REG_CNT(&pThis->svga.StatRegTopRd,                    "VMSVGA/Reg/TopRead",                    "SVGA_REG_TOP reads.");
    9031     REG_CNT(&pThis->svga.StatRegTracesRd,                 "VMSVGA/Reg/TracesRead",                 "SVGA_REG_TRACES reads.");
    9032     REG_CNT(&pThis->svga.StatRegUnknownRd,                "VMSVGA/Reg/UnknownRead",                "SVGA_REG_UNKNOWN reads.");
    9033     REG_CNT(&pThis->svga.StatRegVramSizeRd,               "VMSVGA/Reg/VramSizeRead",               "SVGA_REG_VRAM_SIZE reads.");
    9034     REG_CNT(&pThis->svga.StatRegWidthRd,                  "VMSVGA/Reg/WidthRead",                  "SVGA_REG_WIDTH reads.");
    9035     REG_CNT(&pThis->svga.StatRegWriteOnlyRd,              "VMSVGA/Reg/WriteOnlyRead",              "Write-only SVGA_REG_XXXX reads.");
    9036     REG_CNT(&pThis->svga.StatRegCommandLowRd,             "VMSVGA/Reg/CommandLowRead",             "SVGA_REG_COMMAND_LOW reads.");
    9037     REG_CNT(&pThis->svga.StatRegCommandHighRd,            "VMSVGA/Reg/CommandHighRead",            "SVGA_REG_COMMAND_HIGH reads.");
    9038     REG_CNT(&pThis->svga.StatRegMaxPrimBBMemRd,           "VMSVGA/Reg/MaxPrimBBMemRead",           "SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM reads.");
    9039     REG_CNT(&pThis->svga.StatRegGBMemSizeRd,              "VMSVGA/Reg/GBMemSizeRead",              "SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB reads.");
    9040     REG_CNT(&pThis->svga.StatRegDevCapRd,                 "VMSVGA/Reg/DevCapRead",                 "SVGA_REG_DEV_CAP reads.");
    9041     REG_CNT(&pThis->svga.StatRegCmdPrependLowRd,          "VMSVGA/Reg/CmdPrependLowRead",          "SVGA_REG_CMD_PREPEND_LOW reads.");
    9042     REG_CNT(&pThis->svga.StatRegCmdPrependHighRd,         "VMSVGA/Reg/CmdPrependHighRead",         "SVGA_REG_iCMD_PREPEND_HIGH reads.");
    9043     REG_CNT(&pThis->svga.StatRegScrnTgtMaxWidthRd,        "VMSVGA/Reg/ScrnTgtMaxWidthRead",        "SVGA_REG_SCREENTARGET_MAX_WIDTH reads.");
    9044     REG_CNT(&pThis->svga.StatRegScrnTgtMaxHeightRd,       "VMSVGA/Reg/ScrnTgtMaxHeightRead",       "SVGA_REG_SCREENTARGET_MAX_HEIGHT reads.");
    9045     REG_CNT(&pThis->svga.StatRegMobMaxSizeRd,             "VMSVGA/Reg/MobMaxSizeRead",             "SVGA_REG_MOB_MAX_SIZE reads.");
    9046 
    9047     REG_PRF(&pSVGAState->StatBusyDelayEmts,               "VMSVGA/EmtDelayOnBusyFifo",             "Time we've delayed EMTs because of busy FIFO thread.");
    9048     REG_CNT(&pSVGAState->StatFifoCommands,                "VMSVGA/FifoCommands",                   "FIFO command counter.");
    9049     REG_CNT(&pSVGAState->StatFifoErrors,                  "VMSVGA/FifoErrors",                     "FIFO error counter.");
    9050     REG_CNT(&pSVGAState->StatFifoUnkCmds,                 "VMSVGA/FifoUnknownCommands",            "FIFO unknown command counter.");
    9051     REG_CNT(&pSVGAState->StatFifoTodoTimeout,             "VMSVGA/FifoTodoTimeout",                "Number of times we discovered pending work after a wait timeout.");
    9052     REG_CNT(&pSVGAState->StatFifoTodoWoken,               "VMSVGA/FifoTodoWoken",                  "Number of times we discovered pending work after being woken up.");
    9053     REG_PRF(&pSVGAState->StatFifoStalls,                  "VMSVGA/FifoStalls",                     "Profiling of FIFO stalls (waiting for guest to finish copying data).");
    9054     REG_PRF(&pSVGAState->StatFifoExtendedSleep,           "VMSVGA/FifoExtendedSleep",              "Profiling FIFO sleeps relying on the refresh timer and/or access handler.");
    9055 # if defined(VMSVGA_USE_FIFO_ACCESS_HANDLER) || defined(DEBUG_FIFO_ACCESS)
    9056     REG_CNT(&pSVGAState->StatFifoAccessHandler,           "VMSVGA/FifoAccessHandler",              "Number of times the FIFO access handler triggered.");
    9057 # endif
    9058     REG_CNT(&pSVGAState->StatFifoCursorFetchAgain,        "VMSVGA/FifoCursorFetchAgain",           "Times the cursor update counter changed while reading.");
    9059     REG_CNT(&pSVGAState->StatFifoCursorNoChange,          "VMSVGA/FifoCursorNoChange",             "No cursor position change event though the update counter was modified.");
    9060     REG_CNT(&pSVGAState->StatFifoCursorPosition,          "VMSVGA/FifoCursorPosition",             "Cursor position and visibility changes.");
    9061     REG_CNT(&pSVGAState->StatFifoCursorVisiblity,         "VMSVGA/FifoCursorVisiblity",            "Cursor visibility changes.");
    9062     REG_CNT(&pSVGAState->StatFifoWatchdogWakeUps,         "VMSVGA/FifoWatchdogWakeUps",            "Number of times the FIFO refresh poller/watchdog woke up the FIFO thread.");
    9063 
    9064 # undef REG_CNT
    9065 # undef REG_PRF
    9066 
    9067     /*
    9068      * Info handlers.
    9069      */
    9070     PDMDevHlpDBGFInfoRegister(pDevIns, "vmsvga", "Basic VMSVGA device state details", vmsvgaR3Info);
    9071 # ifdef VBOX_WITH_VMSVGA3D
    9072     PDMDevHlpDBGFInfoRegister(pDevIns, "vmsvga3dctx", "VMSVGA 3d context details. Accepts 'terse'.", vmsvgaR3Info3dContext);
    9073     PDMDevHlpDBGFInfoRegister(pDevIns, "vmsvga3dsfc",
    9074                               "VMSVGA 3d surface details. "
    9075                               "Accepts 'terse', 'invy', and one of 'tiny', 'medium', 'normal', 'big', 'huge', or 'gigantic'.",
    9076                               vmsvgaR3Info3dSurface);
    9077     PDMDevHlpDBGFInfoRegister(pDevIns, "vmsvga3dsurf",
    9078                               "VMSVGA 3d surface details and bitmap: "
    9079                               "sid[>dir]",
    9080                               vmsvgaR3Info3dSurfaceBmp);
    9081 # endif
    9082 
    9083     return VINF_SUCCESS;
    9084 }
    9085 
    9086 /**
    9087  * Power On notification.
    9088  *
    9089  * @returns VBox status code.
    9090  * @param   pDevIns     The device instance data.
    9091  *
    9092  * @remarks Caller enters the device critical section.
    9093  */
    9094 DECLCALLBACK(void) vmsvgaR3PowerOn(PPDMDEVINS pDevIns)
    9095 {
    9096 # ifdef VBOX_WITH_VMSVGA3D
    9097     PVGASTATE   pThis   = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
    9098     PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
    9099     if (pThis->svga.f3DEnabled)
    9100     {
    9101         int rc = vmsvga3dPowerOn(pDevIns, pThis, pThisCC);
    9102         if (RT_SUCCESS(rc))
    9103         {
    9104             /* Initialize FIFO 3D capabilities. */
    9105             vmsvgaR3InitFifo3DCaps(pThis, pThisCC);
    9106         }
    9107     }
    9108 # else  /* !VBOX_WITH_VMSVGA3D */
    9109     RT_NOREF(pDevIns);
    9110 # endif /* !VBOX_WITH_VMSVGA3D */
    9111 }
    9112 
    9113 /**
    9114  * Power Off notification.
    9115  *
    9116  * @param   pDevIns     The device instance data.
    9117  *
    9118  * @remarks Caller enters the device critical section.
    9119  */
    9120 DECLCALLBACK(void) vmsvgaR3PowerOff(PPDMDEVINS pDevIns)
    9121 {
    9122     PVGASTATE   pThis   = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
    9123     PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
    9124 
    9125     /*
    9126      * Notify the FIFO thread.
    9127      */
    9128     if (pThisCC->svga.pFIFOIOThread)
    9129     {
    9130         int rc = vmsvgaR3RunExtCmdOnFifoThread(pDevIns, pThis, pThisCC,  VMSVGA_FIFO_EXTCMD_POWEROFF,
    9131                                                NULL /*pvParam*/, 30000 /*ms*/);
    9132         AssertLogRelRC(rc);
    9133     }
    9134 }
    9135 
    9136 #endif /* IN_RING3 */
     235                        uint32_t cbWidth, uint32_t cHeight);
     236void vmsvgaR3GmrFree(PVGASTATECC pThisCC, uint32_t idGMR);
     237
     238void vmsvgaR3CmdUpdate(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdUpdate const *pCmd);
     239void vmsvgaR3CmdUpdateVerbose(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdUpdateVerbose const *pCmd);
     240void vmsvgaR3CmdRectFill(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdRectFill const *pCmd);
     241void vmsvgaR3CmdRectCopy(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdRectCopy const *pCmd);
     242void vmsvgaR3CmdRectRopCopy(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdRectRopCopy const *pCmd);
     243void vmsvgaR3CmdDisplayCursor(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDisplayCursor const *pCmd);
     244void vmsvgaR3CmdMoveCursor(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdMoveCursor const *pCmd);
     245void vmsvgaR3CmdDefineCursor(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineCursor const *pCmd);
     246void vmsvgaR3CmdDefineAlphaCursor(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineAlphaCursor const *pCmd);
     247void vmsvgaR3CmdEscape(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdEscape const *pCmd);
     248void vmsvgaR3CmdDefineScreen(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineScreen const *pCmd);
     249void vmsvgaR3CmdDestroyScreen(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDestroyScreen const *pCmd);
     250void vmsvgaR3CmdDefineGMRFB(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineGMRFB const *pCmd);
     251void vmsvgaR3CmdBlitGMRFBToScreen(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdBlitGMRFBToScreen const *pCmd);
     252void vmsvgaR3CmdBlitScreenToGMRFB(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdBlitScreenToGMRFB const *pCmd);
     253void vmsvgaR3CmdAnnotationFill(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdAnnotationFill const *pCmd);
     254void vmsvgaR3CmdAnnotationCopy(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdAnnotationCopy const *pCmd);
     255
     256#ifdef VBOX_WITH_VMSVGA3D
     257void vmsvgaR3CmdDefineGMR2(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineGMR2 const *pCmd);
     258void vmsvgaR3CmdRemapGMR2(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdRemapGMR2 const *pCmd);
     259int vmsvgaR3Process3dCmd(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifo3dCmdId enmCmdId, uint32_t cbCmd, void const *pvCmd);
     260#endif
     261
     262#if defined(LOG_ENABLED) || defined(VBOX_STRICT)
     263const char *vmsvgaR3FifoCmdToString(uint32_t u32Cmd);
     264#endif
     265
     266
     267#endif /* !VBOX_INCLUDED_SRC_Graphics_DevVGA_SVGA_internal_h */
  • trunk/src/VBox/Devices/Graphics/DevVGA-SVGA.cpp

    r86252 r86265  
    162162
    163163#include "DevVGA-SVGA.h"
     164#ifdef IN_RING3
     165#include "DevVGA-SVGA-internal.h"
     166#endif
    164167#ifdef VBOX_WITH_VMSVGA3D
    165168# include "DevVGA-SVGA3d.h"
     
    192195*   Structures and Typedefs                                                                                                      *
    193196*********************************************************************************************************************************/
    194 /**
    195  * 64-bit GMR descriptor.
    196  */
    197 typedef struct
    198 {
    199    RTGCPHYS GCPhys;
    200    uint64_t numPages;
    201 } VMSVGAGMRDESCRIPTOR, *PVMSVGAGMRDESCRIPTOR;
    202 
    203 /**
    204  * GMR slot
    205  */
    206 typedef struct
    207 {
    208     uint32_t                    cMaxPages;
    209     uint32_t                    cbTotal;
    210     uint32_t                    numDescriptors;
    211     PVMSVGAGMRDESCRIPTOR        paDesc;
    212 } GMR, *PGMR;
    213 
    214 #ifdef IN_RING3
    215 typedef struct VMSVGACMDBUF *PVMSVGACMDBUF;
    216 typedef struct VMSVGACMDBUFCTX *PVMSVGACMDBUFCTX;
    217 
    218 /* Command buffer. */
    219 typedef struct VMSVGACMDBUF
    220 {
    221     RTLISTNODE nodeBuffer;
    222     /* Context of the buffer. */
    223     PVMSVGACMDBUFCTX pCmdBufCtx;
    224     /* PA of the buffer. */
    225     RTGCPHYS GCPhysCB;
    226     /* A copy of the buffer header. */
    227     SVGACBHeader hdr;
    228     /* A copy of the commands. Size of the memory buffer is hdr.length */
    229     void *pvCommands;
    230 } VMSVGACMDBUF;
    231 
    232 /* Command buffer context. */
    233 typedef struct VMSVGACMDBUFCTX
    234 {
    235     /* Buffers submitted to processing for the FIFO thread. */
    236     RTLISTANCHOR listSubmitted;
    237     /* How many buffers in the queue. */
    238     uint32_t cSubmitted;
    239 } VMSVGACMDBUFCTX;
    240 
    241 /**
    242  * Internal SVGA ring-3 only state.
    243  */
    244 typedef struct VMSVGAR3STATE
    245 {
    246     GMR                    *paGMR; // [VMSVGAState::cGMR]
    247     struct
    248     {
    249         SVGAGuestPtr RT_UNTRUSTED_GUEST         ptr;
    250         uint32_t RT_UNTRUSTED_GUEST             bytesPerLine;
    251         SVGAGMRImageFormat RT_UNTRUSTED_GUEST   format;
    252     } GMRFB;
    253     struct
    254     {
    255         bool                fActive;
    256         uint32_t            xHotspot;
    257         uint32_t            yHotspot;
    258         uint32_t            width;
    259         uint32_t            height;
    260         uint32_t            cbData;
    261         void               *pData;
    262     } Cursor;
    263     SVGAColorBGRX           colorAnnotation;
    264 
    265 # ifdef VMSVGA_USE_EMT_HALT_CODE
    266     /** Number of EMTs in BusyDelayedEmts (quicker than scanning the set). */
    267     uint32_t volatile       cBusyDelayedEmts;
    268     /** Set of EMTs that are   */
    269     VMCPUSET                BusyDelayedEmts;
    270 # else
    271     /** Number of EMTs waiting on hBusyDelayedEmts. */
    272     uint32_t volatile       cBusyDelayedEmts;
    273     /** Semaphore that EMTs wait on when reading SVGA_REG_BUSY and the FIFO is
    274      *  busy (ugly).  */
    275     RTSEMEVENTMULTI         hBusyDelayedEmts;
    276 # endif
    277 
    278     /** Information about screens. */
    279     VMSVGASCREENOBJECT      aScreens[64];
    280 
    281     /** Command buffer contexts. */
    282     PVMSVGACMDBUFCTX        apCmdBufCtxs[SVGA_CB_CONTEXT_MAX];
    283     /** The special Device Context for synchronous commands. */
    284     VMSVGACMDBUFCTX         CmdBufCtxDC;
    285     /** Flag which indicates that there are buffers to be processed. */
    286     uint32_t volatile       fCmdBuf;
    287     /** Critical section for accessing the command buffer data. */
    288     RTCRITSECT              CritSectCmdBuf;
    289 
    290     /** Tracks how much time we waste reading SVGA_REG_BUSY with a busy FIFO. */
    291     STAMPROFILE             StatBusyDelayEmts;
    292 
    293     STAMPROFILE             StatR3Cmd3dPresentProf;
    294     STAMPROFILE             StatR3Cmd3dDrawPrimitivesProf;
    295     STAMPROFILE             StatR3Cmd3dSurfaceDmaProf;
    296     STAMPROFILE             StatR3Cmd3dBlitSurfaceToScreenProf;
    297     STAMCOUNTER             StatR3CmdDefineGmr2;
    298     STAMCOUNTER             StatR3CmdDefineGmr2Free;
    299     STAMCOUNTER             StatR3CmdDefineGmr2Modify;
    300     STAMCOUNTER             StatR3CmdRemapGmr2;
    301     STAMCOUNTER             StatR3CmdRemapGmr2Modify;
    302     STAMCOUNTER             StatR3CmdInvalidCmd;
    303     STAMCOUNTER             StatR3CmdFence;
    304     STAMCOUNTER             StatR3CmdUpdate;
    305     STAMCOUNTER             StatR3CmdUpdateVerbose;
    306     STAMCOUNTER             StatR3CmdDefineCursor;
    307     STAMCOUNTER             StatR3CmdDefineAlphaCursor;
    308     STAMCOUNTER             StatR3CmdMoveCursor;
    309     STAMCOUNTER             StatR3CmdDisplayCursor;
    310     STAMCOUNTER             StatR3CmdRectFill;
    311     STAMCOUNTER             StatR3CmdRectCopy;
    312     STAMCOUNTER             StatR3CmdRectRopCopy;
    313     STAMCOUNTER             StatR3CmdEscape;
    314     STAMCOUNTER             StatR3CmdDefineScreen;
    315     STAMCOUNTER             StatR3CmdDestroyScreen;
    316     STAMCOUNTER             StatR3CmdDefineGmrFb;
    317     STAMCOUNTER             StatR3CmdBlitGmrFbToScreen;
    318     STAMCOUNTER             StatR3CmdBlitScreentoGmrFb;
    319     STAMCOUNTER             StatR3CmdAnnotationFill;
    320     STAMCOUNTER             StatR3CmdAnnotationCopy;
    321     STAMCOUNTER             StatR3Cmd3dSurfaceDefine;
    322     STAMCOUNTER             StatR3Cmd3dSurfaceDefineV2;
    323     STAMCOUNTER             StatR3Cmd3dSurfaceDestroy;
    324     STAMCOUNTER             StatR3Cmd3dSurfaceCopy;
    325     STAMCOUNTER             StatR3Cmd3dSurfaceStretchBlt;
    326     STAMCOUNTER             StatR3Cmd3dSurfaceDma;
    327     STAMCOUNTER             StatR3Cmd3dSurfaceScreen;
    328     STAMCOUNTER             StatR3Cmd3dContextDefine;
    329     STAMCOUNTER             StatR3Cmd3dContextDestroy;
    330     STAMCOUNTER             StatR3Cmd3dSetTransform;
    331     STAMCOUNTER             StatR3Cmd3dSetZRange;
    332     STAMCOUNTER             StatR3Cmd3dSetRenderState;
    333     STAMCOUNTER             StatR3Cmd3dSetRenderTarget;
    334     STAMCOUNTER             StatR3Cmd3dSetTextureState;
    335     STAMCOUNTER             StatR3Cmd3dSetMaterial;
    336     STAMCOUNTER             StatR3Cmd3dSetLightData;
    337     STAMCOUNTER             StatR3Cmd3dSetLightEnable;
    338     STAMCOUNTER             StatR3Cmd3dSetViewPort;
    339     STAMCOUNTER             StatR3Cmd3dSetClipPlane;
    340     STAMCOUNTER             StatR3Cmd3dClear;
    341     STAMCOUNTER             StatR3Cmd3dPresent;
    342     STAMCOUNTER             StatR3Cmd3dPresentReadBack;
    343     STAMCOUNTER             StatR3Cmd3dShaderDefine;
    344     STAMCOUNTER             StatR3Cmd3dShaderDestroy;
    345     STAMCOUNTER             StatR3Cmd3dSetShader;
    346     STAMCOUNTER             StatR3Cmd3dSetShaderConst;
    347     STAMCOUNTER             StatR3Cmd3dDrawPrimitives;
    348     STAMCOUNTER             StatR3Cmd3dSetScissorRect;
    349     STAMCOUNTER             StatR3Cmd3dBeginQuery;
    350     STAMCOUNTER             StatR3Cmd3dEndQuery;
    351     STAMCOUNTER             StatR3Cmd3dWaitForQuery;
    352     STAMCOUNTER             StatR3Cmd3dGenerateMipmaps;
    353     STAMCOUNTER             StatR3Cmd3dActivateSurface;
    354     STAMCOUNTER             StatR3Cmd3dDeactivateSurface;
    355 
    356     STAMCOUNTER             StatR3RegConfigDoneWr;
    357     STAMCOUNTER             StatR3RegGmrDescriptorWr;
    358     STAMCOUNTER             StatR3RegGmrDescriptorWrErrors;
    359     STAMCOUNTER             StatR3RegGmrDescriptorWrFree;
    360 
    361     STAMCOUNTER             StatFifoCommands;
    362     STAMCOUNTER             StatFifoErrors;
    363     STAMCOUNTER             StatFifoUnkCmds;
    364     STAMCOUNTER             StatFifoTodoTimeout;
    365     STAMCOUNTER             StatFifoTodoWoken;
    366     STAMPROFILE             StatFifoStalls;
    367     STAMPROFILE             StatFifoExtendedSleep;
    368 # ifdef VMSVGA_USE_FIFO_ACCESS_HANDLER
    369     STAMCOUNTER             StatFifoAccessHandler;
    370 # endif
    371     STAMCOUNTER             StatFifoCursorFetchAgain;
    372     STAMCOUNTER             StatFifoCursorNoChange;
    373     STAMCOUNTER             StatFifoCursorPosition;
    374     STAMCOUNTER             StatFifoCursorVisiblity;
    375     STAMCOUNTER             StatFifoWatchdogWakeUps;
    376 } VMSVGAR3STATE, *PVMSVGAR3STATE;
    377 #endif /* IN_RING3 */
    378197
    379198
     
    602421static int vmsvgaR3SaveExecFifo(PCPDMDEVHLPR3 pHlp, PVGASTATECC pThisCC, PSSMHANDLE pSSM);
    603422static void vmsvgaR3CmdBufSubmit(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, RTGCPHYS GCPhysCB, SVGACBContext CBCtx);
    604 # ifdef VBOX_WITH_VMSVGA3D
    605 static void vmsvgaR3GmrFree(PVGASTATECC pThisCC, uint32_t idGMR);
    606 # endif /* VBOX_WITH_VMSVGA3D */
    607423#endif /* IN_RING3 */
    608424
    609425
    610 
    611 #ifdef IN_RING3
    612 VMSVGASCREENOBJECT *vmsvgaR3GetScreenObject(PVGASTATECC pThisCC, uint32_t idScreen)
    613 {
    614     PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
    615     if (   idScreen < (uint32_t)RT_ELEMENTS(pSVGAState->aScreens)
    616         && pSVGAState
    617         && pSVGAState->aScreens[idScreen].fDefined)
    618     {
    619         return &pSVGAState->aScreens[idScreen];
    620     }
    621     return NULL;
    622 }
    623 
    624 void vmsvgaR3ResetScreens(PVGASTATE pThis, PVGASTATECC pThisCC)
    625 {
    626 # ifdef VBOX_WITH_VMSVGA3D
    627     if (pThis->svga.f3DEnabled)
    628     {
    629         for (uint32_t idScreen = 0; idScreen < (uint32_t)RT_ELEMENTS(pThisCC->svga.pSvgaR3State->aScreens); ++idScreen)
    630         {
    631             VMSVGASCREENOBJECT *pScreen = vmsvgaR3GetScreenObject(pThisCC, idScreen);
    632             if (pScreen)
    633                 vmsvga3dDestroyScreen(pThisCC, pScreen);
    634         }
    635     }
    636 # else
    637     RT_NOREF(pThis, pThisCC);
    638 # endif
    639 }
    640 #endif /* IN_RING3 */
    641 
    642 #define SVGA_CASE_ID2STR(idx) case idx: return #idx
    643 
    644426#if defined(LOG_ENABLED)
     427# define SVGA_CASE_ID2STR(idx) case idx: return #idx
    645428/**
    646429 * Index register string name lookup
     
    728511    }
    729512}
     513# undef SVGA_CASE_ID2STR
    730514#endif /* LOG_ENABLED */
    731515
    732 #if defined(IN_RING3) && (defined(LOG_ENABLED) || defined(VBOX_STRICT))
    733 /**
    734  * FIFO command name lookup
    735  *
    736  * @returns FIFO command string or "UNKNOWN"
    737  * @param   u32Cmd      FIFO command
    738  */
    739 static const char *vmsvgaR3FifoCmdToString(uint32_t u32Cmd)
    740 {
    741     switch (u32Cmd)
    742     {
    743         SVGA_CASE_ID2STR(SVGA_CMD_INVALID_CMD);
    744         SVGA_CASE_ID2STR(SVGA_CMD_UPDATE);
    745         SVGA_CASE_ID2STR(SVGA_CMD_RECT_FILL);
    746         SVGA_CASE_ID2STR(SVGA_CMD_RECT_COPY);
    747         SVGA_CASE_ID2STR(SVGA_CMD_RECT_ROP_COPY);
    748         SVGA_CASE_ID2STR(SVGA_CMD_DEFINE_CURSOR);
    749         SVGA_CASE_ID2STR(SVGA_CMD_DISPLAY_CURSOR);
    750         SVGA_CASE_ID2STR(SVGA_CMD_MOVE_CURSOR);
    751         SVGA_CASE_ID2STR(SVGA_CMD_DEFINE_ALPHA_CURSOR);
    752         SVGA_CASE_ID2STR(SVGA_CMD_UPDATE_VERBOSE);
    753         SVGA_CASE_ID2STR(SVGA_CMD_FRONT_ROP_FILL);
    754         SVGA_CASE_ID2STR(SVGA_CMD_FENCE);
    755         SVGA_CASE_ID2STR(SVGA_CMD_ESCAPE);
    756         SVGA_CASE_ID2STR(SVGA_CMD_DEFINE_SCREEN);
    757         SVGA_CASE_ID2STR(SVGA_CMD_DESTROY_SCREEN);
    758         SVGA_CASE_ID2STR(SVGA_CMD_DEFINE_GMRFB);
    759         SVGA_CASE_ID2STR(SVGA_CMD_BLIT_GMRFB_TO_SCREEN);
    760         SVGA_CASE_ID2STR(SVGA_CMD_BLIT_SCREEN_TO_GMRFB);
    761         SVGA_CASE_ID2STR(SVGA_CMD_ANNOTATION_FILL);
    762         SVGA_CASE_ID2STR(SVGA_CMD_ANNOTATION_COPY);
    763         SVGA_CASE_ID2STR(SVGA_CMD_DEFINE_GMR2);
    764         SVGA_CASE_ID2STR(SVGA_CMD_REMAP_GMR2);
    765         SVGA_CASE_ID2STR(SVGA_CMD_DEAD);
    766         SVGA_CASE_ID2STR(SVGA_CMD_DEAD_2);
    767         SVGA_CASE_ID2STR(SVGA_CMD_NOP);
    768         SVGA_CASE_ID2STR(SVGA_CMD_NOP_ERROR);
    769         SVGA_CASE_ID2STR(SVGA_CMD_MAX);
    770         SVGA_CASE_ID2STR(SVGA_3D_CMD_SURFACE_DEFINE);
    771         SVGA_CASE_ID2STR(SVGA_3D_CMD_SURFACE_DESTROY);
    772         SVGA_CASE_ID2STR(SVGA_3D_CMD_SURFACE_COPY);
    773         SVGA_CASE_ID2STR(SVGA_3D_CMD_SURFACE_STRETCHBLT);
    774         SVGA_CASE_ID2STR(SVGA_3D_CMD_SURFACE_DMA);
    775         SVGA_CASE_ID2STR(SVGA_3D_CMD_CONTEXT_DEFINE);
    776         SVGA_CASE_ID2STR(SVGA_3D_CMD_CONTEXT_DESTROY);
    777         SVGA_CASE_ID2STR(SVGA_3D_CMD_SETTRANSFORM);
    778         SVGA_CASE_ID2STR(SVGA_3D_CMD_SETZRANGE);
    779         SVGA_CASE_ID2STR(SVGA_3D_CMD_SETRENDERSTATE);
    780         SVGA_CASE_ID2STR(SVGA_3D_CMD_SETRENDERTARGET);
    781         SVGA_CASE_ID2STR(SVGA_3D_CMD_SETTEXTURESTATE);
    782         SVGA_CASE_ID2STR(SVGA_3D_CMD_SETMATERIAL);
    783         SVGA_CASE_ID2STR(SVGA_3D_CMD_SETLIGHTDATA);
    784         SVGA_CASE_ID2STR(SVGA_3D_CMD_SETLIGHTENABLED);
    785         SVGA_CASE_ID2STR(SVGA_3D_CMD_SETVIEWPORT);
    786         SVGA_CASE_ID2STR(SVGA_3D_CMD_SETCLIPPLANE);
    787         SVGA_CASE_ID2STR(SVGA_3D_CMD_CLEAR);
    788         SVGA_CASE_ID2STR(SVGA_3D_CMD_PRESENT);
    789         SVGA_CASE_ID2STR(SVGA_3D_CMD_SHADER_DEFINE);
    790         SVGA_CASE_ID2STR(SVGA_3D_CMD_SHADER_DESTROY);
    791         SVGA_CASE_ID2STR(SVGA_3D_CMD_SET_SHADER);
    792         SVGA_CASE_ID2STR(SVGA_3D_CMD_SET_SHADER_CONST);
    793         SVGA_CASE_ID2STR(SVGA_3D_CMD_DRAW_PRIMITIVES);
    794         SVGA_CASE_ID2STR(SVGA_3D_CMD_SETSCISSORRECT);
    795         SVGA_CASE_ID2STR(SVGA_3D_CMD_BEGIN_QUERY);
    796         SVGA_CASE_ID2STR(SVGA_3D_CMD_END_QUERY);
    797         SVGA_CASE_ID2STR(SVGA_3D_CMD_WAIT_FOR_QUERY);
    798         SVGA_CASE_ID2STR(SVGA_3D_CMD_PRESENT_READBACK);
    799         SVGA_CASE_ID2STR(SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN);
    800         SVGA_CASE_ID2STR(SVGA_3D_CMD_SURFACE_DEFINE_V2);
    801         SVGA_CASE_ID2STR(SVGA_3D_CMD_GENERATE_MIPMAPS);
    802         SVGA_CASE_ID2STR(SVGA_3D_CMD_VIDEO_CREATE_DECODER);
    803         SVGA_CASE_ID2STR(SVGA_3D_CMD_VIDEO_DESTROY_DECODER);
    804         SVGA_CASE_ID2STR(SVGA_3D_CMD_VIDEO_CREATE_PROCESSOR);
    805         SVGA_CASE_ID2STR(SVGA_3D_CMD_VIDEO_DESTROY_PROCESSOR);
    806         SVGA_CASE_ID2STR(SVGA_3D_CMD_VIDEO_DECODE_START_FRAME);
    807         SVGA_CASE_ID2STR(SVGA_3D_CMD_VIDEO_DECODE_RENDER);
    808         SVGA_CASE_ID2STR(SVGA_3D_CMD_VIDEO_DECODE_END_FRAME);
    809         SVGA_CASE_ID2STR(SVGA_3D_CMD_VIDEO_PROCESS_FRAME);
    810         SVGA_CASE_ID2STR(SVGA_3D_CMD_ACTIVATE_SURFACE);
    811         SVGA_CASE_ID2STR(SVGA_3D_CMD_DEACTIVATE_SURFACE);
    812         SVGA_CASE_ID2STR(SVGA_3D_CMD_SCREEN_DMA);
    813         SVGA_CASE_ID2STR(SVGA_3D_CMD_DEAD1);
    814         SVGA_CASE_ID2STR(SVGA_3D_CMD_DEAD2);
    815         SVGA_CASE_ID2STR(SVGA_3D_CMD_LOGICOPS_BITBLT);
    816         SVGA_CASE_ID2STR(SVGA_3D_CMD_LOGICOPS_TRANSBLT);
    817         SVGA_CASE_ID2STR(SVGA_3D_CMD_LOGICOPS_STRETCHBLT);
    818         SVGA_CASE_ID2STR(SVGA_3D_CMD_LOGICOPS_COLORFILL);
    819         SVGA_CASE_ID2STR(SVGA_3D_CMD_LOGICOPS_ALPHABLEND);
    820         SVGA_CASE_ID2STR(SVGA_3D_CMD_LOGICOPS_CLEARTYPEBLEND);
    821         SVGA_CASE_ID2STR(SVGA_3D_CMD_SET_OTABLE_BASE);
    822         SVGA_CASE_ID2STR(SVGA_3D_CMD_READBACK_OTABLE);
    823         SVGA_CASE_ID2STR(SVGA_3D_CMD_DEFINE_GB_MOB);
    824         SVGA_CASE_ID2STR(SVGA_3D_CMD_DESTROY_GB_MOB);
    825         SVGA_CASE_ID2STR(SVGA_3D_CMD_DEAD3);
    826         SVGA_CASE_ID2STR(SVGA_3D_CMD_UPDATE_GB_MOB_MAPPING);
    827         SVGA_CASE_ID2STR(SVGA_3D_CMD_DEFINE_GB_SURFACE);
    828         SVGA_CASE_ID2STR(SVGA_3D_CMD_DESTROY_GB_SURFACE);
    829         SVGA_CASE_ID2STR(SVGA_3D_CMD_BIND_GB_SURFACE);
    830         SVGA_CASE_ID2STR(SVGA_3D_CMD_COND_BIND_GB_SURFACE);
    831         SVGA_CASE_ID2STR(SVGA_3D_CMD_UPDATE_GB_IMAGE);
    832         SVGA_CASE_ID2STR(SVGA_3D_CMD_UPDATE_GB_SURFACE);
    833         SVGA_CASE_ID2STR(SVGA_3D_CMD_READBACK_GB_IMAGE);
    834         SVGA_CASE_ID2STR(SVGA_3D_CMD_READBACK_GB_SURFACE);
    835         SVGA_CASE_ID2STR(SVGA_3D_CMD_INVALIDATE_GB_IMAGE);
    836         SVGA_CASE_ID2STR(SVGA_3D_CMD_INVALIDATE_GB_SURFACE);
    837         SVGA_CASE_ID2STR(SVGA_3D_CMD_DEFINE_GB_CONTEXT);
    838         SVGA_CASE_ID2STR(SVGA_3D_CMD_DESTROY_GB_CONTEXT);
    839         SVGA_CASE_ID2STR(SVGA_3D_CMD_BIND_GB_CONTEXT);
    840         SVGA_CASE_ID2STR(SVGA_3D_CMD_READBACK_GB_CONTEXT);
    841         SVGA_CASE_ID2STR(SVGA_3D_CMD_INVALIDATE_GB_CONTEXT);
    842         SVGA_CASE_ID2STR(SVGA_3D_CMD_DEFINE_GB_SHADER);
    843         SVGA_CASE_ID2STR(SVGA_3D_CMD_DESTROY_GB_SHADER);
    844         SVGA_CASE_ID2STR(SVGA_3D_CMD_BIND_GB_SHADER);
    845         SVGA_CASE_ID2STR(SVGA_3D_CMD_SET_OTABLE_BASE64);
    846         SVGA_CASE_ID2STR(SVGA_3D_CMD_BEGIN_GB_QUERY);
    847         SVGA_CASE_ID2STR(SVGA_3D_CMD_END_GB_QUERY);
    848         SVGA_CASE_ID2STR(SVGA_3D_CMD_WAIT_FOR_GB_QUERY);
    849         SVGA_CASE_ID2STR(SVGA_3D_CMD_NOP);
    850         SVGA_CASE_ID2STR(SVGA_3D_CMD_ENABLE_GART);
    851         SVGA_CASE_ID2STR(SVGA_3D_CMD_DISABLE_GART);
    852         SVGA_CASE_ID2STR(SVGA_3D_CMD_MAP_MOB_INTO_GART);
    853         SVGA_CASE_ID2STR(SVGA_3D_CMD_UNMAP_GART_RANGE);
    854         SVGA_CASE_ID2STR(SVGA_3D_CMD_DEFINE_GB_SCREENTARGET);
    855         SVGA_CASE_ID2STR(SVGA_3D_CMD_DESTROY_GB_SCREENTARGET);
    856         SVGA_CASE_ID2STR(SVGA_3D_CMD_BIND_GB_SCREENTARGET);
    857         SVGA_CASE_ID2STR(SVGA_3D_CMD_UPDATE_GB_SCREENTARGET);
    858         SVGA_CASE_ID2STR(SVGA_3D_CMD_READBACK_GB_IMAGE_PARTIAL);
    859         SVGA_CASE_ID2STR(SVGA_3D_CMD_INVALIDATE_GB_IMAGE_PARTIAL);
    860         SVGA_CASE_ID2STR(SVGA_3D_CMD_SET_GB_SHADERCONSTS_INLINE);
    861         SVGA_CASE_ID2STR(SVGA_3D_CMD_GB_SCREEN_DMA);
    862         SVGA_CASE_ID2STR(SVGA_3D_CMD_BIND_GB_SURFACE_WITH_PITCH);
    863         SVGA_CASE_ID2STR(SVGA_3D_CMD_GB_MOB_FENCE);
    864         SVGA_CASE_ID2STR(SVGA_3D_CMD_DEFINE_GB_SURFACE_V2);
    865         SVGA_CASE_ID2STR(SVGA_3D_CMD_DEFINE_GB_MOB64);
    866         SVGA_CASE_ID2STR(SVGA_3D_CMD_REDEFINE_GB_MOB64);
    867         SVGA_CASE_ID2STR(SVGA_3D_CMD_NOP_ERROR);
    868         SVGA_CASE_ID2STR(SVGA_3D_CMD_SET_VERTEX_STREAMS);
    869         SVGA_CASE_ID2STR(SVGA_3D_CMD_SET_VERTEX_DECLS);
    870         SVGA_CASE_ID2STR(SVGA_3D_CMD_SET_VERTEX_DIVISORS);
    871         SVGA_CASE_ID2STR(SVGA_3D_CMD_DRAW);
    872         SVGA_CASE_ID2STR(SVGA_3D_CMD_DRAW_INDEXED);
    873         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_CONTEXT);
    874         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_CONTEXT);
    875         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_BIND_CONTEXT);
    876         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_READBACK_CONTEXT);
    877         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_INVALIDATE_CONTEXT);
    878         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_SINGLE_CONSTANT_BUFFER);
    879         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_SHADER_RESOURCES);
    880         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_SHADER);
    881         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_SAMPLERS);
    882         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DRAW);
    883         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DRAW_INDEXED);
    884         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DRAW_INSTANCED);
    885         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DRAW_INDEXED_INSTANCED);
    886         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DRAW_AUTO);
    887         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_INPUT_LAYOUT);
    888         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_VERTEX_BUFFERS);
    889         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_INDEX_BUFFER);
    890         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_TOPOLOGY);
    891         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_RENDERTARGETS);
    892         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_BLEND_STATE);
    893         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_DEPTHSTENCIL_STATE);
    894         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_RASTERIZER_STATE);
    895         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_QUERY);
    896         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_QUERY);
    897         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_BIND_QUERY);
    898         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_QUERY_OFFSET);
    899         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_BEGIN_QUERY);
    900         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_END_QUERY);
    901         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_READBACK_QUERY);
    902         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_PREDICATION);
    903         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_SOTARGETS);
    904         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_VIEWPORTS);
    905         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_SCISSORRECTS);
    906         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_CLEAR_RENDERTARGET_VIEW);
    907         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_CLEAR_DEPTHSTENCIL_VIEW);
    908         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_PRED_COPY_REGION);
    909         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_PRED_COPY);
    910         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_STRETCHBLT);
    911         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_GENMIPS);
    912         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_UPDATE_SUBRESOURCE);
    913         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_READBACK_SUBRESOURCE);
    914         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_INVALIDATE_SUBRESOURCE);
    915         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_SHADERRESOURCE_VIEW);
    916         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_SHADERRESOURCE_VIEW);
    917         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_RENDERTARGET_VIEW);
    918         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_RENDERTARGET_VIEW);
    919         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_DEPTHSTENCIL_VIEW);
    920         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_DEPTHSTENCIL_VIEW);
    921         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_ELEMENTLAYOUT);
    922         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_ELEMENTLAYOUT);
    923         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_BLEND_STATE);
    924         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_BLEND_STATE);
    925         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_DEPTHSTENCIL_STATE);
    926         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_DEPTHSTENCIL_STATE);
    927         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_RASTERIZER_STATE);
    928         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_RASTERIZER_STATE);
    929         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_SAMPLER_STATE);
    930         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_SAMPLER_STATE);
    931         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_SHADER);
    932         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_SHADER);
    933         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_BIND_SHADER);
    934         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_STREAMOUTPUT);
    935         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_STREAMOUTPUT);
    936         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_STREAMOUTPUT);
    937         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_COTABLE);
    938         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_READBACK_COTABLE);
    939         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_BUFFER_COPY);
    940         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_TRANSFER_FROM_BUFFER);
    941         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SURFACE_COPY_AND_READBACK);
    942         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_MOVE_QUERY);
    943         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_BIND_ALL_QUERY);
    944         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_READBACK_ALL_QUERY);
    945         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_PRED_TRANSFER_FROM_BUFFER);
    946         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_MOB_FENCE_64);
    947         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_BIND_ALL_SHADER);
    948         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_HINT);
    949         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_BUFFER_UPDATE);
    950         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_VS_CONSTANT_BUFFER_OFFSET);
    951         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_PS_CONSTANT_BUFFER_OFFSET);
    952         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_GS_CONSTANT_BUFFER_OFFSET);
    953         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_RESERVED1);
    954         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_RESERVED2);
    955         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_RESERVED3);
    956         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_COND_BIND_ALL_SHADER);
    957         SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_MAX);
    958         default: return "UNKNOWN";
    959     }
    960 }
    961 #endif /* IN_RING3 && (LOG_ENABLED || VBOX_STRICT) */
    962516
    963517#ifdef IN_RING3
     
    16961250 * @param   pThisCC     The ring-3 VGA state.
    16971251 */
    1698 static int vmsvgaR3ChangeMode(PVGASTATE pThis, PVGASTATECC pThisCC)
     1252int vmsvgaR3ChangeMode(PVGASTATE pThis, PVGASTATECC pThisCC)
    16991253{
    17001254    /* Always do changemode on FIFO thread. */
     
    18961450    pThis->svga.uCursorOn = uCursorOn;
    18971451    pThisCC->pDrv->pfnVBVAReportCursorPosition(pThisCC->pDrv, fFlags, idScreen, x, y);
    1898 }
    1899 
    1900 
    1901 /**
    1902  * Copy a rectangle of pixels within guest VRAM.
    1903  */
    1904 static void vmsvgaR3RectCopy(PVGASTATECC pThisCC, VMSVGASCREENOBJECT const *pScreen, uint32_t srcX, uint32_t srcY,
    1905                              uint32_t dstX, uint32_t dstY, uint32_t width, uint32_t height, unsigned cbFrameBuffer)
    1906 {
    1907     if (!width || !height)
    1908         return; /* Nothing to do, don't even bother. */
    1909 
    1910     /*
    1911      * The guest VRAM (aka GFB) is considered to be a bitmap in the format
    1912      * corresponding to the current display mode.
    1913      */
    1914     uint32_t const  cbPixel = RT_ALIGN(pScreen->cBpp, 8) / 8;
    1915     uint32_t const  cbScanline = pScreen->cbPitch ? pScreen->cbPitch : width * cbPixel;
    1916     uint8_t const   *pSrc;
    1917     uint8_t         *pDst;
    1918     unsigned const  cbRectWidth = width * cbPixel;
    1919     unsigned        uMaxOffset;
    1920 
    1921     uMaxOffset = (RT_MAX(srcY, dstY) + height) * cbScanline + (RT_MAX(srcX, dstX) + width) * cbPixel;
    1922     if (uMaxOffset >= cbFrameBuffer)
    1923     {
    1924         Log(("Max offset (%u) too big for framebuffer (%u bytes), ignoring!\n", uMaxOffset, cbFrameBuffer));
    1925         return; /* Just don't listen to a bad guest. */
    1926     }
    1927 
    1928     pSrc = pDst = pThisCC->pbVRam;
    1929     pSrc += srcY * cbScanline + srcX * cbPixel;
    1930     pDst += dstY * cbScanline + dstX * cbPixel;
    1931 
    1932     if (srcY >= dstY)
    1933     {
    1934         /* Source below destination, copy top to bottom. */
    1935         for (; height > 0; height--)
    1936         {
    1937             memmove(pDst, pSrc, cbRectWidth);
    1938             pSrc += cbScanline;
    1939             pDst += cbScanline;
    1940         }
    1941     }
    1942     else
    1943     {
    1944         /* Source above destination, copy bottom to top. */
    1945         pSrc += cbScanline * (height - 1);
    1946         pDst += cbScanline * (height - 1);
    1947         for (; height > 0; height--)
    1948         {
    1949             memmove(pDst, pSrc, cbRectWidth);
    1950             pSrc -= cbScanline;
    1951             pDst -= cbScanline;
    1952         }
    1953     }
    19541452}
    19551453
     
    30932591
    30942592
    3095 /**
    3096  * Common worker for changing the pointer shape.
    3097  *
    3098  * @param   pThisCC             The VGA/VMSVGA state for ring-3.
    3099  * @param   pSVGAState          The VMSVGA ring-3 instance data.
    3100  * @param   fAlpha              Whether there is alpha or not.
    3101  * @param   xHot                Hotspot x coordinate.
    3102  * @param   yHot                Hotspot y coordinate.
    3103  * @param   cx                  Width.
    3104  * @param   cy                  Height.
    3105  * @param   pbData              Heap copy of the cursor data.  Consumed.
    3106  * @param   cbData              The size of the data.
    3107  */
    3108 static void vmsvgaR3InstallNewCursor(PVGASTATECC pThisCC, PVMSVGAR3STATE pSVGAState, bool fAlpha,
    3109                                      uint32_t xHot, uint32_t yHot, uint32_t cx, uint32_t cy, uint8_t *pbData, uint32_t cbData)
    3110 {
    3111     LogRel2(("vmsvgaR3InstallNewCursor: cx=%d cy=%d xHot=%d yHot=%d fAlpha=%d cbData=%#x\n", cx, cy, xHot, yHot, fAlpha, cbData));
    3112 # ifdef LOG_ENABLED
    3113     if (LogIs2Enabled())
    3114     {
    3115         uint32_t cbAndLine = RT_ALIGN(cx, 8) / 8;
    3116         if (!fAlpha)
    3117         {
    3118             Log2(("VMSVGA Cursor AND mask (%d,%d):\n", cx, cy));
    3119             for (uint32_t y = 0; y < cy; y++)
    3120             {
    3121                 Log2(("%3u:", y));
    3122                 uint8_t const *pbLine = &pbData[y * cbAndLine];
    3123                 for (uint32_t x = 0; x < cx; x += 8)
    3124                 {
    3125                     uint8_t   b = pbLine[x / 8];
    3126                     char      szByte[12];
    3127                     szByte[0] = b & 0x80 ? '*' : ' '; /* most significant bit first */
    3128                     szByte[1] = b & 0x40 ? '*' : ' ';
    3129                     szByte[2] = b & 0x20 ? '*' : ' ';
    3130                     szByte[3] = b & 0x10 ? '*' : ' ';
    3131                     szByte[4] = b & 0x08 ? '*' : ' ';
    3132                     szByte[5] = b & 0x04 ? '*' : ' ';
    3133                     szByte[6] = b & 0x02 ? '*' : ' ';
    3134                     szByte[7] = b & 0x01 ? '*' : ' ';
    3135                     szByte[8] = '\0';
    3136                     Log2(("%s", szByte));
    3137                 }
    3138                 Log2(("\n"));
    3139             }
    3140         }
    3141 
    3142         Log2(("VMSVGA Cursor XOR mask (%d,%d):\n", cx, cy));
    3143         uint32_t const *pu32Xor = (uint32_t const *)&pbData[RT_ALIGN_32(cbAndLine * cy, 4)];
    3144         for (uint32_t y = 0; y < cy; y++)
    3145         {
    3146             Log2(("%3u:", y));
    3147             uint32_t const *pu32Line = &pu32Xor[y * cx];
    3148             for (uint32_t x = 0; x < cx; x++)
    3149                 Log2((" %08x", pu32Line[x]));
    3150             Log2(("\n"));
    3151         }
    3152     }
    3153 # endif
    3154 
    3155     int rc = pThisCC->pDrv->pfnVBVAMousePointerShape(pThisCC->pDrv, true /*fVisible*/, fAlpha, xHot, yHot, cx, cy, pbData);
    3156     AssertRC(rc);
    3157 
    3158     if (pSVGAState->Cursor.fActive)
    3159         RTMemFreeZ(pSVGAState->Cursor.pData, pSVGAState->Cursor.cbData);
    3160 
    3161     pSVGAState->Cursor.fActive  = true;
    3162     pSVGAState->Cursor.xHotspot = xHot;
    3163     pSVGAState->Cursor.yHotspot = yHot;
    3164     pSVGAState->Cursor.width    = cx;
    3165     pSVGAState->Cursor.height   = cy;
    3166     pSVGAState->Cursor.cbData   = cbData;
    3167     pSVGAState->Cursor.pData    = pbData;
    3168 }
    3169 
    3170 
    3171 # ifdef VBOX_WITH_VMSVGA3D
    3172 /** @def VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK
    3173  * Check that the 3D command has at least a_cbMin of payload bytes after the
    3174  * header.  Will break out of the switch if it doesn't.
    3175  */
    3176 #  define VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(a_cbMin) \
    3177      if (1) { \
    3178           AssertMsgBreak(cbCmd >= (a_cbMin), ("size=%#x a_cbMin=%#zx\n", cbCmd, (size_t)(a_cbMin))); \
    3179           RT_UNTRUSTED_VALIDATED_FENCE(); \
    3180      } else do {} while (0)
    3181 
    3182 #  define VMSVGA_3D_CMD_NOTIMPL() \
    3183      if (1) { \
    3184           AssertMsgFailed(("Not implemented %d %s\n", enmCmdId, vmsvgaR3FifoCmdToString(enmCmdId))); \
    3185      } else do {} while (0)
    3186 
    3187 /** SVGA_3D_CMD_* handler.
    3188  * This function parses the command and calls the corresponding command handler.
    3189  *
    3190  * @param   pThis       The shared VGA/VMSVGA state.
    3191  * @param   pThisCC     The VGA/VMSVGA state for the current context.
    3192  * @param   enmCmdId    SVGA_3D_CMD_* command identifier.
    3193  * @param   cbCmd       Size of the command in bytes.
    3194  * @param   pvCmd       Pointer to the command.
    3195  * @returns VBox status code if an error was detected parsing a command.
    3196  */
    3197 static int vmsvgaR3Process3dCmd(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifo3dCmdId enmCmdId, uint32_t cbCmd, void const *pvCmd)
    3198 {
    3199     int rcParse = VINF_SUCCESS;
    3200     PVMSVGAR3STATE pSvgaR3State = pThisCC->svga.pSvgaR3State;
    3201 
    3202     switch (enmCmdId)
    3203     {
    3204     case SVGA_3D_CMD_SURFACE_DEFINE:
    3205     {
    3206         SVGA3dCmdDefineSurface *pCmd = (SVGA3dCmdDefineSurface *)pvCmd;
    3207         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3208         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSurfaceDefine);
    3209 
    3210         uint32_t const cMipLevels = (cbCmd - sizeof(*pCmd)) / sizeof(SVGA3dSize);
    3211         vmsvga3dSurfaceDefine(pThisCC, pCmd->sid, (uint32_t)pCmd->surfaceFlags, pCmd->format, pCmd->face, 0,
    3212                               SVGA3D_TEX_FILTER_NONE, cMipLevels, (SVGA3dSize *)(pCmd + 1));
    3213 #  ifdef DEBUG_GMR_ACCESS
    3214         VMR3ReqCallWaitU(PDMDevHlpGetUVM(pDevIns), VMCPUID_ANY, (PFNRT)vmsvgaR3ResetGmrHandlers, 1, pThis);
    3215 #  endif
    3216         break;
    3217     }
    3218 
    3219     case SVGA_3D_CMD_SURFACE_DEFINE_V2:
    3220     {
    3221         SVGA3dCmdDefineSurface_v2 *pCmd = (SVGA3dCmdDefineSurface_v2 *)pvCmd;
    3222         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3223         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSurfaceDefineV2);
    3224 
    3225         uint32_t const cMipLevels = (cbCmd - sizeof(*pCmd)) / sizeof(SVGA3dSize);
    3226         vmsvga3dSurfaceDefine(pThisCC, pCmd->sid, pCmd->surfaceFlags, pCmd->format, pCmd->face,
    3227                               pCmd->multisampleCount, pCmd->autogenFilter,
    3228                               cMipLevels, (SVGA3dSize *)(pCmd + 1));
    3229         break;
    3230     }
    3231 
    3232     case SVGA_3D_CMD_SURFACE_DESTROY:
    3233     {
    3234         SVGA3dCmdDestroySurface *pCmd = (SVGA3dCmdDestroySurface *)pvCmd;
    3235         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3236         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSurfaceDestroy);
    3237 
    3238         vmsvga3dSurfaceDestroy(pThisCC, pCmd->sid);
    3239         break;
    3240     }
    3241 
    3242     case SVGA_3D_CMD_SURFACE_COPY:
    3243     {
    3244         SVGA3dCmdSurfaceCopy *pCmd = (SVGA3dCmdSurfaceCopy *)pvCmd;
    3245         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3246         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSurfaceCopy);
    3247 
    3248         uint32_t const cCopyBoxes = (cbCmd - sizeof(pCmd)) / sizeof(SVGA3dCopyBox);
    3249         vmsvga3dSurfaceCopy(pThisCC, pCmd->dest, pCmd->src, cCopyBoxes, (SVGA3dCopyBox *)(pCmd + 1));
    3250         break;
    3251     }
    3252 
    3253     case SVGA_3D_CMD_SURFACE_STRETCHBLT:
    3254     {
    3255         SVGA3dCmdSurfaceStretchBlt *pCmd = (SVGA3dCmdSurfaceStretchBlt *)pvCmd;
    3256         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3257         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSurfaceStretchBlt);
    3258 
    3259         vmsvga3dSurfaceStretchBlt(pThis, pThisCC, &pCmd->dest, &pCmd->boxDest,
    3260                                   &pCmd->src, &pCmd->boxSrc, pCmd->mode);
    3261         break;
    3262     }
    3263 
    3264     case SVGA_3D_CMD_SURFACE_DMA:
    3265     {
    3266         SVGA3dCmdSurfaceDMA *pCmd = (SVGA3dCmdSurfaceDMA *)pvCmd;
    3267         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3268         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSurfaceDma);
    3269 
    3270         uint64_t u64NanoTS = 0;
    3271         if (LogRelIs3Enabled())
    3272             u64NanoTS = RTTimeNanoTS();
    3273         uint32_t const cCopyBoxes = (cbCmd - sizeof(*pCmd)) / sizeof(SVGA3dCopyBox);
    3274         STAM_PROFILE_START(&pSvgaR3State->StatR3Cmd3dSurfaceDmaProf, a);
    3275         vmsvga3dSurfaceDMA(pThis, pThisCC, pCmd->guest, pCmd->host, pCmd->transfer,
    3276                            cCopyBoxes, (SVGA3dCopyBox *)(pCmd + 1));
    3277         STAM_PROFILE_STOP(&pSvgaR3State->StatR3Cmd3dSurfaceDmaProf, a);
    3278         if (LogRelIs3Enabled())
    3279         {
    3280             if (cCopyBoxes)
    3281             {
    3282                 SVGA3dCopyBox *pFirstBox = (SVGA3dCopyBox *)(pCmd + 1);
    3283                 LogRel3(("VMSVGA: SURFACE_DMA: %d us %d boxes %d,%d %dx%d%s\n",
    3284                          (RTTimeNanoTS() - u64NanoTS) / 1000ULL, cCopyBoxes,
    3285                          pFirstBox->x, pFirstBox->y, pFirstBox->w, pFirstBox->h,
    3286                          pCmd->transfer == SVGA3D_READ_HOST_VRAM ? " readback!!!" : ""));
    3287             }
    3288         }
    3289         break;
    3290     }
    3291 
    3292     case SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN:
    3293     {
    3294         SVGA3dCmdBlitSurfaceToScreen *pCmd = (SVGA3dCmdBlitSurfaceToScreen *)pvCmd;
    3295         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3296         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSurfaceScreen);
    3297 
    3298         static uint64_t u64FrameStartNanoTS = 0;
    3299         static uint64_t u64ElapsedPerSecNano = 0;
    3300         static int cFrames = 0;
    3301         uint64_t u64NanoTS = 0;
    3302         if (LogRelIs3Enabled())
    3303             u64NanoTS = RTTimeNanoTS();
    3304         uint32_t const cRects = (cbCmd - sizeof(*pCmd)) / sizeof(SVGASignedRect);
    3305         STAM_REL_PROFILE_START(&pSvgaR3State->StatR3Cmd3dBlitSurfaceToScreenProf, a);
    3306         vmsvga3dSurfaceBlitToScreen(pThis, pThisCC, pCmd->destScreenId, pCmd->destRect, pCmd->srcImage,
    3307                                     pCmd->srcRect, cRects, (SVGASignedRect *)(pCmd + 1));
    3308         STAM_REL_PROFILE_STOP(&pSvgaR3State->StatR3Cmd3dBlitSurfaceToScreenProf, a);
    3309         if (LogRelIs3Enabled())
    3310         {
    3311             uint64_t u64ElapsedNano = RTTimeNanoTS() - u64NanoTS;
    3312             u64ElapsedPerSecNano += u64ElapsedNano;
    3313 
    3314             SVGASignedRect *pFirstRect = cRects ? (SVGASignedRect *)(pCmd + 1) : &pCmd->destRect;
    3315             LogRel3(("VMSVGA: SURFACE_TO_SCREEN: %d us %d rects %d,%d %dx%d\n",
    3316                      (u64ElapsedNano) / 1000ULL, cRects,
    3317                      pFirstRect->left, pFirstRect->top,
    3318                      pFirstRect->right - pFirstRect->left, pFirstRect->bottom - pFirstRect->top));
    3319 
    3320             ++cFrames;
    3321             if (u64NanoTS - u64FrameStartNanoTS >= UINT64_C(1000000000))
    3322             {
    3323                 LogRel3(("VMSVGA: SURFACE_TO_SCREEN: FPS %d, elapsed %llu us\n",
    3324                          cFrames, u64ElapsedPerSecNano / 1000ULL));
    3325                 u64FrameStartNanoTS = u64NanoTS;
    3326                 cFrames = 0;
    3327                 u64ElapsedPerSecNano = 0;
    3328             }
    3329         }
    3330         break;
    3331     }
    3332 
    3333     case SVGA_3D_CMD_CONTEXT_DEFINE:
    3334     {
    3335         SVGA3dCmdDefineContext *pCmd = (SVGA3dCmdDefineContext *)pvCmd;
    3336         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3337         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dContextDefine);
    3338 
    3339         vmsvga3dContextDefine(pThisCC, pCmd->cid);
    3340         break;
    3341     }
    3342 
    3343     case SVGA_3D_CMD_CONTEXT_DESTROY:
    3344     {
    3345         SVGA3dCmdDestroyContext *pCmd = (SVGA3dCmdDestroyContext *)pvCmd;
    3346         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3347         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dContextDestroy);
    3348 
    3349         vmsvga3dContextDestroy(pThisCC, pCmd->cid);
    3350         break;
    3351     }
    3352 
    3353     case SVGA_3D_CMD_SETTRANSFORM:
    3354     {
    3355         SVGA3dCmdSetTransform *pCmd = (SVGA3dCmdSetTransform *)pvCmd;
    3356         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3357         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSetTransform);
    3358 
    3359         vmsvga3dSetTransform(pThisCC, pCmd->cid, pCmd->type, pCmd->matrix);
    3360         break;
    3361     }
    3362 
    3363     case SVGA_3D_CMD_SETZRANGE:
    3364     {
    3365         SVGA3dCmdSetZRange *pCmd = (SVGA3dCmdSetZRange *)pvCmd;
    3366         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3367         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSetZRange);
    3368 
    3369         vmsvga3dSetZRange(pThisCC, pCmd->cid, pCmd->zRange);
    3370         break;
    3371     }
    3372 
    3373     case SVGA_3D_CMD_SETRENDERSTATE:
    3374     {
    3375         SVGA3dCmdSetRenderState *pCmd = (SVGA3dCmdSetRenderState *)pvCmd;
    3376         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3377         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSetRenderState);
    3378 
    3379         uint32_t const cRenderStates = (cbCmd - sizeof(*pCmd)) / sizeof(SVGA3dRenderState);
    3380         vmsvga3dSetRenderState(pThisCC, pCmd->cid, cRenderStates, (SVGA3dRenderState *)(pCmd + 1));
    3381         break;
    3382     }
    3383 
    3384     case SVGA_3D_CMD_SETRENDERTARGET:
    3385     {
    3386         SVGA3dCmdSetRenderTarget *pCmd = (SVGA3dCmdSetRenderTarget *)pvCmd;
    3387         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3388         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSetRenderTarget);
    3389 
    3390         vmsvga3dSetRenderTarget(pThisCC, pCmd->cid, pCmd->type, pCmd->target);
    3391         break;
    3392     }
    3393 
    3394     case SVGA_3D_CMD_SETTEXTURESTATE:
    3395     {
    3396         SVGA3dCmdSetTextureState *pCmd = (SVGA3dCmdSetTextureState *)pvCmd;
    3397         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3398         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSetTextureState);
    3399 
    3400         uint32_t const cTextureStates = (cbCmd - sizeof(*pCmd)) / sizeof(SVGA3dTextureState);
    3401         vmsvga3dSetTextureState(pThisCC, pCmd->cid, cTextureStates, (SVGA3dTextureState *)(pCmd + 1));
    3402         break;
    3403     }
    3404 
    3405     case SVGA_3D_CMD_SETMATERIAL:
    3406     {
    3407         SVGA3dCmdSetMaterial *pCmd = (SVGA3dCmdSetMaterial *)pvCmd;
    3408         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3409         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSetMaterial);
    3410 
    3411         vmsvga3dSetMaterial(pThisCC, pCmd->cid, pCmd->face, &pCmd->material);
    3412         break;
    3413     }
    3414 
    3415     case SVGA_3D_CMD_SETLIGHTDATA:
    3416     {
    3417         SVGA3dCmdSetLightData *pCmd = (SVGA3dCmdSetLightData *)pvCmd;
    3418         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3419         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSetLightData);
    3420 
    3421         vmsvga3dSetLightData(pThisCC, pCmd->cid, pCmd->index, &pCmd->data);
    3422         break;
    3423     }
    3424 
    3425     case SVGA_3D_CMD_SETLIGHTENABLED:
    3426     {
    3427         SVGA3dCmdSetLightEnabled *pCmd = (SVGA3dCmdSetLightEnabled *)pvCmd;
    3428         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3429         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSetLightEnable);
    3430 
    3431         vmsvga3dSetLightEnabled(pThisCC, pCmd->cid, pCmd->index, pCmd->enabled);
    3432         break;
    3433     }
    3434 
    3435     case SVGA_3D_CMD_SETVIEWPORT:
    3436     {
    3437         SVGA3dCmdSetViewport *pCmd = (SVGA3dCmdSetViewport *)pvCmd;
    3438         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3439         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSetViewPort);
    3440 
    3441         vmsvga3dSetViewPort(pThisCC, pCmd->cid, &pCmd->rect);
    3442         break;
    3443     }
    3444 
    3445     case SVGA_3D_CMD_SETCLIPPLANE:
    3446     {
    3447         SVGA3dCmdSetClipPlane *pCmd = (SVGA3dCmdSetClipPlane *)pvCmd;
    3448         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3449         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSetClipPlane);
    3450 
    3451         vmsvga3dSetClipPlane(pThisCC, pCmd->cid, pCmd->index, pCmd->plane);
    3452         break;
    3453     }
    3454 
    3455     case SVGA_3D_CMD_CLEAR:
    3456     {
    3457         SVGA3dCmdClear  *pCmd = (SVGA3dCmdClear *)pvCmd;
    3458         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3459         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dClear);
    3460 
    3461         uint32_t const cRects = (cbCmd - sizeof(*pCmd)) / sizeof(SVGA3dRect);
    3462         vmsvga3dCommandClear(pThisCC, pCmd->cid, pCmd->clearFlag, pCmd->color, pCmd->depth, pCmd->stencil, cRects, (SVGA3dRect *)(pCmd + 1));
    3463         break;
    3464     }
    3465 
    3466     case SVGA_3D_CMD_PRESENT:
    3467     case SVGA_3D_CMD_PRESENT_READBACK: /** @todo SVGA_3D_CMD_PRESENT_READBACK isn't quite the same as present... */
    3468     {
    3469         SVGA3dCmdPresent *pCmd = (SVGA3dCmdPresent *)pvCmd;
    3470         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3471         if (enmCmdId == SVGA_3D_CMD_PRESENT)
    3472             STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dPresent);
    3473         else
    3474             STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dPresentReadBack);
    3475 
    3476         uint32_t const cRects = (cbCmd - sizeof(*pCmd)) / sizeof(SVGA3dCopyRect);
    3477         STAM_PROFILE_START(&pSvgaR3State->StatR3Cmd3dPresentProf, a);
    3478         vmsvga3dCommandPresent(pThis, pThisCC, pCmd->sid, cRects, (SVGA3dCopyRect *)(pCmd + 1));
    3479         STAM_PROFILE_STOP(&pSvgaR3State->StatR3Cmd3dPresentProf, a);
    3480         break;
    3481     }
    3482 
    3483     case SVGA_3D_CMD_SHADER_DEFINE:
    3484     {
    3485         SVGA3dCmdDefineShader *pCmd = (SVGA3dCmdDefineShader *)pvCmd;
    3486         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3487         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dShaderDefine);
    3488 
    3489         uint32_t const cbData = (cbCmd - sizeof(*pCmd));
    3490         vmsvga3dShaderDefine(pThisCC, pCmd->cid, pCmd->shid, pCmd->type, cbData, (uint32_t *)(pCmd + 1));
    3491         break;
    3492     }
    3493 
    3494     case SVGA_3D_CMD_SHADER_DESTROY:
    3495     {
    3496         SVGA3dCmdDestroyShader *pCmd = (SVGA3dCmdDestroyShader *)pvCmd;
    3497         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3498         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dShaderDestroy);
    3499 
    3500         vmsvga3dShaderDestroy(pThisCC, pCmd->cid, pCmd->shid, pCmd->type);
    3501         break;
    3502     }
    3503 
    3504     case SVGA_3D_CMD_SET_SHADER:
    3505     {
    3506         SVGA3dCmdSetShader *pCmd = (SVGA3dCmdSetShader *)pvCmd;
    3507         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3508         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSetShader);
    3509 
    3510         vmsvga3dShaderSet(pThisCC, NULL, pCmd->cid, pCmd->type, pCmd->shid);
    3511         break;
    3512     }
    3513 
    3514     case SVGA_3D_CMD_SET_SHADER_CONST:
    3515     {
    3516         SVGA3dCmdSetShaderConst *pCmd = (SVGA3dCmdSetShaderConst *)pvCmd;
    3517         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3518         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSetShaderConst);
    3519 
    3520         uint32_t const cRegisters = (cbCmd - sizeof(*pCmd)) / sizeof(pCmd->values) + 1;
    3521         vmsvga3dShaderSetConst(pThisCC, pCmd->cid, pCmd->reg, pCmd->type, pCmd->ctype, cRegisters, pCmd->values);
    3522         break;
    3523     }
    3524 
    3525     case SVGA_3D_CMD_DRAW_PRIMITIVES:
    3526     {
    3527         SVGA3dCmdDrawPrimitives *pCmd = (SVGA3dCmdDrawPrimitives *)pvCmd;
    3528         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3529         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dDrawPrimitives);
    3530 
    3531         ASSERT_GUEST_STMT_BREAK(pCmd->numRanges <= SVGA3D_MAX_DRAW_PRIMITIVE_RANGES, rcParse = VERR_INVALID_PARAMETER);
    3532         ASSERT_GUEST_STMT_BREAK(pCmd->numVertexDecls <= SVGA3D_MAX_VERTEX_ARRAYS, rcParse = VERR_INVALID_PARAMETER);
    3533         uint32_t const cbRangesAndVertexDecls = pCmd->numVertexDecls * sizeof(SVGA3dVertexDecl)
    3534                                               + pCmd->numRanges * sizeof(SVGA3dPrimitiveRange);
    3535         ASSERT_GUEST_STMT_BREAK(cbRangesAndVertexDecls <= cbCmd - sizeof(*pCmd), rcParse = VERR_INVALID_PARAMETER);
    3536 
    3537         uint32_t const cVertexDivisor = (cbCmd - sizeof(*pCmd) - cbRangesAndVertexDecls) / sizeof(uint32_t);
    3538         ASSERT_GUEST_STMT_BREAK(!cVertexDivisor || cVertexDivisor == pCmd->numVertexDecls, rcParse = VERR_INVALID_PARAMETER);
    3539         RT_UNTRUSTED_VALIDATED_FENCE();
    3540 
    3541         SVGA3dVertexDecl     *pVertexDecl    = (SVGA3dVertexDecl *)(pCmd + 1);
    3542         SVGA3dPrimitiveRange *pNumRange      = (SVGA3dPrimitiveRange *)&pVertexDecl[pCmd->numVertexDecls];
    3543         SVGA3dVertexDivisor  *pVertexDivisor = cVertexDivisor ? (SVGA3dVertexDivisor *)&pNumRange[pCmd->numRanges] : NULL;
    3544 
    3545         STAM_PROFILE_START(&pSvgaR3State->StatR3Cmd3dDrawPrimitivesProf, a);
    3546         vmsvga3dDrawPrimitives(pThisCC, pCmd->cid, pCmd->numVertexDecls, pVertexDecl, pCmd->numRanges,
    3547                                pNumRange, cVertexDivisor, pVertexDivisor);
    3548         STAM_PROFILE_STOP(&pSvgaR3State->StatR3Cmd3dDrawPrimitivesProf, a);
    3549         break;
    3550     }
    3551 
    3552     case SVGA_3D_CMD_SETSCISSORRECT:
    3553     {
    3554         SVGA3dCmdSetScissorRect *pCmd = (SVGA3dCmdSetScissorRect *)pvCmd;
    3555         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3556         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dSetScissorRect);
    3557 
    3558         vmsvga3dSetScissorRect(pThisCC, pCmd->cid, &pCmd->rect);
    3559         break;
    3560     }
    3561 
    3562     case SVGA_3D_CMD_BEGIN_QUERY:
    3563     {
    3564         SVGA3dCmdBeginQuery *pCmd = (SVGA3dCmdBeginQuery *)pvCmd;
    3565         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3566         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dBeginQuery);
    3567 
    3568         vmsvga3dQueryBegin(pThisCC, pCmd->cid, pCmd->type);
    3569         break;
    3570     }
    3571 
    3572     case SVGA_3D_CMD_END_QUERY:
    3573     {
    3574         SVGA3dCmdEndQuery *pCmd = (SVGA3dCmdEndQuery *)pvCmd;
    3575         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3576         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dEndQuery);
    3577 
    3578         vmsvga3dQueryEnd(pThisCC, pCmd->cid, pCmd->type, pCmd->guestResult);
    3579         break;
    3580     }
    3581 
    3582     case SVGA_3D_CMD_WAIT_FOR_QUERY:
    3583     {
    3584         SVGA3dCmdWaitForQuery *pCmd = (SVGA3dCmdWaitForQuery *)pvCmd;
    3585         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3586         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dWaitForQuery);
    3587 
    3588         vmsvga3dQueryWait(pThis, pThisCC, pCmd->cid, pCmd->type, pCmd->guestResult);
    3589         break;
    3590     }
    3591 
    3592     case SVGA_3D_CMD_GENERATE_MIPMAPS:
    3593     {
    3594         SVGA3dCmdGenerateMipmaps *pCmd = (SVGA3dCmdGenerateMipmaps *)pvCmd;
    3595         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3596         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dGenerateMipmaps);
    3597 
    3598         vmsvga3dGenerateMipmaps(pThisCC, pCmd->sid, pCmd->filter);
    3599         break;
    3600     }
    3601 
    3602     case SVGA_3D_CMD_ACTIVATE_SURFACE:
    3603         /* context id + surface id? */
    3604         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dActivateSurface);
    3605         break;
    3606 
    3607     case SVGA_3D_CMD_DEACTIVATE_SURFACE:
    3608         /* context id + surface id? */
    3609         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3Cmd3dDeactivateSurface);
    3610         break;
    3611 
    3612     /*
    3613      *
    3614      * VPGU10: SVGA_CAP_GBOBJECTS+ commands.
    3615      *
    3616      */
    3617     case SVGA_3D_CMD_SCREEN_DMA:
    3618     {
    3619         SVGA3dCmdScreenDMA *pCmd = (SVGA3dCmdScreenDMA *)pvCmd;
    3620         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3621         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3622         break;
    3623     }
    3624 
    3625     case SVGA_3D_CMD_DEAD1:
    3626     case SVGA_3D_CMD_DEAD2:
    3627     {
    3628         VMSVGA_3D_CMD_NOTIMPL();
    3629         break;
    3630     }
    3631 
    3632     case SVGA_3D_CMD_LOGICOPS_BITBLT:
    3633     {
    3634         SVGA3dCmdLogicOpsBitBlt *pCmd = (SVGA3dCmdLogicOpsBitBlt *)pvCmd;
    3635         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3636         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3637         break;
    3638     }
    3639 
    3640     case SVGA_3D_CMD_LOGICOPS_TRANSBLT:
    3641     {
    3642         SVGA3dCmdLogicOpsTransBlt *pCmd = (SVGA3dCmdLogicOpsTransBlt *)pvCmd;
    3643         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3644         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3645         break;
    3646     }
    3647 
    3648     case SVGA_3D_CMD_LOGICOPS_STRETCHBLT:
    3649     {
    3650         SVGA3dCmdLogicOpsStretchBlt *pCmd = (SVGA3dCmdLogicOpsStretchBlt *)pvCmd;
    3651         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3652         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3653         break;
    3654     }
    3655 
    3656     case SVGA_3D_CMD_LOGICOPS_COLORFILL:
    3657     {
    3658         SVGA3dCmdLogicOpsColorFill *pCmd = (SVGA3dCmdLogicOpsColorFill *)pvCmd;
    3659         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3660         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3661         break;
    3662     }
    3663 
    3664     case SVGA_3D_CMD_LOGICOPS_ALPHABLEND:
    3665     {
    3666         SVGA3dCmdLogicOpsAlphaBlend *pCmd = (SVGA3dCmdLogicOpsAlphaBlend *)pvCmd;
    3667         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3668         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3669         break;
    3670     }
    3671 
    3672     case SVGA_3D_CMD_LOGICOPS_CLEARTYPEBLEND:
    3673     {
    3674         SVGA3dCmdLogicOpsClearTypeBlend *pCmd = (SVGA3dCmdLogicOpsClearTypeBlend *)pvCmd;
    3675         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3676         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3677         break;
    3678     }
    3679 
    3680     case SVGA_3D_CMD_SET_OTABLE_BASE:
    3681     {
    3682         SVGA3dCmdSetOTableBase *pCmd = (SVGA3dCmdSetOTableBase *)pvCmd;
    3683         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3684         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3685         break;
    3686     }
    3687 
    3688     case SVGA_3D_CMD_READBACK_OTABLE:
    3689     {
    3690         SVGA3dCmdReadbackOTable *pCmd = (SVGA3dCmdReadbackOTable *)pvCmd;
    3691         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3692         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3693         break;
    3694     }
    3695 
    3696     case SVGA_3D_CMD_DEFINE_GB_MOB:
    3697     {
    3698         SVGA3dCmdDefineGBMob *pCmd = (SVGA3dCmdDefineGBMob *)pvCmd;
    3699         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3700         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3701         break;
    3702     }
    3703 
    3704     case SVGA_3D_CMD_DESTROY_GB_MOB:
    3705     {
    3706         SVGA3dCmdDestroyGBMob *pCmd = (SVGA3dCmdDestroyGBMob *)pvCmd;
    3707         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3708         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3709         break;
    3710     }
    3711 
    3712     case SVGA_3D_CMD_DEAD3:
    3713     {
    3714         VMSVGA_3D_CMD_NOTIMPL();
    3715         break;
    3716     }
    3717 
    3718     case SVGA_3D_CMD_UPDATE_GB_MOB_MAPPING:
    3719     {
    3720         SVGA3dCmdUpdateGBMobMapping *pCmd = (SVGA3dCmdUpdateGBMobMapping *)pvCmd;
    3721         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3722         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3723         break;
    3724     }
    3725 
    3726     case SVGA_3D_CMD_DEFINE_GB_SURFACE:
    3727     {
    3728         SVGA3dCmdDefineGBSurface *pCmd = (SVGA3dCmdDefineGBSurface *)pvCmd;
    3729         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3730         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3731         break;
    3732     }
    3733 
    3734     case SVGA_3D_CMD_DESTROY_GB_SURFACE:
    3735     {
    3736         SVGA3dCmdDestroyGBSurface *pCmd = (SVGA3dCmdDestroyGBSurface *)pvCmd;
    3737         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3738         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3739         break;
    3740     }
    3741 
    3742     case SVGA_3D_CMD_BIND_GB_SURFACE:
    3743     {
    3744         SVGA3dCmdBindGBSurface *pCmd = (SVGA3dCmdBindGBSurface *)pvCmd;
    3745         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3746         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3747         break;
    3748     }
    3749 
    3750     case SVGA_3D_CMD_COND_BIND_GB_SURFACE:
    3751     {
    3752         SVGA3dCmdCondBindGBSurface *pCmd = (SVGA3dCmdCondBindGBSurface *)pvCmd;
    3753         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3754         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3755         break;
    3756     }
    3757 
    3758     case SVGA_3D_CMD_UPDATE_GB_IMAGE:
    3759     {
    3760         SVGA3dCmdUpdateGBImage *pCmd = (SVGA3dCmdUpdateGBImage *)pvCmd;
    3761         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3762         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3763         break;
    3764     }
    3765 
    3766     case SVGA_3D_CMD_UPDATE_GB_SURFACE:
    3767     {
    3768         SVGA3dCmdUpdateGBSurface *pCmd = (SVGA3dCmdUpdateGBSurface *)pvCmd;
    3769         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3770         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3771         break;
    3772     }
    3773 
    3774     case SVGA_3D_CMD_READBACK_GB_IMAGE:
    3775     {
    3776         SVGA3dCmdReadbackGBImage *pCmd = (SVGA3dCmdReadbackGBImage *)pvCmd;
    3777         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3778         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3779         break;
    3780     }
    3781 
    3782     case SVGA_3D_CMD_READBACK_GB_SURFACE:
    3783     {
    3784         SVGA3dCmdReadbackGBSurface *pCmd = (SVGA3dCmdReadbackGBSurface *)pvCmd;
    3785         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3786         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3787         break;
    3788     }
    3789 
    3790     case SVGA_3D_CMD_INVALIDATE_GB_IMAGE:
    3791     {
    3792         SVGA3dCmdInvalidateGBImage *pCmd = (SVGA3dCmdInvalidateGBImage *)pvCmd;
    3793         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3794         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3795         break;
    3796     }
    3797 
    3798     case SVGA_3D_CMD_INVALIDATE_GB_SURFACE:
    3799     {
    3800         SVGA3dCmdInvalidateGBSurface *pCmd = (SVGA3dCmdInvalidateGBSurface *)pvCmd;
    3801         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3802         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3803         break;
    3804     }
    3805 
    3806     case SVGA_3D_CMD_DEFINE_GB_CONTEXT:
    3807     {
    3808         SVGA3dCmdDefineGBContext *pCmd = (SVGA3dCmdDefineGBContext *)pvCmd;
    3809         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3810         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3811         break;
    3812     }
    3813 
    3814     case SVGA_3D_CMD_DESTROY_GB_CONTEXT:
    3815     {
    3816         SVGA3dCmdDestroyGBContext *pCmd = (SVGA3dCmdDestroyGBContext *)pvCmd;
    3817         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3818         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3819         break;
    3820     }
    3821 
    3822     case SVGA_3D_CMD_BIND_GB_CONTEXT:
    3823     {
    3824         SVGA3dCmdBindGBContext *pCmd = (SVGA3dCmdBindGBContext *)pvCmd;
    3825         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3826         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3827         break;
    3828     }
    3829 
    3830     case SVGA_3D_CMD_READBACK_GB_CONTEXT:
    3831     {
    3832         SVGA3dCmdReadbackGBContext *pCmd = (SVGA3dCmdReadbackGBContext *)pvCmd;
    3833         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3834         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3835         break;
    3836     }
    3837 
    3838     case SVGA_3D_CMD_INVALIDATE_GB_CONTEXT:
    3839     {
    3840         SVGA3dCmdInvalidateGBContext *pCmd = (SVGA3dCmdInvalidateGBContext *)pvCmd;
    3841         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3842         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3843         break;
    3844     }
    3845 
    3846     case SVGA_3D_CMD_DEFINE_GB_SHADER:
    3847     {
    3848         SVGA3dCmdDefineGBShader *pCmd = (SVGA3dCmdDefineGBShader *)pvCmd;
    3849         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3850         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3851         break;
    3852     }
    3853 
    3854     case SVGA_3D_CMD_DESTROY_GB_SHADER:
    3855     {
    3856         SVGA3dCmdDestroyGBShader *pCmd = (SVGA3dCmdDestroyGBShader *)pvCmd;
    3857         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3858         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3859         break;
    3860     }
    3861 
    3862     case SVGA_3D_CMD_BIND_GB_SHADER:
    3863     {
    3864         SVGA3dCmdBindGBShader *pCmd = (SVGA3dCmdBindGBShader *)pvCmd;
    3865         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3866         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3867         break;
    3868     }
    3869 
    3870     case SVGA_3D_CMD_SET_OTABLE_BASE64:
    3871     {
    3872         SVGA3dCmdSetOTableBase64 *pCmd = (SVGA3dCmdSetOTableBase64 *)pvCmd;
    3873         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3874         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3875         break;
    3876     }
    3877 
    3878     case SVGA_3D_CMD_BEGIN_GB_QUERY:
    3879     {
    3880         SVGA3dCmdBeginGBQuery *pCmd = (SVGA3dCmdBeginGBQuery *)pvCmd;
    3881         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3882         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3883         break;
    3884     }
    3885 
    3886     case SVGA_3D_CMD_END_GB_QUERY:
    3887     {
    3888         SVGA3dCmdEndGBQuery *pCmd = (SVGA3dCmdEndGBQuery *)pvCmd;
    3889         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3890         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3891         break;
    3892     }
    3893 
    3894     case SVGA_3D_CMD_WAIT_FOR_GB_QUERY:
    3895     {
    3896         SVGA3dCmdWaitForGBQuery *pCmd = (SVGA3dCmdWaitForGBQuery *)pvCmd;
    3897         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3898         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3899         break;
    3900     }
    3901 
    3902     case SVGA_3D_CMD_NOP:
    3903     {
    3904         /* Apparently there is nothing to do. */
    3905         break;
    3906     }
    3907 
    3908     case SVGA_3D_CMD_ENABLE_GART:
    3909     {
    3910         SVGA3dCmdEnableGart *pCmd = (SVGA3dCmdEnableGart *)pvCmd;
    3911         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3912         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3913         break;
    3914     }
    3915 
    3916     case SVGA_3D_CMD_DISABLE_GART:
    3917     {
    3918         /* No corresponding SVGA3dCmd structure. */
    3919         VMSVGA_3D_CMD_NOTIMPL();
    3920         break;
    3921     }
    3922 
    3923     case SVGA_3D_CMD_MAP_MOB_INTO_GART:
    3924     {
    3925         SVGA3dCmdMapMobIntoGart *pCmd = (SVGA3dCmdMapMobIntoGart *)pvCmd;
    3926         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3927         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3928         break;
    3929     }
    3930 
    3931     case SVGA_3D_CMD_UNMAP_GART_RANGE:
    3932     {
    3933         SVGA3dCmdUnmapGartRange *pCmd = (SVGA3dCmdUnmapGartRange *)pvCmd;
    3934         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3935         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3936         break;
    3937     }
    3938 
    3939     case SVGA_3D_CMD_DEFINE_GB_SCREENTARGET:
    3940     {
    3941         SVGA3dCmdDefineGBScreenTarget *pCmd = (SVGA3dCmdDefineGBScreenTarget *)pvCmd;
    3942         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3943         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3944         break;
    3945     }
    3946 
    3947     case SVGA_3D_CMD_DESTROY_GB_SCREENTARGET:
    3948     {
    3949         SVGA3dCmdDestroyGBScreenTarget *pCmd = (SVGA3dCmdDestroyGBScreenTarget *)pvCmd;
    3950         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3951         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3952         break;
    3953     }
    3954 
    3955     case SVGA_3D_CMD_BIND_GB_SCREENTARGET:
    3956     {
    3957         SVGA3dCmdBindGBScreenTarget *pCmd = (SVGA3dCmdBindGBScreenTarget *)pvCmd;
    3958         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3959         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3960         break;
    3961     }
    3962 
    3963     case SVGA_3D_CMD_UPDATE_GB_SCREENTARGET:
    3964     {
    3965         SVGA3dCmdUpdateGBScreenTarget *pCmd = (SVGA3dCmdUpdateGBScreenTarget *)pvCmd;
    3966         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3967         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3968         break;
    3969     }
    3970 
    3971     case SVGA_3D_CMD_READBACK_GB_IMAGE_PARTIAL:
    3972     {
    3973         SVGA3dCmdReadbackGBImagePartial *pCmd = (SVGA3dCmdReadbackGBImagePartial *)pvCmd;
    3974         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3975         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3976         break;
    3977     }
    3978 
    3979     case SVGA_3D_CMD_INVALIDATE_GB_IMAGE_PARTIAL:
    3980     {
    3981         SVGA3dCmdInvalidateGBImagePartial *pCmd = (SVGA3dCmdInvalidateGBImagePartial *)pvCmd;
    3982         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3983         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3984         break;
    3985     }
    3986 
    3987     case SVGA_3D_CMD_SET_GB_SHADERCONSTS_INLINE:
    3988     {
    3989         SVGA3dCmdSetGBShaderConstInline *pCmd = (SVGA3dCmdSetGBShaderConstInline *)pvCmd;
    3990         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3991         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    3992         break;
    3993     }
    3994 
    3995     case SVGA_3D_CMD_GB_SCREEN_DMA:
    3996     {
    3997         SVGA3dCmdGBScreenDMA *pCmd = (SVGA3dCmdGBScreenDMA *)pvCmd;
    3998         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    3999         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    4000         break;
    4001     }
    4002 
    4003     case SVGA_3D_CMD_BIND_GB_SURFACE_WITH_PITCH:
    4004     {
    4005         SVGA3dCmdBindGBSurfaceWithPitch *pCmd = (SVGA3dCmdBindGBSurfaceWithPitch *)pvCmd;
    4006         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    4007         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    4008         break;
    4009     }
    4010 
    4011     case SVGA_3D_CMD_GB_MOB_FENCE:
    4012     {
    4013         SVGA3dCmdGBMobFence *pCmd = (SVGA3dCmdGBMobFence *)pvCmd;
    4014         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    4015         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    4016         break;
    4017     }
    4018 
    4019     case SVGA_3D_CMD_DEFINE_GB_SURFACE_V2:
    4020     {
    4021         /// @todo SVGA3dCmdDefineGBSurface_v2 is not defined in Mesa 17 header. Mesa 20 has it.
    4022         //SVGA3dCmdDefineGBSurface_v2 *pCmd = (SVGA3dCmdDefineGBSurface_v2 *)pvCmd;
    4023         //VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    4024         VMSVGA_3D_CMD_NOTIMPL();
    4025         break;
    4026     }
    4027 
    4028     case SVGA_3D_CMD_DEFINE_GB_MOB64:
    4029     {
    4030         SVGA3dCmdDefineGBMob64 *pCmd = (SVGA3dCmdDefineGBMob64 *)pvCmd;
    4031         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    4032         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    4033         break;
    4034     }
    4035 
    4036     case SVGA_3D_CMD_REDEFINE_GB_MOB64:
    4037     {
    4038         SVGA3dCmdRedefineGBMob64 *pCmd = (SVGA3dCmdRedefineGBMob64 *)pvCmd;
    4039         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    4040         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    4041         break;
    4042     }
    4043 
    4044     case SVGA_3D_CMD_NOP_ERROR:
    4045     {
    4046         /* Apparently there is nothing to do. */
    4047         break;
    4048     }
    4049 
    4050     case SVGA_3D_CMD_SET_VERTEX_STREAMS:
    4051     {
    4052         SVGA3dCmdSetVertexStreams *pCmd = (SVGA3dCmdSetVertexStreams *)pvCmd;
    4053         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    4054         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    4055         break;
    4056     }
    4057 
    4058     case SVGA_3D_CMD_SET_VERTEX_DECLS:
    4059     {
    4060         SVGA3dCmdSetVertexDecls *pCmd = (SVGA3dCmdSetVertexDecls *)pvCmd;
    4061         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    4062         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    4063         break;
    4064     }
    4065 
    4066     case SVGA_3D_CMD_SET_VERTEX_DIVISORS:
    4067     {
    4068         SVGA3dCmdSetVertexDivisors *pCmd = (SVGA3dCmdSetVertexDivisors *)pvCmd;
    4069         VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
    4070         VMSVGA_3D_CMD_NOTIMPL(); RT_NOREF(pCmd);
    4071         break;
    4072     }
    4073 
    4074     case SVGA_3D_CMD_DRAW:
    4075     {
    4076         /* No corresponding SVGA3dCmd structure. */
    4077         VMSVGA_3D_CMD_NOTIMPL();
    4078         break;
    4079     }
    4080 
    4081     case SVGA_3D_CMD_DRAW_INDEXED:
    4082     {
    4083         /* No corresponding SVGA3dCmd structure. */
    4084         VMSVGA_3D_CMD_NOTIMPL();
    4085         break;
    4086     }
    4087 
    4088     default:
    4089         STAM_REL_COUNTER_INC(&pSvgaR3State->StatFifoUnkCmds);
    4090         ASSERT_GUEST_MSG_FAILED(("enmCmdId=%d\n", enmCmdId));
    4091         rcParse = VERR_NOT_IMPLEMENTED;
    4092         break;
    4093     }
    4094 
    4095     return rcParse;
    4096 }
    4097 #  undef VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK
    4098 # endif // VBOX_WITH_VMSVGA3D
    4099 
    4100 
    4101 /*
    4102  *
    4103  * Handlers for FIFO commands.
    4104  *
    4105  * Every handler takes the following parameters:
    4106  *
    4107  *    pThis               The shared VGA/VMSVGA state.
    4108  *    pThisCC             The VGA/VMSVGA state for ring-3.
    4109  *    pCmd                The command data.
    4110  */
    4111 
    4112 
    4113 /* SVGA_CMD_UPDATE */
    4114 static void vmsvgaR3CmdUpdate(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdUpdate const *pCmd)
    4115 {
    4116     RT_NOREF(pThis);
    4117     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    4118 
    4119     STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdUpdate);
    4120     Log(("SVGA_CMD_UPDATE %d,%d %dx%d\n", pCmd->x, pCmd->y, pCmd->width, pCmd->height));
    4121 
    4122     /** @todo Multiple screens? */
    4123     VMSVGASCREENOBJECT *pScreen = vmsvgaR3GetScreenObject(pThisCC, 0);
    4124     if (!pScreen) /* Can happen if screen is not defined (aScreens[idScreen].fDefined == false) yet. */
    4125         return;
    4126 
    4127     vmsvgaR3UpdateScreen(pThisCC, pScreen, pCmd->x, pCmd->y, pCmd->width, pCmd->height);
    4128 }
    4129 
    4130 
    4131 /* SVGA_CMD_UPDATE_VERBOSE */
    4132 static void vmsvgaR3CmdUpdateVerbose(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdUpdateVerbose const *pCmd)
    4133 {
    4134     RT_NOREF(pThis);
    4135     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    4136 
    4137     STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdUpdateVerbose);
    4138     Log(("SVGA_CMD_UPDATE_VERBOSE %d,%d %dx%d reason %#x\n", pCmd->x, pCmd->y, pCmd->width, pCmd->height, pCmd->reason));
    4139 
    4140     /** @todo Multiple screens? */
    4141     VMSVGASCREENOBJECT *pScreen = vmsvgaR3GetScreenObject(pThisCC, 0);
    4142     if (!pScreen) /* Can happen if screen is not defined (aScreens[idScreen].fDefined == false) yet. */
    4143         return;
    4144 
    4145     vmsvgaR3UpdateScreen(pThisCC, pScreen, pCmd->x, pCmd->y, pCmd->width, pCmd->height);
    4146 }
    4147 
    4148 
    4149 /* SVGA_CMD_RECT_FILL */
    4150 static void vmsvgaR3CmdRectFill(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdRectFill const *pCmd)
    4151 {
    4152     RT_NOREF(pThis, pCmd);
    4153     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    4154 
    4155     STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdRectFill);
    4156     Log(("SVGA_CMD_RECT_FILL %08X @ %d,%d (%dx%d)\n", pCmd->pixel, pCmd->destX, pCmd->destY, pCmd->width, pCmd->height));
    4157     LogRelMax(4, ("VMSVGA: Unsupported SVGA_CMD_RECT_FILL command ignored.\n"));
    4158 }
    4159 
    4160 
    4161 /* SVGA_CMD_RECT_COPY */
    4162 static void vmsvgaR3CmdRectCopy(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdRectCopy const *pCmd)
    4163 {
    4164     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    4165 
    4166     STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdRectCopy);
    4167     Log(("SVGA_CMD_RECT_COPY %d,%d -> %d,%d %dx%d\n", pCmd->srcX, pCmd->srcY, pCmd->destX, pCmd->destY, pCmd->width, pCmd->height));
    4168 
    4169     VMSVGASCREENOBJECT *pScreen = vmsvgaR3GetScreenObject(pThisCC, 0);
    4170     AssertPtrReturnVoid(pScreen);
    4171 
    4172     /* Check that arguments aren't complete junk. A precise check is done in vmsvgaR3RectCopy(). */
    4173     ASSERT_GUEST_RETURN_VOID(pCmd->srcX < pThis->svga.u32MaxWidth);
    4174     ASSERT_GUEST_RETURN_VOID(pCmd->destX < pThis->svga.u32MaxWidth);
    4175     ASSERT_GUEST_RETURN_VOID(pCmd->width < pThis->svga.u32MaxWidth);
    4176     ASSERT_GUEST_RETURN_VOID(pCmd->srcY < pThis->svga.u32MaxHeight);
    4177     ASSERT_GUEST_RETURN_VOID(pCmd->destY < pThis->svga.u32MaxHeight);
    4178     ASSERT_GUEST_RETURN_VOID(pCmd->height < pThis->svga.u32MaxHeight);
    4179 
    4180     vmsvgaR3RectCopy(pThisCC, pScreen, pCmd->srcX, pCmd->srcY, pCmd->destX, pCmd->destY,
    4181                      pCmd->width, pCmd->height, pThis->vram_size);
    4182     vmsvgaR3UpdateScreen(pThisCC, pScreen, pCmd->destX, pCmd->destY, pCmd->width, pCmd->height);
    4183 }
    4184 
    4185 
    4186 /* SVGA_CMD_RECT_ROP_COPY */
    4187 static void vmsvgaR3CmdRectRopCopy(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdRectRopCopy const *pCmd)
    4188 {
    4189     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    4190 
    4191     STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdRectRopCopy);
    4192     Log(("SVGA_CMD_RECT_ROP_COPY %d,%d -> %d,%d %dx%d ROP %#X\n", pCmd->srcX, pCmd->srcY, pCmd->destX, pCmd->destY, pCmd->width, pCmd->height, pCmd->rop));
    4193 
    4194     if (pCmd->rop != SVGA_ROP_COPY)
    4195     {
    4196         /* We only support the plain copy ROP which makes SVGA_CMD_RECT_ROP_COPY exactly the same
    4197          * as SVGA_CMD_RECT_COPY. XFree86 4.1.0 and 4.2.0 drivers (driver version 10.4.0 and 10.7.0,
    4198          * respectively) issue SVGA_CMD_RECT_ROP_COPY when SVGA_CAP_RECT_COPY is present even when
    4199          * SVGA_CAP_RASTER_OP is not. However, the ROP will always be SVGA_ROP_COPY.
    4200          */
    4201         LogRelMax(4, ("VMSVGA: SVGA_CMD_RECT_ROP_COPY %d,%d -> %d,%d (%dx%d) ROP %X unsupported\n",
    4202                       pCmd->srcX, pCmd->srcY, pCmd->destX, pCmd->destY, pCmd->width, pCmd->height, pCmd->rop));
    4203         return;
    4204     }
    4205 
    4206     VMSVGASCREENOBJECT *pScreen = vmsvgaR3GetScreenObject(pThisCC, 0);
    4207     AssertPtrReturnVoid(pScreen);
    4208 
    4209     /* Check that arguments aren't complete junk. A precise check is done in vmsvgaR3RectCopy(). */
    4210     ASSERT_GUEST_RETURN_VOID(pCmd->srcX < pThis->svga.u32MaxWidth);
    4211     ASSERT_GUEST_RETURN_VOID(pCmd->destX < pThis->svga.u32MaxWidth);
    4212     ASSERT_GUEST_RETURN_VOID(pCmd->width < pThis->svga.u32MaxWidth);
    4213     ASSERT_GUEST_RETURN_VOID(pCmd->srcY < pThis->svga.u32MaxHeight);
    4214     ASSERT_GUEST_RETURN_VOID(pCmd->destY < pThis->svga.u32MaxHeight);
    4215     ASSERT_GUEST_RETURN_VOID(pCmd->height < pThis->svga.u32MaxHeight);
    4216 
    4217     vmsvgaR3RectCopy(pThisCC, pScreen, pCmd->srcX, pCmd->srcY, pCmd->destX, pCmd->destY,
    4218                      pCmd->width, pCmd->height, pThis->vram_size);
    4219     vmsvgaR3UpdateScreen(pThisCC, pScreen, pCmd->destX, pCmd->destY, pCmd->width, pCmd->height);
    4220 }
    4221 
    4222 
    4223 /* SVGA_CMD_DISPLAY_CURSOR */
    4224 static void vmsvgaR3CmdDisplayCursor(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDisplayCursor const *pCmd)
    4225 {
    4226     RT_NOREF(pThis, pCmd);
    4227     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    4228 
    4229     STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdDisplayCursor);
    4230     Log(("SVGA_CMD_DISPLAY_CURSOR id=%d state=%d\n", pCmd->id, pCmd->state));
    4231     LogRelMax(4, ("VMSVGA: Unsupported SVGA_CMD_DISPLAY_CURSOR command ignored.\n"));
    4232 }
    4233 
    4234 
    4235 /* SVGA_CMD_MOVE_CURSOR */
    4236 static void vmsvgaR3CmdMoveCursor(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdMoveCursor const *pCmd)
    4237 {
    4238     RT_NOREF(pThis, pCmd);
    4239     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    4240 
    4241     STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdMoveCursor);
    4242     Log(("SVGA_CMD_MOVE_CURSOR to %d,%d\n", pCmd->pos.x, pCmd->pos.y));
    4243     LogRelMax(4, ("VMSVGA: Unsupported SVGA_CMD_MOVE_CURSOR command ignored.\n"));
    4244 }
    4245 
    4246 
    4247 /* SVGA_CMD_DEFINE_CURSOR */
    4248 static void vmsvgaR3CmdDefineCursor(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineCursor const *pCmd)
    4249 {
    4250     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    4251 
    4252     STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdDefineCursor);
    4253     Log(("SVGA_CMD_DEFINE_CURSOR id=%d size (%dx%d) hotspot (%d,%d) andMaskDepth=%d xorMaskDepth=%d\n",
    4254              pCmd->id, pCmd->width, pCmd->height, pCmd->hotspotX, pCmd->hotspotY, pCmd->andMaskDepth, pCmd->xorMaskDepth));
    4255 
    4256     ASSERT_GUEST_RETURN_VOID(pCmd->height < 2048 && pCmd->width < 2048);
    4257     ASSERT_GUEST_RETURN_VOID(pCmd->andMaskDepth <= 32);
    4258     ASSERT_GUEST_RETURN_VOID(pCmd->xorMaskDepth <= 32);
    4259     RT_UNTRUSTED_VALIDATED_FENCE();
    4260 
    4261     uint32_t const cbSrcAndLine = RT_ALIGN_32(pCmd->width * (pCmd->andMaskDepth + (pCmd->andMaskDepth == 15)), 32) / 8;
    4262     uint32_t const cbSrcAndMask = cbSrcAndLine * pCmd->height;
    4263     uint32_t const cbSrcXorLine = RT_ALIGN_32(pCmd->width * (pCmd->xorMaskDepth + (pCmd->xorMaskDepth == 15)), 32) / 8;
    4264 
    4265     uint8_t const *pbSrcAndMask = (uint8_t const *)(pCmd + 1);
    4266     uint8_t const *pbSrcXorMask = (uint8_t const *)(pCmd + 1) + cbSrcAndMask;
    4267 
    4268     uint32_t const cx = pCmd->width;
    4269     uint32_t const cy = pCmd->height;
    4270 
    4271     /*
    4272      * Convert the input to 1-bit AND mask and a 32-bit BRGA XOR mask.
    4273      * The AND data uses 8-bit aligned scanlines.
    4274      * The XOR data must be starting on a 32-bit boundrary.
    4275      */
    4276     uint32_t cbDstAndLine = RT_ALIGN_32(cx, 8) / 8;
    4277     uint32_t cbDstAndMask = cbDstAndLine          * cy;
    4278     uint32_t cbDstXorMask = cx * sizeof(uint32_t) * cy;
    4279     uint32_t cbCopy = RT_ALIGN_32(cbDstAndMask, 4) + cbDstXorMask;
    4280 
    4281     uint8_t *pbCopy = (uint8_t *)RTMemAlloc(cbCopy);
    4282     AssertReturnVoid(pbCopy);
    4283 
    4284     /* Convert the AND mask. */
    4285     uint8_t       *pbDst     = pbCopy;
    4286     uint8_t const *pbSrc     = pbSrcAndMask;
    4287     switch (pCmd->andMaskDepth)
    4288     {
    4289         case 1:
    4290             if (cbSrcAndLine == cbDstAndLine)
    4291                 memcpy(pbDst, pbSrc, cbSrcAndLine * cy);
    4292             else
    4293             {
    4294                 Assert(cbSrcAndLine > cbDstAndLine); /* lines are dword alined in source, but only byte in destination. */
    4295                 for (uint32_t y = 0; y < cy; y++)
    4296                 {
    4297                     memcpy(pbDst, pbSrc, cbDstAndLine);
    4298                     pbDst += cbDstAndLine;
    4299                     pbSrc += cbSrcAndLine;
    4300                 }
    4301             }
    4302             break;
    4303         /* Should take the XOR mask into account for the multi-bit AND mask. */
    4304         case 8:
    4305             for (uint32_t y = 0; y < cy; y++)
    4306             {
    4307                 for (uint32_t x = 0; x < cx; )
    4308                 {
    4309                     uint8_t bDst = 0;
    4310                     uint8_t fBit = 0x80;
    4311                     do
    4312                     {
    4313                         uintptr_t const idxPal = pbSrc[x] * 3;
    4314                         if (((   pThis->last_palette[idxPal]
    4315                               | (pThis->last_palette[idxPal] >>  8)
    4316                               | (pThis->last_palette[idxPal] >> 16)) & 0xff) > 0xfc)
    4317                             bDst |= fBit;
    4318                         fBit >>= 1;
    4319                         x++;
    4320                     } while (x < cx && (x & 7));
    4321                     pbDst[(x - 1) / 8] = bDst;
    4322                 }
    4323                 pbDst += cbDstAndLine;
    4324                 pbSrc += cbSrcAndLine;
    4325             }
    4326             break;
    4327         case 15:
    4328             for (uint32_t y = 0; y < cy; y++)
    4329             {
    4330                 for (uint32_t x = 0; x < cx; )
    4331                 {
    4332                     uint8_t bDst = 0;
    4333                     uint8_t fBit = 0x80;
    4334                     do
    4335                     {
    4336                         if ((pbSrc[x * 2] | (pbSrc[x * 2 + 1] & 0x7f)) >= 0xfc)
    4337                             bDst |= fBit;
    4338                         fBit >>= 1;
    4339                         x++;
    4340                     } while (x < cx && (x & 7));
    4341                     pbDst[(x - 1) / 8] = bDst;
    4342                 }
    4343                 pbDst += cbDstAndLine;
    4344                 pbSrc += cbSrcAndLine;
    4345             }
    4346             break;
    4347         case 16:
    4348             for (uint32_t y = 0; y < cy; y++)
    4349             {
    4350                 for (uint32_t x = 0; x < cx; )
    4351                 {
    4352                     uint8_t bDst = 0;
    4353                     uint8_t fBit = 0x80;
    4354                     do
    4355                     {
    4356                         if ((pbSrc[x * 2] | pbSrc[x * 2 + 1]) >= 0xfc)
    4357                             bDst |= fBit;
    4358                         fBit >>= 1;
    4359                         x++;
    4360                     } while (x < cx && (x & 7));
    4361                     pbDst[(x - 1) / 8] = bDst;
    4362                 }
    4363                 pbDst += cbDstAndLine;
    4364                 pbSrc += cbSrcAndLine;
    4365             }
    4366             break;
    4367         case 24:
    4368             for (uint32_t y = 0; y < cy; y++)
    4369             {
    4370                 for (uint32_t x = 0; x < cx; )
    4371                 {
    4372                     uint8_t bDst = 0;
    4373                     uint8_t fBit = 0x80;
    4374                     do
    4375                     {
    4376                         if ((pbSrc[x * 3] | pbSrc[x * 3 + 1] | pbSrc[x * 3 + 2]) >= 0xfc)
    4377                             bDst |= fBit;
    4378                         fBit >>= 1;
    4379                         x++;
    4380                     } while (x < cx && (x & 7));
    4381                     pbDst[(x - 1) / 8] = bDst;
    4382                 }
    4383                 pbDst += cbDstAndLine;
    4384                 pbSrc += cbSrcAndLine;
    4385             }
    4386             break;
    4387         case 32:
    4388             for (uint32_t y = 0; y < cy; y++)
    4389             {
    4390                 for (uint32_t x = 0; x < cx; )
    4391                 {
    4392                     uint8_t bDst = 0;
    4393                     uint8_t fBit = 0x80;
    4394                     do
    4395                     {
    4396                         if ((pbSrc[x * 4] | pbSrc[x * 4 + 1] | pbSrc[x * 4 + 2] | pbSrc[x * 4 + 3]) >= 0xfc)
    4397                             bDst |= fBit;
    4398                         fBit >>= 1;
    4399                         x++;
    4400                     } while (x < cx && (x & 7));
    4401                     pbDst[(x - 1) / 8] = bDst;
    4402                 }
    4403                 pbDst += cbDstAndLine;
    4404                 pbSrc += cbSrcAndLine;
    4405             }
    4406             break;
    4407         default:
    4408             RTMemFreeZ(pbCopy, cbCopy);
    4409             AssertFailedReturnVoid();
    4410     }
    4411 
    4412     /* Convert the XOR mask. */
    4413     uint32_t *pu32Dst = (uint32_t *)(pbCopy + RT_ALIGN_32(cbDstAndMask, 4));
    4414     pbSrc  = pbSrcXorMask;
    4415     switch (pCmd->xorMaskDepth)
    4416     {
    4417         case 1:
    4418             for (uint32_t y = 0; y < cy; y++)
    4419             {
    4420                 for (uint32_t x = 0; x < cx; )
    4421                 {
    4422                     /* most significant bit is the left most one. */
    4423                     uint8_t bSrc = pbSrc[x / 8];
    4424                     do
    4425                     {
    4426                         *pu32Dst++ = bSrc & 0x80 ? UINT32_C(0x00ffffff) : 0;
    4427                         bSrc <<= 1;
    4428                         x++;
    4429                     } while ((x & 7) && x < cx);
    4430                 }
    4431                 pbSrc += cbSrcXorLine;
    4432             }
    4433             break;
    4434         case 8:
    4435             for (uint32_t y = 0; y < cy; y++)
    4436             {
    4437                 for (uint32_t x = 0; x < cx; x++)
    4438                 {
    4439                     uint32_t u = pThis->last_palette[pbSrc[x]];
    4440                     *pu32Dst++ = u;//RT_MAKE_U32_FROM_U8(RT_BYTE1(u), RT_BYTE2(u), RT_BYTE3(u), 0);
    4441                 }
    4442                 pbSrc += cbSrcXorLine;
    4443             }
    4444             break;
    4445         case 15: /* Src: RGB-5-5-5 */
    4446             for (uint32_t y = 0; y < cy; y++)
    4447             {
    4448                 for (uint32_t x = 0; x < cx; x++)
    4449                 {
    4450                     uint32_t const uValue = RT_MAKE_U16(pbSrc[x * 2], pbSrc[x * 2 + 1]);
    4451                     *pu32Dst++ = RT_MAKE_U32_FROM_U8(( uValue        & 0x1f) << 3,
    4452                                                      ((uValue >>  5) & 0x1f) << 3,
    4453                                                      ((uValue >> 10) & 0x1f) << 3, 0);
    4454                 }
    4455                 pbSrc += cbSrcXorLine;
    4456             }
    4457             break;
    4458         case 16: /* Src: RGB-5-6-5 */
    4459             for (uint32_t y = 0; y < cy; y++)
    4460             {
    4461                 for (uint32_t x = 0; x < cx; x++)
    4462                 {
    4463                     uint32_t const uValue = RT_MAKE_U16(pbSrc[x * 2], pbSrc[x * 2 + 1]);
    4464                     *pu32Dst++ = RT_MAKE_U32_FROM_U8(( uValue        & 0x1f) << 3,
    4465                                                      ((uValue >>  5) & 0x3f) << 2,
    4466                                                      ((uValue >> 11) & 0x1f) << 3, 0);
    4467                 }
    4468                 pbSrc += cbSrcXorLine;
    4469             }
    4470             break;
    4471         case 24:
    4472             for (uint32_t y = 0; y < cy; y++)
    4473             {
    4474                 for (uint32_t x = 0; x < cx; x++)
    4475                     *pu32Dst++ = RT_MAKE_U32_FROM_U8(pbSrc[x*3], pbSrc[x*3 + 1], pbSrc[x*3 + 2], 0);
    4476                 pbSrc += cbSrcXorLine;
    4477             }
    4478             break;
    4479         case 32:
    4480             for (uint32_t y = 0; y < cy; y++)
    4481             {
    4482                 for (uint32_t x = 0; x < cx; x++)
    4483                     *pu32Dst++ = RT_MAKE_U32_FROM_U8(pbSrc[x*4], pbSrc[x*4 + 1], pbSrc[x*4 + 2], 0);
    4484                 pbSrc += cbSrcXorLine;
    4485             }
    4486             break;
    4487         default:
    4488             RTMemFreeZ(pbCopy, cbCopy);
    4489             AssertFailedReturnVoid();
    4490     }
    4491 
    4492     /*
    4493      * Pass it to the frontend/whatever.
    4494      */
    4495     vmsvgaR3InstallNewCursor(pThisCC, pSvgaR3State, false /*fAlpha*/, pCmd->hotspotX, pCmd->hotspotY,
    4496                              cx, cy, pbCopy, cbCopy);
    4497 }
    4498 
    4499 
    4500 /* SVGA_CMD_DEFINE_ALPHA_CURSOR */
    4501 static void vmsvgaR3CmdDefineAlphaCursor(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineAlphaCursor const *pCmd)
    4502 {
    4503     RT_NOREF(pThis);
    4504     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    4505 
    4506     STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdDefineAlphaCursor);
    4507     Log(("VMSVGA cmd: SVGA_CMD_DEFINE_ALPHA_CURSOR id=%d size (%dx%d) hotspot (%d,%d)\n", pCmd->id, pCmd->width, pCmd->height, pCmd->hotspotX, pCmd->hotspotY));
    4508 
    4509     /* Check against a reasonable upper limit to prevent integer overflows in the sanity checks below. */
    4510     ASSERT_GUEST_RETURN_VOID(pCmd->height < 2048 && pCmd->width < 2048);
    4511     RT_UNTRUSTED_VALIDATED_FENCE();
    4512 
    4513     /* The mouse pointer interface always expects an AND mask followed by the color data (XOR mask). */
    4514     uint32_t cbAndMask     = (pCmd->width + 7) / 8 * pCmd->height;          /* size of the AND mask */
    4515     cbAndMask              = ((cbAndMask + 3) & ~3);                        /* + gap for alignment */
    4516     uint32_t cbXorMask     = pCmd->width * sizeof(uint32_t) * pCmd->height; /* + size of the XOR mask (32-bit BRGA format) */
    4517     uint32_t cbCursorShape = cbAndMask + cbXorMask;
    4518 
    4519     uint8_t *pCursorCopy = (uint8_t *)RTMemAlloc(cbCursorShape);
    4520     AssertPtrReturnVoid(pCursorCopy);
    4521 
    4522     /* Transparency is defined by the alpha bytes, so make the whole bitmap visible. */
    4523     memset(pCursorCopy, 0xff, cbAndMask);
    4524     /* Colour data */
    4525     memcpy(pCursorCopy + cbAndMask, pCmd + 1, cbXorMask);
    4526 
    4527     vmsvgaR3InstallNewCursor(pThisCC, pSvgaR3State, true /*fAlpha*/, pCmd->hotspotX, pCmd->hotspotY,
    4528                              pCmd->width, pCmd->height, pCursorCopy, cbCursorShape);
    4529 }
    4530 
    4531 
    4532 /* SVGA_CMD_ESCAPE */
    4533 static void vmsvgaR3CmdEscape(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdEscape const *pCmd)
    4534 {
    4535     RT_NOREF(pThis);
    4536     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    4537 
    4538     STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdEscape);
    4539 
    4540     if (pCmd->nsid == SVGA_ESCAPE_NSID_VMWARE)
    4541     {
    4542         ASSERT_GUEST_RETURN_VOID(pCmd->size >= sizeof(uint32_t));
    4543         RT_UNTRUSTED_VALIDATED_FENCE();
    4544 
    4545         uint32_t const cmd = *(uint32_t *)(pCmd + 1);
    4546         Log(("SVGA_CMD_ESCAPE (%#x %#x) VMWARE cmd=%#x\n", pCmd->nsid, pCmd->size, cmd));
    4547 
    4548         switch (cmd)
    4549         {
    4550             case SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS:
    4551             {
    4552                 SVGAEscapeVideoSetRegs *pVideoCmd = (SVGAEscapeVideoSetRegs *)(pCmd + 1);
    4553                 ASSERT_GUEST_RETURN_VOID(pCmd->size >= sizeof(pVideoCmd->header));
    4554                 RT_UNTRUSTED_VALIDATED_FENCE();
    4555 
    4556                 uint32_t const cRegs = (pCmd->size - sizeof(pVideoCmd->header)) / sizeof(pVideoCmd->items[0]);
    4557 
    4558                 Log(("SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS: stream %#x\n", pVideoCmd->header.streamId));
    4559                 for (uint32_t iReg = 0; iReg < cRegs; iReg++)
    4560                     Log(("SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS: reg %#x val %#x\n", pVideoCmd->items[iReg].registerId, pVideoCmd->items[iReg].value));
    4561                 RT_NOREF_PV(pVideoCmd);
    4562                 break;
    4563             }
    4564 
    4565             case SVGA_ESCAPE_VMWARE_VIDEO_FLUSH:
    4566             {
    4567                 SVGAEscapeVideoFlush *pVideoCmd = (SVGAEscapeVideoFlush *)(pCmd + 1);
    4568                 ASSERT_GUEST_RETURN_VOID(pCmd->size >= sizeof(*pVideoCmd));
    4569                 Log(("SVGA_ESCAPE_VMWARE_VIDEO_FLUSH: stream %#x\n", pVideoCmd->streamId));
    4570                 RT_NOREF_PV(pVideoCmd);
    4571                 break;
    4572             }
    4573 
    4574             default:
    4575                 Log(("SVGA_CMD_ESCAPE: Unknown vmware escape: %#x\n", cmd));
    4576                 break;
    4577         }
    4578     }
    4579     else
    4580         Log(("SVGA_CMD_ESCAPE %#x %#x\n", pCmd->nsid, pCmd->size));
    4581 }
    4582 
    4583 
    4584 /* SVGA_CMD_DEFINE_SCREEN */
    4585 static void vmsvgaR3CmdDefineScreen(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineScreen const *pCmd)
    4586 {
    4587     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    4588 
    4589     STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdDefineScreen);
    4590     Log(("SVGA_CMD_DEFINE_SCREEN id=%x flags=%x size=(%d,%d) root=(%d,%d) %d:0x%x 0x%x\n",
    4591              pCmd->screen.id, pCmd->screen.flags, pCmd->screen.size.width, pCmd->screen.size.height, pCmd->screen.root.x, pCmd->screen.root.y,
    4592              pCmd->screen.backingStore.ptr.gmrId, pCmd->screen.backingStore.ptr.offset, pCmd->screen.backingStore.pitch));
    4593 
    4594     uint32_t const idScreen = pCmd->screen.id;
    4595     ASSERT_GUEST_RETURN_VOID(idScreen < RT_ELEMENTS(pSvgaR3State->aScreens));
    4596 
    4597     uint32_t const uWidth = pCmd->screen.size.width;
    4598     ASSERT_GUEST_RETURN_VOID(uWidth <= pThis->svga.u32MaxWidth);
    4599 
    4600     uint32_t const uHeight = pCmd->screen.size.height;
    4601     ASSERT_GUEST_RETURN_VOID(uHeight <= pThis->svga.u32MaxHeight);
    4602 
    4603     uint32_t const cbWidth = uWidth * ((32 + 7) / 8); /** @todo 32? */
    4604     uint32_t const cbPitch = pCmd->screen.backingStore.pitch ? pCmd->screen.backingStore.pitch : cbWidth;
    4605     ASSERT_GUEST_RETURN_VOID(cbWidth <= cbPitch);
    4606 
    4607     uint32_t const uScreenOffset = pCmd->screen.backingStore.ptr.offset;
    4608     ASSERT_GUEST_RETURN_VOID(uScreenOffset < pThis->vram_size);
    4609 
    4610     uint32_t const cbVram = pThis->vram_size - uScreenOffset;
    4611     /* If we have a not zero pitch, then height can't exceed the available VRAM. */
    4612     ASSERT_GUEST_RETURN_VOID(   (uHeight == 0 && cbPitch == 0)
    4613                              || (cbPitch > 0 && uHeight <= cbVram / cbPitch));
    4614     RT_UNTRUSTED_VALIDATED_FENCE();
    4615 
    4616     VMSVGASCREENOBJECT *pScreen = &pSvgaR3State->aScreens[idScreen];
    4617     pScreen->fDefined  = true;
    4618     pScreen->fModified = true;
    4619     pScreen->fuScreen  = pCmd->screen.flags;
    4620     pScreen->idScreen  = idScreen;
    4621     if (!RT_BOOL(pCmd->screen.flags & (SVGA_SCREEN_DEACTIVATE | SVGA_SCREEN_BLANKING)))
    4622     {
    4623         /* Not blanked. */
    4624         ASSERT_GUEST_RETURN_VOID(uWidth > 0 && uHeight > 0);
    4625         RT_UNTRUSTED_VALIDATED_FENCE();
    4626 
    4627         pScreen->xOrigin = pCmd->screen.root.x;
    4628         pScreen->yOrigin = pCmd->screen.root.y;
    4629         pScreen->cWidth  = uWidth;
    4630         pScreen->cHeight = uHeight;
    4631         pScreen->offVRAM = uScreenOffset;
    4632         pScreen->cbPitch = cbPitch;
    4633         pScreen->cBpp    = 32;
    4634     }
    4635     else
    4636     {
    4637         /* Screen blanked. Keep old values. */
    4638     }
    4639 
    4640     pThis->svga.fGFBRegisters = false;
    4641     vmsvgaR3ChangeMode(pThis, pThisCC);
    4642 
    4643 # ifdef VBOX_WITH_VMSVGA3D
    4644     if (RT_LIKELY(pThis->svga.f3DEnabled))
    4645         vmsvga3dDefineScreen(pThis, pThisCC, pScreen);
    4646 # endif
    4647 }
    4648 
    4649 
    4650 /* SVGA_CMD_DESTROY_SCREEN */
    4651 static void vmsvgaR3CmdDestroyScreen(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDestroyScreen const *pCmd)
    4652 {
    4653     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    4654 
    4655     STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdDestroyScreen);
    4656     Log(("SVGA_CMD_DESTROY_SCREEN id=%x\n", pCmd->screenId));
    4657 
    4658     uint32_t const idScreen = pCmd->screenId;
    4659     ASSERT_GUEST_RETURN_VOID(idScreen < RT_ELEMENTS(pSvgaR3State->aScreens));
    4660     RT_UNTRUSTED_VALIDATED_FENCE();
    4661 
    4662     VMSVGASCREENOBJECT *pScreen = &pSvgaR3State->aScreens[idScreen];
    4663     pScreen->fModified = true;
    4664     pScreen->fDefined  = false;
    4665     pScreen->idScreen  = idScreen;
    4666 
    4667 # ifdef VBOX_WITH_VMSVGA3D
    4668     if (RT_LIKELY(pThis->svga.f3DEnabled))
    4669         vmsvga3dDestroyScreen(pThisCC, pScreen);
    4670 # endif
    4671     vmsvgaR3ChangeMode(pThis, pThisCC);
    4672 }
    4673 
    4674 
    4675 /* SVGA_CMD_DEFINE_GMRFB */
    4676 static void vmsvgaR3CmdDefineGMRFB(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineGMRFB const *pCmd)
    4677 {
    4678     RT_NOREF(pThis);
    4679     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    4680 
    4681     STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdDefineGmrFb);
    4682     Log(("SVGA_CMD_DEFINE_GMRFB gmr=%x offset=%x bytesPerLine=%x bpp=%d color depth=%d\n",
    4683              pCmd->ptr.gmrId, pCmd->ptr.offset, pCmd->bytesPerLine, pCmd->format.bitsPerPixel, pCmd->format.colorDepth));
    4684 
    4685     pSvgaR3State->GMRFB.ptr          = pCmd->ptr;
    4686     pSvgaR3State->GMRFB.bytesPerLine = pCmd->bytesPerLine;
    4687     pSvgaR3State->GMRFB.format       = pCmd->format;
    4688 }
    4689 
    4690 
    4691 /* SVGA_CMD_BLIT_GMRFB_TO_SCREEN */
    4692 static void vmsvgaR3CmdBlitGMRFBToScreen(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdBlitGMRFBToScreen const *pCmd)
    4693 {
    4694     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    4695 
    4696     STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdBlitGmrFbToScreen);
    4697     Log(("SVGA_CMD_BLIT_GMRFB_TO_SCREEN src=(%d,%d) dest id=%d (%d,%d)(%d,%d)\n",
    4698              pCmd->srcOrigin.x, pCmd->srcOrigin.y, pCmd->destScreenId, pCmd->destRect.left, pCmd->destRect.top, pCmd->destRect.right, pCmd->destRect.bottom));
    4699 
    4700     ASSERT_GUEST_RETURN_VOID(pCmd->destScreenId < RT_ELEMENTS(pSvgaR3State->aScreens));
    4701     RT_UNTRUSTED_VALIDATED_FENCE();
    4702 
    4703     VMSVGASCREENOBJECT *pScreen = vmsvgaR3GetScreenObject(pThisCC, pCmd->destScreenId);
    4704     AssertPtrReturnVoid(pScreen);
    4705 
    4706     /** @todo Support GMRFB.format.s.bitsPerPixel != pThis->svga.uBpp ?  */
    4707     AssertReturnVoid(pSvgaR3State->GMRFB.format.bitsPerPixel == pScreen->cBpp);
    4708 
    4709     /* Clip destRect to the screen dimensions. */
    4710     SVGASignedRect screenRect;
    4711     screenRect.left   = 0;
    4712     screenRect.top    = 0;
    4713     screenRect.right  = pScreen->cWidth;
    4714     screenRect.bottom = pScreen->cHeight;
    4715     SVGASignedRect clipRect = pCmd->destRect;
    4716     vmsvgaR3ClipRect(&screenRect, &clipRect);
    4717     RT_UNTRUSTED_VALIDATED_FENCE();
    4718 
    4719     uint32_t const width  = clipRect.right - clipRect.left;
    4720     uint32_t const height = clipRect.bottom - clipRect.top;
    4721 
    4722     if (   width == 0
    4723         || height == 0)
    4724         return;  /* Nothing to do. */
    4725 
    4726     int32_t const srcx = pCmd->srcOrigin.x + (clipRect.left - pCmd->destRect.left);
    4727     int32_t const srcy = pCmd->srcOrigin.y + (clipRect.top - pCmd->destRect.top);
    4728 
    4729     /* Copy the defined by GMRFB image to the screen 0 VRAM area.
    4730      * Prepare parameters for vmsvgaR3GmrTransfer.
    4731      */
    4732     AssertReturnVoid(pScreen->offVRAM < pThis->vram_size); /* Paranoia. Ensured by SVGA_CMD_DEFINE_SCREEN. */
    4733 
    4734     /* Destination: host buffer which describes the screen 0 VRAM.
    4735      * Important are pbHstBuf and cbHstBuf. offHst and cbHstPitch are verified by vmsvgaR3GmrTransfer.
    4736      */
    4737     uint8_t * const pbHstBuf = (uint8_t *)pThisCC->pbVRam + pScreen->offVRAM;
    4738     uint32_t const cbScanline = pScreen->cbPitch ? pScreen->cbPitch :
    4739                                                    width * (RT_ALIGN(pScreen->cBpp, 8) / 8);
    4740     uint32_t cbHstBuf = cbScanline * pScreen->cHeight;
    4741     if (cbHstBuf > pThis->vram_size - pScreen->offVRAM)
    4742        cbHstBuf = pThis->vram_size - pScreen->offVRAM; /* Paranoia. */
    4743     uint32_t const offHst =   (clipRect.left * RT_ALIGN(pScreen->cBpp, 8)) / 8
    4744                             + cbScanline * clipRect.top;
    4745     int32_t const cbHstPitch = cbScanline;
    4746 
    4747     /* Source: GMRFB. vmsvgaR3GmrTransfer ensures that no memory outside the GMR is read. */
    4748     SVGAGuestPtr const gstPtr = pSvgaR3State->GMRFB.ptr;
    4749     uint32_t const offGst =  (srcx * RT_ALIGN(pSvgaR3State->GMRFB.format.bitsPerPixel, 8)) / 8
    4750                            + pSvgaR3State->GMRFB.bytesPerLine * srcy;
    4751     int32_t const cbGstPitch = pSvgaR3State->GMRFB.bytesPerLine;
    4752 
    4753     int rc = vmsvgaR3GmrTransfer(pThis, pThisCC, SVGA3D_WRITE_HOST_VRAM,
    4754                                  pbHstBuf, cbHstBuf, offHst, cbHstPitch,
    4755                                  gstPtr, offGst, cbGstPitch,
    4756                                  (width * RT_ALIGN(pScreen->cBpp, 8)) / 8, height);
    4757     AssertRC(rc);
    4758     vmsvgaR3UpdateScreen(pThisCC, pScreen, clipRect.left, clipRect.top, width, height);
    4759 }
    4760 
    4761 
    4762 /* SVGA_CMD_BLIT_SCREEN_TO_GMRFB */
    4763 static void vmsvgaR3CmdBlitScreenToGMRFB(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdBlitScreenToGMRFB const *pCmd)
    4764 {
    4765     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    4766 
    4767     STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdBlitScreentoGmrFb);
    4768     /* Note! This can fetch 3d render results as well!! */
    4769     Log(("SVGA_CMD_BLIT_SCREEN_TO_GMRFB dest=(%d,%d) src id=%d (%d,%d)(%d,%d)\n",
    4770              pCmd->destOrigin.x, pCmd->destOrigin.y, pCmd->srcScreenId, pCmd->srcRect.left, pCmd->srcRect.top, pCmd->srcRect.right, pCmd->srcRect.bottom));
    4771 
    4772     ASSERT_GUEST_RETURN_VOID(pCmd->srcScreenId < RT_ELEMENTS(pSvgaR3State->aScreens));
    4773     RT_UNTRUSTED_VALIDATED_FENCE();
    4774 
    4775     VMSVGASCREENOBJECT *pScreen = vmsvgaR3GetScreenObject(pThisCC, pCmd->srcScreenId);
    4776     AssertPtrReturnVoid(pScreen);
    4777 
    4778     /** @todo Support GMRFB.format.bitsPerPixel != pThis->svga.uBpp ? */
    4779     AssertReturnVoid(pSvgaR3State->GMRFB.format.bitsPerPixel == pScreen->cBpp);
    4780 
    4781     /* Clip destRect to the screen dimensions. */
    4782     SVGASignedRect screenRect;
    4783     screenRect.left   = 0;
    4784     screenRect.top    = 0;
    4785     screenRect.right  = pScreen->cWidth;
    4786     screenRect.bottom = pScreen->cHeight;
    4787     SVGASignedRect clipRect = pCmd->srcRect;
    4788     vmsvgaR3ClipRect(&screenRect, &clipRect);
    4789     RT_UNTRUSTED_VALIDATED_FENCE();
    4790 
    4791     uint32_t const width  = clipRect.right - clipRect.left;
    4792     uint32_t const height = clipRect.bottom - clipRect.top;
    4793 
    4794     if (   width == 0
    4795         || height == 0)
    4796         return;  /* Nothing to do. */
    4797 
    4798     int32_t const dstx = pCmd->destOrigin.x + (clipRect.left - pCmd->srcRect.left);
    4799     int32_t const dsty = pCmd->destOrigin.y + (clipRect.top - pCmd->srcRect.top);
    4800 
    4801     /* Copy the defined by GMRFB image to the screen 0 VRAM area.
    4802      * Prepare parameters for vmsvgaR3GmrTransfer.
    4803      */
    4804     AssertReturnVoid(pScreen->offVRAM < pThis->vram_size); /* Paranoia. Ensured by SVGA_CMD_DEFINE_SCREEN. */
    4805 
    4806     /* Source: host buffer which describes the screen 0 VRAM.
    4807      * Important are pbHstBuf and cbHstBuf. offHst and cbHstPitch are verified by vmsvgaR3GmrTransfer.
    4808      */
    4809     uint8_t * const pbHstBuf = (uint8_t *)pThisCC->pbVRam + pScreen->offVRAM;
    4810     uint32_t const cbScanline = pScreen->cbPitch ? pScreen->cbPitch :
    4811                                                    width * (RT_ALIGN(pScreen->cBpp, 8) / 8);
    4812     uint32_t cbHstBuf = cbScanline * pScreen->cHeight;
    4813     if (cbHstBuf > pThis->vram_size - pScreen->offVRAM)
    4814        cbHstBuf = pThis->vram_size - pScreen->offVRAM; /* Paranoia. */
    4815     uint32_t const offHst =   (clipRect.left * RT_ALIGN(pScreen->cBpp, 8)) / 8
    4816                             + cbScanline * clipRect.top;
    4817     int32_t const cbHstPitch = cbScanline;
    4818 
    4819     /* Destination: GMRFB. vmsvgaR3GmrTransfer ensures that no memory outside the GMR is read. */
    4820     SVGAGuestPtr const gstPtr = pSvgaR3State->GMRFB.ptr;
    4821     uint32_t const offGst =  (dstx * RT_ALIGN(pSvgaR3State->GMRFB.format.bitsPerPixel, 8)) / 8
    4822                            + pSvgaR3State->GMRFB.bytesPerLine * dsty;
    4823     int32_t const cbGstPitch = pSvgaR3State->GMRFB.bytesPerLine;
    4824 
    4825     int rc = vmsvgaR3GmrTransfer(pThis, pThisCC, SVGA3D_READ_HOST_VRAM,
    4826                                  pbHstBuf, cbHstBuf, offHst, cbHstPitch,
    4827                                  gstPtr, offGst, cbGstPitch,
    4828                                  (width * RT_ALIGN(pScreen->cBpp, 8)) / 8, height);
    4829     AssertRC(rc);
    4830 }
    4831 
    4832 
    4833 /* SVGA_CMD_ANNOTATION_FILL */
    4834 static void vmsvgaR3CmdAnnotationFill(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdAnnotationFill const *pCmd)
    4835 {
    4836     RT_NOREF(pThis);
    4837     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    4838 
    4839     STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdAnnotationFill);
    4840     Log(("SVGA_CMD_ANNOTATION_FILL red=%x green=%x blue=%x\n", pCmd->color.r, pCmd->color.g, pCmd->color.b));
    4841 
    4842     pSvgaR3State->colorAnnotation = pCmd->color;
    4843 }
    4844 
    4845 
    4846 /* SVGA_CMD_ANNOTATION_COPY */
    4847 static void vmsvgaR3CmdAnnotationCopy(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdAnnotationCopy const *pCmd)
    4848 {
    4849     RT_NOREF(pThis, pCmd);
    4850     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    4851 
    4852     STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdAnnotationCopy);
    4853     Log(("SVGA_CMD_ANNOTATION_COPY srcOrigin %d,%d, srcScreenId %u\n", pCmd->srcOrigin.x, pCmd->srcOrigin.y, pCmd->srcScreenId));
    4854 
    4855     AssertFailed();
    4856 }
    4857 
    4858 
    4859 # ifdef VBOX_WITH_VMSVGA3D
    4860 /* SVGA_CMD_DEFINE_GMR2 */
    4861 static void vmsvgaR3CmdDefineGMR2(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineGMR2 const *pCmd)
    4862 {
    4863     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    4864 
    4865     STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdDefineGmr2);
    4866     Log(("SVGA_CMD_DEFINE_GMR2 id=%#x %#x pages\n", pCmd->gmrId, pCmd->numPages));
    4867 
    4868     /* Validate current GMR id. */
    4869     ASSERT_GUEST_RETURN_VOID(pCmd->gmrId < pThis->svga.cGMR);
    4870     ASSERT_GUEST_RETURN_VOID(pCmd->numPages <= VMSVGA_MAX_GMR_PAGES);
    4871     RT_UNTRUSTED_VALIDATED_FENCE();
    4872 
    4873     if (!pCmd->numPages)
    4874     {
    4875         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdDefineGmr2Free);
    4876         vmsvgaR3GmrFree(pThisCC, pCmd->gmrId);
    4877     }
    4878     else
    4879     {
    4880         PGMR pGMR = &pSvgaR3State->paGMR[pCmd->gmrId];
    4881         if (pGMR->cMaxPages)
    4882             STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdDefineGmr2Modify);
    4883 
    4884         /* Not sure if we should always free the descriptor, but for simplicity
    4885            we do so if the new size is smaller than the current. */
    4886         /** @todo always free the descriptor in SVGA_CMD_DEFINE_GMR2? */
    4887         if (pGMR->cbTotal / X86_PAGE_SIZE > pGMR->cMaxPages)
    4888             vmsvgaR3GmrFree(pThisCC, pCmd->gmrId);
    4889 
    4890         pGMR->cMaxPages = pCmd->numPages;
    4891         /* The rest is done by the REMAP_GMR2 command. */
    4892     }
    4893 }
    4894 
    4895 
    4896 /* SVGA_CMD_REMAP_GMR2 */
    4897 static void vmsvgaR3CmdRemapGMR2(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdRemapGMR2 const *pCmd)
    4898 {
    4899     PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
    4900 
    4901     STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdRemapGmr2);
    4902     Log(("SVGA_CMD_REMAP_GMR2 id=%#x flags=%#x offset=%#x npages=%#x\n", pCmd->gmrId, pCmd->flags, pCmd->offsetPages, pCmd->numPages));
    4903 
    4904     /* Validate current GMR id and size. */
    4905     ASSERT_GUEST_RETURN_VOID(pCmd->gmrId < pThis->svga.cGMR);
    4906     RT_UNTRUSTED_VALIDATED_FENCE();
    4907     PGMR pGMR = &pSvgaR3State->paGMR[pCmd->gmrId];
    4908     ASSERT_GUEST_RETURN_VOID(   (uint64_t)pCmd->offsetPages + pCmd->numPages
    4909                              <= RT_MIN(pGMR->cMaxPages, RT_MIN(VMSVGA_MAX_GMR_PAGES, UINT32_MAX / X86_PAGE_SIZE)));
    4910     ASSERT_GUEST_RETURN_VOID(!pCmd->offsetPages || pGMR->paDesc); /** @todo */
    4911 
    4912     if (pCmd->numPages == 0)
    4913         return;
    4914     RT_UNTRUSTED_VALIDATED_FENCE();
    4915 
    4916     /* Calc new total page count so we can use it instead of cMaxPages for allocations below. */
    4917     uint32_t const cNewTotalPages = RT_MAX(pGMR->cbTotal >> X86_PAGE_SHIFT, pCmd->offsetPages + pCmd->numPages);
    4918 
    4919     /*
    4920      * We flatten the existing descriptors into a page array, overwrite the
    4921      * pages specified in this command and then recompress the descriptor.
    4922      */
    4923     /** @todo Optimize the GMR remap algorithm! */
    4924 
    4925     /* Save the old page descriptors as an array of page frame numbers (address >> X86_PAGE_SHIFT) */
    4926     uint64_t *paNewPage64 = NULL;
    4927     if (pGMR->paDesc)
    4928     {
    4929         STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdRemapGmr2Modify);
    4930 
    4931         paNewPage64 = (uint64_t *)RTMemAllocZ(cNewTotalPages * sizeof(uint64_t));
    4932         AssertPtrReturnVoid(paNewPage64);
    4933 
    4934         uint32_t idxPage = 0;
    4935         for (uint32_t i = 0; i < pGMR->numDescriptors; i++)
    4936             for (uint32_t j = 0; j < pGMR->paDesc[i].numPages; j++)
    4937                 paNewPage64[idxPage++] = (pGMR->paDesc[i].GCPhys + j * X86_PAGE_SIZE) >> X86_PAGE_SHIFT;
    4938         AssertReturnVoidStmt(idxPage == pGMR->cbTotal >> X86_PAGE_SHIFT, RTMemFree(paNewPage64));
    4939         RT_UNTRUSTED_VALIDATED_FENCE();
    4940     }
    4941 
    4942     /* Free the old GMR if present. */
    4943     if (pGMR->paDesc)
    4944         RTMemFree(pGMR->paDesc);
    4945 
    4946     /* Allocate the maximum amount possible (everything non-continuous) */
    4947     PVMSVGAGMRDESCRIPTOR paDescs;
    4948     pGMR->paDesc = paDescs = (PVMSVGAGMRDESCRIPTOR)RTMemAllocZ(cNewTotalPages * sizeof(VMSVGAGMRDESCRIPTOR));
    4949     AssertReturnVoidStmt(paDescs, RTMemFree(paNewPage64));
    4950 
    4951     if (pCmd->flags & SVGA_REMAP_GMR2_VIA_GMR)
    4952     {
    4953         /** @todo */
    4954         AssertFailed();
    4955         pGMR->numDescriptors = 0;
    4956     }
    4957     else
    4958     {
    4959         uint32_t  *paPages32 = (uint32_t *)(pCmd + 1);
    4960         uint64_t  *paPages64 = (uint64_t *)(pCmd + 1);
    4961         bool       fGCPhys64 = RT_BOOL(pCmd->flags & SVGA_REMAP_GMR2_PPN64);
    4962 
    4963         uint32_t cPages;
    4964         if (paNewPage64)
    4965         {
    4966             /* Overwrite the old page array with the new page values. */
    4967             if (fGCPhys64)
    4968                 for (uint32_t i = pCmd->offsetPages; i < pCmd->offsetPages + pCmd->numPages; i++)
    4969                     paNewPage64[i] = paPages64[i - pCmd->offsetPages];
    4970             else
    4971                 for (uint32_t i = pCmd->offsetPages; i < pCmd->offsetPages + pCmd->numPages; i++)
    4972                     paNewPage64[i] = paPages32[i - pCmd->offsetPages];
    4973 
    4974             /* Use the updated page array instead of the command data. */
    4975             fGCPhys64      = true;
    4976             paPages64      = paNewPage64;
    4977             cPages = cNewTotalPages;
    4978         }
    4979         else
    4980             cPages = pCmd->numPages;
    4981 
    4982         /* The first page. */
    4983         /** @todo The 0x00000FFFFFFFFFFF mask limits to 44 bits and should not be
    4984          *        applied to paNewPage64. */
    4985         RTGCPHYS GCPhys;
    4986         if (fGCPhys64)
    4987             GCPhys = (paPages64[0] << X86_PAGE_SHIFT) & UINT64_C(0x00000FFFFFFFFFFF); /* Seeing rubbish in the top bits with certain linux guests. */
    4988         else
    4989             GCPhys = (RTGCPHYS)paPages32[0] << PAGE_SHIFT;
    4990         paDescs[0].GCPhys    = GCPhys;
    4991         paDescs[0].numPages  = 1;
    4992 
    4993         /* Subsequent pages. */
    4994         uint32_t iDescriptor = 0;
    4995         for (uint32_t i = 1; i < cPages; i++)
    4996         {
    4997             if (pCmd->flags & SVGA_REMAP_GMR2_PPN64)
    4998                 GCPhys = (paPages64[i] << X86_PAGE_SHIFT) & UINT64_C(0x00000FFFFFFFFFFF); /* Seeing rubbish in the top bits with certain linux guests. */
    4999             else
    5000                 GCPhys = (RTGCPHYS)paPages32[i] << X86_PAGE_SHIFT;
    5001 
    5002             /* Continuous physical memory? */
    5003             if (GCPhys == paDescs[iDescriptor].GCPhys + paDescs[iDescriptor].numPages * X86_PAGE_SIZE)
    5004             {
    5005                 Assert(paDescs[iDescriptor].numPages);
    5006                 paDescs[iDescriptor].numPages++;
    5007                 Log5Func(("Page %x GCPhys=%RGp successor\n", i, GCPhys));
    5008             }
    5009             else
    5010             {
    5011                 iDescriptor++;
    5012                 paDescs[iDescriptor].GCPhys   = GCPhys;
    5013                 paDescs[iDescriptor].numPages = 1;
    5014                 Log5Func(("Page %x GCPhys=%RGp\n", i, paDescs[iDescriptor].GCPhys));
    5015             }
    5016         }
    5017 
    5018         pGMR->cbTotal = cNewTotalPages << X86_PAGE_SHIFT;
    5019         Log5Func(("Nr of descriptors %x; cbTotal=%#x\n", iDescriptor + 1, cNewTotalPages));
    5020         pGMR->numDescriptors = iDescriptor + 1;
    5021     }
    5022 
    5023     if (paNewPage64)
    5024         RTMemFree(paNewPage64);
    5025 }
    5026 # endif // VBOX_WITH_VMSVGA3D
    5027 
    5028 
    50292593/*
    50302594 *
     
    58573421                }
    58583422                else
    5859 # endif // VBOX_WITH_VMSVGA3D
     3423# endif /* VBOX_WITH_VMSVGA3D */
    58603424                {
    58613425                    /* Unsupported command. */
     
    71484712#undef VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK
    71494713#undef VMSVGAFIFO_GET_CMD_BUFFER_BREAK
    7150 
    7151 #ifdef VBOX_WITH_VMSVGA3D
    7152 /**
    7153  * Free the specified GMR
    7154  *
    7155  * @param   pThisCC         The VGA/VMSVGA state for ring-3.
    7156  * @param   idGMR           GMR id
    7157  */
    7158 static void vmsvgaR3GmrFree(PVGASTATECC pThisCC, uint32_t idGMR)
    7159 {
    7160     PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
    7161 
    7162     /* Free the old descriptor if present. */
    7163     PGMR pGMR = &pSVGAState->paGMR[idGMR];
    7164     if (   pGMR->numDescriptors
    7165         || pGMR->paDesc /* needed till we implement SVGA_REMAP_GMR2_VIA_GMR */)
    7166     {
    7167 # ifdef DEBUG_GMR_ACCESS
    7168         VMR3ReqCallWaitU(PDMDevHlpGetUVM(pThisCC->pDevIns), VMCPUID_ANY, (PFNRT)vmsvgaR3DeregisterGmr, 2, pDevIns, idGMR);
    7169 # endif
    7170 
    7171         Assert(pGMR->paDesc);
    7172         RTMemFree(pGMR->paDesc);
    7173         pGMR->paDesc         = NULL;
    7174         pGMR->numDescriptors = 0;
    7175         pGMR->cbTotal        = 0;
    7176         pGMR->cMaxPages      = 0;
    7177     }
    7178     Assert(!pGMR->cMaxPages);
    7179     Assert(!pGMR->cbTotal);
    7180 }
    7181 #endif /* VBOX_WITH_VMSVGA3D */
    7182 
    7183 /**
    7184  * Copy between a GMR and a host memory buffer.
    7185  *
    7186  * @returns VBox status code.
    7187  * @param   pThis           The shared VGA/VMSVGA instance data.
    7188  * @param   pThisCC         The VGA/VMSVGA state for ring-3.
    7189  * @param   enmTransferType Transfer type (read/write)
    7190  * @param   pbHstBuf        Host buffer pointer (valid)
    7191  * @param   cbHstBuf        Size of host buffer (valid)
    7192  * @param   offHst          Host buffer offset of the first scanline
    7193  * @param   cbHstPitch      Destination buffer pitch
    7194  * @param   gstPtr          GMR description
    7195  * @param   offGst          Guest buffer offset of the first scanline
    7196  * @param   cbGstPitch      Guest buffer pitch
    7197  * @param   cbWidth         Width in bytes to copy
    7198  * @param   cHeight         Number of scanllines to copy
    7199  */
    7200 int vmsvgaR3GmrTransfer(PVGASTATE pThis, PVGASTATECC pThisCC, const SVGA3dTransferType enmTransferType,
    7201                         uint8_t *pbHstBuf, uint32_t cbHstBuf, uint32_t offHst, int32_t cbHstPitch,
    7202                         SVGAGuestPtr gstPtr, uint32_t offGst, int32_t cbGstPitch,
    7203                         uint32_t cbWidth, uint32_t cHeight)
    7204 {
    7205     PVMSVGAR3STATE  pSVGAState = pThisCC->svga.pSvgaR3State;
    7206     PPDMDEVINS      pDevIns = pThisCC->pDevIns; /* simpler */
    7207     int             rc;
    7208 
    7209     LogFunc(("%s host %p size=%d offset %d pitch=%d; guest gmr=%#x:%#x offset=%d pitch=%d cbWidth=%d cHeight=%d\n",
    7210              enmTransferType == SVGA3D_READ_HOST_VRAM ? "WRITE" : "READ", /* GMR op: READ host VRAM means WRITE GMR */
    7211              pbHstBuf, cbHstBuf, offHst, cbHstPitch,
    7212              gstPtr.gmrId, gstPtr.offset, offGst, cbGstPitch, cbWidth, cHeight));
    7213     AssertReturn(cbWidth && cHeight, VERR_INVALID_PARAMETER);
    7214 
    7215     PGMR pGMR;
    7216     uint32_t cbGmr; /* The GMR size in bytes. */
    7217     if (gstPtr.gmrId == SVGA_GMR_FRAMEBUFFER)
    7218     {
    7219         pGMR = NULL;
    7220         cbGmr = pThis->vram_size;
    7221     }
    7222     else
    7223     {
    7224         AssertReturn(gstPtr.gmrId < pThis->svga.cGMR, VERR_INVALID_PARAMETER);
    7225         RT_UNTRUSTED_VALIDATED_FENCE();
    7226         pGMR = &pSVGAState->paGMR[gstPtr.gmrId];
    7227         cbGmr = pGMR->cbTotal;
    7228     }
    7229 
    7230     /*
    7231      * GMR
    7232      */
    7233     /* Calculate GMR offset of the data to be copied. */
    7234     AssertMsgReturn(gstPtr.offset < cbGmr,
    7235                     ("gmr=%#x:%#x offGst=%#x cbGstPitch=%#x cHeight=%#x cbWidth=%#x cbGmr=%#x\n",
    7236                      gstPtr.gmrId, gstPtr.offset, offGst, cbGstPitch, cHeight, cbWidth, cbGmr),
    7237                     VERR_INVALID_PARAMETER);
    7238     RT_UNTRUSTED_VALIDATED_FENCE();
    7239     AssertMsgReturn(offGst < cbGmr - gstPtr.offset,
    7240                     ("gmr=%#x:%#x offGst=%#x cbGstPitch=%#x cHeight=%#x cbWidth=%#x cbGmr=%#x\n",
    7241                      gstPtr.gmrId, gstPtr.offset, offGst, cbGstPitch, cHeight, cbWidth, cbGmr),
    7242                     VERR_INVALID_PARAMETER);
    7243     RT_UNTRUSTED_VALIDATED_FENCE();
    7244     uint32_t const offGmr = offGst + gstPtr.offset; /* Offset in the GMR, where the first scanline is located. */
    7245 
    7246     /* Verify that cbWidth is less than scanline and fits into the GMR. */
    7247     uint32_t const cbGmrScanline = cbGstPitch > 0 ? cbGstPitch : -cbGstPitch;
    7248     AssertMsgReturn(cbGmrScanline != 0,
    7249                     ("gmr=%#x:%#x offGst=%#x cbGstPitch=%#x cHeight=%#x cbWidth=%#x cbGmr=%#x\n",
    7250                      gstPtr.gmrId, gstPtr.offset, offGst, cbGstPitch, cHeight, cbWidth, cbGmr),
    7251                     VERR_INVALID_PARAMETER);
    7252     RT_UNTRUSTED_VALIDATED_FENCE();
    7253     AssertMsgReturn(cbWidth <= cbGmrScanline,
    7254                     ("gmr=%#x:%#x offGst=%#x cbGstPitch=%#x cHeight=%#x cbWidth=%#x cbGmr=%#x\n",
    7255                      gstPtr.gmrId, gstPtr.offset, offGst, cbGstPitch, cHeight, cbWidth, cbGmr),
    7256                     VERR_INVALID_PARAMETER);
    7257     AssertMsgReturn(cbWidth <= cbGmr - offGmr,
    7258                     ("gmr=%#x:%#x offGst=%#x cbGstPitch=%#x cHeight=%#x cbWidth=%#x cbGmr=%#x\n",
    7259                      gstPtr.gmrId, gstPtr.offset, offGst, cbGstPitch, cHeight, cbWidth, cbGmr),
    7260                     VERR_INVALID_PARAMETER);
    7261     RT_UNTRUSTED_VALIDATED_FENCE();
    7262 
    7263     /* How many bytes are available for the data in the GMR. */
    7264     uint32_t const cbGmrLeft = cbGstPitch > 0 ? cbGmr - offGmr : offGmr + cbWidth;
    7265 
    7266     /* How many scanlines would fit into the available data. */
    7267     uint32_t cGmrScanlines = cbGmrLeft / cbGmrScanline;
    7268     uint32_t const cbGmrLastScanline = cbGmrLeft - cGmrScanlines * cbGmrScanline; /* Slack space. */
    7269     if (cbWidth <= cbGmrLastScanline)
    7270         ++cGmrScanlines;
    7271 
    7272     if (cHeight > cGmrScanlines)
    7273         cHeight = cGmrScanlines;
    7274 
    7275     AssertMsgReturn(cHeight > 0,
    7276                     ("gmr=%#x:%#x offGst=%#x cbGstPitch=%#x cHeight=%#x cbWidth=%#x cbGmr=%#x\n",
    7277                      gstPtr.gmrId, gstPtr.offset, offGst, cbGstPitch, cHeight, cbWidth, cbGmr),
    7278                     VERR_INVALID_PARAMETER);
    7279     RT_UNTRUSTED_VALIDATED_FENCE();
    7280 
    7281     /*
    7282      * Host buffer.
    7283      */
    7284     AssertMsgReturn(offHst < cbHstBuf,
    7285                     ("buffer=%p size %d offHst=%d cbHstPitch=%d cHeight=%d cbWidth=%d\n",
    7286                      pbHstBuf, cbHstBuf, offHst, cbHstPitch, cHeight, cbWidth),
    7287                     VERR_INVALID_PARAMETER);
    7288 
    7289     /* Verify that cbWidth is less than scanline and fits into the buffer. */
    7290     uint32_t const cbHstScanline = cbHstPitch > 0 ? cbHstPitch : -cbHstPitch;
    7291     AssertMsgReturn(cbHstScanline != 0,
    7292                     ("buffer=%p size %d offHst=%d cbHstPitch=%d cHeight=%d cbWidth=%d\n",
    7293                      pbHstBuf, cbHstBuf, offHst, cbHstPitch, cHeight, cbWidth),
    7294                     VERR_INVALID_PARAMETER);
    7295     AssertMsgReturn(cbWidth <= cbHstScanline,
    7296                     ("buffer=%p size %d offHst=%d cbHstPitch=%d cHeight=%d cbWidth=%d\n",
    7297                      pbHstBuf, cbHstBuf, offHst, cbHstPitch, cHeight, cbWidth),
    7298                     VERR_INVALID_PARAMETER);
    7299     AssertMsgReturn(cbWidth <= cbHstBuf - offHst,
    7300                     ("buffer=%p size %d offHst=%d cbHstPitch=%d cHeight=%d cbWidth=%d\n",
    7301                      pbHstBuf, cbHstBuf, offHst, cbHstPitch, cHeight, cbWidth),
    7302                     VERR_INVALID_PARAMETER);
    7303 
    7304     /* How many bytes are available for the data in the buffer. */
    7305     uint32_t const cbHstLeft = cbHstPitch > 0 ? cbHstBuf - offHst : offHst + cbWidth;
    7306 
    7307     /* How many scanlines would fit into the available data. */
    7308     uint32_t cHstScanlines = cbHstLeft / cbHstScanline;
    7309     uint32_t const cbHstLastScanline = cbHstLeft - cHstScanlines * cbHstScanline; /* Slack space. */
    7310     if (cbWidth <= cbHstLastScanline)
    7311         ++cHstScanlines;
    7312 
    7313     if (cHeight > cHstScanlines)
    7314         cHeight = cHstScanlines;
    7315 
    7316     AssertMsgReturn(cHeight > 0,
    7317                     ("buffer=%p size %d offHst=%d cbHstPitch=%d cHeight=%d cbWidth=%d\n",
    7318                      pbHstBuf, cbHstBuf, offHst, cbHstPitch, cHeight, cbWidth),
    7319                     VERR_INVALID_PARAMETER);
    7320 
    7321     uint8_t *pbHst = pbHstBuf + offHst;
    7322 
    7323     /* Shortcut for the framebuffer. */
    7324     if (gstPtr.gmrId == SVGA_GMR_FRAMEBUFFER)
    7325     {
    7326         uint8_t *pbGst = pThisCC->pbVRam + offGmr;
    7327 
    7328         uint8_t const *pbSrc;
    7329         int32_t cbSrcPitch;
    7330         uint8_t *pbDst;
    7331         int32_t cbDstPitch;
    7332 
    7333         if (enmTransferType == SVGA3D_READ_HOST_VRAM)
    7334         {
    7335             pbSrc      = pbHst;
    7336             cbSrcPitch = cbHstPitch;
    7337             pbDst      = pbGst;
    7338             cbDstPitch = cbGstPitch;
    7339         }
    7340         else
    7341         {
    7342             pbSrc      = pbGst;
    7343             cbSrcPitch = cbGstPitch;
    7344             pbDst      = pbHst;
    7345             cbDstPitch = cbHstPitch;
    7346         }
    7347 
    7348         if (   cbWidth == (uint32_t)cbGstPitch
    7349             && cbGstPitch == cbHstPitch)
    7350         {
    7351             /* Entire scanlines, positive pitch. */
    7352             memcpy(pbDst, pbSrc, cbWidth * cHeight);
    7353         }
    7354         else
    7355         {
    7356             for (uint32_t i = 0; i < cHeight; ++i)
    7357             {
    7358                 memcpy(pbDst, pbSrc, cbWidth);
    7359 
    7360                 pbDst += cbDstPitch;
    7361                 pbSrc += cbSrcPitch;
    7362             }
    7363         }
    7364         return VINF_SUCCESS;
    7365     }
    7366 
    7367     AssertPtrReturn(pGMR, VERR_INVALID_PARAMETER);
    7368     AssertReturn(pGMR->numDescriptors > 0, VERR_INVALID_PARAMETER);
    7369 
    7370     PVMSVGAGMRDESCRIPTOR const paDesc = pGMR->paDesc; /* Local copy of the pointer. */
    7371     uint32_t iDesc = 0;                               /* Index in the descriptor array. */
    7372     uint32_t offDesc = 0;                             /* GMR offset of the current descriptor. */
    7373     uint32_t offGmrScanline = offGmr;                 /* GMR offset of the scanline which is being copied. */
    7374     uint8_t *pbHstScanline = pbHst;                   /* Host address of the scanline which is being copied. */
    7375     for (uint32_t i = 0; i < cHeight; ++i)
    7376     {
    7377         uint32_t cbCurrentWidth = cbWidth;
    7378         uint32_t offGmrCurrent  = offGmrScanline;
    7379         uint8_t *pbCurrentHost  = pbHstScanline;
    7380 
    7381         /* Find the right descriptor */
    7382         while (offDesc + paDesc[iDesc].numPages * PAGE_SIZE <= offGmrCurrent)
    7383         {
    7384             offDesc += paDesc[iDesc].numPages * PAGE_SIZE;
    7385             AssertReturn(offDesc < pGMR->cbTotal, VERR_INTERNAL_ERROR); /* overflow protection */
    7386             ++iDesc;
    7387             AssertReturn(iDesc < pGMR->numDescriptors, VERR_INTERNAL_ERROR);
    7388         }
    7389 
    7390         while (cbCurrentWidth)
    7391         {
    7392             uint32_t cbToCopy;
    7393 
    7394             if (offGmrCurrent + cbCurrentWidth <= offDesc + paDesc[iDesc].numPages * PAGE_SIZE)
    7395             {
    7396                 cbToCopy = cbCurrentWidth;
    7397             }
    7398             else
    7399             {
    7400                 cbToCopy = (offDesc + paDesc[iDesc].numPages * PAGE_SIZE - offGmrCurrent);
    7401                 AssertReturn(cbToCopy <= cbCurrentWidth, VERR_INVALID_PARAMETER);
    7402             }
    7403 
    7404             RTGCPHYS const GCPhys = paDesc[iDesc].GCPhys + offGmrCurrent - offDesc;
    7405 
    7406             Log5Func(("%s phys=%RGp\n", (enmTransferType == SVGA3D_WRITE_HOST_VRAM) ? "READ" : "WRITE", GCPhys));
    7407 
    7408             if (enmTransferType == SVGA3D_WRITE_HOST_VRAM)
    7409                 rc = PDMDevHlpPhysRead(pDevIns, GCPhys, pbCurrentHost, cbToCopy);
    7410             else
    7411                 rc = PDMDevHlpPhysWrite(pDevIns, GCPhys, pbCurrentHost, cbToCopy);
    7412             AssertRCBreak(rc);
    7413 
    7414             cbCurrentWidth -= cbToCopy;
    7415             offGmrCurrent  += cbToCopy;
    7416             pbCurrentHost  += cbToCopy;
    7417 
    7418             /* Go to the next descriptor if there's anything left. */
    7419             if (cbCurrentWidth)
    7420             {
    7421                 offDesc += paDesc[iDesc].numPages * PAGE_SIZE;
    7422                 AssertReturn(offDesc < pGMR->cbTotal, VERR_INTERNAL_ERROR);
    7423                 ++iDesc;
    7424                 AssertReturn(iDesc < pGMR->numDescriptors, VERR_INTERNAL_ERROR);
    7425             }
    7426         }
    7427 
    7428         offGmrScanline += cbGstPitch;
    7429         pbHstScanline  += cbHstPitch;
    7430     }
    7431 
    7432     return VINF_SUCCESS;
    7433 }
    7434 
    7435 
    7436 /**
    7437  * Unsigned coordinates in pBox. Clip to [0; pSizeSrc), [0; pSizeDest).
    7438  *
    7439  * @param   pSizeSrc    Source surface dimensions.
    7440  * @param   pSizeDest   Destination surface dimensions.
    7441  * @param   pBox        Coordinates to be clipped.
    7442  */
    7443 void vmsvgaR3ClipCopyBox(const SVGA3dSize *pSizeSrc, const SVGA3dSize *pSizeDest, SVGA3dCopyBox *pBox)
    7444 {
    7445     /* Src x, w */
    7446     if (pBox->srcx > pSizeSrc->width)
    7447         pBox->srcx = pSizeSrc->width;
    7448     if (pBox->w > pSizeSrc->width - pBox->srcx)
    7449         pBox->w = pSizeSrc->width - pBox->srcx;
    7450 
    7451     /* Src y, h */
    7452     if (pBox->srcy > pSizeSrc->height)
    7453         pBox->srcy = pSizeSrc->height;
    7454     if (pBox->h > pSizeSrc->height - pBox->srcy)
    7455         pBox->h = pSizeSrc->height - pBox->srcy;
    7456 
    7457     /* Src z, d */
    7458     if (pBox->srcz > pSizeSrc->depth)
    7459         pBox->srcz = pSizeSrc->depth;
    7460     if (pBox->d > pSizeSrc->depth - pBox->srcz)
    7461         pBox->d = pSizeSrc->depth - pBox->srcz;
    7462 
    7463     /* Dest x, w */
    7464     if (pBox->x > pSizeDest->width)
    7465         pBox->x = pSizeDest->width;
    7466     if (pBox->w > pSizeDest->width - pBox->x)
    7467         pBox->w = pSizeDest->width - pBox->x;
    7468 
    7469     /* Dest y, h */
    7470     if (pBox->y > pSizeDest->height)
    7471         pBox->y = pSizeDest->height;
    7472     if (pBox->h > pSizeDest->height - pBox->y)
    7473         pBox->h = pSizeDest->height - pBox->y;
    7474 
    7475     /* Dest z, d */
    7476     if (pBox->z > pSizeDest->depth)
    7477         pBox->z = pSizeDest->depth;
    7478     if (pBox->d > pSizeDest->depth - pBox->z)
    7479         pBox->d = pSizeDest->depth - pBox->z;
    7480 }
    7481 
    7482 /**
    7483  * Unsigned coordinates in pBox. Clip to [0; pSize).
    7484  *
    7485  * @param   pSize   Source surface dimensions.
    7486  * @param   pBox    Coordinates to be clipped.
    7487  */
    7488 void vmsvgaR3ClipBox(const SVGA3dSize *pSize, SVGA3dBox *pBox)
    7489 {
    7490     /* x, w */
    7491     if (pBox->x > pSize->width)
    7492         pBox->x = pSize->width;
    7493     if (pBox->w > pSize->width - pBox->x)
    7494         pBox->w = pSize->width - pBox->x;
    7495 
    7496     /* y, h */
    7497     if (pBox->y > pSize->height)
    7498         pBox->y = pSize->height;
    7499     if (pBox->h > pSize->height - pBox->y)
    7500         pBox->h = pSize->height - pBox->y;
    7501 
    7502     /* z, d */
    7503     if (pBox->z > pSize->depth)
    7504         pBox->z = pSize->depth;
    7505     if (pBox->d > pSize->depth - pBox->z)
    7506         pBox->d = pSize->depth - pBox->z;
    7507 }
    7508 
    7509 /**
    7510  * Clip.
    7511  *
    7512  * @param   pBound  Bounding rectangle.
    7513  * @param   pRect   Rectangle to be clipped.
    7514  */
    7515 void vmsvgaR3ClipRect(SVGASignedRect const *pBound, SVGASignedRect *pRect)
    7516 {
    7517     int32_t left;
    7518     int32_t top;
    7519     int32_t right;
    7520     int32_t bottom;
    7521 
    7522     /* Right order. */
    7523     Assert(pBound->left <= pBound->right && pBound->top <= pBound->bottom);
    7524     if (pRect->left < pRect->right)
    7525     {
    7526         left = pRect->left;
    7527         right = pRect->right;
    7528     }
    7529     else
    7530     {
    7531         left = pRect->right;
    7532         right = pRect->left;
    7533     }
    7534     if (pRect->top < pRect->bottom)
    7535     {
    7536         top = pRect->top;
    7537         bottom = pRect->bottom;
    7538     }
    7539     else
    7540     {
    7541         top = pRect->bottom;
    7542         bottom = pRect->top;
    7543     }
    7544 
    7545     if (left < pBound->left)
    7546         left = pBound->left;
    7547     if (right < pBound->left)
    7548         right = pBound->left;
    7549 
    7550     if (left > pBound->right)
    7551         left = pBound->right;
    7552     if (right > pBound->right)
    7553         right = pBound->right;
    7554 
    7555     if (top < pBound->top)
    7556         top = pBound->top;
    7557     if (bottom < pBound->top)
    7558         bottom = pBound->top;
    7559 
    7560     if (top > pBound->bottom)
    7561         top = pBound->bottom;
    7562     if (bottom > pBound->bottom)
    7563         bottom = pBound->bottom;
    7564 
    7565     pRect->left = left;
    7566     pRect->right = right;
    7567     pRect->top = top;
    7568     pRect->bottom = bottom;
    7569 }
    75704714
    75714715/**
  • trunk/src/VBox/Devices/Makefile.kmk

    r86043 r86265  
    303303  VBoxDD_DEFS           += VBOX_WITH_VMSVGA
    304304  VBoxDD_INCS           += $(VBOX_PATH_VMSVGA_INC)
    305   VBoxDD_SOURCES        += Graphics/DevVGA-SVGA.cpp
     305  VBoxDD_SOURCES        += \
     306        Graphics/DevVGA-SVGA.cpp \
     307        Graphics/DevVGA-SVGA-cmd.cpp
    306308 endif
    307309 ifdef VBOX_WITH_VMSVGA3D
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