VirtualBox

source: vbox/trunk/src/VBox/Devices/Graphics/DevVGA-SVGA.cpp@ 86252

Last change on this file since 86252 was 86252, checked in by vboxsync, 5 years ago

Devices/Graphics: Build fix.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 381.0 KB
Line 
1/* $Id: DevVGA-SVGA.cpp 86252 2020-09-23 19:06:31Z vboxsync $ */
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.
16 */
17
18/*
19 * Copyright (C) 2013-2020 Oracle Corporation
20 *
21 * This file is part of VirtualBox Open Source Edition (OSE), as
22 * available from http://www.virtualbox.org. This file is free software;
23 * you can redistribute it and/or modify it under the terms of the GNU
24 * General Public License (GPL) as published by the Free Software
25 * Foundation, in version 2 as it comes in the "COPYING" file of the
26 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
27 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
28 */
29
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) )
189
190
191/*********************************************************************************************************************************
192* Structures and Typedefs *
193*********************************************************************************************************************************/
194/**
195 * 64-bit GMR descriptor.
196 */
197typedef struct
198{
199 RTGCPHYS GCPhys;
200 uint64_t numPages;
201} VMSVGAGMRDESCRIPTOR, *PVMSVGAGMRDESCRIPTOR;
202
203/**
204 * GMR slot
205 */
206typedef 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
215typedef struct VMSVGACMDBUF *PVMSVGACMDBUF;
216typedef struct VMSVGACMDBUFCTX *PVMSVGACMDBUFCTX;
217
218/* Command buffer. */
219typedef 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. */
233typedef 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 */
244typedef 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)
385static FNPGMPHYSHANDLER vmsvgaR3FifoAccessHandler;
386# endif
387# ifdef DEBUG_GMR_ACCESS
388static 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 */
401static 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 */
411static 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 */
423static 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 */
442static 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 */
550static 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
599static void vmsvgaR3SetTraces(PPDMDEVINS pDevIns, PVGASTATE pThis, bool fTraces);
600static int vmsvgaR3LoadExecFifo(PCPDMDEVHLPR3 pHlp, PVGASTATE pThis, PVGASTATECC pThisCC, PSSMHANDLE pSSM,
601 uint32_t uVersion, uint32_t uPass);
602static int vmsvgaR3SaveExecFifo(PCPDMDEVHLPR3 pHlp, PVGASTATECC pThisCC, PSSMHANDLE pSSM);
603static void vmsvgaR3CmdBufSubmit(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, RTGCPHYS GCPhysCB, SVGACBContext CBCtx);
604# ifdef VBOX_WITH_VMSVGA3D
605static void vmsvgaR3GmrFree(PVGASTATECC pThisCC, uint32_t idGMR);
606# endif /* VBOX_WITH_VMSVGA3D */
607#endif /* IN_RING3 */
608
609
610
611#ifdef IN_RING3
612VMSVGASCREENOBJECT *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
624void 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 */
652static const char *vmsvgaIndexToString(PVGASTATE pThis, uint32_t idxReg)
653{
654 switch (idxReg)
655 {
656 SVGA_CASE_ID2STR(SVGA_REG_ID);
657 SVGA_CASE_ID2STR(SVGA_REG_ENABLE);
658 SVGA_CASE_ID2STR(SVGA_REG_WIDTH);
659 SVGA_CASE_ID2STR(SVGA_REG_HEIGHT);
660 SVGA_CASE_ID2STR(SVGA_REG_MAX_WIDTH);
661 SVGA_CASE_ID2STR(SVGA_REG_MAX_HEIGHT);
662 SVGA_CASE_ID2STR(SVGA_REG_DEPTH);
663 SVGA_CASE_ID2STR(SVGA_REG_BITS_PER_PIXEL); /* Current bpp in the guest */
664 SVGA_CASE_ID2STR(SVGA_REG_PSEUDOCOLOR);
665 SVGA_CASE_ID2STR(SVGA_REG_RED_MASK);
666 SVGA_CASE_ID2STR(SVGA_REG_GREEN_MASK);
667 SVGA_CASE_ID2STR(SVGA_REG_BLUE_MASK);
668 SVGA_CASE_ID2STR(SVGA_REG_BYTES_PER_LINE);
669 SVGA_CASE_ID2STR(SVGA_REG_FB_START); /* (Deprecated) */
670 SVGA_CASE_ID2STR(SVGA_REG_FB_OFFSET);
671 SVGA_CASE_ID2STR(SVGA_REG_VRAM_SIZE);
672 SVGA_CASE_ID2STR(SVGA_REG_FB_SIZE);
673
674 /* ID 0 implementation only had the above registers, then the palette */
675 SVGA_CASE_ID2STR(SVGA_REG_CAPABILITIES);
676 SVGA_CASE_ID2STR(SVGA_REG_MEM_START); /* (Deprecated) */
677 SVGA_CASE_ID2STR(SVGA_REG_MEM_SIZE);
678 SVGA_CASE_ID2STR(SVGA_REG_CONFIG_DONE); /* Set when memory area configured */
679 SVGA_CASE_ID2STR(SVGA_REG_SYNC); /* See "FIFO Synchronization Registers" */
680 SVGA_CASE_ID2STR(SVGA_REG_BUSY); /* See "FIFO Synchronization Registers" */
681 SVGA_CASE_ID2STR(SVGA_REG_GUEST_ID); /* Set guest OS identifier */
682 SVGA_CASE_ID2STR(SVGA_REG_CURSOR_ID); /* (Deprecated) */
683 SVGA_CASE_ID2STR(SVGA_REG_CURSOR_X); /* (Deprecated) */
684 SVGA_CASE_ID2STR(SVGA_REG_CURSOR_Y); /* (Deprecated) */
685 SVGA_CASE_ID2STR(SVGA_REG_CURSOR_ON); /* (Deprecated) */
686 SVGA_CASE_ID2STR(SVGA_REG_HOST_BITS_PER_PIXEL); /* (Deprecated) */
687 SVGA_CASE_ID2STR(SVGA_REG_SCRATCH_SIZE); /* Number of scratch registers */
688 SVGA_CASE_ID2STR(SVGA_REG_MEM_REGS); /* Number of FIFO registers */
689 SVGA_CASE_ID2STR(SVGA_REG_NUM_DISPLAYS); /* (Deprecated) */
690 SVGA_CASE_ID2STR(SVGA_REG_PITCHLOCK); /* Fixed pitch for all modes */
691 SVGA_CASE_ID2STR(SVGA_REG_IRQMASK); /* Interrupt mask */
692
693 /* Legacy multi-monitor support */
694 SVGA_CASE_ID2STR(SVGA_REG_NUM_GUEST_DISPLAYS); /* Number of guest displays in X/Y direction */
695 SVGA_CASE_ID2STR(SVGA_REG_DISPLAY_ID); /* Display ID for the following display attributes */
696 SVGA_CASE_ID2STR(SVGA_REG_DISPLAY_IS_PRIMARY); /* Whether this is a primary display */
697 SVGA_CASE_ID2STR(SVGA_REG_DISPLAY_POSITION_X); /* The display position x */
698 SVGA_CASE_ID2STR(SVGA_REG_DISPLAY_POSITION_Y); /* The display position y */
699 SVGA_CASE_ID2STR(SVGA_REG_DISPLAY_WIDTH); /* The display's width */
700 SVGA_CASE_ID2STR(SVGA_REG_DISPLAY_HEIGHT); /* The display's height */
701
702 SVGA_CASE_ID2STR(SVGA_REG_GMR_ID);
703 SVGA_CASE_ID2STR(SVGA_REG_GMR_DESCRIPTOR);
704 SVGA_CASE_ID2STR(SVGA_REG_GMR_MAX_IDS);
705 SVGA_CASE_ID2STR(SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH);
706
707 SVGA_CASE_ID2STR(SVGA_REG_TRACES); /* Enable trace-based updates even when FIFO is on */
708 SVGA_CASE_ID2STR(SVGA_REG_GMRS_MAX_PAGES); /* Maximum number of 4KB pages for all GMRs */
709 SVGA_CASE_ID2STR(SVGA_REG_MEMORY_SIZE); /* Total dedicated device memory excluding FIFO */
710 SVGA_CASE_ID2STR(SVGA_REG_COMMAND_LOW); /* Lower 32 bits and submits commands */
711 SVGA_CASE_ID2STR(SVGA_REG_COMMAND_HIGH); /* Upper 32 bits of command buffer PA */
712 SVGA_CASE_ID2STR(SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM); /* Max primary memory */
713 SVGA_CASE_ID2STR(SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB); /* Suggested limit on mob mem */
714 SVGA_CASE_ID2STR(SVGA_REG_DEV_CAP); /* Write dev cap index, read value */
715 SVGA_CASE_ID2STR(SVGA_REG_CMD_PREPEND_LOW);
716 SVGA_CASE_ID2STR(SVGA_REG_iCMD_PREPEND_HIGH);
717 SVGA_CASE_ID2STR(SVGA_REG_SCREENTARGET_MAX_WIDTH);
718 SVGA_CASE_ID2STR(SVGA_REG_SCREENTARGET_MAX_HEIGHT);
719 SVGA_CASE_ID2STR(SVGA_REG_MOB_MAX_SIZE);
720 SVGA_CASE_ID2STR(SVGA_REG_TOP); /* Must be 1 more than the last register */
721
722 default:
723 if (idxReg - (uint32_t)SVGA_SCRATCH_BASE < pThis->svga.cScratchRegion)
724 return "SVGA_SCRATCH_BASE reg";
725 if (idxReg - (uint32_t)SVGA_PALETTE_BASE < (uint32_t)SVGA_NUM_PALETTE_REGS)
726 return "SVGA_PALETTE_BASE reg";
727 return "UNKNOWN";
728 }
729}
730#endif /* LOG_ENABLED */
731
732#if defined(IN_RING3) && (defined(LOG_ENABLED) || defined(VBOX_STRICT))
733/**
734 * FIFO command name lookup
735 *
736 * @returns FIFO command string or "UNKNOWN"
737 * @param u32Cmd FIFO command
738 */
739static const char *vmsvgaR3FifoCmdToString(uint32_t u32Cmd)
740{
741 switch (u32Cmd)
742 {
743 SVGA_CASE_ID2STR(SVGA_CMD_INVALID_CMD);
744 SVGA_CASE_ID2STR(SVGA_CMD_UPDATE);
745 SVGA_CASE_ID2STR(SVGA_CMD_RECT_FILL);
746 SVGA_CASE_ID2STR(SVGA_CMD_RECT_COPY);
747 SVGA_CASE_ID2STR(SVGA_CMD_RECT_ROP_COPY);
748 SVGA_CASE_ID2STR(SVGA_CMD_DEFINE_CURSOR);
749 SVGA_CASE_ID2STR(SVGA_CMD_DISPLAY_CURSOR);
750 SVGA_CASE_ID2STR(SVGA_CMD_MOVE_CURSOR);
751 SVGA_CASE_ID2STR(SVGA_CMD_DEFINE_ALPHA_CURSOR);
752 SVGA_CASE_ID2STR(SVGA_CMD_UPDATE_VERBOSE);
753 SVGA_CASE_ID2STR(SVGA_CMD_FRONT_ROP_FILL);
754 SVGA_CASE_ID2STR(SVGA_CMD_FENCE);
755 SVGA_CASE_ID2STR(SVGA_CMD_ESCAPE);
756 SVGA_CASE_ID2STR(SVGA_CMD_DEFINE_SCREEN);
757 SVGA_CASE_ID2STR(SVGA_CMD_DESTROY_SCREEN);
758 SVGA_CASE_ID2STR(SVGA_CMD_DEFINE_GMRFB);
759 SVGA_CASE_ID2STR(SVGA_CMD_BLIT_GMRFB_TO_SCREEN);
760 SVGA_CASE_ID2STR(SVGA_CMD_BLIT_SCREEN_TO_GMRFB);
761 SVGA_CASE_ID2STR(SVGA_CMD_ANNOTATION_FILL);
762 SVGA_CASE_ID2STR(SVGA_CMD_ANNOTATION_COPY);
763 SVGA_CASE_ID2STR(SVGA_CMD_DEFINE_GMR2);
764 SVGA_CASE_ID2STR(SVGA_CMD_REMAP_GMR2);
765 SVGA_CASE_ID2STR(SVGA_CMD_DEAD);
766 SVGA_CASE_ID2STR(SVGA_CMD_DEAD_2);
767 SVGA_CASE_ID2STR(SVGA_CMD_NOP);
768 SVGA_CASE_ID2STR(SVGA_CMD_NOP_ERROR);
769 SVGA_CASE_ID2STR(SVGA_CMD_MAX);
770 SVGA_CASE_ID2STR(SVGA_3D_CMD_SURFACE_DEFINE);
771 SVGA_CASE_ID2STR(SVGA_3D_CMD_SURFACE_DESTROY);
772 SVGA_CASE_ID2STR(SVGA_3D_CMD_SURFACE_COPY);
773 SVGA_CASE_ID2STR(SVGA_3D_CMD_SURFACE_STRETCHBLT);
774 SVGA_CASE_ID2STR(SVGA_3D_CMD_SURFACE_DMA);
775 SVGA_CASE_ID2STR(SVGA_3D_CMD_CONTEXT_DEFINE);
776 SVGA_CASE_ID2STR(SVGA_3D_CMD_CONTEXT_DESTROY);
777 SVGA_CASE_ID2STR(SVGA_3D_CMD_SETTRANSFORM);
778 SVGA_CASE_ID2STR(SVGA_3D_CMD_SETZRANGE);
779 SVGA_CASE_ID2STR(SVGA_3D_CMD_SETRENDERSTATE);
780 SVGA_CASE_ID2STR(SVGA_3D_CMD_SETRENDERTARGET);
781 SVGA_CASE_ID2STR(SVGA_3D_CMD_SETTEXTURESTATE);
782 SVGA_CASE_ID2STR(SVGA_3D_CMD_SETMATERIAL);
783 SVGA_CASE_ID2STR(SVGA_3D_CMD_SETLIGHTDATA);
784 SVGA_CASE_ID2STR(SVGA_3D_CMD_SETLIGHTENABLED);
785 SVGA_CASE_ID2STR(SVGA_3D_CMD_SETVIEWPORT);
786 SVGA_CASE_ID2STR(SVGA_3D_CMD_SETCLIPPLANE);
787 SVGA_CASE_ID2STR(SVGA_3D_CMD_CLEAR);
788 SVGA_CASE_ID2STR(SVGA_3D_CMD_PRESENT);
789 SVGA_CASE_ID2STR(SVGA_3D_CMD_SHADER_DEFINE);
790 SVGA_CASE_ID2STR(SVGA_3D_CMD_SHADER_DESTROY);
791 SVGA_CASE_ID2STR(SVGA_3D_CMD_SET_SHADER);
792 SVGA_CASE_ID2STR(SVGA_3D_CMD_SET_SHADER_CONST);
793 SVGA_CASE_ID2STR(SVGA_3D_CMD_DRAW_PRIMITIVES);
794 SVGA_CASE_ID2STR(SVGA_3D_CMD_SETSCISSORRECT);
795 SVGA_CASE_ID2STR(SVGA_3D_CMD_BEGIN_QUERY);
796 SVGA_CASE_ID2STR(SVGA_3D_CMD_END_QUERY);
797 SVGA_CASE_ID2STR(SVGA_3D_CMD_WAIT_FOR_QUERY);
798 SVGA_CASE_ID2STR(SVGA_3D_CMD_PRESENT_READBACK);
799 SVGA_CASE_ID2STR(SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN);
800 SVGA_CASE_ID2STR(SVGA_3D_CMD_SURFACE_DEFINE_V2);
801 SVGA_CASE_ID2STR(SVGA_3D_CMD_GENERATE_MIPMAPS);
802 SVGA_CASE_ID2STR(SVGA_3D_CMD_VIDEO_CREATE_DECODER);
803 SVGA_CASE_ID2STR(SVGA_3D_CMD_VIDEO_DESTROY_DECODER);
804 SVGA_CASE_ID2STR(SVGA_3D_CMD_VIDEO_CREATE_PROCESSOR);
805 SVGA_CASE_ID2STR(SVGA_3D_CMD_VIDEO_DESTROY_PROCESSOR);
806 SVGA_CASE_ID2STR(SVGA_3D_CMD_VIDEO_DECODE_START_FRAME);
807 SVGA_CASE_ID2STR(SVGA_3D_CMD_VIDEO_DECODE_RENDER);
808 SVGA_CASE_ID2STR(SVGA_3D_CMD_VIDEO_DECODE_END_FRAME);
809 SVGA_CASE_ID2STR(SVGA_3D_CMD_VIDEO_PROCESS_FRAME);
810 SVGA_CASE_ID2STR(SVGA_3D_CMD_ACTIVATE_SURFACE);
811 SVGA_CASE_ID2STR(SVGA_3D_CMD_DEACTIVATE_SURFACE);
812 SVGA_CASE_ID2STR(SVGA_3D_CMD_SCREEN_DMA);
813 SVGA_CASE_ID2STR(SVGA_3D_CMD_DEAD1);
814 SVGA_CASE_ID2STR(SVGA_3D_CMD_DEAD2);
815 SVGA_CASE_ID2STR(SVGA_3D_CMD_LOGICOPS_BITBLT);
816 SVGA_CASE_ID2STR(SVGA_3D_CMD_LOGICOPS_TRANSBLT);
817 SVGA_CASE_ID2STR(SVGA_3D_CMD_LOGICOPS_STRETCHBLT);
818 SVGA_CASE_ID2STR(SVGA_3D_CMD_LOGICOPS_COLORFILL);
819 SVGA_CASE_ID2STR(SVGA_3D_CMD_LOGICOPS_ALPHABLEND);
820 SVGA_CASE_ID2STR(SVGA_3D_CMD_LOGICOPS_CLEARTYPEBLEND);
821 SVGA_CASE_ID2STR(SVGA_3D_CMD_SET_OTABLE_BASE);
822 SVGA_CASE_ID2STR(SVGA_3D_CMD_READBACK_OTABLE);
823 SVGA_CASE_ID2STR(SVGA_3D_CMD_DEFINE_GB_MOB);
824 SVGA_CASE_ID2STR(SVGA_3D_CMD_DESTROY_GB_MOB);
825 SVGA_CASE_ID2STR(SVGA_3D_CMD_DEAD3);
826 SVGA_CASE_ID2STR(SVGA_3D_CMD_UPDATE_GB_MOB_MAPPING);
827 SVGA_CASE_ID2STR(SVGA_3D_CMD_DEFINE_GB_SURFACE);
828 SVGA_CASE_ID2STR(SVGA_3D_CMD_DESTROY_GB_SURFACE);
829 SVGA_CASE_ID2STR(SVGA_3D_CMD_BIND_GB_SURFACE);
830 SVGA_CASE_ID2STR(SVGA_3D_CMD_COND_BIND_GB_SURFACE);
831 SVGA_CASE_ID2STR(SVGA_3D_CMD_UPDATE_GB_IMAGE);
832 SVGA_CASE_ID2STR(SVGA_3D_CMD_UPDATE_GB_SURFACE);
833 SVGA_CASE_ID2STR(SVGA_3D_CMD_READBACK_GB_IMAGE);
834 SVGA_CASE_ID2STR(SVGA_3D_CMD_READBACK_GB_SURFACE);
835 SVGA_CASE_ID2STR(SVGA_3D_CMD_INVALIDATE_GB_IMAGE);
836 SVGA_CASE_ID2STR(SVGA_3D_CMD_INVALIDATE_GB_SURFACE);
837 SVGA_CASE_ID2STR(SVGA_3D_CMD_DEFINE_GB_CONTEXT);
838 SVGA_CASE_ID2STR(SVGA_3D_CMD_DESTROY_GB_CONTEXT);
839 SVGA_CASE_ID2STR(SVGA_3D_CMD_BIND_GB_CONTEXT);
840 SVGA_CASE_ID2STR(SVGA_3D_CMD_READBACK_GB_CONTEXT);
841 SVGA_CASE_ID2STR(SVGA_3D_CMD_INVALIDATE_GB_CONTEXT);
842 SVGA_CASE_ID2STR(SVGA_3D_CMD_DEFINE_GB_SHADER);
843 SVGA_CASE_ID2STR(SVGA_3D_CMD_DESTROY_GB_SHADER);
844 SVGA_CASE_ID2STR(SVGA_3D_CMD_BIND_GB_SHADER);
845 SVGA_CASE_ID2STR(SVGA_3D_CMD_SET_OTABLE_BASE64);
846 SVGA_CASE_ID2STR(SVGA_3D_CMD_BEGIN_GB_QUERY);
847 SVGA_CASE_ID2STR(SVGA_3D_CMD_END_GB_QUERY);
848 SVGA_CASE_ID2STR(SVGA_3D_CMD_WAIT_FOR_GB_QUERY);
849 SVGA_CASE_ID2STR(SVGA_3D_CMD_NOP);
850 SVGA_CASE_ID2STR(SVGA_3D_CMD_ENABLE_GART);
851 SVGA_CASE_ID2STR(SVGA_3D_CMD_DISABLE_GART);
852 SVGA_CASE_ID2STR(SVGA_3D_CMD_MAP_MOB_INTO_GART);
853 SVGA_CASE_ID2STR(SVGA_3D_CMD_UNMAP_GART_RANGE);
854 SVGA_CASE_ID2STR(SVGA_3D_CMD_DEFINE_GB_SCREENTARGET);
855 SVGA_CASE_ID2STR(SVGA_3D_CMD_DESTROY_GB_SCREENTARGET);
856 SVGA_CASE_ID2STR(SVGA_3D_CMD_BIND_GB_SCREENTARGET);
857 SVGA_CASE_ID2STR(SVGA_3D_CMD_UPDATE_GB_SCREENTARGET);
858 SVGA_CASE_ID2STR(SVGA_3D_CMD_READBACK_GB_IMAGE_PARTIAL);
859 SVGA_CASE_ID2STR(SVGA_3D_CMD_INVALIDATE_GB_IMAGE_PARTIAL);
860 SVGA_CASE_ID2STR(SVGA_3D_CMD_SET_GB_SHADERCONSTS_INLINE);
861 SVGA_CASE_ID2STR(SVGA_3D_CMD_GB_SCREEN_DMA);
862 SVGA_CASE_ID2STR(SVGA_3D_CMD_BIND_GB_SURFACE_WITH_PITCH);
863 SVGA_CASE_ID2STR(SVGA_3D_CMD_GB_MOB_FENCE);
864 SVGA_CASE_ID2STR(SVGA_3D_CMD_DEFINE_GB_SURFACE_V2);
865 SVGA_CASE_ID2STR(SVGA_3D_CMD_DEFINE_GB_MOB64);
866 SVGA_CASE_ID2STR(SVGA_3D_CMD_REDEFINE_GB_MOB64);
867 SVGA_CASE_ID2STR(SVGA_3D_CMD_NOP_ERROR);
868 SVGA_CASE_ID2STR(SVGA_3D_CMD_SET_VERTEX_STREAMS);
869 SVGA_CASE_ID2STR(SVGA_3D_CMD_SET_VERTEX_DECLS);
870 SVGA_CASE_ID2STR(SVGA_3D_CMD_SET_VERTEX_DIVISORS);
871 SVGA_CASE_ID2STR(SVGA_3D_CMD_DRAW);
872 SVGA_CASE_ID2STR(SVGA_3D_CMD_DRAW_INDEXED);
873 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_CONTEXT);
874 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_CONTEXT);
875 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_BIND_CONTEXT);
876 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_READBACK_CONTEXT);
877 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_INVALIDATE_CONTEXT);
878 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_SINGLE_CONSTANT_BUFFER);
879 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_SHADER_RESOURCES);
880 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_SHADER);
881 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_SAMPLERS);
882 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DRAW);
883 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DRAW_INDEXED);
884 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DRAW_INSTANCED);
885 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DRAW_INDEXED_INSTANCED);
886 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DRAW_AUTO);
887 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_INPUT_LAYOUT);
888 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_VERTEX_BUFFERS);
889 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_INDEX_BUFFER);
890 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_TOPOLOGY);
891 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_RENDERTARGETS);
892 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_BLEND_STATE);
893 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_DEPTHSTENCIL_STATE);
894 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_RASTERIZER_STATE);
895 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_QUERY);
896 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_QUERY);
897 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_BIND_QUERY);
898 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_QUERY_OFFSET);
899 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_BEGIN_QUERY);
900 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_END_QUERY);
901 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_READBACK_QUERY);
902 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_PREDICATION);
903 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_SOTARGETS);
904 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_VIEWPORTS);
905 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_SCISSORRECTS);
906 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_CLEAR_RENDERTARGET_VIEW);
907 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_CLEAR_DEPTHSTENCIL_VIEW);
908 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_PRED_COPY_REGION);
909 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_PRED_COPY);
910 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_STRETCHBLT);
911 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_GENMIPS);
912 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_UPDATE_SUBRESOURCE);
913 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_READBACK_SUBRESOURCE);
914 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_INVALIDATE_SUBRESOURCE);
915 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_SHADERRESOURCE_VIEW);
916 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_SHADERRESOURCE_VIEW);
917 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_RENDERTARGET_VIEW);
918 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_RENDERTARGET_VIEW);
919 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_DEPTHSTENCIL_VIEW);
920 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_DEPTHSTENCIL_VIEW);
921 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_ELEMENTLAYOUT);
922 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_ELEMENTLAYOUT);
923 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_BLEND_STATE);
924 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_BLEND_STATE);
925 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_DEPTHSTENCIL_STATE);
926 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_DEPTHSTENCIL_STATE);
927 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_RASTERIZER_STATE);
928 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_RASTERIZER_STATE);
929 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_SAMPLER_STATE);
930 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_SAMPLER_STATE);
931 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_SHADER);
932 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_SHADER);
933 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_BIND_SHADER);
934 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DEFINE_STREAMOUTPUT);
935 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_DESTROY_STREAMOUTPUT);
936 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_STREAMOUTPUT);
937 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_COTABLE);
938 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_READBACK_COTABLE);
939 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_BUFFER_COPY);
940 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_TRANSFER_FROM_BUFFER);
941 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SURFACE_COPY_AND_READBACK);
942 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_MOVE_QUERY);
943 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_BIND_ALL_QUERY);
944 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_READBACK_ALL_QUERY);
945 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_PRED_TRANSFER_FROM_BUFFER);
946 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_MOB_FENCE_64);
947 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_BIND_ALL_SHADER);
948 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_HINT);
949 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_BUFFER_UPDATE);
950 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_VS_CONSTANT_BUFFER_OFFSET);
951 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_PS_CONSTANT_BUFFER_OFFSET);
952 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_SET_GS_CONSTANT_BUFFER_OFFSET);
953 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_RESERVED1);
954 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_RESERVED2);
955 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_RESERVED3);
956 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_COND_BIND_ALL_SHADER);
957 SVGA_CASE_ID2STR(SVGA_3D_CMD_DX_MAX);
958 default: return "UNKNOWN";
959 }
960}
961#endif /* IN_RING3 && (LOG_ENABLED || VBOX_STRICT) */
962
963#ifdef IN_RING3
964
965/**
966 * @interface_method_impl{PDMIDISPLAYPORT,pfnSetViewport}
967 */
968DECLCALLBACK(void) vmsvgaR3PortSetViewport(PPDMIDISPLAYPORT pInterface, uint32_t idScreen, uint32_t x, uint32_t y, uint32_t cx, uint32_t cy)
969{
970 PVGASTATECC pThisCC = RT_FROM_MEMBER(pInterface, VGASTATECC, IPort);
971 PVGASTATE pThis = PDMDEVINS_2_DATA(pThisCC->pDevIns, PVGASTATE);
972
973 Log(("vmsvgaPortSetViewPort: screen %d (%d,%d)(%d,%d)\n", idScreen, x, y, cx, cy));
974 VMSVGAVIEWPORT const OldViewport = pThis->svga.viewport;
975
976 /** @todo Test how it interacts with multiple screen objects. */
977 VMSVGASCREENOBJECT *pScreen = vmsvgaR3GetScreenObject(pThisCC, idScreen);
978 uint32_t const uWidth = pScreen ? pScreen->cWidth : 0;
979 uint32_t const uHeight = pScreen ? pScreen->cHeight : 0;
980
981 if (x < uWidth)
982 {
983 pThis->svga.viewport.x = x;
984 pThis->svga.viewport.cx = RT_MIN(cx, uWidth - x);
985 pThis->svga.viewport.xRight = x + pThis->svga.viewport.cx;
986 }
987 else
988 {
989 pThis->svga.viewport.x = uWidth;
990 pThis->svga.viewport.cx = 0;
991 pThis->svga.viewport.xRight = uWidth;
992 }
993 if (y < uHeight)
994 {
995 pThis->svga.viewport.y = y;
996 pThis->svga.viewport.cy = RT_MIN(cy, uHeight - y);
997 pThis->svga.viewport.yLowWC = uHeight - y - pThis->svga.viewport.cy;
998 pThis->svga.viewport.yHighWC = uHeight - y;
999 }
1000 else
1001 {
1002 pThis->svga.viewport.y = uHeight;
1003 pThis->svga.viewport.cy = 0;
1004 pThis->svga.viewport.yLowWC = 0;
1005 pThis->svga.viewport.yHighWC = 0;
1006 }
1007
1008# ifdef VBOX_WITH_VMSVGA3D
1009 /*
1010 * Now inform the 3D backend.
1011 */
1012 if (pThis->svga.f3DEnabled)
1013 vmsvga3dUpdateHostScreenViewport(pThisCC, idScreen, &OldViewport);
1014# else
1015 RT_NOREF(OldViewport);
1016# endif
1017}
1018
1019
1020/**
1021 * Updating screen information in API
1022 *
1023 * @param pThis The The shared VGA/VMSVGA instance data.
1024 * @param pThisCC The VGA/VMSVGA state for ring-3.
1025 */
1026void vmsvgaR3VBVAResize(PVGASTATE pThis, PVGASTATECC pThisCC)
1027{
1028 int rc;
1029
1030 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
1031
1032 for (unsigned iScreen = 0; iScreen < RT_ELEMENTS(pSVGAState->aScreens); ++iScreen)
1033 {
1034 VMSVGASCREENOBJECT *pScreen = &pSVGAState->aScreens[iScreen];
1035 if (!pScreen->fModified)
1036 continue;
1037
1038 pScreen->fModified = false;
1039
1040 VBVAINFOVIEW view;
1041 RT_ZERO(view);
1042 view.u32ViewIndex = pScreen->idScreen;
1043 // view.u32ViewOffset = 0;
1044 view.u32ViewSize = pThis->vram_size;
1045 view.u32MaxScreenSize = pThis->vram_size;
1046
1047 VBVAINFOSCREEN screen;
1048 RT_ZERO(screen);
1049 screen.u32ViewIndex = pScreen->idScreen;
1050
1051 if (pScreen->fDefined)
1052 {
1053 if ( pScreen->cWidth == VMSVGA_VAL_UNINITIALIZED
1054 || pScreen->cHeight == VMSVGA_VAL_UNINITIALIZED
1055 || pScreen->cBpp == VMSVGA_VAL_UNINITIALIZED)
1056 {
1057 Assert(pThis->svga.fGFBRegisters);
1058 continue;
1059 }
1060
1061 screen.i32OriginX = pScreen->xOrigin;
1062 screen.i32OriginY = pScreen->yOrigin;
1063 screen.u32StartOffset = pScreen->offVRAM;
1064 screen.u32LineSize = pScreen->cbPitch;
1065 screen.u32Width = pScreen->cWidth;
1066 screen.u32Height = pScreen->cHeight;
1067 screen.u16BitsPerPixel = pScreen->cBpp;
1068 if (!(pScreen->fuScreen & SVGA_SCREEN_DEACTIVATE))
1069 screen.u16Flags = VBVA_SCREEN_F_ACTIVE;
1070 if (pScreen->fuScreen & SVGA_SCREEN_BLANKING)
1071 screen.u16Flags |= VBVA_SCREEN_F_BLANK2;
1072 }
1073 else
1074 {
1075 /* Screen is destroyed. */
1076 screen.u16Flags = VBVA_SCREEN_F_DISABLED;
1077 }
1078
1079 rc = pThisCC->pDrv->pfnVBVAResize(pThisCC->pDrv, &view, &screen, pThisCC->pbVRam, /*fResetInputMapping=*/ true);
1080 AssertRC(rc);
1081 }
1082}
1083
1084
1085/**
1086 * @interface_method_impl{PDMIDISPLAYPORT,pfnReportMonitorPositions}
1087 *
1088 * Used to update screen offsets (positions) since appearently vmwgfx fails to
1089 * pass correct offsets thru FIFO.
1090 */
1091DECLCALLBACK(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 */
1130static int vmsvgaReadPort(PPDMDEVINS pDevIns, PVGASTATE pThis, uint32_t *pu32)
1131{
1132#ifdef IN_RING3
1133 PVGASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
1134#endif
1135 int rc = VINF_SUCCESS;
1136 *pu32 = 0;
1137
1138 /* Rough index register validation. */
1139 uint32_t idxReg = pThis->svga.u32IndexReg;
1140#if !defined(IN_RING3) && defined(VBOX_STRICT)
1141 ASSERT_GUEST_MSG_RETURN(idxReg < SVGA_SCRATCH_BASE + pThis->svga.cScratchRegion, ("idxReg=%#x\n", idxReg),
1142 VINF_IOM_R3_IOPORT_READ);
1143#else
1144 ASSERT_GUEST_MSG_STMT_RETURN(idxReg < SVGA_SCRATCH_BASE + pThis->svga.cScratchRegion, ("idxReg=%#x\n", idxReg),
1145 STAM_REL_COUNTER_INC(&pThis->svga.StatRegUnknownRd),
1146 VINF_SUCCESS);
1147#endif
1148 RT_UNTRUSTED_VALIDATED_FENCE();
1149
1150 /* We must adjust the register number if we're in SVGA_ID_0 mode because the PALETTE range moved. */
1151 if ( idxReg >= SVGA_REG_ID_0_TOP
1152 && pThis->svga.u32SVGAId == SVGA_ID_0)
1153 {
1154 idxReg += SVGA_PALETTE_BASE - SVGA_REG_ID_0_TOP;
1155 Log(("vmsvgaWritePort: SVGA_ID_0 reg adj %#x -> %#x\n", pThis->svga.u32IndexReg, idxReg));
1156 }
1157
1158 switch (idxReg)
1159 {
1160 case SVGA_REG_ID:
1161 STAM_REL_COUNTER_INC(&pThis->svga.StatRegIdRd);
1162 *pu32 = pThis->svga.u32SVGAId;
1163 break;
1164
1165 case SVGA_REG_ENABLE:
1166 STAM_REL_COUNTER_INC(&pThis->svga.StatRegEnableRd);
1167 *pu32 = pThis->svga.fEnabled;
1168 break;
1169
1170 case SVGA_REG_WIDTH:
1171 {
1172 STAM_REL_COUNTER_INC(&pThis->svga.StatRegWidthRd);
1173 if ( pThis->svga.fEnabled
1174 && pThis->svga.uWidth != VMSVGA_VAL_UNINITIALIZED)
1175 *pu32 = pThis->svga.uWidth;
1176 else
1177 {
1178#ifndef IN_RING3
1179 rc = VINF_IOM_R3_IOPORT_READ;
1180#else
1181 *pu32 = pThisCC->pDrv->cx;
1182#endif
1183 }
1184 break;
1185 }
1186
1187 case SVGA_REG_HEIGHT:
1188 {
1189 STAM_REL_COUNTER_INC(&pThis->svga.StatRegHeightRd);
1190 if ( pThis->svga.fEnabled
1191 && pThis->svga.uHeight != VMSVGA_VAL_UNINITIALIZED)
1192 *pu32 = pThis->svga.uHeight;
1193 else
1194 {
1195#ifndef IN_RING3
1196 rc = VINF_IOM_R3_IOPORT_READ;
1197#else
1198 *pu32 = pThisCC->pDrv->cy;
1199#endif
1200 }
1201 break;
1202 }
1203
1204 case SVGA_REG_MAX_WIDTH:
1205 STAM_REL_COUNTER_INC(&pThis->svga.StatRegMaxWidthRd);
1206 *pu32 = pThis->svga.u32MaxWidth;
1207 break;
1208
1209 case SVGA_REG_MAX_HEIGHT:
1210 STAM_REL_COUNTER_INC(&pThis->svga.StatRegMaxHeightRd);
1211 *pu32 = pThis->svga.u32MaxHeight;
1212 break;
1213
1214 case SVGA_REG_DEPTH:
1215 /* This returns the color depth of the current mode. */
1216 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDepthRd);
1217 switch (pThis->svga.uBpp)
1218 {
1219 case 15:
1220 case 16:
1221 case 24:
1222 *pu32 = pThis->svga.uBpp;
1223 break;
1224
1225 default:
1226 case 32:
1227 *pu32 = 24; /* The upper 8 bits are either alpha bits or not used. */
1228 break;
1229 }
1230 break;
1231
1232 case SVGA_REG_HOST_BITS_PER_PIXEL: /* (Deprecated) */
1233 STAM_REL_COUNTER_INC(&pThis->svga.StatRegHostBitsPerPixelRd);
1234 *pu32 = pThis->svga.uHostBpp;
1235 break;
1236
1237 case SVGA_REG_BITS_PER_PIXEL: /* Current bpp in the guest */
1238 STAM_REL_COUNTER_INC(&pThis->svga.StatRegBitsPerPixelRd);
1239 *pu32 = pThis->svga.uBpp;
1240 break;
1241
1242 case SVGA_REG_PSEUDOCOLOR:
1243 STAM_REL_COUNTER_INC(&pThis->svga.StatRegPsuedoColorRd);
1244 *pu32 = pThis->svga.uBpp == 8; /* See section 6 "Pseudocolor" in svga_interface.txt. */
1245 break;
1246
1247 case SVGA_REG_RED_MASK:
1248 case SVGA_REG_GREEN_MASK:
1249 case SVGA_REG_BLUE_MASK:
1250 {
1251 uint32_t uBpp;
1252
1253 if (pThis->svga.fEnabled)
1254 uBpp = pThis->svga.uBpp;
1255 else
1256 uBpp = pThis->svga.uHostBpp;
1257
1258 uint32_t u32RedMask, u32GreenMask, u32BlueMask;
1259 switch (uBpp)
1260 {
1261 case 8:
1262 u32RedMask = 0x07;
1263 u32GreenMask = 0x38;
1264 u32BlueMask = 0xc0;
1265 break;
1266
1267 case 15:
1268 u32RedMask = 0x0000001f;
1269 u32GreenMask = 0x000003e0;
1270 u32BlueMask = 0x00007c00;
1271 break;
1272
1273 case 16:
1274 u32RedMask = 0x0000001f;
1275 u32GreenMask = 0x000007e0;
1276 u32BlueMask = 0x0000f800;
1277 break;
1278
1279 case 24:
1280 case 32:
1281 default:
1282 u32RedMask = 0x00ff0000;
1283 u32GreenMask = 0x0000ff00;
1284 u32BlueMask = 0x000000ff;
1285 break;
1286 }
1287 switch (idxReg)
1288 {
1289 case SVGA_REG_RED_MASK:
1290 STAM_REL_COUNTER_INC(&pThis->svga.StatRegRedMaskRd);
1291 *pu32 = u32RedMask;
1292 break;
1293
1294 case SVGA_REG_GREEN_MASK:
1295 STAM_REL_COUNTER_INC(&pThis->svga.StatRegGreenMaskRd);
1296 *pu32 = u32GreenMask;
1297 break;
1298
1299 case SVGA_REG_BLUE_MASK:
1300 STAM_REL_COUNTER_INC(&pThis->svga.StatRegBlueMaskRd);
1301 *pu32 = u32BlueMask;
1302 break;
1303 }
1304 break;
1305 }
1306
1307 case SVGA_REG_BYTES_PER_LINE:
1308 {
1309 STAM_REL_COUNTER_INC(&pThis->svga.StatRegBytesPerLineRd);
1310 if ( pThis->svga.fEnabled
1311 && pThis->svga.cbScanline)
1312 *pu32 = pThis->svga.cbScanline;
1313 else
1314 {
1315#ifndef IN_RING3
1316 rc = VINF_IOM_R3_IOPORT_READ;
1317#else
1318 *pu32 = pThisCC->pDrv->cbScanline;
1319#endif
1320 }
1321 break;
1322 }
1323
1324 case SVGA_REG_VRAM_SIZE: /* VRAM size */
1325 STAM_REL_COUNTER_INC(&pThis->svga.StatRegVramSizeRd);
1326 *pu32 = pThis->vram_size;
1327 break;
1328
1329 case SVGA_REG_FB_START: /* Frame buffer physical address. */
1330 STAM_REL_COUNTER_INC(&pThis->svga.StatRegFbStartRd);
1331 Assert(pThis->GCPhysVRAM <= 0xffffffff);
1332 *pu32 = pThis->GCPhysVRAM;
1333 break;
1334
1335 case SVGA_REG_FB_OFFSET: /* Offset of the frame buffer in VRAM */
1336 STAM_REL_COUNTER_INC(&pThis->svga.StatRegFbOffsetRd);
1337 /* Always zero in our case. */
1338 *pu32 = 0;
1339 break;
1340
1341 case SVGA_REG_FB_SIZE: /* Frame buffer size */
1342 {
1343#ifndef IN_RING3
1344 rc = VINF_IOM_R3_IOPORT_READ;
1345#else
1346 STAM_REL_COUNTER_INC(&pThis->svga.StatRegFbSizeRd);
1347
1348 /* VMWare testcases want at least 4 MB in case the hardware is disabled. */
1349 if ( pThis->svga.fEnabled
1350 && pThis->svga.uHeight != VMSVGA_VAL_UNINITIALIZED)
1351 {
1352 /* Hardware enabled; return real framebuffer size .*/
1353 *pu32 = (uint32_t)pThis->svga.uHeight * pThis->svga.cbScanline;
1354 }
1355 else
1356 *pu32 = RT_MAX(0x100000, (uint32_t)pThisCC->pDrv->cy * pThisCC->pDrv->cbScanline);
1357
1358 *pu32 = RT_MIN(pThis->vram_size, *pu32);
1359 Log(("h=%d w=%d bpp=%d\n", pThisCC->pDrv->cy, pThisCC->pDrv->cx, pThisCC->pDrv->cBits));
1360#endif
1361 break;
1362 }
1363
1364 case SVGA_REG_CAPABILITIES:
1365 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCapabilitesRd);
1366 *pu32 = pThis->svga.u32DeviceCaps;
1367 break;
1368
1369 case SVGA_REG_MEM_START: /* FIFO start */
1370 STAM_REL_COUNTER_INC(&pThis->svga.StatRegMemStartRd);
1371 Assert(pThis->svga.GCPhysFIFO <= 0xffffffff);
1372 *pu32 = pThis->svga.GCPhysFIFO;
1373 break;
1374
1375 case SVGA_REG_MEM_SIZE: /* FIFO size */
1376 STAM_REL_COUNTER_INC(&pThis->svga.StatRegMemSizeRd);
1377 *pu32 = pThis->svga.cbFIFO;
1378 break;
1379
1380 case SVGA_REG_CONFIG_DONE: /* Set when memory area configured */
1381 STAM_REL_COUNTER_INC(&pThis->svga.StatRegConfigDoneRd);
1382 *pu32 = pThis->svga.fConfigured;
1383 break;
1384
1385 case SVGA_REG_SYNC: /* See "FIFO Synchronization Registers" */
1386 STAM_REL_COUNTER_INC(&pThis->svga.StatRegSyncRd);
1387 *pu32 = 0;
1388 break;
1389
1390 case SVGA_REG_BUSY: /* See "FIFO Synchronization Registers" */
1391 STAM_REL_COUNTER_INC(&pThis->svga.StatRegBusyRd);
1392 if (pThis->svga.fBusy)
1393 {
1394#ifndef IN_RING3
1395 /* Go to ring-3 and halt the CPU. */
1396 rc = VINF_IOM_R3_IOPORT_READ;
1397 RT_NOREF(pDevIns);
1398 break;
1399#else
1400# if defined(VMSVGA_USE_EMT_HALT_CODE)
1401 /* The guest is basically doing a HLT via the device here, but with
1402 a special wake up condition on FIFO completion. */
1403 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
1404 STAM_REL_PROFILE_START(&pSVGAState->StatBusyDelayEmts, EmtDelay);
1405 PVM pVM = PDMDevHlpGetVM(pDevIns);
1406 VMCPUID idCpu = PDMDevHlpGetCurrentCpuId(pDevIns);
1407 VMCPUSET_ATOMIC_ADD(&pSVGAState->BusyDelayedEmts, idCpu);
1408 ASMAtomicIncU32(&pSVGAState->cBusyDelayedEmts);
1409 if (pThis->svga.fBusy)
1410 {
1411 PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect); /* hack around lock order issue. */
1412 rc = VMR3WaitForDeviceReady(pVM, idCpu);
1413 PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VERR_IGNORED);
1414 }
1415 ASMAtomicDecU32(&pSVGAState->cBusyDelayedEmts);
1416 VMCPUSET_ATOMIC_DEL(&pSVGAState->BusyDelayedEmts, idCpu);
1417# else
1418
1419 /* Delay the EMT a bit so the FIFO and others can get some work done.
1420 This used to be a crude 50 ms sleep. The current code tries to be
1421 more efficient, but the consept is still very crude. */
1422 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
1423 STAM_REL_PROFILE_START(&pSVGAState->StatBusyDelayEmts, EmtDelay);
1424 RTThreadYield();
1425 if (pThis->svga.fBusy)
1426 {
1427 uint32_t cRefs = ASMAtomicIncU32(&pSVGAState->cBusyDelayedEmts);
1428
1429 if (pThis->svga.fBusy && cRefs == 1)
1430 RTSemEventMultiReset(pSVGAState->hBusyDelayedEmts);
1431 if (pThis->svga.fBusy)
1432 {
1433 /** @todo If this code is going to stay, we need to call into the halt/wait
1434 * code in VMEmt.cpp here, otherwise all kind of EMT interaction will
1435 * suffer when the guest is polling on a busy FIFO. */
1436 uint64_t cNsMaxWait = TMVirtualSyncGetNsToDeadline(PDMDevHlpGetVM(pDevIns));
1437 if (cNsMaxWait >= RT_NS_100US)
1438 RTSemEventMultiWaitEx(pSVGAState->hBusyDelayedEmts,
1439 RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_NORESUME,
1440 RT_MIN(cNsMaxWait, RT_NS_10MS));
1441 }
1442
1443 ASMAtomicDecU32(&pSVGAState->cBusyDelayedEmts);
1444 }
1445 STAM_REL_PROFILE_STOP(&pSVGAState->StatBusyDelayEmts, EmtDelay);
1446# endif
1447 *pu32 = pThis->svga.fBusy != 0;
1448#endif
1449 }
1450 else
1451 *pu32 = false;
1452 break;
1453
1454 case SVGA_REG_GUEST_ID: /* Set guest OS identifier */
1455 STAM_REL_COUNTER_INC(&pThis->svga.StatRegGuestIdRd);
1456 *pu32 = pThis->svga.u32GuestId;
1457 break;
1458
1459 case SVGA_REG_SCRATCH_SIZE: /* Number of scratch registers */
1460 STAM_REL_COUNTER_INC(&pThis->svga.StatRegScratchSizeRd);
1461 *pu32 = pThis->svga.cScratchRegion;
1462 break;
1463
1464 case SVGA_REG_MEM_REGS: /* Number of FIFO registers */
1465 STAM_REL_COUNTER_INC(&pThis->svga.StatRegMemRegsRd);
1466 *pu32 = SVGA_FIFO_NUM_REGS;
1467 break;
1468
1469 case SVGA_REG_PITCHLOCK: /* Fixed pitch for all modes */
1470 STAM_REL_COUNTER_INC(&pThis->svga.StatRegPitchLockRd);
1471 *pu32 = pThis->svga.u32PitchLock;
1472 break;
1473
1474 case SVGA_REG_IRQMASK: /* Interrupt mask */
1475 STAM_REL_COUNTER_INC(&pThis->svga.StatRegIrqMaskRd);
1476 *pu32 = pThis->svga.u32IrqMask;
1477 break;
1478
1479 /* See "Guest memory regions" below. */
1480 case SVGA_REG_GMR_ID:
1481 STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrIdRd);
1482 *pu32 = pThis->svga.u32CurrentGMRId;
1483 break;
1484
1485 case SVGA_REG_GMR_DESCRIPTOR:
1486 STAM_REL_COUNTER_INC(&pThis->svga.StatRegWriteOnlyRd);
1487 /* Write only */
1488 *pu32 = 0;
1489 break;
1490
1491 case SVGA_REG_GMR_MAX_IDS:
1492 STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrMaxIdsRd);
1493 *pu32 = pThis->svga.cGMR;
1494 break;
1495
1496 case SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH:
1497 STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrMaxDescriptorLengthRd);
1498 *pu32 = VMSVGA_MAX_GMR_PAGES;
1499 break;
1500
1501 case SVGA_REG_TRACES: /* Enable trace-based updates even when FIFO is on */
1502 STAM_REL_COUNTER_INC(&pThis->svga.StatRegTracesRd);
1503 *pu32 = pThis->svga.fTraces;
1504 break;
1505
1506 case SVGA_REG_GMRS_MAX_PAGES: /* Maximum number of 4KB pages for all GMRs */
1507 STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrsMaxPagesRd);
1508 *pu32 = VMSVGA_MAX_GMR_PAGES;
1509 break;
1510
1511 case SVGA_REG_MEMORY_SIZE: /* Total dedicated device memory excluding FIFO */
1512 STAM_REL_COUNTER_INC(&pThis->svga.StatRegMemorySizeRd);
1513 *pu32 = VMSVGA_SURFACE_SIZE;
1514 break;
1515
1516 case SVGA_REG_TOP: /* Must be 1 more than the last register */
1517 STAM_REL_COUNTER_INC(&pThis->svga.StatRegTopRd);
1518 break;
1519
1520 /* Mouse cursor support. */
1521 case SVGA_REG_CURSOR_ID:
1522 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorIdRd);
1523 *pu32 = pThis->svga.uCursorID;
1524 break;
1525
1526 case SVGA_REG_CURSOR_X:
1527 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorXRd);
1528 *pu32 = pThis->svga.uCursorX;
1529 break;
1530
1531 case SVGA_REG_CURSOR_Y:
1532 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorYRd);
1533 *pu32 = pThis->svga.uCursorY;
1534 break;
1535
1536 case SVGA_REG_CURSOR_ON:
1537 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorOnRd);
1538 *pu32 = pThis->svga.uCursorOn;
1539 break;
1540
1541 /* Legacy multi-monitor support */
1542 case SVGA_REG_NUM_GUEST_DISPLAYS:/* Number of guest displays in X/Y direction */
1543 STAM_REL_COUNTER_INC(&pThis->svga.StatRegNumGuestDisplaysRd);
1544 *pu32 = 1;
1545 break;
1546
1547 case SVGA_REG_DISPLAY_ID: /* Display ID for the following display attributes */
1548 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayIdRd);
1549 *pu32 = 0;
1550 break;
1551
1552 case SVGA_REG_DISPLAY_IS_PRIMARY:/* Whether this is a primary display */
1553 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayIsPrimaryRd);
1554 *pu32 = 0;
1555 break;
1556
1557 case SVGA_REG_DISPLAY_POSITION_X:/* The display position x */
1558 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayPositionXRd);
1559 *pu32 = 0;
1560 break;
1561
1562 case SVGA_REG_DISPLAY_POSITION_Y:/* The display position y */
1563 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayPositionYRd);
1564 *pu32 = 0;
1565 break;
1566
1567 case SVGA_REG_DISPLAY_WIDTH: /* The display's width */
1568 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayWidthRd);
1569 *pu32 = pThis->svga.uWidth;
1570 break;
1571
1572 case SVGA_REG_DISPLAY_HEIGHT: /* The display's height */
1573 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayHeightRd);
1574 *pu32 = pThis->svga.uHeight;
1575 break;
1576
1577 case SVGA_REG_NUM_DISPLAYS: /* (Deprecated) */
1578 STAM_REL_COUNTER_INC(&pThis->svga.StatRegNumDisplaysRd);
1579 /* We must return something sensible here otherwise the Linux driver
1580 will take a legacy code path without 3d support. This number also
1581 limits how many screens Linux guests will allow. */
1582 *pu32 = pThis->cMonitors;
1583 break;
1584
1585 /*
1586 * SVGA_CAP_GBOBJECTS+ registers.
1587 */
1588 case SVGA_REG_COMMAND_LOW:
1589 /* Lower 32 bits of command buffer physical address. */
1590 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCommandLowRd);
1591 *pu32 = pThis->svga.u32RegCommandLow;
1592 break;
1593
1594 case SVGA_REG_COMMAND_HIGH:
1595 /* Upper 32 bits of command buffer PA. */
1596 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCommandHighRd);
1597 *pu32 = pThis->svga.u32RegCommandHigh;
1598 break;
1599
1600 case SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM:
1601 /* Max primary (screen) memory. */
1602 STAM_REL_COUNTER_INC(&pThis->svga.StatRegMaxPrimBBMemRd);
1603 *pu32 = pThis->vram_size; /** @todo Maybe half VRAM? */
1604 break;
1605
1606 case SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB:
1607 /* Suggested limit on mob mem (i.e. size of the guest mapped VRAM in KB) */
1608 STAM_REL_COUNTER_INC(&pThis->svga.StatRegGBMemSizeRd);
1609 *pu32 = pThis->vram_size / 1024;
1610 break;
1611
1612 case SVGA_REG_DEV_CAP:
1613 /* Write dev cap index, read value */
1614 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDevCapRd);
1615 if (pThis->svga.u32DevCapIndex < RT_ELEMENTS(pThis->svga.au32DevCaps))
1616 {
1617 RT_UNTRUSTED_VALIDATED_FENCE();
1618 *pu32 = pThis->svga.au32DevCaps[pThis->svga.u32DevCapIndex];
1619 }
1620 else
1621 *pu32 = 0;
1622 break;
1623
1624 case SVGA_REG_CMD_PREPEND_LOW:
1625 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCmdPrependLowRd);
1626 *pu32 = 0; /* Not supported. */
1627 break;
1628
1629 case SVGA_REG_iCMD_PREPEND_HIGH:
1630 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCmdPrependHighRd);
1631 *pu32 = 0; /* Not supported. */
1632 break;
1633
1634 case SVGA_REG_SCREENTARGET_MAX_WIDTH:
1635 STAM_REL_COUNTER_INC(&pThis->svga.StatRegScrnTgtMaxWidthRd);
1636 *pu32 = pThis->svga.u32MaxWidth;
1637 break;
1638
1639 case SVGA_REG_SCREENTARGET_MAX_HEIGHT:
1640 STAM_REL_COUNTER_INC(&pThis->svga.StatRegScrnTgtMaxHeightRd);
1641 *pu32 = pThis->svga.u32MaxHeight;
1642 break;
1643
1644 case SVGA_REG_MOB_MAX_SIZE:
1645 /* Essentially the max texture size */
1646 STAM_REL_COUNTER_INC(&pThis->svga.StatRegMobMaxSizeRd);
1647 *pu32 = _128M; /** @todo Some actual value. Probably the mapped VRAM size. */
1648 break;
1649
1650 default:
1651 {
1652 uint32_t offReg;
1653 if ((offReg = idxReg - SVGA_SCRATCH_BASE) < pThis->svga.cScratchRegion)
1654 {
1655 STAM_REL_COUNTER_INC(&pThis->svga.StatRegScratchRd);
1656 RT_UNTRUSTED_VALIDATED_FENCE();
1657 *pu32 = pThis->svga.au32ScratchRegion[offReg];
1658 }
1659 else if ((offReg = idxReg - SVGA_PALETTE_BASE) < (uint32_t)SVGA_NUM_PALETTE_REGS)
1660 {
1661 /* Note! Using last_palette rather than palette here to preserve the VGA one. */
1662 STAM_REL_COUNTER_INC(&pThis->svga.StatRegPaletteRd);
1663 RT_UNTRUSTED_VALIDATED_FENCE();
1664 uint32_t u32 = pThis->last_palette[offReg / 3];
1665 switch (offReg % 3)
1666 {
1667 case 0: *pu32 = (u32 >> 16) & 0xff; break; /* red */
1668 case 1: *pu32 = (u32 >> 8) & 0xff; break; /* green */
1669 case 2: *pu32 = u32 & 0xff; break; /* blue */
1670 }
1671 }
1672 else
1673 {
1674#if !defined(IN_RING3) && defined(VBOX_STRICT)
1675 rc = VINF_IOM_R3_IOPORT_READ;
1676#else
1677 STAM_REL_COUNTER_INC(&pThis->svga.StatRegUnknownRd);
1678
1679 /* Do not assert. The guest might be reading all registers. */
1680 LogFunc(("Unknown reg=%#x\n", idxReg));
1681#endif
1682 }
1683 break;
1684 }
1685 }
1686 Log(("vmsvgaReadPort index=%s (%d) val=%#x rc=%x\n", vmsvgaIndexToString(pThis, idxReg), idxReg, *pu32, rc));
1687 return rc;
1688}
1689
1690#ifdef IN_RING3
1691/**
1692 * Apply the current resolution settings to change the video mode.
1693 *
1694 * @returns VBox status code.
1695 * @param pThis The shared VGA state.
1696 * @param pThisCC The ring-3 VGA state.
1697 */
1698static int vmsvgaR3ChangeMode(PVGASTATE pThis, PVGASTATECC pThisCC)
1699{
1700 /* Always do changemode on FIFO thread. */
1701 Assert(RTThreadSelf() == pThisCC->svga.pFIFOIOThread->Thread);
1702
1703 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
1704
1705 pThisCC->pDrv->pfnLFBModeChange(pThisCC->pDrv, true);
1706
1707 if (pThis->svga.fGFBRegisters)
1708 {
1709 /* "For backwards compatibility, when the GFB mode registers (WIDTH,
1710 * HEIGHT, PITCHLOCK, BITS_PER_PIXEL) are modified, the SVGA device
1711 * deletes all screens other than screen #0, and redefines screen
1712 * #0 according to the specified mode. Drivers that use
1713 * SVGA_CMD_DEFINE_SCREEN should destroy or redefine screen #0."
1714 */
1715
1716 VMSVGASCREENOBJECT *pScreen = &pSVGAState->aScreens[0];
1717 pScreen->fDefined = true;
1718 pScreen->fModified = true;
1719 pScreen->fuScreen = SVGA_SCREEN_MUST_BE_SET | SVGA_SCREEN_IS_PRIMARY;
1720 pScreen->idScreen = 0;
1721 pScreen->xOrigin = 0;
1722 pScreen->yOrigin = 0;
1723 pScreen->offVRAM = 0;
1724 pScreen->cbPitch = pThis->svga.cbScanline;
1725 pScreen->cWidth = pThis->svga.uWidth;
1726 pScreen->cHeight = pThis->svga.uHeight;
1727 pScreen->cBpp = pThis->svga.uBpp;
1728
1729 for (unsigned iScreen = 1; iScreen < RT_ELEMENTS(pSVGAState->aScreens); ++iScreen)
1730 {
1731 /* Delete screen. */
1732 pScreen = &pSVGAState->aScreens[iScreen];
1733 if (pScreen->fDefined)
1734 {
1735 pScreen->fModified = true;
1736 pScreen->fDefined = false;
1737 }
1738 }
1739 }
1740 else
1741 {
1742 /* "If Screen Objects are supported, they can be used to fully
1743 * replace the functionality provided by the framebuffer registers
1744 * (SVGA_REG_WIDTH, HEIGHT, etc.) and by SVGA_CAP_DISPLAY_TOPOLOGY."
1745 */
1746 pThis->svga.uWidth = VMSVGA_VAL_UNINITIALIZED;
1747 pThis->svga.uHeight = VMSVGA_VAL_UNINITIALIZED;
1748 pThis->svga.uBpp = pThis->svga.uHostBpp;
1749 }
1750
1751 vmsvgaR3VBVAResize(pThis, pThisCC);
1752
1753 /* Last stuff. For the VGA device screenshot. */
1754 pThis->last_bpp = pSVGAState->aScreens[0].cBpp;
1755 pThis->last_scr_width = pSVGAState->aScreens[0].cWidth;
1756 pThis->last_scr_height = pSVGAState->aScreens[0].cHeight;
1757 pThis->last_width = pSVGAState->aScreens[0].cWidth;
1758 pThis->last_height = pSVGAState->aScreens[0].cHeight;
1759
1760 /* vmsvgaPortSetViewPort not called after state load; set sensible defaults. */
1761 if ( pThis->svga.viewport.cx == 0
1762 && pThis->svga.viewport.cy == 0)
1763 {
1764 pThis->svga.viewport.cx = pSVGAState->aScreens[0].cWidth;
1765 pThis->svga.viewport.xRight = pSVGAState->aScreens[0].cWidth;
1766 pThis->svga.viewport.cy = pSVGAState->aScreens[0].cHeight;
1767 pThis->svga.viewport.yHighWC = pSVGAState->aScreens[0].cHeight;
1768 pThis->svga.viewport.yLowWC = 0;
1769 }
1770
1771 return VINF_SUCCESS;
1772}
1773
1774int 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 */
1800DECLINLINE(void) vmsvgaHCSafeFifoBusyRegUpdate(PVGASTATE pThis, PVGASTATECC pThisCC, bool fState)
1801{
1802 ASMAtomicWriteU32(&pThisCC->svga.pau32FIFO[SVGA_FIFO_BUSY], fState);
1803
1804 if (RT_UNLIKELY(fState != (pThis->svga.fBusy != 0)))
1805 {
1806 /* Race / unfortunately scheduling. Highly unlikly. */
1807 uint32_t cLoops = 64;
1808 do
1809 {
1810 ASMNopPause();
1811 fState = (pThis->svga.fBusy != 0);
1812 ASMAtomicWriteU32(&pThisCC->svga.pau32FIFO[SVGA_FIFO_BUSY], fState != 0);
1813 } while (cLoops-- > 0 && fState != (pThis->svga.fBusy != 0));
1814 }
1815}
1816
1817
1818/**
1819 * Update the scanline pitch in response to the guest changing mode
1820 * width/bpp.
1821 *
1822 * @param pThis The shared VGA/VMSVGA state.
1823 * @param pThisCC The VGA/VMSVGA state for the current context.
1824 */
1825DECLINLINE(void) vmsvgaHCUpdatePitch(PVGASTATE pThis, PVGASTATECC pThisCC)
1826{
1827 uint32_t RT_UNTRUSTED_VOLATILE_GUEST *pFIFO = pThisCC->svga.pau32FIFO;
1828 uint32_t uFifoPitchLock = pFIFO[SVGA_FIFO_PITCHLOCK];
1829 uint32_t uRegPitchLock = pThis->svga.u32PitchLock;
1830 uint32_t uFifoMin = pFIFO[SVGA_FIFO_MIN];
1831
1832 /* The SVGA_FIFO_PITCHLOCK register is only valid if SVGA_FIFO_MIN points past
1833 * it. If SVGA_FIFO_MIN is small, there may well be data at the SVGA_FIFO_PITCHLOCK
1834 * location but it has a different meaning.
1835 */
1836 if ((uFifoMin / sizeof(uint32_t)) <= SVGA_FIFO_PITCHLOCK)
1837 uFifoPitchLock = 0;
1838
1839 /* Sanitize values. */
1840 if ((uFifoPitchLock < 200) || (uFifoPitchLock > 32768))
1841 uFifoPitchLock = 0;
1842 if ((uRegPitchLock < 200) || (uRegPitchLock > 32768))
1843 uRegPitchLock = 0;
1844
1845 /* Prefer the register value to the FIFO value.*/
1846 if (uRegPitchLock)
1847 pThis->svga.cbScanline = uRegPitchLock;
1848 else if (uFifoPitchLock)
1849 pThis->svga.cbScanline = uFifoPitchLock;
1850 else
1851 pThis->svga.cbScanline = pThis->svga.uWidth * (RT_ALIGN(pThis->svga.uBpp, 8) / 8);
1852
1853 if ((uFifoMin / sizeof(uint32_t)) <= SVGA_FIFO_PITCHLOCK)
1854 pThis->svga.u32PitchLock = pThis->svga.cbScanline;
1855}
1856
1857#endif /* IN_RING0 || IN_RING3 */
1858
1859#ifdef IN_RING3
1860
1861/**
1862 * Sends cursor position and visibility information from legacy
1863 * SVGA registers to the front-end.
1864 */
1865static void vmsvgaR3RegUpdateCursor(PVGASTATECC pThisCC, PVGASTATE pThis, uint32_t uCursorOn)
1866{
1867 /*
1868 * Writing the X/Y/ID registers does not trigger changes; only writing the
1869 * SVGA_REG_CURSOR_ON register does. That minimizes the overhead.
1870 * We boldly assume that guests aren't stupid and aren't writing the CURSOR_ON
1871 * register if they don't have to.
1872 */
1873 uint32_t x, y, idScreen;
1874 uint32_t fFlags = VBVA_CURSOR_VALID_DATA;
1875
1876 x = pThis->svga.uCursorX;
1877 y = pThis->svga.uCursorY;
1878 idScreen = SVGA_ID_INVALID; /* The old register interface is single screen only. */
1879
1880 /* The original values for SVGA_REG_CURSOR_ON were off (0) and on (1); later, the values
1881 * were extended as follows:
1882 *
1883 * SVGA_CURSOR_ON_HIDE 0
1884 * SVGA_CURSOR_ON_SHOW 1
1885 * SVGA_CURSOR_ON_REMOVE_FROM_FB 2 - cursor on but not in the framebuffer
1886 * SVGA_CURSOR_ON_RESTORE_TO_FB 3 - cursor on, possibly in the framebuffer
1887 *
1888 * Since we never draw the cursor into the guest's framebuffer, we do not need to
1889 * distinguish between the non-zero values but still remember them.
1890 */
1891 if (RT_BOOL(pThis->svga.uCursorOn) != RT_BOOL(uCursorOn))
1892 {
1893 LogRel2(("vmsvgaR3RegUpdateCursor: uCursorOn %d prev CursorOn %d (%d,%d)\n", uCursorOn, pThis->svga.uCursorOn, x, y));
1894 pThisCC->pDrv->pfnVBVAMousePointerShape(pThisCC->pDrv, RT_BOOL(uCursorOn), false, 0, 0, 0, 0, NULL);
1895 }
1896 pThis->svga.uCursorOn = uCursorOn;
1897 pThisCC->pDrv->pfnVBVAReportCursorPosition(pThisCC->pDrv, fFlags, idScreen, x, y);
1898}
1899
1900
1901/**
1902 * Copy a rectangle of pixels within guest VRAM.
1903 */
1904static void vmsvgaR3RectCopy(PVGASTATECC pThisCC, VMSVGASCREENOBJECT const *pScreen, uint32_t srcX, uint32_t srcY,
1905 uint32_t dstX, uint32_t dstY, uint32_t width, uint32_t height, unsigned cbFrameBuffer)
1906{
1907 if (!width || !height)
1908 return; /* Nothing to do, don't even bother. */
1909
1910 /*
1911 * The guest VRAM (aka GFB) is considered to be a bitmap in the format
1912 * corresponding to the current display mode.
1913 */
1914 uint32_t const cbPixel = RT_ALIGN(pScreen->cBpp, 8) / 8;
1915 uint32_t const cbScanline = pScreen->cbPitch ? pScreen->cbPitch : width * cbPixel;
1916 uint8_t const *pSrc;
1917 uint8_t *pDst;
1918 unsigned const cbRectWidth = width * cbPixel;
1919 unsigned uMaxOffset;
1920
1921 uMaxOffset = (RT_MAX(srcY, dstY) + height) * cbScanline + (RT_MAX(srcX, dstX) + width) * cbPixel;
1922 if (uMaxOffset >= cbFrameBuffer)
1923 {
1924 Log(("Max offset (%u) too big for framebuffer (%u bytes), ignoring!\n", uMaxOffset, cbFrameBuffer));
1925 return; /* Just don't listen to a bad guest. */
1926 }
1927
1928 pSrc = pDst = pThisCC->pbVRam;
1929 pSrc += srcY * cbScanline + srcX * cbPixel;
1930 pDst += dstY * cbScanline + dstX * cbPixel;
1931
1932 if (srcY >= dstY)
1933 {
1934 /* Source below destination, copy top to bottom. */
1935 for (; height > 0; height--)
1936 {
1937 memmove(pDst, pSrc, cbRectWidth);
1938 pSrc += cbScanline;
1939 pDst += cbScanline;
1940 }
1941 }
1942 else
1943 {
1944 /* Source above destination, copy bottom to top. */
1945 pSrc += cbScanline * (height - 1);
1946 pDst += cbScanline * (height - 1);
1947 for (; height > 0; height--)
1948 {
1949 memmove(pDst, pSrc, cbRectWidth);
1950 pSrc -= cbScanline;
1951 pDst -= cbScanline;
1952 }
1953 }
1954}
1955
1956#endif /* IN_RING3 */
1957
1958
1959/**
1960 * Write port register
1961 *
1962 * @returns Strict VBox status code.
1963 * @param pDevIns The device instance.
1964 * @param pThis The shared VGA/VMSVGA state.
1965 * @param pThisCC The VGA/VMSVGA state for the current context.
1966 * @param u32 Value to write
1967 */
1968static VBOXSTRICTRC vmsvgaWritePort(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, uint32_t u32)
1969{
1970#ifdef IN_RING3
1971 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
1972#endif
1973 VBOXSTRICTRC rc = VINF_SUCCESS;
1974 RT_NOREF(pThisCC);
1975
1976 /* Rough index register validation. */
1977 uint32_t idxReg = pThis->svga.u32IndexReg;
1978#if !defined(IN_RING3) && defined(VBOX_STRICT)
1979 ASSERT_GUEST_MSG_RETURN(idxReg < SVGA_SCRATCH_BASE + pThis->svga.cScratchRegion, ("idxReg=%#x\n", idxReg),
1980 VINF_IOM_R3_IOPORT_WRITE);
1981#else
1982 ASSERT_GUEST_MSG_STMT_RETURN(idxReg < SVGA_SCRATCH_BASE + pThis->svga.cScratchRegion, ("idxReg=%#x\n", idxReg),
1983 STAM_REL_COUNTER_INC(&pThis->svga.StatRegUnknownWr),
1984 VINF_SUCCESS);
1985#endif
1986 RT_UNTRUSTED_VALIDATED_FENCE();
1987
1988 /* We must adjust the register number if we're in SVGA_ID_0 mode because the PALETTE range moved. */
1989 if ( idxReg >= SVGA_REG_ID_0_TOP
1990 && pThis->svga.u32SVGAId == SVGA_ID_0)
1991 {
1992 idxReg += SVGA_PALETTE_BASE - SVGA_REG_ID_0_TOP;
1993 Log(("vmsvgaWritePort: SVGA_ID_0 reg adj %#x -> %#x\n", pThis->svga.u32IndexReg, idxReg));
1994 }
1995 Log(("vmsvgaWritePort index=%s (%d) val=%#x\n", vmsvgaIndexToString(pThis, idxReg), idxReg, u32));
1996 /* Check if the guest uses legacy registers. See vmsvgaR3ChangeMode */
1997 switch (idxReg)
1998 {
1999 case SVGA_REG_WIDTH:
2000 case SVGA_REG_HEIGHT:
2001 case SVGA_REG_PITCHLOCK:
2002 case SVGA_REG_BITS_PER_PIXEL:
2003 pThis->svga.fGFBRegisters = true;
2004 break;
2005 default:
2006 break;
2007 }
2008
2009 switch (idxReg)
2010 {
2011 case SVGA_REG_ID:
2012 STAM_REL_COUNTER_INC(&pThis->svga.StatRegIdWr);
2013 if ( u32 == SVGA_ID_0
2014 || u32 == SVGA_ID_1
2015 || u32 == SVGA_ID_2)
2016 pThis->svga.u32SVGAId = u32;
2017 else
2018 PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "Trying to set SVGA_REG_ID to %#x (%d)\n", u32, u32);
2019 break;
2020
2021 case SVGA_REG_ENABLE:
2022 STAM_REL_COUNTER_INC(&pThis->svga.StatRegEnableWr);
2023#ifdef IN_RING3
2024 if ( (u32 & SVGA_REG_ENABLE_ENABLE)
2025 && pThis->svga.fEnabled == false)
2026 {
2027 /* Make a backup copy of the first 512kb in order to save font data etc. */
2028 /** @todo should probably swap here, rather than copy + zero */
2029 memcpy(pThisCC->svga.pbVgaFrameBufferR3, pThisCC->pbVRam, VMSVGA_VGA_FB_BACKUP_SIZE);
2030 memset(pThisCC->pbVRam, 0, VMSVGA_VGA_FB_BACKUP_SIZE);
2031 }
2032
2033 pThis->svga.fEnabled = u32;
2034 if (pThis->svga.fEnabled)
2035 {
2036 if ( pThis->svga.uWidth == VMSVGA_VAL_UNINITIALIZED
2037 && pThis->svga.uHeight == VMSVGA_VAL_UNINITIALIZED)
2038 {
2039 /* Keep the current mode. */
2040 pThis->svga.uWidth = pThisCC->pDrv->cx;
2041 pThis->svga.uHeight = pThisCC->pDrv->cy;
2042 pThis->svga.uBpp = (pThisCC->pDrv->cBits + 7) & ~7;
2043 }
2044
2045 if ( pThis->svga.uWidth != VMSVGA_VAL_UNINITIALIZED
2046 && pThis->svga.uHeight != VMSVGA_VAL_UNINITIALIZED)
2047 ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE);
2048# ifdef LOG_ENABLED
2049 uint32_t *pFIFO = pThisCC->svga.pau32FIFO;
2050 Log(("configured=%d busy=%d\n", pThis->svga.fConfigured, pFIFO[SVGA_FIFO_BUSY]));
2051 Log(("next %x stop %x\n", pFIFO[SVGA_FIFO_NEXT_CMD], pFIFO[SVGA_FIFO_STOP]));
2052# endif
2053
2054 /* Disable or enable dirty page tracking according to the current fTraces value. */
2055 vmsvgaR3SetTraces(pDevIns, pThis, !!pThis->svga.fTraces);
2056
2057 /* bird: Whatever this is was added to make screenshot work, ask sunlover should explain... */
2058 for (uint32_t idScreen = 0; idScreen < pThis->cMonitors; ++idScreen)
2059 pThisCC->pDrv->pfnVBVAEnable(pThisCC->pDrv, idScreen, NULL /*pHostFlags*/);
2060
2061 /* Make the cursor visible again as needed. */
2062 if (pSVGAState->Cursor.fActive)
2063 pThisCC->pDrv->pfnVBVAMousePointerShape(pThisCC->pDrv, true /*fVisible*/, false, 0, 0, 0, 0, NULL);
2064 }
2065 else
2066 {
2067 /* Make sure the cursor is off. */
2068 if (pSVGAState->Cursor.fActive)
2069 pThisCC->pDrv->pfnVBVAMousePointerShape(pThisCC->pDrv, false /*fVisible*/, false, 0, 0, 0, 0, NULL);
2070
2071 /* Restore the text mode backup. */
2072 memcpy(pThisCC->pbVRam, pThisCC->svga.pbVgaFrameBufferR3, VMSVGA_VGA_FB_BACKUP_SIZE);
2073
2074 pThisCC->pDrv->pfnLFBModeChange(pThisCC->pDrv, false);
2075
2076 /* Enable dirty page tracking again when going into legacy mode. */
2077 vmsvgaR3SetTraces(pDevIns, pThis, true);
2078
2079 /* bird: Whatever this is was added to make screenshot work, ask sunlover should explain... */
2080 for (uint32_t idScreen = 0; idScreen < pThis->cMonitors; ++idScreen)
2081 pThisCC->pDrv->pfnVBVADisable(pThisCC->pDrv, idScreen);
2082
2083 /* Clear the pitch lock. */
2084 pThis->svga.u32PitchLock = 0;
2085 }
2086#else /* !IN_RING3 */
2087 rc = VINF_IOM_R3_IOPORT_WRITE;
2088#endif /* !IN_RING3 */
2089 break;
2090
2091 case SVGA_REG_WIDTH:
2092 STAM_REL_COUNTER_INC(&pThis->svga.StatRegWidthWr);
2093 if (pThis->svga.uWidth != u32)
2094 {
2095#if defined(IN_RING3) || defined(IN_RING0)
2096 pThis->svga.uWidth = u32;
2097 vmsvgaHCUpdatePitch(pThis, pThisCC);
2098 if (pThis->svga.fEnabled)
2099 ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE);
2100#else
2101 rc = VINF_IOM_R3_IOPORT_WRITE;
2102#endif
2103 }
2104 /* else: nop */
2105 break;
2106
2107 case SVGA_REG_HEIGHT:
2108 STAM_REL_COUNTER_INC(&pThis->svga.StatRegHeightWr);
2109 if (pThis->svga.uHeight != u32)
2110 {
2111 pThis->svga.uHeight = u32;
2112 if (pThis->svga.fEnabled)
2113 ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE);
2114 }
2115 /* else: nop */
2116 break;
2117
2118 case SVGA_REG_DEPTH:
2119 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDepthWr);
2120 /** @todo read-only?? */
2121 break;
2122
2123 case SVGA_REG_BITS_PER_PIXEL: /* Current bpp in the guest */
2124 STAM_REL_COUNTER_INC(&pThis->svga.StatRegBitsPerPixelWr);
2125 if (pThis->svga.uBpp != u32)
2126 {
2127#if defined(IN_RING3) || defined(IN_RING0)
2128 pThis->svga.uBpp = u32;
2129 vmsvgaHCUpdatePitch(pThis, pThisCC);
2130 if (pThis->svga.fEnabled)
2131 ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE);
2132#else
2133 rc = VINF_IOM_R3_IOPORT_WRITE;
2134#endif
2135 }
2136 /* else: nop */
2137 break;
2138
2139 case SVGA_REG_PSEUDOCOLOR:
2140 STAM_REL_COUNTER_INC(&pThis->svga.StatRegPseudoColorWr);
2141 break;
2142
2143 case SVGA_REG_CONFIG_DONE: /* Set when memory area configured */
2144#ifdef IN_RING3
2145 STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegConfigDoneWr);
2146 pThis->svga.fConfigured = u32;
2147 /* Disabling the FIFO enables tracing (dirty page detection) by default. */
2148 if (!pThis->svga.fConfigured)
2149 pThis->svga.fTraces = true;
2150 vmsvgaR3SetTraces(pDevIns, pThis, !!pThis->svga.fTraces);
2151#else
2152 rc = VINF_IOM_R3_IOPORT_WRITE;
2153#endif
2154 break;
2155
2156 case SVGA_REG_SYNC: /* See "FIFO Synchronization Registers" */
2157 STAM_REL_COUNTER_INC(&pThis->svga.StatRegSyncWr);
2158 if ( pThis->svga.fEnabled
2159 && pThis->svga.fConfigured)
2160 {
2161#if defined(IN_RING3) || defined(IN_RING0)
2162 Log(("SVGA_REG_SYNC: SVGA_FIFO_BUSY=%d\n", pThisCC->svga.pau32FIFO[SVGA_FIFO_BUSY]));
2163 /*
2164 * The VMSVGA_BUSY_F_EMT_FORCE flag makes sure we will check if the FIFO is empty
2165 * at least once; VMSVGA_BUSY_F_FIFO alone does not ensure that.
2166 */
2167 ASMAtomicWriteU32(&pThis->svga.fBusy, VMSVGA_BUSY_F_EMT_FORCE | VMSVGA_BUSY_F_FIFO);
2168 if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_BUSY, pThisCC->svga.pau32FIFO[SVGA_FIFO_MIN]))
2169 vmsvgaHCSafeFifoBusyRegUpdate(pThis, pThisCC, true);
2170
2171 /* Kick the FIFO thread to start processing commands again. */
2172 PDMDevHlpSUPSemEventSignal(pDevIns, pThis->svga.hFIFORequestSem);
2173#else
2174 rc = VINF_IOM_R3_IOPORT_WRITE;
2175#endif
2176 }
2177 /* else nothing to do. */
2178 else
2179 Log(("Sync ignored enabled=%d configured=%d\n", pThis->svga.fEnabled, pThis->svga.fConfigured));
2180
2181 break;
2182
2183 case SVGA_REG_BUSY: /* See "FIFO Synchronization Registers" (read-only) */
2184 STAM_REL_COUNTER_INC(&pThis->svga.StatRegBusyWr);
2185 break;
2186
2187 case SVGA_REG_GUEST_ID: /* Set guest OS identifier */
2188 STAM_REL_COUNTER_INC(&pThis->svga.StatRegGuestIdWr);
2189 pThis->svga.u32GuestId = u32;
2190 break;
2191
2192 case SVGA_REG_PITCHLOCK: /* Fixed pitch for all modes */
2193 STAM_REL_COUNTER_INC(&pThis->svga.StatRegPitchLockWr);
2194 pThis->svga.u32PitchLock = u32;
2195 /* Should this also update the FIFO pitch lock? Unclear. */
2196 break;
2197
2198 case SVGA_REG_IRQMASK: /* Interrupt mask */
2199 STAM_REL_COUNTER_INC(&pThis->svga.StatRegIrqMaskWr);
2200 pThis->svga.u32IrqMask = u32;
2201
2202 /* Irq pending after the above change? */
2203 if (pThis->svga.u32IrqStatus & u32)
2204 {
2205 Log(("SVGA_REG_IRQMASK: Trigger interrupt with status %x\n", pThis->svga.u32IrqStatus));
2206 PDMDevHlpPCISetIrqNoWait(pDevIns, 0, 1);
2207 }
2208 else
2209 PDMDevHlpPCISetIrqNoWait(pDevIns, 0, 0);
2210 break;
2211
2212 /* Mouse cursor support */
2213 case SVGA_REG_CURSOR_ID:
2214 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorIdWr);
2215 pThis->svga.uCursorID = u32;
2216 break;
2217
2218 case SVGA_REG_CURSOR_X:
2219 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorXWr);
2220 pThis->svga.uCursorX = u32;
2221 break;
2222
2223 case SVGA_REG_CURSOR_Y:
2224 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorYWr);
2225 pThis->svga.uCursorY = u32;
2226 break;
2227
2228 case SVGA_REG_CURSOR_ON:
2229#ifdef IN_RING3
2230 /* The cursor is only updated when SVGA_REG_CURSOR_ON is written. */
2231 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorOnWr);
2232 vmsvgaR3RegUpdateCursor(pThisCC, pThis, u32);
2233#else
2234 rc = VINF_IOM_R3_IOPORT_WRITE;
2235#endif
2236 break;
2237
2238 /* Legacy multi-monitor support */
2239 case SVGA_REG_NUM_GUEST_DISPLAYS:/* Number of guest displays in X/Y direction */
2240 STAM_REL_COUNTER_INC(&pThis->svga.StatRegNumGuestDisplaysWr);
2241 break;
2242 case SVGA_REG_DISPLAY_ID: /* Display ID for the following display attributes */
2243 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayIdWr);
2244 break;
2245 case SVGA_REG_DISPLAY_IS_PRIMARY:/* Whether this is a primary display */
2246 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayIsPrimaryWr);
2247 break;
2248 case SVGA_REG_DISPLAY_POSITION_X:/* The display position x */
2249 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayPositionXWr);
2250 break;
2251 case SVGA_REG_DISPLAY_POSITION_Y:/* The display position y */
2252 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayPositionYWr);
2253 break;
2254 case SVGA_REG_DISPLAY_WIDTH: /* The display's width */
2255 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayWidthWr);
2256 break;
2257 case SVGA_REG_DISPLAY_HEIGHT: /* The display's height */
2258 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayHeightWr);
2259 break;
2260#ifdef VBOX_WITH_VMSVGA3D
2261 /* See "Guest memory regions" below. */
2262 case SVGA_REG_GMR_ID:
2263 STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrIdWr);
2264 pThis->svga.u32CurrentGMRId = u32;
2265 break;
2266
2267 case SVGA_REG_GMR_DESCRIPTOR:
2268# ifndef IN_RING3
2269 rc = VINF_IOM_R3_IOPORT_WRITE;
2270 break;
2271# else /* IN_RING3 */
2272 {
2273 STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegGmrDescriptorWr);
2274
2275 /* Validate current GMR id. */
2276 uint32_t idGMR = pThis->svga.u32CurrentGMRId;
2277 AssertBreak(idGMR < pThis->svga.cGMR);
2278 RT_UNTRUSTED_VALIDATED_FENCE();
2279
2280 /* Free the old GMR if present. */
2281 vmsvgaR3GmrFree(pThisCC, idGMR);
2282
2283 /* Just undefine the GMR? */
2284 RTGCPHYS GCPhys = (RTGCPHYS)u32 << PAGE_SHIFT;
2285 if (GCPhys == 0)
2286 {
2287 STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegGmrDescriptorWrFree);
2288 break;
2289 }
2290
2291
2292 /* Never cross a page boundary automatically. */
2293 const uint32_t cMaxPages = RT_MIN(VMSVGA_MAX_GMR_PAGES, UINT32_MAX / X86_PAGE_SIZE);
2294 uint32_t cPagesTotal = 0;
2295 uint32_t iDesc = 0;
2296 PVMSVGAGMRDESCRIPTOR paDescs = NULL;
2297 uint32_t cLoops = 0;
2298 RTGCPHYS GCPhysBase = GCPhys;
2299 while (PHYS_PAGE_ADDRESS(GCPhys) == PHYS_PAGE_ADDRESS(GCPhysBase))
2300 {
2301 /* Read descriptor. */
2302 SVGAGuestMemDescriptor desc;
2303 rc = PDMDevHlpPhysRead(pDevIns, GCPhys, &desc, sizeof(desc));
2304 AssertRCBreak(VBOXSTRICTRC_VAL(rc));
2305
2306 if (desc.numPages != 0)
2307 {
2308 AssertBreakStmt(desc.numPages <= cMaxPages, rc = VERR_OUT_OF_RANGE);
2309 cPagesTotal += desc.numPages;
2310 AssertBreakStmt(cPagesTotal <= cMaxPages, rc = VERR_OUT_OF_RANGE);
2311
2312 if ((iDesc & 15) == 0)
2313 {
2314 void *pvNew = RTMemRealloc(paDescs, (iDesc + 16) * sizeof(VMSVGAGMRDESCRIPTOR));
2315 AssertBreakStmt(pvNew, rc = VERR_NO_MEMORY);
2316 paDescs = (PVMSVGAGMRDESCRIPTOR)pvNew;
2317 }
2318
2319 paDescs[iDesc].GCPhys = (RTGCPHYS)desc.ppn << PAGE_SHIFT;
2320 paDescs[iDesc++].numPages = desc.numPages;
2321
2322 /* Continue with the next descriptor. */
2323 GCPhys += sizeof(desc);
2324 }
2325 else if (desc.ppn == 0)
2326 break; /* terminator */
2327 else /* Pointer to the next physical page of descriptors. */
2328 GCPhys = GCPhysBase = (RTGCPHYS)desc.ppn << PAGE_SHIFT;
2329
2330 cLoops++;
2331 AssertBreakStmt(cLoops < VMSVGA_MAX_GMR_DESC_LOOP_COUNT, rc = VERR_OUT_OF_RANGE);
2332 }
2333
2334 AssertStmt(iDesc > 0 || RT_FAILURE_NP(rc), rc = VERR_OUT_OF_RANGE);
2335 if (RT_SUCCESS(rc))
2336 {
2337 /* Commit the GMR. */
2338 pSVGAState->paGMR[idGMR].paDesc = paDescs;
2339 pSVGAState->paGMR[idGMR].numDescriptors = iDesc;
2340 pSVGAState->paGMR[idGMR].cMaxPages = cPagesTotal;
2341 pSVGAState->paGMR[idGMR].cbTotal = cPagesTotal * PAGE_SIZE;
2342 Assert((pSVGAState->paGMR[idGMR].cbTotal >> PAGE_SHIFT) == cPagesTotal);
2343 Log(("Defined new gmr %x numDescriptors=%d cbTotal=%x (%#x pages)\n",
2344 idGMR, iDesc, pSVGAState->paGMR[idGMR].cbTotal, cPagesTotal));
2345 }
2346 else
2347 {
2348 RTMemFree(paDescs);
2349 STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegGmrDescriptorWrErrors);
2350 }
2351 break;
2352 }
2353# endif /* IN_RING3 */
2354#endif // VBOX_WITH_VMSVGA3D
2355
2356 case SVGA_REG_TRACES: /* Enable trace-based updates even when FIFO is on */
2357 STAM_REL_COUNTER_INC(&pThis->svga.StatRegTracesWr);
2358 if (pThis->svga.fTraces == u32)
2359 break; /* nothing to do */
2360
2361#ifdef IN_RING3
2362 vmsvgaR3SetTraces(pDevIns, pThis, !!u32);
2363#else
2364 rc = VINF_IOM_R3_IOPORT_WRITE;
2365#endif
2366 break;
2367
2368 case SVGA_REG_TOP: /* Must be 1 more than the last register */
2369 STAM_REL_COUNTER_INC(&pThis->svga.StatRegTopWr);
2370 break;
2371
2372 case SVGA_REG_NUM_DISPLAYS: /* (Deprecated) */
2373 STAM_REL_COUNTER_INC(&pThis->svga.StatRegNumDisplaysWr);
2374 Log(("Write to deprecated register %x - val %x ignored\n", idxReg, u32));
2375 break;
2376
2377 /*
2378 * SVGA_CAP_GBOBJECTS+ registers.
2379 */
2380 case SVGA_REG_COMMAND_LOW:
2381 {
2382 /* Lower 32 bits of command buffer physical address and submit the command buffer. */
2383#ifdef IN_RING3
2384 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCommandLowWr);
2385 pThis->svga.u32RegCommandLow = u32;
2386
2387 /* "lower 6 bits are used for the SVGACBContext" */
2388 RTGCPHYS GCPhysCB = pThis->svga.u32RegCommandHigh;
2389 GCPhysCB <<= 32;
2390 GCPhysCB |= pThis->svga.u32RegCommandLow & ~SVGA_CB_CONTEXT_MASK;
2391 SVGACBContext const CBCtx = (SVGACBContext)(pThis->svga.u32RegCommandLow & SVGA_CB_CONTEXT_MASK);
2392 vmsvgaR3CmdBufSubmit(pDevIns, pThis, pThisCC, GCPhysCB, CBCtx);
2393#else
2394 rc = VINF_IOM_R3_IOPORT_WRITE;
2395#endif
2396 break;
2397 }
2398
2399 case SVGA_REG_COMMAND_HIGH:
2400 /* Upper 32 bits of command buffer PA. */
2401 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCommandHighWr);
2402 pThis->svga.u32RegCommandHigh = u32;
2403 break;
2404
2405 case SVGA_REG_DEV_CAP:
2406 /* Write dev cap index, read value */
2407 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDevCapWr);
2408 pThis->svga.u32DevCapIndex = u32;
2409 break;
2410
2411 case SVGA_REG_CMD_PREPEND_LOW:
2412 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCmdPrependLowWr);
2413 /* Not supported. */
2414 break;
2415
2416 case SVGA_REG_iCMD_PREPEND_HIGH:
2417 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCmdPrependHighWr);
2418 /* Not supported. */
2419 break;
2420
2421 case SVGA_REG_FB_START:
2422 case SVGA_REG_MEM_START:
2423 case SVGA_REG_HOST_BITS_PER_PIXEL:
2424 case SVGA_REG_MAX_WIDTH:
2425 case SVGA_REG_MAX_HEIGHT:
2426 case SVGA_REG_VRAM_SIZE:
2427 case SVGA_REG_FB_SIZE:
2428 case SVGA_REG_CAPABILITIES:
2429 case SVGA_REG_MEM_SIZE:
2430 case SVGA_REG_SCRATCH_SIZE: /* Number of scratch registers */
2431 case SVGA_REG_MEM_REGS: /* Number of FIFO registers */
2432 case SVGA_REG_BYTES_PER_LINE:
2433 case SVGA_REG_FB_OFFSET:
2434 case SVGA_REG_RED_MASK:
2435 case SVGA_REG_GREEN_MASK:
2436 case SVGA_REG_BLUE_MASK:
2437 case SVGA_REG_GMRS_MAX_PAGES: /* Maximum number of 4KB pages for all GMRs */
2438 case SVGA_REG_MEMORY_SIZE: /* Total dedicated device memory excluding FIFO */
2439 case SVGA_REG_GMR_MAX_IDS:
2440 case SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH:
2441 case SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM:
2442 case SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB:
2443 case SVGA_REG_SCREENTARGET_MAX_WIDTH:
2444 case SVGA_REG_SCREENTARGET_MAX_HEIGHT:
2445 case SVGA_REG_MOB_MAX_SIZE:
2446 /* Read only - ignore. */
2447 Log(("Write to R/O register %x - val %x ignored\n", idxReg, u32));
2448 STAM_REL_COUNTER_INC(&pThis->svga.StatRegReadOnlyWr);
2449 break;
2450
2451 default:
2452 {
2453 uint32_t offReg;
2454 if ((offReg = idxReg - SVGA_SCRATCH_BASE) < pThis->svga.cScratchRegion)
2455 {
2456 RT_UNTRUSTED_VALIDATED_FENCE();
2457 pThis->svga.au32ScratchRegion[offReg] = u32;
2458 STAM_REL_COUNTER_INC(&pThis->svga.StatRegScratchWr);
2459 }
2460 else if ((offReg = idxReg - SVGA_PALETTE_BASE) < (uint32_t)SVGA_NUM_PALETTE_REGS)
2461 {
2462 /* Note! Using last_palette rather than palette here to preserve the VGA one.
2463 Btw, see rgb_to_pixel32. */
2464 STAM_REL_COUNTER_INC(&pThis->svga.StatRegPaletteWr);
2465 u32 &= 0xff;
2466 RT_UNTRUSTED_VALIDATED_FENCE();
2467 uint32_t uRgb = pThis->last_palette[offReg / 3];
2468 switch (offReg % 3)
2469 {
2470 case 0: uRgb = (uRgb & UINT32_C(0x0000ffff)) | (u32 << 16); break; /* red */
2471 case 1: uRgb = (uRgb & UINT32_C(0x00ff00ff)) | (u32 << 8); break; /* green */
2472 case 2: uRgb = (uRgb & UINT32_C(0x00ffff00)) | u32 ; break; /* blue */
2473 }
2474 pThis->last_palette[offReg / 3] = uRgb;
2475 }
2476 else
2477 {
2478#if !defined(IN_RING3) && defined(VBOX_STRICT)
2479 rc = VINF_IOM_R3_IOPORT_WRITE;
2480#else
2481 STAM_REL_COUNTER_INC(&pThis->svga.StatRegUnknownWr);
2482 AssertMsgFailed(("reg=%#x u32=%#x\n", idxReg, u32));
2483#endif
2484 }
2485 break;
2486 }
2487 }
2488 return rc;
2489}
2490
2491/**
2492 * @callback_method_impl{FNIOMIOPORTNEWIN}
2493 */
2494DECLCALLBACK(VBOXSTRICTRC) vmsvgaIORead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb)
2495{
2496 PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
2497 RT_NOREF_PV(pvUser);
2498
2499 /* Only dword accesses. */
2500 if (cb == 4)
2501 {
2502 switch (offPort)
2503 {
2504 case SVGA_INDEX_PORT:
2505 *pu32 = pThis->svga.u32IndexReg;
2506 break;
2507
2508 case SVGA_VALUE_PORT:
2509 return vmsvgaReadPort(pDevIns, pThis, pu32);
2510
2511 case SVGA_BIOS_PORT:
2512 Log(("Ignoring BIOS port read\n"));
2513 *pu32 = 0;
2514 break;
2515
2516 case SVGA_IRQSTATUS_PORT:
2517 LogFlow(("vmsvgaIORead: SVGA_IRQSTATUS_PORT %x\n", pThis->svga.u32IrqStatus));
2518 *pu32 = pThis->svga.u32IrqStatus;
2519 break;
2520
2521 default:
2522 ASSERT_GUEST_MSG_FAILED(("vmsvgaIORead: Unknown register %u was read from.\n", offPort));
2523 *pu32 = UINT32_MAX;
2524 break;
2525 }
2526 }
2527 else
2528 {
2529 Log(("Ignoring non-dword I/O port read at %x cb=%d\n", offPort, cb));
2530 *pu32 = UINT32_MAX;
2531 }
2532 return VINF_SUCCESS;
2533}
2534
2535/**
2536 * @callback_method_impl{FNIOMIOPORTNEWOUT}
2537 */
2538DECLCALLBACK(VBOXSTRICTRC) vmsvgaIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb)
2539{
2540 PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
2541 PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
2542 RT_NOREF_PV(pvUser);
2543
2544 /* Only dword accesses. */
2545 if (cb == 4)
2546 switch (offPort)
2547 {
2548 case SVGA_INDEX_PORT:
2549 pThis->svga.u32IndexReg = u32;
2550 break;
2551
2552 case SVGA_VALUE_PORT:
2553 return vmsvgaWritePort(pDevIns, pThis, pThisCC, u32);
2554
2555 case SVGA_BIOS_PORT:
2556 Log(("Ignoring BIOS port write (val=%x)\n", u32));
2557 break;
2558
2559 case SVGA_IRQSTATUS_PORT:
2560 Log(("vmsvgaIOWrite SVGA_IRQSTATUS_PORT %x: status %x -> %x\n", u32, pThis->svga.u32IrqStatus, pThis->svga.u32IrqStatus & ~u32));
2561 ASMAtomicAndU32(&pThis->svga.u32IrqStatus, ~u32);
2562 /* Clear the irq in case all events have been cleared. */
2563 if (!(pThis->svga.u32IrqStatus & pThis->svga.u32IrqMask))
2564 {
2565 Log(("vmsvgaIOWrite SVGA_IRQSTATUS_PORT: clearing IRQ\n"));
2566 PDMDevHlpPCISetIrqNoWait(pDevIns, 0, 0);
2567 }
2568 break;
2569
2570 default:
2571 ASSERT_GUEST_MSG_FAILED(("vmsvgaIOWrite: Unknown register %u was written to, value %#x LB %u.\n", offPort, u32, cb));
2572 break;
2573 }
2574 else
2575 Log(("Ignoring non-dword write at %x val=%x cb=%d\n", offPort, u32, cb));
2576
2577 return VINF_SUCCESS;
2578}
2579
2580#ifdef IN_RING3
2581
2582# ifdef DEBUG_FIFO_ACCESS
2583/**
2584 * Handle FIFO memory access.
2585 * @returns VBox status code.
2586 * @param pVM VM handle.
2587 * @param pThis The shared VGA/VMSVGA instance data.
2588 * @param GCPhys The access physical address.
2589 * @param fWriteAccess Read or write access
2590 */
2591static 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 */
2939static DECLCALLBACK(VBOXSTRICTRC)
2940vmsvgaR3FifoAccessHandler(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf,
2941 PGMACCESSTYPE enmAccessType, PGMACCESSORIGIN enmOrigin, void *pvUser)
2942{
2943 NOREF(pVCpu); NOREF(pvPhys); NOREF(pvBuf); NOREF(cbBuf); NOREF(enmOrigin); NOREF(enmAccessType); NOREF(GCPhys);
2944 PVGASTATE pThis = (PVGASTATE)pvUser;
2945 AssertPtr(pThis);
2946
2947# ifdef VMSVGA_USE_FIFO_ACCESS_HANDLER
2948 /*
2949 * Wake up the FIFO thread as it might have work to do now.
2950 */
2951 int rc = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->svga.hFIFORequestSem);
2952 AssertLogRelRC(rc);
2953# endif
2954
2955# ifdef DEBUG_FIFO_ACCESS
2956 /*
2957 * When in debug-fifo-access mode, we do not disable the access handler,
2958 * but leave it on as we wish to catch all access.
2959 */
2960 Assert(GCPhys >= pThis->svga.GCPhysFIFO);
2961 rc = vmsvgaR3DebugFifoAccess(pVM, pThis, GCPhys, enmAccessType == PGMACCESSTYPE_WRITE);
2962# elif defined(VMSVGA_USE_FIFO_ACCESS_HANDLER)
2963 /*
2964 * Temporarily disable the access handler now that we've kicked the FIFO thread.
2965 */
2966 STAM_REL_COUNTER_INC(&pThisCC->svga.pSvgaR3State->StatFifoAccessHandler);
2967 rc = PGMHandlerPhysicalPageTempOff(pVM, pThis->svga.GCPhysFIFO, pThis->svga.GCPhysFIFO);
2968# endif
2969 if (RT_SUCCESS(rc))
2970 return VINF_PGM_HANDLER_DO_DEFAULT;
2971 AssertMsg(rc <= VINF_SUCCESS, ("rc=%Rrc\n", rc));
2972 return rc;
2973}
2974# endif /* VMSVGA_USE_FIFO_ACCESS_HANDLER || DEBUG_FIFO_ACCESS */
2975
2976#endif /* IN_RING3 */
2977
2978#ifdef DEBUG_GMR_ACCESS
2979# ifdef IN_RING3
2980
2981/**
2982 * HC access handler for the FIFO.
2983 *
2984 * @returns VINF_SUCCESS if the handler have carried out the operation.
2985 * @returns VINF_PGM_HANDLER_DO_DEFAULT if the caller should carry out the access operation.
2986 * @param pVM VM Handle.
2987 * @param pVCpu The cross context CPU structure for the calling EMT.
2988 * @param GCPhys The physical address the guest is writing to.
2989 * @param pvPhys The HC mapping of that address.
2990 * @param pvBuf What the guest is reading/writing.
2991 * @param cbBuf How much it's reading/writing.
2992 * @param enmAccessType The access type.
2993 * @param enmOrigin Who is making the access.
2994 * @param pvUser User argument.
2995 */
2996static DECLCALLBACK(VBOXSTRICTRC)
2997vmsvgaR3GmrAccessHandler(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 */
3034static 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 */
3052static 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 */
3067static 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 */
3108static 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 */
3197static 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 */
4114static 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 */
4132static 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 */
4150static 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 */
4162static 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 */
4187static 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 */
4224static 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 */
4236static 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 */
4248static 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 */
4501static 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 */
4533static 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 */
4585static 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 */
4651static 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 */
4676static 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 */
4692static 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 */
4763static 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 */
4834static 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 */
4847static 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 */
4861static 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 */
4897static 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 */
5055static 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 */
5077static 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 */
5098static 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 */
5121static 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 */
5133static 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 */
5144static 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 */
5172static 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 */
5210static 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 */
5278static 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 */
5351static 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 */
5368static 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 */
5411static 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 */
5514static 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 */
5532static 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 */
5891static 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 */
5961static 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 */
6065static 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 */
6159static 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 */
6207static 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 */
6349static uint32_t
6350vmsvgaR3FifoUpdateCursor(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 */
6423DECLINLINE(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 */
6450void 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 */
6471void 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 */
6528static 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 */
7158static 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 */
7200int vmsvgaR3GmrTransfer(PVGASTATE pThis, PVGASTATECC pThisCC, const SVGA3dTransferType enmTransferType,
7201 uint8_t *pbHstBuf, uint32_t cbHstBuf, uint32_t offHst, int32_t cbHstPitch,
7202 SVGAGuestPtr gstPtr, uint32_t offGst, int32_t cbGstPitch,
7203 uint32_t cbWidth, uint32_t cHeight)
7204{
7205 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
7206 PPDMDEVINS pDevIns = pThisCC->pDevIns; /* simpler */
7207 int rc;
7208
7209 LogFunc(("%s host %p size=%d offset %d pitch=%d; guest gmr=%#x:%#x offset=%d pitch=%d cbWidth=%d cHeight=%d\n",
7210 enmTransferType == SVGA3D_READ_HOST_VRAM ? "WRITE" : "READ", /* GMR op: READ host VRAM means WRITE GMR */
7211 pbHstBuf, cbHstBuf, offHst, cbHstPitch,
7212 gstPtr.gmrId, gstPtr.offset, offGst, cbGstPitch, cbWidth, cHeight));
7213 AssertReturn(cbWidth && cHeight, VERR_INVALID_PARAMETER);
7214
7215 PGMR pGMR;
7216 uint32_t cbGmr; /* The GMR size in bytes. */
7217 if (gstPtr.gmrId == SVGA_GMR_FRAMEBUFFER)
7218 {
7219 pGMR = NULL;
7220 cbGmr = pThis->vram_size;
7221 }
7222 else
7223 {
7224 AssertReturn(gstPtr.gmrId < pThis->svga.cGMR, VERR_INVALID_PARAMETER);
7225 RT_UNTRUSTED_VALIDATED_FENCE();
7226 pGMR = &pSVGAState->paGMR[gstPtr.gmrId];
7227 cbGmr = pGMR->cbTotal;
7228 }
7229
7230 /*
7231 * GMR
7232 */
7233 /* Calculate GMR offset of the data to be copied. */
7234 AssertMsgReturn(gstPtr.offset < cbGmr,
7235 ("gmr=%#x:%#x offGst=%#x cbGstPitch=%#x cHeight=%#x cbWidth=%#x cbGmr=%#x\n",
7236 gstPtr.gmrId, gstPtr.offset, offGst, cbGstPitch, cHeight, cbWidth, cbGmr),
7237 VERR_INVALID_PARAMETER);
7238 RT_UNTRUSTED_VALIDATED_FENCE();
7239 AssertMsgReturn(offGst < cbGmr - gstPtr.offset,
7240 ("gmr=%#x:%#x offGst=%#x cbGstPitch=%#x cHeight=%#x cbWidth=%#x cbGmr=%#x\n",
7241 gstPtr.gmrId, gstPtr.offset, offGst, cbGstPitch, cHeight, cbWidth, cbGmr),
7242 VERR_INVALID_PARAMETER);
7243 RT_UNTRUSTED_VALIDATED_FENCE();
7244 uint32_t const offGmr = offGst + gstPtr.offset; /* Offset in the GMR, where the first scanline is located. */
7245
7246 /* Verify that cbWidth is less than scanline and fits into the GMR. */
7247 uint32_t const cbGmrScanline = cbGstPitch > 0 ? cbGstPitch : -cbGstPitch;
7248 AssertMsgReturn(cbGmrScanline != 0,
7249 ("gmr=%#x:%#x offGst=%#x cbGstPitch=%#x cHeight=%#x cbWidth=%#x cbGmr=%#x\n",
7250 gstPtr.gmrId, gstPtr.offset, offGst, cbGstPitch, cHeight, cbWidth, cbGmr),
7251 VERR_INVALID_PARAMETER);
7252 RT_UNTRUSTED_VALIDATED_FENCE();
7253 AssertMsgReturn(cbWidth <= cbGmrScanline,
7254 ("gmr=%#x:%#x offGst=%#x cbGstPitch=%#x cHeight=%#x cbWidth=%#x cbGmr=%#x\n",
7255 gstPtr.gmrId, gstPtr.offset, offGst, cbGstPitch, cHeight, cbWidth, cbGmr),
7256 VERR_INVALID_PARAMETER);
7257 AssertMsgReturn(cbWidth <= cbGmr - offGmr,
7258 ("gmr=%#x:%#x offGst=%#x cbGstPitch=%#x cHeight=%#x cbWidth=%#x cbGmr=%#x\n",
7259 gstPtr.gmrId, gstPtr.offset, offGst, cbGstPitch, cHeight, cbWidth, cbGmr),
7260 VERR_INVALID_PARAMETER);
7261 RT_UNTRUSTED_VALIDATED_FENCE();
7262
7263 /* How many bytes are available for the data in the GMR. */
7264 uint32_t const cbGmrLeft = cbGstPitch > 0 ? cbGmr - offGmr : offGmr + cbWidth;
7265
7266 /* How many scanlines would fit into the available data. */
7267 uint32_t cGmrScanlines = cbGmrLeft / cbGmrScanline;
7268 uint32_t const cbGmrLastScanline = cbGmrLeft - cGmrScanlines * cbGmrScanline; /* Slack space. */
7269 if (cbWidth <= cbGmrLastScanline)
7270 ++cGmrScanlines;
7271
7272 if (cHeight > cGmrScanlines)
7273 cHeight = cGmrScanlines;
7274
7275 AssertMsgReturn(cHeight > 0,
7276 ("gmr=%#x:%#x offGst=%#x cbGstPitch=%#x cHeight=%#x cbWidth=%#x cbGmr=%#x\n",
7277 gstPtr.gmrId, gstPtr.offset, offGst, cbGstPitch, cHeight, cbWidth, cbGmr),
7278 VERR_INVALID_PARAMETER);
7279 RT_UNTRUSTED_VALIDATED_FENCE();
7280
7281 /*
7282 * Host buffer.
7283 */
7284 AssertMsgReturn(offHst < cbHstBuf,
7285 ("buffer=%p size %d offHst=%d cbHstPitch=%d cHeight=%d cbWidth=%d\n",
7286 pbHstBuf, cbHstBuf, offHst, cbHstPitch, cHeight, cbWidth),
7287 VERR_INVALID_PARAMETER);
7288
7289 /* Verify that cbWidth is less than scanline and fits into the buffer. */
7290 uint32_t const cbHstScanline = cbHstPitch > 0 ? cbHstPitch : -cbHstPitch;
7291 AssertMsgReturn(cbHstScanline != 0,
7292 ("buffer=%p size %d offHst=%d cbHstPitch=%d cHeight=%d cbWidth=%d\n",
7293 pbHstBuf, cbHstBuf, offHst, cbHstPitch, cHeight, cbWidth),
7294 VERR_INVALID_PARAMETER);
7295 AssertMsgReturn(cbWidth <= cbHstScanline,
7296 ("buffer=%p size %d offHst=%d cbHstPitch=%d cHeight=%d cbWidth=%d\n",
7297 pbHstBuf, cbHstBuf, offHst, cbHstPitch, cHeight, cbWidth),
7298 VERR_INVALID_PARAMETER);
7299 AssertMsgReturn(cbWidth <= cbHstBuf - offHst,
7300 ("buffer=%p size %d offHst=%d cbHstPitch=%d cHeight=%d cbWidth=%d\n",
7301 pbHstBuf, cbHstBuf, offHst, cbHstPitch, cHeight, cbWidth),
7302 VERR_INVALID_PARAMETER);
7303
7304 /* How many bytes are available for the data in the buffer. */
7305 uint32_t const cbHstLeft = cbHstPitch > 0 ? cbHstBuf - offHst : offHst + cbWidth;
7306
7307 /* How many scanlines would fit into the available data. */
7308 uint32_t cHstScanlines = cbHstLeft / cbHstScanline;
7309 uint32_t const cbHstLastScanline = cbHstLeft - cHstScanlines * cbHstScanline; /* Slack space. */
7310 if (cbWidth <= cbHstLastScanline)
7311 ++cHstScanlines;
7312
7313 if (cHeight > cHstScanlines)
7314 cHeight = cHstScanlines;
7315
7316 AssertMsgReturn(cHeight > 0,
7317 ("buffer=%p size %d offHst=%d cbHstPitch=%d cHeight=%d cbWidth=%d\n",
7318 pbHstBuf, cbHstBuf, offHst, cbHstPitch, cHeight, cbWidth),
7319 VERR_INVALID_PARAMETER);
7320
7321 uint8_t *pbHst = pbHstBuf + offHst;
7322
7323 /* Shortcut for the framebuffer. */
7324 if (gstPtr.gmrId == SVGA_GMR_FRAMEBUFFER)
7325 {
7326 uint8_t *pbGst = pThisCC->pbVRam + offGmr;
7327
7328 uint8_t const *pbSrc;
7329 int32_t cbSrcPitch;
7330 uint8_t *pbDst;
7331 int32_t cbDstPitch;
7332
7333 if (enmTransferType == SVGA3D_READ_HOST_VRAM)
7334 {
7335 pbSrc = pbHst;
7336 cbSrcPitch = cbHstPitch;
7337 pbDst = pbGst;
7338 cbDstPitch = cbGstPitch;
7339 }
7340 else
7341 {
7342 pbSrc = pbGst;
7343 cbSrcPitch = cbGstPitch;
7344 pbDst = pbHst;
7345 cbDstPitch = cbHstPitch;
7346 }
7347
7348 if ( cbWidth == (uint32_t)cbGstPitch
7349 && cbGstPitch == cbHstPitch)
7350 {
7351 /* Entire scanlines, positive pitch. */
7352 memcpy(pbDst, pbSrc, cbWidth * cHeight);
7353 }
7354 else
7355 {
7356 for (uint32_t i = 0; i < cHeight; ++i)
7357 {
7358 memcpy(pbDst, pbSrc, cbWidth);
7359
7360 pbDst += cbDstPitch;
7361 pbSrc += cbSrcPitch;
7362 }
7363 }
7364 return VINF_SUCCESS;
7365 }
7366
7367 AssertPtrReturn(pGMR, VERR_INVALID_PARAMETER);
7368 AssertReturn(pGMR->numDescriptors > 0, VERR_INVALID_PARAMETER);
7369
7370 PVMSVGAGMRDESCRIPTOR const paDesc = pGMR->paDesc; /* Local copy of the pointer. */
7371 uint32_t iDesc = 0; /* Index in the descriptor array. */
7372 uint32_t offDesc = 0; /* GMR offset of the current descriptor. */
7373 uint32_t offGmrScanline = offGmr; /* GMR offset of the scanline which is being copied. */
7374 uint8_t *pbHstScanline = pbHst; /* Host address of the scanline which is being copied. */
7375 for (uint32_t i = 0; i < cHeight; ++i)
7376 {
7377 uint32_t cbCurrentWidth = cbWidth;
7378 uint32_t offGmrCurrent = offGmrScanline;
7379 uint8_t *pbCurrentHost = pbHstScanline;
7380
7381 /* Find the right descriptor */
7382 while (offDesc + paDesc[iDesc].numPages * PAGE_SIZE <= offGmrCurrent)
7383 {
7384 offDesc += paDesc[iDesc].numPages * PAGE_SIZE;
7385 AssertReturn(offDesc < pGMR->cbTotal, VERR_INTERNAL_ERROR); /* overflow protection */
7386 ++iDesc;
7387 AssertReturn(iDesc < pGMR->numDescriptors, VERR_INTERNAL_ERROR);
7388 }
7389
7390 while (cbCurrentWidth)
7391 {
7392 uint32_t cbToCopy;
7393
7394 if (offGmrCurrent + cbCurrentWidth <= offDesc + paDesc[iDesc].numPages * PAGE_SIZE)
7395 {
7396 cbToCopy = cbCurrentWidth;
7397 }
7398 else
7399 {
7400 cbToCopy = (offDesc + paDesc[iDesc].numPages * PAGE_SIZE - offGmrCurrent);
7401 AssertReturn(cbToCopy <= cbCurrentWidth, VERR_INVALID_PARAMETER);
7402 }
7403
7404 RTGCPHYS const GCPhys = paDesc[iDesc].GCPhys + offGmrCurrent - offDesc;
7405
7406 Log5Func(("%s phys=%RGp\n", (enmTransferType == SVGA3D_WRITE_HOST_VRAM) ? "READ" : "WRITE", GCPhys));
7407
7408 if (enmTransferType == SVGA3D_WRITE_HOST_VRAM)
7409 rc = PDMDevHlpPhysRead(pDevIns, GCPhys, pbCurrentHost, cbToCopy);
7410 else
7411 rc = PDMDevHlpPhysWrite(pDevIns, GCPhys, pbCurrentHost, cbToCopy);
7412 AssertRCBreak(rc);
7413
7414 cbCurrentWidth -= cbToCopy;
7415 offGmrCurrent += cbToCopy;
7416 pbCurrentHost += cbToCopy;
7417
7418 /* Go to the next descriptor if there's anything left. */
7419 if (cbCurrentWidth)
7420 {
7421 offDesc += paDesc[iDesc].numPages * PAGE_SIZE;
7422 AssertReturn(offDesc < pGMR->cbTotal, VERR_INTERNAL_ERROR);
7423 ++iDesc;
7424 AssertReturn(iDesc < pGMR->numDescriptors, VERR_INTERNAL_ERROR);
7425 }
7426 }
7427
7428 offGmrScanline += cbGstPitch;
7429 pbHstScanline += cbHstPitch;
7430 }
7431
7432 return VINF_SUCCESS;
7433}
7434
7435
7436/**
7437 * Unsigned coordinates in pBox. Clip to [0; pSizeSrc), [0; pSizeDest).
7438 *
7439 * @param pSizeSrc Source surface dimensions.
7440 * @param pSizeDest Destination surface dimensions.
7441 * @param pBox Coordinates to be clipped.
7442 */
7443void 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 */
7488void 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 */
7515void 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 */
7575static 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 */
7590static 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 */
7638DECLCALLBACK(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 */
7707void 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 */
7717DECLCALLBACK(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 */
7762DECLCALLBACK(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 */
7787DECLCALLBACK(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 */
7809static 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 */
7896static 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 */
7956int 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 */
8063int 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 */
8108static 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 */
8138int 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 */
8198static 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 */
8246static 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 */
8274static 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. */
8322static 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 */
8577static 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 */
8650int 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 */
8703int 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 */
8761int 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 */
9094DECLCALLBACK(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 */
9120DECLCALLBACK(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 */
Note: See TracBrowser for help on using the repository browser.

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