VirtualBox

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

Last change on this file since 97405 was 96950, checked in by vboxsync, 2 years ago

Devices/Graphics: Some old Xorg servers apparently in collaboration with
old versions of GNOME can send window coordinates with a negative height
value via SVGA_CMD_UPDATE which ends up as an index array in subsequent
VBox code. Drop such invalid updates in vmsvgaR3UpdateScreen() as is
done similarly elsewhere (and assert(3C) if enabled). bugref:10292

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 306.9 KB
Line 
1/* $Id: DevVGA-SVGA.cpp 96950 2022-09-30 10:19:06Z 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 * - Log6 for DX shaders.
13 * - Log7 for SVGA command dump.
14 * - LogRel for the usual important stuff.
15 * - LogRel2 for cursor.
16 * - LogRel3 for 3D performance data.
17 * - LogRel4 for HW accelerated graphics output.
18 */
19
20/*
21 * Copyright (C) 2013-2022 Oracle and/or its affiliates.
22 *
23 * This file is part of VirtualBox base platform packages, as
24 * available from https://www.virtualbox.org.
25 *
26 * This program is free software; you can redistribute it and/or
27 * modify it under the terms of the GNU General Public License
28 * as published by the Free Software Foundation, in version 3 of the
29 * License.
30 *
31 * This program is distributed in the hope that it will be useful, but
32 * WITHOUT ANY WARRANTY; without even the implied warranty of
33 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
34 * General Public License for more details.
35 *
36 * You should have received a copy of the GNU General Public License
37 * along with this program; if not, see <https://www.gnu.org/licenses>.
38 *
39 * SPDX-License-Identifier: GPL-3.0-only
40 */
41
42
43/** @page pg_dev_vmsvga VMSVGA - VMware SVGA II Device Emulation
44 *
45 * This device emulation was contributed by trivirt AG. It offers an
46 * alternative to our Bochs based VGA graphics and 3d emulations. This is
47 * valuable for Xorg based guests, as there is driver support shipping with Xorg
48 * since it forked from XFree86.
49 *
50 *
51 * @section sec_dev_vmsvga_sdk The VMware SDK
52 *
53 * This is officially deprecated now, however it's still quite useful,
54 * especially for getting the old features working:
55 * http://vmware-svga.sourceforge.net/
56 *
57 * They currently point developers at the following resources.
58 * - http://cgit.freedesktop.org/xorg/driver/xf86-video-vmware/
59 * - http://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/svga/
60 * - http://cgit.freedesktop.org/mesa/vmwgfx/
61 *
62 * @subsection subsec_dev_vmsvga_sdk_results Test results
63 *
64 * Test results:
65 * - 2dmark.img:
66 * + todo
67 * - backdoor-tclo.img:
68 * + todo
69 * - blit-cube.img:
70 * + todo
71 * - bunnies.img:
72 * + todo
73 * - cube.img:
74 * + todo
75 * - cubemark.img:
76 * + todo
77 * - dynamic-vertex-stress.img:
78 * + todo
79 * - dynamic-vertex.img:
80 * + todo
81 * - fence-stress.img:
82 * + todo
83 * - gmr-test.img:
84 * + todo
85 * - half-float-test.img:
86 * + todo
87 * - noscreen-cursor.img:
88 * - The CURSOR I/O and FIFO registers are not implemented, so the mouse
89 * cursor doesn't show. (Hacking the GUI a little, would make the cursor
90 * visible though.)
91 * - Cursor animation via the palette doesn't work.
92 * - During debugging, it turns out that the framebuffer content seems to
93 * be halfways ignore or something (memset(fb, 0xcc, lots)).
94 * - Trouble with way to small FIFO and the 256x256 cursor fails. Need to
95 * grow it 0x10 fold (128KB -> 2MB like in WS10).
96 * - null.img:
97 * + todo
98 * - pong.img:
99 * + todo
100 * - presentReadback.img:
101 * + todo
102 * - resolution-set.img:
103 * + todo
104 * - rt-gamma-test.img:
105 * + todo
106 * - screen-annotation.img:
107 * + todo
108 * - screen-cursor.img:
109 * + todo
110 * - screen-dma-coalesce.img:
111 * + todo
112 * - screen-gmr-discontig.img:
113 * + todo
114 * - screen-gmr-remap.img:
115 * + todo
116 * - screen-multimon.img:
117 * + todo
118 * - screen-present-clip.img:
119 * + todo
120 * - screen-render-test.img:
121 * + todo
122 * - screen-simple.img:
123 * + todo
124 * - screen-text.img:
125 * + todo
126 * - simple-shaders.img:
127 * + todo
128 * - simple_blit.img:
129 * + todo
130 * - tiny-2d-updates.img:
131 * + todo
132 * - video-formats.img:
133 * + todo
134 * - video-sync.img:
135 * + todo
136 *
137 */
138
139
140/*********************************************************************************************************************************
141* Header Files *
142*********************************************************************************************************************************/
143#define LOG_GROUP LOG_GROUP_DEV_VMSVGA
144#include <VBox/vmm/pdmdev.h>
145#include <VBox/version.h>
146#include <VBox/err.h>
147#include <VBox/log.h>
148#include <VBox/vmm/pgm.h>
149#include <VBox/sup.h>
150
151#include <iprt/assert.h>
152#include <iprt/semaphore.h>
153#include <iprt/uuid.h>
154#ifdef IN_RING3
155# include <iprt/ctype.h>
156# include <iprt/mem.h>
157# ifdef VBOX_STRICT
158# include <iprt/time.h>
159# endif
160#endif
161
162#include <VBox/AssertGuest.h>
163#include <VBox/VMMDev.h>
164#include <VBoxVideo.h>
165#include <VBox/bioslogo.h>
166
167#ifdef LOG_ENABLED
168#include "svgadump/svga_dump.h"
169#endif
170
171/* should go BEFORE any other DevVGA include to make all DevVGA.h config defines be visible */
172#include "DevVGA.h"
173
174/* Should be included after DevVGA.h/DevVGA-SVGA.h to pick all defines. */
175#ifdef VBOX_WITH_VMSVGA3D
176# include "DevVGA-SVGA3d.h"
177# ifdef RT_OS_DARWIN
178# include "DevVGA-SVGA3d-cocoa.h"
179# endif
180# ifdef RT_OS_LINUX
181# ifdef IN_RING3
182# include "DevVGA-SVGA3d-glLdr.h"
183# endif
184# endif
185#endif
186#ifdef IN_RING3
187#include "DevVGA-SVGA-internal.h"
188#endif
189
190
191/*********************************************************************************************************************************
192* Defined Constants And Macros *
193*********************************************************************************************************************************/
194/**
195 * Macro for checking if a fixed FIFO register is valid according to the
196 * current FIFO configuration.
197 *
198 * @returns true / false.
199 * @param a_iIndex The fifo register index (like SVGA_FIFO_CAPABILITIES).
200 * @param a_offFifoMin A valid SVGA_FIFO_MIN value.
201 */
202#define VMSVGA_IS_VALID_FIFO_REG(a_iIndex, a_offFifoMin) ( ((a_iIndex) + 1) * sizeof(uint32_t) <= (a_offFifoMin) )
203
204
205/*********************************************************************************************************************************
206* Structures and Typedefs *
207*********************************************************************************************************************************/
208
209
210/*********************************************************************************************************************************
211* Internal Functions *
212*********************************************************************************************************************************/
213#ifdef IN_RING3
214# if defined(VMSVGA_USE_FIFO_ACCESS_HANDLER) || defined(DEBUG_FIFO_ACCESS)
215static FNPGMPHYSHANDLER vmsvgaR3FifoAccessHandler;
216# endif
217# ifdef DEBUG_GMR_ACCESS
218static FNPGMPHYSHANDLER vmsvgaR3GmrAccessHandler;
219# endif
220#endif
221
222
223/*********************************************************************************************************************************
224* Global Variables *
225*********************************************************************************************************************************/
226#ifdef IN_RING3
227
228/**
229 * SSM descriptor table for the VMSVGAGMRDESCRIPTOR structure.
230 */
231static SSMFIELD const g_aVMSVGAGMRDESCRIPTORFields[] =
232{
233 SSMFIELD_ENTRY_GCPHYS( VMSVGAGMRDESCRIPTOR, GCPhys),
234 SSMFIELD_ENTRY( VMSVGAGMRDESCRIPTOR, numPages),
235 SSMFIELD_ENTRY_TERM()
236};
237
238/**
239 * SSM descriptor table for the GMR structure.
240 */
241static SSMFIELD const g_aGMRFields[] =
242{
243 SSMFIELD_ENTRY( GMR, cMaxPages),
244 SSMFIELD_ENTRY( GMR, cbTotal),
245 SSMFIELD_ENTRY( GMR, numDescriptors),
246 SSMFIELD_ENTRY_IGN_HCPTR( GMR, paDesc),
247 SSMFIELD_ENTRY_TERM()
248};
249
250/**
251 * SSM descriptor table for the VMSVGASCREENOBJECT structure.
252 */
253static SSMFIELD const g_aVMSVGASCREENOBJECTFields[] =
254{
255 SSMFIELD_ENTRY( VMSVGASCREENOBJECT, fuScreen),
256 SSMFIELD_ENTRY( VMSVGASCREENOBJECT, idScreen),
257 SSMFIELD_ENTRY( VMSVGASCREENOBJECT, xOrigin),
258 SSMFIELD_ENTRY( VMSVGASCREENOBJECT, yOrigin),
259 SSMFIELD_ENTRY( VMSVGASCREENOBJECT, cWidth),
260 SSMFIELD_ENTRY( VMSVGASCREENOBJECT, cHeight),
261 SSMFIELD_ENTRY( VMSVGASCREENOBJECT, offVRAM),
262 SSMFIELD_ENTRY( VMSVGASCREENOBJECT, cbPitch),
263 SSMFIELD_ENTRY( VMSVGASCREENOBJECT, cBpp),
264 SSMFIELD_ENTRY( VMSVGASCREENOBJECT, fDefined),
265 SSMFIELD_ENTRY( VMSVGASCREENOBJECT, fModified),
266 SSMFIELD_ENTRY_VER( VMSVGASCREENOBJECT, cDpi, VGA_SAVEDSTATE_VERSION_VMSVGA_MIPLEVELS),
267 SSMFIELD_ENTRY_TERM()
268};
269
270/**
271 * SSM descriptor table for the VMSVGAR3STATE structure.
272 */
273static SSMFIELD const g_aVMSVGAR3STATEFields[] =
274{
275 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, paGMR),
276 SSMFIELD_ENTRY( VMSVGAR3STATE, GMRFB),
277 SSMFIELD_ENTRY( VMSVGAR3STATE, Cursor.fActive),
278 SSMFIELD_ENTRY( VMSVGAR3STATE, Cursor.xHotspot),
279 SSMFIELD_ENTRY( VMSVGAR3STATE, Cursor.yHotspot),
280 SSMFIELD_ENTRY( VMSVGAR3STATE, Cursor.width),
281 SSMFIELD_ENTRY( VMSVGAR3STATE, Cursor.height),
282 SSMFIELD_ENTRY( VMSVGAR3STATE, Cursor.cbData),
283 SSMFIELD_ENTRY_IGN_HCPTR( VMSVGAR3STATE, Cursor.pData),
284 SSMFIELD_ENTRY( VMSVGAR3STATE, colorAnnotation),
285 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, cBusyDelayedEmts),
286#ifdef VMSVGA_USE_EMT_HALT_CODE
287 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, BusyDelayedEmts),
288#else
289 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, hBusyDelayedEmts),
290#endif
291 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatBusyDelayEmts),
292 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dPresentProf),
293 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dDrawPrimitivesProf),
294 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSurfaceDmaProf),
295 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dBlitSurfaceToScreenProf),
296 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdDefineGmr2),
297 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdDefineGmr2Free),
298 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdDefineGmr2Modify),
299 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdRemapGmr2),
300 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdRemapGmr2Modify),
301 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdInvalidCmd),
302 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdFence),
303 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdUpdate),
304 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdUpdateVerbose),
305 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdDefineCursor),
306 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdDefineAlphaCursor),
307 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdMoveCursor),
308 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdDisplayCursor),
309 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdRectFill),
310 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdRectCopy),
311 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdRectRopCopy),
312 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdEscape),
313 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdDefineScreen),
314 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdDestroyScreen),
315 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdDefineGmrFb),
316 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdBlitGmrFbToScreen),
317 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdBlitScreentoGmrFb),
318 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdAnnotationFill),
319 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdAnnotationCopy),
320 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSurfaceDefine),
321 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSurfaceDefineV2),
322 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSurfaceDestroy),
323 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSurfaceCopy),
324 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSurfaceStretchBlt),
325 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSurfaceDma),
326 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSurfaceScreen),
327 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dContextDefine),
328 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dContextDestroy),
329 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetTransform),
330 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetZRange),
331 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetRenderState),
332 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetRenderTarget),
333 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetTextureState),
334 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetMaterial),
335 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetLightData),
336 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetLightEnable),
337 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetViewPort),
338 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetClipPlane),
339 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dClear),
340 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dPresent),
341 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dPresentReadBack),
342 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dShaderDefine),
343 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dShaderDestroy),
344 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetShader),
345 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetShaderConst),
346 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dDrawPrimitives),
347 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetScissorRect),
348 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dBeginQuery),
349 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dEndQuery),
350 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dWaitForQuery),
351 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dGenerateMipmaps),
352 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dActivateSurface),
353 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dDeactivateSurface),
354
355 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3RegConfigDoneWr),
356 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3RegGmrDescriptorWr),
357 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3RegGmrDescriptorWrErrors),
358 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3RegGmrDescriptorWrFree),
359
360 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatFifoCommands),
361 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatFifoErrors),
362 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatFifoUnkCmds),
363 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatFifoTodoTimeout),
364 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatFifoTodoWoken),
365 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatFifoStalls),
366 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatFifoExtendedSleep),
367# if defined(VMSVGA_USE_FIFO_ACCESS_HANDLER) || defined(DEBUG_FIFO_ACCESS)
368 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatFifoAccessHandler),
369# endif
370 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatFifoCursorFetchAgain),
371 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatFifoCursorNoChange),
372 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatFifoCursorPosition),
373 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatFifoCursorVisiblity),
374
375 SSMFIELD_ENTRY_TERM()
376};
377
378/**
379 * SSM descriptor table for the VGAState.svga structure.
380 */
381static SSMFIELD const g_aVGAStateSVGAFields[] =
382{
383 SSMFIELD_ENTRY_IGN_GCPHYS( VMSVGAState, GCPhysFIFO),
384 SSMFIELD_ENTRY_IGNORE( VMSVGAState, cbFIFO),
385 SSMFIELD_ENTRY_IGNORE( VMSVGAState, cbFIFOConfig),
386 SSMFIELD_ENTRY( VMSVGAState, u32SVGAId),
387 SSMFIELD_ENTRY( VMSVGAState, fEnabled),
388 SSMFIELD_ENTRY( VMSVGAState, fConfigured),
389 SSMFIELD_ENTRY( VMSVGAState, fBusy),
390 SSMFIELD_ENTRY( VMSVGAState, fTraces),
391 SSMFIELD_ENTRY( VMSVGAState, u32GuestId),
392 SSMFIELD_ENTRY( VMSVGAState, cScratchRegion),
393 SSMFIELD_ENTRY( VMSVGAState, au32ScratchRegion),
394 SSMFIELD_ENTRY( VMSVGAState, u32IrqStatus),
395 SSMFIELD_ENTRY( VMSVGAState, u32IrqMask),
396 SSMFIELD_ENTRY( VMSVGAState, u32PitchLock),
397 SSMFIELD_ENTRY( VMSVGAState, u32CurrentGMRId),
398 SSMFIELD_ENTRY( VMSVGAState, u32DeviceCaps),
399 SSMFIELD_ENTRY( VMSVGAState, u32IndexReg),
400 SSMFIELD_ENTRY_IGNORE( VMSVGAState, hFIFORequestSem),
401 SSMFIELD_ENTRY_IGNORE( VMSVGAState, uLastCursorUpdateCount),
402 SSMFIELD_ENTRY_IGNORE( VMSVGAState, fFIFOThreadSleeping),
403 SSMFIELD_ENTRY_VER( VMSVGAState, fGFBRegisters, VGA_SAVEDSTATE_VERSION_VMSVGA_SCREENS),
404 SSMFIELD_ENTRY( VMSVGAState, uWidth),
405 SSMFIELD_ENTRY( VMSVGAState, uHeight),
406 SSMFIELD_ENTRY( VMSVGAState, uBpp),
407 SSMFIELD_ENTRY( VMSVGAState, cbScanline),
408 SSMFIELD_ENTRY_VER( VMSVGAState, uScreenOffset, VGA_SAVEDSTATE_VERSION_VMSVGA),
409 SSMFIELD_ENTRY_VER( VMSVGAState, uCursorX, VGA_SAVEDSTATE_VERSION_VMSVGA_CURSOR),
410 SSMFIELD_ENTRY_VER( VMSVGAState, uCursorY, VGA_SAVEDSTATE_VERSION_VMSVGA_CURSOR),
411 SSMFIELD_ENTRY_VER( VMSVGAState, uCursorID, VGA_SAVEDSTATE_VERSION_VMSVGA_CURSOR),
412 SSMFIELD_ENTRY_VER( VMSVGAState, uCursorOn, VGA_SAVEDSTATE_VERSION_VMSVGA_CURSOR),
413 SSMFIELD_ENTRY( VMSVGAState, u32MaxWidth),
414 SSMFIELD_ENTRY( VMSVGAState, u32MaxHeight),
415 SSMFIELD_ENTRY( VMSVGAState, u32ActionFlags),
416 SSMFIELD_ENTRY( VMSVGAState, f3DEnabled),
417 SSMFIELD_ENTRY( VMSVGAState, fVRAMTracking),
418 SSMFIELD_ENTRY_IGNORE( VMSVGAState, u8FIFOExtCommand),
419 SSMFIELD_ENTRY_IGNORE( VMSVGAState, fFifoExtCommandWakeup),
420 SSMFIELD_ENTRY_IGNORE( VMSVGAState, cGMR),
421 SSMFIELD_ENTRY_VER( VMSVGAState, au32DevCaps, VGA_SAVEDSTATE_VERSION_VMSVGA_DX),
422 SSMFIELD_ENTRY_VER( VMSVGAState, u32DevCapIndex, VGA_SAVEDSTATE_VERSION_VMSVGA_DX),
423 SSMFIELD_ENTRY_VER( VMSVGAState, u32RegCommandLow, VGA_SAVEDSTATE_VERSION_VMSVGA_DX),
424 SSMFIELD_ENTRY_VER( VMSVGAState, u32RegCommandHigh, VGA_SAVEDSTATE_VERSION_VMSVGA_DX),
425
426 SSMFIELD_ENTRY_TERM()
427};
428#endif /* IN_RING3 */
429
430
431/*********************************************************************************************************************************
432* Internal Functions *
433*********************************************************************************************************************************/
434#ifdef IN_RING3
435static void vmsvgaR3SetTraces(PPDMDEVINS pDevIns, PVGASTATE pThis, bool fTraces);
436static int vmsvgaR3LoadExecFifo(PCPDMDEVHLPR3 pHlp, PVGASTATE pThis, PVGASTATECC pThisCC, PSSMHANDLE pSSM,
437 uint32_t uVersion, uint32_t uPass);
438static int vmsvgaR3SaveExecFifo(PCPDMDEVHLPR3 pHlp, PVGASTATECC pThisCC, PSSMHANDLE pSSM);
439static void vmsvgaR3CmdBufSubmit(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, RTGCPHYS GCPhysCB, SVGACBContext CBCtx);
440static void vmsvgaR3PowerOnDevice(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, bool fLoadState);
441#endif /* IN_RING3 */
442
443
444#define SVGA_CASE_ID2STR(idx) case idx: return #idx
445#if defined(LOG_ENABLED)
446/**
447 * Index register string name lookup
448 *
449 * @returns Index register string or "UNKNOWN"
450 * @param pThis The shared VGA/VMSVGA state.
451 * @param idxReg The index register.
452 */
453static const char *vmsvgaIndexToString(PVGASTATE pThis, uint32_t idxReg)
454{
455 AssertCompile(SVGA_REG_TOP == 77); /* Ensure that the correct headers are used. */
456 switch (idxReg)
457 {
458 SVGA_CASE_ID2STR(SVGA_REG_ID);
459 SVGA_CASE_ID2STR(SVGA_REG_ENABLE);
460 SVGA_CASE_ID2STR(SVGA_REG_WIDTH);
461 SVGA_CASE_ID2STR(SVGA_REG_HEIGHT);
462 SVGA_CASE_ID2STR(SVGA_REG_MAX_WIDTH);
463 SVGA_CASE_ID2STR(SVGA_REG_MAX_HEIGHT);
464 SVGA_CASE_ID2STR(SVGA_REG_DEPTH);
465 SVGA_CASE_ID2STR(SVGA_REG_BITS_PER_PIXEL); /* Current bpp in the guest */
466 SVGA_CASE_ID2STR(SVGA_REG_PSEUDOCOLOR);
467 SVGA_CASE_ID2STR(SVGA_REG_RED_MASK);
468 SVGA_CASE_ID2STR(SVGA_REG_GREEN_MASK);
469 SVGA_CASE_ID2STR(SVGA_REG_BLUE_MASK);
470 SVGA_CASE_ID2STR(SVGA_REG_BYTES_PER_LINE);
471 SVGA_CASE_ID2STR(SVGA_REG_FB_START); /* (Deprecated) */
472 SVGA_CASE_ID2STR(SVGA_REG_FB_OFFSET);
473 SVGA_CASE_ID2STR(SVGA_REG_VRAM_SIZE);
474 SVGA_CASE_ID2STR(SVGA_REG_FB_SIZE);
475
476 /* ID 0 implementation only had the above registers, then the palette */
477 SVGA_CASE_ID2STR(SVGA_REG_CAPABILITIES);
478 SVGA_CASE_ID2STR(SVGA_REG_MEM_START); /* (Deprecated) */
479 SVGA_CASE_ID2STR(SVGA_REG_MEM_SIZE);
480 SVGA_CASE_ID2STR(SVGA_REG_CONFIG_DONE); /* Set when memory area configured */
481 SVGA_CASE_ID2STR(SVGA_REG_SYNC); /* See "FIFO Synchronization Registers" */
482 SVGA_CASE_ID2STR(SVGA_REG_BUSY); /* See "FIFO Synchronization Registers" */
483 SVGA_CASE_ID2STR(SVGA_REG_GUEST_ID); /* Set guest OS identifier */
484 SVGA_CASE_ID2STR(SVGA_REG_DEAD); /* (Deprecated) SVGA_REG_CURSOR_ID. */
485 SVGA_CASE_ID2STR(SVGA_REG_CURSOR_X); /* (Deprecated) */
486 SVGA_CASE_ID2STR(SVGA_REG_CURSOR_Y); /* (Deprecated) */
487 SVGA_CASE_ID2STR(SVGA_REG_CURSOR_ON); /* (Deprecated) */
488 SVGA_CASE_ID2STR(SVGA_REG_HOST_BITS_PER_PIXEL); /* (Deprecated) */
489 SVGA_CASE_ID2STR(SVGA_REG_SCRATCH_SIZE); /* Number of scratch registers */
490 SVGA_CASE_ID2STR(SVGA_REG_MEM_REGS); /* Number of FIFO registers */
491 SVGA_CASE_ID2STR(SVGA_REG_NUM_DISPLAYS); /* (Deprecated) */
492 SVGA_CASE_ID2STR(SVGA_REG_PITCHLOCK); /* Fixed pitch for all modes */
493 SVGA_CASE_ID2STR(SVGA_REG_IRQMASK); /* Interrupt mask */
494
495 /* Legacy multi-monitor support */
496 SVGA_CASE_ID2STR(SVGA_REG_NUM_GUEST_DISPLAYS); /* Number of guest displays in X/Y direction */
497 SVGA_CASE_ID2STR(SVGA_REG_DISPLAY_ID); /* Display ID for the following display attributes */
498 SVGA_CASE_ID2STR(SVGA_REG_DISPLAY_IS_PRIMARY); /* Whether this is a primary display */
499 SVGA_CASE_ID2STR(SVGA_REG_DISPLAY_POSITION_X); /* The display position x */
500 SVGA_CASE_ID2STR(SVGA_REG_DISPLAY_POSITION_Y); /* The display position y */
501 SVGA_CASE_ID2STR(SVGA_REG_DISPLAY_WIDTH); /* The display's width */
502 SVGA_CASE_ID2STR(SVGA_REG_DISPLAY_HEIGHT); /* The display's height */
503
504 SVGA_CASE_ID2STR(SVGA_REG_GMR_ID);
505 SVGA_CASE_ID2STR(SVGA_REG_GMR_DESCRIPTOR);
506 SVGA_CASE_ID2STR(SVGA_REG_GMR_MAX_IDS);
507 SVGA_CASE_ID2STR(SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH);
508
509 SVGA_CASE_ID2STR(SVGA_REG_TRACES); /* Enable trace-based updates even when FIFO is on */
510 SVGA_CASE_ID2STR(SVGA_REG_GMRS_MAX_PAGES); /* Maximum number of 4KB pages for all GMRs */
511 SVGA_CASE_ID2STR(SVGA_REG_MEMORY_SIZE); /* Total dedicated device memory excluding FIFO */
512 SVGA_CASE_ID2STR(SVGA_REG_COMMAND_LOW); /* Lower 32 bits and submits commands */
513 SVGA_CASE_ID2STR(SVGA_REG_COMMAND_HIGH); /* Upper 32 bits of command buffer PA */
514 SVGA_CASE_ID2STR(SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM); /* Max primary memory */
515 SVGA_CASE_ID2STR(SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB); /* Suggested limit on mob mem */
516 SVGA_CASE_ID2STR(SVGA_REG_DEV_CAP); /* Write dev cap index, read value */
517 SVGA_CASE_ID2STR(SVGA_REG_CMD_PREPEND_LOW);
518 SVGA_CASE_ID2STR(SVGA_REG_CMD_PREPEND_HIGH);
519 SVGA_CASE_ID2STR(SVGA_REG_SCREENTARGET_MAX_WIDTH);
520 SVGA_CASE_ID2STR(SVGA_REG_SCREENTARGET_MAX_HEIGHT);
521 SVGA_CASE_ID2STR(SVGA_REG_MOB_MAX_SIZE);
522 SVGA_CASE_ID2STR(SVGA_REG_BLANK_SCREEN_TARGETS);
523 SVGA_CASE_ID2STR(SVGA_REG_CAP2);
524 SVGA_CASE_ID2STR(SVGA_REG_DEVEL_CAP);
525 SVGA_CASE_ID2STR(SVGA_REG_GUEST_DRIVER_ID);
526 SVGA_CASE_ID2STR(SVGA_REG_GUEST_DRIVER_VERSION1);
527 SVGA_CASE_ID2STR(SVGA_REG_GUEST_DRIVER_VERSION2);
528 SVGA_CASE_ID2STR(SVGA_REG_GUEST_DRIVER_VERSION3);
529 SVGA_CASE_ID2STR(SVGA_REG_CURSOR_MOBID);
530 SVGA_CASE_ID2STR(SVGA_REG_CURSOR_MAX_BYTE_SIZE);
531 SVGA_CASE_ID2STR(SVGA_REG_CURSOR_MAX_DIMENSION);
532 SVGA_CASE_ID2STR(SVGA_REG_FIFO_CAPS);
533 SVGA_CASE_ID2STR(SVGA_REG_FENCE);
534 SVGA_CASE_ID2STR(SVGA_REG_RESERVED1);
535 SVGA_CASE_ID2STR(SVGA_REG_RESERVED2);
536 SVGA_CASE_ID2STR(SVGA_REG_RESERVED3);
537 SVGA_CASE_ID2STR(SVGA_REG_RESERVED4);
538 SVGA_CASE_ID2STR(SVGA_REG_RESERVED5);
539 SVGA_CASE_ID2STR(SVGA_REG_SCREENDMA);
540 SVGA_CASE_ID2STR(SVGA_REG_GBOBJECT_MEM_SIZE_KB);
541 SVGA_CASE_ID2STR(SVGA_REG_TOP); /* Must be 1 more than the last register */
542
543 default:
544 if (idxReg - (uint32_t)SVGA_SCRATCH_BASE < pThis->svga.cScratchRegion)
545 return "SVGA_SCRATCH_BASE reg";
546 if (idxReg - (uint32_t)SVGA_PALETTE_BASE < (uint32_t)SVGA_NUM_PALETTE_REGS)
547 return "SVGA_PALETTE_BASE reg";
548 return "UNKNOWN";
549 }
550}
551#endif /* LOG_ENABLED */
552
553#if defined(LOG_ENABLED) || (defined(IN_RING3) && defined(VBOX_WITH_VMSVGA3D))
554static const char *vmsvgaDevCapIndexToString(SVGA3dDevCapIndex idxDevCap)
555{
556 AssertCompile(SVGA3D_DEVCAP_MAX == 260);
557 switch (idxDevCap)
558 {
559 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_INVALID);
560 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_3D);
561 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_LIGHTS);
562 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_TEXTURES);
563 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_CLIP_PLANES);
564 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_VERTEX_SHADER_VERSION);
565 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_VERTEX_SHADER);
566 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_FRAGMENT_SHADER_VERSION);
567 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_FRAGMENT_SHADER);
568 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_RENDER_TARGETS);
569 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_S23E8_TEXTURES);
570 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_S10E5_TEXTURES);
571 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_FIXED_VERTEXBLEND);
572 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_D16_BUFFER_FORMAT);
573 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_D24S8_BUFFER_FORMAT);
574 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_D24X8_BUFFER_FORMAT);
575 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_QUERY_TYPES);
576 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_TEXTURE_GRADIENT_SAMPLING);
577 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_POINT_SIZE);
578 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_SHADER_TEXTURES);
579 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_TEXTURE_WIDTH);
580 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_TEXTURE_HEIGHT);
581 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_VOLUME_EXTENT);
582 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_TEXTURE_REPEAT);
583 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_TEXTURE_ASPECT_RATIO);
584 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_TEXTURE_ANISOTROPY);
585 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_PRIMITIVE_COUNT);
586 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_VERTEX_INDEX);
587 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_VERTEX_SHADER_INSTRUCTIONS);
588 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_INSTRUCTIONS);
589 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEMPS);
590 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_TEMPS);
591 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_TEXTURE_OPS);
592 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8);
593 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8);
594 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10);
595 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5);
596 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5);
597 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4);
598 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_R5G6B5);
599 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE16);
600 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8);
601 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_ALPHA8);
602 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8);
603 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_Z_D16);
604 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8);
605 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8);
606 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_DXT1);
607 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_DXT2);
608 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_DXT3);
609 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_DXT4);
610 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_DXT5);
611 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_BUMPX8L8V8U8);
612 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_A2W10V10U10);
613 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_BUMPU8V8);
614 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_Q8W8V8U8);
615 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_CxV8U8);
616 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_R_S10E5);
617 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_R_S23E8);
618 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_RG_S10E5);
619 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_RG_S23E8);
620 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_ARGB_S10E5);
621 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_ARGB_S23E8);
622 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MISSING62);
623 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEXTURES);
624 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_SIMULTANEOUS_RENDER_TARGETS);
625 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_V16U16);
626 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_G16R16);
627 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16);
628 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_UYVY);
629 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_YUY2);
630 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DEAD4); /* SVGA3D_DEVCAP_MULTISAMPLE_NONMASKABLESAMPLES */
631 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DEAD5); /* SVGA3D_DEVCAP_MULTISAMPLE_MASKABLESAMPLES */
632 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DEAD7); /* SVGA3D_DEVCAP_ALPHATOCOVERAGE */
633 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DEAD6); /* SVGA3D_DEVCAP_SUPERSAMPLE */
634 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_AUTOGENMIPMAPS);
635 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_NV12);
636 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DEAD10); /* SVGA3D_DEVCAP_SURFACEFMT_AYUV */
637 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_CONTEXT_IDS);
638 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_SURFACE_IDS);
639 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_Z_DF16);
640 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_Z_DF24);
641 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8_INT);
642 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_ATI1);
643 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_ATI2);
644 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DEAD1);
645 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DEAD8); /* SVGA3D_DEVCAP_VIDEO_DECODE */
646 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DEAD9); /* SVGA3D_DEVCAP_VIDEO_PROCESS */
647 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_LINE_AA);
648 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_LINE_STIPPLE);
649 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_LINE_WIDTH);
650 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX_AA_LINE_WIDTH);
651 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SURFACEFMT_YV12);
652 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DEAD3); /* Old SVGA3D_DEVCAP_LOGICOPS */
653 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_TS_COLOR_KEY);
654 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DEAD2);
655 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXCONTEXT);
656 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DEAD11); /* SVGA3D_DEVCAP_MAX_TEXTURE_ARRAY_SIZE */
657 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DX_MAX_VERTEXBUFFERS);
658 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DX_MAX_CONSTANT_BUFFERS);
659 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DX_PROVOKING_VERTEX);
660 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_X8R8G8B8);
661 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_A8R8G8B8);
662 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R5G6B5);
663 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_X1R5G5B5);
664 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_A1R5G5B5);
665 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_A4R4G4B4);
666 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_Z_D32);
667 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_Z_D16);
668 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_Z_D24S8);
669 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_Z_D15S1);
670 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_LUMINANCE8);
671 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_LUMINANCE4_ALPHA4);
672 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_LUMINANCE16);
673 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_LUMINANCE8_ALPHA8);
674 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_DXT1);
675 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_DXT2);
676 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_DXT3);
677 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_DXT4);
678 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_DXT5);
679 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BUMPU8V8);
680 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BUMPL6V5U5);
681 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BUMPX8L8V8U8);
682 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_FORMAT_DEAD1);
683 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_ARGB_S10E5);
684 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_ARGB_S23E8);
685 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_A2R10G10B10);
686 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_V8U8);
687 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_Q8W8V8U8);
688 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_CxV8U8);
689 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_X8L8V8U8);
690 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_A2W10V10U10);
691 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_ALPHA8);
692 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R_S10E5);
693 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R_S23E8);
694 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_RG_S10E5);
695 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_RG_S23E8);
696 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BUFFER);
697 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_Z_D24X8);
698 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_V16U16);
699 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_G16R16);
700 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_A16B16G16R16);
701 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_UYVY);
702 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_YUY2);
703 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_NV12);
704 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_FORMAT_DEAD2); /* SVGA3D_DEVCAP_DXFMT_AYUV */
705 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R32G32B32A32_TYPELESS);
706 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R32G32B32A32_UINT);
707 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R32G32B32A32_SINT);
708 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R32G32B32_TYPELESS);
709 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R32G32B32_FLOAT);
710 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R32G32B32_UINT);
711 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R32G32B32_SINT);
712 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R16G16B16A16_TYPELESS);
713 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R16G16B16A16_UINT);
714 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R16G16B16A16_SNORM);
715 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R16G16B16A16_SINT);
716 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R32G32_TYPELESS);
717 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R32G32_UINT);
718 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R32G32_SINT);
719 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R32G8X24_TYPELESS);
720 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_D32_FLOAT_S8X24_UINT);
721 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R32_FLOAT_X8X24);
722 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_X32_G8X24_UINT);
723 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R10G10B10A2_TYPELESS);
724 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R10G10B10A2_UINT);
725 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R11G11B10_FLOAT);
726 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R8G8B8A8_TYPELESS);
727 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R8G8B8A8_UNORM);
728 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R8G8B8A8_UNORM_SRGB);
729 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R8G8B8A8_UINT);
730 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R8G8B8A8_SINT);
731 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R16G16_TYPELESS);
732 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R16G16_UINT);
733 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R16G16_SINT);
734 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R32_TYPELESS);
735 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_D32_FLOAT);
736 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R32_UINT);
737 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R32_SINT);
738 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R24G8_TYPELESS);
739 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_D24_UNORM_S8_UINT);
740 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R24_UNORM_X8);
741 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_X24_G8_UINT);
742 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R8G8_TYPELESS);
743 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R8G8_UNORM);
744 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R8G8_UINT);
745 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R8G8_SINT);
746 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R16_TYPELESS);
747 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R16_UNORM);
748 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R16_UINT);
749 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R16_SNORM);
750 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R16_SINT);
751 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R8_TYPELESS);
752 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R8_UNORM);
753 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R8_UINT);
754 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R8_SNORM);
755 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R8_SINT);
756 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_P8);
757 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R9G9B9E5_SHAREDEXP);
758 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R8G8_B8G8_UNORM);
759 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_G8R8_G8B8_UNORM);
760 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BC1_TYPELESS);
761 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BC1_UNORM_SRGB);
762 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BC2_TYPELESS);
763 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BC2_UNORM_SRGB);
764 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BC3_TYPELESS);
765 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BC3_UNORM_SRGB);
766 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BC4_TYPELESS);
767 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_ATI1);
768 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BC4_SNORM);
769 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BC5_TYPELESS);
770 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_ATI2);
771 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BC5_SNORM);
772 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R10G10B10_XR_BIAS_A2_UNORM);
773 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_B8G8R8A8_TYPELESS);
774 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_B8G8R8A8_UNORM_SRGB);
775 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_B8G8R8X8_TYPELESS);
776 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_B8G8R8X8_UNORM_SRGB);
777 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_Z_DF16);
778 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_Z_DF24);
779 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_Z_D24S8_INT);
780 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_YV12);
781 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R32G32B32A32_FLOAT);
782 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R16G16B16A16_FLOAT);
783 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R16G16B16A16_UNORM);
784 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R32G32_FLOAT);
785 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R10G10B10A2_UNORM);
786 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R8G8B8A8_SNORM);
787 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R16G16_FLOAT);
788 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R16G16_UNORM);
789 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R16G16_SNORM);
790 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R32_FLOAT);
791 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R8G8_SNORM);
792 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_R16_FLOAT);
793 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_D16_UNORM);
794 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_A8_UNORM);
795 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BC1_UNORM);
796 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BC2_UNORM);
797 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BC3_UNORM);
798 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_B5G6R5_UNORM);
799 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_B5G5R5A1_UNORM);
800 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_B8G8R8A8_UNORM);
801 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_B8G8R8X8_UNORM);
802 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BC4_UNORM);
803 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BC5_UNORM);
804 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SM41);
805 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MULTISAMPLE_2X);
806 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MULTISAMPLE_4X);
807 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MS_FULL_QUALITY);
808 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_LOGICOPS);
809 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_LOGIC_BLENDOPS);
810 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_RESERVED_1);
811 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BC6H_TYPELESS);
812 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BC6H_UF16);
813 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BC6H_SF16);
814 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BC7_TYPELESS);
815 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BC7_UNORM);
816 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_DXFMT_BC7_UNORM_SRGB);
817 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_RESERVED_2);
818 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_SM5);
819 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MULTISAMPLE_8X);
820
821 SVGA_CASE_ID2STR(SVGA3D_DEVCAP_MAX);
822
823 default:
824 break;
825 }
826 return "UNKNOWN";
827}
828#endif /* defined(LOG_ENABLED) || (defined(IN_RING3) && defined(VBOX_WITH_VMSVGA3D)) */
829#undef SVGA_CASE_ID2STR
830
831
832#ifdef IN_RING3
833
834/**
835 * @interface_method_impl{PDMIDISPLAYPORT,pfnSetViewport}
836 */
837DECLCALLBACK(void) vmsvgaR3PortSetViewport(PPDMIDISPLAYPORT pInterface, uint32_t idScreen, uint32_t x, uint32_t y, uint32_t cx, uint32_t cy)
838{
839 PVGASTATECC pThisCC = RT_FROM_MEMBER(pInterface, VGASTATECC, IPort);
840 PVGASTATE pThis = PDMDEVINS_2_DATA(pThisCC->pDevIns, PVGASTATE);
841
842 Log(("vmsvgaPortSetViewPort: screen %d (%d,%d)(%d,%d)\n", idScreen, x, y, cx, cy));
843 VMSVGAVIEWPORT const OldViewport = pThis->svga.viewport;
844
845 /** @todo Test how it interacts with multiple screen objects. */
846 VMSVGASCREENOBJECT *pScreen = vmsvgaR3GetScreenObject(pThisCC, idScreen);
847 uint32_t const uWidth = pScreen ? pScreen->cWidth : 0;
848 uint32_t const uHeight = pScreen ? pScreen->cHeight : 0;
849
850 if (x < uWidth)
851 {
852 pThis->svga.viewport.x = x;
853 pThis->svga.viewport.cx = RT_MIN(cx, uWidth - x);
854 pThis->svga.viewport.xRight = x + pThis->svga.viewport.cx;
855 }
856 else
857 {
858 pThis->svga.viewport.x = uWidth;
859 pThis->svga.viewport.cx = 0;
860 pThis->svga.viewport.xRight = uWidth;
861 }
862 if (y < uHeight)
863 {
864 pThis->svga.viewport.y = y;
865 pThis->svga.viewport.cy = RT_MIN(cy, uHeight - y);
866 pThis->svga.viewport.yLowWC = uHeight - y - pThis->svga.viewport.cy;
867 pThis->svga.viewport.yHighWC = uHeight - y;
868 }
869 else
870 {
871 pThis->svga.viewport.y = uHeight;
872 pThis->svga.viewport.cy = 0;
873 pThis->svga.viewport.yLowWC = 0;
874 pThis->svga.viewport.yHighWC = 0;
875 }
876
877# ifdef VBOX_WITH_VMSVGA3D
878 /*
879 * Now inform the 3D backend.
880 */
881 if (pThis->svga.f3DEnabled)
882 vmsvga3dUpdateHostScreenViewport(pThisCC, idScreen, &OldViewport);
883# else
884 RT_NOREF(OldViewport);
885# endif
886}
887
888
889/**
890 * Updating screen information in API
891 *
892 * @param pThis The The shared VGA/VMSVGA instance data.
893 * @param pThisCC The VGA/VMSVGA state for ring-3.
894 */
895void vmsvgaR3VBVAResize(PVGASTATE pThis, PVGASTATECC pThisCC)
896{
897 int rc;
898
899 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
900
901 for (unsigned iScreen = 0; iScreen < RT_ELEMENTS(pSVGAState->aScreens); ++iScreen)
902 {
903 VMSVGASCREENOBJECT *pScreen = &pSVGAState->aScreens[iScreen];
904 if (!pScreen->fModified)
905 continue;
906
907 pScreen->fModified = false;
908
909 VBVAINFOVIEW view;
910 RT_ZERO(view);
911 view.u32ViewIndex = pScreen->idScreen;
912 // view.u32ViewOffset = 0;
913 view.u32ViewSize = pThis->vram_size;
914 view.u32MaxScreenSize = pThis->vram_size;
915
916 VBVAINFOSCREEN screen;
917 RT_ZERO(screen);
918 screen.u32ViewIndex = pScreen->idScreen;
919
920 if (pScreen->fDefined)
921 {
922 if ( pScreen->cWidth == VMSVGA_VAL_UNINITIALIZED
923 || pScreen->cHeight == VMSVGA_VAL_UNINITIALIZED
924 || pScreen->cBpp == VMSVGA_VAL_UNINITIALIZED)
925 {
926 Assert(pThis->svga.fGFBRegisters);
927 continue;
928 }
929
930 screen.i32OriginX = pScreen->xOrigin;
931 screen.i32OriginY = pScreen->yOrigin;
932 screen.u32StartOffset = pScreen->offVRAM;
933 screen.u32LineSize = pScreen->cbPitch;
934 screen.u32Width = pScreen->cWidth;
935 screen.u32Height = pScreen->cHeight;
936 screen.u16BitsPerPixel = pScreen->cBpp;
937 if (!(pScreen->fuScreen & SVGA_SCREEN_DEACTIVATE))
938 screen.u16Flags = VBVA_SCREEN_F_ACTIVE;
939 if (pScreen->fuScreen & SVGA_SCREEN_BLANKING)
940 screen.u16Flags |= VBVA_SCREEN_F_BLANK2;
941 }
942 else
943 {
944 /* Screen is destroyed. */
945 screen.u16Flags = VBVA_SCREEN_F_DISABLED;
946 }
947
948 void *pvVRAM = pScreen->pvScreenBitmap ? pScreen->pvScreenBitmap : pThisCC->pbVRam;
949 rc = pThisCC->pDrv->pfnVBVAResize(pThisCC->pDrv, &view, &screen, pvVRAM, /*fResetInputMapping=*/ true);
950 AssertRC(rc);
951 }
952}
953
954
955/**
956 * @interface_method_impl{PDMIDISPLAYPORT,pfnReportMonitorPositions}
957 *
958 * Used to update screen offsets (positions) since appearently vmwgfx fails to
959 * pass correct offsets thru FIFO.
960 */
961DECLCALLBACK(void) vmsvgaR3PortReportMonitorPositions(PPDMIDISPLAYPORT pInterface, uint32_t cPositions, PCRTPOINT paPositions)
962{
963 PVGASTATECC pThisCC = RT_FROM_MEMBER(pInterface, VGASTATECC, IPort);
964 PVGASTATE pThis = PDMDEVINS_2_DATA(pThisCC->pDevIns, PVGASTATE);
965 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
966
967 AssertReturnVoid(pSVGAState);
968
969 /* We assume cPositions is the # of outputs Xserver reports and paPositions is (-1, -1) for disabled monitors. */
970 cPositions = RT_MIN(cPositions, RT_ELEMENTS(pSVGAState->aScreens));
971 for (uint32_t i = 0; i < cPositions; ++i)
972 {
973 if ( pSVGAState->aScreens[i].xOrigin == paPositions[i].x
974 && pSVGAState->aScreens[i].yOrigin == paPositions[i].y)
975 continue;
976
977 if (paPositions[i].x == -1)
978 continue;
979 if (paPositions[i].y == -1)
980 continue;
981
982 pSVGAState->aScreens[i].xOrigin = paPositions[i].x;
983 pSVGAState->aScreens[i].yOrigin = paPositions[i].y;
984 pSVGAState->aScreens[i].fModified = true;
985 }
986
987 vmsvgaR3VBVAResize(pThis, pThisCC);
988}
989
990#endif /* IN_RING3 */
991
992/**
993 * Read port register
994 *
995 * @returns VBox status code.
996 * @param pDevIns The device instance.
997 * @param pThis The shared VGA/VMSVGA state.
998 * @param pu32 Where to store the read value
999 */
1000static int vmsvgaReadPort(PPDMDEVINS pDevIns, PVGASTATE pThis, uint32_t *pu32)
1001{
1002#ifdef IN_RING3
1003 PVGASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
1004#endif
1005 int rc = VINF_SUCCESS;
1006 *pu32 = 0;
1007
1008 /* Rough index register validation. */
1009 uint32_t idxReg = pThis->svga.u32IndexReg;
1010#if !defined(IN_RING3) && defined(VBOX_STRICT)
1011 ASSERT_GUEST_MSG_RETURN(idxReg < SVGA_SCRATCH_BASE + pThis->svga.cScratchRegion, ("idxReg=%#x\n", idxReg),
1012 VINF_IOM_R3_IOPORT_READ);
1013#else
1014 ASSERT_GUEST_MSG_STMT_RETURN(idxReg < SVGA_SCRATCH_BASE + pThis->svga.cScratchRegion, ("idxReg=%#x\n", idxReg),
1015 STAM_REL_COUNTER_INC(&pThis->svga.StatRegUnknownRd),
1016 VINF_SUCCESS);
1017#endif
1018 RT_UNTRUSTED_VALIDATED_FENCE();
1019
1020 /* We must adjust the register number if we're in SVGA_ID_0 mode because the PALETTE range moved. */
1021 if ( idxReg >= SVGA_REG_ID_0_TOP
1022 && pThis->svga.u32SVGAId == SVGA_ID_0)
1023 {
1024 idxReg += SVGA_PALETTE_BASE - SVGA_REG_ID_0_TOP;
1025 Log(("vmsvgaWritePort: SVGA_ID_0 reg adj %#x -> %#x\n", pThis->svga.u32IndexReg, idxReg));
1026 }
1027
1028 switch (idxReg)
1029 {
1030 case SVGA_REG_ID:
1031 STAM_REL_COUNTER_INC(&pThis->svga.StatRegIdRd);
1032 *pu32 = pThis->svga.u32SVGAId;
1033 break;
1034
1035 case SVGA_REG_ENABLE:
1036 STAM_REL_COUNTER_INC(&pThis->svga.StatRegEnableRd);
1037 *pu32 = pThis->svga.fEnabled;
1038 break;
1039
1040 case SVGA_REG_WIDTH:
1041 {
1042 STAM_REL_COUNTER_INC(&pThis->svga.StatRegWidthRd);
1043 if ( pThis->svga.fEnabled
1044 && pThis->svga.uWidth != VMSVGA_VAL_UNINITIALIZED)
1045 *pu32 = pThis->svga.uWidth;
1046 else
1047 {
1048#ifndef IN_RING3
1049 rc = VINF_IOM_R3_IOPORT_READ;
1050#else
1051 *pu32 = pThisCC->pDrv->cx;
1052#endif
1053 }
1054 break;
1055 }
1056
1057 case SVGA_REG_HEIGHT:
1058 {
1059 STAM_REL_COUNTER_INC(&pThis->svga.StatRegHeightRd);
1060 if ( pThis->svga.fEnabled
1061 && pThis->svga.uHeight != VMSVGA_VAL_UNINITIALIZED)
1062 *pu32 = pThis->svga.uHeight;
1063 else
1064 {
1065#ifndef IN_RING3
1066 rc = VINF_IOM_R3_IOPORT_READ;
1067#else
1068 *pu32 = pThisCC->pDrv->cy;
1069#endif
1070 }
1071 break;
1072 }
1073
1074 case SVGA_REG_MAX_WIDTH:
1075 STAM_REL_COUNTER_INC(&pThis->svga.StatRegMaxWidthRd);
1076 *pu32 = pThis->svga.u32MaxWidth;
1077 break;
1078
1079 case SVGA_REG_MAX_HEIGHT:
1080 STAM_REL_COUNTER_INC(&pThis->svga.StatRegMaxHeightRd);
1081 *pu32 = pThis->svga.u32MaxHeight;
1082 break;
1083
1084 case SVGA_REG_DEPTH:
1085 /* This returns the color depth of the current mode. */
1086 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDepthRd);
1087 switch (pThis->svga.uBpp)
1088 {
1089 case 15:
1090 case 16:
1091 case 24:
1092 *pu32 = pThis->svga.uBpp;
1093 break;
1094
1095 default:
1096 case 32:
1097 *pu32 = 24; /* The upper 8 bits are either alpha bits or not used. */
1098 break;
1099 }
1100 break;
1101
1102 case SVGA_REG_HOST_BITS_PER_PIXEL: /* (Deprecated) */
1103 STAM_REL_COUNTER_INC(&pThis->svga.StatRegHostBitsPerPixelRd);
1104 *pu32 = pThis->svga.uHostBpp;
1105 break;
1106
1107 case SVGA_REG_BITS_PER_PIXEL: /* Current bpp in the guest */
1108 STAM_REL_COUNTER_INC(&pThis->svga.StatRegBitsPerPixelRd);
1109 *pu32 = pThis->svga.uBpp;
1110 break;
1111
1112 case SVGA_REG_PSEUDOCOLOR:
1113 STAM_REL_COUNTER_INC(&pThis->svga.StatRegPsuedoColorRd);
1114 *pu32 = pThis->svga.uBpp == 8; /* See section 6 "Pseudocolor" in svga_interface.txt. */
1115 break;
1116
1117 case SVGA_REG_RED_MASK:
1118 case SVGA_REG_GREEN_MASK:
1119 case SVGA_REG_BLUE_MASK:
1120 {
1121 uint32_t uBpp;
1122
1123 if (pThis->svga.fEnabled)
1124 uBpp = pThis->svga.uBpp;
1125 else
1126 uBpp = pThis->svga.uHostBpp;
1127
1128 uint32_t u32RedMask, u32GreenMask, u32BlueMask;
1129 switch (uBpp)
1130 {
1131 case 8:
1132 u32RedMask = 0x07;
1133 u32GreenMask = 0x38;
1134 u32BlueMask = 0xc0;
1135 break;
1136
1137 case 15:
1138 u32RedMask = 0x0000001f;
1139 u32GreenMask = 0x000003e0;
1140 u32BlueMask = 0x00007c00;
1141 break;
1142
1143 case 16:
1144 u32RedMask = 0x0000001f;
1145 u32GreenMask = 0x000007e0;
1146 u32BlueMask = 0x0000f800;
1147 break;
1148
1149 case 24:
1150 case 32:
1151 default:
1152 u32RedMask = 0x00ff0000;
1153 u32GreenMask = 0x0000ff00;
1154 u32BlueMask = 0x000000ff;
1155 break;
1156 }
1157 switch (idxReg)
1158 {
1159 case SVGA_REG_RED_MASK:
1160 STAM_REL_COUNTER_INC(&pThis->svga.StatRegRedMaskRd);
1161 *pu32 = u32RedMask;
1162 break;
1163
1164 case SVGA_REG_GREEN_MASK:
1165 STAM_REL_COUNTER_INC(&pThis->svga.StatRegGreenMaskRd);
1166 *pu32 = u32GreenMask;
1167 break;
1168
1169 case SVGA_REG_BLUE_MASK:
1170 STAM_REL_COUNTER_INC(&pThis->svga.StatRegBlueMaskRd);
1171 *pu32 = u32BlueMask;
1172 break;
1173 }
1174 break;
1175 }
1176
1177 case SVGA_REG_BYTES_PER_LINE:
1178 {
1179 STAM_REL_COUNTER_INC(&pThis->svga.StatRegBytesPerLineRd);
1180 if ( pThis->svga.fEnabled
1181 && pThis->svga.cbScanline)
1182 *pu32 = pThis->svga.cbScanline;
1183 else
1184 {
1185#ifndef IN_RING3
1186 rc = VINF_IOM_R3_IOPORT_READ;
1187#else
1188 *pu32 = pThisCC->pDrv->cbScanline;
1189#endif
1190 }
1191 break;
1192 }
1193
1194 case SVGA_REG_VRAM_SIZE: /* VRAM size */
1195 STAM_REL_COUNTER_INC(&pThis->svga.StatRegVramSizeRd);
1196 *pu32 = pThis->vram_size;
1197 break;
1198
1199 case SVGA_REG_FB_START: /* Frame buffer physical address. */
1200 STAM_REL_COUNTER_INC(&pThis->svga.StatRegFbStartRd);
1201 Assert(pThis->GCPhysVRAM <= 0xffffffff);
1202 *pu32 = pThis->GCPhysVRAM;
1203 break;
1204
1205 case SVGA_REG_FB_OFFSET: /* Offset of the frame buffer in VRAM */
1206 STAM_REL_COUNTER_INC(&pThis->svga.StatRegFbOffsetRd);
1207 /* Always zero in our case. */
1208 *pu32 = 0;
1209 break;
1210
1211 case SVGA_REG_FB_SIZE: /* Frame buffer size */
1212 {
1213#ifndef IN_RING3
1214 rc = VINF_IOM_R3_IOPORT_READ;
1215#else
1216 STAM_REL_COUNTER_INC(&pThis->svga.StatRegFbSizeRd);
1217
1218 /* VMWare testcases want at least 4 MB in case the hardware is disabled. */
1219 if ( pThis->svga.fEnabled
1220 && pThis->svga.uHeight != VMSVGA_VAL_UNINITIALIZED)
1221 {
1222 /* Hardware enabled; return real framebuffer size .*/
1223 *pu32 = (uint32_t)pThis->svga.uHeight * pThis->svga.cbScanline;
1224 }
1225 else
1226 *pu32 = RT_MAX(0x100000, (uint32_t)pThisCC->pDrv->cy * pThisCC->pDrv->cbScanline);
1227
1228 *pu32 = RT_MIN(pThis->vram_size, *pu32);
1229 Log(("h=%d w=%d bpp=%d\n", pThisCC->pDrv->cy, pThisCC->pDrv->cx, pThisCC->pDrv->cBits));
1230#endif
1231 break;
1232 }
1233
1234 case SVGA_REG_CAPABILITIES:
1235 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCapabilitesRd);
1236 *pu32 = pThis->svga.u32DeviceCaps;
1237 break;
1238
1239 case SVGA_REG_MEM_START: /* FIFO start */
1240 STAM_REL_COUNTER_INC(&pThis->svga.StatRegMemStartRd);
1241 Assert(pThis->svga.GCPhysFIFO <= 0xffffffff);
1242 *pu32 = pThis->svga.GCPhysFIFO;
1243 break;
1244
1245 case SVGA_REG_MEM_SIZE: /* FIFO size */
1246 STAM_REL_COUNTER_INC(&pThis->svga.StatRegMemSizeRd);
1247 *pu32 = pThis->svga.cbFIFO;
1248 break;
1249
1250 case SVGA_REG_CONFIG_DONE: /* Set when memory area configured */
1251 STAM_REL_COUNTER_INC(&pThis->svga.StatRegConfigDoneRd);
1252 *pu32 = pThis->svga.fConfigured;
1253 break;
1254
1255 case SVGA_REG_SYNC: /* See "FIFO Synchronization Registers" */
1256 STAM_REL_COUNTER_INC(&pThis->svga.StatRegSyncRd);
1257 *pu32 = 0;
1258 break;
1259
1260 case SVGA_REG_BUSY: /* See "FIFO Synchronization Registers" */
1261 STAM_REL_COUNTER_INC(&pThis->svga.StatRegBusyRd);
1262 if (pThis->svga.fBusy)
1263 {
1264#ifndef IN_RING3
1265 /* Go to ring-3 and halt the CPU. */
1266 rc = VINF_IOM_R3_IOPORT_READ;
1267 RT_NOREF(pDevIns);
1268 break;
1269#else /* IN_RING3 */
1270# if defined(VMSVGA_USE_EMT_HALT_CODE)
1271 /* The guest is basically doing a HLT via the device here, but with
1272 a special wake up condition on FIFO completion. */
1273 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
1274 STAM_REL_PROFILE_START(&pSVGAState->StatBusyDelayEmts, EmtDelay);
1275 VMCPUID idCpu = PDMDevHlpGetCurrentCpuId(pDevIns);
1276 VMCPUSET_ATOMIC_ADD(&pSVGAState->BusyDelayedEmts, idCpu);
1277 ASMAtomicIncU32(&pSVGAState->cBusyDelayedEmts);
1278 if (pThis->svga.fBusy)
1279 {
1280 PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect); /* hack around lock order issue. */
1281 rc = PDMDevHlpVMWaitForDeviceReady(pDevIns, idCpu);
1282 int const rcLock = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VERR_IGNORED);
1283 PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, &pThis->CritSect, rcLock);
1284 }
1285 ASMAtomicDecU32(&pSVGAState->cBusyDelayedEmts);
1286 VMCPUSET_ATOMIC_DEL(&pSVGAState->BusyDelayedEmts, idCpu);
1287# else
1288
1289 /* Delay the EMT a bit so the FIFO and others can get some work done.
1290 This used to be a crude 50 ms sleep. The current code tries to be
1291 more efficient, but the consept is still very crude. */
1292 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
1293 STAM_REL_PROFILE_START(&pSVGAState->StatBusyDelayEmts, EmtDelay);
1294 RTThreadYield();
1295 if (pThis->svga.fBusy)
1296 {
1297 uint32_t cRefs = ASMAtomicIncU32(&pSVGAState->cBusyDelayedEmts);
1298
1299 if (pThis->svga.fBusy && cRefs == 1)
1300 RTSemEventMultiReset(pSVGAState->hBusyDelayedEmts);
1301 if (pThis->svga.fBusy)
1302 {
1303 /** @todo If this code is going to stay, we need to call into the halt/wait
1304 * code in VMEmt.cpp here, otherwise all kind of EMT interaction will
1305 * suffer when the guest is polling on a busy FIFO. */
1306 uint64_t uIgnored1, uIgnored2;
1307 uint64_t cNsMaxWait = TMVirtualSyncGetNsToDeadline(PDMDevHlpGetVM(pDevIns), &uIgnored1, &uIgnored2);
1308 if (cNsMaxWait >= RT_NS_100US)
1309 RTSemEventMultiWaitEx(pSVGAState->hBusyDelayedEmts,
1310 RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_NORESUME,
1311 RT_MIN(cNsMaxWait, RT_NS_10MS));
1312 }
1313
1314 ASMAtomicDecU32(&pSVGAState->cBusyDelayedEmts);
1315 }
1316 STAM_REL_PROFILE_STOP(&pSVGAState->StatBusyDelayEmts, EmtDelay);
1317# endif
1318 *pu32 = pThis->svga.fBusy != 0;
1319#endif /* IN_RING3 */
1320 }
1321 else
1322 *pu32 = false;
1323 break;
1324
1325 case SVGA_REG_GUEST_ID: /* Set guest OS identifier */
1326 STAM_REL_COUNTER_INC(&pThis->svga.StatRegGuestIdRd);
1327 *pu32 = pThis->svga.u32GuestId;
1328 break;
1329
1330 case SVGA_REG_SCRATCH_SIZE: /* Number of scratch registers */
1331 STAM_REL_COUNTER_INC(&pThis->svga.StatRegScratchSizeRd);
1332 *pu32 = pThis->svga.cScratchRegion;
1333 break;
1334
1335 case SVGA_REG_MEM_REGS: /* Number of FIFO registers */
1336 STAM_REL_COUNTER_INC(&pThis->svga.StatRegMemRegsRd);
1337 *pu32 = SVGA_FIFO_NUM_REGS;
1338 break;
1339
1340 case SVGA_REG_PITCHLOCK: /* Fixed pitch for all modes */
1341 STAM_REL_COUNTER_INC(&pThis->svga.StatRegPitchLockRd);
1342 *pu32 = pThis->svga.u32PitchLock;
1343 break;
1344
1345 case SVGA_REG_IRQMASK: /* Interrupt mask */
1346 STAM_REL_COUNTER_INC(&pThis->svga.StatRegIrqMaskRd);
1347 *pu32 = pThis->svga.u32IrqMask;
1348 break;
1349
1350 /* See "Guest memory regions" below. */
1351 case SVGA_REG_GMR_ID:
1352 STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrIdRd);
1353 *pu32 = pThis->svga.u32CurrentGMRId;
1354 break;
1355
1356 case SVGA_REG_GMR_DESCRIPTOR:
1357 STAM_REL_COUNTER_INC(&pThis->svga.StatRegWriteOnlyRd);
1358 /* Write only */
1359 *pu32 = 0;
1360 break;
1361
1362 case SVGA_REG_GMR_MAX_IDS:
1363 STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrMaxIdsRd);
1364 *pu32 = pThis->svga.cGMR;
1365 break;
1366
1367 case SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH:
1368 STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrMaxDescriptorLengthRd);
1369 *pu32 = VMSVGA_MAX_GMR_PAGES;
1370 break;
1371
1372 case SVGA_REG_TRACES: /* Enable trace-based updates even when FIFO is on */
1373 STAM_REL_COUNTER_INC(&pThis->svga.StatRegTracesRd);
1374 *pu32 = pThis->svga.fTraces;
1375 break;
1376
1377 case SVGA_REG_GMRS_MAX_PAGES: /* Maximum number of 4KB pages for all GMRs */
1378 STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrsMaxPagesRd);
1379 *pu32 = VMSVGA_MAX_GMR_PAGES;
1380 break;
1381
1382 case SVGA_REG_MEMORY_SIZE: /* Total dedicated device memory excluding FIFO */
1383 STAM_REL_COUNTER_INC(&pThis->svga.StatRegMemorySizeRd);
1384 *pu32 = VMSVGA_SURFACE_SIZE;
1385 break;
1386
1387 case SVGA_REG_TOP: /* Must be 1 more than the last register */
1388 STAM_REL_COUNTER_INC(&pThis->svga.StatRegTopRd);
1389 break;
1390
1391 /* Mouse cursor support. */
1392 case SVGA_REG_DEAD: /* SVGA_REG_CURSOR_ID */
1393 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorIdRd);
1394 *pu32 = pThis->svga.uCursorID;
1395 break;
1396
1397 case SVGA_REG_CURSOR_X:
1398 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorXRd);
1399 *pu32 = pThis->svga.uCursorX;
1400 break;
1401
1402 case SVGA_REG_CURSOR_Y:
1403 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorYRd);
1404 *pu32 = pThis->svga.uCursorY;
1405 break;
1406
1407 case SVGA_REG_CURSOR_ON:
1408 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorOnRd);
1409 *pu32 = pThis->svga.uCursorOn;
1410 break;
1411
1412 /* Legacy multi-monitor support */
1413 case SVGA_REG_NUM_GUEST_DISPLAYS:/* Number of guest displays in X/Y direction */
1414 STAM_REL_COUNTER_INC(&pThis->svga.StatRegNumGuestDisplaysRd);
1415 *pu32 = 1;
1416 break;
1417
1418 case SVGA_REG_DISPLAY_ID: /* Display ID for the following display attributes */
1419 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayIdRd);
1420 *pu32 = 0;
1421 break;
1422
1423 case SVGA_REG_DISPLAY_IS_PRIMARY:/* Whether this is a primary display */
1424 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayIsPrimaryRd);
1425 *pu32 = 0;
1426 break;
1427
1428 case SVGA_REG_DISPLAY_POSITION_X:/* The display position x */
1429 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayPositionXRd);
1430 *pu32 = 0;
1431 break;
1432
1433 case SVGA_REG_DISPLAY_POSITION_Y:/* The display position y */
1434 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayPositionYRd);
1435 *pu32 = 0;
1436 break;
1437
1438 case SVGA_REG_DISPLAY_WIDTH: /* The display's width */
1439 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayWidthRd);
1440 *pu32 = pThis->svga.uWidth;
1441 break;
1442
1443 case SVGA_REG_DISPLAY_HEIGHT: /* The display's height */
1444 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayHeightRd);
1445 *pu32 = pThis->svga.uHeight;
1446 break;
1447
1448 case SVGA_REG_NUM_DISPLAYS: /* (Deprecated) */
1449 STAM_REL_COUNTER_INC(&pThis->svga.StatRegNumDisplaysRd);
1450 /* We must return something sensible here otherwise the Linux driver
1451 will take a legacy code path without 3d support. This number also
1452 limits how many screens Linux guests will allow. */
1453 *pu32 = pThis->cMonitors;
1454 break;
1455
1456 /*
1457 * SVGA_CAP_GBOBJECTS+ registers.
1458 */
1459 case SVGA_REG_COMMAND_LOW:
1460 /* Lower 32 bits of command buffer physical address. */
1461 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCommandLowRd);
1462 *pu32 = pThis->svga.u32RegCommandLow;
1463 break;
1464
1465 case SVGA_REG_COMMAND_HIGH:
1466 /* Upper 32 bits of command buffer PA. */
1467 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCommandHighRd);
1468 *pu32 = pThis->svga.u32RegCommandHigh;
1469 break;
1470
1471 case SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM:
1472 /* Max primary (screen) memory. */
1473 STAM_REL_COUNTER_INC(&pThis->svga.StatRegMaxPrimBBMemRd);
1474 *pu32 = pThis->vram_size; /** @todo Maybe half VRAM? */
1475 break;
1476
1477 case SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB:
1478 /* Suggested limit on mob mem (i.e. size of the guest mapped VRAM in KB) */
1479 STAM_REL_COUNTER_INC(&pThis->svga.StatRegGBMemSizeRd);
1480 *pu32 = pThis->vram_size / 1024;
1481 break;
1482
1483 case SVGA_REG_DEV_CAP:
1484 /* Write dev cap index, read value */
1485 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDevCapRd);
1486 if (pThis->svga.u32DevCapIndex < RT_ELEMENTS(pThis->svga.au32DevCaps))
1487 {
1488 RT_UNTRUSTED_VALIDATED_FENCE();
1489 *pu32 = pThis->svga.au32DevCaps[pThis->svga.u32DevCapIndex];
1490 }
1491 else
1492 *pu32 = 0;
1493 break;
1494
1495 case SVGA_REG_CMD_PREPEND_LOW:
1496 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCmdPrependLowRd);
1497 *pu32 = 0; /* Not supported. */
1498 break;
1499
1500 case SVGA_REG_CMD_PREPEND_HIGH:
1501 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCmdPrependHighRd);
1502 *pu32 = 0; /* Not supported. */
1503 break;
1504
1505 case SVGA_REG_SCREENTARGET_MAX_WIDTH:
1506 STAM_REL_COUNTER_INC(&pThis->svga.StatRegScrnTgtMaxWidthRd);
1507 *pu32 = pThis->svga.u32MaxWidth;
1508 break;
1509
1510 case SVGA_REG_SCREENTARGET_MAX_HEIGHT:
1511 STAM_REL_COUNTER_INC(&pThis->svga.StatRegScrnTgtMaxHeightRd);
1512 *pu32 = pThis->svga.u32MaxHeight;
1513 break;
1514
1515 case SVGA_REG_MOB_MAX_SIZE:
1516 /* Essentially the max texture size */
1517 STAM_REL_COUNTER_INC(&pThis->svga.StatRegMobMaxSizeRd);
1518 *pu32 = _128M; /** @todo Some actual value. Probably the mapped VRAM size. */
1519 break;
1520
1521 default:
1522 {
1523 uint32_t offReg;
1524 if ((offReg = idxReg - SVGA_SCRATCH_BASE) < pThis->svga.cScratchRegion)
1525 {
1526 STAM_REL_COUNTER_INC(&pThis->svga.StatRegScratchRd);
1527 RT_UNTRUSTED_VALIDATED_FENCE();
1528 *pu32 = pThis->svga.au32ScratchRegion[offReg];
1529 }
1530 else if ((offReg = idxReg - SVGA_PALETTE_BASE) < (uint32_t)SVGA_NUM_PALETTE_REGS)
1531 {
1532 /* Note! Using last_palette rather than palette here to preserve the VGA one. */
1533 STAM_REL_COUNTER_INC(&pThis->svga.StatRegPaletteRd);
1534 RT_UNTRUSTED_VALIDATED_FENCE();
1535 uint32_t u32 = pThis->last_palette[offReg / 3];
1536 switch (offReg % 3)
1537 {
1538 case 0: *pu32 = (u32 >> 16) & 0xff; break; /* red */
1539 case 1: *pu32 = (u32 >> 8) & 0xff; break; /* green */
1540 case 2: *pu32 = u32 & 0xff; break; /* blue */
1541 }
1542 }
1543 else
1544 {
1545#if !defined(IN_RING3) && defined(VBOX_STRICT)
1546 rc = VINF_IOM_R3_IOPORT_READ;
1547#else
1548 STAM_REL_COUNTER_INC(&pThis->svga.StatRegUnknownRd);
1549
1550 /* Do not assert. The guest might be reading all registers. */
1551 LogFunc(("Unknown reg=%#x\n", idxReg));
1552#endif
1553 }
1554 break;
1555 }
1556 }
1557 LogFlow(("vmsvgaReadPort index=%s (%d) val=%#x rc=%x\n", vmsvgaIndexToString(pThis, idxReg), idxReg, *pu32, rc));
1558 return rc;
1559}
1560
1561#ifdef IN_RING3
1562/**
1563 * Apply the current resolution settings to change the video mode.
1564 *
1565 * @returns VBox status code.
1566 * @param pThis The shared VGA state.
1567 * @param pThisCC The ring-3 VGA state.
1568 */
1569int vmsvgaR3ChangeMode(PVGASTATE pThis, PVGASTATECC pThisCC)
1570{
1571 /* Always do changemode on FIFO thread. */
1572 Assert(RTThreadSelf() == pThisCC->svga.pFIFOIOThread->Thread);
1573
1574 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
1575
1576 pThisCC->pDrv->pfnLFBModeChange(pThisCC->pDrv, true);
1577
1578 if (pThis->svga.fGFBRegisters)
1579 {
1580 /* "For backwards compatibility, when the GFB mode registers (WIDTH,
1581 * HEIGHT, PITCHLOCK, BITS_PER_PIXEL) are modified, the SVGA device
1582 * deletes all screens other than screen #0, and redefines screen
1583 * #0 according to the specified mode. Drivers that use
1584 * SVGA_CMD_DEFINE_SCREEN should destroy or redefine screen #0."
1585 */
1586
1587 VMSVGASCREENOBJECT *pScreen = &pSVGAState->aScreens[0];
1588 pScreen->fDefined = true;
1589 pScreen->fModified = true;
1590 pScreen->fuScreen = SVGA_SCREEN_MUST_BE_SET | SVGA_SCREEN_IS_PRIMARY;
1591 pScreen->idScreen = 0;
1592 pScreen->xOrigin = 0;
1593 pScreen->yOrigin = 0;
1594 pScreen->offVRAM = 0;
1595 pScreen->cbPitch = pThis->svga.cbScanline;
1596 pScreen->cWidth = pThis->svga.uWidth;
1597 pScreen->cHeight = pThis->svga.uHeight;
1598 pScreen->cBpp = pThis->svga.uBpp;
1599
1600 for (unsigned iScreen = 1; iScreen < RT_ELEMENTS(pSVGAState->aScreens); ++iScreen)
1601 {
1602 /* Delete screen. */
1603 pScreen = &pSVGAState->aScreens[iScreen];
1604 if (pScreen->fDefined)
1605 {
1606 pScreen->fModified = true;
1607 pScreen->fDefined = false;
1608 }
1609 }
1610 }
1611 else
1612 {
1613 /* "If Screen Objects are supported, they can be used to fully
1614 * replace the functionality provided by the framebuffer registers
1615 * (SVGA_REG_WIDTH, HEIGHT, etc.) and by SVGA_CAP_DISPLAY_TOPOLOGY."
1616 */
1617 pThis->svga.uWidth = VMSVGA_VAL_UNINITIALIZED;
1618 pThis->svga.uHeight = VMSVGA_VAL_UNINITIALIZED;
1619 pThis->svga.uBpp = pThis->svga.uHostBpp;
1620 }
1621
1622 vmsvgaR3VBVAResize(pThis, pThisCC);
1623
1624 /* Last stuff. For the VGA device screenshot. */
1625 pThis->last_bpp = pSVGAState->aScreens[0].cBpp;
1626 pThis->last_scr_width = pSVGAState->aScreens[0].cWidth;
1627 pThis->last_scr_height = pSVGAState->aScreens[0].cHeight;
1628 pThis->last_width = pSVGAState->aScreens[0].cWidth;
1629 pThis->last_height = pSVGAState->aScreens[0].cHeight;
1630
1631 /* vmsvgaPortSetViewPort not called after state load; set sensible defaults. */
1632 if ( pThis->svga.viewport.cx == 0
1633 && pThis->svga.viewport.cy == 0)
1634 {
1635 pThis->svga.viewport.cx = pSVGAState->aScreens[0].cWidth;
1636 pThis->svga.viewport.xRight = pSVGAState->aScreens[0].cWidth;
1637 pThis->svga.viewport.cy = pSVGAState->aScreens[0].cHeight;
1638 pThis->svga.viewport.yHighWC = pSVGAState->aScreens[0].cHeight;
1639 pThis->svga.viewport.yLowWC = 0;
1640 }
1641
1642 return VINF_SUCCESS;
1643}
1644
1645int vmsvgaR3UpdateScreen(PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen, int x, int y, int w, int h)
1646{
1647 VBVACMDHDR cmd;
1648
1649 ASSERT_GUEST_LOGREL_MSG_RETURN(w > 0 && h > 0,
1650 ("vmsvgaR3UpdateScreen: screen %d (%d,%d) %dx%d: Invalid height and/or width supplied.\n",
1651 pScreen->idScreen, x, y, w, h),
1652 VERR_INVALID_PARAMETER);
1653
1654 cmd.x = (int16_t)(pScreen->xOrigin + x);
1655 cmd.y = (int16_t)(pScreen->yOrigin + y);
1656 cmd.w = (uint16_t)w;
1657 cmd.h = (uint16_t)h;
1658
1659 pThisCC->pDrv->pfnVBVAUpdateBegin(pThisCC->pDrv, pScreen->idScreen);
1660 pThisCC->pDrv->pfnVBVAUpdateProcess(pThisCC->pDrv, pScreen->idScreen, &cmd, sizeof(cmd));
1661 pThisCC->pDrv->pfnVBVAUpdateEnd(pThisCC->pDrv, pScreen->idScreen,
1662 pScreen->xOrigin + x, pScreen->yOrigin + y, w, h);
1663
1664 return VINF_SUCCESS;
1665}
1666
1667#endif /* IN_RING3 */
1668#if defined(IN_RING0) || defined(IN_RING3)
1669
1670/**
1671 * Safely updates the SVGA_FIFO_BUSY register (in shared memory).
1672 *
1673 * @param pThis The shared VGA/VMSVGA instance data.
1674 * @param pThisCC The VGA/VMSVGA state for the current context.
1675 * @param fState The busy state.
1676 */
1677DECLINLINE(void) vmsvgaHCSafeFifoBusyRegUpdate(PVGASTATE pThis, PVGASTATECC pThisCC, bool fState)
1678{
1679 ASMAtomicWriteU32(&pThisCC->svga.pau32FIFO[SVGA_FIFO_BUSY], fState);
1680
1681 if (RT_UNLIKELY(fState != (pThis->svga.fBusy != 0)))
1682 {
1683 /* Race / unfortunately scheduling. Highly unlikly. */
1684 uint32_t cLoops = 64;
1685 do
1686 {
1687 ASMNopPause();
1688 fState = (pThis->svga.fBusy != 0);
1689 ASMAtomicWriteU32(&pThisCC->svga.pau32FIFO[SVGA_FIFO_BUSY], fState != 0);
1690 } while (cLoops-- > 0 && fState != (pThis->svga.fBusy != 0));
1691 }
1692}
1693
1694
1695/**
1696 * Update the scanline pitch in response to the guest changing mode
1697 * width/bpp.
1698 *
1699 * @param pThis The shared VGA/VMSVGA state.
1700 * @param pThisCC The VGA/VMSVGA state for the current context.
1701 */
1702DECLINLINE(void) vmsvgaHCUpdatePitch(PVGASTATE pThis, PVGASTATECC pThisCC)
1703{
1704 uint32_t RT_UNTRUSTED_VOLATILE_GUEST *pFIFO = pThisCC->svga.pau32FIFO;
1705 uint32_t uFifoPitchLock = pFIFO[SVGA_FIFO_PITCHLOCK];
1706 uint32_t uRegPitchLock = pThis->svga.u32PitchLock;
1707 uint32_t uFifoMin = pFIFO[SVGA_FIFO_MIN];
1708
1709 /* The SVGA_FIFO_PITCHLOCK register is only valid if SVGA_FIFO_MIN points past
1710 * it. If SVGA_FIFO_MIN is small, there may well be data at the SVGA_FIFO_PITCHLOCK
1711 * location but it has a different meaning.
1712 */
1713 if ((uFifoMin / sizeof(uint32_t)) <= SVGA_FIFO_PITCHLOCK)
1714 uFifoPitchLock = 0;
1715
1716 /* Sanitize values. */
1717 if ((uFifoPitchLock < 200) || (uFifoPitchLock > 32768))
1718 uFifoPitchLock = 0;
1719 if ((uRegPitchLock < 200) || (uRegPitchLock > 32768))
1720 uRegPitchLock = 0;
1721
1722 /* Prefer the register value to the FIFO value.*/
1723 if (uRegPitchLock)
1724 pThis->svga.cbScanline = uRegPitchLock;
1725 else if (uFifoPitchLock)
1726 pThis->svga.cbScanline = uFifoPitchLock;
1727 else
1728 pThis->svga.cbScanline = (uint32_t)pThis->svga.uWidth * (RT_ALIGN(pThis->svga.uBpp, 8) / 8);
1729
1730 if ((uFifoMin / sizeof(uint32_t)) <= SVGA_FIFO_PITCHLOCK)
1731 pThis->svga.u32PitchLock = pThis->svga.cbScanline;
1732}
1733
1734#endif /* IN_RING0 || IN_RING3 */
1735
1736#ifdef IN_RING3
1737
1738/**
1739 * Sends cursor position and visibility information from legacy
1740 * SVGA registers to the front-end.
1741 */
1742static void vmsvgaR3RegUpdateCursor(PVGASTATECC pThisCC, PVGASTATE pThis, uint32_t uCursorOn)
1743{
1744 /*
1745 * Writing the X/Y/ID registers does not trigger changes; only writing the
1746 * SVGA_REG_CURSOR_ON register does. That minimizes the overhead.
1747 * We boldly assume that guests aren't stupid and aren't writing the CURSOR_ON
1748 * register if they don't have to.
1749 */
1750 uint32_t x, y, idScreen;
1751 uint32_t fFlags = VBVA_CURSOR_VALID_DATA;
1752
1753 x = pThis->svga.uCursorX;
1754 y = pThis->svga.uCursorY;
1755 idScreen = SVGA_ID_INVALID; /* The old register interface is single screen only. */
1756
1757 /* The original values for SVGA_REG_CURSOR_ON were off (0) and on (1); later, the values
1758 * were extended as follows:
1759 *
1760 * SVGA_CURSOR_ON_HIDE 0
1761 * SVGA_CURSOR_ON_SHOW 1
1762 * SVGA_CURSOR_ON_REMOVE_FROM_FB 2 - cursor on but not in the framebuffer
1763 * SVGA_CURSOR_ON_RESTORE_TO_FB 3 - cursor on, possibly in the framebuffer
1764 *
1765 * Since we never draw the cursor into the guest's framebuffer, we do not need to
1766 * distinguish between the non-zero values but still remember them.
1767 */
1768 if (RT_BOOL(pThis->svga.uCursorOn) != RT_BOOL(uCursorOn))
1769 {
1770 LogRel2(("vmsvgaR3RegUpdateCursor: uCursorOn %d prev CursorOn %d (%d,%d)\n", uCursorOn, pThis->svga.uCursorOn, x, y));
1771 pThisCC->pDrv->pfnVBVAMousePointerShape(pThisCC->pDrv, RT_BOOL(uCursorOn), false, 0, 0, 0, 0, NULL);
1772 }
1773 pThis->svga.uCursorOn = uCursorOn;
1774 pThisCC->pDrv->pfnVBVAReportCursorPosition(pThisCC->pDrv, fFlags, idScreen, x, y);
1775}
1776
1777#endif /* IN_RING3 */
1778
1779
1780/**
1781 * Write port register
1782 *
1783 * @returns Strict VBox status code.
1784 * @param pDevIns The device instance.
1785 * @param pThis The shared VGA/VMSVGA state.
1786 * @param pThisCC The VGA/VMSVGA state for the current context.
1787 * @param u32 Value to write
1788 */
1789static VBOXSTRICTRC vmsvgaWritePort(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, uint32_t u32)
1790{
1791#ifdef IN_RING3
1792 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
1793#endif
1794 VBOXSTRICTRC rc = VINF_SUCCESS;
1795 RT_NOREF(pThisCC);
1796
1797 /* Rough index register validation. */
1798 uint32_t idxReg = pThis->svga.u32IndexReg;
1799#if !defined(IN_RING3) && defined(VBOX_STRICT)
1800 ASSERT_GUEST_MSG_RETURN(idxReg < SVGA_SCRATCH_BASE + pThis->svga.cScratchRegion, ("idxReg=%#x\n", idxReg),
1801 VINF_IOM_R3_IOPORT_WRITE);
1802#else
1803 ASSERT_GUEST_MSG_STMT_RETURN(idxReg < SVGA_SCRATCH_BASE + pThis->svga.cScratchRegion, ("idxReg=%#x\n", idxReg),
1804 STAM_REL_COUNTER_INC(&pThis->svga.StatRegUnknownWr),
1805 VINF_SUCCESS);
1806#endif
1807 RT_UNTRUSTED_VALIDATED_FENCE();
1808
1809 /* We must adjust the register number if we're in SVGA_ID_0 mode because the PALETTE range moved. */
1810 if ( idxReg >= SVGA_REG_ID_0_TOP
1811 && pThis->svga.u32SVGAId == SVGA_ID_0)
1812 {
1813 idxReg += SVGA_PALETTE_BASE - SVGA_REG_ID_0_TOP;
1814 Log(("vmsvgaWritePort: SVGA_ID_0 reg adj %#x -> %#x\n", pThis->svga.u32IndexReg, idxReg));
1815 }
1816#ifdef LOG_ENABLED
1817 if (idxReg != SVGA_REG_DEV_CAP)
1818 LogFlow(("vmsvgaWritePort index=%s (%d) val=%#x\n", vmsvgaIndexToString(pThis, idxReg), idxReg, u32));
1819 else
1820 LogFlow(("vmsvgaWritePort index=%s (%d) val=%s (%d)\n", vmsvgaIndexToString(pThis, idxReg), idxReg, vmsvgaDevCapIndexToString((SVGA3dDevCapIndex)u32), u32));
1821#endif
1822 /* Check if the guest uses legacy registers. See vmsvgaR3ChangeMode */
1823 switch (idxReg)
1824 {
1825 case SVGA_REG_WIDTH:
1826 case SVGA_REG_HEIGHT:
1827 case SVGA_REG_PITCHLOCK:
1828 case SVGA_REG_BITS_PER_PIXEL:
1829 pThis->svga.fGFBRegisters = true;
1830 break;
1831 default:
1832 break;
1833 }
1834
1835 switch (idxReg)
1836 {
1837 case SVGA_REG_ID:
1838 STAM_REL_COUNTER_INC(&pThis->svga.StatRegIdWr);
1839 if ( u32 == SVGA_ID_0
1840 || u32 == SVGA_ID_1
1841 || u32 == SVGA_ID_2)
1842 pThis->svga.u32SVGAId = u32;
1843 else
1844 PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "Trying to set SVGA_REG_ID to %#x (%d)\n", u32, u32);
1845 break;
1846
1847 case SVGA_REG_ENABLE:
1848 STAM_REL_COUNTER_INC(&pThis->svga.StatRegEnableWr);
1849#ifdef IN_RING3
1850 if ( (u32 & SVGA_REG_ENABLE_ENABLE)
1851 && pThis->svga.fEnabled == false)
1852 {
1853 /* Make a backup copy of the first 512kb in order to save font data etc. */
1854 /** @todo should probably swap here, rather than copy + zero */
1855 memcpy(pThisCC->svga.pbVgaFrameBufferR3, pThisCC->pbVRam, VMSVGA_VGA_FB_BACKUP_SIZE);
1856 memset(pThisCC->pbVRam, 0, VMSVGA_VGA_FB_BACKUP_SIZE);
1857 }
1858
1859 pThis->svga.fEnabled = u32;
1860 if (pThis->svga.fEnabled)
1861 {
1862 if ( pThis->svga.uWidth == VMSVGA_VAL_UNINITIALIZED
1863 && pThis->svga.uHeight == VMSVGA_VAL_UNINITIALIZED)
1864 {
1865 /* Keep the current mode. */
1866 pThis->svga.uWidth = pThisCC->pDrv->cx;
1867 pThis->svga.uHeight = pThisCC->pDrv->cy;
1868 pThis->svga.uBpp = (pThisCC->pDrv->cBits + 7) & ~7;
1869 vmsvgaHCUpdatePitch(pThis, pThisCC);
1870 }
1871
1872 if ( pThis->svga.uWidth != VMSVGA_VAL_UNINITIALIZED
1873 && pThis->svga.uHeight != VMSVGA_VAL_UNINITIALIZED)
1874 ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE);
1875# ifdef LOG_ENABLED
1876 uint32_t *pFIFO = pThisCC->svga.pau32FIFO;
1877 Log(("configured=%d busy=%d\n", pThis->svga.fConfigured, pFIFO[SVGA_FIFO_BUSY]));
1878 Log(("next %x stop %x\n", pFIFO[SVGA_FIFO_NEXT_CMD], pFIFO[SVGA_FIFO_STOP]));
1879# endif
1880
1881 /* Disable or enable dirty page tracking according to the current fTraces value. */
1882 vmsvgaR3SetTraces(pDevIns, pThis, !!pThis->svga.fTraces);
1883
1884 /* bird: Whatever this is was added to make screenshot work, ask sunlover should explain... */
1885 for (uint32_t idScreen = 0; idScreen < pThis->cMonitors; ++idScreen)
1886 pThisCC->pDrv->pfnVBVAEnable(pThisCC->pDrv, idScreen, NULL /*pHostFlags*/);
1887
1888 /* Make the cursor visible again as needed. */
1889 if (pSVGAState->Cursor.fActive)
1890 pThisCC->pDrv->pfnVBVAMousePointerShape(pThisCC->pDrv, true /*fVisible*/, false, 0, 0, 0, 0, NULL);
1891 }
1892 else
1893 {
1894 /* Make sure the cursor is off. */
1895 if (pSVGAState->Cursor.fActive)
1896 pThisCC->pDrv->pfnVBVAMousePointerShape(pThisCC->pDrv, false /*fVisible*/, false, 0, 0, 0, 0, NULL);
1897
1898 /* Restore the text mode backup. */
1899 memcpy(pThisCC->pbVRam, pThisCC->svga.pbVgaFrameBufferR3, VMSVGA_VGA_FB_BACKUP_SIZE);
1900
1901 pThisCC->pDrv->pfnLFBModeChange(pThisCC->pDrv, false);
1902
1903 /* Enable dirty page tracking again when going into legacy mode. */
1904 vmsvgaR3SetTraces(pDevIns, pThis, true);
1905
1906 /* bird: Whatever this is was added to make screenshot work, ask sunlover should explain... */
1907 for (uint32_t idScreen = 0; idScreen < pThis->cMonitors; ++idScreen)
1908 pThisCC->pDrv->pfnVBVADisable(pThisCC->pDrv, idScreen);
1909
1910 /* Clear the pitch lock. */
1911 pThis->svga.u32PitchLock = 0;
1912 }
1913#else /* !IN_RING3 */
1914 rc = VINF_IOM_R3_IOPORT_WRITE;
1915#endif /* !IN_RING3 */
1916 break;
1917
1918 case SVGA_REG_WIDTH:
1919 STAM_REL_COUNTER_INC(&pThis->svga.StatRegWidthWr);
1920 if (u32 != pThis->svga.uWidth)
1921 {
1922 if (u32 <= pThis->svga.u32MaxWidth)
1923 {
1924#if defined(IN_RING3) || defined(IN_RING0)
1925 pThis->svga.uWidth = u32;
1926 vmsvgaHCUpdatePitch(pThis, pThisCC);
1927 if (pThis->svga.fEnabled)
1928 ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE);
1929#else
1930 rc = VINF_IOM_R3_IOPORT_WRITE;
1931#endif
1932 }
1933 else
1934 Log(("SVGA_REG_WIDTH: New value is out of bounds: %u, max %u\n", u32, pThis->svga.u32MaxWidth));
1935 }
1936 /* else: nop */
1937 break;
1938
1939 case SVGA_REG_HEIGHT:
1940 STAM_REL_COUNTER_INC(&pThis->svga.StatRegHeightWr);
1941 if (u32 != pThis->svga.uHeight)
1942 {
1943 if (u32 <= pThis->svga.u32MaxHeight)
1944 {
1945 pThis->svga.uHeight = u32;
1946 if (pThis->svga.fEnabled)
1947 ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE);
1948 }
1949 else
1950 Log(("SVGA_REG_HEIGHT: New value is out of bounds: %u, max %u\n", u32, pThis->svga.u32MaxHeight));
1951 }
1952 /* else: nop */
1953 break;
1954
1955 case SVGA_REG_DEPTH:
1956 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDepthWr);
1957 /** @todo read-only?? */
1958 break;
1959
1960 case SVGA_REG_BITS_PER_PIXEL: /* Current bpp in the guest */
1961 STAM_REL_COUNTER_INC(&pThis->svga.StatRegBitsPerPixelWr);
1962 if (pThis->svga.uBpp != u32)
1963 {
1964 if (u32 <= 32)
1965 {
1966#if defined(IN_RING3) || defined(IN_RING0)
1967 pThis->svga.uBpp = u32;
1968 vmsvgaHCUpdatePitch(pThis, pThisCC);
1969 if (pThis->svga.fEnabled)
1970 ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE);
1971#else
1972 rc = VINF_IOM_R3_IOPORT_WRITE;
1973#endif
1974 }
1975 else
1976 Log(("SVGA_REG_BITS_PER_PIXEL: New value is out of bounds: %u, max 32\n", u32));
1977 }
1978 /* else: nop */
1979 break;
1980
1981 case SVGA_REG_PSEUDOCOLOR:
1982 STAM_REL_COUNTER_INC(&pThis->svga.StatRegPseudoColorWr);
1983 break;
1984
1985 case SVGA_REG_CONFIG_DONE: /* Set when memory area configured */
1986#ifdef IN_RING3
1987 STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegConfigDoneWr);
1988 pThis->svga.fConfigured = u32;
1989 /* Disabling the FIFO enables tracing (dirty page detection) by default. */
1990 if (!pThis->svga.fConfigured)
1991 pThis->svga.fTraces = true;
1992 vmsvgaR3SetTraces(pDevIns, pThis, !!pThis->svga.fTraces);
1993#else
1994 rc = VINF_IOM_R3_IOPORT_WRITE;
1995#endif
1996 break;
1997
1998 case SVGA_REG_SYNC: /* See "FIFO Synchronization Registers" */
1999 STAM_REL_COUNTER_INC(&pThis->svga.StatRegSyncWr);
2000 if ( pThis->svga.fEnabled
2001 && pThis->svga.fConfigured)
2002 {
2003#if defined(IN_RING3) || defined(IN_RING0)
2004 Log(("SVGA_REG_SYNC: SVGA_FIFO_BUSY=%d\n", pThisCC->svga.pau32FIFO[SVGA_FIFO_BUSY]));
2005 /*
2006 * The VMSVGA_BUSY_F_EMT_FORCE flag makes sure we will check if the FIFO is empty
2007 * at least once; VMSVGA_BUSY_F_FIFO alone does not ensure that.
2008 */
2009 ASMAtomicWriteU32(&pThis->svga.fBusy, VMSVGA_BUSY_F_EMT_FORCE | VMSVGA_BUSY_F_FIFO);
2010 if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_BUSY, pThisCC->svga.pau32FIFO[SVGA_FIFO_MIN]))
2011 vmsvgaHCSafeFifoBusyRegUpdate(pThis, pThisCC, true);
2012
2013 /* Kick the FIFO thread to start processing commands again. */
2014 PDMDevHlpSUPSemEventSignal(pDevIns, pThis->svga.hFIFORequestSem);
2015#else
2016 rc = VINF_IOM_R3_IOPORT_WRITE;
2017#endif
2018 }
2019 /* else nothing to do. */
2020 else
2021 Log(("Sync ignored enabled=%d configured=%d\n", pThis->svga.fEnabled, pThis->svga.fConfigured));
2022
2023 break;
2024
2025 case SVGA_REG_BUSY: /* See "FIFO Synchronization Registers" (read-only) */
2026 STAM_REL_COUNTER_INC(&pThis->svga.StatRegBusyWr);
2027 break;
2028
2029 case SVGA_REG_GUEST_ID: /* Set guest OS identifier */
2030 STAM_REL_COUNTER_INC(&pThis->svga.StatRegGuestIdWr);
2031 pThis->svga.u32GuestId = u32;
2032 break;
2033
2034 case SVGA_REG_PITCHLOCK: /* Fixed pitch for all modes */
2035 STAM_REL_COUNTER_INC(&pThis->svga.StatRegPitchLockWr);
2036 pThis->svga.u32PitchLock = u32;
2037 /* Should this also update the FIFO pitch lock? Unclear. */
2038 break;
2039
2040 case SVGA_REG_IRQMASK: /* Interrupt mask */
2041 STAM_REL_COUNTER_INC(&pThis->svga.StatRegIrqMaskWr);
2042 pThis->svga.u32IrqMask = u32;
2043
2044 /* Irq pending after the above change? */
2045 if (pThis->svga.u32IrqStatus & u32)
2046 {
2047 Log(("SVGA_REG_IRQMASK: Trigger interrupt with status %x\n", pThis->svga.u32IrqStatus));
2048 PDMDevHlpPCISetIrqNoWait(pDevIns, 0, 1);
2049 }
2050 else
2051 PDMDevHlpPCISetIrqNoWait(pDevIns, 0, 0);
2052 break;
2053
2054 /* Mouse cursor support */
2055 case SVGA_REG_DEAD: /* SVGA_REG_CURSOR_ID */
2056 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorIdWr);
2057 pThis->svga.uCursorID = u32;
2058 break;
2059
2060 case SVGA_REG_CURSOR_X:
2061 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorXWr);
2062 pThis->svga.uCursorX = u32;
2063 break;
2064
2065 case SVGA_REG_CURSOR_Y:
2066 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorYWr);
2067 pThis->svga.uCursorY = u32;
2068 break;
2069
2070 case SVGA_REG_CURSOR_ON:
2071#ifdef IN_RING3
2072 /* The cursor is only updated when SVGA_REG_CURSOR_ON is written. */
2073 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorOnWr);
2074 vmsvgaR3RegUpdateCursor(pThisCC, pThis, u32);
2075#else
2076 rc = VINF_IOM_R3_IOPORT_WRITE;
2077#endif
2078 break;
2079
2080 /* Legacy multi-monitor support */
2081 case SVGA_REG_NUM_GUEST_DISPLAYS:/* Number of guest displays in X/Y direction */
2082 STAM_REL_COUNTER_INC(&pThis->svga.StatRegNumGuestDisplaysWr);
2083 break;
2084 case SVGA_REG_DISPLAY_ID: /* Display ID for the following display attributes */
2085 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayIdWr);
2086 break;
2087 case SVGA_REG_DISPLAY_IS_PRIMARY:/* Whether this is a primary display */
2088 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayIsPrimaryWr);
2089 break;
2090 case SVGA_REG_DISPLAY_POSITION_X:/* The display position x */
2091 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayPositionXWr);
2092 break;
2093 case SVGA_REG_DISPLAY_POSITION_Y:/* The display position y */
2094 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayPositionYWr);
2095 break;
2096 case SVGA_REG_DISPLAY_WIDTH: /* The display's width */
2097 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayWidthWr);
2098 break;
2099 case SVGA_REG_DISPLAY_HEIGHT: /* The display's height */
2100 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayHeightWr);
2101 break;
2102#ifdef VBOX_WITH_VMSVGA3D
2103 /* See "Guest memory regions" below. */
2104 case SVGA_REG_GMR_ID:
2105 STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrIdWr);
2106 pThis->svga.u32CurrentGMRId = u32;
2107 break;
2108
2109 case SVGA_REG_GMR_DESCRIPTOR:
2110# ifndef IN_RING3
2111 rc = VINF_IOM_R3_IOPORT_WRITE;
2112 break;
2113# else /* IN_RING3 */
2114 {
2115 STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegGmrDescriptorWr);
2116
2117 /* Validate current GMR id. */
2118 uint32_t idGMR = pThis->svga.u32CurrentGMRId;
2119 AssertBreak(idGMR < pThis->svga.cGMR);
2120 RT_UNTRUSTED_VALIDATED_FENCE();
2121
2122 /* Free the old GMR if present. */
2123 vmsvgaR3GmrFree(pThisCC, idGMR);
2124
2125 /* Just undefine the GMR? */
2126 RTGCPHYS GCPhys = (RTGCPHYS)u32 << GUEST_PAGE_SHIFT;
2127 if (GCPhys == 0)
2128 {
2129 STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegGmrDescriptorWrFree);
2130 break;
2131 }
2132
2133
2134 /* Never cross a page boundary automatically. */
2135 const uint32_t cMaxPages = RT_MIN(VMSVGA_MAX_GMR_PAGES, UINT32_MAX / X86_PAGE_SIZE);
2136 uint32_t cPagesTotal = 0;
2137 uint32_t iDesc = 0;
2138 PVMSVGAGMRDESCRIPTOR paDescs = NULL;
2139 uint32_t cLoops = 0;
2140 RTGCPHYS GCPhysBase = GCPhys;
2141 while ((GCPhys >> GUEST_PAGE_SHIFT) == (GCPhysBase >> GUEST_PAGE_SHIFT))
2142 {
2143 /* Read descriptor. */
2144 SVGAGuestMemDescriptor desc;
2145 rc = PDMDevHlpPCIPhysRead(pDevIns, GCPhys, &desc, sizeof(desc));
2146 AssertRCBreak(VBOXSTRICTRC_VAL(rc));
2147
2148 if (desc.numPages != 0)
2149 {
2150 AssertBreakStmt(desc.numPages <= cMaxPages, rc = VERR_OUT_OF_RANGE);
2151 cPagesTotal += desc.numPages;
2152 AssertBreakStmt(cPagesTotal <= cMaxPages, rc = VERR_OUT_OF_RANGE);
2153
2154 if ((iDesc & 15) == 0)
2155 {
2156 void *pvNew = RTMemRealloc(paDescs, (iDesc + 16) * sizeof(VMSVGAGMRDESCRIPTOR));
2157 AssertBreakStmt(pvNew, rc = VERR_NO_MEMORY);
2158 paDescs = (PVMSVGAGMRDESCRIPTOR)pvNew;
2159 }
2160
2161 paDescs[iDesc].GCPhys = (RTGCPHYS)desc.ppn << GUEST_PAGE_SHIFT;
2162 paDescs[iDesc++].numPages = desc.numPages;
2163
2164 /* Continue with the next descriptor. */
2165 GCPhys += sizeof(desc);
2166 }
2167 else if (desc.ppn == 0)
2168 break; /* terminator */
2169 else /* Pointer to the next physical page of descriptors. */
2170 GCPhys = GCPhysBase = (RTGCPHYS)desc.ppn << GUEST_PAGE_SHIFT;
2171
2172 cLoops++;
2173 AssertBreakStmt(cLoops < VMSVGA_MAX_GMR_DESC_LOOP_COUNT, rc = VERR_OUT_OF_RANGE);
2174 }
2175
2176 AssertStmt(iDesc > 0 || RT_FAILURE_NP(rc), rc = VERR_OUT_OF_RANGE);
2177 if (RT_SUCCESS(rc))
2178 {
2179 /* Commit the GMR. */
2180 pSVGAState->paGMR[idGMR].paDesc = paDescs;
2181 pSVGAState->paGMR[idGMR].numDescriptors = iDesc;
2182 pSVGAState->paGMR[idGMR].cMaxPages = cPagesTotal;
2183 pSVGAState->paGMR[idGMR].cbTotal = cPagesTotal * GUEST_PAGE_SIZE;
2184 Assert((pSVGAState->paGMR[idGMR].cbTotal >> GUEST_PAGE_SHIFT) == cPagesTotal);
2185 Log(("Defined new gmr %x numDescriptors=%d cbTotal=%x (%#x pages)\n",
2186 idGMR, iDesc, pSVGAState->paGMR[idGMR].cbTotal, cPagesTotal));
2187 }
2188 else
2189 {
2190 RTMemFree(paDescs);
2191 STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegGmrDescriptorWrErrors);
2192 }
2193 break;
2194 }
2195# endif /* IN_RING3 */
2196#endif // VBOX_WITH_VMSVGA3D
2197
2198 case SVGA_REG_TRACES: /* Enable trace-based updates even when FIFO is on */
2199 STAM_REL_COUNTER_INC(&pThis->svga.StatRegTracesWr);
2200 if (pThis->svga.fTraces == u32)
2201 break; /* nothing to do */
2202
2203#ifdef IN_RING3
2204 vmsvgaR3SetTraces(pDevIns, pThis, !!u32);
2205#else
2206 rc = VINF_IOM_R3_IOPORT_WRITE;
2207#endif
2208 break;
2209
2210 case SVGA_REG_TOP: /* Must be 1 more than the last register */
2211 STAM_REL_COUNTER_INC(&pThis->svga.StatRegTopWr);
2212 break;
2213
2214 case SVGA_REG_NUM_DISPLAYS: /* (Deprecated) */
2215 STAM_REL_COUNTER_INC(&pThis->svga.StatRegNumDisplaysWr);
2216 Log(("Write to deprecated register %x - val %x ignored\n", idxReg, u32));
2217 break;
2218
2219 /*
2220 * SVGA_CAP_GBOBJECTS+ registers.
2221 */
2222 case SVGA_REG_COMMAND_LOW:
2223 {
2224 /* Lower 32 bits of command buffer physical address and submit the command buffer. */
2225#ifdef IN_RING3
2226 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCommandLowWr);
2227 pThis->svga.u32RegCommandLow = u32;
2228
2229 /* "lower 6 bits are used for the SVGACBContext" */
2230 RTGCPHYS GCPhysCB = pThis->svga.u32RegCommandHigh;
2231 GCPhysCB <<= 32;
2232 GCPhysCB |= pThis->svga.u32RegCommandLow & ~SVGA_CB_CONTEXT_MASK;
2233 SVGACBContext const CBCtx = (SVGACBContext)(pThis->svga.u32RegCommandLow & SVGA_CB_CONTEXT_MASK);
2234 vmsvgaR3CmdBufSubmit(pDevIns, pThis, pThisCC, GCPhysCB, CBCtx);
2235#else
2236 rc = VINF_IOM_R3_IOPORT_WRITE;
2237#endif
2238 break;
2239 }
2240
2241 case SVGA_REG_COMMAND_HIGH:
2242 /* Upper 32 bits of command buffer PA. */
2243 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCommandHighWr);
2244 pThis->svga.u32RegCommandHigh = u32;
2245 break;
2246
2247 case SVGA_REG_DEV_CAP:
2248 /* Write dev cap index, read value */
2249 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDevCapWr);
2250 pThis->svga.u32DevCapIndex = u32;
2251 break;
2252
2253 case SVGA_REG_CMD_PREPEND_LOW:
2254 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCmdPrependLowWr);
2255 /* Not supported. */
2256 break;
2257
2258 case SVGA_REG_CMD_PREPEND_HIGH:
2259 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCmdPrependHighWr);
2260 /* Not supported. */
2261 break;
2262
2263 case SVGA_REG_FB_START:
2264 case SVGA_REG_MEM_START:
2265 case SVGA_REG_HOST_BITS_PER_PIXEL:
2266 case SVGA_REG_MAX_WIDTH:
2267 case SVGA_REG_MAX_HEIGHT:
2268 case SVGA_REG_VRAM_SIZE:
2269 case SVGA_REG_FB_SIZE:
2270 case SVGA_REG_CAPABILITIES:
2271 case SVGA_REG_MEM_SIZE:
2272 case SVGA_REG_SCRATCH_SIZE: /* Number of scratch registers */
2273 case SVGA_REG_MEM_REGS: /* Number of FIFO registers */
2274 case SVGA_REG_BYTES_PER_LINE:
2275 case SVGA_REG_FB_OFFSET:
2276 case SVGA_REG_RED_MASK:
2277 case SVGA_REG_GREEN_MASK:
2278 case SVGA_REG_BLUE_MASK:
2279 case SVGA_REG_GMRS_MAX_PAGES: /* Maximum number of 4KB pages for all GMRs */
2280 case SVGA_REG_MEMORY_SIZE: /* Total dedicated device memory excluding FIFO */
2281 case SVGA_REG_GMR_MAX_IDS:
2282 case SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH:
2283 case SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM:
2284 case SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB:
2285 case SVGA_REG_SCREENTARGET_MAX_WIDTH:
2286 case SVGA_REG_SCREENTARGET_MAX_HEIGHT:
2287 case SVGA_REG_MOB_MAX_SIZE:
2288 /* Read only - ignore. */
2289 Log(("Write to R/O register %x - val %x ignored\n", idxReg, u32));
2290 STAM_REL_COUNTER_INC(&pThis->svga.StatRegReadOnlyWr);
2291 break;
2292
2293 default:
2294 {
2295 uint32_t offReg;
2296 if ((offReg = idxReg - SVGA_SCRATCH_BASE) < pThis->svga.cScratchRegion)
2297 {
2298 RT_UNTRUSTED_VALIDATED_FENCE();
2299 pThis->svga.au32ScratchRegion[offReg] = u32;
2300 STAM_REL_COUNTER_INC(&pThis->svga.StatRegScratchWr);
2301 }
2302 else if ((offReg = idxReg - SVGA_PALETTE_BASE) < (uint32_t)SVGA_NUM_PALETTE_REGS)
2303 {
2304 /* Note! Using last_palette rather than palette here to preserve the VGA one.
2305 Btw, see rgb_to_pixel32. */
2306 STAM_REL_COUNTER_INC(&pThis->svga.StatRegPaletteWr);
2307 u32 &= 0xff;
2308 RT_UNTRUSTED_VALIDATED_FENCE();
2309 uint32_t uRgb = pThis->last_palette[offReg / 3];
2310 switch (offReg % 3)
2311 {
2312 case 0: uRgb = (uRgb & UINT32_C(0x0000ffff)) | (u32 << 16); break; /* red */
2313 case 1: uRgb = (uRgb & UINT32_C(0x00ff00ff)) | (u32 << 8); break; /* green */
2314 case 2: uRgb = (uRgb & UINT32_C(0x00ffff00)) | u32 ; break; /* blue */
2315 }
2316 pThis->last_palette[offReg / 3] = uRgb;
2317 }
2318 else
2319 {
2320#if !defined(IN_RING3) && defined(VBOX_STRICT)
2321 rc = VINF_IOM_R3_IOPORT_WRITE;
2322#else
2323 STAM_REL_COUNTER_INC(&pThis->svga.StatRegUnknownWr);
2324 AssertMsgFailed(("reg=%#x u32=%#x\n", idxReg, u32));
2325#endif
2326 }
2327 break;
2328 }
2329 }
2330 return rc;
2331}
2332
2333/**
2334 * @callback_method_impl{FNIOMIOPORTNEWIN}
2335 */
2336DECLCALLBACK(VBOXSTRICTRC) vmsvgaIORead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb)
2337{
2338 PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
2339 RT_NOREF_PV(pvUser);
2340
2341 /* Only dword accesses. */
2342 if (cb == 4)
2343 {
2344 switch (offPort)
2345 {
2346 case SVGA_INDEX_PORT:
2347 *pu32 = pThis->svga.u32IndexReg;
2348 break;
2349
2350 case SVGA_VALUE_PORT:
2351 return vmsvgaReadPort(pDevIns, pThis, pu32);
2352
2353 case SVGA_BIOS_PORT:
2354 Log(("Ignoring BIOS port read\n"));
2355 *pu32 = 0;
2356 break;
2357
2358 case SVGA_IRQSTATUS_PORT:
2359 LogFlow(("vmsvgaIORead: SVGA_IRQSTATUS_PORT %x\n", pThis->svga.u32IrqStatus));
2360 *pu32 = pThis->svga.u32IrqStatus;
2361 break;
2362
2363 default:
2364 ASSERT_GUEST_MSG_FAILED(("vmsvgaIORead: Unknown register %u was read from.\n", offPort));
2365 *pu32 = UINT32_MAX;
2366 break;
2367 }
2368 }
2369 else
2370 {
2371 Log(("Ignoring non-dword I/O port read at %x cb=%d\n", offPort, cb));
2372 *pu32 = UINT32_MAX;
2373 }
2374 return VINF_SUCCESS;
2375}
2376
2377/**
2378 * @callback_method_impl{FNIOMIOPORTNEWOUT}
2379 */
2380DECLCALLBACK(VBOXSTRICTRC) vmsvgaIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb)
2381{
2382 PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
2383 PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
2384 RT_NOREF_PV(pvUser);
2385
2386 /* Only dword accesses. */
2387 if (cb == 4)
2388 switch (offPort)
2389 {
2390 case SVGA_INDEX_PORT:
2391 pThis->svga.u32IndexReg = u32;
2392 break;
2393
2394 case SVGA_VALUE_PORT:
2395 return vmsvgaWritePort(pDevIns, pThis, pThisCC, u32);
2396
2397 case SVGA_BIOS_PORT:
2398 Log(("Ignoring BIOS port write (val=%x)\n", u32));
2399 break;
2400
2401 case SVGA_IRQSTATUS_PORT:
2402 LogFlow(("vmsvgaIOWrite SVGA_IRQSTATUS_PORT %x: status %x -> %x\n", u32, pThis->svga.u32IrqStatus, pThis->svga.u32IrqStatus & ~u32));
2403 ASMAtomicAndU32(&pThis->svga.u32IrqStatus, ~u32);
2404 /* Clear the irq in case all events have been cleared. */
2405 if (!(pThis->svga.u32IrqStatus & pThis->svga.u32IrqMask))
2406 {
2407 Log(("vmsvgaIOWrite SVGA_IRQSTATUS_PORT: clearing IRQ\n"));
2408 PDMDevHlpPCISetIrqNoWait(pDevIns, 0, 0);
2409 }
2410 break;
2411
2412 default:
2413 ASSERT_GUEST_MSG_FAILED(("vmsvgaIOWrite: Unknown register %u was written to, value %#x LB %u.\n", offPort, u32, cb));
2414 break;
2415 }
2416 else
2417 Log(("Ignoring non-dword write at %x val=%x cb=%d\n", offPort, u32, cb));
2418
2419 return VINF_SUCCESS;
2420}
2421
2422#ifdef IN_RING3
2423
2424# ifdef DEBUG_FIFO_ACCESS
2425/**
2426 * Handle FIFO memory access.
2427 * @returns VBox status code.
2428 * @param pVM VM handle.
2429 * @param pThis The shared VGA/VMSVGA instance data.
2430 * @param GCPhys The access physical address.
2431 * @param fWriteAccess Read or write access
2432 */
2433static int vmsvgaR3DebugFifoAccess(PVM pVM, PVGASTATE pThis, RTGCPHYS GCPhys, bool fWriteAccess)
2434{
2435 RT_NOREF(pVM);
2436 RTGCPHYS GCPhysOffset = GCPhys - pThis->svga.GCPhysFIFO;
2437 uint32_t *pFIFO = pThisCC->svga.pau32FIFO;
2438
2439 switch (GCPhysOffset >> 2)
2440 {
2441 case SVGA_FIFO_MIN:
2442 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_MIN = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2443 break;
2444 case SVGA_FIFO_MAX:
2445 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_MAX = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2446 break;
2447 case SVGA_FIFO_NEXT_CMD:
2448 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_NEXT_CMD = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2449 break;
2450 case SVGA_FIFO_STOP:
2451 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_STOP = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2452 break;
2453 case SVGA_FIFO_CAPABILITIES:
2454 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CAPABILITIES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2455 break;
2456 case SVGA_FIFO_FLAGS:
2457 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_FLAGS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2458 break;
2459 case SVGA_FIFO_FENCE:
2460 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_FENCE = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2461 break;
2462 case SVGA_FIFO_3D_HWVERSION:
2463 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_HWVERSION = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2464 break;
2465 case SVGA_FIFO_PITCHLOCK:
2466 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_PITCHLOCK = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2467 break;
2468 case SVGA_FIFO_CURSOR_ON:
2469 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_ON = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2470 break;
2471 case SVGA_FIFO_CURSOR_X:
2472 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_X = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2473 break;
2474 case SVGA_FIFO_CURSOR_Y:
2475 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_Y = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2476 break;
2477 case SVGA_FIFO_CURSOR_COUNT:
2478 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_COUNT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2479 break;
2480 case SVGA_FIFO_CURSOR_LAST_UPDATED:
2481 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_LAST_UPDATED = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2482 break;
2483 case SVGA_FIFO_RESERVED:
2484 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_RESERVED = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2485 break;
2486 case SVGA_FIFO_CURSOR_SCREEN_ID:
2487 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_SCREEN_ID = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2488 break;
2489 case SVGA_FIFO_DEAD:
2490 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_DEAD = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2491 break;
2492 case SVGA_FIFO_3D_HWVERSION_REVISED:
2493 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_HWVERSION_REVISED = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2494 break;
2495 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_3D:
2496 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_3D = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2497 break;
2498 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_LIGHTS:
2499 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_LIGHTS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2500 break;
2501 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURES:
2502 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2503 break;
2504 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_CLIP_PLANES:
2505 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_CLIP_PLANES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2506 break;
2507 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_VERTEX_SHADER_VERSION:
2508 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_VERTEX_SHADER_VERSION = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2509 break;
2510 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_VERTEX_SHADER:
2511 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_VERTEX_SHADER = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2512 break;
2513 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_FRAGMENT_SHADER_VERSION:
2514 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_FRAGMENT_SHADER_VERSION = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2515 break;
2516 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_FRAGMENT_SHADER:
2517 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_FRAGMENT_SHADER = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2518 break;
2519 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_RENDER_TARGETS:
2520 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_RENDER_TARGETS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2521 break;
2522 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_S23E8_TEXTURES:
2523 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_S23E8_TEXTURES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2524 break;
2525 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_S10E5_TEXTURES:
2526 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_S10E5_TEXTURES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2527 break;
2528 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_FIXED_VERTEXBLEND:
2529 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_FIXED_VERTEXBLEND = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2530 break;
2531 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_D16_BUFFER_FORMAT:
2532 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_D16_BUFFER_FORMAT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2533 break;
2534 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_D24S8_BUFFER_FORMAT:
2535 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_D24S8_BUFFER_FORMAT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2536 break;
2537 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_D24X8_BUFFER_FORMAT:
2538 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_D24X8_BUFFER_FORMAT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2539 break;
2540 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_QUERY_TYPES:
2541 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_QUERY_TYPES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2542 break;
2543 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_TEXTURE_GRADIENT_SAMPLING:
2544 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_TEXTURE_GRADIENT_SAMPLING = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2545 break;
2546 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_POINT_SIZE:
2547 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_POINT_SIZE = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2548 break;
2549 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_SHADER_TEXTURES:
2550 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_SHADER_TEXTURES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2551 break;
2552 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURE_WIDTH:
2553 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURE_WIDTH = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2554 break;
2555 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURE_HEIGHT:
2556 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURE_HEIGHT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2557 break;
2558 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_VOLUME_EXTENT:
2559 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_VOLUME_EXTENT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2560 break;
2561 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURE_REPEAT:
2562 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURE_REPEAT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2563 break;
2564 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURE_ASPECT_RATIO:
2565 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]));
2566 break;
2567 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURE_ANISOTROPY:
2568 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURE_ANISOTROPY = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2569 break;
2570 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_PRIMITIVE_COUNT:
2571 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_PRIMITIVE_COUNT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2572 break;
2573 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_VERTEX_INDEX:
2574 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_VERTEX_INDEX = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2575 break;
2576 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_VERTEX_SHADER_INSTRUCTIONS:
2577 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]));
2578 break;
2579 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_INSTRUCTIONS:
2580 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]));
2581 break;
2582 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEMPS:
2583 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]));
2584 break;
2585 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_TEMPS:
2586 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]));
2587 break;
2588 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_TEXTURE_OPS:
2589 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_TEXTURE_OPS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2590 break;
2591 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8:
2592 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2593 break;
2594 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8:
2595 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2596 break;
2597 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10:
2598 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2599 break;
2600 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5:
2601 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2602 break;
2603 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5:
2604 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2605 break;
2606 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4:
2607 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2608 break;
2609 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_R5G6B5:
2610 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_R5G6B5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2611 break;
2612 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE16:
2613 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2614 break;
2615 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8:
2616 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2617 break;
2618 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_ALPHA8:
2619 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_ALPHA8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2620 break;
2621 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8:
2622 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2623 break;
2624 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_D16:
2625 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_D16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2626 break;
2627 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8:
2628 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2629 break;
2630 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8:
2631 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2632 break;
2633 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_DXT1:
2634 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_DXT1 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2635 break;
2636 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_DXT2:
2637 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_DXT2 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2638 break;
2639 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_DXT3:
2640 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_DXT3 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2641 break;
2642 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_DXT4:
2643 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_DXT4 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2644 break;
2645 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_DXT5:
2646 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_DXT5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2647 break;
2648 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_BUMPX8L8V8U8:
2649 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_BUMPX8L8V8U8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2650 break;
2651 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A2W10V10U10:
2652 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A2W10V10U10 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2653 break;
2654 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_BUMPU8V8:
2655 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_BUMPU8V8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2656 break;
2657 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Q8W8V8U8:
2658 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Q8W8V8U8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2659 break;
2660 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_CxV8U8:
2661 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_CxV8U8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2662 break;
2663 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_R_S10E5:
2664 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_R_S10E5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2665 break;
2666 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_R_S23E8:
2667 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_R_S23E8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2668 break;
2669 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_RG_S10E5:
2670 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_RG_S10E5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2671 break;
2672 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_RG_S23E8:
2673 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_RG_S23E8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2674 break;
2675 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_ARGB_S10E5:
2676 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_ARGB_S10E5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2677 break;
2678 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_ARGB_S23E8:
2679 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_ARGB_S23E8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2680 break;
2681 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEXTURES:
2682 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]));
2683 break;
2684 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_SIMULTANEOUS_RENDER_TARGETS:
2685 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]));
2686 break;
2687 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_V16U16:
2688 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_V16U16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2689 break;
2690 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_G16R16:
2691 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_G16R16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2692 break;
2693 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16:
2694 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2695 break;
2696 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_UYVY:
2697 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_UYVY = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2698 break;
2699 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_YUY2:
2700 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_YUY2 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2701 break;
2702 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_DEAD4: /* SVGA3D_DEVCAP_MULTISAMPLE_NONMASKABLESAMPLES */
2703 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_DEAD4 (SVGA3D_DEVCAP_MULTISAMPLE_NONMASKABLESAMPLES) = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2704 break;
2705 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_DEAD5: /* SVGA3D_DEVCAP_MULTISAMPLE_MASKABLESAMPLES */
2706 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_DEAD5 (SVGA3D_DEVCAP_MULTISAMPLE_MASKABLESAMPLES) = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2707 break;
2708 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_DEAD7: /* SVGA3D_DEVCAP_ALPHATOCOVERAGE */
2709 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_DEAD7 (SVGA3D_DEVCAP_ALPHATOCOVERAGE) = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2710 break;
2711 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_DEAD6: /* SVGA3D_DEVCAP_SUPERSAMPLE */
2712 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_DEAD6 (SVGA3D_DEVCAP_SUPERSAMPLE) = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2713 break;
2714 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_AUTOGENMIPMAPS:
2715 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_AUTOGENMIPMAPS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2716 break;
2717 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_NV12:
2718 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_NV12 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2719 break;
2720 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_DEAD10: /* SVGA3D_DEVCAP_SURFACEFMT_AYUV */
2721 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_DEAD10 (SVGA3D_DEVCAP_SURFACEFMT_AYUV) = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2722 break;
2723 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_CONTEXT_IDS:
2724 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_CONTEXT_IDS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2725 break;
2726 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_SURFACE_IDS:
2727 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_SURFACE_IDS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2728 break;
2729 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_DF16:
2730 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_DF16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2731 break;
2732 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_DF24:
2733 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_DF24 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2734 break;
2735 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8_INT:
2736 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]));
2737 break;
2738 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_ATI1:
2739 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_ATI1 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2740 break;
2741 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_ATI2:
2742 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_ATI2 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2743 break;
2744 case SVGA_FIFO_3D_CAPS_LAST:
2745 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS_LAST = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2746 break;
2747 case SVGA_FIFO_GUEST_3D_HWVERSION:
2748 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_GUEST_3D_HWVERSION = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2749 break;
2750 case SVGA_FIFO_FENCE_GOAL:
2751 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_FENCE_GOAL = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2752 break;
2753 case SVGA_FIFO_BUSY:
2754 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_BUSY = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2755 break;
2756 default:
2757 Log(("vmsvgaFIFOAccess [0x%x]: %s access at offset %x = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", GCPhysOffset, pFIFO[GCPhysOffset >> 2]));
2758 break;
2759 }
2760
2761 return VINF_EM_RAW_EMULATE_INSTR;
2762}
2763# endif /* DEBUG_FIFO_ACCESS */
2764
2765# if defined(VMSVGA_USE_FIFO_ACCESS_HANDLER) || defined(DEBUG_FIFO_ACCESS)
2766/**
2767 * HC access handler for the FIFO.
2768 *
2769 * @returns VINF_SUCCESS if the handler have carried out the operation.
2770 * @returns VINF_PGM_HANDLER_DO_DEFAULT if the caller should carry out the access operation.
2771 * @param pVM VM Handle.
2772 * @param pVCpu The cross context CPU structure for the calling EMT.
2773 * @param GCPhys The physical address the guest is writing to.
2774 * @param pvPhys The HC mapping of that address.
2775 * @param pvBuf What the guest is reading/writing.
2776 * @param cbBuf How much it's reading/writing.
2777 * @param enmAccessType The access type.
2778 * @param enmOrigin Who is making the access.
2779 * @param pvUser User argument.
2780 */
2781static DECLCALLBACK(VBOXSTRICTRC)
2782vmsvgaR3FifoAccessHandler(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf,
2783 PGMACCESSTYPE enmAccessType, PGMACCESSORIGIN enmOrigin, void *pvUser)
2784{
2785 NOREF(pVCpu); NOREF(pvPhys); NOREF(pvBuf); NOREF(cbBuf); NOREF(enmOrigin); NOREF(enmAccessType); NOREF(GCPhys);
2786 PVGASTATE pThis = (PVGASTATE)pvUser;
2787 AssertPtr(pThis);
2788
2789# ifdef VMSVGA_USE_FIFO_ACCESS_HANDLER
2790 /*
2791 * Wake up the FIFO thread as it might have work to do now.
2792 */
2793 int rc = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->svga.hFIFORequestSem);
2794 AssertLogRelRC(rc);
2795# endif
2796
2797# ifdef DEBUG_FIFO_ACCESS
2798 /*
2799 * When in debug-fifo-access mode, we do not disable the access handler,
2800 * but leave it on as we wish to catch all access.
2801 */
2802 Assert(GCPhys >= pThis->svga.GCPhysFIFO);
2803 rc = vmsvgaR3DebugFifoAccess(pVM, pThis, GCPhys, enmAccessType == PGMACCESSTYPE_WRITE);
2804# elif defined(VMSVGA_USE_FIFO_ACCESS_HANDLER)
2805 /*
2806 * Temporarily disable the access handler now that we've kicked the FIFO thread.
2807 */
2808 STAM_REL_COUNTER_INC(&pThisCC->svga.pSvgaR3State->StatFifoAccessHandler);
2809 rc = PGMHandlerPhysicalPageTempOff(pVM, pThis->svga.GCPhysFIFO, pThis->svga.GCPhysFIFO);
2810# endif
2811 if (RT_SUCCESS(rc))
2812 return VINF_PGM_HANDLER_DO_DEFAULT;
2813 AssertMsg(rc <= VINF_SUCCESS, ("rc=%Rrc\n", rc));
2814 return rc;
2815}
2816# endif /* VMSVGA_USE_FIFO_ACCESS_HANDLER || DEBUG_FIFO_ACCESS */
2817
2818#endif /* IN_RING3 */
2819
2820#ifdef DEBUG_GMR_ACCESS
2821# ifdef IN_RING3
2822
2823/**
2824 * HC access handler for GMRs.
2825 *
2826 * @returns VINF_SUCCESS if the handler have carried out the operation.
2827 * @returns VINF_PGM_HANDLER_DO_DEFAULT if the caller should carry out the access operation.
2828 * @param pVM VM Handle.
2829 * @param pVCpu The cross context CPU structure for the calling EMT.
2830 * @param GCPhys The physical address the guest is writing to.
2831 * @param pvPhys The HC mapping of that address.
2832 * @param pvBuf What the guest is reading/writing.
2833 * @param cbBuf How much it's reading/writing.
2834 * @param enmAccessType The access type.
2835 * @param enmOrigin Who is making the access.
2836 * @param pvUser User argument.
2837 */
2838static DECLCALLBACK(VBOXSTRICTRC)
2839vmsvgaR3GmrAccessHandler(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf,
2840 PGMACCESSTYPE enmAccessType, PGMACCESSORIGIN enmOrigin, void *pvUser)
2841{
2842 PVGASTATE pThis = (PVGASTATE)pvUser;
2843 Assert(pThis);
2844 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
2845 NOREF(pVCpu); NOREF(pvPhys); NOREF(pvBuf); NOREF(cbBuf); NOREF(enmAccessType); NOREF(enmOrigin);
2846
2847 Log(("vmsvgaR3GmrAccessHandler: GMR access to page %RGp\n", GCPhys));
2848
2849 for (uint32_t i = 0; i < pThis->svga.cGMR; ++i)
2850 {
2851 PGMR pGMR = &pSVGAState->paGMR[i];
2852
2853 if (pGMR->numDescriptors)
2854 {
2855 for (uint32_t j = 0; j < pGMR->numDescriptors; j++)
2856 {
2857 if ( GCPhys >= pGMR->paDesc[j].GCPhys
2858 && GCPhys < pGMR->paDesc[j].GCPhys + pGMR->paDesc[j].numPages * GUEST_PAGE_SIZE)
2859 {
2860 /*
2861 * Turn off the write handler for this particular page and make it R/W.
2862 * Then return telling the caller to restart the guest instruction.
2863 */
2864 int rc = PGMHandlerPhysicalPageTempOff(pVM, pGMR->paDesc[j].GCPhys, GCPhys);
2865 AssertRC(rc);
2866 return VINF_PGM_HANDLER_DO_DEFAULT;
2867 }
2868 }
2869 }
2870 }
2871
2872 return VINF_PGM_HANDLER_DO_DEFAULT;
2873}
2874
2875/** Callback handler for VMR3ReqCallWaitU */
2876static DECLCALLBACK(int) vmsvgaR3RegisterGmr(PPDMDEVINS pDevIns, uint32_t gmrId)
2877{
2878 PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
2879 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
2880 PGMR pGMR = &pSVGAState->paGMR[gmrId];
2881 int rc;
2882
2883 for (uint32_t i = 0; i < pGMR->numDescriptors; i++)
2884 {
2885 rc = PDMDevHlpPGMHandlerPhysicalRegister(pDevIns, pGMR->paDesc[i].GCPhys,
2886 pGMR->paDesc[i].GCPhys + pGMR->paDesc[i].numPages * GUEST_PAGE_SIZE - 1,
2887 pThis->svga.hGmrAccessHandlerType, pThis, NIL_RTR0PTR, NIL_RTRCPTR, "VMSVGA GMR");
2888 AssertRC(rc);
2889 }
2890 return VINF_SUCCESS;
2891}
2892
2893/** Callback handler for VMR3ReqCallWaitU */
2894static DECLCALLBACK(int) vmsvgaR3DeregisterGmr(PPDMDEVINS pDevIns, uint32_t gmrId)
2895{
2896 PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
2897 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
2898 PGMR pGMR = &pSVGAState->paGMR[gmrId];
2899
2900 for (uint32_t i = 0; i < pGMR->numDescriptors; i++)
2901 {
2902 int rc = PDMDevHlpPGMHandlerPhysicalDeregister(pDevIns, pGMR->paDesc[i].GCPhys);
2903 AssertRC(rc);
2904 }
2905 return VINF_SUCCESS;
2906}
2907
2908/** Callback handler for VMR3ReqCallWaitU */
2909static DECLCALLBACK(int) vmsvgaR3ResetGmrHandlers(PVGASTATE pThis)
2910{
2911 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
2912
2913 for (uint32_t i = 0; i < pThis->svga.cGMR; ++i)
2914 {
2915 PGMR pGMR = &pSVGAState->paGMR[i];
2916
2917 if (pGMR->numDescriptors)
2918 {
2919 for (uint32_t j = 0; j < pGMR->numDescriptors; j++)
2920 {
2921 int rc = PDMDevHlpPGMHandlerPhysicalReset(pDevIns, pGMR->paDesc[j].GCPhys);
2922 AssertRC(rc);
2923 }
2924 }
2925 }
2926 return VINF_SUCCESS;
2927}
2928
2929# endif /* IN_RING3 */
2930#endif /* DEBUG_GMR_ACCESS */
2931
2932/* -=-=-=-=-=- Ring 3 -=-=-=-=-=- */
2933
2934#ifdef IN_RING3
2935
2936
2937/*
2938 *
2939 * Command buffer submission.
2940 *
2941 * Guest submits a buffer by writing to SVGA_REG_COMMAND_LOW register.
2942 *
2943 * EMT thread appends a command buffer to the context queue (VMSVGACMDBUFCTX::listSubmitted)
2944 * and wakes up the FIFO thread.
2945 *
2946 * FIFO thread fetches the command buffer from the queue, processes the commands and writes
2947 * the buffer header back to the guest memory.
2948 *
2949 * If buffers are preempted, then the EMT thread removes all buffers from the context queue.
2950 *
2951 */
2952
2953
2954/** Update a command buffer header 'status' and 'errorOffset' fields in the guest memory.
2955 *
2956 * @param pDevIns The device instance.
2957 * @param GCPhysCB Guest physical address of the command buffer header.
2958 * @param status Command buffer status (SVGA_CB_STATUS_*).
2959 * @param errorOffset Offset to the first byte of the failing command for SVGA_CB_STATUS_COMMAND_ERROR.
2960 * errorOffset is ignored if the status is not SVGA_CB_STATUS_COMMAND_ERROR.
2961 * @thread FIFO or EMT.
2962 */
2963static void vmsvgaR3CmdBufWriteStatus(PPDMDEVINS pDevIns, RTGCPHYS GCPhysCB, SVGACBStatus status, uint32_t errorOffset)
2964{
2965 SVGACBHeader hdr;
2966 hdr.status = status;
2967 hdr.errorOffset = errorOffset;
2968 AssertCompile( RT_OFFSETOF(SVGACBHeader, status) == 0
2969 && RT_OFFSETOF(SVGACBHeader, errorOffset) == 4
2970 && RT_OFFSETOF(SVGACBHeader, id) == 8);
2971 size_t const cbWrite = status == SVGA_CB_STATUS_COMMAND_ERROR
2972 ? RT_UOFFSET_AFTER(SVGACBHeader, errorOffset) /* Both 'status' and 'errorOffset' fields. */
2973 : RT_UOFFSET_AFTER(SVGACBHeader, status); /* Only 'status' field. */
2974 PDMDevHlpPCIPhysWrite(pDevIns, GCPhysCB, &hdr, cbWrite);
2975}
2976
2977
2978/** Raise an IRQ.
2979 *
2980 * @param pDevIns The device instance.
2981 * @param pThis The shared VGA/VMSVGA state.
2982 * @param u32IrqStatus SVGA_IRQFLAG_* bits.
2983 * @thread FIFO or EMT.
2984 */
2985static void vmsvgaR3CmdBufRaiseIRQ(PPDMDEVINS pDevIns, PVGASTATE pThis, uint32_t u32IrqStatus)
2986{
2987 int const rcLock = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VERR_IGNORED);
2988 PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, &pThis->CritSect, rcLock);
2989
2990 if (pThis->svga.u32IrqMask & u32IrqStatus)
2991 {
2992 LogFunc(("Trigger interrupt with status %#x\n", u32IrqStatus));
2993 ASMAtomicOrU32(&pThis->svga.u32IrqStatus, u32IrqStatus);
2994 PDMDevHlpPCISetIrq(pDevIns, 0, 1);
2995 }
2996
2997 PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect);
2998}
2999
3000
3001/** Allocate a command buffer structure.
3002 *
3003 * @param pCmdBufCtx The command buffer context which must allocate the buffer.
3004 * @return Pointer to the allocated command buffer structure.
3005 */
3006static PVMSVGACMDBUF vmsvgaR3CmdBufAlloc(PVMSVGACMDBUFCTX pCmdBufCtx)
3007{
3008 if (!pCmdBufCtx)
3009 return NULL;
3010
3011 PVMSVGACMDBUF pCmdBuf = (PVMSVGACMDBUF)RTMemAllocZ(sizeof(*pCmdBuf));
3012 if (pCmdBuf)
3013 {
3014 // RT_ZERO(pCmdBuf->nodeBuffer);
3015 pCmdBuf->pCmdBufCtx = pCmdBufCtx;
3016 // pCmdBuf->GCPhysCB = 0;
3017 // RT_ZERO(pCmdBuf->hdr);
3018 // pCmdBuf->pvCommands = NULL;
3019 }
3020
3021 return pCmdBuf;
3022}
3023
3024
3025/** Free a command buffer structure.
3026 *
3027 * @param pCmdBuf The command buffer pointer.
3028 */
3029static void vmsvgaR3CmdBufFree(PVMSVGACMDBUF pCmdBuf)
3030{
3031 if (pCmdBuf)
3032 RTMemFree(pCmdBuf->pvCommands);
3033 RTMemFree(pCmdBuf);
3034}
3035
3036
3037/** Initialize a command buffer context.
3038 *
3039 * @param pCmdBufCtx The command buffer context.
3040 */
3041static void vmsvgaR3CmdBufCtxInit(PVMSVGACMDBUFCTX pCmdBufCtx)
3042{
3043 RTListInit(&pCmdBufCtx->listSubmitted);
3044 pCmdBufCtx->cSubmitted = 0;
3045}
3046
3047
3048/** Destroy a command buffer context.
3049 *
3050 * @param pCmdBufCtx The command buffer context pointer.
3051 */
3052static void vmsvgaR3CmdBufCtxTerm(PVMSVGACMDBUFCTX pCmdBufCtx)
3053{
3054 if (!pCmdBufCtx)
3055 return;
3056
3057 if (pCmdBufCtx->listSubmitted.pNext)
3058 {
3059 /* If the list has been initialized. */
3060 PVMSVGACMDBUF pIter, pNext;
3061 RTListForEachSafe(&pCmdBufCtx->listSubmitted, pIter, pNext, VMSVGACMDBUF, nodeBuffer)
3062 {
3063 RTListNodeRemove(&pIter->nodeBuffer);
3064 --pCmdBufCtx->cSubmitted;
3065 vmsvgaR3CmdBufFree(pIter);
3066 }
3067 }
3068 Assert(pCmdBufCtx->cSubmitted == 0);
3069 pCmdBufCtx->cSubmitted = 0;
3070}
3071
3072
3073/** Handles SVGA_DC_CMD_START_STOP_CONTEXT command.
3074 *
3075 * @param pSvgaR3State VMSVGA R3 state.
3076 * @param pCmd The command data.
3077 * @return SVGACBStatus code.
3078 * @thread EMT
3079 */
3080static SVGACBStatus vmsvgaR3CmdBufDCStartStop(PVMSVGAR3STATE pSvgaR3State, SVGADCCmdStartStop const *pCmd)
3081{
3082 /* Create or destroy a regular command buffer context. */
3083 if (pCmd->context >= RT_ELEMENTS(pSvgaR3State->apCmdBufCtxs))
3084 return SVGA_CB_STATUS_COMMAND_ERROR;
3085 RT_UNTRUSTED_VALIDATED_FENCE();
3086
3087 SVGACBStatus CBStatus = SVGA_CB_STATUS_COMPLETED;
3088
3089 int rc = RTCritSectEnter(&pSvgaR3State->CritSectCmdBuf);
3090 AssertRC(rc);
3091 if (pCmd->enable)
3092 {
3093 pSvgaR3State->apCmdBufCtxs[pCmd->context] = (PVMSVGACMDBUFCTX)RTMemAlloc(sizeof(VMSVGACMDBUFCTX));
3094 if (pSvgaR3State->apCmdBufCtxs[pCmd->context])
3095 vmsvgaR3CmdBufCtxInit(pSvgaR3State->apCmdBufCtxs[pCmd->context]);
3096 else
3097 CBStatus = SVGA_CB_STATUS_QUEUE_FULL;
3098 }
3099 else
3100 {
3101 vmsvgaR3CmdBufCtxTerm(pSvgaR3State->apCmdBufCtxs[pCmd->context]);
3102 pSvgaR3State->apCmdBufCtxs[pCmd->context] = NULL;
3103 }
3104 RTCritSectLeave(&pSvgaR3State->CritSectCmdBuf);
3105
3106 return CBStatus;
3107}
3108
3109
3110/** Handles SVGA_DC_CMD_PREEMPT command.
3111 *
3112 * @param pDevIns The device instance.
3113 * @param pSvgaR3State VMSVGA R3 state.
3114 * @param pCmd The command data.
3115 * @return SVGACBStatus code.
3116 * @thread EMT
3117 */
3118static SVGACBStatus vmsvgaR3CmdBufDCPreempt(PPDMDEVINS pDevIns, PVMSVGAR3STATE pSvgaR3State, SVGADCCmdPreempt const *pCmd)
3119{
3120 /* Remove buffers from the processing queue of the specified context. */
3121 if (pCmd->context >= RT_ELEMENTS(pSvgaR3State->apCmdBufCtxs))
3122 return SVGA_CB_STATUS_COMMAND_ERROR;
3123 RT_UNTRUSTED_VALIDATED_FENCE();
3124
3125 PVMSVGACMDBUFCTX const pCmdBufCtx = pSvgaR3State->apCmdBufCtxs[pCmd->context];
3126 RTLISTANCHOR listPreempted;
3127
3128 int rc = RTCritSectEnter(&pSvgaR3State->CritSectCmdBuf);
3129 AssertRC(rc);
3130 if (pCmd->ignoreIDZero)
3131 {
3132 RTListInit(&listPreempted);
3133
3134 PVMSVGACMDBUF pIter, pNext;
3135 RTListForEachSafe(&pCmdBufCtx->listSubmitted, pIter, pNext, VMSVGACMDBUF, nodeBuffer)
3136 {
3137 if (pIter->hdr.id == 0)
3138 continue;
3139
3140 RTListNodeRemove(&pIter->nodeBuffer);
3141 --pCmdBufCtx->cSubmitted;
3142 RTListAppend(&listPreempted, &pIter->nodeBuffer);
3143 }
3144 }
3145 else
3146 {
3147 RTListMove(&listPreempted, &pCmdBufCtx->listSubmitted);
3148 pCmdBufCtx->cSubmitted = 0;
3149 }
3150 RTCritSectLeave(&pSvgaR3State->CritSectCmdBuf);
3151
3152 PVMSVGACMDBUF pIter, pNext;
3153 RTListForEachSafe(&listPreempted, pIter, pNext, VMSVGACMDBUF, nodeBuffer)
3154 {
3155 RTListNodeRemove(&pIter->nodeBuffer);
3156 vmsvgaR3CmdBufWriteStatus(pDevIns, pIter->GCPhysCB, SVGA_CB_STATUS_PREEMPTED, 0);
3157 LogFunc(("Preempted %RX64\n", pIter->GCPhysCB));
3158 vmsvgaR3CmdBufFree(pIter);
3159 }
3160
3161 return SVGA_CB_STATUS_COMPLETED;
3162}
3163
3164
3165/** @def VMSVGA_INC_CMD_SIZE_BREAK
3166 * Increments the size of the command cbCmd by a_cbMore.
3167 * Checks that the command buffer has at least cbCmd bytes. Will break out of the switch if it doesn't.
3168 * Used by vmsvgaR3CmdBufProcessDC and vmsvgaR3CmdBufProcessCommands.
3169 */
3170#define VMSVGA_INC_CMD_SIZE_BREAK(a_cbMore) \
3171 if (1) { \
3172 cbCmd += (a_cbMore); \
3173 ASSERT_GUEST_MSG_STMT_BREAK(cbRemain >= cbCmd, ("size=%#x remain=%#zx\n", cbCmd, (size_t)cbRemain), CBstatus = SVGA_CB_STATUS_COMMAND_ERROR); \
3174 RT_UNTRUSTED_VALIDATED_FENCE(); \
3175 } else do {} while (0)
3176
3177
3178/** Processes Device Context command buffer.
3179 *
3180 * @param pDevIns The device instance.
3181 * @param pSvgaR3State VMSVGA R3 state.
3182 * @param pvCommands Pointer to the command buffer.
3183 * @param cbCommands Size of the command buffer.
3184 * @param poffNextCmd Where to store the offset of the first unprocessed command.
3185 * @return SVGACBStatus code.
3186 * @thread EMT
3187 */
3188static SVGACBStatus vmsvgaR3CmdBufProcessDC(PPDMDEVINS pDevIns, PVMSVGAR3STATE pSvgaR3State, void const *pvCommands, uint32_t cbCommands, uint32_t *poffNextCmd)
3189{
3190 SVGACBStatus CBstatus = SVGA_CB_STATUS_COMPLETED;
3191
3192 uint8_t const *pu8Cmd = (uint8_t *)pvCommands;
3193 uint32_t cbRemain = cbCommands;
3194 while (cbRemain)
3195 {
3196 /* Command identifier is a 32 bit value. */
3197 if (cbRemain < sizeof(uint32_t))
3198 {
3199 CBstatus = SVGA_CB_STATUS_COMMAND_ERROR;
3200 break;
3201 }
3202
3203 /* Fetch the command id. */
3204 uint32_t const cmdId = *(uint32_t *)pu8Cmd;
3205 uint32_t cbCmd = sizeof(uint32_t);
3206 switch (cmdId)
3207 {
3208 case SVGA_DC_CMD_NOP:
3209 {
3210 /* NOP */
3211 break;
3212 }
3213
3214 case SVGA_DC_CMD_START_STOP_CONTEXT:
3215 {
3216 SVGADCCmdStartStop *pCmd = (SVGADCCmdStartStop *)&pu8Cmd[cbCmd];
3217 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
3218 CBstatus = vmsvgaR3CmdBufDCStartStop(pSvgaR3State, pCmd);
3219 break;
3220 }
3221
3222 case SVGA_DC_CMD_PREEMPT:
3223 {
3224 SVGADCCmdPreempt *pCmd = (SVGADCCmdPreempt *)&pu8Cmd[cbCmd];
3225 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
3226 CBstatus = vmsvgaR3CmdBufDCPreempt(pDevIns, pSvgaR3State, pCmd);
3227 break;
3228 }
3229
3230 default:
3231 {
3232 /* Unsupported command. */
3233 CBstatus = SVGA_CB_STATUS_COMMAND_ERROR;
3234 break;
3235 }
3236 }
3237
3238 if (CBstatus != SVGA_CB_STATUS_COMPLETED)
3239 break;
3240
3241 pu8Cmd += cbCmd;
3242 cbRemain -= cbCmd;
3243 }
3244
3245 Assert(cbRemain <= cbCommands);
3246 *poffNextCmd = cbCommands - cbRemain;
3247 return CBstatus;
3248}
3249
3250
3251/** Submits a device context command buffer for synchronous processing.
3252 *
3253 * @param pDevIns The device instance.
3254 * @param pThisCC The VGA/VMSVGA state for the current context.
3255 * @param ppCmdBuf Pointer to the command buffer pointer.
3256 * The function can set the command buffer pointer to NULL to prevent deallocation by the caller.
3257 * @param poffNextCmd Where to store the offset of the first unprocessed command.
3258 * @return SVGACBStatus code.
3259 * @thread EMT
3260 */
3261static SVGACBStatus vmsvgaR3CmdBufSubmitDC(PPDMDEVINS pDevIns, PVGASTATECC pThisCC, PVMSVGACMDBUF *ppCmdBuf, uint32_t *poffNextCmd)
3262{
3263 /* Synchronously process the device context commands. */
3264 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
3265 return vmsvgaR3CmdBufProcessDC(pDevIns, pSvgaR3State, (*ppCmdBuf)->pvCommands, (*ppCmdBuf)->hdr.length, poffNextCmd);
3266}
3267
3268/** Submits a command buffer for asynchronous processing by the FIFO thread.
3269 *
3270 * @param pDevIns The device instance.
3271 * @param pThis The shared VGA/VMSVGA state.
3272 * @param pThisCC The VGA/VMSVGA state for the current context.
3273 * @param ppCmdBuf Pointer to the command buffer pointer.
3274 * The function can set the command buffer pointer to NULL to prevent deallocation by the caller.
3275 * @return SVGACBStatus code.
3276 * @thread EMT
3277 */
3278static SVGACBStatus vmsvgaR3CmdBufSubmitCtx(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, PVMSVGACMDBUF *ppCmdBuf)
3279{
3280 /* Command buffer submission. */
3281 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
3282
3283 SVGACBStatus CBstatus = SVGA_CB_STATUS_NONE;
3284
3285 PVMSVGACMDBUF const pCmdBuf = *ppCmdBuf;
3286 PVMSVGACMDBUFCTX const pCmdBufCtx = pCmdBuf->pCmdBufCtx;
3287
3288 int rc = RTCritSectEnter(&pSvgaR3State->CritSectCmdBuf);
3289 AssertRC(rc);
3290
3291 if (RT_LIKELY(pCmdBufCtx->cSubmitted < SVGA_CB_MAX_QUEUED_PER_CONTEXT))
3292 {
3293 RTListAppend(&pCmdBufCtx->listSubmitted, &pCmdBuf->nodeBuffer);
3294 ++pCmdBufCtx->cSubmitted;
3295 *ppCmdBuf = NULL; /* Consume the buffer. */
3296 ASMAtomicWriteU32(&pThisCC->svga.pSvgaR3State->fCmdBuf, 1);
3297 }
3298 else
3299 CBstatus = SVGA_CB_STATUS_QUEUE_FULL;
3300
3301 RTCritSectLeave(&pSvgaR3State->CritSectCmdBuf);
3302
3303 /* Inform the FIFO thread. */
3304 if (*ppCmdBuf == NULL)
3305 PDMDevHlpSUPSemEventSignal(pDevIns, pThis->svga.hFIFORequestSem);
3306
3307 return CBstatus;
3308}
3309
3310
3311/** SVGA_REG_COMMAND_LOW write handler.
3312 * Submits a command buffer to the FIFO thread or processes a device context command.
3313 *
3314 * @param pDevIns The device instance.
3315 * @param pThis The shared VGA/VMSVGA state.
3316 * @param pThisCC The VGA/VMSVGA state for the current context.
3317 * @param GCPhysCB Guest physical address of the command buffer header.
3318 * @param CBCtx Context the command buffer is submitted to.
3319 * @thread EMT
3320 */
3321static void vmsvgaR3CmdBufSubmit(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, RTGCPHYS GCPhysCB, SVGACBContext CBCtx)
3322{
3323 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
3324
3325 SVGACBStatus CBstatus = SVGA_CB_STATUS_NONE;
3326 uint32_t offNextCmd = 0;
3327 uint32_t fIRQ = 0;
3328
3329 /* Get the context if the device has the capability. */
3330 PVMSVGACMDBUFCTX pCmdBufCtx = NULL;
3331 if (pThis->svga.u32DeviceCaps & SVGA_CAP_COMMAND_BUFFERS)
3332 {
3333 if (RT_LIKELY(CBCtx < RT_ELEMENTS(pSvgaR3State->apCmdBufCtxs)))
3334 pCmdBufCtx = pSvgaR3State->apCmdBufCtxs[CBCtx];
3335 else if (CBCtx == SVGA_CB_CONTEXT_DEVICE)
3336 pCmdBufCtx = &pSvgaR3State->CmdBufCtxDC;
3337 RT_UNTRUSTED_VALIDATED_FENCE();
3338 }
3339
3340 /* Allocate a new command buffer. */
3341 PVMSVGACMDBUF pCmdBuf = vmsvgaR3CmdBufAlloc(pCmdBufCtx);
3342 if (RT_LIKELY(pCmdBuf))
3343 {
3344 pCmdBuf->GCPhysCB = GCPhysCB;
3345
3346 int rc = PDMDevHlpPCIPhysRead(pDevIns, GCPhysCB, &pCmdBuf->hdr, sizeof(pCmdBuf->hdr));
3347 if (RT_SUCCESS(rc))
3348 {
3349 LogFunc(("status %RX32 errorOffset %RX32 id %RX64 flags %RX32 length %RX32 ptr %RX64 offset %RX32 dxContext %RX32 (%RX32 %RX32 %RX32 %RX32 %RX32 %RX32)\n",
3350 pCmdBuf->hdr.status,
3351 pCmdBuf->hdr.errorOffset,
3352 pCmdBuf->hdr.id,
3353 pCmdBuf->hdr.flags,
3354 pCmdBuf->hdr.length,
3355 pCmdBuf->hdr.ptr.pa,
3356 pCmdBuf->hdr.offset,
3357 pCmdBuf->hdr.dxContext,
3358 pCmdBuf->hdr.mustBeZero[0],
3359 pCmdBuf->hdr.mustBeZero[1],
3360 pCmdBuf->hdr.mustBeZero[2],
3361 pCmdBuf->hdr.mustBeZero[3],
3362 pCmdBuf->hdr.mustBeZero[4],
3363 pCmdBuf->hdr.mustBeZero[5]));
3364
3365 /* Verify the command buffer header. */
3366 if (RT_LIKELY( pCmdBuf->hdr.status == SVGA_CB_STATUS_NONE
3367 && (pCmdBuf->hdr.flags & ~(SVGA_CB_FLAG_NO_IRQ | SVGA_CB_FLAG_DX_CONTEXT)) == 0 /* No unexpected flags. */
3368 && pCmdBuf->hdr.length <= SVGA_CB_MAX_SIZE))
3369 {
3370 RT_UNTRUSTED_VALIDATED_FENCE();
3371
3372 /* Read the command buffer content. */
3373 pCmdBuf->pvCommands = RTMemAlloc(pCmdBuf->hdr.length);
3374 if (pCmdBuf->pvCommands)
3375 {
3376 RTGCPHYS const GCPhysCmd = (RTGCPHYS)pCmdBuf->hdr.ptr.pa;
3377 rc = PDMDevHlpPCIPhysRead(pDevIns, GCPhysCmd, pCmdBuf->pvCommands, pCmdBuf->hdr.length);
3378 if (RT_SUCCESS(rc))
3379 {
3380 /* Submit the buffer. Device context buffers will be processed synchronously. */
3381 if (RT_LIKELY(CBCtx < RT_ELEMENTS(pSvgaR3State->apCmdBufCtxs)))
3382 /* This usually processes the CB async and sets pCmbBuf to NULL. */
3383 CBstatus = vmsvgaR3CmdBufSubmitCtx(pDevIns, pThis, pThisCC, &pCmdBuf);
3384 else
3385 CBstatus = vmsvgaR3CmdBufSubmitDC(pDevIns, pThisCC, &pCmdBuf, &offNextCmd);
3386 }
3387 else
3388 {
3389 ASSERT_GUEST_MSG_FAILED(("Failed to read commands at %RGp\n", GCPhysCmd));
3390 CBstatus = SVGA_CB_STATUS_CB_HEADER_ERROR;
3391 fIRQ = SVGA_IRQFLAG_ERROR | SVGA_IRQFLAG_COMMAND_BUFFER;
3392 }
3393 }
3394 else
3395 {
3396 /* No memory for commands. */
3397 CBstatus = SVGA_CB_STATUS_QUEUE_FULL;
3398 }
3399 }
3400 else
3401 {
3402 ASSERT_GUEST_MSG_FAILED(("Invalid buffer header\n"));
3403 CBstatus = SVGA_CB_STATUS_CB_HEADER_ERROR;
3404 fIRQ = SVGA_IRQFLAG_ERROR | SVGA_IRQFLAG_COMMAND_BUFFER;
3405 }
3406 }
3407 else
3408 {
3409 LogFunc(("Failed to read buffer header at %RGp\n", GCPhysCB));
3410 ASSERT_GUEST_FAILED();
3411 /* Do not attempt to write the status. */
3412 }
3413
3414 /* Free the buffer if pfnCmdBufSubmit did not consume it. */
3415 vmsvgaR3CmdBufFree(pCmdBuf);
3416 }
3417 else
3418 {
3419 LogFunc(("Can't allocate buffer for context id %#x\n", CBCtx));
3420 AssertFailed();
3421 CBstatus = SVGA_CB_STATUS_QUEUE_FULL;
3422 }
3423
3424 if (CBstatus != SVGA_CB_STATUS_NONE)
3425 {
3426 LogFunc(("Write status %#x, offNextCmd %#x, fIRQ %#x\n", CBstatus, offNextCmd, fIRQ));
3427 vmsvgaR3CmdBufWriteStatus(pDevIns, GCPhysCB, CBstatus, offNextCmd);
3428 if (fIRQ)
3429 vmsvgaR3CmdBufRaiseIRQ(pDevIns, pThis, fIRQ);
3430 }
3431}
3432
3433
3434/** Checks if there are some buffers to be processed.
3435 *
3436 * @param pThisCC The VGA/VMSVGA state for the current context.
3437 * @return true if buffers must be processed.
3438 * @thread FIFO
3439 */
3440static bool vmsvgaR3CmdBufHasWork(PVGASTATECC pThisCC)
3441{
3442 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
3443 return RT_BOOL(ASMAtomicReadU32(&pSvgaR3State->fCmdBuf));
3444}
3445
3446
3447/** Processes a command buffer.
3448 *
3449 * @param pDevIns The device instance.
3450 * @param pThis The shared VGA/VMSVGA state.
3451 * @param pThisCC The VGA/VMSVGA state for the current context.
3452 * @param idDXContext VGPU10 DX context of the commands or SVGA3D_INVALID_ID if they are not for a specific context.
3453 * @param pvCommands Pointer to the command buffer.
3454 * @param cbCommands Size of the command buffer.
3455 * @param poffNextCmd Where to store the offset of the first unprocessed command.
3456 * @param pu32IrqStatus Where to store SVGA_IRQFLAG_ if the IRQ is generated by the last command in the buffer.
3457 * @return SVGACBStatus code.
3458 * @thread FIFO
3459 */
3460static SVGACBStatus vmsvgaR3CmdBufProcessCommands(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, uint32_t idDXContext, void const *pvCommands, uint32_t cbCommands, uint32_t *poffNextCmd, uint32_t *pu32IrqStatus)
3461{
3462# ifndef VBOX_WITH_VMSVGA3D
3463 RT_NOREF(idDXContext);
3464# endif
3465 SVGACBStatus CBstatus = SVGA_CB_STATUS_COMPLETED;
3466 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
3467
3468# ifdef VBOX_WITH_VMSVGA3D
3469# ifdef VMSVGA3D_DX
3470 /* Commands submitted for the SVGA3D_INVALID_ID context do not affect pipeline. So ignore them. */
3471 if (idDXContext != SVGA3D_INVALID_ID)
3472 {
3473 if (pSvgaR3State->idDXContextCurrent != idDXContext)
3474 {
3475 LogFlow(("DXCTX: buffer %d->%d\n", pSvgaR3State->idDXContextCurrent, idDXContext));
3476 vmsvga3dDXSwitchContext(pThisCC, idDXContext);
3477 pSvgaR3State->idDXContextCurrent = idDXContext;
3478 }
3479 }
3480# endif
3481# endif
3482
3483 uint32_t RT_UNTRUSTED_VOLATILE_GUEST * const pFIFO = pThisCC->svga.pau32FIFO;
3484
3485 uint8_t const *pu8Cmd = (uint8_t *)pvCommands;
3486 uint32_t cbRemain = cbCommands;
3487 while (cbRemain)
3488 {
3489 /* Command identifier is a 32 bit value. */
3490 if (cbRemain < sizeof(uint32_t))
3491 {
3492 CBstatus = SVGA_CB_STATUS_COMMAND_ERROR;
3493 break;
3494 }
3495
3496 /* Fetch the command id.
3497 * 'cmdId' is actually a SVGAFifoCmdId. It is treated as uint32_t in order to avoid a compiler
3498 * warning. Because we support some obsolete and deprecated commands, which are not included in
3499 * the SVGAFifoCmdId enum in the VMSVGA headers anymore.
3500 */
3501 uint32_t const cmdId = *(uint32_t *)pu8Cmd;
3502 uint32_t cbCmd = sizeof(uint32_t);
3503
3504 LogFunc(("[cid=%d] %s %d\n", (int32_t)idDXContext, vmsvgaR3FifoCmdToString(cmdId), cmdId));
3505# ifdef LOG_ENABLED
3506# ifdef VBOX_WITH_VMSVGA3D
3507 if (SVGA_3D_CMD_BASE <= cmdId && cmdId < SVGA_3D_CMD_MAX)
3508 {
3509 SVGA3dCmdHeader const *header = (SVGA3dCmdHeader *)pu8Cmd;
3510 svga_dump_command(cmdId, (uint8_t *)&header[1], header->size);
3511 }
3512 else if (cmdId == SVGA_CMD_FENCE)
3513 {
3514 Log7(("\tSVGA_CMD_FENCE\n"));
3515 Log7(("\t\t0x%08x\n", ((uint32_t *)pu8Cmd)[1]));
3516 }
3517# endif
3518# endif
3519
3520 /* At the end of the switch cbCmd is equal to the total length of the command including the cmdId.
3521 * I.e. pu8Cmd + cbCmd must point to the next command.
3522 * However if CBstatus is set to anything but SVGA_CB_STATUS_COMPLETED in the switch, then
3523 * the cbCmd value is ignored (and pu8Cmd still points to the failed command).
3524 */
3525 /** @todo This code is very similar to the FIFO loop command processing. Think about merging. */
3526 switch (cmdId)
3527 {
3528 case SVGA_CMD_INVALID_CMD:
3529 {
3530 /* Nothing to do. */
3531 STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdInvalidCmd);
3532 break;
3533 }
3534
3535 case SVGA_CMD_FENCE:
3536 {
3537 SVGAFifoCmdFence *pCmd = (SVGAFifoCmdFence *)&pu8Cmd[cbCmd];
3538 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
3539 STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdFence);
3540 Log(("SVGA_CMD_FENCE %#x\n", pCmd->fence));
3541
3542 uint32_t const offFifoMin = pFIFO[SVGA_FIFO_MIN];
3543 if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_FENCE, offFifoMin))
3544 {
3545 pFIFO[SVGA_FIFO_FENCE] = pCmd->fence;
3546
3547 if (pThis->svga.u32IrqMask & SVGA_IRQFLAG_ANY_FENCE)
3548 {
3549 Log(("any fence irq\n"));
3550 *pu32IrqStatus |= SVGA_IRQFLAG_ANY_FENCE;
3551 }
3552 else if ( VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_FENCE_GOAL, offFifoMin)
3553 && (pThis->svga.u32IrqMask & SVGA_IRQFLAG_FENCE_GOAL)
3554 && pFIFO[SVGA_FIFO_FENCE_GOAL] == pCmd->fence)
3555 {
3556 Log(("fence goal reached irq (fence=%#x)\n", pCmd->fence));
3557 *pu32IrqStatus |= SVGA_IRQFLAG_FENCE_GOAL;
3558 }
3559 }
3560 else
3561 Log(("SVGA_CMD_FENCE is bogus when offFifoMin is %#x!\n", offFifoMin));
3562 break;
3563 }
3564
3565 case SVGA_CMD_UPDATE:
3566 {
3567 SVGAFifoCmdUpdate *pCmd = (SVGAFifoCmdUpdate *)&pu8Cmd[cbCmd];
3568 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
3569 vmsvgaR3CmdUpdate(pThis, pThisCC, pCmd);
3570 break;
3571 }
3572
3573 case SVGA_CMD_UPDATE_VERBOSE:
3574 {
3575 SVGAFifoCmdUpdateVerbose *pCmd = (SVGAFifoCmdUpdateVerbose *)&pu8Cmd[cbCmd];
3576 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
3577 vmsvgaR3CmdUpdateVerbose(pThis, pThisCC, pCmd);
3578 break;
3579 }
3580
3581 case SVGA_CMD_DEFINE_CURSOR:
3582 {
3583 /* Followed by bitmap data. */
3584 SVGAFifoCmdDefineCursor *pCmd = (SVGAFifoCmdDefineCursor *)&pu8Cmd[cbCmd];
3585 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
3586
3587 /* Figure out the size of the bitmap data. */
3588 ASSERT_GUEST_STMT_BREAK(pCmd->height < 2048 && pCmd->width < 2048, CBstatus = SVGA_CB_STATUS_COMMAND_ERROR);
3589 ASSERT_GUEST_STMT_BREAK(pCmd->andMaskDepth <= 32, CBstatus = SVGA_CB_STATUS_COMMAND_ERROR);
3590 ASSERT_GUEST_STMT_BREAK(pCmd->xorMaskDepth <= 32, CBstatus = SVGA_CB_STATUS_COMMAND_ERROR);
3591 RT_UNTRUSTED_VALIDATED_FENCE();
3592
3593 uint32_t const cbAndLine = RT_ALIGN_32(pCmd->width * (pCmd->andMaskDepth + (pCmd->andMaskDepth == 15)), 32) / 8;
3594 uint32_t const cbAndMask = cbAndLine * pCmd->height;
3595 uint32_t const cbXorLine = RT_ALIGN_32(pCmd->width * (pCmd->xorMaskDepth + (pCmd->xorMaskDepth == 15)), 32) / 8;
3596 uint32_t const cbXorMask = cbXorLine * pCmd->height;
3597
3598 VMSVGA_INC_CMD_SIZE_BREAK(cbAndMask + cbXorMask);
3599 vmsvgaR3CmdDefineCursor(pThis, pThisCC, pCmd);
3600 break;
3601 }
3602
3603 case SVGA_CMD_DEFINE_ALPHA_CURSOR:
3604 {
3605 /* Followed by bitmap data. */
3606 SVGAFifoCmdDefineAlphaCursor *pCmd = (SVGAFifoCmdDefineAlphaCursor *)&pu8Cmd[cbCmd];
3607 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
3608
3609 /* Figure out the size of the bitmap data. */
3610 ASSERT_GUEST_STMT_BREAK(pCmd->height < 2048 && pCmd->width < 2048, CBstatus = SVGA_CB_STATUS_COMMAND_ERROR);
3611
3612 VMSVGA_INC_CMD_SIZE_BREAK(pCmd->width * pCmd->height * sizeof(uint32_t)); /* 32-bit BRGA format */
3613 vmsvgaR3CmdDefineAlphaCursor(pThis, pThisCC, pCmd);
3614 break;
3615 }
3616
3617 case SVGA_CMD_MOVE_CURSOR:
3618 {
3619 /* Deprecated; there should be no driver which *requires* this command. However, if
3620 * we do ecncounter this command, it might be useful to not get the FIFO completely out of
3621 * alignment.
3622 * May be issued by guest if SVGA_CAP_CURSOR_BYPASS is missing.
3623 */
3624 SVGAFifoCmdMoveCursor *pCmd = (SVGAFifoCmdMoveCursor *)&pu8Cmd[cbCmd];
3625 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
3626 vmsvgaR3CmdMoveCursor(pThis, pThisCC, pCmd);
3627 break;
3628 }
3629
3630 case SVGA_CMD_DISPLAY_CURSOR:
3631 {
3632 /* Deprecated; there should be no driver which *requires* this command. However, if
3633 * we do ecncounter this command, it might be useful to not get the FIFO completely out of
3634 * alignment.
3635 * May be issued by guest if SVGA_CAP_CURSOR_BYPASS is missing.
3636 */
3637 SVGAFifoCmdDisplayCursor *pCmd = (SVGAFifoCmdDisplayCursor *)&pu8Cmd[cbCmd];
3638 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
3639 vmsvgaR3CmdDisplayCursor(pThis, pThisCC, pCmd);
3640 break;
3641 }
3642
3643 case SVGA_CMD_RECT_FILL:
3644 {
3645 SVGAFifoCmdRectFill *pCmd = (SVGAFifoCmdRectFill *)&pu8Cmd[cbCmd];
3646 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
3647 vmsvgaR3CmdRectFill(pThis, pThisCC, pCmd);
3648 break;
3649 }
3650
3651 case SVGA_CMD_RECT_COPY:
3652 {
3653 SVGAFifoCmdRectCopy *pCmd = (SVGAFifoCmdRectCopy *)&pu8Cmd[cbCmd];
3654 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
3655 vmsvgaR3CmdRectCopy(pThis, pThisCC, pCmd);
3656 break;
3657 }
3658
3659 case SVGA_CMD_RECT_ROP_COPY:
3660 {
3661 SVGAFifoCmdRectRopCopy *pCmd = (SVGAFifoCmdRectRopCopy *)&pu8Cmd[cbCmd];
3662 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
3663 vmsvgaR3CmdRectRopCopy(pThis, pThisCC, pCmd);
3664 break;
3665 }
3666
3667 case SVGA_CMD_ESCAPE:
3668 {
3669 /* Followed by 'size' bytes of data. */
3670 SVGAFifoCmdEscape *pCmd = (SVGAFifoCmdEscape *)&pu8Cmd[cbCmd];
3671 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
3672
3673 ASSERT_GUEST_STMT_BREAK(pCmd->size < pThis->svga.cbFIFO - sizeof(SVGAFifoCmdEscape), CBstatus = SVGA_CB_STATUS_COMMAND_ERROR);
3674 RT_UNTRUSTED_VALIDATED_FENCE();
3675
3676 VMSVGA_INC_CMD_SIZE_BREAK(pCmd->size);
3677 vmsvgaR3CmdEscape(pThis, pThisCC, pCmd);
3678 break;
3679 }
3680# ifdef VBOX_WITH_VMSVGA3D
3681 case SVGA_CMD_DEFINE_GMR2:
3682 {
3683 SVGAFifoCmdDefineGMR2 *pCmd = (SVGAFifoCmdDefineGMR2 *)&pu8Cmd[cbCmd];
3684 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
3685 vmsvgaR3CmdDefineGMR2(pThis, pThisCC, pCmd);
3686 break;
3687 }
3688
3689 case SVGA_CMD_REMAP_GMR2:
3690 {
3691 /* Followed by page descriptors or guest ptr. */
3692 SVGAFifoCmdRemapGMR2 *pCmd = (SVGAFifoCmdRemapGMR2 *)&pu8Cmd[cbCmd];
3693 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
3694
3695 /* Calculate the size of what comes after next and fetch it. */
3696 uint32_t cbMore = 0;
3697 if (pCmd->flags & SVGA_REMAP_GMR2_VIA_GMR)
3698 cbMore = sizeof(SVGAGuestPtr);
3699 else
3700 {
3701 uint32_t const cbPageDesc = (pCmd->flags & SVGA_REMAP_GMR2_PPN64) ? sizeof(uint64_t) : sizeof(uint32_t);
3702 if (pCmd->flags & SVGA_REMAP_GMR2_SINGLE_PPN)
3703 {
3704 cbMore = cbPageDesc;
3705 pCmd->numPages = 1;
3706 }
3707 else
3708 {
3709 ASSERT_GUEST_STMT_BREAK(pCmd->numPages <= pThis->svga.cbFIFO / cbPageDesc, CBstatus = SVGA_CB_STATUS_COMMAND_ERROR);
3710 cbMore = cbPageDesc * pCmd->numPages;
3711 }
3712 }
3713 VMSVGA_INC_CMD_SIZE_BREAK(cbMore);
3714 vmsvgaR3CmdRemapGMR2(pThis, pThisCC, pCmd);
3715# ifdef DEBUG_GMR_ACCESS
3716 VMR3ReqCallWaitU(PDMDevHlpGetUVM(pDevIns), VMCPUID_ANY, (PFNRT)vmsvgaR3RegisterGmr, 2, pDevIns, pCmd->gmrId);
3717# endif
3718 break;
3719 }
3720# endif /* VBOX_WITH_VMSVGA3D */
3721 case SVGA_CMD_DEFINE_SCREEN:
3722 {
3723 /* The size of this command is specified by the guest and depends on capabilities. */
3724 SVGAFifoCmdDefineScreen *pCmd = (SVGAFifoCmdDefineScreen *)&pu8Cmd[cbCmd];
3725 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(pCmd->screen.structSize));
3726 ASSERT_GUEST_STMT_BREAK(pCmd->screen.structSize < pThis->svga.cbFIFO, CBstatus = SVGA_CB_STATUS_COMMAND_ERROR);
3727 RT_UNTRUSTED_VALIDATED_FENCE();
3728
3729 VMSVGA_INC_CMD_SIZE_BREAK(RT_MAX(sizeof(pCmd->screen.structSize), pCmd->screen.structSize) - sizeof(pCmd->screen.structSize));
3730 vmsvgaR3CmdDefineScreen(pThis, pThisCC, pCmd);
3731 break;
3732 }
3733
3734 case SVGA_CMD_DESTROY_SCREEN:
3735 {
3736 SVGAFifoCmdDestroyScreen *pCmd = (SVGAFifoCmdDestroyScreen *)&pu8Cmd[cbCmd];
3737 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
3738 vmsvgaR3CmdDestroyScreen(pThis, pThisCC, pCmd);
3739 break;
3740 }
3741
3742 case SVGA_CMD_DEFINE_GMRFB:
3743 {
3744 SVGAFifoCmdDefineGMRFB *pCmd = (SVGAFifoCmdDefineGMRFB *)&pu8Cmd[cbCmd];
3745 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
3746 vmsvgaR3CmdDefineGMRFB(pThis, pThisCC, pCmd);
3747 break;
3748 }
3749
3750 case SVGA_CMD_BLIT_GMRFB_TO_SCREEN:
3751 {
3752 SVGAFifoCmdBlitGMRFBToScreen *pCmd = (SVGAFifoCmdBlitGMRFBToScreen *)&pu8Cmd[cbCmd];
3753 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
3754 vmsvgaR3CmdBlitGMRFBToScreen(pThis, pThisCC, pCmd);
3755 break;
3756 }
3757
3758 case SVGA_CMD_BLIT_SCREEN_TO_GMRFB:
3759 {
3760 SVGAFifoCmdBlitScreenToGMRFB *pCmd = (SVGAFifoCmdBlitScreenToGMRFB *)&pu8Cmd[cbCmd];
3761 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
3762 vmsvgaR3CmdBlitScreenToGMRFB(pThis, pThisCC, pCmd);
3763 break;
3764 }
3765
3766 case SVGA_CMD_ANNOTATION_FILL:
3767 {
3768 SVGAFifoCmdAnnotationFill *pCmd = (SVGAFifoCmdAnnotationFill *)&pu8Cmd[cbCmd];
3769 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
3770 vmsvgaR3CmdAnnotationFill(pThis, pThisCC, pCmd);
3771 break;
3772 }
3773
3774 case SVGA_CMD_ANNOTATION_COPY:
3775 {
3776 SVGAFifoCmdAnnotationCopy *pCmd = (SVGAFifoCmdAnnotationCopy *)&pu8Cmd[cbCmd];
3777 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
3778 vmsvgaR3CmdAnnotationCopy(pThis, pThisCC, pCmd);
3779 break;
3780 }
3781
3782 default:
3783 {
3784# ifdef VBOX_WITH_VMSVGA3D
3785 if ( cmdId >= SVGA_3D_CMD_BASE
3786 && cmdId < SVGA_3D_CMD_MAX)
3787 {
3788 RT_UNTRUSTED_VALIDATED_FENCE();
3789
3790 /* All 3d commands start with a common header, which defines the identifier and the size
3791 * of the command. The identifier has been already read. Fetch the size.
3792 */
3793 uint32_t const *pcbMore = (uint32_t const *)&pu8Cmd[cbCmd];
3794 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pcbMore));
3795 VMSVGA_INC_CMD_SIZE_BREAK(*pcbMore);
3796 if (RT_LIKELY(pThis->svga.f3DEnabled))
3797 { /* likely */ }
3798 else
3799 {
3800 LogRelMax(8, ("VMSVGA: 3D disabled, command %d skipped\n", cmdId));
3801 break;
3802 }
3803
3804 /* Command data begins after the 32 bit command length. */
3805 int rc = vmsvgaR3Process3dCmd(pThis, pThisCC, idDXContext, (SVGAFifo3dCmdId)cmdId, *pcbMore, pcbMore + 1);
3806 if (RT_SUCCESS(rc))
3807 { /* likely */ }
3808 else
3809 {
3810 CBstatus = SVGA_CB_STATUS_COMMAND_ERROR;
3811 break;
3812 }
3813 }
3814 else
3815# endif /* VBOX_WITH_VMSVGA3D */
3816 {
3817 /* Unsupported command. */
3818 STAM_REL_COUNTER_INC(&pSvgaR3State->StatFifoUnkCmds);
3819 ASSERT_GUEST_MSG_FAILED(("cmdId=%d\n", cmdId));
3820 LogRelMax(16, ("VMSVGA: unsupported command %d\n", cmdId));
3821 CBstatus = SVGA_CB_STATUS_COMMAND_ERROR;
3822 break;
3823 }
3824 }
3825 }
3826
3827 if (CBstatus != SVGA_CB_STATUS_COMPLETED)
3828 break;
3829
3830 pu8Cmd += cbCmd;
3831 cbRemain -= cbCmd;
3832
3833 /* If this is not the last command in the buffer, then generate IRQ, if required.
3834 * This avoids a double call to vmsvgaR3CmdBufRaiseIRQ if FENCE is the last command
3835 * in the buffer (usually the case).
3836 */
3837 if (RT_LIKELY(!(cbRemain && *pu32IrqStatus)))
3838 { /* likely */ }
3839 else
3840 {
3841 vmsvgaR3CmdBufRaiseIRQ(pDevIns, pThis, *pu32IrqStatus);
3842 *pu32IrqStatus = 0;
3843 }
3844 }
3845
3846 Assert(cbRemain <= cbCommands);
3847 *poffNextCmd = cbCommands - cbRemain;
3848 return CBstatus;
3849}
3850
3851
3852/** Process command buffers.
3853 *
3854 * @param pDevIns The device instance.
3855 * @param pThis The shared VGA/VMSVGA state.
3856 * @param pThisCC The VGA/VMSVGA state for the current context.
3857 * @param pThread Handle of the FIFO thread.
3858 * @thread FIFO
3859 */
3860static void vmsvgaR3CmdBufProcessBuffers(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, PPDMTHREAD pThread)
3861{
3862 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
3863
3864 for (;;)
3865 {
3866 if (pThread->enmState != PDMTHREADSTATE_RUNNING)
3867 break;
3868
3869 /* See if there is a submitted buffer. */
3870 PVMSVGACMDBUF pCmdBuf = NULL;
3871
3872 int rc = RTCritSectEnter(&pSvgaR3State->CritSectCmdBuf);
3873 AssertRC(rc);
3874
3875 /* It seems that a higher queue index has a higher priority.
3876 * See SVGACBContext in svga_reg.h from latest vmwgfx Linux driver.
3877 */
3878 for (unsigned i = RT_ELEMENTS(pSvgaR3State->apCmdBufCtxs); i > 0; --i)
3879 {
3880 PVMSVGACMDBUFCTX pCmdBufCtx = pSvgaR3State->apCmdBufCtxs[i - 1];
3881 if (pCmdBufCtx)
3882 {
3883 pCmdBuf = RTListRemoveFirst(&pCmdBufCtx->listSubmitted, VMSVGACMDBUF, nodeBuffer);
3884 if (pCmdBuf)
3885 {
3886 Assert(pCmdBufCtx->cSubmitted > 0);
3887 --pCmdBufCtx->cSubmitted;
3888 break;
3889 }
3890 }
3891 }
3892
3893 if (!pCmdBuf)
3894 {
3895 ASMAtomicWriteU32(&pSvgaR3State->fCmdBuf, 0);
3896 RTCritSectLeave(&pSvgaR3State->CritSectCmdBuf);
3897 break;
3898 }
3899
3900 RTCritSectLeave(&pSvgaR3State->CritSectCmdBuf);
3901
3902 SVGACBStatus CBstatus = SVGA_CB_STATUS_NONE;
3903 uint32_t offNextCmd = 0;
3904 uint32_t u32IrqStatus = 0;
3905 uint32_t const idDXContext = RT_BOOL(pCmdBuf->hdr.flags & SVGA_CB_FLAG_DX_CONTEXT)
3906 ? pCmdBuf->hdr.dxContext
3907 : SVGA3D_INVALID_ID;
3908 /* Process one buffer. */
3909 CBstatus = vmsvgaR3CmdBufProcessCommands(pDevIns, pThis, pThisCC, idDXContext, pCmdBuf->pvCommands, pCmdBuf->hdr.length, &offNextCmd, &u32IrqStatus);
3910
3911 if (!RT_BOOL(pCmdBuf->hdr.flags & SVGA_CB_FLAG_NO_IRQ))
3912 u32IrqStatus |= SVGA_IRQFLAG_COMMAND_BUFFER;
3913 if (CBstatus == SVGA_CB_STATUS_COMMAND_ERROR)
3914 u32IrqStatus |= SVGA_IRQFLAG_ERROR;
3915
3916 vmsvgaR3CmdBufWriteStatus(pDevIns, pCmdBuf->GCPhysCB, CBstatus, offNextCmd);
3917 if (u32IrqStatus)
3918 vmsvgaR3CmdBufRaiseIRQ(pDevIns, pThis, u32IrqStatus);
3919
3920 vmsvgaR3CmdBufFree(pCmdBuf);
3921 }
3922}
3923
3924
3925/**
3926 * Worker for vmsvgaR3FifoThread that handles an external command.
3927 *
3928 * @param pDevIns The device instance.
3929 * @param pThis The shared VGA/VMSVGA instance data.
3930 * @param pThisCC The VGA/VMSVGA state for ring-3.
3931 */
3932static void vmsvgaR3FifoHandleExtCmd(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC)
3933{
3934 uint8_t uExtCmd = pThis->svga.u8FIFOExtCommand;
3935 switch (pThis->svga.u8FIFOExtCommand)
3936 {
3937 case VMSVGA_FIFO_EXTCMD_RESET:
3938 Log(("vmsvgaR3FifoLoop: reset the fifo thread.\n"));
3939 Assert(pThisCC->svga.pvFIFOExtCmdParam == NULL);
3940
3941 vmsvgaR3ResetScreens(pThis, pThisCC);
3942# ifdef VBOX_WITH_VMSVGA3D
3943 if (pThis->svga.f3DEnabled)
3944 {
3945 /* The 3d subsystem must be reset from the fifo thread. */
3946 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
3947 pSVGAState->pFuncs3D->pfnReset(pThisCC);
3948 }
3949# endif
3950 break;
3951
3952 case VMSVGA_FIFO_EXTCMD_POWEROFF:
3953 Log(("vmsvgaR3FifoLoop: power off.\n"));
3954 Assert(pThisCC->svga.pvFIFOExtCmdParam == NULL);
3955
3956 /* The screens must be reset on the FIFO thread, because they may use 3D resources. */
3957 vmsvgaR3ResetScreens(pThis, pThisCC);
3958 break;
3959
3960 case VMSVGA_FIFO_EXTCMD_TERMINATE:
3961 Log(("vmsvgaR3FifoLoop: terminate the fifo thread.\n"));
3962 Assert(pThisCC->svga.pvFIFOExtCmdParam == NULL);
3963# ifdef VBOX_WITH_VMSVGA3D
3964 if (pThis->svga.f3DEnabled)
3965 {
3966 /* The 3d subsystem must be shut down from the fifo thread. */
3967 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
3968 if (pSVGAState->pFuncs3D && pSVGAState->pFuncs3D->pfnTerminate)
3969 pSVGAState->pFuncs3D->pfnTerminate(pThisCC);
3970 }
3971# endif
3972 break;
3973
3974 case VMSVGA_FIFO_EXTCMD_SAVESTATE:
3975 {
3976 Log(("vmsvgaR3FifoLoop: VMSVGA_FIFO_EXTCMD_SAVESTATE.\n"));
3977 PSSMHANDLE pSSM = (PSSMHANDLE)pThisCC->svga.pvFIFOExtCmdParam;
3978 AssertLogRelMsgBreak(RT_VALID_PTR(pSSM), ("pSSM=%p\n", pSSM));
3979 vmsvgaR3SaveExecFifo(pDevIns->pHlpR3, pThisCC, pSSM);
3980# ifdef VBOX_WITH_VMSVGA3D
3981 if (pThis->svga.f3DEnabled)
3982 {
3983 if (vmsvga3dIsLegacyBackend(pThisCC))
3984 vmsvga3dSaveExec(pDevIns, pThisCC, pSSM);
3985# ifdef VMSVGA3D_DX
3986 else
3987 vmsvga3dDXSaveExec(pDevIns, pThisCC, pSSM);
3988# endif
3989 }
3990# endif
3991 break;
3992 }
3993
3994 case VMSVGA_FIFO_EXTCMD_LOADSTATE:
3995 {
3996 Log(("vmsvgaR3FifoLoop: VMSVGA_FIFO_EXTCMD_LOADSTATE.\n"));
3997 PVMSVGA_STATE_LOAD pLoadState = (PVMSVGA_STATE_LOAD)pThisCC->svga.pvFIFOExtCmdParam;
3998 AssertLogRelMsgBreak(RT_VALID_PTR(pLoadState), ("pLoadState=%p\n", pLoadState));
3999 vmsvgaR3LoadExecFifo(pDevIns->pHlpR3, pThis, pThisCC, pLoadState->pSSM, pLoadState->uVersion, pLoadState->uPass);
4000# ifdef VBOX_WITH_VMSVGA3D
4001 if (pThis->svga.f3DEnabled)
4002 {
4003 /* The following RT_OS_DARWIN code was in vmsvga3dLoadExec and therefore must be executed before each vmsvga3dLoadExec invocation. */
4004# ifndef 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-SVGA.cpp */
4005 /* Must initialize now as the recreation calls below rely on an initialized 3d subsystem. */
4006 vmsvgaR3PowerOnDevice(pDevIns, pThis, pThisCC, /*fLoadState=*/ true);
4007# endif
4008
4009 if (vmsvga3dIsLegacyBackend(pThisCC))
4010 vmsvga3dLoadExec(pDevIns, pThis, pThisCC, pLoadState->pSSM, pLoadState->uVersion, pLoadState->uPass);
4011# ifdef VMSVGA3D_DX
4012 else
4013 vmsvga3dDXLoadExec(pDevIns, pThis, pThisCC, pLoadState->pSSM, pLoadState->uVersion, pLoadState->uPass);
4014# endif
4015 }
4016# endif
4017 break;
4018 }
4019
4020 case VMSVGA_FIFO_EXTCMD_UPDATE_SURFACE_HEAP_BUFFERS:
4021 {
4022# ifdef VBOX_WITH_VMSVGA3D
4023 uint32_t sid = (uint32_t)(uintptr_t)pThisCC->svga.pvFIFOExtCmdParam;
4024 Log(("vmsvgaR3FifoLoop: VMSVGA_FIFO_EXTCMD_UPDATE_SURFACE_HEAP_BUFFERS sid=%#x\n", sid));
4025 vmsvga3dUpdateHeapBuffersForSurfaces(pThisCC, sid);
4026# endif
4027 break;
4028 }
4029
4030
4031 default:
4032 AssertLogRelMsgFailed(("uExtCmd=%#x pvFIFOExtCmdParam=%p\n", uExtCmd, pThisCC->svga.pvFIFOExtCmdParam));
4033 break;
4034 }
4035
4036 /*
4037 * Signal the end of the external command.
4038 */
4039 pThisCC->svga.pvFIFOExtCmdParam = NULL;
4040 pThis->svga.u8FIFOExtCommand = VMSVGA_FIFO_EXTCMD_NONE;
4041 ASMMemoryFence(); /* paranoia^2 */
4042 int rc = RTSemEventSignal(pThisCC->svga.hFIFOExtCmdSem);
4043 AssertLogRelRC(rc);
4044}
4045
4046/**
4047 * Worker for vmsvgaR3Destruct, vmsvgaR3Reset, vmsvgaR3Save and vmsvgaR3Load for
4048 * doing a job on the FIFO thread (even when it's officially suspended).
4049 *
4050 * @returns VBox status code (fully asserted).
4051 * @param pDevIns The device instance.
4052 * @param pThis The shared VGA/VMSVGA instance data.
4053 * @param pThisCC The VGA/VMSVGA state for ring-3.
4054 * @param uExtCmd The command to execute on the FIFO thread.
4055 * @param pvParam Pointer to command parameters.
4056 * @param cMsWait The time to wait for the command, given in
4057 * milliseconds.
4058 */
4059static int vmsvgaR3RunExtCmdOnFifoThread(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC,
4060 uint8_t uExtCmd, void *pvParam, RTMSINTERVAL cMsWait)
4061{
4062 Assert(cMsWait >= RT_MS_1SEC * 5);
4063 AssertLogRelMsg(pThis->svga.u8FIFOExtCommand == VMSVGA_FIFO_EXTCMD_NONE,
4064 ("old=%d new=%d\n", pThis->svga.u8FIFOExtCommand, uExtCmd));
4065
4066 int rc;
4067 PPDMTHREAD pThread = pThisCC->svga.pFIFOIOThread;
4068 PDMTHREADSTATE enmState = pThread->enmState;
4069 if (enmState == PDMTHREADSTATE_SUSPENDED)
4070 {
4071 /*
4072 * The thread is suspended, we have to temporarily wake it up so it can
4073 * perform the task.
4074 * (We ASSUME not racing code here, both wrt thread state and ext commands.)
4075 */
4076 Log(("vmsvgaR3RunExtCmdOnFifoThread: uExtCmd=%d enmState=SUSPENDED\n", uExtCmd));
4077 /* Post the request. */
4078 pThis->svga.fFifoExtCommandWakeup = true;
4079 pThisCC->svga.pvFIFOExtCmdParam = pvParam;
4080 pThis->svga.u8FIFOExtCommand = uExtCmd;
4081 ASMMemoryFence(); /* paranoia^3 */
4082
4083 /* Resume the thread. */
4084 rc = PDMDevHlpThreadResume(pDevIns, pThread);
4085 AssertLogRelRC(rc);
4086 if (RT_SUCCESS(rc))
4087 {
4088 /* Wait. Take care in case the semaphore was already posted (same as below). */
4089 rc = RTSemEventWait(pThisCC->svga.hFIFOExtCmdSem, cMsWait);
4090 if ( rc == VINF_SUCCESS
4091 && pThis->svga.u8FIFOExtCommand == uExtCmd)
4092 rc = RTSemEventWait(pThisCC->svga.hFIFOExtCmdSem, cMsWait);
4093 AssertLogRelMsg(pThis->svga.u8FIFOExtCommand != uExtCmd || RT_FAILURE_NP(rc),
4094 ("%#x %Rrc\n", pThis->svga.u8FIFOExtCommand, rc));
4095
4096 /* suspend the thread */
4097 pThis->svga.fFifoExtCommandWakeup = false;
4098 int rc2 = PDMDevHlpThreadSuspend(pDevIns, pThread);
4099 AssertLogRelRC(rc2);
4100 if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
4101 rc = rc2;
4102 }
4103 pThis->svga.fFifoExtCommandWakeup = false;
4104 pThisCC->svga.pvFIFOExtCmdParam = NULL;
4105 }
4106 else if (enmState == PDMTHREADSTATE_RUNNING)
4107 {
4108 /*
4109 * The thread is running, should only happen during reset and vmsvga3dsfc.
4110 * We ASSUME not racing code here, both wrt thread state and ext commands.
4111 */
4112 Log(("vmsvgaR3RunExtCmdOnFifoThread: uExtCmd=%d enmState=RUNNING\n", uExtCmd));
4113 Assert(uExtCmd == VMSVGA_FIFO_EXTCMD_RESET || uExtCmd == VMSVGA_FIFO_EXTCMD_UPDATE_SURFACE_HEAP_BUFFERS || uExtCmd == VMSVGA_FIFO_EXTCMD_POWEROFF);
4114
4115 /* Post the request. */
4116 pThisCC->svga.pvFIFOExtCmdParam = pvParam;
4117 pThis->svga.u8FIFOExtCommand = uExtCmd;
4118 ASMMemoryFence(); /* paranoia^2 */
4119 rc = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->svga.hFIFORequestSem);
4120 AssertLogRelRC(rc);
4121
4122 /* Wait. Take care in case the semaphore was already posted (same as above). */
4123 rc = RTSemEventWait(pThisCC->svga.hFIFOExtCmdSem, cMsWait);
4124 if ( rc == VINF_SUCCESS
4125 && pThis->svga.u8FIFOExtCommand == uExtCmd)
4126 rc = RTSemEventWait(pThisCC->svga.hFIFOExtCmdSem, cMsWait); /* it was already posted, retry the wait. */
4127 AssertLogRelMsg(pThis->svga.u8FIFOExtCommand != uExtCmd || RT_FAILURE_NP(rc),
4128 ("%#x %Rrc\n", pThis->svga.u8FIFOExtCommand, rc));
4129
4130 pThisCC->svga.pvFIFOExtCmdParam = NULL;
4131 }
4132 else
4133 {
4134 /*
4135 * Something is wrong with the thread!
4136 */
4137 AssertLogRelMsgFailed(("uExtCmd=%d enmState=%d\n", uExtCmd, enmState));
4138 rc = VERR_INVALID_STATE;
4139 }
4140 return rc;
4141}
4142
4143
4144/**
4145 * Marks the FIFO non-busy, notifying any waiting EMTs.
4146 *
4147 * @param pDevIns The device instance.
4148 * @param pThis The shared VGA/VMSVGA instance data.
4149 * @param pThisCC The VGA/VMSVGA state for ring-3.
4150 * @param pSVGAState Pointer to the ring-3 only SVGA state data.
4151 * @param offFifoMin The start byte offset of the command FIFO.
4152 */
4153static void vmsvgaR3FifoSetNotBusy(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, PVMSVGAR3STATE pSVGAState, uint32_t offFifoMin)
4154{
4155 ASMAtomicAndU32(&pThis->svga.fBusy, ~(VMSVGA_BUSY_F_FIFO | VMSVGA_BUSY_F_EMT_FORCE));
4156 if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_BUSY, offFifoMin))
4157 vmsvgaHCSafeFifoBusyRegUpdate(pThis, pThisCC, pThis->svga.fBusy != 0);
4158
4159 /* Wake up any waiting EMTs. */
4160 if (pSVGAState->cBusyDelayedEmts > 0)
4161 {
4162# ifdef VMSVGA_USE_EMT_HALT_CODE
4163 VMCPUID idCpu = VMCpuSetFindLastPresentInternal(&pSVGAState->BusyDelayedEmts);
4164 if (idCpu != NIL_VMCPUID)
4165 {
4166 PDMDevHlpVMNotifyCpuDeviceReady(pDevIns, idCpu);
4167 while (idCpu-- > 0)
4168 if (VMCPUSET_IS_PRESENT(&pSVGAState->BusyDelayedEmts, idCpu))
4169 PDMDevHlpVMNotifyCpuDeviceReady(pDevIns, idCpu);
4170 }
4171# else
4172 int rc2 = RTSemEventMultiSignal(pSVGAState->hBusyDelayedEmts);
4173 AssertRC(rc2);
4174# endif
4175 }
4176}
4177
4178/**
4179 * Reads (more) payload into the command buffer.
4180 *
4181 * @returns pbBounceBuf on success
4182 * @retval (void *)1 if the thread was requested to stop.
4183 * @retval NULL on FIFO error.
4184 *
4185 * @param cbPayloadReq The number of bytes of payload requested.
4186 * @param pFIFO The FIFO.
4187 * @param offCurrentCmd The FIFO byte offset of the current command.
4188 * @param offFifoMin The start byte offset of the command FIFO.
4189 * @param offFifoMax The end byte offset of the command FIFO.
4190 * @param pbBounceBuf The bounch buffer. Same size as the entire FIFO, so
4191 * always sufficient size.
4192 * @param pcbAlreadyRead How much payload we've already read into the bounce
4193 * buffer. (We will NEVER re-read anything.)
4194 * @param pThread The calling PDM thread handle.
4195 * @param pThis The shared VGA/VMSVGA instance data.
4196 * @param pSVGAState Pointer to the ring-3 only SVGA state data. For
4197 * statistics collection.
4198 * @param pDevIns The device instance.
4199 */
4200static void *vmsvgaR3FifoGetCmdPayload(uint32_t cbPayloadReq, uint32_t RT_UNTRUSTED_VOLATILE_GUEST *pFIFO,
4201 uint32_t offCurrentCmd, uint32_t offFifoMin, uint32_t offFifoMax,
4202 uint8_t *pbBounceBuf, uint32_t *pcbAlreadyRead,
4203 PPDMTHREAD pThread, PVGASTATE pThis, PVMSVGAR3STATE pSVGAState, PPDMDEVINS pDevIns)
4204{
4205 Assert(pbBounceBuf);
4206 Assert(pcbAlreadyRead);
4207 Assert(offFifoMin < offFifoMax);
4208 Assert(offCurrentCmd >= offFifoMin && offCurrentCmd < offFifoMax);
4209 Assert(offFifoMax <= pThis->svga.cbFIFO);
4210
4211 /*
4212 * Check if the requested payload size has already been satisfied .
4213 * .
4214 * When called to read more, the caller is responsible for making sure the .
4215 * new command size (cbRequsted) never is smaller than what has already .
4216 * been read.
4217 */
4218 uint32_t cbAlreadyRead = *pcbAlreadyRead;
4219 if (cbPayloadReq <= cbAlreadyRead)
4220 {
4221 AssertLogRelReturn(cbPayloadReq == cbAlreadyRead, NULL);
4222 return pbBounceBuf;
4223 }
4224
4225 /*
4226 * Commands bigger than the fifo buffer are invalid.
4227 */
4228 uint32_t const cbFifoCmd = offFifoMax - offFifoMin;
4229 AssertMsgReturnStmt(cbPayloadReq <= cbFifoCmd, ("cbPayloadReq=%#x cbFifoCmd=%#x\n", cbPayloadReq, cbFifoCmd),
4230 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoErrors),
4231 NULL);
4232
4233 /*
4234 * Move offCurrentCmd past the command dword.
4235 */
4236 offCurrentCmd += sizeof(uint32_t);
4237 if (offCurrentCmd >= offFifoMax)
4238 offCurrentCmd = offFifoMin;
4239
4240 /*
4241 * Do we have sufficient payload data available already?
4242 * The host should not read beyond [SVGA_FIFO_NEXT_CMD], therefore '>=' in the condition below.
4243 */
4244 uint32_t cbAfter, cbBefore;
4245 uint32_t offNextCmd = pFIFO[SVGA_FIFO_NEXT_CMD];
4246 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
4247 if (offNextCmd >= offCurrentCmd)
4248 {
4249 if (RT_LIKELY(offNextCmd < offFifoMax))
4250 cbAfter = offNextCmd - offCurrentCmd;
4251 else
4252 {
4253 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoErrors);
4254 LogRelMax(16, ("vmsvgaR3FifoGetCmdPayload: Invalid offNextCmd=%#x (offFifoMin=%#x offFifoMax=%#x)\n",
4255 offNextCmd, offFifoMin, offFifoMax));
4256 cbAfter = offFifoMax - offCurrentCmd;
4257 }
4258 cbBefore = 0;
4259 }
4260 else
4261 {
4262 cbAfter = offFifoMax - offCurrentCmd;
4263 if (offNextCmd >= offFifoMin)
4264 cbBefore = offNextCmd - offFifoMin;
4265 else
4266 {
4267 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoErrors);
4268 LogRelMax(16, ("vmsvgaR3FifoGetCmdPayload: Invalid offNextCmd=%#x (offFifoMin=%#x offFifoMax=%#x)\n",
4269 offNextCmd, offFifoMin, offFifoMax));
4270 cbBefore = 0;
4271 }
4272 }
4273 if (cbAfter + cbBefore < cbPayloadReq)
4274 {
4275 /*
4276 * Insufficient, must wait for it to arrive.
4277 */
4278/** @todo Should clear the busy flag here to maybe encourage the guest to wake us up. */
4279 STAM_REL_PROFILE_START(&pSVGAState->StatFifoStalls, Stall);
4280 for (uint32_t i = 0;; i++)
4281 {
4282 if (pThread->enmState != PDMTHREADSTATE_RUNNING)
4283 {
4284 STAM_REL_PROFILE_STOP(&pSVGAState->StatFifoStalls, Stall);
4285 return (void *)(uintptr_t)1;
4286 }
4287 Log(("Guest still copying (%x vs %x) current %x next %x stop %x loop %u; sleep a bit\n",
4288 cbPayloadReq, cbAfter + cbBefore, offCurrentCmd, offNextCmd, pFIFO[SVGA_FIFO_STOP], i));
4289
4290 PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pThis->svga.hFIFORequestSem, i < 16 ? 1 : 2);
4291
4292 offNextCmd = pFIFO[SVGA_FIFO_NEXT_CMD];
4293 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
4294 if (offNextCmd >= offCurrentCmd)
4295 {
4296 cbAfter = RT_MIN(offNextCmd, offFifoMax) - offCurrentCmd;
4297 cbBefore = 0;
4298 }
4299 else
4300 {
4301 cbAfter = offFifoMax - offCurrentCmd;
4302 cbBefore = RT_MAX(offNextCmd, offFifoMin) - offFifoMin;
4303 }
4304
4305 if (cbAfter + cbBefore >= cbPayloadReq)
4306 break;
4307 }
4308 STAM_REL_PROFILE_STOP(&pSVGAState->StatFifoStalls, Stall);
4309 }
4310
4311 /*
4312 * Copy out the memory and update what pcbAlreadyRead points to.
4313 */
4314 if (cbAfter >= cbPayloadReq)
4315 memcpy(pbBounceBuf + cbAlreadyRead,
4316 (uint8_t *)pFIFO + offCurrentCmd + cbAlreadyRead,
4317 cbPayloadReq - cbAlreadyRead);
4318 else
4319 {
4320 LogFlow(("Split data buffer at %x (%u-%u)\n", offCurrentCmd, cbAfter, cbBefore));
4321 if (cbAlreadyRead < cbAfter)
4322 {
4323 memcpy(pbBounceBuf + cbAlreadyRead,
4324 (uint8_t *)pFIFO + offCurrentCmd + cbAlreadyRead,
4325 cbAfter - cbAlreadyRead);
4326 cbAlreadyRead = cbAfter;
4327 }
4328 memcpy(pbBounceBuf + cbAlreadyRead,
4329 (uint8_t *)pFIFO + offFifoMin + cbAlreadyRead - cbAfter,
4330 cbPayloadReq - cbAlreadyRead);
4331 }
4332 *pcbAlreadyRead = cbPayloadReq;
4333 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
4334 return pbBounceBuf;
4335}
4336
4337
4338/**
4339 * Sends cursor position and visibility information from the FIFO to the front-end.
4340 * @returns SVGA_FIFO_CURSOR_COUNT value used.
4341 */
4342static uint32_t
4343vmsvgaR3FifoUpdateCursor(PVGASTATECC pThisCC, PVMSVGAR3STATE pSVGAState, uint32_t RT_UNTRUSTED_VOLATILE_GUEST *pFIFO,
4344 uint32_t offFifoMin, uint32_t uCursorUpdateCount,
4345 uint32_t *pxLast, uint32_t *pyLast, uint32_t *pfLastVisible)
4346{
4347 /*
4348 * Check if the cursor update counter has changed and try get a stable
4349 * set of values if it has. This is race-prone, especially consindering
4350 * the screen ID, but little we can do about that.
4351 */
4352 uint32_t x, y, fVisible, idScreen;
4353 for (uint32_t i = 0; ; i++)
4354 {
4355 x = pFIFO[SVGA_FIFO_CURSOR_X];
4356 y = pFIFO[SVGA_FIFO_CURSOR_Y];
4357 fVisible = pFIFO[SVGA_FIFO_CURSOR_ON];
4358 idScreen = VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_CURSOR_SCREEN_ID, offFifoMin)
4359 ? pFIFO[SVGA_FIFO_CURSOR_SCREEN_ID] : SVGA_ID_INVALID;
4360 if ( uCursorUpdateCount == pFIFO[SVGA_FIFO_CURSOR_COUNT]
4361 || i > 3)
4362 break;
4363 if (i == 0)
4364 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoCursorFetchAgain);
4365 ASMNopPause();
4366 uCursorUpdateCount = pFIFO[SVGA_FIFO_CURSOR_COUNT];
4367 }
4368
4369 /*
4370 * Check if anything has changed, as calling into pDrv is not light-weight.
4371 */
4372 if ( *pxLast == x
4373 && *pyLast == y
4374 && (idScreen != SVGA_ID_INVALID || *pfLastVisible == fVisible))
4375 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoCursorNoChange);
4376 else
4377 {
4378 /*
4379 * Detected changes.
4380 *
4381 * We handle global, not per-screen visibility information by sending
4382 * pfnVBVAMousePointerShape without shape data.
4383 */
4384 *pxLast = x;
4385 *pyLast = y;
4386 uint32_t fFlags = VBVA_CURSOR_VALID_DATA;
4387 if (idScreen != SVGA_ID_INVALID)
4388 fFlags |= VBVA_CURSOR_SCREEN_RELATIVE;
4389 else if (*pfLastVisible != fVisible)
4390 {
4391 LogRel2(("vmsvgaR3FifoUpdateCursor: fVisible %d fLastVisible %d (%d,%d)\n", fVisible, *pfLastVisible, x, y));
4392 *pfLastVisible = fVisible;
4393 pThisCC->pDrv->pfnVBVAMousePointerShape(pThisCC->pDrv, RT_BOOL(fVisible), false, 0, 0, 0, 0, NULL);
4394 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoCursorVisiblity);
4395 }
4396 pThisCC->pDrv->pfnVBVAReportCursorPosition(pThisCC->pDrv, fFlags, idScreen, x, y);
4397 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoCursorPosition);
4398 }
4399
4400 /*
4401 * Update done. Signal this to the guest.
4402 */
4403 pFIFO[SVGA_FIFO_CURSOR_LAST_UPDATED] = uCursorUpdateCount;
4404
4405 return uCursorUpdateCount;
4406}
4407
4408
4409/**
4410 * Checks if there is work to be done, either cursor updating or FIFO commands.
4411 *
4412 * @returns true if pending work, false if not.
4413 * @param pThisCC The VGA/VMSVGA state for ring-3.
4414 * @param uLastCursorCount The last cursor update counter value.
4415 */
4416DECLINLINE(bool) vmsvgaR3FifoHasWork(PVGASTATECC pThisCC, uint32_t uLastCursorCount)
4417{
4418 /* If FIFO does not exist than there is nothing to do. Command buffers also require the enabled FIFO. */
4419 uint32_t RT_UNTRUSTED_VOLATILE_GUEST * const pFIFO = pThisCC->svga.pau32FIFO;
4420 AssertReturn(pFIFO, false);
4421
4422 if (vmsvgaR3CmdBufHasWork(pThisCC))
4423 return true;
4424
4425 if (pFIFO[SVGA_FIFO_NEXT_CMD] != pFIFO[SVGA_FIFO_STOP])
4426 return true;
4427
4428 if ( uLastCursorCount != pFIFO[SVGA_FIFO_CURSOR_COUNT]
4429 && VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_CURSOR_LAST_UPDATED, pFIFO[SVGA_FIFO_MIN]))
4430 return true;
4431
4432 return false;
4433}
4434
4435
4436/**
4437 * Called by the VGA refresh timer to wake up the FIFO thread when needed.
4438 *
4439 * @param pDevIns The device instance.
4440 * @param pThis The shared VGA/VMSVGA instance data.
4441 * @param pThisCC The VGA/VMSVGA state for ring-3.
4442 */
4443void vmsvgaR3FifoWatchdogTimer(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC)
4444{
4445 /* Caller already checked pThis->svga.fFIFOThreadSleeping, so we only have
4446 to recheck it before doing the signalling. */
4447 if ( vmsvgaR3FifoHasWork(pThisCC, ASMAtomicReadU32(&pThis->svga.uLastCursorUpdateCount))
4448 && pThis->svga.fFIFOThreadSleeping
4449 && !ASMAtomicReadBool(&pThis->svga.fBadGuest))
4450 {
4451 int rc = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->svga.hFIFORequestSem);
4452 AssertRC(rc);
4453 STAM_REL_COUNTER_INC(&pThisCC->svga.pSvgaR3State->StatFifoWatchdogWakeUps);
4454 }
4455}
4456
4457
4458/**
4459 * Called by the FIFO thread to process pending actions.
4460 *
4461 * @param pDevIns The device instance.
4462 * @param pThis The shared VGA/VMSVGA instance data.
4463 * @param pThisCC The VGA/VMSVGA state for ring-3.
4464 */
4465void vmsvgaR3FifoPendingActions(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC)
4466{
4467 RT_NOREF(pDevIns);
4468
4469 /* Currently just mode changes. */
4470 if (ASMBitTestAndClear(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE_BIT))
4471 {
4472 vmsvgaR3ChangeMode(pThis, pThisCC);
4473# ifdef VBOX_WITH_VMSVGA3D
4474 if (pThisCC->svga.p3dState != NULL)
4475 vmsvga3dChangeMode(pThisCC);
4476# endif
4477 }
4478}
4479
4480
4481/*
4482 * These two macros are put outside vmsvgaR3FifoLoop because doxygen gets confused,
4483 * even the latest version, and thinks we're documenting vmsvgaR3FifoLoop. Sigh.
4484 */
4485/** @def VMSVGAFIFO_GET_CMD_BUFFER_BREAK
4486 * Macro for shortening calls to vmsvgaR3FifoGetCmdPayload.
4487 *
4488 * Will break out of the switch on failure.
4489 * Will restart and quit the loop if the thread was requested to stop.
4490 *
4491 * @param a_PtrVar Request variable pointer.
4492 * @param a_Type Request typedef (not pointer) for casting.
4493 * @param a_cbPayloadReq How much payload to fetch.
4494 * @remarks Accesses a bunch of variables in the current scope!
4495 */
4496# define VMSVGAFIFO_GET_CMD_BUFFER_BREAK(a_PtrVar, a_Type, a_cbPayloadReq) \
4497 if (1) { \
4498 (a_PtrVar) = (a_Type *)vmsvgaR3FifoGetCmdPayload((a_cbPayloadReq), pFIFO, offCurrentCmd, offFifoMin, offFifoMax, \
4499 pbBounceBuf, &cbPayload, pThread, pThis, pSVGAState, pDevIns); \
4500 if (RT_UNLIKELY((uintptr_t)(a_PtrVar) < 2)) { if ((uintptr_t)(a_PtrVar) == 1) continue; break; } \
4501 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE(); \
4502 } else do {} while (0)
4503/* @def VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK
4504 * Macro for shortening calls to vmsvgaR3FifoGetCmdPayload for refetching the
4505 * buffer after figuring out the actual command size.
4506 *
4507 * Will break out of the switch on failure.
4508 *
4509 * @param a_PtrVar Request variable pointer.
4510 * @param a_Type Request typedef (not pointer) for casting.
4511 * @param a_cbPayloadReq How much payload to fetch.
4512 * @remarks Accesses a bunch of variables in the current scope!
4513 */
4514# define VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(a_PtrVar, a_Type, a_cbPayloadReq) \
4515 if (1) { \
4516 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(a_PtrVar, a_Type, a_cbPayloadReq); \
4517 } else do {} while (0)
4518
4519/**
4520 * @callback_method_impl{PFNPDMTHREADDEV, The async FIFO handling thread.}
4521 */
4522static DECLCALLBACK(int) vmsvgaR3FifoLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
4523{
4524 PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
4525 PVGASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
4526 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
4527 int rc;
4528
4529 if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
4530 return VINF_SUCCESS;
4531
4532 /*
4533 * Special mode where we only execute an external command and the go back
4534 * to being suspended. Currently, all ext cmds ends up here, with the reset
4535 * one also being eligble for runtime execution further down as well.
4536 */
4537 if (pThis->svga.fFifoExtCommandWakeup)
4538 {
4539 vmsvgaR3FifoHandleExtCmd(pDevIns, pThis, pThisCC);
4540 while (pThread->enmState == PDMTHREADSTATE_RUNNING)
4541 if (pThis->svga.u8FIFOExtCommand == VMSVGA_FIFO_EXTCMD_NONE)
4542 PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pThis->svga.hFIFORequestSem, RT_MS_1MIN);
4543 else
4544 vmsvgaR3FifoHandleExtCmd(pDevIns, pThis, pThisCC);
4545 return VINF_SUCCESS;
4546 }
4547
4548
4549 /*
4550 * Signal the semaphore to make sure we don't wait for 250ms after a
4551 * suspend & resume scenario (see vmsvgaR3FifoGetCmdPayload).
4552 */
4553 PDMDevHlpSUPSemEventSignal(pDevIns, pThis->svga.hFIFORequestSem);
4554
4555 /*
4556 * Allocate a bounce buffer for command we get from the FIFO.
4557 * (All code must return via the end of the function to free this buffer.)
4558 */
4559 uint8_t *pbBounceBuf = (uint8_t *)RTMemAllocZ(pThis->svga.cbFIFO);
4560 AssertReturn(pbBounceBuf, VERR_NO_MEMORY);
4561
4562 /*
4563 * Polling/sleep interval config.
4564 *
4565 * We wait for an a short interval if the guest has recently given us work
4566 * to do, but the interval increases the longer we're kept idle. Once we've
4567 * reached the refresh timer interval, we'll switch to extended waits,
4568 * depending on it or the guest to kick us into action when needed.
4569 *
4570 * Should the refresh time go fishing, we'll just continue increasing the
4571 * sleep length till we reaches the 250 ms max after about 16 seconds.
4572 */
4573 RTMSINTERVAL const cMsMinSleep = 16;
4574 RTMSINTERVAL const cMsIncSleep = 2;
4575 RTMSINTERVAL const cMsMaxSleep = 250;
4576 RTMSINTERVAL const cMsExtendedSleep = 15 * RT_MS_1SEC; /* Regular paranoia dictates that this cannot be indefinite. */
4577 RTMSINTERVAL cMsSleep = cMsMaxSleep;
4578
4579 /*
4580 * Cursor update state (SVGA_FIFO_CAP_CURSOR_BYPASS_3).
4581 *
4582 * Initialize with values that will detect an update from the guest.
4583 * Make sure that if the guest never updates the cursor position, then the device does not report it.
4584 * The guest has to change the value of uLastCursorUpdateCount, when the cursor position is actually updated.
4585 * xLastCursor, yLastCursor and fLastCursorVisible are set to report the first update.
4586 */
4587 uint32_t RT_UNTRUSTED_VOLATILE_GUEST * const pFIFO = pThisCC->svga.pau32FIFO;
4588 pThis->svga.uLastCursorUpdateCount = pFIFO[SVGA_FIFO_CURSOR_COUNT];
4589 uint32_t xLastCursor = ~pFIFO[SVGA_FIFO_CURSOR_X];
4590 uint32_t yLastCursor = ~pFIFO[SVGA_FIFO_CURSOR_Y];
4591 uint32_t fLastCursorVisible = ~pFIFO[SVGA_FIFO_CURSOR_ON];
4592
4593 /*
4594 * The FIFO loop.
4595 */
4596 LogFlow(("vmsvgaR3FifoLoop: started loop\n"));
4597 bool fBadOrDisabledFifo = ASMAtomicReadBool(&pThis->svga.fBadGuest);
4598 while (pThread->enmState == PDMTHREADSTATE_RUNNING)
4599 {
4600# if defined(RT_OS_DARWIN) && defined(VBOX_WITH_VMSVGA3D)
4601 /*
4602 * Should service the run loop every so often.
4603 */
4604 if (pThis->svga.f3DEnabled)
4605 vmsvga3dCocoaServiceRunLoop();
4606# endif
4607
4608 /* First check any pending actions. */
4609 vmsvgaR3FifoPendingActions(pDevIns, pThis, pThisCC);
4610
4611 /*
4612 * Unless there's already work pending, go to sleep for a short while.
4613 * (See polling/sleep interval config above.)
4614 */
4615 if ( fBadOrDisabledFifo
4616 || !vmsvgaR3FifoHasWork(pThisCC, pThis->svga.uLastCursorUpdateCount))
4617 {
4618 ASMAtomicWriteBool(&pThis->svga.fFIFOThreadSleeping, true);
4619 Assert(pThis->cMilliesRefreshInterval > 0);
4620 if (cMsSleep < pThis->cMilliesRefreshInterval)
4621 rc = PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pThis->svga.hFIFORequestSem, cMsSleep);
4622 else
4623 {
4624# ifdef VMSVGA_USE_FIFO_ACCESS_HANDLER
4625 int rc2 = PDMDevHlpPGMHandlerPhysicalReset(pDevIns, pThis->svga.GCPhysFIFO);
4626 AssertRC(rc2); /* No break. Racing EMTs unmapping and remapping the region. */
4627# endif
4628 if ( !fBadOrDisabledFifo
4629 && vmsvgaR3FifoHasWork(pThisCC, pThis->svga.uLastCursorUpdateCount))
4630 rc = VINF_SUCCESS;
4631 else
4632 {
4633 STAM_REL_PROFILE_START(&pSVGAState->StatFifoExtendedSleep, Acc);
4634 rc = PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pThis->svga.hFIFORequestSem, cMsExtendedSleep);
4635 STAM_REL_PROFILE_STOP(&pSVGAState->StatFifoExtendedSleep, Acc);
4636 }
4637 }
4638 ASMAtomicWriteBool(&pThis->svga.fFIFOThreadSleeping, false);
4639 AssertBreak(RT_SUCCESS(rc) || rc == VERR_TIMEOUT || rc == VERR_INTERRUPTED);
4640 if (pThread->enmState != PDMTHREADSTATE_RUNNING)
4641 {
4642 LogFlow(("vmsvgaR3FifoLoop: thread state %x\n", pThread->enmState));
4643 break;
4644 }
4645 }
4646 else
4647 rc = VINF_SUCCESS;
4648 fBadOrDisabledFifo = ASMAtomicReadBool(&pThis->svga.fBadGuest);
4649 if (rc == VERR_TIMEOUT)
4650 {
4651 if (!vmsvgaR3FifoHasWork(pThisCC, pThis->svga.uLastCursorUpdateCount))
4652 {
4653 cMsSleep = RT_MIN(cMsSleep + cMsIncSleep, cMsMaxSleep);
4654 continue;
4655 }
4656 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoTodoTimeout);
4657
4658 Log(("vmsvgaR3FifoLoop: timeout\n"));
4659 }
4660 else if (vmsvgaR3FifoHasWork(pThisCC, pThis->svga.uLastCursorUpdateCount))
4661 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoTodoWoken);
4662 cMsSleep = cMsMinSleep;
4663
4664 Log(("vmsvgaR3FifoLoop: enabled=%d configured=%d busy=%d\n", pThis->svga.fEnabled, pThis->svga.fConfigured, pFIFO[SVGA_FIFO_BUSY]));
4665 Log(("vmsvgaR3FifoLoop: min %x max %x\n", pFIFO[SVGA_FIFO_MIN], pFIFO[SVGA_FIFO_MAX]));
4666 Log(("vmsvgaR3FifoLoop: next %x stop %x\n", pFIFO[SVGA_FIFO_NEXT_CMD], pFIFO[SVGA_FIFO_STOP]));
4667
4668 /*
4669 * Handle external commands (currently only reset).
4670 */
4671 if (pThis->svga.u8FIFOExtCommand != VMSVGA_FIFO_EXTCMD_NONE)
4672 {
4673 vmsvgaR3FifoHandleExtCmd(pDevIns, pThis, pThisCC);
4674 continue;
4675 }
4676
4677 /*
4678 * If guest misbehaves, then do nothing.
4679 */
4680 if (ASMAtomicReadBool(&pThis->svga.fBadGuest))
4681 {
4682 vmsvgaR3FifoSetNotBusy(pDevIns, pThis, pThisCC, pSVGAState, pFIFO[SVGA_FIFO_MIN]);
4683 cMsSleep = cMsExtendedSleep;
4684 LogRelMax(1, ("VMSVGA: FIFO processing stopped because of the guest misbehavior\n"));
4685 continue;
4686 }
4687
4688 /*
4689 * The device must be enabled and configured.
4690 */
4691 if ( !pThis->svga.fEnabled
4692 || !pThis->svga.fConfigured)
4693 {
4694 vmsvgaR3FifoSetNotBusy(pDevIns, pThis, pThisCC, pSVGAState, pFIFO[SVGA_FIFO_MIN]);
4695 fBadOrDisabledFifo = true;
4696 cMsSleep = cMsMaxSleep; /* cheat */
4697 continue;
4698 }
4699
4700 /*
4701 * Get and check the min/max values. We ASSUME that they will remain
4702 * unchanged while we process requests. A further ASSUMPTION is that
4703 * the guest won't mess with SVGA_FIFO_NEXT_CMD while we're busy, so
4704 * we don't read it back while in the loop.
4705 */
4706 uint32_t const offFifoMin = pFIFO[SVGA_FIFO_MIN];
4707 uint32_t const offFifoMax = pFIFO[SVGA_FIFO_MAX];
4708 uint32_t offCurrentCmd = pFIFO[SVGA_FIFO_STOP];
4709 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
4710 if (RT_UNLIKELY( !VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_STOP, offFifoMin)
4711 || offFifoMax <= offFifoMin
4712 || offFifoMax > pThis->svga.cbFIFO
4713 || (offFifoMax & 3) != 0
4714 || (offFifoMin & 3) != 0
4715 || offCurrentCmd < offFifoMin
4716 || offCurrentCmd > offFifoMax))
4717 {
4718 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoErrors);
4719 LogRelMax(8, ("vmsvgaR3FifoLoop: Bad fifo: min=%#x stop=%#x max=%#x\n", offFifoMin, offCurrentCmd, offFifoMax));
4720 vmsvgaR3FifoSetNotBusy(pDevIns, pThis, pThisCC, pSVGAState, offFifoMin);
4721 fBadOrDisabledFifo = true;
4722 continue;
4723 }
4724 RT_UNTRUSTED_VALIDATED_FENCE();
4725 if (RT_UNLIKELY(offCurrentCmd & 3))
4726 {
4727 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoErrors);
4728 LogRelMax(8, ("vmsvgaR3FifoLoop: Misaligned offCurrentCmd=%#x?\n", offCurrentCmd));
4729 offCurrentCmd &= ~UINT32_C(3);
4730 }
4731
4732 /*
4733 * Update the cursor position before we start on the FIFO commands.
4734 */
4735 /** @todo do we need to check whether the guest disabled the SVGA_FIFO_CAP_CURSOR_BYPASS_3 capability here? */
4736 if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_CURSOR_LAST_UPDATED, offFifoMin))
4737 {
4738 uint32_t const uCursorUpdateCount = pFIFO[SVGA_FIFO_CURSOR_COUNT];
4739 if (uCursorUpdateCount == pThis->svga.uLastCursorUpdateCount)
4740 { /* halfways likely */ }
4741 else
4742 {
4743 uint32_t const uNewCount = vmsvgaR3FifoUpdateCursor(pThisCC, pSVGAState, pFIFO, offFifoMin, uCursorUpdateCount,
4744 &xLastCursor, &yLastCursor, &fLastCursorVisible);
4745 ASMAtomicWriteU32(&pThis->svga.uLastCursorUpdateCount, uNewCount);
4746 }
4747 }
4748
4749 /*
4750 * Mark the FIFO as busy.
4751 */
4752 ASMAtomicWriteU32(&pThis->svga.fBusy, VMSVGA_BUSY_F_FIFO); // Clears VMSVGA_BUSY_F_EMT_FORCE!
4753 if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_BUSY, offFifoMin))
4754 ASMAtomicWriteU32(&pFIFO[SVGA_FIFO_BUSY], true);
4755
4756 /*
4757 * Process all submitted command buffers.
4758 */
4759 vmsvgaR3CmdBufProcessBuffers(pDevIns, pThis, pThisCC, pThread);
4760
4761 /*
4762 * Execute all queued FIFO commands.
4763 * Quit if pending external command or changes in the thread state.
4764 */
4765 bool fDone = false;
4766 while ( !(fDone = (pFIFO[SVGA_FIFO_NEXT_CMD] == offCurrentCmd))
4767 && pThread->enmState == PDMTHREADSTATE_RUNNING)
4768 {
4769 uint32_t cbPayload = 0;
4770 uint32_t u32IrqStatus = 0;
4771
4772 Assert(offCurrentCmd < offFifoMax && offCurrentCmd >= offFifoMin);
4773
4774 /* First check any pending actions. */
4775 vmsvgaR3FifoPendingActions(pDevIns, pThis, pThisCC);
4776
4777 /* Check for pending external commands (reset). */
4778 if (pThis->svga.u8FIFOExtCommand != VMSVGA_FIFO_EXTCMD_NONE)
4779 break;
4780
4781 /*
4782 * Process the command.
4783 */
4784 /* 'enmCmdId' is actually a SVGAFifoCmdId. It is treated as uint32_t in order to avoid a compiler
4785 * warning. Because we implement some obsolete and deprecated commands, which are not included in
4786 * the SVGAFifoCmdId enum in the VMSVGA headers anymore.
4787 */
4788 uint32_t const enmCmdId = pFIFO[offCurrentCmd / sizeof(uint32_t)];
4789 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
4790 LogFlow(("vmsvgaR3FifoLoop: FIFO command (iCmd=0x%x) %s %d\n",
4791 offCurrentCmd / sizeof(uint32_t), vmsvgaR3FifoCmdToString(enmCmdId), enmCmdId));
4792 switch (enmCmdId)
4793 {
4794 case SVGA_CMD_INVALID_CMD:
4795 /* Nothing to do. */
4796 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdInvalidCmd);
4797 break;
4798
4799 case SVGA_CMD_FENCE:
4800 {
4801 SVGAFifoCmdFence *pCmdFence;
4802 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmdFence, SVGAFifoCmdFence, sizeof(*pCmdFence));
4803 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdFence);
4804 if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_FENCE, offFifoMin))
4805 {
4806 Log(("vmsvgaR3FifoLoop: SVGA_CMD_FENCE %#x\n", pCmdFence->fence));
4807 pFIFO[SVGA_FIFO_FENCE] = pCmdFence->fence;
4808
4809 if (pThis->svga.u32IrqMask & SVGA_IRQFLAG_ANY_FENCE)
4810 {
4811 Log(("vmsvgaR3FifoLoop: any fence irq\n"));
4812 u32IrqStatus |= SVGA_IRQFLAG_ANY_FENCE;
4813 }
4814 else
4815 if ( VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_FENCE_GOAL, offFifoMin)
4816 && (pThis->svga.u32IrqMask & SVGA_IRQFLAG_FENCE_GOAL)
4817 && pFIFO[SVGA_FIFO_FENCE_GOAL] == pCmdFence->fence)
4818 {
4819 Log(("vmsvgaR3FifoLoop: fence goal reached irq (fence=%#x)\n", pCmdFence->fence));
4820 u32IrqStatus |= SVGA_IRQFLAG_FENCE_GOAL;
4821 }
4822 }
4823 else
4824 Log(("SVGA_CMD_FENCE is bogus when offFifoMin is %#x!\n", offFifoMin));
4825 break;
4826 }
4827
4828 case SVGA_CMD_UPDATE:
4829 {
4830 SVGAFifoCmdUpdate *pCmd;
4831 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdUpdate, sizeof(*pCmd));
4832 vmsvgaR3CmdUpdate(pThis, pThisCC, pCmd);
4833 break;
4834 }
4835
4836 case SVGA_CMD_UPDATE_VERBOSE:
4837 {
4838 SVGAFifoCmdUpdateVerbose *pCmd;
4839 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdUpdateVerbose, sizeof(*pCmd));
4840 vmsvgaR3CmdUpdateVerbose(pThis, pThisCC, pCmd);
4841 break;
4842 }
4843
4844 case SVGA_CMD_DEFINE_CURSOR:
4845 {
4846 /* Followed by bitmap data. */
4847 SVGAFifoCmdDefineCursor *pCmd;
4848 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineCursor, sizeof(*pCmd));
4849
4850 /* Figure out the size of the bitmap data. */
4851 ASSERT_GUEST_BREAK(pCmd->height < 2048 && pCmd->width < 2048);
4852 ASSERT_GUEST_BREAK(pCmd->andMaskDepth <= 32);
4853 ASSERT_GUEST_BREAK(pCmd->xorMaskDepth <= 32);
4854 RT_UNTRUSTED_VALIDATED_FENCE();
4855
4856 uint32_t const cbAndLine = RT_ALIGN_32(pCmd->width * (pCmd->andMaskDepth + (pCmd->andMaskDepth == 15)), 32) / 8;
4857 uint32_t const cbAndMask = cbAndLine * pCmd->height;
4858 uint32_t const cbXorLine = RT_ALIGN_32(pCmd->width * (pCmd->xorMaskDepth + (pCmd->xorMaskDepth == 15)), 32) / 8;
4859 uint32_t const cbXorMask = cbXorLine * pCmd->height;
4860
4861 uint32_t const cbCmd = sizeof(SVGAFifoCmdDefineCursor) + cbAndMask + cbXorMask;
4862 VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineCursor, cbCmd);
4863 vmsvgaR3CmdDefineCursor(pThis, pThisCC, pCmd);
4864 break;
4865 }
4866
4867 case SVGA_CMD_DEFINE_ALPHA_CURSOR:
4868 {
4869 /* Followed by bitmap data. */
4870 SVGAFifoCmdDefineAlphaCursor *pCmd;
4871 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineAlphaCursor, sizeof(*pCmd));
4872
4873 /* Figure out the size of the bitmap data. */
4874 ASSERT_GUEST_BREAK(pCmd->height < 2048 && pCmd->width < 2048);
4875
4876 uint32_t const cbCmd = sizeof(SVGAFifoCmdDefineAlphaCursor) + pCmd->width * pCmd->height * sizeof(uint32_t) /* 32-bit BRGA format */;
4877 VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineAlphaCursor, cbCmd);
4878 vmsvgaR3CmdDefineAlphaCursor(pThis, pThisCC, pCmd);
4879 break;
4880 }
4881
4882 case SVGA_CMD_MOVE_CURSOR:
4883 {
4884 /* Deprecated; there should be no driver which *requires* this command. However, if
4885 * we do ecncounter this command, it might be useful to not get the FIFO completely out of
4886 * alignment.
4887 * May be issued by guest if SVGA_CAP_CURSOR_BYPASS is missing.
4888 */
4889 SVGAFifoCmdMoveCursor *pCmd;
4890 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdMoveCursor, sizeof(*pCmd));
4891 vmsvgaR3CmdMoveCursor(pThis, pThisCC, pCmd);
4892 break;
4893 }
4894
4895 case SVGA_CMD_DISPLAY_CURSOR:
4896 {
4897 /* Deprecated; there should be no driver which *requires* this command. However, if
4898 * we do ecncounter this command, it might be useful to not get the FIFO completely out of
4899 * alignment.
4900 * May be issued by guest if SVGA_CAP_CURSOR_BYPASS is missing.
4901 */
4902 SVGAFifoCmdDisplayCursor *pCmd;
4903 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDisplayCursor, sizeof(*pCmd));
4904 vmsvgaR3CmdDisplayCursor(pThis, pThisCC, pCmd);
4905 break;
4906 }
4907
4908 case SVGA_CMD_RECT_FILL:
4909 {
4910 SVGAFifoCmdRectFill *pCmd;
4911 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdRectFill, sizeof(*pCmd));
4912 vmsvgaR3CmdRectFill(pThis, pThisCC, pCmd);
4913 break;
4914 }
4915
4916 case SVGA_CMD_RECT_COPY:
4917 {
4918 SVGAFifoCmdRectCopy *pCmd;
4919 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdRectCopy, sizeof(*pCmd));
4920 vmsvgaR3CmdRectCopy(pThis, pThisCC, pCmd);
4921 break;
4922 }
4923
4924 case SVGA_CMD_RECT_ROP_COPY:
4925 {
4926 SVGAFifoCmdRectRopCopy *pCmd;
4927 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdRectRopCopy, sizeof(*pCmd));
4928 vmsvgaR3CmdRectRopCopy(pThis, pThisCC, pCmd);
4929 break;
4930 }
4931
4932 case SVGA_CMD_ESCAPE:
4933 {
4934 /* Followed by 'size' bytes of data. */
4935 SVGAFifoCmdEscape *pCmd;
4936 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdEscape, sizeof(*pCmd));
4937
4938 ASSERT_GUEST_BREAK(pCmd->size < pThis->svga.cbFIFO - sizeof(SVGAFifoCmdEscape));
4939 RT_UNTRUSTED_VALIDATED_FENCE();
4940
4941 uint32_t const cbCmd = sizeof(SVGAFifoCmdEscape) + pCmd->size;
4942 VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdEscape, cbCmd);
4943 vmsvgaR3CmdEscape(pThis, pThisCC, pCmd);
4944 break;
4945 }
4946# ifdef VBOX_WITH_VMSVGA3D
4947 case SVGA_CMD_DEFINE_GMR2:
4948 {
4949 SVGAFifoCmdDefineGMR2 *pCmd;
4950 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineGMR2, sizeof(*pCmd));
4951 vmsvgaR3CmdDefineGMR2(pThis, pThisCC, pCmd);
4952 break;
4953 }
4954
4955 case SVGA_CMD_REMAP_GMR2:
4956 {
4957 /* Followed by page descriptors or guest ptr. */
4958 SVGAFifoCmdRemapGMR2 *pCmd;
4959 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdRemapGMR2, sizeof(*pCmd));
4960
4961 /* Calculate the size of what comes after next and fetch it. */
4962 uint32_t cbCmd = sizeof(SVGAFifoCmdRemapGMR2);
4963 if (pCmd->flags & SVGA_REMAP_GMR2_VIA_GMR)
4964 cbCmd += sizeof(SVGAGuestPtr);
4965 else
4966 {
4967 uint32_t const cbPageDesc = (pCmd->flags & SVGA_REMAP_GMR2_PPN64) ? sizeof(uint64_t) : sizeof(uint32_t);
4968 if (pCmd->flags & SVGA_REMAP_GMR2_SINGLE_PPN)
4969 {
4970 cbCmd += cbPageDesc;
4971 pCmd->numPages = 1;
4972 }
4973 else
4974 {
4975 ASSERT_GUEST_BREAK(pCmd->numPages <= pThis->svga.cbFIFO / cbPageDesc);
4976 cbCmd += cbPageDesc * pCmd->numPages;
4977 }
4978 }
4979 VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdRemapGMR2, cbCmd);
4980 vmsvgaR3CmdRemapGMR2(pThis, pThisCC, pCmd);
4981# ifdef DEBUG_GMR_ACCESS
4982 VMR3ReqCallWaitU(PDMDevHlpGetUVM(pDevIns), VMCPUID_ANY, (PFNRT)vmsvgaR3RegisterGmr, 2, pDevIns, pCmd->gmrId);
4983# endif
4984 break;
4985 }
4986# endif // VBOX_WITH_VMSVGA3D
4987 case SVGA_CMD_DEFINE_SCREEN:
4988 {
4989 /* The size of this command is specified by the guest and depends on capabilities. */
4990 Assert(pFIFO[SVGA_FIFO_CAPABILITIES] & SVGA_FIFO_CAP_SCREEN_OBJECT_2);
4991
4992 SVGAFifoCmdDefineScreen *pCmd;
4993 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineScreen, sizeof(pCmd->screen.structSize));
4994 AssertBreak(pCmd->screen.structSize < pThis->svga.cbFIFO);
4995 RT_UNTRUSTED_VALIDATED_FENCE();
4996
4997 RT_BZERO(&pCmd->screen.id, sizeof(*pCmd) - RT_OFFSETOF(SVGAFifoCmdDefineScreen, screen.id));
4998 VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineScreen, RT_MAX(sizeof(pCmd->screen.structSize), pCmd->screen.structSize));
4999 vmsvgaR3CmdDefineScreen(pThis, pThisCC, pCmd);
5000 break;
5001 }
5002
5003 case SVGA_CMD_DESTROY_SCREEN:
5004 {
5005 SVGAFifoCmdDestroyScreen *pCmd;
5006 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDestroyScreen, sizeof(*pCmd));
5007 vmsvgaR3CmdDestroyScreen(pThis, pThisCC, pCmd);
5008 break;
5009 }
5010
5011 case SVGA_CMD_DEFINE_GMRFB:
5012 {
5013 SVGAFifoCmdDefineGMRFB *pCmd;
5014 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineGMRFB, sizeof(*pCmd));
5015 vmsvgaR3CmdDefineGMRFB(pThis, pThisCC, pCmd);
5016 break;
5017 }
5018
5019 case SVGA_CMD_BLIT_GMRFB_TO_SCREEN:
5020 {
5021 SVGAFifoCmdBlitGMRFBToScreen *pCmd;
5022 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdBlitGMRFBToScreen, sizeof(*pCmd));
5023 vmsvgaR3CmdBlitGMRFBToScreen(pThis, pThisCC, pCmd);
5024 break;
5025 }
5026
5027 case SVGA_CMD_BLIT_SCREEN_TO_GMRFB:
5028 {
5029 SVGAFifoCmdBlitScreenToGMRFB *pCmd;
5030 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdBlitScreenToGMRFB, sizeof(*pCmd));
5031 vmsvgaR3CmdBlitScreenToGMRFB(pThis, pThisCC, pCmd);
5032 break;
5033 }
5034
5035 case SVGA_CMD_ANNOTATION_FILL:
5036 {
5037 SVGAFifoCmdAnnotationFill *pCmd;
5038 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdAnnotationFill, sizeof(*pCmd));
5039 vmsvgaR3CmdAnnotationFill(pThis, pThisCC, pCmd);
5040 break;
5041 }
5042
5043 case SVGA_CMD_ANNOTATION_COPY:
5044 {
5045 SVGAFifoCmdAnnotationCopy *pCmd;
5046 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdAnnotationCopy, sizeof(*pCmd));
5047 vmsvgaR3CmdAnnotationCopy(pThis, pThisCC, pCmd);
5048 break;
5049 }
5050
5051 default:
5052# ifdef VBOX_WITH_VMSVGA3D
5053 if ( (int)enmCmdId >= SVGA_3D_CMD_BASE
5054 && (int)enmCmdId < SVGA_3D_CMD_MAX)
5055 {
5056 RT_UNTRUSTED_VALIDATED_FENCE();
5057
5058 /* All 3d commands start with a common header, which defines the identifier and the size
5059 * of the command. The identifier has been already read from FIFO. Fetch the size.
5060 */
5061 uint32_t *pcbCmd;
5062 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pcbCmd, uint32_t, sizeof(*pcbCmd));
5063 uint32_t const cbCmd = *pcbCmd;
5064 AssertBreak(cbCmd < pThis->svga.cbFIFO);
5065 uint32_t *pu32Cmd;
5066 VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pu32Cmd, uint32_t, sizeof(*pcbCmd) + cbCmd);
5067 pu32Cmd++; /* Skip the command size. */
5068
5069 if (RT_LIKELY(pThis->svga.f3DEnabled))
5070 { /* likely */ }
5071 else
5072 {
5073 LogRelMax(8, ("VMSVGA: 3D disabled, command %d skipped\n", enmCmdId));
5074 break;
5075 }
5076
5077 vmsvgaR3Process3dCmd(pThis, pThisCC, SVGA3D_INVALID_ID, (SVGAFifo3dCmdId)enmCmdId, cbCmd, pu32Cmd);
5078 }
5079 else
5080# endif // VBOX_WITH_VMSVGA3D
5081 {
5082 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoUnkCmds);
5083 AssertMsgFailed(("enmCmdId=%d\n", enmCmdId));
5084 LogRelMax(16, ("VMSVGA: unsupported command %d\n", enmCmdId));
5085 }
5086 }
5087
5088 /* Go to the next slot */
5089 Assert(cbPayload + sizeof(uint32_t) <= offFifoMax - offFifoMin);
5090 offCurrentCmd += RT_ALIGN_32(cbPayload + sizeof(uint32_t), sizeof(uint32_t));
5091 if (offCurrentCmd >= offFifoMax)
5092 {
5093 offCurrentCmd -= offFifoMax - offFifoMin;
5094 Assert(offCurrentCmd >= offFifoMin);
5095 Assert(offCurrentCmd < offFifoMax);
5096 }
5097 ASMAtomicWriteU32(&pFIFO[SVGA_FIFO_STOP], offCurrentCmd);
5098 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoCommands);
5099
5100 /*
5101 * Raise IRQ if required. Must enter the critical section here
5102 * before making final decisions here, otherwise cubebench and
5103 * others may end up waiting forever.
5104 */
5105 if ( u32IrqStatus
5106 || (pThis->svga.u32IrqMask & SVGA_IRQFLAG_FIFO_PROGRESS))
5107 {
5108 int const rcLock = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VERR_IGNORED);
5109 PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, &pThis->CritSect, rcLock);
5110
5111 /* FIFO progress might trigger an interrupt. */
5112 if (pThis->svga.u32IrqMask & SVGA_IRQFLAG_FIFO_PROGRESS)
5113 {
5114 Log(("vmsvgaR3FifoLoop: fifo progress irq\n"));
5115 u32IrqStatus |= SVGA_IRQFLAG_FIFO_PROGRESS;
5116 }
5117
5118 /* Unmasked IRQ pending? */
5119 if (pThis->svga.u32IrqMask & u32IrqStatus)
5120 {
5121 Log(("vmsvgaR3FifoLoop: Trigger interrupt with status %x\n", u32IrqStatus));
5122 ASMAtomicOrU32(&pThis->svga.u32IrqStatus, u32IrqStatus);
5123 PDMDevHlpPCISetIrq(pDevIns, 0, 1);
5124 }
5125
5126 PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect);
5127 }
5128 }
5129
5130 /* If really done, clear the busy flag. */
5131 if (fDone)
5132 {
5133 Log(("vmsvgaR3FifoLoop: emptied the FIFO next=%x stop=%x\n", pFIFO[SVGA_FIFO_NEXT_CMD], offCurrentCmd));
5134 vmsvgaR3FifoSetNotBusy(pDevIns, pThis, pThisCC, pSVGAState, offFifoMin);
5135 }
5136 }
5137
5138 /*
5139 * Free the bounce buffer. (There are no returns above!)
5140 */
5141 RTMemFree(pbBounceBuf);
5142
5143 return VINF_SUCCESS;
5144}
5145
5146#undef VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK
5147#undef VMSVGAFIFO_GET_CMD_BUFFER_BREAK
5148
5149/**
5150 * @callback_method_impl{PFNPDMTHREADWAKEUPDEV,
5151 * Unblock the FIFO I/O thread so it can respond to a state change.}
5152 */
5153static DECLCALLBACK(int) vmsvgaR3FifoLoopWakeUp(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
5154{
5155 RT_NOREF(pDevIns);
5156 PVGASTATE pThis = (PVGASTATE)pThread->pvUser;
5157 Log(("vmsvgaR3FifoLoopWakeUp\n"));
5158 return PDMDevHlpSUPSemEventSignal(pDevIns, pThis->svga.hFIFORequestSem);
5159}
5160
5161/**
5162 * Enables or disables dirty page tracking for the framebuffer
5163 *
5164 * @param pDevIns The device instance.
5165 * @param pThis The shared VGA/VMSVGA instance data.
5166 * @param fTraces Enable/disable traces
5167 */
5168static void vmsvgaR3SetTraces(PPDMDEVINS pDevIns, PVGASTATE pThis, bool fTraces)
5169{
5170 if ( (!pThis->svga.fConfigured || !pThis->svga.fEnabled)
5171 && !fTraces)
5172 {
5173 //Assert(pThis->svga.fTraces);
5174 Log(("vmsvgaR3SetTraces: *not* allowed to disable dirty page tracking when the device is in legacy mode.\n"));
5175 return;
5176 }
5177
5178 pThis->svga.fTraces = fTraces;
5179 if (pThis->svga.fTraces)
5180 {
5181 unsigned cbFrameBuffer = pThis->vram_size;
5182
5183 Log(("vmsvgaR3SetTraces: enable dirty page handling for the frame buffer only (%x bytes)\n", 0));
5184 /** @todo How does this work with screens? */
5185 if (pThis->svga.uHeight != VMSVGA_VAL_UNINITIALIZED)
5186 {
5187# ifndef DEBUG_bird /* BB-10.3.1 triggers this as it initializes everything to zero. Better just ignore it. */
5188 Assert(pThis->svga.cbScanline);
5189# endif
5190 /* Hardware enabled; return real framebuffer size .*/
5191 cbFrameBuffer = (uint32_t)pThis->svga.uHeight * pThis->svga.cbScanline;
5192 cbFrameBuffer = RT_ALIGN(cbFrameBuffer, GUEST_PAGE_SIZE);
5193 }
5194
5195 if (!pThis->svga.fVRAMTracking)
5196 {
5197 Log(("vmsvgaR3SetTraces: enable frame buffer dirty page tracking. (%x bytes; vram %x)\n", cbFrameBuffer, pThis->vram_size));
5198 vgaR3RegisterVRAMHandler(pDevIns, pThis, cbFrameBuffer);
5199 pThis->svga.fVRAMTracking = true;
5200 }
5201 }
5202 else
5203 {
5204 if (pThis->svga.fVRAMTracking)
5205 {
5206 Log(("vmsvgaR3SetTraces: disable frame buffer dirty page tracking\n"));
5207 vgaR3UnregisterVRAMHandler(pDevIns, pThis);
5208 pThis->svga.fVRAMTracking = false;
5209 }
5210 }
5211}
5212
5213/**
5214 * @callback_method_impl{FNPCIIOREGIONMAP}
5215 */
5216DECLCALLBACK(int) vmsvgaR3PciIORegionFifoMapUnmap(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion,
5217 RTGCPHYS GCPhysAddress, RTGCPHYS cb, PCIADDRESSSPACE enmType)
5218{
5219 PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
5220 int rc;
5221 RT_NOREF(pPciDev);
5222 Assert(pPciDev == pDevIns->apPciDevs[0]);
5223
5224 Log(("vmsvgaR3PciIORegionFifoMapUnmap: iRegion=%d GCPhysAddress=%RGp cb=%RGp enmType=%d\n", iRegion, GCPhysAddress, cb, enmType));
5225 AssertReturn( iRegion == pThis->pciRegions.iFIFO
5226 && ( enmType == PCI_ADDRESS_SPACE_MEM
5227 || (enmType == PCI_ADDRESS_SPACE_MEM_PREFETCH /* got wrong in 6.1.0RC1 */ && pThis->fStateLoaded))
5228 , VERR_INTERNAL_ERROR);
5229 if (GCPhysAddress != NIL_RTGCPHYS)
5230 {
5231 /*
5232 * Mapping the FIFO RAM.
5233 */
5234 AssertLogRelMsg(cb == pThis->svga.cbFIFO, ("cb=%#RGp cbFIFO=%#x\n", cb, pThis->svga.cbFIFO));
5235 rc = PDMDevHlpMmio2Map(pDevIns, pThis->hMmio2VmSvgaFifo, GCPhysAddress);
5236 AssertRC(rc);
5237
5238# if defined(VMSVGA_USE_FIFO_ACCESS_HANDLER) || defined(DEBUG_FIFO_ACCESS)
5239 if (RT_SUCCESS(rc))
5240 {
5241 rc = PDMDevHlpPGMHandlerPhysicalRegister(pDevIns, GCPhysAddress,
5242# ifdef DEBUG_FIFO_ACCESS
5243 GCPhysAddress + (pThis->svga.cbFIFO - 1),
5244# else
5245 GCPhysAddress + GUEST_PAGE_SIZE - 1,
5246# endif
5247 pThis->svga.hFifoAccessHandlerType, pThis, NIL_RTR0PTR, NIL_RTRCPTR,
5248 "VMSVGA FIFO");
5249 AssertRC(rc);
5250 }
5251# endif
5252 if (RT_SUCCESS(rc))
5253 {
5254 pThis->svga.GCPhysFIFO = GCPhysAddress;
5255 Log(("vmsvgaR3IORegionMap: GCPhysFIFO=%RGp cbFIFO=%#x\n", GCPhysAddress, pThis->svga.cbFIFO));
5256 }
5257 rc = VINF_PCI_MAPPING_DONE; /* caller only cares about this status, so it is okay that we overwrite errors here. */
5258 }
5259 else
5260 {
5261 Assert(pThis->svga.GCPhysFIFO);
5262# if defined(VMSVGA_USE_FIFO_ACCESS_HANDLER) || defined(DEBUG_FIFO_ACCESS)
5263 rc = PDMDevHlpPGMHandlerPhysicalDeregister(pDevIns, pThis->svga.GCPhysFIFO);
5264 AssertRC(rc);
5265# else
5266 rc = VINF_SUCCESS;
5267# endif
5268 pThis->svga.GCPhysFIFO = 0;
5269 }
5270 return rc;
5271}
5272
5273# ifdef VBOX_WITH_VMSVGA3D
5274
5275/**
5276 * Used by vmsvga3dInfoSurfaceWorker to make the FIFO thread to save one or all
5277 * surfaces to VMSVGA3DMIPMAPLEVEL::pSurfaceData heap buffers.
5278 *
5279 * @param pDevIns The device instance.
5280 * @param pThis The The shared VGA/VMSVGA instance data.
5281 * @param pThisCC The VGA/VMSVGA state for ring-3.
5282 * @param sid Either UINT32_MAX or the ID of a specific surface. If
5283 * UINT32_MAX is used, all surfaces are processed.
5284 */
5285void vmsvgaR33dSurfaceUpdateHeapBuffersOnFifoThread(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, uint32_t sid)
5286{
5287 vmsvgaR3RunExtCmdOnFifoThread(pDevIns, pThis, pThisCC, VMSVGA_FIFO_EXTCMD_UPDATE_SURFACE_HEAP_BUFFERS, (void *)(uintptr_t)sid,
5288 sid == UINT32_MAX ? 10 * RT_MS_1SEC : RT_MS_1MIN);
5289}
5290
5291
5292/**
5293 * @callback_method_impl{FNDBGFHANDLERDEV, "vmsvga3dsfc"}
5294 */
5295DECLCALLBACK(void) vmsvgaR3Info3dSurface(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
5296{
5297 /* There might be a specific surface ID at the start of the
5298 arguments, if not show all surfaces. */
5299 uint32_t sid = UINT32_MAX;
5300 if (pszArgs)
5301 pszArgs = RTStrStripL(pszArgs);
5302 if (pszArgs && RT_C_IS_DIGIT(*pszArgs))
5303 sid = RTStrToUInt32(pszArgs);
5304
5305 /* Verbose or terse display, we default to verbose. */
5306 bool fVerbose = true;
5307 if (RTStrIStr(pszArgs, "terse"))
5308 fVerbose = false;
5309
5310 /* The size of the ascii art (x direction, y is 3/4 of x). */
5311 uint32_t cxAscii = 80;
5312 if (RTStrIStr(pszArgs, "gigantic"))
5313 cxAscii = 300;
5314 else if (RTStrIStr(pszArgs, "huge"))
5315 cxAscii = 180;
5316 else if (RTStrIStr(pszArgs, "big"))
5317 cxAscii = 132;
5318 else if (RTStrIStr(pszArgs, "normal"))
5319 cxAscii = 80;
5320 else if (RTStrIStr(pszArgs, "medium"))
5321 cxAscii = 64;
5322 else if (RTStrIStr(pszArgs, "small"))
5323 cxAscii = 48;
5324 else if (RTStrIStr(pszArgs, "tiny"))
5325 cxAscii = 24;
5326
5327 /* Y invert the image when producing the ASCII art. */
5328 bool fInvY = false;
5329 if (RTStrIStr(pszArgs, "invy"))
5330 fInvY = true;
5331
5332 vmsvga3dInfoSurfaceWorker(pDevIns, PDMDEVINS_2_DATA(pDevIns, PVGASTATE), PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC),
5333 pHlp, sid, fVerbose, cxAscii, fInvY, NULL);
5334}
5335
5336
5337/**
5338 * @callback_method_impl{FNDBGFHANDLERDEV, "vmsvga3dsurf"}
5339 */
5340DECLCALLBACK(void) vmsvgaR3Info3dSurfaceBmp(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
5341{
5342 /* pszArg = "sid[>dir]"
5343 * Writes %dir%/info-S-sidI.bmp, where S - sequential bitmap number, I - decimal surface id.
5344 */
5345 char *pszBitmapPath = NULL;
5346 uint32_t sid = UINT32_MAX;
5347 if (pszArgs)
5348 pszArgs = RTStrStripL(pszArgs);
5349 if (pszArgs && RT_C_IS_DIGIT(*pszArgs))
5350 RTStrToUInt32Ex(pszArgs, &pszBitmapPath, 0, &sid);
5351 if ( pszBitmapPath
5352 && *pszBitmapPath == '>')
5353 ++pszBitmapPath;
5354
5355 const bool fVerbose = true;
5356 const uint32_t cxAscii = 0; /* No ASCII */
5357 const bool fInvY = false; /* Do not invert. */
5358 vmsvga3dInfoSurfaceWorker(pDevIns, PDMDEVINS_2_DATA(pDevIns, PVGASTATE), PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC),
5359 pHlp, sid, fVerbose, cxAscii, fInvY, pszBitmapPath);
5360}
5361
5362/**
5363 * @callback_method_impl{FNDBGFHANDLERDEV, "vmsvga3dctx"}
5364 */
5365DECLCALLBACK(void) vmsvgaR3Info3dContext(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
5366{
5367 /* There might be a specific surface ID at the start of the
5368 arguments, if not show all contexts. */
5369 uint32_t sid = UINT32_MAX;
5370 if (pszArgs)
5371 pszArgs = RTStrStripL(pszArgs);
5372 if (pszArgs && RT_C_IS_DIGIT(*pszArgs))
5373 sid = RTStrToUInt32(pszArgs);
5374
5375 /* Verbose or terse display, we default to verbose. */
5376 bool fVerbose = true;
5377 if (RTStrIStr(pszArgs, "terse"))
5378 fVerbose = false;
5379
5380 vmsvga3dInfoContextWorker(PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC), pHlp, sid, fVerbose);
5381}
5382# endif /* VBOX_WITH_VMSVGA3D */
5383
5384/**
5385 * @callback_method_impl{FNDBGFHANDLERDEV, "vmsvga"}
5386 */
5387static DECLCALLBACK(void) vmsvgaR3Info(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
5388{
5389 PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
5390 PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
5391 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
5392 uint32_t RT_UNTRUSTED_VOLATILE_GUEST *pFIFO = pThisCC->svga.pau32FIFO;
5393 RT_NOREF(pszArgs);
5394
5395 pHlp->pfnPrintf(pHlp, "Extension enabled: %RTbool\n", pThis->svga.fEnabled);
5396 pHlp->pfnPrintf(pHlp, "Configured: %RTbool\n", pThis->svga.fConfigured);
5397 pHlp->pfnPrintf(pHlp, "Base I/O port: %#x\n",
5398 pThis->hIoPortVmSvga != NIL_IOMIOPORTHANDLE
5399 ? PDMDevHlpIoPortGetMappingAddress(pDevIns, pThis->hIoPortVmSvga) : UINT32_MAX);
5400 pHlp->pfnPrintf(pHlp, "FIFO address: %RGp\n", pThis->svga.GCPhysFIFO);
5401 pHlp->pfnPrintf(pHlp, "FIFO size: %u (%#x)\n", pThis->svga.cbFIFO, pThis->svga.cbFIFO);
5402 pHlp->pfnPrintf(pHlp, "FIFO external cmd: %#x\n", pThis->svga.u8FIFOExtCommand);
5403 pHlp->pfnPrintf(pHlp, "FIFO extcmd wakeup: %u\n", pThis->svga.fFifoExtCommandWakeup);
5404 pHlp->pfnPrintf(pHlp, "FIFO min/max: %u/%u\n", pFIFO[SVGA_FIFO_MIN], pFIFO[SVGA_FIFO_MAX]);
5405 pHlp->pfnPrintf(pHlp, "Busy: %#x\n", pThis->svga.fBusy);
5406 pHlp->pfnPrintf(pHlp, "Traces: %RTbool (effective: %RTbool)\n", pThis->svga.fTraces, pThis->svga.fVRAMTracking);
5407 pHlp->pfnPrintf(pHlp, "Guest ID: %#x (%d)\n", pThis->svga.u32GuestId, pThis->svga.u32GuestId);
5408 pHlp->pfnPrintf(pHlp, "IRQ status: %#x\n", pThis->svga.u32IrqStatus);
5409 pHlp->pfnPrintf(pHlp, "IRQ mask: %#x\n", pThis->svga.u32IrqMask);
5410 pHlp->pfnPrintf(pHlp, "Pitch lock: %#x (FIFO:%#x)\n", pThis->svga.u32PitchLock, pFIFO[SVGA_FIFO_PITCHLOCK]);
5411 pHlp->pfnPrintf(pHlp, "Current GMR ID: %#x\n", pThis->svga.u32CurrentGMRId);
5412 pHlp->pfnPrintf(pHlp, "Device Capabilites: %#x\n", pThis->svga.u32DeviceCaps);
5413 pHlp->pfnPrintf(pHlp, "Index reg: %#x\n", pThis->svga.u32IndexReg);
5414 pHlp->pfnPrintf(pHlp, "Action flags: %#x\n", pThis->svga.u32ActionFlags);
5415 pHlp->pfnPrintf(pHlp, "Max display size: %ux%u\n", pThis->svga.u32MaxWidth, pThis->svga.u32MaxHeight);
5416 pHlp->pfnPrintf(pHlp, "Display size: %ux%u %ubpp\n", pThis->svga.uWidth, pThis->svga.uHeight, pThis->svga.uBpp);
5417 pHlp->pfnPrintf(pHlp, "Scanline: %u (%#x)\n", pThis->svga.cbScanline, pThis->svga.cbScanline);
5418 pHlp->pfnPrintf(pHlp, "Viewport position: %ux%u\n", pThis->svga.viewport.x, pThis->svga.viewport.y);
5419 pHlp->pfnPrintf(pHlp, "Viewport size: %ux%u\n", pThis->svga.viewport.cx, pThis->svga.viewport.cy);
5420
5421 pHlp->pfnPrintf(pHlp, "Cursor active: %RTbool\n", pSVGAState->Cursor.fActive);
5422 pHlp->pfnPrintf(pHlp, "Cursor hotspot: %ux%u\n", pSVGAState->Cursor.xHotspot, pSVGAState->Cursor.yHotspot);
5423 pHlp->pfnPrintf(pHlp, "Cursor size: %ux%u\n", pSVGAState->Cursor.width, pSVGAState->Cursor.height);
5424 pHlp->pfnPrintf(pHlp, "Cursor byte size: %u (%#x)\n", pSVGAState->Cursor.cbData, pSVGAState->Cursor.cbData);
5425
5426 pHlp->pfnPrintf(pHlp, "FIFO cursor: state %u, screen %d\n", pFIFO[SVGA_FIFO_CURSOR_ON], pFIFO[SVGA_FIFO_CURSOR_SCREEN_ID]);
5427 pHlp->pfnPrintf(pHlp, "FIFO cursor at: %u,%u\n", pFIFO[SVGA_FIFO_CURSOR_X], pFIFO[SVGA_FIFO_CURSOR_Y]);
5428
5429 pHlp->pfnPrintf(pHlp, "Legacy cursor: ID %u, state %u\n", pThis->svga.uCursorID, pThis->svga.uCursorOn);
5430 pHlp->pfnPrintf(pHlp, "Legacy cursor at: %u,%u\n", pThis->svga.uCursorX, pThis->svga.uCursorY);
5431
5432# ifdef VBOX_WITH_VMSVGA3D
5433 pHlp->pfnPrintf(pHlp, "3D enabled: %RTbool\n", pThis->svga.f3DEnabled);
5434# endif
5435 if (pThisCC->pDrv)
5436 {
5437 pHlp->pfnPrintf(pHlp, "Driver mode: %ux%u %ubpp\n", pThisCC->pDrv->cx, pThisCC->pDrv->cy, pThisCC->pDrv->cBits);
5438 pHlp->pfnPrintf(pHlp, "Driver pitch: %u (%#x)\n", pThisCC->pDrv->cbScanline, pThisCC->pDrv->cbScanline);
5439 }
5440
5441 /* Dump screen information. */
5442 for (unsigned iScreen = 0; iScreen < RT_ELEMENTS(pSVGAState->aScreens); ++iScreen)
5443 {
5444 VMSVGASCREENOBJECT *pScreen = vmsvgaR3GetScreenObject(pThisCC, iScreen);
5445 if (pScreen)
5446 {
5447 pHlp->pfnPrintf(pHlp, "Screen %u defined (ID %u):\n", iScreen, pScreen->idScreen);
5448 pHlp->pfnPrintf(pHlp, " %u x %u x %ubpp @ %u, %u\n", pScreen->cWidth, pScreen->cHeight,
5449 pScreen->cBpp, pScreen->xOrigin, pScreen->yOrigin);
5450 pHlp->pfnPrintf(pHlp, " Pitch %u bytes, VRAM offset %X\n", pScreen->cbPitch, pScreen->offVRAM);
5451 pHlp->pfnPrintf(pHlp, " Flags %X", pScreen->fuScreen);
5452 if (pScreen->fuScreen != SVGA_SCREEN_MUST_BE_SET)
5453 {
5454 pHlp->pfnPrintf(pHlp, " (");
5455 if (pScreen->fuScreen & SVGA_SCREEN_IS_PRIMARY)
5456 pHlp->pfnPrintf(pHlp, " IS_PRIMARY");
5457 if (pScreen->fuScreen & SVGA_SCREEN_FULLSCREEN_HINT)
5458 pHlp->pfnPrintf(pHlp, " FULLSCREEN_HINT");
5459 if (pScreen->fuScreen & SVGA_SCREEN_DEACTIVATE)
5460 pHlp->pfnPrintf(pHlp, " DEACTIVATE");
5461 if (pScreen->fuScreen & SVGA_SCREEN_BLANKING)
5462 pHlp->pfnPrintf(pHlp, " BLANKING");
5463 pHlp->pfnPrintf(pHlp, " )");
5464 }
5465 pHlp->pfnPrintf(pHlp, ", %smodified\n", pScreen->fModified ? "" : "not ");
5466 }
5467 }
5468
5469}
5470
5471static int vmsvgaR3LoadBufCtx(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, PSSMHANDLE pSSM, PVMSVGACMDBUFCTX pBufCtx, SVGACBContext CBCtx)
5472{
5473 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
5474 PVMSVGAR3STATE pSvgaR3State = pThisCC->svga.pSvgaR3State;
5475
5476 uint32_t cSubmitted;
5477 int rc = pHlp->pfnSSMGetU32(pSSM, &cSubmitted);
5478 AssertLogRelRCReturn(rc, rc);
5479
5480 for (uint32_t i = 0; i < cSubmitted; ++i)
5481 {
5482 PVMSVGACMDBUF pCmdBuf = vmsvgaR3CmdBufAlloc(pBufCtx);
5483 AssertPtrReturn(pCmdBuf, VERR_NO_MEMORY);
5484
5485 pHlp->pfnSSMGetGCPhys(pSSM, &pCmdBuf->GCPhysCB);
5486
5487 uint32_t u32;
5488 rc = pHlp->pfnSSMGetU32(pSSM, &u32);
5489 AssertRCReturn(rc, rc);
5490 AssertReturn(u32 == sizeof(SVGACBHeader), VERR_INVALID_STATE);
5491 pHlp->pfnSSMGetMem(pSSM, &pCmdBuf->hdr, sizeof(SVGACBHeader));
5492
5493 rc = pHlp->pfnSSMGetU32(pSSM, &u32);
5494 AssertRCReturn(rc, rc);
5495 AssertReturn(u32 == pCmdBuf->hdr.length, VERR_INVALID_STATE);
5496
5497 if (pCmdBuf->hdr.length)
5498 {
5499 pCmdBuf->pvCommands = RTMemAlloc(pCmdBuf->hdr.length);
5500 AssertPtrReturn(pCmdBuf->pvCommands, VERR_NO_MEMORY);
5501
5502 rc = pHlp->pfnSSMGetMem(pSSM, pCmdBuf->pvCommands, pCmdBuf->hdr.length);
5503 AssertRCReturn(rc, rc);
5504 }
5505
5506 if (RT_LIKELY(CBCtx < RT_ELEMENTS(pSvgaR3State->apCmdBufCtxs)))
5507 {
5508 vmsvgaR3CmdBufSubmitCtx(pDevIns, pThis, pThisCC, &pCmdBuf);
5509 }
5510 else
5511 {
5512 uint32_t offNextCmd = 0;
5513 vmsvgaR3CmdBufSubmitDC(pDevIns, pThisCC, &pCmdBuf, &offNextCmd);
5514 }
5515
5516 /* Free the buffer if CmdBufSubmit* did not consume it. */
5517 vmsvgaR3CmdBufFree(pCmdBuf);
5518 }
5519 return rc;
5520}
5521
5522static int vmsvgaR3LoadCommandBuffers(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, PSSMHANDLE pSSM)
5523{
5524 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
5525 PVMSVGAR3STATE pSvgaR3State = pThisCC->svga.pSvgaR3State;
5526
5527 bool f;
5528 uint32_t u32;
5529
5530 /* Device context command buffers. */
5531 int rc = vmsvgaR3LoadBufCtx(pDevIns, pThis, pThisCC, pSSM, &pSvgaR3State->CmdBufCtxDC, SVGA_CB_CONTEXT_MAX);
5532 AssertLogRelRCReturn(rc, rc);
5533
5534 /* DX contexts command buffers. */
5535 uint32_t cBufCtx;
5536 rc = pHlp->pfnSSMGetU32(pSSM, &cBufCtx);
5537 AssertLogRelRCReturn(rc, rc);
5538 AssertReturn(cBufCtx == RT_ELEMENTS(pSvgaR3State->apCmdBufCtxs), VERR_INVALID_STATE);
5539 for (uint32_t j = 0; j < cBufCtx; ++j)
5540 {
5541 rc = pHlp->pfnSSMGetBool(pSSM, &f);
5542 AssertLogRelRCReturn(rc, rc);
5543 if (f)
5544 {
5545 pSvgaR3State->apCmdBufCtxs[j] = (PVMSVGACMDBUFCTX)RTMemAlloc(sizeof(VMSVGACMDBUFCTX));
5546 AssertPtrReturn(pSvgaR3State->apCmdBufCtxs[j], VERR_NO_MEMORY);
5547 vmsvgaR3CmdBufCtxInit(pSvgaR3State->apCmdBufCtxs[j]);
5548
5549 rc = vmsvgaR3LoadBufCtx(pDevIns, pThis, pThisCC, pSSM, pSvgaR3State->apCmdBufCtxs[j], (SVGACBContext)j);
5550 AssertLogRelRCReturn(rc, rc);
5551 }
5552 }
5553
5554 rc = pHlp->pfnSSMGetU32(pSSM, &u32);
5555 pSvgaR3State->fCmdBuf = u32;
5556 return rc;
5557}
5558
5559static int vmsvgaR3LoadGbo(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, VMSVGAGBO *pGbo)
5560{
5561 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
5562
5563 int rc;
5564 pHlp->pfnSSMGetU32(pSSM, &pGbo->fGboFlags);
5565 pHlp->pfnSSMGetU32(pSSM, &pGbo->cTotalPages);
5566 pHlp->pfnSSMGetU32(pSSM, &pGbo->cbTotal);
5567 rc = pHlp->pfnSSMGetU32(pSSM, &pGbo->cDescriptors);
5568 AssertRCReturn(rc, rc);
5569
5570 if (pGbo->cDescriptors)
5571 {
5572 pGbo->paDescriptors = (PVMSVGAGBODESCRIPTOR)RTMemAllocZ(pGbo->cDescriptors * sizeof(VMSVGAGBODESCRIPTOR));
5573 AssertPtrReturn(pGbo->paDescriptors, VERR_NO_MEMORY);
5574 }
5575
5576 for (uint32_t iDesc = 0; iDesc < pGbo->cDescriptors; ++iDesc)
5577 {
5578 PVMSVGAGBODESCRIPTOR pDesc = &pGbo->paDescriptors[iDesc];
5579 pHlp->pfnSSMGetGCPhys(pSSM, &pDesc->GCPhys);
5580 rc = pHlp->pfnSSMGetU64(pSSM, &pDesc->cPages);
5581 }
5582
5583 if (pGbo->fGboFlags & VMSVGAGBO_F_HOST_BACKED)
5584 {
5585 pGbo->pvHost = RTMemAlloc(pGbo->cbTotal);
5586 AssertPtrReturn(pGbo->pvHost, VERR_NO_MEMORY);
5587 rc = pHlp->pfnSSMGetMem(pSSM, pGbo->pvHost, pGbo->cbTotal);
5588 }
5589
5590 return rc;
5591}
5592
5593/**
5594 * Portion of VMSVGA state which must be loaded oin the FIFO thread.
5595 */
5596static int vmsvgaR3LoadExecFifo(PCPDMDEVHLPR3 pHlp, PVGASTATE pThis, PVGASTATECC pThisCC,
5597 PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
5598{
5599 RT_NOREF(uPass);
5600
5601 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
5602 int rc;
5603
5604 if (uVersion >= VGA_SAVEDSTATE_VERSION_VMSVGA_SCREENS)
5605 {
5606 uint32_t cScreens = 0;
5607 rc = pHlp->pfnSSMGetU32(pSSM, &cScreens);
5608 AssertRCReturn(rc, rc);
5609 AssertLogRelMsgReturn(cScreens <= _64K, /* big enough */
5610 ("cScreens=%#x\n", cScreens),
5611 VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
5612
5613 for (uint32_t i = 0; i < cScreens; ++i)
5614 {
5615 VMSVGASCREENOBJECT screen;
5616 RT_ZERO(screen);
5617
5618 rc = pHlp->pfnSSMGetStructEx(pSSM, &screen, sizeof(screen), 0, g_aVMSVGASCREENOBJECTFields, NULL);
5619 AssertLogRelRCReturn(rc, rc);
5620
5621 if (screen.idScreen < RT_ELEMENTS(pSVGAState->aScreens))
5622 {
5623 VMSVGASCREENOBJECT *pScreen = &pSVGAState->aScreens[screen.idScreen];
5624 *pScreen = screen;
5625 pScreen->fModified = true;
5626
5627 if (uVersion >= VGA_SAVEDSTATE_VERSION_VMSVGA_DX)
5628 {
5629 uint32_t u32;
5630 pHlp->pfnSSMGetU32(pSSM, &u32); /* Size of screen bitmap. */
5631 AssertLogRelRCReturn(rc, rc);
5632 if (u32)
5633 {
5634 pScreen->pvScreenBitmap = RTMemAlloc(u32);
5635 AssertPtrReturn(pScreen->pvScreenBitmap, VERR_NO_MEMORY);
5636
5637 pHlp->pfnSSMGetMem(pSSM, pScreen->pvScreenBitmap, u32);
5638 }
5639 }
5640 }
5641 else
5642 {
5643 LogRel(("VGA: ignored screen object %d\n", screen.idScreen));
5644 }
5645 }
5646 }
5647 else
5648 {
5649 /* Try to setup at least the first screen. */
5650 VMSVGASCREENOBJECT *pScreen = &pSVGAState->aScreens[0];
5651 pScreen->fDefined = true;
5652 pScreen->fModified = true;
5653 pScreen->fuScreen = SVGA_SCREEN_MUST_BE_SET | SVGA_SCREEN_IS_PRIMARY;
5654 pScreen->idScreen = 0;
5655 pScreen->xOrigin = 0;
5656 pScreen->yOrigin = 0;
5657 pScreen->offVRAM = pThis->svga.uScreenOffset;
5658 pScreen->cbPitch = pThis->svga.cbScanline;
5659 pScreen->cWidth = pThis->svga.uWidth;
5660 pScreen->cHeight = pThis->svga.uHeight;
5661 pScreen->cBpp = pThis->svga.uBpp;
5662 }
5663
5664 return VINF_SUCCESS;
5665}
5666
5667/**
5668 * @copydoc FNSSMDEVLOADEXEC
5669 */
5670int vmsvgaR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
5671{
5672 RT_NOREF(uPass);
5673 PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
5674 PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
5675 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
5676 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
5677 int rc;
5678
5679 /* Load our part of the VGAState */
5680 rc = pHlp->pfnSSMGetStructEx(pSSM, &pThis->svga, sizeof(pThis->svga), 0, g_aVGAStateSVGAFields, NULL);
5681 AssertRCReturn(rc, rc);
5682
5683 /* Load the VGA framebuffer. */
5684 AssertCompile(VMSVGA_VGA_FB_BACKUP_SIZE >= _32K);
5685 uint32_t cbVgaFramebuffer = _32K;
5686 if (uVersion >= VGA_SAVEDSTATE_VERSION_VMSVGA_VGA_FB_FIX)
5687 {
5688 rc = pHlp->pfnSSMGetU32(pSSM, &cbVgaFramebuffer);
5689 AssertRCReturn(rc, rc);
5690 AssertLogRelMsgReturn(cbVgaFramebuffer <= _4M && cbVgaFramebuffer >= _32K && RT_IS_POWER_OF_TWO(cbVgaFramebuffer),
5691 ("cbVgaFramebuffer=%#x - expected 32KB..4MB, power of two\n", cbVgaFramebuffer),
5692 VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
5693 AssertCompile(VMSVGA_VGA_FB_BACKUP_SIZE <= _4M);
5694 AssertCompile(RT_IS_POWER_OF_TWO(VMSVGA_VGA_FB_BACKUP_SIZE));
5695 }
5696 rc = pHlp->pfnSSMGetMem(pSSM, pThisCC->svga.pbVgaFrameBufferR3, RT_MIN(cbVgaFramebuffer, VMSVGA_VGA_FB_BACKUP_SIZE));
5697 AssertRCReturn(rc, rc);
5698 if (cbVgaFramebuffer > VMSVGA_VGA_FB_BACKUP_SIZE)
5699 pHlp->pfnSSMSkip(pSSM, cbVgaFramebuffer - VMSVGA_VGA_FB_BACKUP_SIZE);
5700 else if (cbVgaFramebuffer < VMSVGA_VGA_FB_BACKUP_SIZE)
5701 RT_BZERO(&pThisCC->svga.pbVgaFrameBufferR3[cbVgaFramebuffer], VMSVGA_VGA_FB_BACKUP_SIZE - cbVgaFramebuffer);
5702
5703 /* Load the VMSVGA state. */
5704 rc = pHlp->pfnSSMGetStructEx(pSSM, pSVGAState, sizeof(*pSVGAState), 0, g_aVMSVGAR3STATEFields, NULL);
5705 AssertRCReturn(rc, rc);
5706
5707 /* Load the active cursor bitmaps. */
5708 if (pSVGAState->Cursor.fActive)
5709 {
5710 pSVGAState->Cursor.pData = RTMemAlloc(pSVGAState->Cursor.cbData);
5711 AssertReturn(pSVGAState->Cursor.pData, VERR_NO_MEMORY);
5712
5713 rc = pHlp->pfnSSMGetMem(pSSM, pSVGAState->Cursor.pData, pSVGAState->Cursor.cbData);
5714 AssertRCReturn(rc, rc);
5715 }
5716
5717 /* Load the GMR state. */
5718 uint32_t cGMR = 256; /* Hardcoded in previous saved state versions. */
5719 if (uVersion >= VGA_SAVEDSTATE_VERSION_VMSVGA_GMR_COUNT)
5720 {
5721 rc = pHlp->pfnSSMGetU32(pSSM, &cGMR);
5722 AssertRCReturn(rc, rc);
5723 /* Numbers of GMRs was never less than 256. 1MB is a large arbitrary limit. */
5724 AssertLogRelMsgReturn(cGMR <= _1M && cGMR >= 256,
5725 ("cGMR=%#x - expected 256B..1MB\n", cGMR),
5726 VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
5727 }
5728
5729 if (pThis->svga.cGMR != cGMR)
5730 {
5731 /* Reallocate GMR array. */
5732 Assert(pSVGAState->paGMR != NULL);
5733 RTMemFree(pSVGAState->paGMR);
5734 pSVGAState->paGMR = (PGMR)RTMemAllocZ(cGMR * sizeof(GMR));
5735 AssertReturn(pSVGAState->paGMR, VERR_NO_MEMORY);
5736 pThis->svga.cGMR = cGMR;
5737 }
5738
5739 for (uint32_t i = 0; i < cGMR; ++i)
5740 {
5741 PGMR pGMR = &pSVGAState->paGMR[i];
5742
5743 rc = pHlp->pfnSSMGetStructEx(pSSM, pGMR, sizeof(*pGMR), 0, g_aGMRFields, NULL);
5744 AssertRCReturn(rc, rc);
5745
5746 if (pGMR->numDescriptors)
5747 {
5748 Assert(pGMR->cMaxPages || pGMR->cbTotal);
5749 pGMR->paDesc = (PVMSVGAGMRDESCRIPTOR)RTMemAllocZ(pGMR->numDescriptors * sizeof(VMSVGAGMRDESCRIPTOR));
5750 AssertReturn(pGMR->paDesc, VERR_NO_MEMORY);
5751
5752 for (uint32_t j = 0; j < pGMR->numDescriptors; ++j)
5753 {
5754 rc = pHlp->pfnSSMGetStructEx(pSSM, &pGMR->paDesc[j], sizeof(pGMR->paDesc[j]), 0, g_aVMSVGAGMRDESCRIPTORFields, NULL);
5755 AssertRCReturn(rc, rc);
5756 }
5757 }
5758 }
5759
5760 if (uVersion >= VGA_SAVEDSTATE_VERSION_VMSVGA_DX)
5761 {
5762 bool f;
5763 uint32_t u32;
5764
5765 if (uVersion >= VGA_SAVEDSTATE_VERSION_VMSVGA_DX_CMDBUF)
5766 {
5767 /* Command buffers are saved independently from VGPU10. */
5768 rc = pHlp->pfnSSMGetBool(pSSM, &f);
5769 AssertLogRelRCReturn(rc, rc);
5770 if (f)
5771 {
5772 rc = vmsvgaR3LoadCommandBuffers(pDevIns, pThis, pThisCC, pSSM);
5773 AssertLogRelRCReturn(rc, rc);
5774 }
5775 }
5776
5777 rc = pHlp->pfnSSMGetBool(pSSM, &f);
5778 AssertLogRelRCReturn(rc, rc);
5779 pThis->fVMSVGA10 = f;
5780
5781 if (pThis->fVMSVGA10)
5782 {
5783 if (uVersion < VGA_SAVEDSTATE_VERSION_VMSVGA_DX_CMDBUF)
5784 {
5785 rc = vmsvgaR3LoadCommandBuffers(pDevIns, pThis, pThisCC, pSSM);
5786 AssertLogRelRCReturn(rc, rc);
5787 }
5788
5789 /*
5790 * OTables GBOs.
5791 */
5792 rc = pHlp->pfnSSMGetU32(pSSM, &u32);
5793 AssertLogRelRCReturn(rc, rc);
5794 AssertReturn(u32 == SVGA_OTABLE_MAX, VERR_INVALID_STATE);
5795 for (int i = 0; i < SVGA_OTABLE_MAX; ++i)
5796 {
5797 VMSVGAGBO *pGbo = &pSVGAState->aGboOTables[i];
5798 rc = vmsvgaR3LoadGbo(pDevIns, pSSM, pGbo);
5799 AssertRCReturn(rc, rc);
5800 }
5801
5802 /*
5803 * MOBs.
5804 */
5805 for (;;)
5806 {
5807 rc = pHlp->pfnSSMGetU32(pSSM, &u32); /* MOB id. */
5808 AssertRCReturn(rc, rc);
5809 if (u32 == SVGA_ID_INVALID)
5810 break;
5811
5812 PVMSVGAMOB pMob = (PVMSVGAMOB)RTMemAllocZ(sizeof(*pMob));
5813 AssertPtrReturn(pMob, VERR_NO_MEMORY);
5814
5815 rc = vmsvgaR3LoadGbo(pDevIns, pSSM, &pMob->Gbo);
5816 AssertRCReturn(rc, rc);
5817
5818 pMob->Core.Key = u32;
5819 if (RTAvlU32Insert(&pSVGAState->MOBTree, &pMob->Core))
5820 RTListPrepend(&pSVGAState->MOBLRUList, &pMob->nodeLRU);
5821 else
5822 AssertFailedReturn(VERR_NO_MEMORY);
5823 }
5824
5825# ifdef VMSVGA3D_DX
5826 if (pThis->svga.f3DEnabled)
5827 {
5828 pHlp->pfnSSMGetU32(pSSM, &pSVGAState->idDXContextCurrent);
5829 }
5830# endif
5831 }
5832 }
5833
5834# 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. */
5835 vmsvgaR3PowerOnDevice(pDevIns, pThis, pThisCC, /*fLoadState=*/ true);
5836# endif
5837
5838 VMSVGA_STATE_LOAD LoadState;
5839 LoadState.pSSM = pSSM;
5840 LoadState.uVersion = uVersion;
5841 LoadState.uPass = uPass;
5842 rc = vmsvgaR3RunExtCmdOnFifoThread(pDevIns, pThis, pThisCC, VMSVGA_FIFO_EXTCMD_LOADSTATE, &LoadState, RT_INDEFINITE_WAIT);
5843 AssertLogRelRCReturn(rc, rc);
5844
5845 return VINF_SUCCESS;
5846}
5847
5848/**
5849 * Reinit the video mode after the state has been loaded.
5850 */
5851int vmsvgaR3LoadDone(PPDMDEVINS pDevIns)
5852{
5853 PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
5854 PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
5855 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
5856
5857 /* VMSVGA is working via VBVA interface, therefore it needs to be
5858 * enabled on saved state restore. See @bugref{10071#c7}. */
5859 if (pThis->svga.fEnabled)
5860 {
5861 for (uint32_t idScreen = 0; idScreen < pThis->cMonitors; ++idScreen)
5862 pThisCC->pDrv->pfnVBVAEnable(pThisCC->pDrv, idScreen, NULL /*pHostFlags*/);
5863 }
5864
5865 /* Set the active cursor. */
5866 if (pSVGAState->Cursor.fActive)
5867 {
5868 /* We don't store the alpha flag, but we can take a guess that if
5869 * the old register interface was used, the cursor was B&W.
5870 */
5871 bool fAlpha = pThis->svga.uCursorOn ? false : true;
5872
5873 int rc = pThisCC->pDrv->pfnVBVAMousePointerShape(pThisCC->pDrv,
5874 true /*fVisible*/,
5875 fAlpha,
5876 pSVGAState->Cursor.xHotspot,
5877 pSVGAState->Cursor.yHotspot,
5878 pSVGAState->Cursor.width,
5879 pSVGAState->Cursor.height,
5880 pSVGAState->Cursor.pData);
5881 AssertRC(rc);
5882
5883 if (pThis->svga.uCursorOn)
5884 pThisCC->pDrv->pfnVBVAReportCursorPosition(pThisCC->pDrv, VBVA_CURSOR_VALID_DATA, SVGA_ID_INVALID, pThis->svga.uCursorX, pThis->svga.uCursorY);
5885 }
5886
5887 /* If the VRAM handler should not be registered, we have to explicitly
5888 * unregister it here!
5889 */
5890 if (!pThis->svga.fVRAMTracking)
5891 {
5892 vgaR3UnregisterVRAMHandler(pDevIns, pThis);
5893 }
5894
5895 /* Let the FIFO thread deal with changing the mode. */
5896 ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE);
5897
5898 return VINF_SUCCESS;
5899}
5900
5901static int vmsvgaR3SaveBufCtx(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, PVMSVGACMDBUFCTX pBufCtx)
5902{
5903 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
5904
5905 int rc = pHlp->pfnSSMPutU32(pSSM, pBufCtx->cSubmitted);
5906 AssertLogRelRCReturn(rc, rc);
5907 if (pBufCtx->cSubmitted)
5908 {
5909 PVMSVGACMDBUF pIter;
5910 RTListForEach(&pBufCtx->listSubmitted, pIter, VMSVGACMDBUF, nodeBuffer)
5911 {
5912 pHlp->pfnSSMPutGCPhys(pSSM, pIter->GCPhysCB);
5913 pHlp->pfnSSMPutU32(pSSM, sizeof(SVGACBHeader));
5914 pHlp->pfnSSMPutMem(pSSM, &pIter->hdr, sizeof(SVGACBHeader));
5915 pHlp->pfnSSMPutU32(pSSM, pIter->hdr.length);
5916 if (pIter->hdr.length)
5917 rc = pHlp->pfnSSMPutMem(pSSM, pIter->pvCommands, pIter->hdr.length);
5918 AssertLogRelRCReturn(rc, rc);
5919 }
5920 }
5921 return rc;
5922}
5923
5924static int vmsvgaR3SaveGbo(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, VMSVGAGBO *pGbo)
5925{
5926 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
5927
5928 int rc;
5929 pHlp->pfnSSMPutU32(pSSM, pGbo->fGboFlags);
5930 pHlp->pfnSSMPutU32(pSSM, pGbo->cTotalPages);
5931 pHlp->pfnSSMPutU32(pSSM, pGbo->cbTotal);
5932 rc = pHlp->pfnSSMPutU32(pSSM, pGbo->cDescriptors);
5933 for (uint32_t iDesc = 0; iDesc < pGbo->cDescriptors; ++iDesc)
5934 {
5935 PVMSVGAGBODESCRIPTOR pDesc = &pGbo->paDescriptors[iDesc];
5936 pHlp->pfnSSMPutGCPhys(pSSM, pDesc->GCPhys);
5937 rc = pHlp->pfnSSMPutU64(pSSM, pDesc->cPages);
5938 }
5939 if (pGbo->fGboFlags & VMSVGAGBO_F_HOST_BACKED)
5940 rc = pHlp->pfnSSMPutMem(pSSM, pGbo->pvHost, pGbo->cbTotal);
5941 return rc;
5942}
5943
5944/**
5945 * Portion of SVGA state which must be saved in the FIFO thread.
5946 */
5947static int vmsvgaR3SaveExecFifo(PCPDMDEVHLPR3 pHlp, PVGASTATECC pThisCC, PSSMHANDLE pSSM)
5948{
5949 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
5950 int rc;
5951
5952 /* Save the screen objects. */
5953 /* Count defined screen object. */
5954 uint32_t cScreens = 0;
5955 for (uint32_t i = 0; i < RT_ELEMENTS(pSVGAState->aScreens); ++i)
5956 {
5957 if (pSVGAState->aScreens[i].fDefined)
5958 ++cScreens;
5959 }
5960
5961 rc = pHlp->pfnSSMPutU32(pSSM, cScreens);
5962 AssertLogRelRCReturn(rc, rc);
5963
5964 for (uint32_t i = 0; i < RT_ELEMENTS(pSVGAState->aScreens); ++i)
5965 {
5966 VMSVGASCREENOBJECT *pScreen = &pSVGAState->aScreens[i];
5967 if (!pScreen->fDefined)
5968 continue;
5969
5970 rc = pHlp->pfnSSMPutStructEx(pSSM, pScreen, sizeof(*pScreen), 0, g_aVMSVGASCREENOBJECTFields, NULL);
5971 AssertLogRelRCReturn(rc, rc);
5972
5973 /*
5974 * VGA_SAVEDSTATE_VERSION_VMSVGA_DX
5975 */
5976 if (pScreen->pvScreenBitmap)
5977 {
5978 uint32_t const cbScreenBitmap = pScreen->cHeight * pScreen->cbPitch;
5979 pHlp->pfnSSMPutU32(pSSM, cbScreenBitmap);
5980 pHlp->pfnSSMPutMem(pSSM, pScreen->pvScreenBitmap, cbScreenBitmap);
5981 }
5982 else
5983 pHlp->pfnSSMPutU32(pSSM, 0);
5984 }
5985 return VINF_SUCCESS;
5986}
5987
5988/**
5989 * @copydoc FNSSMDEVSAVEEXEC
5990 */
5991int vmsvgaR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
5992{
5993 PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
5994 PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
5995 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
5996 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
5997 int rc;
5998
5999 /* Save our part of the VGAState */
6000 rc = pHlp->pfnSSMPutStructEx(pSSM, &pThis->svga, sizeof(pThis->svga), 0, g_aVGAStateSVGAFields, NULL);
6001 AssertLogRelRCReturn(rc, rc);
6002
6003 /* Save the framebuffer backup. */
6004 rc = pHlp->pfnSSMPutU32(pSSM, VMSVGA_VGA_FB_BACKUP_SIZE);
6005 rc = pHlp->pfnSSMPutMem(pSSM, pThisCC->svga.pbVgaFrameBufferR3, VMSVGA_VGA_FB_BACKUP_SIZE);
6006 AssertLogRelRCReturn(rc, rc);
6007
6008 /* Save the VMSVGA state. */
6009 rc = pHlp->pfnSSMPutStructEx(pSSM, pSVGAState, sizeof(*pSVGAState), 0, g_aVMSVGAR3STATEFields, NULL);
6010 AssertLogRelRCReturn(rc, rc);
6011
6012 /* Save the active cursor bitmaps. */
6013 if (pSVGAState->Cursor.fActive)
6014 {
6015 rc = pHlp->pfnSSMPutMem(pSSM, pSVGAState->Cursor.pData, pSVGAState->Cursor.cbData);
6016 AssertLogRelRCReturn(rc, rc);
6017 }
6018
6019 /* Save the GMR state */
6020 rc = pHlp->pfnSSMPutU32(pSSM, pThis->svga.cGMR);
6021 AssertLogRelRCReturn(rc, rc);
6022 for (uint32_t i = 0; i < pThis->svga.cGMR; ++i)
6023 {
6024 PGMR pGMR = &pSVGAState->paGMR[i];
6025
6026 rc = pHlp->pfnSSMPutStructEx(pSSM, pGMR, sizeof(*pGMR), 0, g_aGMRFields, NULL);
6027 AssertLogRelRCReturn(rc, rc);
6028
6029 for (uint32_t j = 0; j < pGMR->numDescriptors; ++j)
6030 {
6031 rc = pHlp->pfnSSMPutStructEx(pSSM, &pGMR->paDesc[j], sizeof(pGMR->paDesc[j]), 0, g_aVMSVGAGMRDESCRIPTORFields, NULL);
6032 AssertLogRelRCReturn(rc, rc);
6033 }
6034 }
6035
6036 /*
6037 * VGA_SAVEDSTATE_VERSION_VMSVGA_DX+
6038 */
6039 if (pThis->svga.u32DeviceCaps & SVGA_CAP_COMMAND_BUFFERS)
6040 {
6041 rc = pHlp->pfnSSMPutBool(pSSM, true);
6042 AssertLogRelRCReturn(rc, rc);
6043
6044 /* Device context command buffers. */
6045 rc = vmsvgaR3SaveBufCtx(pDevIns, pSSM, &pSVGAState->CmdBufCtxDC);
6046 AssertRCReturn(rc, rc);
6047
6048 /* DX contexts command buffers. */
6049 rc = pHlp->pfnSSMPutU32(pSSM, RT_ELEMENTS(pSVGAState->apCmdBufCtxs));
6050 AssertLogRelRCReturn(rc, rc);
6051 for (unsigned i = 0; i < RT_ELEMENTS(pSVGAState->apCmdBufCtxs); ++i)
6052 {
6053 if (pSVGAState->apCmdBufCtxs[i])
6054 {
6055 pHlp->pfnSSMPutBool(pSSM, true);
6056 rc = vmsvgaR3SaveBufCtx(pDevIns, pSSM, pSVGAState->apCmdBufCtxs[i]);
6057 AssertRCReturn(rc, rc);
6058 }
6059 else
6060 pHlp->pfnSSMPutBool(pSSM, false);
6061 }
6062
6063 rc = pHlp->pfnSSMPutU32(pSSM, pSVGAState->fCmdBuf);
6064 AssertRCReturn(rc, rc);
6065 }
6066 else
6067 {
6068 rc = pHlp->pfnSSMPutBool(pSSM, false);
6069 AssertLogRelRCReturn(rc, rc);
6070 }
6071
6072 rc = pHlp->pfnSSMPutBool(pSSM, pThis->fVMSVGA10);
6073 AssertLogRelRCReturn(rc, rc);
6074
6075 if (pThis->fVMSVGA10)
6076 {
6077 /*
6078 * OTables GBOs.
6079 */
6080 pHlp->pfnSSMPutU32(pSSM, SVGA_OTABLE_MAX);
6081 for (int i = 0; i < SVGA_OTABLE_MAX; ++i)
6082 {
6083 VMSVGAGBO *pGbo = &pSVGAState->aGboOTables[i];
6084 rc = vmsvgaR3SaveGbo(pDevIns, pSSM, pGbo);
6085 AssertRCReturn(rc, rc);
6086 }
6087
6088 /*
6089 * MOBs.
6090 */
6091 PVMSVGAMOB pIter;
6092 RTListForEach(&pSVGAState->MOBLRUList, pIter, VMSVGAMOB, nodeLRU)
6093 {
6094 pHlp->pfnSSMPutU32(pSSM, pIter->Core.Key); /* MOB id. */
6095 rc = vmsvgaR3SaveGbo(pDevIns, pSSM, &pIter->Gbo);
6096 AssertRCReturn(rc, rc);
6097 }
6098
6099 pHlp->pfnSSMPutU32(pSSM, SVGA_ID_INVALID); /* End marker. */
6100
6101# ifdef VMSVGA3D_DX
6102 if (pThis->svga.f3DEnabled)
6103 {
6104 pHlp->pfnSSMPutU32(pSSM, pSVGAState->idDXContextCurrent);
6105 }
6106# endif
6107 }
6108
6109 /*
6110 * Must save some state (3D in particular) in the FIFO thread.
6111 */
6112 rc = vmsvgaR3RunExtCmdOnFifoThread(pDevIns, pThis, pThisCC, VMSVGA_FIFO_EXTCMD_SAVESTATE, pSSM, RT_INDEFINITE_WAIT);
6113 AssertLogRelRCReturn(rc, rc);
6114
6115 return VINF_SUCCESS;
6116}
6117
6118/**
6119 * Destructor for PVMSVGAR3STATE structure. The structure is not deallocated.
6120 *
6121 * @param pThis The shared VGA/VMSVGA instance data.
6122 * @param pThisCC The device context.
6123 */
6124static void vmsvgaR3StateTerm(PVGASTATE pThis, PVGASTATECC pThisCC)
6125{
6126 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
6127
6128# ifndef VMSVGA_USE_EMT_HALT_CODE
6129 if (pSVGAState->hBusyDelayedEmts != NIL_RTSEMEVENTMULTI)
6130 {
6131 RTSemEventMultiDestroy(pSVGAState->hBusyDelayedEmts);
6132 pSVGAState->hBusyDelayedEmts = NIL_RTSEMEVENT;
6133 }
6134# endif
6135
6136 if (pSVGAState->Cursor.fActive)
6137 {
6138 RTMemFreeZ(pSVGAState->Cursor.pData, pSVGAState->Cursor.cbData);
6139 pSVGAState->Cursor.pData = NULL;
6140 pSVGAState->Cursor.fActive = false;
6141 }
6142
6143 if (pSVGAState->paGMR)
6144 {
6145 for (unsigned i = 0; i < pThis->svga.cGMR; ++i)
6146 if (pSVGAState->paGMR[i].paDesc)
6147 RTMemFree(pSVGAState->paGMR[i].paDesc);
6148
6149 RTMemFree(pSVGAState->paGMR);
6150 pSVGAState->paGMR = NULL;
6151 }
6152
6153 if (RTCritSectIsInitialized(&pSVGAState->CritSectCmdBuf))
6154 {
6155 RTCritSectEnter(&pSVGAState->CritSectCmdBuf);
6156 for (unsigned i = 0; i < RT_ELEMENTS(pSVGAState->apCmdBufCtxs); ++i)
6157 {
6158 vmsvgaR3CmdBufCtxTerm(pSVGAState->apCmdBufCtxs[i]);
6159 pSVGAState->apCmdBufCtxs[i] = NULL;
6160 }
6161 vmsvgaR3CmdBufCtxTerm(&pSVGAState->CmdBufCtxDC);
6162 RTCritSectLeave(&pSVGAState->CritSectCmdBuf);
6163 RTCritSectDelete(&pSVGAState->CritSectCmdBuf);
6164 }
6165}
6166
6167/**
6168 * Constructor for PVMSVGAR3STATE structure.
6169 *
6170 * @returns VBox status code.
6171 * @param pDevIns The PDM device instance.
6172 * @param pThis The shared VGA/VMSVGA instance data.
6173 * @param pSVGAState Pointer to the structure. It is already allocated.
6174 */
6175static int vmsvgaR3StateInit(PPDMDEVINS pDevIns, PVGASTATE pThis, PVMSVGAR3STATE pSVGAState)
6176{
6177 int rc = VINF_SUCCESS;
6178
6179 pSVGAState->pDevIns = pDevIns;
6180
6181 pSVGAState->paGMR = (PGMR)RTMemAllocZ(pThis->svga.cGMR * sizeof(GMR));
6182 AssertReturn(pSVGAState->paGMR, VERR_NO_MEMORY);
6183
6184# ifndef VMSVGA_USE_EMT_HALT_CODE
6185 /* Create semaphore for delaying EMTs wait for the FIFO to stop being busy. */
6186 rc = RTSemEventMultiCreate(&pSVGAState->hBusyDelayedEmts);
6187 AssertRCReturn(rc, rc);
6188# endif
6189
6190 rc = RTCritSectInit(&pSVGAState->CritSectCmdBuf);
6191 AssertRCReturn(rc, rc);
6192
6193 vmsvgaR3CmdBufCtxInit(&pSVGAState->CmdBufCtxDC);
6194
6195 RTListInit(&pSVGAState->MOBLRUList);
6196# ifdef VBOX_WITH_VMSVGA3D
6197# ifdef VMSVGA3D_DX
6198 pSVGAState->idDXContextCurrent = SVGA3D_INVALID_ID;
6199# endif
6200# endif
6201 return rc;
6202}
6203
6204# ifdef VBOX_WITH_VMSVGA3D
6205static void vmsvga3dR3Free3dInterfaces(PVGASTATECC pThisCC)
6206{
6207 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
6208
6209 RTMemFree(pSVGAState->pFuncsMap);
6210 pSVGAState->pFuncsMap = NULL;
6211 RTMemFree(pSVGAState->pFuncsGBO);
6212 pSVGAState->pFuncsGBO = NULL;
6213 RTMemFree(pSVGAState->pFuncsDX);
6214 pSVGAState->pFuncsDX = NULL;
6215 RTMemFree(pSVGAState->pFuncsVGPU9);
6216 pSVGAState->pFuncsVGPU9 = NULL;
6217 RTMemFree(pSVGAState->pFuncs3D);
6218 pSVGAState->pFuncs3D = NULL;
6219}
6220
6221/* This structure is used only by vmsvgaR3Init3dInterfaces */
6222typedef struct VMSVGA3DINTERFACE
6223{
6224 char const *pcszName;
6225 uint32_t cbFuncs;
6226 void **ppvFuncs;
6227} VMSVGA3DINTERFACE;
6228
6229extern VMSVGA3DBACKENDDESC const g_BackendLegacy;
6230#if defined(VMSVGA3D_DX_BACKEND)
6231extern VMSVGA3DBACKENDDESC const g_BackendDX;
6232#endif
6233
6234/**
6235 * Initializes the optional host 3D backend interfaces.
6236 *
6237 * @returns VBox status code.
6238 * @param pThisCC The VGA/VMSVGA state for ring-3.
6239 */
6240static int vmsvgaR3Init3dInterfaces(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC)
6241{
6242#ifndef VMSVGA3D_DX
6243 RT_NOREF(pThis);
6244#endif
6245
6246 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
6247
6248#define ENTRY_3D_INTERFACE(a_Name, a_Field) { VMSVGA3D_BACKEND_INTERFACE_NAME_##a_Name, sizeof(VMSVGA3DBACKENDFUNCS##a_Name), (void **)&pSVGAState->a_Field }
6249 VMSVGA3DINTERFACE a3dInterface[] =
6250 {
6251 ENTRY_3D_INTERFACE(3D, pFuncs3D),
6252 ENTRY_3D_INTERFACE(VGPU9, pFuncsVGPU9),
6253 ENTRY_3D_INTERFACE(DX, pFuncsDX),
6254 ENTRY_3D_INTERFACE(MAP, pFuncsMap),
6255 ENTRY_3D_INTERFACE(GBO, pFuncsGBO),
6256 };
6257#undef ENTRY_3D_INTERFACE
6258
6259 VMSVGA3DBACKENDDESC const *pBackend = NULL;
6260#if defined(VMSVGA3D_DX_BACKEND)
6261 if (pThis->fVMSVGA10)
6262 pBackend = &g_BackendDX;
6263 else
6264#endif
6265 pBackend = &g_BackendLegacy;
6266
6267 int rc = VINF_SUCCESS;
6268 for (uint32_t i = 0; i < RT_ELEMENTS(a3dInterface); ++i)
6269 {
6270 VMSVGA3DINTERFACE *p = &a3dInterface[i];
6271
6272 int rc2 = pBackend->pfnQueryInterface(pThisCC, p->pcszName, NULL, p->cbFuncs);
6273 if (RT_SUCCESS(rc2))
6274 {
6275 *p->ppvFuncs = RTMemAllocZ(p->cbFuncs);
6276 AssertBreakStmt(*p->ppvFuncs, rc = VERR_NO_MEMORY);
6277
6278 pBackend->pfnQueryInterface(pThisCC, p->pcszName, *p->ppvFuncs, p->cbFuncs);
6279 }
6280 }
6281
6282 if (RT_SUCCESS(rc))
6283 {
6284 /* 3D interface is required. */
6285 if (pSVGAState->pFuncs3D)
6286 {
6287 rc = pSVGAState->pFuncs3D->pfnInit(pDevIns, pThis, pThisCC);
6288 if (RT_SUCCESS(rc))
6289 return VINF_SUCCESS;
6290 }
6291 else
6292 rc = VERR_NOT_SUPPORTED;
6293 }
6294
6295 vmsvga3dR3Free3dInterfaces(pThisCC);
6296 return rc;
6297}
6298# endif /* VBOX_WITH_VMSVGA3D */
6299
6300/**
6301 * Compute the host capabilities: device and FIFO.
6302 * Depends on 3D backend initialization.
6303 *
6304 * @returns VBox status code.
6305 * @param pThis The shared VGA/VMSVGA instance data.
6306 * @param pThisCC The VGA/VMSVGA state for ring-3.
6307 * @param pu32DeviceCaps Device capabilities (SVGA_CAP_*).
6308 * @param pu32FIFOCaps FIFO capabilities (SVGA_FIFO_CAPS_*).
6309 */
6310static void vmsvgaR3GetCaps(PVGASTATE pThis, PVGASTATECC pThisCC, uint32_t *pu32DeviceCaps, uint32_t *pu32FIFOCaps)
6311{
6312#ifndef VBOX_WITH_VMSVGA3D
6313 RT_NOREF(pThisCC);
6314#endif
6315
6316 /* Device caps. */
6317 *pu32DeviceCaps = SVGA_CAP_GMR
6318 | SVGA_CAP_GMR2
6319 | SVGA_CAP_CURSOR
6320 | SVGA_CAP_CURSOR_BYPASS
6321 | SVGA_CAP_CURSOR_BYPASS_2
6322 | SVGA_CAP_EXTENDED_FIFO
6323 | SVGA_CAP_IRQMASK
6324 | SVGA_CAP_PITCHLOCK
6325 | SVGA_CAP_RECT_COPY
6326 | SVGA_CAP_TRACES
6327 | SVGA_CAP_SCREEN_OBJECT_2
6328 | SVGA_CAP_ALPHA_CURSOR;
6329
6330 *pu32DeviceCaps |= SVGA_CAP_COMMAND_BUFFERS /* Enable register based command buffer submission. */
6331// | SVGA_CAP_CMD_BUFFERS_2 /* Support for SVGA_REG_CMD_PREPEND_LOW/HIGH */
6332 ;
6333
6334 /* VGPU10 capabilities. */
6335 if (pThis->fVMSVGA10)
6336 {
6337# ifdef VBOX_WITH_VMSVGA3D
6338 if (pThisCC->svga.pSvgaR3State->pFuncsGBO)
6339 *pu32DeviceCaps |= SVGA_CAP_GBOBJECTS; /* Enable guest-backed objects and surfaces. */
6340 if (pThisCC->svga.pSvgaR3State->pFuncsDX)
6341 *pu32DeviceCaps |= SVGA_CAP_DX; /* Enable support for DX commands, and command buffers in a mob. */
6342# endif
6343 }
6344
6345# ifdef VBOX_WITH_VMSVGA3D
6346 if (pThisCC->svga.pSvgaR3State->pFuncs3D)
6347 *pu32DeviceCaps |= SVGA_CAP_3D;
6348# endif
6349
6350 /* FIFO capabilities. */
6351 *pu32FIFOCaps = SVGA_FIFO_CAP_FENCE
6352 | SVGA_FIFO_CAP_PITCHLOCK
6353 | SVGA_FIFO_CAP_CURSOR_BYPASS_3
6354 | SVGA_FIFO_CAP_RESERVE
6355 | SVGA_FIFO_CAP_GMR2
6356 | SVGA_FIFO_CAP_3D_HWVERSION_REVISED
6357 | SVGA_FIFO_CAP_SCREEN_OBJECT_2;
6358}
6359
6360/** Initialize the FIFO on power on and reset.
6361 *
6362 * @param pThis The shared VGA/VMSVGA instance data.
6363 * @param pThisCC The VGA/VMSVGA state for ring-3.
6364 */
6365static void vmsvgaR3InitFIFO(PVGASTATE pThis, PVGASTATECC pThisCC)
6366{
6367 RT_BZERO(pThisCC->svga.pau32FIFO, pThis->svga.cbFIFO);
6368
6369 /* Valid with SVGA_FIFO_CAP_SCREEN_OBJECT_2 */
6370 pThisCC->svga.pau32FIFO[SVGA_FIFO_CURSOR_SCREEN_ID] = SVGA_ID_INVALID;
6371}
6372
6373# ifdef VBOX_WITH_VMSVGA3D
6374/**
6375 * Initializes the host 3D capabilities and writes them to FIFO memory.
6376 *
6377 * @returns VBox status code.
6378 * @param pThis The shared VGA/VMSVGA instance data.
6379 * @param pThisCC The VGA/VMSVGA state for ring-3.
6380 */
6381static void vmsvgaR3InitFifo3DCaps(PVGASTATE pThis, PVGASTATECC pThisCC)
6382{
6383 /* Query the capabilities and store them in the pThis->svga.au32DevCaps array. */
6384 bool const fSavedBuffering = RTLogRelSetBuffering(true);
6385
6386 for (unsigned i = 0; i < RT_ELEMENTS(pThis->svga.au32DevCaps); ++i)
6387 {
6388 uint32_t val = 0;
6389 int rc = vmsvga3dQueryCaps(pThisCC, (SVGA3dDevCapIndex)i, &val);
6390 if (RT_SUCCESS(rc))
6391 pThis->svga.au32DevCaps[i] = val;
6392 else
6393 pThis->svga.au32DevCaps[i] = 0;
6394
6395 /* LogRel the capability value. */
6396 if (i < SVGA3D_DEVCAP_MAX)
6397 {
6398 char const *pszDevCapName = &vmsvgaDevCapIndexToString((SVGA3dDevCapIndex)i)[sizeof("SVGA3D_DEVCAP")];
6399 if (RT_SUCCESS(rc))
6400 {
6401 if ( i == SVGA3D_DEVCAP_MAX_POINT_SIZE
6402 || i == SVGA3D_DEVCAP_MAX_LINE_WIDTH
6403 || i == SVGA3D_DEVCAP_MAX_AA_LINE_WIDTH)
6404 {
6405 float const fval = *(float *)&val;
6406 LogRel(("VMSVGA3d: cap[%u]=" FLOAT_FMT_STR " {%s}\n", i, FLOAT_FMT_ARGS(fval), pszDevCapName));
6407 }
6408 else
6409 LogRel(("VMSVGA3d: cap[%u]=%#010x {%s}\n", i, val, pszDevCapName));
6410 }
6411 else
6412 LogRel(("VMSVGA3d: cap[%u]=failed rc=%Rrc {%s}\n", i, rc, pszDevCapName));
6413 }
6414 else
6415 LogRel(("VMSVGA3d: new cap[%u]=%#010x rc=%Rrc\n", i, val, rc));
6416 }
6417
6418 RTLogRelSetBuffering(fSavedBuffering);
6419
6420 /* 3d hardware version; latest and greatest */
6421 pThisCC->svga.pau32FIFO[SVGA_FIFO_3D_HWVERSION_REVISED] = SVGA3D_HWVERSION_CURRENT;
6422 pThisCC->svga.pau32FIFO[SVGA_FIFO_3D_HWVERSION] = SVGA3D_HWVERSION_CURRENT;
6423
6424 /* Fill out 3d capabilities up to SVGA3D_DEVCAP_SURFACEFMT_ATI2 in the FIFO memory.
6425 * SVGA3D_DEVCAP_SURFACEFMT_ATI2 is the last capabiltiy for pre-SVGA_CAP_GBOBJECTS hardware.
6426 * If the VMSVGA device supports SVGA_CAP_GBOBJECTS capability, then the guest has to use SVGA_REG_DEV_CAP
6427 * register to query the devcaps. Older guests will still try to read the devcaps from FIFO.
6428 */
6429 SVGA3dCapsRecord *pCaps;
6430 SVGA3dCapPair *pData;
6431
6432 pCaps = (SVGA3dCapsRecord *)&pThisCC->svga.pau32FIFO[SVGA_FIFO_3D_CAPS];
6433 pCaps->header.type = SVGA3DCAPS_RECORD_DEVCAPS;
6434 pData = (SVGA3dCapPair *)&pCaps->data;
6435
6436 AssertCompile(SVGA3D_DEVCAP_DEAD1 == SVGA3D_DEVCAP_SURFACEFMT_ATI2 + 1);
6437 for (unsigned i = 0; i < SVGA3D_DEVCAP_DEAD1; ++i)
6438 {
6439 pData[i][0] = i;
6440 pData[i][1] = pThis->svga.au32DevCaps[i];
6441 }
6442 pCaps->header.length = (sizeof(pCaps->header) + SVGA3D_DEVCAP_DEAD1 * sizeof(SVGA3dCapPair)) / sizeof(uint32_t);
6443 pCaps = (SVGA3dCapsRecord *)((uint32_t *)pCaps + pCaps->header.length);
6444
6445 /* Mark end of record array (a zero word). */
6446 pCaps->header.length = 0;
6447}
6448
6449# endif
6450
6451/**
6452 * Resets the SVGA hardware state
6453 *
6454 * @returns VBox status code.
6455 * @param pDevIns The device instance.
6456 */
6457int vmsvgaR3Reset(PPDMDEVINS pDevIns)
6458{
6459 PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
6460 PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
6461 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
6462
6463 /* Reset before init? */
6464 if (!pSVGAState)
6465 return VINF_SUCCESS;
6466
6467 Log(("vmsvgaR3Reset\n"));
6468
6469 /* Reset the FIFO processing as well as the 3d state (if we have one). */
6470 pThisCC->svga.pau32FIFO[SVGA_FIFO_NEXT_CMD] = pThisCC->svga.pau32FIFO[SVGA_FIFO_STOP] = 0; /** @todo should probably let the FIFO thread do this ... */
6471 int rc = vmsvgaR3RunExtCmdOnFifoThread(pDevIns, pThis, pThisCC, VMSVGA_FIFO_EXTCMD_RESET, NULL /*pvParam*/, 10000 /*ms*/);
6472
6473 /* Reset other stuff. */
6474 pThis->svga.cScratchRegion = VMSVGA_SCRATCH_SIZE;
6475 RT_ZERO(pThis->svga.au32ScratchRegion);
6476
6477 ASMAtomicWriteBool(&pThis->svga.fBadGuest, false);
6478
6479 vmsvgaR3StateTerm(pThis, pThisCC);
6480 vmsvgaR3StateInit(pDevIns, pThis, pThisCC->svga.pSvgaR3State);
6481
6482 RT_BZERO(pThisCC->svga.pbVgaFrameBufferR3, VMSVGA_VGA_FB_BACKUP_SIZE);
6483
6484 vmsvgaR3InitFIFO(pThis, pThisCC);
6485
6486 /* Initialize FIFO and register capabilities. */
6487 vmsvgaR3GetCaps(pThis, pThisCC, &pThis->svga.u32DeviceCaps, &pThisCC->svga.pau32FIFO[SVGA_FIFO_CAPABILITIES]);
6488
6489# ifdef VBOX_WITH_VMSVGA3D
6490 if (pThis->svga.f3DEnabled)
6491 vmsvgaR3InitFifo3DCaps(pThis, pThisCC);
6492# endif
6493
6494 /* VRAM tracking is enabled by default during bootup. */
6495 pThis->svga.fVRAMTracking = true;
6496 pThis->svga.fEnabled = false;
6497
6498 /* Invalidate current settings. */
6499 pThis->svga.uWidth = VMSVGA_VAL_UNINITIALIZED;
6500 pThis->svga.uHeight = VMSVGA_VAL_UNINITIALIZED;
6501 pThis->svga.uBpp = pThis->svga.uHostBpp;
6502 pThis->svga.cbScanline = 0;
6503 pThis->svga.u32PitchLock = 0;
6504
6505 return rc;
6506}
6507
6508/**
6509 * Cleans up the SVGA hardware state
6510 *
6511 * @returns VBox status code.
6512 * @param pDevIns The device instance.
6513 */
6514int vmsvgaR3Destruct(PPDMDEVINS pDevIns)
6515{
6516 PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
6517 PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
6518
6519 /*
6520 * Ask the FIFO thread to terminate the 3d state and then terminate it.
6521 */
6522 if (pThisCC->svga.pFIFOIOThread)
6523 {
6524 int rc = vmsvgaR3RunExtCmdOnFifoThread(pDevIns, pThis, pThisCC, VMSVGA_FIFO_EXTCMD_TERMINATE,
6525 NULL /*pvParam*/, 30000 /*ms*/);
6526 AssertLogRelRC(rc);
6527
6528 rc = PDMDevHlpThreadDestroy(pDevIns, pThisCC->svga.pFIFOIOThread, NULL);
6529 AssertLogRelRC(rc);
6530 pThisCC->svga.pFIFOIOThread = NULL;
6531 }
6532
6533 /*
6534 * Destroy the special SVGA state.
6535 */
6536 if (pThisCC->svga.pSvgaR3State)
6537 {
6538 vmsvgaR3StateTerm(pThis, pThisCC);
6539
6540# ifdef VBOX_WITH_VMSVGA3D
6541 vmsvga3dR3Free3dInterfaces(pThisCC);
6542# endif
6543
6544 RTMemFree(pThisCC->svga.pSvgaR3State);
6545 pThisCC->svga.pSvgaR3State = NULL;
6546 }
6547
6548 /*
6549 * Free our resources residing in the VGA state.
6550 */
6551 if (pThisCC->svga.pbVgaFrameBufferR3)
6552 {
6553 RTMemFree(pThisCC->svga.pbVgaFrameBufferR3);
6554 pThisCC->svga.pbVgaFrameBufferR3 = NULL;
6555 }
6556 if (pThisCC->svga.hFIFOExtCmdSem != NIL_RTSEMEVENT)
6557 {
6558 RTSemEventDestroy(pThisCC->svga.hFIFOExtCmdSem);
6559 pThisCC->svga.hFIFOExtCmdSem = NIL_RTSEMEVENT;
6560 }
6561 if (pThis->svga.hFIFORequestSem != NIL_SUPSEMEVENT)
6562 {
6563 PDMDevHlpSUPSemEventClose(pDevIns, pThis->svga.hFIFORequestSem);
6564 pThis->svga.hFIFORequestSem = NIL_SUPSEMEVENT;
6565 }
6566
6567 return VINF_SUCCESS;
6568}
6569
6570static DECLCALLBACK(size_t) vmsvga3dFloatFormat(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
6571 const char *pszType, void const *pvValue,
6572 int cchWidth, int cchPrecision, unsigned fFlags, void *pvUser)
6573{
6574 RT_NOREF(pszType, cchWidth, cchPrecision, fFlags, pvUser);
6575 double const v = *(double *)&pvValue;
6576 return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, FLOAT_FMT_STR, FLOAT_FMT_ARGS(v));
6577}
6578
6579/**
6580 * Initialize the SVGA hardware state
6581 *
6582 * @returns VBox status code.
6583 * @param pDevIns The device instance.
6584 */
6585int vmsvgaR3Init(PPDMDEVINS pDevIns)
6586{
6587 PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
6588 PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
6589 PVMSVGAR3STATE pSVGAState;
6590 int rc;
6591
6592 rc = RTStrFormatTypeRegister("float", vmsvga3dFloatFormat, NULL);
6593 AssertMsgReturn(RT_SUCCESS(rc) || rc == VERR_ALREADY_EXISTS, ("%Rrc\n", rc), rc);
6594
6595 pThis->svga.cScratchRegion = VMSVGA_SCRATCH_SIZE;
6596 memset(pThis->svga.au32ScratchRegion, 0, sizeof(pThis->svga.au32ScratchRegion));
6597
6598 pThis->svga.cGMR = VMSVGA_MAX_GMR_IDS;
6599
6600 /* Necessary for creating a backup of the text mode frame buffer when switching into svga mode. */
6601 pThisCC->svga.pbVgaFrameBufferR3 = (uint8_t *)RTMemAllocZ(VMSVGA_VGA_FB_BACKUP_SIZE);
6602 AssertReturn(pThisCC->svga.pbVgaFrameBufferR3, VERR_NO_MEMORY);
6603
6604 /* Create event semaphore. */
6605 rc = PDMDevHlpSUPSemEventCreate(pDevIns, &pThis->svga.hFIFORequestSem);
6606 AssertRCReturn(rc, rc);
6607
6608 /* Create event semaphore. */
6609 rc = RTSemEventCreate(&pThisCC->svga.hFIFOExtCmdSem);
6610 AssertRCReturn(rc, rc);
6611
6612 pThisCC->svga.pSvgaR3State = (PVMSVGAR3STATE)RTMemAllocZ(sizeof(VMSVGAR3STATE));
6613 AssertReturn(pThisCC->svga.pSvgaR3State, VERR_NO_MEMORY);
6614
6615 rc = vmsvgaR3StateInit(pDevIns, pThis, pThisCC->svga.pSvgaR3State);
6616 AssertMsgRCReturn(rc, ("Failed to create pSvgaR3State.\n"), rc);
6617
6618 pSVGAState = pThisCC->svga.pSvgaR3State;
6619
6620 /* Register the write-protected GBO access handler type (no ring-0 callbacks here). */
6621 rc = PDMDevHlpPGMHandlerPhysicalTypeRegister(pDevIns, PGMPHYSHANDLERKIND_WRITE, vmsvgaR3GboAccessHandler,
6622 "VMSVGA GBO", &pSVGAState->hGboAccessHandlerType);
6623 AssertRCReturn(rc, rc);
6624
6625 /* VRAM tracking is enabled by default during bootup. */
6626 pThis->svga.fVRAMTracking = true;
6627
6628 /* Set up the host bpp. This value is as a default for the programmable
6629 * bpp value. On old implementations, SVGA_REG_HOST_BITS_PER_PIXEL did not
6630 * exist and SVGA_REG_BITS_PER_PIXEL was read-only, returning what was later
6631 * separated as SVGA_REG_HOST_BITS_PER_PIXEL.
6632 *
6633 * NB: The driver cBits value is currently constant for the lifetime of the
6634 * VM. If that changes, the host bpp logic might need revisiting.
6635 */
6636 pThis->svga.uHostBpp = (pThisCC->pDrv->cBits + 7) & ~7;
6637
6638 /* Invalidate current settings. */
6639 pThis->svga.uWidth = VMSVGA_VAL_UNINITIALIZED;
6640 pThis->svga.uHeight = VMSVGA_VAL_UNINITIALIZED;
6641 pThis->svga.uBpp = pThis->svga.uHostBpp;
6642 pThis->svga.cbScanline = 0;
6643
6644 pThis->svga.u32MaxWidth = VBE_DISPI_MAX_XRES;
6645 pThis->svga.u32MaxHeight = VBE_DISPI_MAX_YRES;
6646 while (pThis->svga.u32MaxWidth * pThis->svga.u32MaxHeight * 4 /* 32 bpp */ > pThis->vram_size)
6647 {
6648 pThis->svga.u32MaxWidth -= 256;
6649 pThis->svga.u32MaxHeight -= 256;
6650 }
6651 Log(("VMSVGA: Maximum size (%d,%d)\n", pThis->svga.u32MaxWidth, pThis->svga.u32MaxHeight));
6652
6653# ifdef DEBUG_GMR_ACCESS
6654 /* Register the GMR access handler type. */
6655 rc = PDMDevHlpPGMHandlerPhysicalTypeRegister(pDevIns, PGMPHYSHANDLERKIND_WRITE, vmsvgaR3GmrAccessHandler,
6656 "VMSVGA GMR", &pThis->svga.hGmrAccessHandlerType);
6657 AssertRCReturn(rc, rc);
6658# endif
6659
6660# if defined(VMSVGA_USE_FIFO_ACCESS_HANDLER) || defined(DEBUG_FIFO_ACCESS)
6661 /* Register the FIFO access handler type. In addition to debugging FIFO
6662 access, this is also used to facilitate extended fifo thread sleeps. */
6663 rc = PDMDevHlpPGMHandlerPhysicalTypeRegister(pDevIns,
6664# ifdef DEBUG_FIFO_ACCESS
6665 PGMPHYSHANDLERKIND_ALL,
6666# else
6667 PGMPHYSHANDLERKIND_WRITE,
6668# endif
6669 vmsvgaR3FifoAccessHandler,
6670 "VMSVGA FIFO", &pThis->svga.hFifoAccessHandlerType);
6671 AssertRCReturn(rc, rc);
6672# endif
6673
6674 /* Create the async IO thread. */
6675 rc = PDMDevHlpThreadCreate(pDevIns, &pThisCC->svga.pFIFOIOThread, pThis, vmsvgaR3FifoLoop, vmsvgaR3FifoLoopWakeUp, 0,
6676 RTTHREADTYPE_IO, "VMSVGA FIFO");
6677 if (RT_FAILURE(rc))
6678 {
6679 AssertMsgFailed(("%s: Async IO Thread creation for FIFO handling failed rc=%d\n", __FUNCTION__, rc));
6680 return rc;
6681 }
6682
6683 /*
6684 * Statistics.
6685 */
6686# define REG_CNT(a_pvSample, a_pszName, a_pszDesc) \
6687 PDMDevHlpSTAMRegister(pDevIns, (a_pvSample), STAMTYPE_COUNTER, a_pszName, STAMUNIT_OCCURENCES, a_pszDesc)
6688# define REG_PRF(a_pvSample, a_pszName, a_pszDesc) \
6689 PDMDevHlpSTAMRegister(pDevIns, (a_pvSample), STAMTYPE_PROFILE, a_pszName, STAMUNIT_TICKS_PER_CALL, a_pszDesc)
6690# ifdef VBOX_WITH_STATISTICS
6691 REG_PRF(&pSVGAState->StatR3Cmd3dDrawPrimitivesProf, "VMSVGA/Cmd/3dDrawPrimitivesProf", "Profiling of SVGA_3D_CMD_DRAW_PRIMITIVES.");
6692 REG_PRF(&pSVGAState->StatR3Cmd3dPresentProf, "VMSVGA/Cmd/3dPresentProfBoth", "Profiling of SVGA_3D_CMD_PRESENT and SVGA_3D_CMD_PRESENT_READBACK.");
6693 REG_PRF(&pSVGAState->StatR3Cmd3dSurfaceDmaProf, "VMSVGA/Cmd/3dSurfaceDmaProf", "Profiling of SVGA_3D_CMD_SURFACE_DMA.");
6694# endif
6695 REG_PRF(&pSVGAState->StatR3Cmd3dBlitSurfaceToScreenProf, "VMSVGA/Cmd/3dBlitSurfaceToScreenProf", "Profiling of SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN.");
6696 REG_CNT(&pSVGAState->StatR3Cmd3dActivateSurface, "VMSVGA/Cmd/3dActivateSurface", "SVGA_3D_CMD_ACTIVATE_SURFACE");
6697 REG_CNT(&pSVGAState->StatR3Cmd3dBeginQuery, "VMSVGA/Cmd/3dBeginQuery", "SVGA_3D_CMD_BEGIN_QUERY");
6698 REG_CNT(&pSVGAState->StatR3Cmd3dClear, "VMSVGA/Cmd/3dClear", "SVGA_3D_CMD_CLEAR");
6699 REG_CNT(&pSVGAState->StatR3Cmd3dContextDefine, "VMSVGA/Cmd/3dContextDefine", "SVGA_3D_CMD_CONTEXT_DEFINE");
6700 REG_CNT(&pSVGAState->StatR3Cmd3dContextDestroy, "VMSVGA/Cmd/3dContextDestroy", "SVGA_3D_CMD_CONTEXT_DESTROY");
6701 REG_CNT(&pSVGAState->StatR3Cmd3dDeactivateSurface, "VMSVGA/Cmd/3dDeactivateSurface", "SVGA_3D_CMD_DEACTIVATE_SURFACE");
6702 REG_CNT(&pSVGAState->StatR3Cmd3dDrawPrimitives, "VMSVGA/Cmd/3dDrawPrimitives", "SVGA_3D_CMD_DRAW_PRIMITIVES");
6703 REG_CNT(&pSVGAState->StatR3Cmd3dEndQuery, "VMSVGA/Cmd/3dEndQuery", "SVGA_3D_CMD_END_QUERY");
6704 REG_CNT(&pSVGAState->StatR3Cmd3dGenerateMipmaps, "VMSVGA/Cmd/3dGenerateMipmaps", "SVGA_3D_CMD_GENERATE_MIPMAPS");
6705 REG_CNT(&pSVGAState->StatR3Cmd3dPresent, "VMSVGA/Cmd/3dPresent", "SVGA_3D_CMD_PRESENT");
6706 REG_CNT(&pSVGAState->StatR3Cmd3dPresentReadBack, "VMSVGA/Cmd/3dPresentReadBack", "SVGA_3D_CMD_PRESENT_READBACK");
6707 REG_CNT(&pSVGAState->StatR3Cmd3dSetClipPlane, "VMSVGA/Cmd/3dSetClipPlane", "SVGA_3D_CMD_SETCLIPPLANE");
6708 REG_CNT(&pSVGAState->StatR3Cmd3dSetLightData, "VMSVGA/Cmd/3dSetLightData", "SVGA_3D_CMD_SETLIGHTDATA");
6709 REG_CNT(&pSVGAState->StatR3Cmd3dSetLightEnable, "VMSVGA/Cmd/3dSetLightEnable", "SVGA_3D_CMD_SETLIGHTENABLE");
6710 REG_CNT(&pSVGAState->StatR3Cmd3dSetMaterial, "VMSVGA/Cmd/3dSetMaterial", "SVGA_3D_CMD_SETMATERIAL");
6711 REG_CNT(&pSVGAState->StatR3Cmd3dSetRenderState, "VMSVGA/Cmd/3dSetRenderState", "SVGA_3D_CMD_SETRENDERSTATE");
6712 REG_CNT(&pSVGAState->StatR3Cmd3dSetRenderTarget, "VMSVGA/Cmd/3dSetRenderTarget", "SVGA_3D_CMD_SETRENDERTARGET");
6713 REG_CNT(&pSVGAState->StatR3Cmd3dSetScissorRect, "VMSVGA/Cmd/3dSetScissorRect", "SVGA_3D_CMD_SETSCISSORRECT");
6714 REG_CNT(&pSVGAState->StatR3Cmd3dSetShader, "VMSVGA/Cmd/3dSetShader", "SVGA_3D_CMD_SET_SHADER");
6715 REG_CNT(&pSVGAState->StatR3Cmd3dSetShaderConst, "VMSVGA/Cmd/3dSetShaderConst", "SVGA_3D_CMD_SET_SHADER_CONST");
6716 REG_CNT(&pSVGAState->StatR3Cmd3dSetTextureState, "VMSVGA/Cmd/3dSetTextureState", "SVGA_3D_CMD_SETTEXTURESTATE");
6717 REG_CNT(&pSVGAState->StatR3Cmd3dSetTransform, "VMSVGA/Cmd/3dSetTransform", "SVGA_3D_CMD_SETTRANSFORM");
6718 REG_CNT(&pSVGAState->StatR3Cmd3dSetViewPort, "VMSVGA/Cmd/3dSetViewPort", "SVGA_3D_CMD_SETVIEWPORT");
6719 REG_CNT(&pSVGAState->StatR3Cmd3dSetZRange, "VMSVGA/Cmd/3dSetZRange", "SVGA_3D_CMD_SETZRANGE");
6720 REG_CNT(&pSVGAState->StatR3Cmd3dShaderDefine, "VMSVGA/Cmd/3dShaderDefine", "SVGA_3D_CMD_SHADER_DEFINE");
6721 REG_CNT(&pSVGAState->StatR3Cmd3dShaderDestroy, "VMSVGA/Cmd/3dShaderDestroy", "SVGA_3D_CMD_SHADER_DESTROY");
6722 REG_CNT(&pSVGAState->StatR3Cmd3dSurfaceCopy, "VMSVGA/Cmd/3dSurfaceCopy", "SVGA_3D_CMD_SURFACE_COPY");
6723 REG_CNT(&pSVGAState->StatR3Cmd3dSurfaceDefine, "VMSVGA/Cmd/3dSurfaceDefine", "SVGA_3D_CMD_SURFACE_DEFINE");
6724 REG_CNT(&pSVGAState->StatR3Cmd3dSurfaceDefineV2, "VMSVGA/Cmd/3dSurfaceDefineV2", "SVGA_3D_CMD_SURFACE_DEFINE_V2");
6725 REG_CNT(&pSVGAState->StatR3Cmd3dSurfaceDestroy, "VMSVGA/Cmd/3dSurfaceDestroy", "SVGA_3D_CMD_SURFACE_DESTROY");
6726 REG_CNT(&pSVGAState->StatR3Cmd3dSurfaceDma, "VMSVGA/Cmd/3dSurfaceDma", "SVGA_3D_CMD_SURFACE_DMA");
6727 REG_CNT(&pSVGAState->StatR3Cmd3dSurfaceScreen, "VMSVGA/Cmd/3dSurfaceScreen", "SVGA_3D_CMD_SURFACE_SCREEN");
6728 REG_CNT(&pSVGAState->StatR3Cmd3dSurfaceStretchBlt, "VMSVGA/Cmd/3dSurfaceStretchBlt", "SVGA_3D_CMD_SURFACE_STRETCHBLT");
6729 REG_CNT(&pSVGAState->StatR3Cmd3dWaitForQuery, "VMSVGA/Cmd/3dWaitForQuery", "SVGA_3D_CMD_WAIT_FOR_QUERY");
6730 REG_CNT(&pSVGAState->StatR3CmdAnnotationCopy, "VMSVGA/Cmd/AnnotationCopy", "SVGA_CMD_ANNOTATION_COPY");
6731 REG_CNT(&pSVGAState->StatR3CmdAnnotationFill, "VMSVGA/Cmd/AnnotationFill", "SVGA_CMD_ANNOTATION_FILL");
6732 REG_CNT(&pSVGAState->StatR3CmdBlitGmrFbToScreen, "VMSVGA/Cmd/BlitGmrFbToScreen", "SVGA_CMD_BLIT_GMRFB_TO_SCREEN");
6733 REG_CNT(&pSVGAState->StatR3CmdBlitScreentoGmrFb, "VMSVGA/Cmd/BlitScreentoGmrFb", "SVGA_CMD_BLIT_SCREEN_TO_GMRFB");
6734 REG_CNT(&pSVGAState->StatR3CmdDefineAlphaCursor, "VMSVGA/Cmd/DefineAlphaCursor", "SVGA_CMD_DEFINE_ALPHA_CURSOR");
6735 REG_CNT(&pSVGAState->StatR3CmdDefineCursor, "VMSVGA/Cmd/DefineCursor", "SVGA_CMD_DEFINE_CURSOR");
6736 REG_CNT(&pSVGAState->StatR3CmdMoveCursor, "VMSVGA/Cmd/MoveCursor", "SVGA_CMD_MOVE_CURSOR");
6737 REG_CNT(&pSVGAState->StatR3CmdDisplayCursor, "VMSVGA/Cmd/DisplayCursor", "SVGA_CMD_DISPLAY_CURSOR");
6738 REG_CNT(&pSVGAState->StatR3CmdRectFill, "VMSVGA/Cmd/RectFill", "SVGA_CMD_RECT_FILL");
6739 REG_CNT(&pSVGAState->StatR3CmdRectCopy, "VMSVGA/Cmd/RectCopy", "SVGA_CMD_RECT_COPY");
6740 REG_CNT(&pSVGAState->StatR3CmdRectRopCopy, "VMSVGA/Cmd/RectRopCopy", "SVGA_CMD_RECT_ROP_COPY");
6741 REG_CNT(&pSVGAState->StatR3CmdDefineGmr2, "VMSVGA/Cmd/DefineGmr2", "SVGA_CMD_DEFINE_GMR2");
6742 REG_CNT(&pSVGAState->StatR3CmdDefineGmr2Free, "VMSVGA/Cmd/DefineGmr2/Free", "Number of SVGA_CMD_DEFINE_GMR2 commands that only frees.");
6743 REG_CNT(&pSVGAState->StatR3CmdDefineGmr2Modify, "VMSVGA/Cmd/DefineGmr2/Modify", "Number of SVGA_CMD_DEFINE_GMR2 commands that redefines a non-free GMR.");
6744 REG_CNT(&pSVGAState->StatR3CmdDefineGmrFb, "VMSVGA/Cmd/DefineGmrFb", "SVGA_CMD_DEFINE_GMRFB");
6745 REG_CNT(&pSVGAState->StatR3CmdDefineScreen, "VMSVGA/Cmd/DefineScreen", "SVGA_CMD_DEFINE_SCREEN");
6746 REG_CNT(&pSVGAState->StatR3CmdDestroyScreen, "VMSVGA/Cmd/DestroyScreen", "SVGA_CMD_DESTROY_SCREEN");
6747 REG_CNT(&pSVGAState->StatR3CmdEscape, "VMSVGA/Cmd/Escape", "SVGA_CMD_ESCAPE");
6748 REG_CNT(&pSVGAState->StatR3CmdFence, "VMSVGA/Cmd/Fence", "SVGA_CMD_FENCE");
6749 REG_CNT(&pSVGAState->StatR3CmdInvalidCmd, "VMSVGA/Cmd/InvalidCmd", "SVGA_CMD_INVALID_CMD");
6750 REG_CNT(&pSVGAState->StatR3CmdRemapGmr2, "VMSVGA/Cmd/RemapGmr2", "SVGA_CMD_REMAP_GMR2");
6751 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.");
6752 REG_CNT(&pSVGAState->StatR3CmdUpdate, "VMSVGA/Cmd/Update", "SVGA_CMD_UPDATE");
6753 REG_CNT(&pSVGAState->StatR3CmdUpdateVerbose, "VMSVGA/Cmd/UpdateVerbose", "SVGA_CMD_UPDATE_VERBOSE");
6754
6755 REG_CNT(&pSVGAState->StatR3RegConfigDoneWr, "VMSVGA/Reg/ConfigDoneWrite", "SVGA_REG_CONFIG_DONE writes");
6756 REG_CNT(&pSVGAState->StatR3RegGmrDescriptorWr, "VMSVGA/Reg/GmrDescriptorWrite", "SVGA_REG_GMR_DESCRIPTOR writes");
6757 REG_CNT(&pSVGAState->StatR3RegGmrDescriptorWrErrors, "VMSVGA/Reg/GmrDescriptorWrite/Errors", "Number of erroneous SVGA_REG_GMR_DESCRIPTOR commands.");
6758 REG_CNT(&pSVGAState->StatR3RegGmrDescriptorWrFree, "VMSVGA/Reg/GmrDescriptorWrite/Free", "Number of SVGA_REG_GMR_DESCRIPTOR commands only freeing the GMR.");
6759 REG_CNT(&pThis->svga.StatRegBitsPerPixelWr, "VMSVGA/Reg/BitsPerPixelWrite", "SVGA_REG_BITS_PER_PIXEL writes.");
6760 REG_CNT(&pThis->svga.StatRegBusyWr, "VMSVGA/Reg/BusyWrite", "SVGA_REG_BUSY writes.");
6761 REG_CNT(&pThis->svga.StatRegCursorXWr, "VMSVGA/Reg/CursorXWrite", "SVGA_REG_CURSOR_X writes.");
6762 REG_CNT(&pThis->svga.StatRegCursorYWr, "VMSVGA/Reg/CursorYWrite", "SVGA_REG_CURSOR_Y writes.");
6763 REG_CNT(&pThis->svga.StatRegCursorIdWr, "VMSVGA/Reg/CursorIdWrite", "SVGA_REG_DEAD (SVGA_REG_CURSOR_ID) writes.");
6764 REG_CNT(&pThis->svga.StatRegCursorOnWr, "VMSVGA/Reg/CursorOnWrite", "SVGA_REG_CURSOR_ON writes.");
6765 REG_CNT(&pThis->svga.StatRegDepthWr, "VMSVGA/Reg/DepthWrite", "SVGA_REG_DEPTH writes.");
6766 REG_CNT(&pThis->svga.StatRegDisplayHeightWr, "VMSVGA/Reg/DisplayHeightWrite", "SVGA_REG_DISPLAY_HEIGHT writes.");
6767 REG_CNT(&pThis->svga.StatRegDisplayIdWr, "VMSVGA/Reg/DisplayIdWrite", "SVGA_REG_DISPLAY_ID writes.");
6768 REG_CNT(&pThis->svga.StatRegDisplayIsPrimaryWr, "VMSVGA/Reg/DisplayIsPrimaryWrite", "SVGA_REG_DISPLAY_IS_PRIMARY writes.");
6769 REG_CNT(&pThis->svga.StatRegDisplayPositionXWr, "VMSVGA/Reg/DisplayPositionXWrite", "SVGA_REG_DISPLAY_POSITION_X writes.");
6770 REG_CNT(&pThis->svga.StatRegDisplayPositionYWr, "VMSVGA/Reg/DisplayPositionYWrite", "SVGA_REG_DISPLAY_POSITION_Y writes.");
6771 REG_CNT(&pThis->svga.StatRegDisplayWidthWr, "VMSVGA/Reg/DisplayWidthWrite", "SVGA_REG_DISPLAY_WIDTH writes.");
6772 REG_CNT(&pThis->svga.StatRegEnableWr, "VMSVGA/Reg/EnableWrite", "SVGA_REG_ENABLE writes.");
6773 REG_CNT(&pThis->svga.StatRegGmrIdWr, "VMSVGA/Reg/GmrIdWrite", "SVGA_REG_GMR_ID writes.");
6774 REG_CNT(&pThis->svga.StatRegGuestIdWr, "VMSVGA/Reg/GuestIdWrite", "SVGA_REG_GUEST_ID writes.");
6775 REG_CNT(&pThis->svga.StatRegHeightWr, "VMSVGA/Reg/HeightWrite", "SVGA_REG_HEIGHT writes.");
6776 REG_CNT(&pThis->svga.StatRegIdWr, "VMSVGA/Reg/IdWrite", "SVGA_REG_ID writes.");
6777 REG_CNT(&pThis->svga.StatRegIrqMaskWr, "VMSVGA/Reg/IrqMaskWrite", "SVGA_REG_IRQMASK writes.");
6778 REG_CNT(&pThis->svga.StatRegNumDisplaysWr, "VMSVGA/Reg/NumDisplaysWrite", "SVGA_REG_NUM_DISPLAYS writes.");
6779 REG_CNT(&pThis->svga.StatRegNumGuestDisplaysWr, "VMSVGA/Reg/NumGuestDisplaysWrite", "SVGA_REG_NUM_GUEST_DISPLAYS writes.");
6780 REG_CNT(&pThis->svga.StatRegPaletteWr, "VMSVGA/Reg/PaletteWrite", "SVGA_PALETTE_XXXX writes.");
6781 REG_CNT(&pThis->svga.StatRegPitchLockWr, "VMSVGA/Reg/PitchLockWrite", "SVGA_REG_PITCHLOCK writes.");
6782 REG_CNT(&pThis->svga.StatRegPseudoColorWr, "VMSVGA/Reg/PseudoColorWrite", "SVGA_REG_PSEUDOCOLOR writes.");
6783 REG_CNT(&pThis->svga.StatRegReadOnlyWr, "VMSVGA/Reg/ReadOnlyWrite", "Read-only SVGA_REG_XXXX writes.");
6784 REG_CNT(&pThis->svga.StatRegScratchWr, "VMSVGA/Reg/ScratchWrite", "SVGA_REG_SCRATCH_XXXX writes.");
6785 REG_CNT(&pThis->svga.StatRegSyncWr, "VMSVGA/Reg/SyncWrite", "SVGA_REG_SYNC writes.");
6786 REG_CNT(&pThis->svga.StatRegTopWr, "VMSVGA/Reg/TopWrite", "SVGA_REG_TOP writes.");
6787 REG_CNT(&pThis->svga.StatRegTracesWr, "VMSVGA/Reg/TracesWrite", "SVGA_REG_TRACES writes.");
6788 REG_CNT(&pThis->svga.StatRegUnknownWr, "VMSVGA/Reg/UnknownWrite", "Writes to unknown register.");
6789 REG_CNT(&pThis->svga.StatRegWidthWr, "VMSVGA/Reg/WidthWrite", "SVGA_REG_WIDTH writes.");
6790 REG_CNT(&pThis->svga.StatRegCommandLowWr, "VMSVGA/Reg/CommandLowWrite", "SVGA_REG_COMMAND_LOW writes.");
6791 REG_CNT(&pThis->svga.StatRegCommandHighWr, "VMSVGA/Reg/CommandHighWrite", "SVGA_REG_COMMAND_HIGH writes.");
6792 REG_CNT(&pThis->svga.StatRegDevCapWr, "VMSVGA/Reg/DevCapWrite", "SVGA_REG_DEV_CAP writes.");
6793 REG_CNT(&pThis->svga.StatRegCmdPrependLowWr, "VMSVGA/Reg/CmdPrependLowWrite", "SVGA_REG_CMD_PREPEND_LOW writes.");
6794 REG_CNT(&pThis->svga.StatRegCmdPrependHighWr, "VMSVGA/Reg/CmdPrependHighWrite", "SVGA_REG_CMD_PREPEND_HIGH writes.");
6795
6796 REG_CNT(&pThis->svga.StatRegBitsPerPixelRd, "VMSVGA/Reg/BitsPerPixelRead", "SVGA_REG_BITS_PER_PIXEL reads.");
6797 REG_CNT(&pThis->svga.StatRegBlueMaskRd, "VMSVGA/Reg/BlueMaskRead", "SVGA_REG_BLUE_MASK reads.");
6798 REG_CNT(&pThis->svga.StatRegBusyRd, "VMSVGA/Reg/BusyRead", "SVGA_REG_BUSY reads.");
6799 REG_CNT(&pThis->svga.StatRegBytesPerLineRd, "VMSVGA/Reg/BytesPerLineRead", "SVGA_REG_BYTES_PER_LINE reads.");
6800 REG_CNT(&pThis->svga.StatRegCapabilitesRd, "VMSVGA/Reg/CapabilitesRead", "SVGA_REG_CAPABILITIES reads.");
6801 REG_CNT(&pThis->svga.StatRegConfigDoneRd, "VMSVGA/Reg/ConfigDoneRead", "SVGA_REG_CONFIG_DONE reads.");
6802 REG_CNT(&pThis->svga.StatRegCursorXRd, "VMSVGA/Reg/CursorXRead", "SVGA_REG_CURSOR_X reads.");
6803 REG_CNT(&pThis->svga.StatRegCursorYRd, "VMSVGA/Reg/CursorYRead", "SVGA_REG_CURSOR_Y reads.");
6804 REG_CNT(&pThis->svga.StatRegCursorIdRd, "VMSVGA/Reg/CursorIdRead", "SVGA_REG_DEAD (SVGA_REG_CURSOR_ID) reads.");
6805 REG_CNT(&pThis->svga.StatRegCursorOnRd, "VMSVGA/Reg/CursorOnRead", "SVGA_REG_CURSOR_ON reads.");
6806 REG_CNT(&pThis->svga.StatRegDepthRd, "VMSVGA/Reg/DepthRead", "SVGA_REG_DEPTH reads.");
6807 REG_CNT(&pThis->svga.StatRegDisplayHeightRd, "VMSVGA/Reg/DisplayHeightRead", "SVGA_REG_DISPLAY_HEIGHT reads.");
6808 REG_CNT(&pThis->svga.StatRegDisplayIdRd, "VMSVGA/Reg/DisplayIdRead", "SVGA_REG_DISPLAY_ID reads.");
6809 REG_CNT(&pThis->svga.StatRegDisplayIsPrimaryRd, "VMSVGA/Reg/DisplayIsPrimaryRead", "SVGA_REG_DISPLAY_IS_PRIMARY reads.");
6810 REG_CNT(&pThis->svga.StatRegDisplayPositionXRd, "VMSVGA/Reg/DisplayPositionXRead", "SVGA_REG_DISPLAY_POSITION_X reads.");
6811 REG_CNT(&pThis->svga.StatRegDisplayPositionYRd, "VMSVGA/Reg/DisplayPositionYRead", "SVGA_REG_DISPLAY_POSITION_Y reads.");
6812 REG_CNT(&pThis->svga.StatRegDisplayWidthRd, "VMSVGA/Reg/DisplayWidthRead", "SVGA_REG_DISPLAY_WIDTH reads.");
6813 REG_CNT(&pThis->svga.StatRegEnableRd, "VMSVGA/Reg/EnableRead", "SVGA_REG_ENABLE reads.");
6814 REG_CNT(&pThis->svga.StatRegFbOffsetRd, "VMSVGA/Reg/FbOffsetRead", "SVGA_REG_FB_OFFSET reads.");
6815 REG_CNT(&pThis->svga.StatRegFbSizeRd, "VMSVGA/Reg/FbSizeRead", "SVGA_REG_FB_SIZE reads.");
6816 REG_CNT(&pThis->svga.StatRegFbStartRd, "VMSVGA/Reg/FbStartRead", "SVGA_REG_FB_START reads.");
6817 REG_CNT(&pThis->svga.StatRegGmrIdRd, "VMSVGA/Reg/GmrIdRead", "SVGA_REG_GMR_ID reads.");
6818 REG_CNT(&pThis->svga.StatRegGmrMaxDescriptorLengthRd, "VMSVGA/Reg/GmrMaxDescriptorLengthRead", "SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH reads.");
6819 REG_CNT(&pThis->svga.StatRegGmrMaxIdsRd, "VMSVGA/Reg/GmrMaxIdsRead", "SVGA_REG_GMR_MAX_IDS reads.");
6820 REG_CNT(&pThis->svga.StatRegGmrsMaxPagesRd, "VMSVGA/Reg/GmrsMaxPagesRead", "SVGA_REG_GMRS_MAX_PAGES reads.");
6821 REG_CNT(&pThis->svga.StatRegGreenMaskRd, "VMSVGA/Reg/GreenMaskRead", "SVGA_REG_GREEN_MASK reads.");
6822 REG_CNT(&pThis->svga.StatRegGuestIdRd, "VMSVGA/Reg/GuestIdRead", "SVGA_REG_GUEST_ID reads.");
6823 REG_CNT(&pThis->svga.StatRegHeightRd, "VMSVGA/Reg/HeightRead", "SVGA_REG_HEIGHT reads.");
6824 REG_CNT(&pThis->svga.StatRegHostBitsPerPixelRd, "VMSVGA/Reg/HostBitsPerPixelRead", "SVGA_REG_HOST_BITS_PER_PIXEL reads.");
6825 REG_CNT(&pThis->svga.StatRegIdRd, "VMSVGA/Reg/IdRead", "SVGA_REG_ID reads.");
6826 REG_CNT(&pThis->svga.StatRegIrqMaskRd, "VMSVGA/Reg/IrqMaskRead", "SVGA_REG_IRQ_MASK reads.");
6827 REG_CNT(&pThis->svga.StatRegMaxHeightRd, "VMSVGA/Reg/MaxHeightRead", "SVGA_REG_MAX_HEIGHT reads.");
6828 REG_CNT(&pThis->svga.StatRegMaxWidthRd, "VMSVGA/Reg/MaxWidthRead", "SVGA_REG_MAX_WIDTH reads.");
6829 REG_CNT(&pThis->svga.StatRegMemorySizeRd, "VMSVGA/Reg/MemorySizeRead", "SVGA_REG_MEMORY_SIZE reads.");
6830 REG_CNT(&pThis->svga.StatRegMemRegsRd, "VMSVGA/Reg/MemRegsRead", "SVGA_REG_MEM_REGS reads.");
6831 REG_CNT(&pThis->svga.StatRegMemSizeRd, "VMSVGA/Reg/MemSizeRead", "SVGA_REG_MEM_SIZE reads.");
6832 REG_CNT(&pThis->svga.StatRegMemStartRd, "VMSVGA/Reg/MemStartRead", "SVGA_REG_MEM_START reads.");
6833 REG_CNT(&pThis->svga.StatRegNumDisplaysRd, "VMSVGA/Reg/NumDisplaysRead", "SVGA_REG_NUM_DISPLAYS reads.");
6834 REG_CNT(&pThis->svga.StatRegNumGuestDisplaysRd, "VMSVGA/Reg/NumGuestDisplaysRead", "SVGA_REG_NUM_GUEST_DISPLAYS reads.");
6835 REG_CNT(&pThis->svga.StatRegPaletteRd, "VMSVGA/Reg/PaletteRead", "SVGA_REG_PLAETTE_XXXX reads.");
6836 REG_CNT(&pThis->svga.StatRegPitchLockRd, "VMSVGA/Reg/PitchLockRead", "SVGA_REG_PITCHLOCK reads.");
6837 REG_CNT(&pThis->svga.StatRegPsuedoColorRd, "VMSVGA/Reg/PsuedoColorRead", "SVGA_REG_PSEUDOCOLOR reads.");
6838 REG_CNT(&pThis->svga.StatRegRedMaskRd, "VMSVGA/Reg/RedMaskRead", "SVGA_REG_RED_MASK reads.");
6839 REG_CNT(&pThis->svga.StatRegScratchRd, "VMSVGA/Reg/ScratchRead", "SVGA_REG_SCRATCH reads.");
6840 REG_CNT(&pThis->svga.StatRegScratchSizeRd, "VMSVGA/Reg/ScratchSizeRead", "SVGA_REG_SCRATCH_SIZE reads.");
6841 REG_CNT(&pThis->svga.StatRegSyncRd, "VMSVGA/Reg/SyncRead", "SVGA_REG_SYNC reads.");
6842 REG_CNT(&pThis->svga.StatRegTopRd, "VMSVGA/Reg/TopRead", "SVGA_REG_TOP reads.");
6843 REG_CNT(&pThis->svga.StatRegTracesRd, "VMSVGA/Reg/TracesRead", "SVGA_REG_TRACES reads.");
6844 REG_CNT(&pThis->svga.StatRegUnknownRd, "VMSVGA/Reg/UnknownRead", "SVGA_REG_UNKNOWN reads.");
6845 REG_CNT(&pThis->svga.StatRegVramSizeRd, "VMSVGA/Reg/VramSizeRead", "SVGA_REG_VRAM_SIZE reads.");
6846 REG_CNT(&pThis->svga.StatRegWidthRd, "VMSVGA/Reg/WidthRead", "SVGA_REG_WIDTH reads.");
6847 REG_CNT(&pThis->svga.StatRegWriteOnlyRd, "VMSVGA/Reg/WriteOnlyRead", "Write-only SVGA_REG_XXXX reads.");
6848 REG_CNT(&pThis->svga.StatRegCommandLowRd, "VMSVGA/Reg/CommandLowRead", "SVGA_REG_COMMAND_LOW reads.");
6849 REG_CNT(&pThis->svga.StatRegCommandHighRd, "VMSVGA/Reg/CommandHighRead", "SVGA_REG_COMMAND_HIGH reads.");
6850 REG_CNT(&pThis->svga.StatRegMaxPrimBBMemRd, "VMSVGA/Reg/MaxPrimBBMemRead", "SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM reads.");
6851 REG_CNT(&pThis->svga.StatRegGBMemSizeRd, "VMSVGA/Reg/GBMemSizeRead", "SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB reads.");
6852 REG_CNT(&pThis->svga.StatRegDevCapRd, "VMSVGA/Reg/DevCapRead", "SVGA_REG_DEV_CAP reads.");
6853 REG_CNT(&pThis->svga.StatRegCmdPrependLowRd, "VMSVGA/Reg/CmdPrependLowRead", "SVGA_REG_CMD_PREPEND_LOW reads.");
6854 REG_CNT(&pThis->svga.StatRegCmdPrependHighRd, "VMSVGA/Reg/CmdPrependHighRead", "SVGA_REG_CMD_PREPEND_HIGH reads.");
6855 REG_CNT(&pThis->svga.StatRegScrnTgtMaxWidthRd, "VMSVGA/Reg/ScrnTgtMaxWidthRead", "SVGA_REG_SCREENTARGET_MAX_WIDTH reads.");
6856 REG_CNT(&pThis->svga.StatRegScrnTgtMaxHeightRd, "VMSVGA/Reg/ScrnTgtMaxHeightRead", "SVGA_REG_SCREENTARGET_MAX_HEIGHT reads.");
6857 REG_CNT(&pThis->svga.StatRegMobMaxSizeRd, "VMSVGA/Reg/MobMaxSizeRead", "SVGA_REG_MOB_MAX_SIZE reads.");
6858
6859 REG_PRF(&pSVGAState->StatBusyDelayEmts, "VMSVGA/EmtDelayOnBusyFifo", "Time we've delayed EMTs because of busy FIFO thread.");
6860 REG_CNT(&pSVGAState->StatFifoCommands, "VMSVGA/FifoCommands", "FIFO command counter.");
6861 REG_CNT(&pSVGAState->StatFifoErrors, "VMSVGA/FifoErrors", "FIFO error counter.");
6862 REG_CNT(&pSVGAState->StatFifoUnkCmds, "VMSVGA/FifoUnknownCommands", "FIFO unknown command counter.");
6863 REG_CNT(&pSVGAState->StatFifoTodoTimeout, "VMSVGA/FifoTodoTimeout", "Number of times we discovered pending work after a wait timeout.");
6864 REG_CNT(&pSVGAState->StatFifoTodoWoken, "VMSVGA/FifoTodoWoken", "Number of times we discovered pending work after being woken up.");
6865 REG_PRF(&pSVGAState->StatFifoStalls, "VMSVGA/FifoStalls", "Profiling of FIFO stalls (waiting for guest to finish copying data).");
6866 REG_PRF(&pSVGAState->StatFifoExtendedSleep, "VMSVGA/FifoExtendedSleep", "Profiling FIFO sleeps relying on the refresh timer and/or access handler.");
6867# if defined(VMSVGA_USE_FIFO_ACCESS_HANDLER) || defined(DEBUG_FIFO_ACCESS)
6868 REG_CNT(&pSVGAState->StatFifoAccessHandler, "VMSVGA/FifoAccessHandler", "Number of times the FIFO access handler triggered.");
6869# endif
6870 REG_CNT(&pSVGAState->StatFifoCursorFetchAgain, "VMSVGA/FifoCursorFetchAgain", "Times the cursor update counter changed while reading.");
6871 REG_CNT(&pSVGAState->StatFifoCursorNoChange, "VMSVGA/FifoCursorNoChange", "No cursor position change event though the update counter was modified.");
6872 REG_CNT(&pSVGAState->StatFifoCursorPosition, "VMSVGA/FifoCursorPosition", "Cursor position and visibility changes.");
6873 REG_CNT(&pSVGAState->StatFifoCursorVisiblity, "VMSVGA/FifoCursorVisiblity", "Cursor visibility changes.");
6874 REG_CNT(&pSVGAState->StatFifoWatchdogWakeUps, "VMSVGA/FifoWatchdogWakeUps", "Number of times the FIFO refresh poller/watchdog woke up the FIFO thread.");
6875
6876# undef REG_CNT
6877# undef REG_PRF
6878
6879 /*
6880 * Info handlers.
6881 */
6882 PDMDevHlpDBGFInfoRegister(pDevIns, "vmsvga", "Basic VMSVGA device state details", vmsvgaR3Info);
6883# ifdef VBOX_WITH_VMSVGA3D
6884 PDMDevHlpDBGFInfoRegister(pDevIns, "vmsvga3dctx", "VMSVGA 3d context details. Accepts 'terse'.", vmsvgaR3Info3dContext);
6885 PDMDevHlpDBGFInfoRegister(pDevIns, "vmsvga3dsfc",
6886 "VMSVGA 3d surface details. "
6887 "Accepts 'terse', 'invy', and one of 'tiny', 'medium', 'normal', 'big', 'huge', or 'gigantic'.",
6888 vmsvgaR3Info3dSurface);
6889 PDMDevHlpDBGFInfoRegister(pDevIns, "vmsvga3dsurf",
6890 "VMSVGA 3d surface details and bitmap: "
6891 "sid[>dir]",
6892 vmsvgaR3Info3dSurfaceBmp);
6893# endif
6894
6895 return VINF_SUCCESS;
6896}
6897
6898/* Initialize 3D backend, set device capabilities and call pfnPowerOn callback of 3D backend.
6899 *
6900 * @param pDevIns The device instance.
6901 * @param pThis The shared VGA/VMSVGA instance data.
6902 * @param pThisCC The VGA/VMSVGA state for ring-3.
6903 * @param fLoadState Whether saved state is being loaded.
6904 */
6905static void vmsvgaR3PowerOnDevice(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, bool fLoadState)
6906{
6907# ifdef VBOX_WITH_VMSVGA3D
6908 if (pThis->svga.f3DEnabled)
6909 {
6910 /* Load a 3D backend. */
6911 int rc = vmsvgaR3Init3dInterfaces(pDevIns, pThis, pThisCC);
6912 if (RT_FAILURE(rc))
6913 {
6914 LogRel(("VMSVGA3d: 3D support disabled! (vmsvga3dInit -> %Rrc)\n", rc));
6915 pThis->svga.f3DEnabled = false;
6916 }
6917 }
6918# endif
6919
6920# if defined(VBOX_WITH_VMSVGA3D) && defined(RT_OS_LINUX)
6921 if (pThis->svga.f3DEnabled)
6922 {
6923 /* The FIFO thread may use X API for accelerated screen output. */
6924 /* This must be done after backend initialization by vmsvgaR3Init3dInterfaces,
6925 * because it dynamically resolves XInitThreads.
6926 */
6927 XInitThreads();
6928 }
6929# endif
6930
6931 if (!fLoadState)
6932 {
6933 vmsvgaR3InitFIFO(pThis, pThisCC);
6934 vmsvgaR3GetCaps(pThis, pThisCC, &pThis->svga.u32DeviceCaps, &pThisCC->svga.pau32FIFO[SVGA_FIFO_CAPABILITIES]);
6935 }
6936# ifdef DEBUG
6937 else
6938 {
6939 /* If saved state is being loaded then FIFO and caps are already restored. */
6940 uint32_t u32DeviceCaps = 0;
6941 uint32_t u32FIFOCaps = 0;
6942 vmsvgaR3GetCaps(pThis, pThisCC, &u32DeviceCaps, &u32FIFOCaps);
6943
6944 /* Capabilities should not change normally. */
6945 Assert( pThis->svga.u32DeviceCaps == u32DeviceCaps
6946 && pThisCC->svga.pau32FIFO[SVGA_FIFO_CAPABILITIES] == u32FIFOCaps);
6947 }
6948#endif
6949
6950# ifdef VBOX_WITH_VMSVGA3D
6951 if (pThis->svga.f3DEnabled)
6952 {
6953 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
6954 int rc = pSVGAState->pFuncs3D->pfnPowerOn(pDevIns, pThis, pThisCC);
6955 if (RT_SUCCESS(rc))
6956 {
6957 /* Initialize FIFO 3D capabilities. */
6958 vmsvgaR3InitFifo3DCaps(pThis, pThisCC);
6959 }
6960 else
6961 {
6962 LogRel(("VMSVGA3d: 3D support disabled! (vmsvga3dPowerOn -> %Rrc)\n", rc));
6963 pThis->svga.f3DEnabled = false;
6964 }
6965 }
6966# else /* !VBOX_WITH_VMSVGA3D */
6967 RT_NOREF(pDevIns);
6968# endif /* !VBOX_WITH_VMSVGA3D */
6969}
6970
6971
6972/**
6973 * Power On notification.
6974 *
6975 * @returns VBox status code.
6976 * @param pDevIns The device instance data.
6977 *
6978 * @remarks Caller enters the device critical section.
6979 */
6980DECLCALLBACK(void) vmsvgaR3PowerOn(PPDMDEVINS pDevIns)
6981{
6982 PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
6983 PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
6984
6985 vmsvgaR3PowerOnDevice(pDevIns, pThis, pThisCC, /*fLoadState=*/ false);
6986}
6987
6988/**
6989 * Power Off notification.
6990 *
6991 * @param pDevIns The device instance data.
6992 *
6993 * @remarks Caller enters the device critical section.
6994 */
6995DECLCALLBACK(void) vmsvgaR3PowerOff(PPDMDEVINS pDevIns)
6996{
6997 PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
6998 PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
6999
7000 /*
7001 * Notify the FIFO thread.
7002 */
7003 if (pThisCC->svga.pFIFOIOThread)
7004 {
7005 /* Hack around a deadlock:
7006 * - the caller holds the device critsect;
7007 * - FIFO thread may attempt to enter the critsect too (when raising an IRQ).
7008 */
7009 PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect);
7010
7011 int rc = vmsvgaR3RunExtCmdOnFifoThread(pDevIns, pThis, pThisCC, VMSVGA_FIFO_EXTCMD_POWEROFF,
7012 NULL /*pvParam*/, 30000 /*ms*/);
7013 AssertLogRelRC(rc);
7014
7015 int const rcLock = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VERR_IGNORED);
7016 PDM_CRITSECT_RELEASE_ASSERT_RC_DEV(pDevIns, &pThis->CritSect, rcLock);
7017 }
7018}
7019
7020#endif /* IN_RING3 */
Note: See TracBrowser for help on using the repository browser.

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