Changeset 86265 in vbox
- Timestamp:
- Sep 24, 2020 12:42:43 PM (4 years ago)
- 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 1 1 /* $Id$ */ 2 2 /** @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. 16 4 */ 17 5 … … 28 16 */ 29 17 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 131 23 #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> 133 27 #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_CODE139 # include <VBox/vmm/vmapi.h>140 # include <VBox/vmm/vmcpuset.h>141 #endif142 #include <VBox/sup.h>143 144 #include <iprt/assert.h>145 #include <iprt/semaphore.h>146 #include <iprt/uuid.h>147 #ifdef IN_RING3148 # include <iprt/ctype.h>149 # include <iprt/mem.h>150 # ifdef VBOX_STRICT151 # include <iprt/time.h>152 # endif153 #endif154 155 #include <VBox/AssertGuest.h>156 #include <VBox/VMMDev.h>157 28 #include <VBoxVideo.h> 158 #include <VBox/bioslogo.h>159 29 160 30 /* should go BEFORE any other DevVGA include to make all DevVGA.h config defines be visible */ 161 31 #include "DevVGA.h" 162 32 163 #include "DevVGA-SVGA .h"33 #include "DevVGA-SVGA-internal.h" 164 34 #ifdef VBOX_WITH_VMSVGA3D 165 35 # include "DevVGA-SVGA3d.h" 166 # ifdef RT_OS_DARWIN167 # include "DevVGA-SVGA3d-cocoa.h"168 # endif169 # ifdef RT_OS_LINUX170 # ifdef IN_RING3171 # include "DevVGA-SVGA3d-glLdr.h"172 # endif173 # endif174 36 #endif 175 37 176 38 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 733 41 /** 734 42 * FIFO command name lookup … … 737 45 * @param u32Cmd FIFO command 738 46 */ 739 staticconst char *vmsvgaR3FifoCmdToString(uint32_t u32Cmd)47 const char *vmsvgaR3FifoCmdToString(uint32_t u32Cmd) 740 48 { 741 49 switch (u32Cmd) … … 959 267 } 960 268 } 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 273 VMSVGASCREENOBJECT *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 285 void vmsvgaR3ResetScreens(PVGASTATE pThis, PVGASTATECC pThisCC) 286 { 287 #ifdef VBOX_WITH_VMSVGA3D 1012 288 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) 1052 291 { 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); 1072 295 } 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); 1134 299 #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 #else1144 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 #endif1148 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_TOP1152 && 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.fEnabled1174 && pThis->svga.uWidth != VMSVGA_VAL_UNINITIALIZED)1175 *pu32 = pThis->svga.uWidth;1176 else1177 {1178 #ifndef IN_RING31179 rc = VINF_IOM_R3_IOPORT_READ;1180 #else1181 *pu32 = pThisCC->pDrv->cx;1182 #endif1183 }1184 break;1185 }1186 1187 case SVGA_REG_HEIGHT:1188 {1189 STAM_REL_COUNTER_INC(&pThis->svga.StatRegHeightRd);1190 if ( pThis->svga.fEnabled1191 && pThis->svga.uHeight != VMSVGA_VAL_UNINITIALIZED)1192 *pu32 = pThis->svga.uHeight;1193 else1194 {1195 #ifndef IN_RING31196 rc = VINF_IOM_R3_IOPORT_READ;1197 #else1198 *pu32 = pThisCC->pDrv->cy;1199 #endif1200 }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 else1256 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.fEnabled1311 && pThis->svga.cbScanline)1312 *pu32 = pThis->svga.cbScanline;1313 else1314 {1315 #ifndef IN_RING31316 rc = VINF_IOM_R3_IOPORT_READ;1317 #else1318 *pu32 = pThisCC->pDrv->cbScanline;1319 #endif1320 }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_RING31344 rc = VINF_IOM_R3_IOPORT_READ;1345 #else1346 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.fEnabled1350 && 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 else1356 *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 #endif1361 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_RING31395 /* Go to ring-3 and halt the CPU. */1396 rc = VINF_IOM_R3_IOPORT_READ;1397 RT_NOREF(pDevIns);1398 break;1399 #else1400 # if defined(VMSVGA_USE_EMT_HALT_CODE)1401 /* The guest is basically doing a HLT via the device here, but with1402 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 # else1418 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 be1421 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/wait1434 * code in VMEmt.cpp here, otherwise all kind of EMT interaction will1435 * 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 # endif1447 *pu32 = pThis->svga.fBusy != 0;1448 #endif1449 }1450 else1451 *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 driver1580 will take a legacy code path without 3d support. This number also1581 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 else1621 *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 else1673 {1674 #if !defined(IN_RING3) && defined(VBOX_STRICT)1675 rc = VINF_IOM_R3_IOPORT_READ;1676 #else1677 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 #endif1682 }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_RING31691 /**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 device1711 * deletes all screens other than screen #0, and redefines screen1712 * #0 according to the specified mode. Drivers that use1713 * 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 else1741 {1742 /* "If Screen Objects are supported, they can be used to fully1743 * replace the functionality provided by the framebuffer registers1744 * (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 == 01762 && 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 do1809 {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 mode1820 * 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 past1833 * it. If SVGA_FIFO_MIN is small, there may well be data at the SVGA_FIFO_PITCHLOCK1834 * 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 else1851 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_RING31860 1861 /**1862 * Sends cursor position and visibility information from legacy1863 * 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 the1869 * 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_ON1871 * 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 values1881 * were extended as follows:1882 *1883 * SVGA_CURSOR_ON_HIDE 01884 * SVGA_CURSOR_ON_SHOW 11885 * SVGA_CURSOR_ON_REMOVE_FROM_FB 2 - cursor on but not in the framebuffer1886 * SVGA_CURSOR_ON_RESTORE_TO_FB 3 - cursor on, possibly in the framebuffer1887 *1888 * Since we never draw the cursor into the guest's framebuffer, we do not need to1889 * 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 300 } 1899 301 … … 1953 355 } 1954 356 } 1955 1956 #endif /* IN_RING3 */1957 1958 1959 /**1960 * Write port register1961 *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 write1967 */1968 static VBOXSTRICTRC vmsvgaWritePort(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, uint32_t u32)1969 {1970 #ifdef IN_RING31971 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;1972 #endif1973 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 #else1982 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 #endif1986 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_TOP1990 && 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_02014 || u32 == SVGA_ID_12015 || u32 == SVGA_ID_2)2016 pThis->svga.u32SVGAId = u32;2017 else2018 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_RING32024 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_UNINITIALIZED2037 && 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_UNINITIALIZED2046 && pThis->svga.uHeight != VMSVGA_VAL_UNINITIALIZED)2047 ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE);2048 # ifdef LOG_ENABLED2049 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 # endif2053 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 else2066 {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 #else2101 rc = VINF_IOM_R3_IOPORT_WRITE;2102 #endif2103 }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 #else2133 rc = VINF_IOM_R3_IOPORT_WRITE;2134 #endif2135 }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_RING32145 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 #else2152 rc = VINF_IOM_R3_IOPORT_WRITE;2153 #endif2154 break;2155 2156 case SVGA_REG_SYNC: /* See "FIFO Synchronization Registers" */2157 STAM_REL_COUNTER_INC(&pThis->svga.StatRegSyncWr);2158 if ( pThis->svga.fEnabled2159 && 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 empty2165 * 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 #else2174 rc = VINF_IOM_R3_IOPORT_WRITE;2175 #endif2176 }2177 /* else nothing to do. */2178 else2179 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 else2209 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_RING32230 /* 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 #else2234 rc = VINF_IOM_R3_IOPORT_WRITE;2235 #endif2236 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_VMSVGA3D2261 /* 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_RING32269 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 else2347 {2348 RTMemFree(paDescs);2349 STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegGmrDescriptorWrErrors);2350 }2351 break;2352 }2353 # endif /* IN_RING3 */2354 #endif // VBOX_WITH_VMSVGA3D2355 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_RING32362 vmsvgaR3SetTraces(pDevIns, pThis, !!u32);2363 #else2364 rc = VINF_IOM_R3_IOPORT_WRITE;2365 #endif2366 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_RING32384 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 #else2394 rc = VINF_IOM_R3_IOPORT_WRITE;2395 #endif2396 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 else2477 {2478 #if !defined(IN_RING3) && defined(VBOX_STRICT)2479 rc = VINF_IOM_R3_IOPORT_WRITE;2480 #else2481 STAM_REL_COUNTER_INC(&pThis->svga.StatRegUnknownWr);2482 AssertMsgFailed(("reg=%#x u32=%#x\n", idxReg, u32));2483 #endif2484 }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 else2528 {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 else2575 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_RING32581 2582 # ifdef DEBUG_FIFO_ACCESS2583 /**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 access2590 */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_HANDLER2948 /*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 # endif2954 2955 # ifdef DEBUG_FIFO_ACCESS2956 /*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 # endif2969 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_ACCESS2979 # ifdef IN_RING32980 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].GCPhys3016 && 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_RING33093 357 3094 358 … … 3110 374 { 3111 375 LogRel2(("vmsvgaR3InstallNewCursor: cx=%d cy=%d xHot=%d yHot=%d fAlpha=%d cbData=%#x\n", cx, cy, xHot, yHot, fAlpha, cbData)); 3112 # 376 #ifdef LOG_ENABLED 3113 377 if (LogIs2Enabled()) 3114 378 { … … 3151 415 } 3152 416 } 3153 # 417 #endif 3154 418 3155 419 int rc = pThisCC->pDrv->pfnVBVAMousePointerShape(pThisCC->pDrv, true /*fVisible*/, fAlpha, xHot, yHot, cx, cy, pbData); … … 3169 433 3170 434 3171 # 435 #ifdef VBOX_WITH_VMSVGA3D 3172 436 /** @def VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK 3173 437 * Check that the 3D command has at least a_cbMin of payload bytes after the 3174 438 * header. Will break out of the switch if it doesn't. 3175 439 */ 3176 # 440 # define VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(a_cbMin) \ 3177 441 if (1) { \ 3178 442 AssertMsgBreak(cbCmd >= (a_cbMin), ("size=%#x a_cbMin=%#zx\n", cbCmd, (size_t)(a_cbMin))); \ … … 3180 444 } else do {} while (0) 3181 445 3182 # 446 # define VMSVGA_3D_CMD_NOTIMPL() \ 3183 447 if (1) { \ 3184 448 AssertMsgFailed(("Not implemented %d %s\n", enmCmdId, vmsvgaR3FifoCmdToString(enmCmdId))); \ … … 3195 459 * @returns VBox status code if an error was detected parsing a command. 3196 460 */ 3197 staticint vmsvgaR3Process3dCmd(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifo3dCmdId enmCmdId, uint32_t cbCmd, void const *pvCmd)461 int vmsvgaR3Process3dCmd(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifo3dCmdId enmCmdId, uint32_t cbCmd, void const *pvCmd) 3198 462 { 3199 463 int rcParse = VINF_SUCCESS; … … 3211 475 vmsvga3dSurfaceDefine(pThisCC, pCmd->sid, (uint32_t)pCmd->surfaceFlags, pCmd->format, pCmd->face, 0, 3212 476 SVGA3D_TEX_FILTER_NONE, cMipLevels, (SVGA3dSize *)(pCmd + 1)); 3213 # 477 # ifdef DEBUG_GMR_ACCESS 3214 478 VMR3ReqCallWaitU(PDMDevHlpGetUVM(pDevIns), VMCPUID_ANY, (PFNRT)vmsvgaR3ResetGmrHandlers, 1, pThis); 3215 # 479 # endif 3216 480 break; 3217 481 } … … 4095 1359 return rcParse; 4096 1360 } 4097 # 4098 # endif // VBOX_WITH_VMSVGA3D1361 # undef VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK 1362 #endif /* VBOX_WITH_VMSVGA3D */ 4099 1363 4100 1364 … … 4112 1376 4113 1377 /* SVGA_CMD_UPDATE */ 4114 staticvoid vmsvgaR3CmdUpdate(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdUpdate const *pCmd)1378 void vmsvgaR3CmdUpdate(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdUpdate const *pCmd) 4115 1379 { 4116 1380 RT_NOREF(pThis); … … 4130 1394 4131 1395 /* SVGA_CMD_UPDATE_VERBOSE */ 4132 staticvoid vmsvgaR3CmdUpdateVerbose(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdUpdateVerbose const *pCmd)1396 void vmsvgaR3CmdUpdateVerbose(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdUpdateVerbose const *pCmd) 4133 1397 { 4134 1398 RT_NOREF(pThis); … … 4148 1412 4149 1413 /* SVGA_CMD_RECT_FILL */ 4150 staticvoid vmsvgaR3CmdRectFill(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdRectFill const *pCmd)1414 void vmsvgaR3CmdRectFill(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdRectFill const *pCmd) 4151 1415 { 4152 1416 RT_NOREF(pThis, pCmd); … … 4160 1424 4161 1425 /* SVGA_CMD_RECT_COPY */ 4162 staticvoid vmsvgaR3CmdRectCopy(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdRectCopy const *pCmd)1426 void vmsvgaR3CmdRectCopy(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdRectCopy const *pCmd) 4163 1427 { 4164 1428 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; … … 4185 1449 4186 1450 /* SVGA_CMD_RECT_ROP_COPY */ 4187 staticvoid vmsvgaR3CmdRectRopCopy(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdRectRopCopy const *pCmd)1451 void vmsvgaR3CmdRectRopCopy(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdRectRopCopy const *pCmd) 4188 1452 { 4189 1453 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; … … 4222 1486 4223 1487 /* SVGA_CMD_DISPLAY_CURSOR */ 4224 staticvoid vmsvgaR3CmdDisplayCursor(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDisplayCursor const *pCmd)1488 void vmsvgaR3CmdDisplayCursor(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDisplayCursor const *pCmd) 4225 1489 { 4226 1490 RT_NOREF(pThis, pCmd); … … 4234 1498 4235 1499 /* SVGA_CMD_MOVE_CURSOR */ 4236 staticvoid vmsvgaR3CmdMoveCursor(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdMoveCursor const *pCmd)1500 void vmsvgaR3CmdMoveCursor(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdMoveCursor const *pCmd) 4237 1501 { 4238 1502 RT_NOREF(pThis, pCmd); … … 4246 1510 4247 1511 /* SVGA_CMD_DEFINE_CURSOR */ 4248 staticvoid vmsvgaR3CmdDefineCursor(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineCursor const *pCmd)1512 void vmsvgaR3CmdDefineCursor(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineCursor const *pCmd) 4249 1513 { 4250 1514 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; … … 4499 1763 4500 1764 /* SVGA_CMD_DEFINE_ALPHA_CURSOR */ 4501 staticvoid vmsvgaR3CmdDefineAlphaCursor(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineAlphaCursor const *pCmd)1765 void vmsvgaR3CmdDefineAlphaCursor(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineAlphaCursor const *pCmd) 4502 1766 { 4503 1767 RT_NOREF(pThis); … … 4531 1795 4532 1796 /* SVGA_CMD_ESCAPE */ 4533 staticvoid vmsvgaR3CmdEscape(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdEscape const *pCmd)1797 void vmsvgaR3CmdEscape(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdEscape const *pCmd) 4534 1798 { 4535 1799 RT_NOREF(pThis); … … 4583 1847 4584 1848 /* SVGA_CMD_DEFINE_SCREEN */ 4585 staticvoid vmsvgaR3CmdDefineScreen(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineScreen const *pCmd)1849 void vmsvgaR3CmdDefineScreen(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineScreen const *pCmd) 4586 1850 { 4587 1851 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; … … 4641 1905 vmsvgaR3ChangeMode(pThis, pThisCC); 4642 1906 4643 # 1907 #ifdef VBOX_WITH_VMSVGA3D 4644 1908 if (RT_LIKELY(pThis->svga.f3DEnabled)) 4645 1909 vmsvga3dDefineScreen(pThis, pThisCC, pScreen); 4646 # 1910 #endif 4647 1911 } 4648 1912 4649 1913 4650 1914 /* SVGA_CMD_DESTROY_SCREEN */ 4651 staticvoid vmsvgaR3CmdDestroyScreen(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDestroyScreen const *pCmd)1915 void vmsvgaR3CmdDestroyScreen(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDestroyScreen const *pCmd) 4652 1916 { 4653 1917 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; … … 4665 1929 pScreen->idScreen = idScreen; 4666 1930 4667 # 1931 #ifdef VBOX_WITH_VMSVGA3D 4668 1932 if (RT_LIKELY(pThis->svga.f3DEnabled)) 4669 1933 vmsvga3dDestroyScreen(pThisCC, pScreen); 4670 # 1934 #endif 4671 1935 vmsvgaR3ChangeMode(pThis, pThisCC); 4672 1936 } … … 4674 1938 4675 1939 /* SVGA_CMD_DEFINE_GMRFB */ 4676 staticvoid vmsvgaR3CmdDefineGMRFB(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineGMRFB const *pCmd)1940 void vmsvgaR3CmdDefineGMRFB(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineGMRFB const *pCmd) 4677 1941 { 4678 1942 RT_NOREF(pThis); … … 4690 1954 4691 1955 /* SVGA_CMD_BLIT_GMRFB_TO_SCREEN */ 4692 staticvoid vmsvgaR3CmdBlitGMRFBToScreen(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdBlitGMRFBToScreen const *pCmd)1956 void vmsvgaR3CmdBlitGMRFBToScreen(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdBlitGMRFBToScreen const *pCmd) 4693 1957 { 4694 1958 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; … … 4761 2025 4762 2026 /* SVGA_CMD_BLIT_SCREEN_TO_GMRFB */ 4763 staticvoid vmsvgaR3CmdBlitScreenToGMRFB(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdBlitScreenToGMRFB const *pCmd)2027 void vmsvgaR3CmdBlitScreenToGMRFB(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdBlitScreenToGMRFB const *pCmd) 4764 2028 { 4765 2029 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; … … 4832 2096 4833 2097 /* SVGA_CMD_ANNOTATION_FILL */ 4834 staticvoid vmsvgaR3CmdAnnotationFill(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdAnnotationFill const *pCmd)2098 void vmsvgaR3CmdAnnotationFill(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdAnnotationFill const *pCmd) 4835 2099 { 4836 2100 RT_NOREF(pThis); … … 4845 2109 4846 2110 /* SVGA_CMD_ANNOTATION_COPY */ 4847 staticvoid vmsvgaR3CmdAnnotationCopy(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdAnnotationCopy const *pCmd)2111 void vmsvgaR3CmdAnnotationCopy(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdAnnotationCopy const *pCmd) 4848 2112 { 4849 2113 RT_NOREF(pThis, pCmd); … … 4857 2121 4858 2122 4859 # 2123 #ifdef VBOX_WITH_VMSVGA3D 4860 2124 /* SVGA_CMD_DEFINE_GMR2 */ 4861 staticvoid vmsvgaR3CmdDefineGMR2(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineGMR2 const *pCmd)2125 void vmsvgaR3CmdDefineGMR2(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineGMR2 const *pCmd) 4862 2126 { 4863 2127 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; … … 4895 2159 4896 2160 /* SVGA_CMD_REMAP_GMR2 */ 4897 staticvoid vmsvgaR3CmdRemapGMR2(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdRemapGMR2 const *pCmd)2161 void vmsvgaR3CmdRemapGMR2(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdRemapGMR2 const *pCmd) 4898 2162 { 4899 2163 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State; … … 5024 2288 RTMemFree(paNewPage64); 5025 2289 } 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 7152 2292 /** 7153 2293 * Free the specified GMR … … 7156 2296 * @param idGMR GMR id 7157 2297 */ 7158 staticvoid vmsvgaR3GmrFree(PVGASTATECC pThisCC, uint32_t idGMR)2298 void vmsvgaR3GmrFree(PVGASTATECC pThisCC, uint32_t idGMR) 7159 2299 { 7160 2300 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State; … … 7180 2320 } 7181 2321 #endif /* VBOX_WITH_VMSVGA3D */ 2322 7182 2323 7183 2324 /** … … 7480 2621 } 7481 2622 2623 7482 2624 /** 7483 2625 * Unsigned coordinates in pBox. Clip to [0; pSize). … … 7507 2649 } 7508 2650 2651 7509 2652 /** 7510 2653 * Clip. … … 7569 2712 } 7570 2713 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 framebuffer7585 *7586 * @param pDevIns The device instance.7587 * @param pThis The shared VGA/VMSVGA instance data.7588 * @param fTraces Enable/disable traces7589 */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 # endif7612 /* 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 else7625 {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.iFIFO7648 && ( enmType == PCI_ADDRESS_SPACE_MEM7649 || (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_ACCESS7665 GCPhysAddress + (pThis->svga.cbFIFO - 1),7666 # else7667 GCPhysAddress + PAGE_SIZE - 1,7668 # endif7669 pThis->svga.hFifoAccessHandlerType, pThis, NIL_RTR0PTR, NIL_RTRCPTR,7670 "VMSVGA FIFO");7671 AssertRC(rc);7672 }7673 # endif7674 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 else7682 {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 # else7688 rc = VINF_SUCCESS;7689 # endif7690 pThis->svga.GCPhysFIFO = 0;7691 }7692 return rc;7693 }7694 7695 # ifdef VBOX_WITH_VMSVGA3D7696 7697 /**7698 * Used by vmsvga3dInfoSurfaceWorker to make the FIFO thread to save one or all7699 * 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. If7705 * 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 the7720 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 ( pszBitmapPath7774 && *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 the7790 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_IOMIOPORTHANDLE7821 ? 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_VMSVGA3D7855 pHlp->pfnPrintf(pHlp, "3D enabled: %RTbool\n", pThis->svga.f3DEnabled);7856 # endif7857 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 else7928 {7929 LogRel(("VGA: ignored screen object %d\n", screen.idScreen));7930 }7931 }7932 }7933 else7934 {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 FNSSMDEVLOADEXEC7955 */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 # endif8049 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 if8073 * 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 explicitly8092 * 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 FNSSMDEVSAVEEXEC8137 */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_CODE8201 if (pSVGAState->hBusyDelayedEmts != NIL_RTSEMEVENTMULTI)8202 {8203 RTSemEventMultiDestroy(pSVGAState->hBusyDelayedEmts);8204 pSVGAState->hBusyDelayedEmts = NIL_RTSEMEVENT;8205 }8206 # endif8207 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_CODE8255 /* Create semaphore for delaying EMTs wait for the FIFO to stop being busy. */8256 rc = RTSemEventMultiCreate(&pSVGAState->hBusyDelayedEmts);8257 AssertRCReturn(rc, rc);8258 # endif8259 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_GMR8278 | SVGA_CAP_GMR28279 | SVGA_CAP_CURSOR8280 | SVGA_CAP_CURSOR_BYPASS8281 | SVGA_CAP_CURSOR_BYPASS_28282 | SVGA_CAP_EXTENDED_FIFO8283 | SVGA_CAP_IRQMASK8284 | SVGA_CAP_PITCHLOCK8285 | SVGA_CAP_RECT_COPY8286 | SVGA_CAP_TRACES8287 | SVGA_CAP_SCREEN_OBJECT_28288 | 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_VMSVGA3D8301 pThis->svga.u32DeviceCaps |= SVGA_CAP_3D;8302 # endif8303 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_FENCE8309 | SVGA_FIFO_CAP_PITCHLOCK8310 | SVGA_FIFO_CAP_CURSOR_BYPASS_38311 | SVGA_FIFO_CAP_RESERVE8312 | SVGA_FIFO_CAP_GMR28313 | SVGA_FIFO_CAP_3D_HWVERSION_REVISED8314 | 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_VMSVGA3D8321 /** 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 else8589 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 else8599 {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 else8605 LogRel(("VMSVGA3d: cap[%u]=failed rc=%Rrc {%s}\n", i, rc, &g_apszVmSvgaDevCapNames[i][1]));8606 }8607 else8608 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_CAP8620 * 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 # endif8643 8644 /**8645 * Resets the SVGA hardware state8646 *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_VMSVGA3D8679 if (pThis->svga.f3DEnabled)8680 vmsvgaR3InitFifo3DCaps(pThis, pThisCC);8681 # endif8682 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 state8699 *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 state8757 *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_VMSVGA3D8797 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 # endif8807 /* 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 programmable8811 * bpp value. On old implementations, SVGA_REG_HOST_BITS_PER_PIXEL did not8812 * exist and SVGA_REG_BITS_PER_PIXEL was read-only, returning what was later8813 * separated as SVGA_REG_HOST_BITS_PER_PIXEL.8814 *8815 * NB: The driver cBits value is currently constant for the lifetime of the8816 * 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_ACCESS8836 /* 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 # endif8844 8845 # if defined(VMSVGA_USE_FIFO_ACCESS_HANDLER) || defined(DEBUG_FIFO_ACCESS)8846 /* Register the FIFO access handler type. In addition to8847 debugging FIFO access, this is also used to facilitate8848 extended fifo thread sleeps. */8849 rc = PGMR3HandlerPhysicalTypeRegister(PDMDevHlpGetVM(pDevIns),8850 # ifdef DEBUG_FIFO_ACCESS8851 PGMPHYSHANDLERKIND_ALL,8852 # else8853 PGMPHYSHANDLERKIND_WRITE,8854 # endif8855 vmsvgaR3FifoAccessHandler,8856 NULL, NULL, NULL,8857 NULL, NULL, NULL,8858 "VMSVGA FIFO", &pThis->svga.hFifoAccessHandlerType);8859 AssertRCReturn(rc, rc);8860 # endif8861 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_STATISTICS8879 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 # endif8883 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 # endif9058 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_CNT9065 # undef REG_PRF9066 9067 /*9068 * Info handlers.9069 */9070 PDMDevHlpDBGFInfoRegister(pDevIns, "vmsvga", "Basic VMSVGA device state details", vmsvgaR3Info);9071 # ifdef VBOX_WITH_VMSVGA3D9072 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 # endif9082 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_VMSVGA3D9097 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 1 1 /* $Id$ */ 2 2 /** @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. 16 4 */ 17 5 … … 28 16 */ 29 17 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 189 30 190 31 … … 212 53 } GMR, *PGMR; 213 54 214 #ifdef IN_RING3215 55 typedef struct VMSVGACMDBUF *PVMSVGACMDBUF; 216 56 typedef struct VMSVGACMDBUFCTX *PVMSVGACMDBUFCTX; … … 375 215 STAMCOUNTER StatFifoWatchdogWakeUps; 376 216 } VMSVGAR3STATE, *PVMSVGAR3STATE; 377 #endif /* IN_RING3 */378 217 379 218 380 219 /********************************************************************************************************************************* 381 * Internal Functions*220 * Functions * 382 221 *********************************************************************************************************************************/ 383 #ifdef IN_RING3384 # if defined(VMSVGA_USE_FIFO_ACCESS_HANDLER) || defined(DEBUG_FIFO_ACCESS)385 static FNPGMPHYSHANDLER vmsvgaR3FifoAccessHandler;386 # endif387 # ifdef DEBUG_GMR_ACCESS388 static FNPGMPHYSHANDLER vmsvgaR3GmrAccessHandler;389 # endif390 #endif391 392 393 /*********************************************************************************************************************************394 * Global Variables *395 *********************************************************************************************************************************/396 #ifdef IN_RING3397 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_CODE456 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, BusyDelayedEmts),457 #else458 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, hBusyDelayedEmts),459 #endif460 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 # endif539 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_RING3599 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_VMSVGA3D605 static void vmsvgaR3GmrFree(PVGASTATECC pThisCC, uint32_t idGMR);606 # endif /* VBOX_WITH_VMSVGA3D */607 #endif /* IN_RING3 */608 609 610 611 #ifdef IN_RING3612 VMSVGASCREENOBJECT *vmsvgaR3GetScreenObject(PVGASTATECC pThisCC, uint32_t idScreen)613 {614 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;615 if ( idScreen < (uint32_t)RT_ELEMENTS(pSVGAState->aScreens)616 && pSVGAState617 && 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_VMSVGA3D627 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 # else637 RT_NOREF(pThis, pThisCC);638 # endif639 }640 #endif /* IN_RING3 */641 642 #define SVGA_CASE_ID2STR(idx) case idx: return #idx643 644 #if defined(LOG_ENABLED)645 /**646 * Index register string name lookup647 *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 lookup735 *736 * @returns FIFO command string or "UNKNOWN"737 * @param u32Cmd FIFO command738 */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_RING3964 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 else988 {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 else1001 {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_VMSVGA3D1009 /*1010 * Now inform the 3D backend.1011 */1012 if (pThis->svga.f3DEnabled)1013 vmsvga3dUpdateHostScreenViewport(pThisCC, idScreen, &OldViewport);1014 # else1015 RT_NOREF(OldViewport);1016 # endif1017 }1018 1019 1020 /**1021 * Updating screen information in API1022 *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_UNINITIALIZED1054 || pScreen->cHeight == VMSVGA_VAL_UNINITIALIZED1055 || 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 else1074 {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 to1089 * 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].x1104 && 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 register1124 *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 value1129 */1130 static int vmsvgaReadPort(PPDMDEVINS pDevIns, PVGASTATE pThis, uint32_t *pu32)1131 {1132 #ifdef IN_RING31133 PVGASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);1134 #endif1135 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 #else1144 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 #endif1148 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_TOP1152 && 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.fEnabled1174 && pThis->svga.uWidth != VMSVGA_VAL_UNINITIALIZED)1175 *pu32 = pThis->svga.uWidth;1176 else1177 {1178 #ifndef IN_RING31179 rc = VINF_IOM_R3_IOPORT_READ;1180 #else1181 *pu32 = pThisCC->pDrv->cx;1182 #endif1183 }1184 break;1185 }1186 1187 case SVGA_REG_HEIGHT:1188 {1189 STAM_REL_COUNTER_INC(&pThis->svga.StatRegHeightRd);1190 if ( pThis->svga.fEnabled1191 && pThis->svga.uHeight != VMSVGA_VAL_UNINITIALIZED)1192 *pu32 = pThis->svga.uHeight;1193 else1194 {1195 #ifndef IN_RING31196 rc = VINF_IOM_R3_IOPORT_READ;1197 #else1198 *pu32 = pThisCC->pDrv->cy;1199 #endif1200 }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 else1256 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.fEnabled1311 && pThis->svga.cbScanline)1312 *pu32 = pThis->svga.cbScanline;1313 else1314 {1315 #ifndef IN_RING31316 rc = VINF_IOM_R3_IOPORT_READ;1317 #else1318 *pu32 = pThisCC->pDrv->cbScanline;1319 #endif1320 }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_RING31344 rc = VINF_IOM_R3_IOPORT_READ;1345 #else1346 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.fEnabled1350 && 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 else1356 *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 #endif1361 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_RING31395 /* Go to ring-3 and halt the CPU. */1396 rc = VINF_IOM_R3_IOPORT_READ;1397 RT_NOREF(pDevIns);1398 break;1399 #else1400 # if defined(VMSVGA_USE_EMT_HALT_CODE)1401 /* The guest is basically doing a HLT via the device here, but with1402 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 # else1418 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 be1421 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/wait1434 * code in VMEmt.cpp here, otherwise all kind of EMT interaction will1435 * 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 # endif1447 *pu32 = pThis->svga.fBusy != 0;1448 #endif1449 }1450 else1451 *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 driver1580 will take a legacy code path without 3d support. This number also1581 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 else1621 *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 else1673 {1674 #if !defined(IN_RING3) && defined(VBOX_STRICT)1675 rc = VINF_IOM_R3_IOPORT_READ;1676 #else1677 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 #endif1682 }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_RING31691 /**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 device1711 * deletes all screens other than screen #0, and redefines screen1712 * #0 according to the specified mode. Drivers that use1713 * 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 else1741 {1742 /* "If Screen Objects are supported, they can be used to fully1743 * replace the functionality provided by the framebuffer registers1744 * (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 == 01762 && 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 do1809 {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 mode1820 * 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 past1833 * it. If SVGA_FIFO_MIN is small, there may well be data at the SVGA_FIFO_PITCHLOCK1834 * 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 else1851 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_RING31860 1861 /**1862 * Sends cursor position and visibility information from legacy1863 * 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 the1869 * 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_ON1871 * 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 values1881 * were extended as follows:1882 *1883 * SVGA_CURSOR_ON_HIDE 01884 * SVGA_CURSOR_ON_SHOW 11885 * SVGA_CURSOR_ON_REMOVE_FROM_FB 2 - cursor on but not in the framebuffer1886 * SVGA_CURSOR_ON_RESTORE_TO_FB 3 - cursor on, possibly in the framebuffer1887 *1888 * Since we never draw the cursor into the guest's framebuffer, we do not need to1889 * 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 format1912 * 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 else1943 {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 register1961 *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 write1967 */1968 static VBOXSTRICTRC vmsvgaWritePort(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, uint32_t u32)1969 {1970 #ifdef IN_RING31971 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;1972 #endif1973 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 #else1982 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 #endif1986 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_TOP1990 && 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_02014 || u32 == SVGA_ID_12015 || u32 == SVGA_ID_2)2016 pThis->svga.u32SVGAId = u32;2017 else2018 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_RING32024 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_UNINITIALIZED2037 && 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_UNINITIALIZED2046 && pThis->svga.uHeight != VMSVGA_VAL_UNINITIALIZED)2047 ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE);2048 # ifdef LOG_ENABLED2049 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 # endif2053 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 else2066 {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 #else2101 rc = VINF_IOM_R3_IOPORT_WRITE;2102 #endif2103 }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 #else2133 rc = VINF_IOM_R3_IOPORT_WRITE;2134 #endif2135 }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_RING32145 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 #else2152 rc = VINF_IOM_R3_IOPORT_WRITE;2153 #endif2154 break;2155 2156 case SVGA_REG_SYNC: /* See "FIFO Synchronization Registers" */2157 STAM_REL_COUNTER_INC(&pThis->svga.StatRegSyncWr);2158 if ( pThis->svga.fEnabled2159 && 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 empty2165 * 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 #else2174 rc = VINF_IOM_R3_IOPORT_WRITE;2175 #endif2176 }2177 /* else nothing to do. */2178 else2179 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 else2209 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_RING32230 /* 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 #else2234 rc = VINF_IOM_R3_IOPORT_WRITE;2235 #endif2236 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_VMSVGA3D2261 /* 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_RING32269 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 else2347 {2348 RTMemFree(paDescs);2349 STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegGmrDescriptorWrErrors);2350 }2351 break;2352 }2353 # endif /* IN_RING3 */2354 #endif // VBOX_WITH_VMSVGA3D2355 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_RING32362 vmsvgaR3SetTraces(pDevIns, pThis, !!u32);2363 #else2364 rc = VINF_IOM_R3_IOPORT_WRITE;2365 #endif2366 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_RING32384 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 #else2394 rc = VINF_IOM_R3_IOPORT_WRITE;2395 #endif2396 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 else2477 {2478 #if !defined(IN_RING3) && defined(VBOX_STRICT)2479 rc = VINF_IOM_R3_IOPORT_WRITE;2480 #else2481 STAM_REL_COUNTER_INC(&pThis->svga.StatRegUnknownWr);2482 AssertMsgFailed(("reg=%#x u32=%#x\n", idxReg, u32));2483 #endif2484 }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 else2528 {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 else2575 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_RING32581 2582 # ifdef DEBUG_FIFO_ACCESS2583 /**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 access2590 */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_HANDLER2948 /*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 # endif2954 2955 # ifdef DEBUG_FIFO_ACCESS2956 /*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 # endif2969 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 222 #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 */ 223 DECLCALLBACK(int) vmsvgaR3ResetGmrHandlers(PVGASTATE pThis); 224 DECLCALLBACK(int) vmsvgaR3DeregisterGmr(PPDMDEVINS pDevIns, uint32_t gmrId); 225 #endif 226 227 void vmsvgaR3ResetScreens(PVGASTATE pThis, PVGASTATECC pThisCC); 228 229 int vmsvgaR3ChangeMode(PVGASTATE pThis, PVGASTATECC pThisCC); 230 int vmsvgaR3UpdateScreen(PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen, int x, int y, int w, int h); 231 7200 232 int vmsvgaR3GmrTransfer(PVGASTATE pThis, PVGASTATECC pThisCC, const SVGA3dTransferType enmTransferType, 7201 233 uint8_t *pbHstBuf, uint32_t cbHstBuf, uint32_t offHst, int32_t cbHstPitch, 7202 234 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); 236 void vmsvgaR3GmrFree(PVGASTATECC pThisCC, uint32_t idGMR); 237 238 void vmsvgaR3CmdUpdate(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdUpdate const *pCmd); 239 void vmsvgaR3CmdUpdateVerbose(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdUpdateVerbose const *pCmd); 240 void vmsvgaR3CmdRectFill(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdRectFill const *pCmd); 241 void vmsvgaR3CmdRectCopy(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdRectCopy const *pCmd); 242 void vmsvgaR3CmdRectRopCopy(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdRectRopCopy const *pCmd); 243 void vmsvgaR3CmdDisplayCursor(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDisplayCursor const *pCmd); 244 void vmsvgaR3CmdMoveCursor(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdMoveCursor const *pCmd); 245 void vmsvgaR3CmdDefineCursor(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineCursor const *pCmd); 246 void vmsvgaR3CmdDefineAlphaCursor(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineAlphaCursor const *pCmd); 247 void vmsvgaR3CmdEscape(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdEscape const *pCmd); 248 void vmsvgaR3CmdDefineScreen(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineScreen const *pCmd); 249 void vmsvgaR3CmdDestroyScreen(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDestroyScreen const *pCmd); 250 void vmsvgaR3CmdDefineGMRFB(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineGMRFB const *pCmd); 251 void vmsvgaR3CmdBlitGMRFBToScreen(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdBlitGMRFBToScreen const *pCmd); 252 void vmsvgaR3CmdBlitScreenToGMRFB(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdBlitScreenToGMRFB const *pCmd); 253 void vmsvgaR3CmdAnnotationFill(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdAnnotationFill const *pCmd); 254 void vmsvgaR3CmdAnnotationCopy(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdAnnotationCopy const *pCmd); 255 256 #ifdef VBOX_WITH_VMSVGA3D 257 void vmsvgaR3CmdDefineGMR2(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdDefineGMR2 const *pCmd); 258 void vmsvgaR3CmdRemapGMR2(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifoCmdRemapGMR2 const *pCmd); 259 int vmsvgaR3Process3dCmd(PVGASTATE pThis, PVGASTATECC pThisCC, SVGAFifo3dCmdId enmCmdId, uint32_t cbCmd, void const *pvCmd); 260 #endif 261 262 #if defined(LOG_ENABLED) || defined(VBOX_STRICT) 263 const 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 162 162 163 163 #include "DevVGA-SVGA.h" 164 #ifdef IN_RING3 165 #include "DevVGA-SVGA-internal.h" 166 #endif 164 167 #ifdef VBOX_WITH_VMSVGA3D 165 168 # include "DevVGA-SVGA3d.h" … … 192 195 * Structures and Typedefs * 193 196 *********************************************************************************************************************************/ 194 /**195 * 64-bit GMR descriptor.196 */197 typedef struct198 {199 RTGCPHYS GCPhys;200 uint64_t numPages;201 } VMSVGAGMRDESCRIPTOR, *PVMSVGAGMRDESCRIPTOR;202 203 /**204 * GMR slot205 */206 typedef struct207 {208 uint32_t cMaxPages;209 uint32_t cbTotal;210 uint32_t numDescriptors;211 PVMSVGAGMRDESCRIPTOR paDesc;212 } GMR, *PGMR;213 214 #ifdef IN_RING3215 typedef struct VMSVGACMDBUF *PVMSVGACMDBUF;216 typedef struct VMSVGACMDBUFCTX *PVMSVGACMDBUFCTX;217 218 /* Command buffer. */219 typedef struct VMSVGACMDBUF220 {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 VMSVGACMDBUFCTX234 {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 VMSVGAR3STATE245 {246 GMR *paGMR; // [VMSVGAState::cGMR]247 struct248 {249 SVGAGuestPtr RT_UNTRUSTED_GUEST ptr;250 uint32_t RT_UNTRUSTED_GUEST bytesPerLine;251 SVGAGMRImageFormat RT_UNTRUSTED_GUEST format;252 } GMRFB;253 struct254 {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_CODE266 /** 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 # else271 /** 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 is274 * busy (ugly). */275 RTSEMEVENTMULTI hBusyDelayedEmts;276 # endif277 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_HANDLER369 STAMCOUNTER StatFifoAccessHandler;370 # endif371 STAMCOUNTER StatFifoCursorFetchAgain;372 STAMCOUNTER StatFifoCursorNoChange;373 STAMCOUNTER StatFifoCursorPosition;374 STAMCOUNTER StatFifoCursorVisiblity;375 STAMCOUNTER StatFifoWatchdogWakeUps;376 } VMSVGAR3STATE, *PVMSVGAR3STATE;377 #endif /* IN_RING3 */378 197 379 198 … … 602 421 static int vmsvgaR3SaveExecFifo(PCPDMDEVHLPR3 pHlp, PVGASTATECC pThisCC, PSSMHANDLE pSSM); 603 422 static void vmsvgaR3CmdBufSubmit(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, RTGCPHYS GCPhysCB, SVGACBContext CBCtx); 604 # ifdef VBOX_WITH_VMSVGA3D605 static void vmsvgaR3GmrFree(PVGASTATECC pThisCC, uint32_t idGMR);606 # endif /* VBOX_WITH_VMSVGA3D */607 423 #endif /* IN_RING3 */ 608 424 609 425 610 611 #ifdef IN_RING3612 VMSVGASCREENOBJECT *vmsvgaR3GetScreenObject(PVGASTATECC pThisCC, uint32_t idScreen)613 {614 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;615 if ( idScreen < (uint32_t)RT_ELEMENTS(pSVGAState->aScreens)616 && pSVGAState617 && 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_VMSVGA3D627 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 # else637 RT_NOREF(pThis, pThisCC);638 # endif639 }640 #endif /* IN_RING3 */641 642 #define SVGA_CASE_ID2STR(idx) case idx: return #idx643 644 426 #if defined(LOG_ENABLED) 427 # define SVGA_CASE_ID2STR(idx) case idx: return #idx 645 428 /** 646 429 * Index register string name lookup … … 728 511 } 729 512 } 513 # undef SVGA_CASE_ID2STR 730 514 #endif /* LOG_ENABLED */ 731 515 732 #if defined(IN_RING3) && (defined(LOG_ENABLED) || defined(VBOX_STRICT))733 /**734 * FIFO command name lookup735 *736 * @returns FIFO command string or "UNKNOWN"737 * @param u32Cmd FIFO command738 */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 516 963 517 #ifdef IN_RING3 … … 1696 1250 * @param pThisCC The ring-3 VGA state. 1697 1251 */ 1698 staticint vmsvgaR3ChangeMode(PVGASTATE pThis, PVGASTATECC pThisCC)1252 int vmsvgaR3ChangeMode(PVGASTATE pThis, PVGASTATECC pThisCC) 1699 1253 { 1700 1254 /* Always do changemode on FIFO thread. */ … … 1896 1450 pThis->svga.uCursorOn = uCursorOn; 1897 1451 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 format1912 * 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 else1943 {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 1452 } 1955 1453 … … 3093 2591 3094 2592 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_ENABLED3113 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 # endif3154 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_VMSVGA3D3172 /** @def VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK3173 * Check that the 3D command has at least a_cbMin of payload bytes after the3174 * 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_ACCESS3214 VMR3ReqCallWaitU(PDMDevHlpGetUVM(pDevIns), VMCPUID_ANY, (PFNRT)vmsvgaR3ResetGmrHandlers, 1, pThis);3215 # endif3216 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 else3474 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_BREAK4098 # endif // VBOX_WITH_VMSVGA3D4099 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 same4197 * 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 when4199 * 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 else4293 {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 do4312 {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 do4335 {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 do4355 {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 do4375 {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 do4395 {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 do4425 {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 else4580 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 else4636 {4637 /* Screen blanked. Keep old values. */4638 }4639 4640 pThis->svga.fGFBRegisters = false;4641 vmsvgaR3ChangeMode(pThis, pThisCC);4642 4643 # ifdef VBOX_WITH_VMSVGA3D4644 if (RT_LIKELY(pThis->svga.f3DEnabled))4645 vmsvga3dDefineScreen(pThis, pThisCC, pScreen);4646 # endif4647 }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_VMSVGA3D4668 if (RT_LIKELY(pThis->svga.f3DEnabled))4669 vmsvga3dDestroyScreen(pThisCC, pScreen);4670 # endif4671 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 == 04723 || 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)) / 84744 + 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)) / 84750 + 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 == 04795 || 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)) / 84816 + 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)) / 84822 + 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_VMSVGA3D4860 /* 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 else4879 {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 simplicity4885 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->numPages4909 <= 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 the4921 * 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 else4958 {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 else4971 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 else4980 cPages = pCmd->numPages;4981 4982 /* The first page. */4983 /** @todo The 0x00000FFFFFFFFFFF mask limits to 44 bits and should not be4984 * 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 else4989 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 else5000 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 else5010 {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_VMSVGA3D5027 5028 5029 2593 /* 5030 2594 * … … 5857 3421 } 5858 3422 else 5859 # endif / / VBOX_WITH_VMSVGA3D3423 # endif /* VBOX_WITH_VMSVGA3D */ 5860 3424 { 5861 3425 /* Unsupported command. */ … … 7148 4712 #undef VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK 7149 4713 #undef VMSVGAFIFO_GET_CMD_BUFFER_BREAK 7150 7151 #ifdef VBOX_WITH_VMSVGA3D7152 /**7153 * Free the specified GMR7154 *7155 * @param pThisCC The VGA/VMSVGA state for ring-3.7156 * @param idGMR GMR id7157 */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->numDescriptors7165 || pGMR->paDesc /* needed till we implement SVGA_REMAP_GMR2_VIA_GMR */)7166 {7167 # ifdef DEBUG_GMR_ACCESS7168 VMR3ReqCallWaitU(PDMDevHlpGetUVM(pThisCC->pDevIns), VMCPUID_ANY, (PFNRT)vmsvgaR3DeregisterGmr, 2, pDevIns, idGMR);7169 # endif7170 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 scanline7193 * @param cbHstPitch Destination buffer pitch7194 * @param gstPtr GMR description7195 * @param offGst Guest buffer offset of the first scanline7196 * @param cbGstPitch Guest buffer pitch7197 * @param cbWidth Width in bytes to copy7198 * @param cHeight Number of scanllines to copy7199 */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 else7223 {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 * GMR7232 */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 else7341 {7342 pbSrc = pbGst;7343 cbSrcPitch = cbGstPitch;7344 pbDst = pbHst;7345 cbDstPitch = cbHstPitch;7346 }7347 7348 if ( cbWidth == (uint32_t)cbGstPitch7349 && cbGstPitch == cbHstPitch)7350 {7351 /* Entire scanlines, positive pitch. */7352 memcpy(pbDst, pbSrc, cbWidth * cHeight);7353 }7354 else7355 {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 else7399 {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 else7411 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 else7530 {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 else7540 {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 4714 7571 4715 /** -
trunk/src/VBox/Devices/Makefile.kmk
r86043 r86265 303 303 VBoxDD_DEFS += VBOX_WITH_VMSVGA 304 304 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 306 308 endif 307 309 ifdef VBOX_WITH_VMSVGA3D
Note:
See TracChangeset
for help on using the changeset viewer.