VirtualBox

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

Last change on this file since 65282 was 65271, checked in by vboxsync, 8 years ago

VMSVGA: GMR work.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 232.5 KB
Line 
1/* $Id: DevVGA-SVGA.cpp 65271 2017-01-12 19:54:10Z 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 */
12
13/*
14 * Copyright (C) 2013-2016 Oracle Corporation
15 *
16 * This file is part of VirtualBox Open Source Edition (OSE), as
17 * available from http://www.virtualbox.org. This file is free software;
18 * you can redistribute it and/or modify it under the terms of the GNU
19 * General Public License (GPL) as published by the Free Software
20 * Foundation, in version 2 as it comes in the "COPYING" file of the
21 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
22 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
23 */
24
25
26/*********************************************************************************************************************************
27* Header Files *
28*********************************************************************************************************************************/
29#define LOG_GROUP LOG_GROUP_DEV_VMSVGA
30#define VMSVGA_USE_EMT_HALT_CODE
31#include <VBox/vmm/pdmdev.h>
32#include <VBox/version.h>
33#include <VBox/err.h>
34#include <VBox/log.h>
35#include <VBox/vmm/pgm.h>
36#ifdef VMSVGA_USE_EMT_HALT_CODE
37# include <VBox/vmm/vmapi.h>
38# include <VBox/vmm/vmcpuset.h>
39#endif
40#include <VBox/sup.h>
41
42#include <iprt/assert.h>
43#include <iprt/semaphore.h>
44#include <iprt/uuid.h>
45#ifdef IN_RING3
46# include <iprt/ctype.h>
47# include <iprt/mem.h>
48#endif
49
50#include <VBox/VMMDev.h>
51#include <VBox/VBoxVideo.h>
52#include <VBox/bioslogo.h>
53
54/* should go BEFORE any other DevVGA include to make all DevVGA.h config defines be visible */
55#include "DevVGA.h"
56
57#include "DevVGA-SVGA.h"
58#include "vmsvga/svga_reg.h"
59#include "vmsvga/svga_escape.h"
60#include "vmsvga/svga_overlay.h"
61#include "vmsvga/svga3d_reg.h"
62#include "vmsvga/svga3d_caps.h"
63#ifdef VBOX_WITH_VMSVGA3D
64# include "DevVGA-SVGA3d.h"
65# ifdef RT_OS_DARWIN
66# include "DevVGA-SVGA3d-cocoa.h"
67# endif
68#endif
69
70
71/*********************************************************************************************************************************
72* Defined Constants And Macros *
73*********************************************************************************************************************************/
74/**
75 * Macro for checking if a fixed FIFO register is valid according to the
76 * current FIFO configuration.
77 *
78 * @returns true / false.
79 * @param a_iIndex The fifo register index (like SVGA_FIFO_CAPABILITIES).
80 * @param a_offFifoMin A valid SVGA_FIFO_MIN value.
81 */
82#define VMSVGA_IS_VALID_FIFO_REG(a_iIndex, a_offFifoMin) ( ((a_iIndex) + 1) * sizeof(uint32_t) <= (a_offFifoMin) )
83
84
85/*********************************************************************************************************************************
86* Structures and Typedefs *
87*********************************************************************************************************************************/
88/**
89 * 64-bit GMR descriptor.
90 */
91typedef struct
92{
93 RTGCPHYS GCPhys;
94 uint64_t numPages;
95} VMSVGAGMRDESCRIPTOR, *PVMSVGAGMRDESCRIPTOR;
96
97/**
98 * GMR slot
99 */
100typedef struct
101{
102 uint32_t cMaxPages;
103 uint32_t cbTotal;
104 uint32_t numDescriptors;
105 PVMSVGAGMRDESCRIPTOR paDesc;
106} GMR, *PGMR;
107
108#ifdef IN_RING3
109/**
110 * Internal SVGA ring-3 only state.
111 */
112typedef struct VMSVGAR3STATE
113{
114 GMR aGMR[VMSVGA_MAX_GMR_IDS];
115 struct
116 {
117 SVGAGuestPtr ptr;
118 uint32_t bytesPerLine;
119 SVGAGMRImageFormat format;
120 } GMRFB;
121 struct
122 {
123 bool fActive;
124 uint32_t xHotspot;
125 uint32_t yHotspot;
126 uint32_t width;
127 uint32_t height;
128 uint32_t cbData;
129 void *pData;
130 } Cursor;
131 SVGAColorBGRX colorAnnotation;
132
133# ifdef VMSVGA_USE_EMT_HALT_CODE
134 /** Number of EMTs in BusyDelayedEmts (quicker than scanning the set). */
135 uint32_t volatile cBusyDelayedEmts;
136 /** Set of EMTs that are */
137 VMCPUSET BusyDelayedEmts;
138# else
139 /** Number of EMTs waiting on hBusyDelayedEmts. */
140 uint32_t volatile cBusyDelayedEmts;
141 /** Semaphore that EMTs wait on when reading SVGA_REG_BUSY and the FIFO is
142 * busy (ugly). */
143 RTSEMEVENTMULTI hBusyDelayedEmts;
144# endif
145 /** Tracks how much time we waste reading SVGA_REG_BUSY with a busy FIFO. */
146 STAMPROFILE StatBusyDelayEmts;
147
148 STAMPROFILE StatR3Cmd3dPresentProf;
149 STAMPROFILE StatR3Cmd3dDrawPrimitivesProf;
150 STAMPROFILE StatR3Cmd3dSurfaceDmaProf;
151 STAMCOUNTER StatR3CmdDefineGmr2;
152 STAMCOUNTER StatR3CmdDefineGmr2Free;
153 STAMCOUNTER StatR3CmdDefineGmr2Modify;
154 STAMCOUNTER StatR3CmdRemapGmr2;
155 STAMCOUNTER StatR3CmdRemapGmr2Modify;
156 STAMCOUNTER StatR3CmdInvalidCmd;
157 STAMCOUNTER StatR3CmdFence;
158 STAMCOUNTER StatR3CmdUpdate;
159 STAMCOUNTER StatR3CmdUpdateVerbose;
160 STAMCOUNTER StatR3CmdDefineCursor;
161 STAMCOUNTER StatR3CmdDefineAlphaCursor;
162 STAMCOUNTER StatR3CmdEscape;
163 STAMCOUNTER StatR3CmdDefineScreen;
164 STAMCOUNTER StatR3CmdDestroyScreen;
165 STAMCOUNTER StatR3CmdDefineGmrFb;
166 STAMCOUNTER StatR3CmdBlitGmrFbToScreen;
167 STAMCOUNTER StatR3CmdBlitScreentoGmrFb;
168 STAMCOUNTER StatR3CmdAnnotationFill;
169 STAMCOUNTER StatR3CmdAnnotationCopy;
170 STAMCOUNTER StatR3Cmd3dSurfaceDefine;
171 STAMCOUNTER StatR3Cmd3dSurfaceDefineV2;
172 STAMCOUNTER StatR3Cmd3dSurfaceDestroy;
173 STAMCOUNTER StatR3Cmd3dSurfaceCopy;
174 STAMCOUNTER StatR3Cmd3dSurfaceStretchBlt;
175 STAMCOUNTER StatR3Cmd3dSurfaceDma;
176 STAMCOUNTER StatR3Cmd3dSurfaceScreen;
177 STAMCOUNTER StatR3Cmd3dContextDefine;
178 STAMCOUNTER StatR3Cmd3dContextDestroy;
179 STAMCOUNTER StatR3Cmd3dSetTransform;
180 STAMCOUNTER StatR3Cmd3dSetZRange;
181 STAMCOUNTER StatR3Cmd3dSetRenderState;
182 STAMCOUNTER StatR3Cmd3dSetRenderTarget;
183 STAMCOUNTER StatR3Cmd3dSetTextureState;
184 STAMCOUNTER StatR3Cmd3dSetMaterial;
185 STAMCOUNTER StatR3Cmd3dSetLightData;
186 STAMCOUNTER StatR3Cmd3dSetLightEnable;
187 STAMCOUNTER StatR3Cmd3dSetViewPort;
188 STAMCOUNTER StatR3Cmd3dSetClipPlane;
189 STAMCOUNTER StatR3Cmd3dClear;
190 STAMCOUNTER StatR3Cmd3dPresent;
191 STAMCOUNTER StatR3Cmd3dPresentReadBack;
192 STAMCOUNTER StatR3Cmd3dShaderDefine;
193 STAMCOUNTER StatR3Cmd3dShaderDestroy;
194 STAMCOUNTER StatR3Cmd3dSetShader;
195 STAMCOUNTER StatR3Cmd3dSetShaderConst;
196 STAMCOUNTER StatR3Cmd3dDrawPrimitives;
197 STAMCOUNTER StatR3Cmd3dSetScissorRect;
198 STAMCOUNTER StatR3Cmd3dBeginQuery;
199 STAMCOUNTER StatR3Cmd3dEndQuery;
200 STAMCOUNTER StatR3Cmd3dWaitForQuery;
201 STAMCOUNTER StatR3Cmd3dGenerateMipmaps;
202 STAMCOUNTER StatR3Cmd3dActivateSurface;
203 STAMCOUNTER StatR3Cmd3dDeactivateSurface;
204
205 STAMCOUNTER StatR3RegConfigDoneWr;
206 STAMCOUNTER StatR3RegGmrDescriptorWr;
207 STAMCOUNTER StatR3RegGmrDescriptorWrErrors;
208 STAMCOUNTER StatR3RegGmrDescriptorWrFree;
209
210 STAMCOUNTER StatFifoCommands;
211 STAMCOUNTER StatFifoErrors;
212 STAMCOUNTER StatFifoUnkCmds;
213 STAMCOUNTER StatFifoTodoTimeout;
214 STAMCOUNTER StatFifoTodoWoken;
215 STAMPROFILE StatFifoStalls;
216
217} VMSVGAR3STATE, *PVMSVGAR3STATE;
218#endif /* IN_RING3 */
219
220
221/*********************************************************************************************************************************
222* Internal Functions *
223*********************************************************************************************************************************/
224#ifdef IN_RING3
225# ifdef DEBUG_FIFO_ACCESS
226static FNPGMPHYSHANDLER vmsvgaR3FIFOAccessHandler;
227# endif
228# ifdef DEBUG_GMR_ACCESS
229static FNPGMPHYSHANDLER vmsvgaR3GMRAccessHandler;
230# endif
231#endif
232
233
234/*********************************************************************************************************************************
235* Global Variables *
236*********************************************************************************************************************************/
237#ifdef IN_RING3
238
239/**
240 * SSM descriptor table for the VMSVGAGMRDESCRIPTOR structure.
241 */
242static SSMFIELD const g_aVMSVGAGMRDESCRIPTORFields[] =
243{
244 SSMFIELD_ENTRY_GCPHYS( VMSVGAGMRDESCRIPTOR, GCPhys),
245 SSMFIELD_ENTRY( VMSVGAGMRDESCRIPTOR, numPages),
246 SSMFIELD_ENTRY_TERM()
247};
248
249/**
250 * SSM descriptor table for the GMR structure.
251 */
252static SSMFIELD const g_aGMRFields[] =
253{
254 SSMFIELD_ENTRY( GMR, cMaxPages),
255 SSMFIELD_ENTRY( GMR, cbTotal),
256 SSMFIELD_ENTRY( GMR, numDescriptors),
257 SSMFIELD_ENTRY_IGN_HCPTR( GMR, paDesc),
258 SSMFIELD_ENTRY_TERM()
259};
260
261/**
262 * SSM descriptor table for the VMSVGAR3STATE structure.
263 */
264static SSMFIELD const g_aVMSVGAR3STATEFields[] =
265{
266 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, aGMR),
267 SSMFIELD_ENTRY( VMSVGAR3STATE, GMRFB),
268 SSMFIELD_ENTRY( VMSVGAR3STATE, Cursor.fActive),
269 SSMFIELD_ENTRY( VMSVGAR3STATE, Cursor.xHotspot),
270 SSMFIELD_ENTRY( VMSVGAR3STATE, Cursor.yHotspot),
271 SSMFIELD_ENTRY( VMSVGAR3STATE, Cursor.width),
272 SSMFIELD_ENTRY( VMSVGAR3STATE, Cursor.height),
273 SSMFIELD_ENTRY( VMSVGAR3STATE, Cursor.cbData),
274 SSMFIELD_ENTRY_IGN_HCPTR( VMSVGAR3STATE, Cursor.pData),
275 SSMFIELD_ENTRY( VMSVGAR3STATE, colorAnnotation),
276 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, cBusyDelayedEmts),
277#ifdef VMSVGA_USE_EMT_HALT_CODE
278 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, BusyDelayedEmts),
279#else
280 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, hBusyDelayedEmts),
281#endif
282 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatBusyDelayEmts),
283 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dPresentProf),
284 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dDrawPrimitivesProf),
285 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSurfaceDmaProf),
286 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdDefineGmr2),
287 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdDefineGmr2Free),
288 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdDefineGmr2Modify),
289 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdRemapGmr2),
290 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdRemapGmr2Modify),
291 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdInvalidCmd),
292 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdFence),
293 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdUpdate),
294 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdUpdateVerbose),
295 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdDefineCursor),
296 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdDefineAlphaCursor),
297 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdEscape),
298 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdDefineScreen),
299 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdDestroyScreen),
300 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdDefineGmrFb),
301 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdBlitGmrFbToScreen),
302 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdBlitScreentoGmrFb),
303 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdAnnotationFill),
304 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdAnnotationCopy),
305 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSurfaceDefine),
306 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSurfaceDefineV2),
307 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSurfaceDestroy),
308 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSurfaceCopy),
309 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSurfaceStretchBlt),
310 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSurfaceDma),
311 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSurfaceScreen),
312 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dContextDefine),
313 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dContextDestroy),
314 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetTransform),
315 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetZRange),
316 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetRenderState),
317 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetRenderTarget),
318 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetTextureState),
319 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetMaterial),
320 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetLightData),
321 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetLightEnable),
322 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetViewPort),
323 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetClipPlane),
324 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dClear),
325 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dPresent),
326 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dPresentReadBack),
327 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dShaderDefine),
328 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dShaderDestroy),
329 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetShader),
330 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetShaderConst),
331 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dDrawPrimitives),
332 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetScissorRect),
333 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dBeginQuery),
334 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dEndQuery),
335 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dWaitForQuery),
336 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dGenerateMipmaps),
337 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dActivateSurface),
338 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dDeactivateSurface),
339
340 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3RegConfigDoneWr),
341 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3RegGmrDescriptorWr),
342 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3RegGmrDescriptorWrErrors),
343 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3RegGmrDescriptorWrFree),
344
345 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatFifoCommands),
346 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatFifoErrors),
347 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatFifoUnkCmds),
348 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatFifoTodoTimeout),
349 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatFifoTodoWoken),
350 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatFifoStalls),
351 SSMFIELD_ENTRY_TERM()
352};
353
354/**
355 * SSM descriptor table for the VGAState.svga structure.
356 */
357static SSMFIELD const g_aVGAStateSVGAFields[] =
358{
359 SSMFIELD_ENTRY_IGNORE( VMSVGAState, u64HostWindowId),
360 SSMFIELD_ENTRY_IGN_HCPTR( VMSVGAState, pFIFOR3),
361 SSMFIELD_ENTRY_IGN_HCPTR( VMSVGAState, pFIFOR0),
362 SSMFIELD_ENTRY_IGN_HCPTR( VMSVGAState, pSvgaR3State),
363 SSMFIELD_ENTRY_IGN_HCPTR( VMSVGAState, p3dState),
364 SSMFIELD_ENTRY_IGN_HCPTR( VMSVGAState, pFrameBufferBackup),
365 SSMFIELD_ENTRY_IGN_HCPTR( VMSVGAState, pvFIFOExtCmdParam),
366 SSMFIELD_ENTRY_IGN_GCPHYS( VMSVGAState, GCPhysFIFO),
367 SSMFIELD_ENTRY_IGNORE( VMSVGAState, cbFIFO),
368 SSMFIELD_ENTRY( VMSVGAState, u32SVGAId),
369 SSMFIELD_ENTRY( VMSVGAState, fEnabled),
370 SSMFIELD_ENTRY( VMSVGAState, fConfigured),
371 SSMFIELD_ENTRY( VMSVGAState, fBusy),
372 SSMFIELD_ENTRY( VMSVGAState, fTraces),
373 SSMFIELD_ENTRY( VMSVGAState, u32GuestId),
374 SSMFIELD_ENTRY( VMSVGAState, cScratchRegion),
375 SSMFIELD_ENTRY( VMSVGAState, au32ScratchRegion),
376 SSMFIELD_ENTRY( VMSVGAState, u32IrqStatus),
377 SSMFIELD_ENTRY( VMSVGAState, u32IrqMask),
378 SSMFIELD_ENTRY( VMSVGAState, u32PitchLock),
379 SSMFIELD_ENTRY( VMSVGAState, u32CurrentGMRId),
380 SSMFIELD_ENTRY( VMSVGAState, u32RegCaps),
381 SSMFIELD_ENTRY_IGNORE( VMSVGAState, BasePort),
382 SSMFIELD_ENTRY( VMSVGAState, u32IndexReg),
383 SSMFIELD_ENTRY_IGNORE( VMSVGAState, pSupDrvSession),
384 SSMFIELD_ENTRY_IGNORE( VMSVGAState, FIFORequestSem),
385 SSMFIELD_ENTRY_IGNORE( VMSVGAState, FIFOExtCmdSem),
386 SSMFIELD_ENTRY_IGN_HCPTR( VMSVGAState, pFIFOIOThread),
387 SSMFIELD_ENTRY( VMSVGAState, uWidth),
388 SSMFIELD_ENTRY( VMSVGAState, uHeight),
389 SSMFIELD_ENTRY( VMSVGAState, uBpp),
390 SSMFIELD_ENTRY( VMSVGAState, cbScanline),
391 SSMFIELD_ENTRY( VMSVGAState, u32MaxWidth),
392 SSMFIELD_ENTRY( VMSVGAState, u32MaxHeight),
393 SSMFIELD_ENTRY( VMSVGAState, u32ActionFlags),
394 SSMFIELD_ENTRY( VMSVGAState, f3DEnabled),
395 SSMFIELD_ENTRY( VMSVGAState, fVRAMTracking),
396 SSMFIELD_ENTRY_IGNORE( VMSVGAState, u8FIFOExtCommand),
397 SSMFIELD_ENTRY_IGNORE( VMSVGAState, fFifoExtCommandWakeup),
398 SSMFIELD_ENTRY_TERM()
399};
400
401static void vmsvgaSetTraces(PVGASTATE pThis, bool fTraces);
402
403#endif /* IN_RING3 */
404
405#ifdef LOG_ENABLED
406
407/**
408 * Index register string name lookup
409 *
410 * @returns Index register string or "UNKNOWN"
411 * @param pThis VMSVGA State
412 * @param idxReg The index register.
413 */
414static const char *vmsvgaIndexToString(PVGASTATE pThis, uint32_t idxReg)
415{
416 switch (idxReg)
417 {
418 case SVGA_REG_ID:
419 return "SVGA_REG_ID";
420 case SVGA_REG_ENABLE:
421 return "SVGA_REG_ENABLE";
422 case SVGA_REG_WIDTH:
423 return "SVGA_REG_WIDTH";
424 case SVGA_REG_HEIGHT:
425 return "SVGA_REG_HEIGHT";
426 case SVGA_REG_MAX_WIDTH:
427 return "SVGA_REG_MAX_WIDTH";
428 case SVGA_REG_MAX_HEIGHT:
429 return "SVGA_REG_MAX_HEIGHT";
430 case SVGA_REG_DEPTH:
431 return "SVGA_REG_DEPTH";
432 case SVGA_REG_BITS_PER_PIXEL: /* Current bpp in the guest */
433 return "SVGA_REG_BITS_PER_PIXEL";
434 case SVGA_REG_HOST_BITS_PER_PIXEL: /* (Deprecated) */
435 return "SVGA_REG_HOST_BITS_PER_PIXEL";
436 case SVGA_REG_PSEUDOCOLOR:
437 return "SVGA_REG_PSEUDOCOLOR";
438 case SVGA_REG_RED_MASK:
439 return "SVGA_REG_RED_MASK";
440 case SVGA_REG_GREEN_MASK:
441 return "SVGA_REG_GREEN_MASK";
442 case SVGA_REG_BLUE_MASK:
443 return "SVGA_REG_BLUE_MASK";
444 case SVGA_REG_BYTES_PER_LINE:
445 return "SVGA_REG_BYTES_PER_LINE";
446 case SVGA_REG_VRAM_SIZE: /* VRAM size */
447 return "SVGA_REG_VRAM_SIZE";
448 case SVGA_REG_FB_START: /* Frame buffer physical address. */
449 return "SVGA_REG_FB_START";
450 case SVGA_REG_FB_OFFSET: /* Offset of the frame buffer in VRAM */
451 return "SVGA_REG_FB_OFFSET";
452 case SVGA_REG_FB_SIZE: /* Frame buffer size */
453 return "SVGA_REG_FB_SIZE";
454 case SVGA_REG_CAPABILITIES:
455 return "SVGA_REG_CAPABILITIES";
456 case SVGA_REG_MEM_START: /* FIFO start */
457 return "SVGA_REG_MEM_START";
458 case SVGA_REG_MEM_SIZE: /* FIFO size */
459 return "SVGA_REG_MEM_SIZE";
460 case SVGA_REG_CONFIG_DONE: /* Set when memory area configured */
461 return "SVGA_REG_CONFIG_DONE";
462 case SVGA_REG_SYNC: /* See "FIFO Synchronization Registers" */
463 return "SVGA_REG_SYNC";
464 case SVGA_REG_BUSY: /* See "FIFO Synchronization Registers" */
465 return "SVGA_REG_BUSY";
466 case SVGA_REG_GUEST_ID: /* Set guest OS identifier */
467 return "SVGA_REG_GUEST_ID";
468 case SVGA_REG_SCRATCH_SIZE: /* Number of scratch registers */
469 return "SVGA_REG_SCRATCH_SIZE";
470 case SVGA_REG_MEM_REGS: /* Number of FIFO registers */
471 return "SVGA_REG_MEM_REGS";
472 case SVGA_REG_PITCHLOCK: /* Fixed pitch for all modes */
473 return "SVGA_REG_PITCHLOCK";
474 case SVGA_REG_IRQMASK: /* Interrupt mask */
475 return "SVGA_REG_IRQMASK";
476 case SVGA_REG_GMR_ID:
477 return "SVGA_REG_GMR_ID";
478 case SVGA_REG_GMR_DESCRIPTOR:
479 return "SVGA_REG_GMR_DESCRIPTOR";
480 case SVGA_REG_GMR_MAX_IDS:
481 return "SVGA_REG_GMR_MAX_IDS";
482 case SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH:
483 return "SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH";
484 case SVGA_REG_TRACES: /* Enable trace-based updates even when FIFO is on */
485 return "SVGA_REG_TRACES";
486 case SVGA_REG_GMRS_MAX_PAGES: /* Maximum number of 4KB pages for all GMRs */
487 return "SVGA_REG_GMRS_MAX_PAGES";
488 case SVGA_REG_MEMORY_SIZE: /* Total dedicated device memory excluding FIFO */
489 return "SVGA_REG_MEMORY_SIZE";
490 case SVGA_REG_TOP: /* Must be 1 more than the last register */
491 return "SVGA_REG_TOP";
492 case SVGA_PALETTE_BASE: /* Base of SVGA color map */
493 return "SVGA_PALETTE_BASE";
494 case SVGA_REG_CURSOR_ID:
495 return "SVGA_REG_CURSOR_ID";
496 case SVGA_REG_CURSOR_X:
497 return "SVGA_REG_CURSOR_X";
498 case SVGA_REG_CURSOR_Y:
499 return "SVGA_REG_CURSOR_Y";
500 case SVGA_REG_CURSOR_ON:
501 return "SVGA_REG_CURSOR_ON";
502 case SVGA_REG_NUM_GUEST_DISPLAYS:/* Number of guest displays in X/Y direction */
503 return "SVGA_REG_NUM_GUEST_DISPLAYS";
504 case SVGA_REG_DISPLAY_ID: /* Display ID for the following display attributes */
505 return "SVGA_REG_DISPLAY_ID";
506 case SVGA_REG_DISPLAY_IS_PRIMARY:/* Whether this is a primary display */
507 return "SVGA_REG_DISPLAY_IS_PRIMARY";
508 case SVGA_REG_DISPLAY_POSITION_X:/* The display position x */
509 return "SVGA_REG_DISPLAY_POSITION_X";
510 case SVGA_REG_DISPLAY_POSITION_Y:/* The display position y */
511 return "SVGA_REG_DISPLAY_POSITION_Y";
512 case SVGA_REG_DISPLAY_WIDTH: /* The display's width */
513 return "SVGA_REG_DISPLAY_WIDTH";
514 case SVGA_REG_DISPLAY_HEIGHT: /* The display's height */
515 return "SVGA_REG_DISPLAY_HEIGHT";
516 case SVGA_REG_NUM_DISPLAYS: /* (Deprecated) */
517 return "SVGA_REG_NUM_DISPLAYS";
518
519 default:
520 if (idxReg - (uint32_t)SVGA_SCRATCH_BASE < pThis->svga.cScratchRegion)
521 return "SVGA_SCRATCH_BASE reg";
522 if (idxReg - (uint32_t)SVGA_PALETTE_BASE < (uint32_t)SVGA_NUM_PALETTE_REGS)
523 return "SVGA_PALETTE_BASE reg";
524 return "UNKNOWN";
525 }
526}
527
528#ifdef IN_RING3
529/**
530 * FIFO command name lookup
531 *
532 * @returns FIFO command string or "UNKNOWN"
533 * @param u32Cmd FIFO command
534 */
535static const char *vmsvgaFIFOCmdToString(uint32_t u32Cmd)
536{
537 switch (u32Cmd)
538 {
539 case SVGA_CMD_INVALID_CMD:
540 return "SVGA_CMD_INVALID_CMD";
541 case SVGA_CMD_UPDATE:
542 return "SVGA_CMD_UPDATE";
543 case SVGA_CMD_RECT_COPY:
544 return "SVGA_CMD_RECT_COPY";
545 case SVGA_CMD_DEFINE_CURSOR:
546 return "SVGA_CMD_DEFINE_CURSOR";
547 case SVGA_CMD_DEFINE_ALPHA_CURSOR:
548 return "SVGA_CMD_DEFINE_ALPHA_CURSOR";
549 case SVGA_CMD_UPDATE_VERBOSE:
550 return "SVGA_CMD_UPDATE_VERBOSE";
551 case SVGA_CMD_FRONT_ROP_FILL:
552 return "SVGA_CMD_FRONT_ROP_FILL";
553 case SVGA_CMD_FENCE:
554 return "SVGA_CMD_FENCE";
555 case SVGA_CMD_ESCAPE:
556 return "SVGA_CMD_ESCAPE";
557 case SVGA_CMD_DEFINE_SCREEN:
558 return "SVGA_CMD_DEFINE_SCREEN";
559 case SVGA_CMD_DESTROY_SCREEN:
560 return "SVGA_CMD_DESTROY_SCREEN";
561 case SVGA_CMD_DEFINE_GMRFB:
562 return "SVGA_CMD_DEFINE_GMRFB";
563 case SVGA_CMD_BLIT_GMRFB_TO_SCREEN:
564 return "SVGA_CMD_BLIT_GMRFB_TO_SCREEN";
565 case SVGA_CMD_BLIT_SCREEN_TO_GMRFB:
566 return "SVGA_CMD_BLIT_SCREEN_TO_GMRFB";
567 case SVGA_CMD_ANNOTATION_FILL:
568 return "SVGA_CMD_ANNOTATION_FILL";
569 case SVGA_CMD_ANNOTATION_COPY:
570 return "SVGA_CMD_ANNOTATION_COPY";
571 case SVGA_CMD_DEFINE_GMR2:
572 return "SVGA_CMD_DEFINE_GMR2";
573 case SVGA_CMD_REMAP_GMR2:
574 return "SVGA_CMD_REMAP_GMR2";
575 case SVGA_3D_CMD_SURFACE_DEFINE:
576 return "SVGA_3D_CMD_SURFACE_DEFINE";
577 case SVGA_3D_CMD_SURFACE_DESTROY:
578 return "SVGA_3D_CMD_SURFACE_DESTROY";
579 case SVGA_3D_CMD_SURFACE_COPY:
580 return "SVGA_3D_CMD_SURFACE_COPY";
581 case SVGA_3D_CMD_SURFACE_STRETCHBLT:
582 return "SVGA_3D_CMD_SURFACE_STRETCHBLT";
583 case SVGA_3D_CMD_SURFACE_DMA:
584 return "SVGA_3D_CMD_SURFACE_DMA";
585 case SVGA_3D_CMD_CONTEXT_DEFINE:
586 return "SVGA_3D_CMD_CONTEXT_DEFINE";
587 case SVGA_3D_CMD_CONTEXT_DESTROY:
588 return "SVGA_3D_CMD_CONTEXT_DESTROY";
589 case SVGA_3D_CMD_SETTRANSFORM:
590 return "SVGA_3D_CMD_SETTRANSFORM";
591 case SVGA_3D_CMD_SETZRANGE:
592 return "SVGA_3D_CMD_SETZRANGE";
593 case SVGA_3D_CMD_SETRENDERSTATE:
594 return "SVGA_3D_CMD_SETRENDERSTATE";
595 case SVGA_3D_CMD_SETRENDERTARGET:
596 return "SVGA_3D_CMD_SETRENDERTARGET";
597 case SVGA_3D_CMD_SETTEXTURESTATE:
598 return "SVGA_3D_CMD_SETTEXTURESTATE";
599 case SVGA_3D_CMD_SETMATERIAL:
600 return "SVGA_3D_CMD_SETMATERIAL";
601 case SVGA_3D_CMD_SETLIGHTDATA:
602 return "SVGA_3D_CMD_SETLIGHTDATA";
603 case SVGA_3D_CMD_SETLIGHTENABLED:
604 return "SVGA_3D_CMD_SETLIGHTENABLED";
605 case SVGA_3D_CMD_SETVIEWPORT:
606 return "SVGA_3D_CMD_SETVIEWPORT";
607 case SVGA_3D_CMD_SETCLIPPLANE:
608 return "SVGA_3D_CMD_SETCLIPPLANE";
609 case SVGA_3D_CMD_CLEAR:
610 return "SVGA_3D_CMD_CLEAR";
611 case SVGA_3D_CMD_PRESENT:
612 return "SVGA_3D_CMD_PRESENT";
613 case SVGA_3D_CMD_SHADER_DEFINE:
614 return "SVGA_3D_CMD_SHADER_DEFINE";
615 case SVGA_3D_CMD_SHADER_DESTROY:
616 return "SVGA_3D_CMD_SHADER_DESTROY";
617 case SVGA_3D_CMD_SET_SHADER:
618 return "SVGA_3D_CMD_SET_SHADER";
619 case SVGA_3D_CMD_SET_SHADER_CONST:
620 return "SVGA_3D_CMD_SET_SHADER_CONST";
621 case SVGA_3D_CMD_DRAW_PRIMITIVES:
622 return "SVGA_3D_CMD_DRAW_PRIMITIVES";
623 case SVGA_3D_CMD_SETSCISSORRECT:
624 return "SVGA_3D_CMD_SETSCISSORRECT";
625 case SVGA_3D_CMD_BEGIN_QUERY:
626 return "SVGA_3D_CMD_BEGIN_QUERY";
627 case SVGA_3D_CMD_END_QUERY:
628 return "SVGA_3D_CMD_END_QUERY";
629 case SVGA_3D_CMD_WAIT_FOR_QUERY:
630 return "SVGA_3D_CMD_WAIT_FOR_QUERY";
631 case SVGA_3D_CMD_PRESENT_READBACK:
632 return "SVGA_3D_CMD_PRESENT_READBACK";
633 case SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN:
634 return "SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN";
635 case SVGA_3D_CMD_SURFACE_DEFINE_V2:
636 return "SVGA_3D_CMD_SURFACE_DEFINE_V2";
637 case SVGA_3D_CMD_GENERATE_MIPMAPS:
638 return "SVGA_3D_CMD_GENERATE_MIPMAPS";
639 case SVGA_3D_CMD_ACTIVATE_SURFACE:
640 return "SVGA_3D_CMD_ACTIVATE_SURFACE";
641 case SVGA_3D_CMD_DEACTIVATE_SURFACE:
642 return "SVGA_3D_CMD_DEACTIVATE_SURFACE";
643 default:
644 return "UNKNOWN";
645 }
646}
647# endif /* IN_RING3 */
648
649#endif /* LOG_ENABLED */
650
651#ifdef IN_RING3
652/**
653 * @interface_method_impl{PDMIDISPLAYPORT,pfnSetViewport}
654 */
655DECLCALLBACK(void) vmsvgaPortSetViewport(PPDMIDISPLAYPORT pInterface, uint32_t idScreen, uint32_t x, uint32_t y, uint32_t cx, uint32_t cy)
656{
657 PVGASTATE pThis = RT_FROM_MEMBER(pInterface, VGASTATE, IPort);
658
659 Log(("vmsvgaPortSetViewPort: screen %d (%d,%d)(%d,%d)\n", idScreen, x, y, cx, cy));
660 VMSVGAVIEWPORT const OldViewport = pThis->svga.viewport;
661
662 if (x < pThis->svga.uWidth)
663 {
664 pThis->svga.viewport.x = x;
665 pThis->svga.viewport.cx = RT_MIN(cx, pThis->svga.uWidth - x);
666 pThis->svga.viewport.xRight = x + pThis->svga.viewport.cx;
667 }
668 else
669 {
670 pThis->svga.viewport.x = pThis->svga.uWidth;
671 pThis->svga.viewport.cx = 0;
672 pThis->svga.viewport.xRight = pThis->svga.uWidth;
673 }
674 if (y < pThis->svga.uHeight)
675 {
676 pThis->svga.viewport.y = y;
677 pThis->svga.viewport.cy = RT_MIN(cy, pThis->svga.uHeight - y);
678 pThis->svga.viewport.yLowWC = pThis->svga.uHeight - y - pThis->svga.viewport.cy;
679 pThis->svga.viewport.yHighWC = pThis->svga.uHeight - y;
680 }
681 else
682 {
683 pThis->svga.viewport.y = pThis->svga.uHeight;
684 pThis->svga.viewport.cy = 0;
685 pThis->svga.viewport.yLowWC = 0;
686 pThis->svga.viewport.yHighWC = 0;
687 }
688
689# ifdef VBOX_WITH_VMSVGA3D
690 /*
691 * Now inform the 3D backend.
692 */
693 if (pThis->svga.f3DEnabled)
694 vmsvga3dUpdateHostScreenViewport(pThis, idScreen, &OldViewport);
695# else
696 RT_NOREF(idScreen, OldViewport);
697# endif
698}
699#endif /* IN_RING3 */
700
701/**
702 * Read port register
703 *
704 * @returns VBox status code.
705 * @param pThis VMSVGA State
706 * @param pu32 Where to store the read value
707 */
708PDMBOTHCBDECL(int) vmsvgaReadPort(PVGASTATE pThis, uint32_t *pu32)
709{
710 int rc = VINF_SUCCESS;
711 *pu32 = 0;
712
713 /* We must adjust the register number if we're in SVGA_ID_0 mode because the PALETTE range moved. */
714 uint32_t idxReg = pThis->svga.u32IndexReg;
715 if ( idxReg >= SVGA_REG_CAPABILITIES
716 && pThis->svga.u32SVGAId == SVGA_ID_0)
717 {
718 idxReg += SVGA_PALETTE_BASE - SVGA_REG_CAPABILITIES;
719 Log(("vmsvgaWritePort: SVGA_ID_0 reg adj %#x -> %#x\n", pThis->svga.u32IndexReg, idxReg));
720 }
721
722 switch (idxReg)
723 {
724 case SVGA_REG_ID:
725 STAM_REL_COUNTER_INC(&pThis->svga.StatRegIdRd);
726 *pu32 = pThis->svga.u32SVGAId;
727 break;
728
729 case SVGA_REG_ENABLE:
730 STAM_REL_COUNTER_INC(&pThis->svga.StatRegEnableRd);
731 *pu32 = pThis->svga.fEnabled;
732 break;
733
734 case SVGA_REG_WIDTH:
735 {
736 STAM_REL_COUNTER_INC(&pThis->svga.StatRegWidthRd);
737 if ( pThis->svga.fEnabled
738 && pThis->svga.uWidth != VMSVGA_VAL_UNINITIALIZED)
739 {
740 *pu32 = pThis->svga.uWidth;
741 }
742 else
743 {
744#ifndef IN_RING3
745 rc = VINF_IOM_R3_IOPORT_READ;
746#else
747 *pu32 = pThis->pDrv->cx;
748#endif
749 }
750 break;
751 }
752
753 case SVGA_REG_HEIGHT:
754 {
755 STAM_REL_COUNTER_INC(&pThis->svga.StatRegHeightRd);
756 if ( pThis->svga.fEnabled
757 && pThis->svga.uHeight != VMSVGA_VAL_UNINITIALIZED)
758 {
759 *pu32 = pThis->svga.uHeight;
760 }
761 else
762 {
763#ifndef IN_RING3
764 rc = VINF_IOM_R3_IOPORT_READ;
765#else
766 *pu32 = pThis->pDrv->cy;
767#endif
768 }
769 break;
770 }
771
772 case SVGA_REG_MAX_WIDTH:
773 STAM_REL_COUNTER_INC(&pThis->svga.StatRegMaxWidthRd);
774 *pu32 = pThis->svga.u32MaxWidth;
775 break;
776
777 case SVGA_REG_MAX_HEIGHT:
778 STAM_REL_COUNTER_INC(&pThis->svga.StatRegMaxHeightRd);
779 *pu32 = pThis->svga.u32MaxHeight;
780 break;
781
782 case SVGA_REG_DEPTH:
783 /* This returns the color depth of the current mode. */
784 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDepthRd);
785 switch (pThis->svga.uBpp)
786 {
787 case 15:
788 case 16:
789 case 24:
790 *pu32 = pThis->svga.uBpp;
791 break;
792
793 default:
794 case 32:
795 *pu32 = 24; /* The upper 8 bits are either alpha bits or not used. */
796 break;
797 }
798 break;
799
800 case SVGA_REG_HOST_BITS_PER_PIXEL: /* (Deprecated) */
801 STAM_REL_COUNTER_INC(&pThis->svga.StatRegHostBitsPerPixelRd);
802 if ( pThis->svga.fEnabled
803 && pThis->svga.uBpp != VMSVGA_VAL_UNINITIALIZED)
804 {
805 *pu32 = pThis->svga.uBpp;
806 }
807 else
808 {
809#ifndef IN_RING3
810 rc = VINF_IOM_R3_IOPORT_READ;
811#else
812 *pu32 = pThis->pDrv->cBits;
813#endif
814 }
815 break;
816
817 case SVGA_REG_BITS_PER_PIXEL: /* Current bpp in the guest */
818 STAM_REL_COUNTER_INC(&pThis->svga.StatRegBitsPerPixelRd);
819 if ( pThis->svga.fEnabled
820 && pThis->svga.uBpp != VMSVGA_VAL_UNINITIALIZED)
821 {
822 *pu32 = (pThis->svga.uBpp + 7) & ~7;
823 }
824 else
825 {
826#ifndef IN_RING3
827 rc = VINF_IOM_R3_IOPORT_READ;
828#else
829 *pu32 = (pThis->pDrv->cBits + 7) & ~7;
830#endif
831 }
832 break;
833
834 case SVGA_REG_PSEUDOCOLOR:
835 STAM_REL_COUNTER_INC(&pThis->svga.StatRegPsuedoColorRd);
836 *pu32 = 0;
837 break;
838
839 case SVGA_REG_RED_MASK:
840 case SVGA_REG_GREEN_MASK:
841 case SVGA_REG_BLUE_MASK:
842 {
843 uint32_t uBpp;
844
845 if ( pThis->svga.fEnabled
846 && pThis->svga.uBpp != VMSVGA_VAL_UNINITIALIZED)
847 {
848 uBpp = pThis->svga.uBpp;
849 }
850 else
851 {
852#ifndef IN_RING3
853 rc = VINF_IOM_R3_IOPORT_READ;
854 break;
855#else
856 uBpp = pThis->pDrv->cBits;
857#endif
858 }
859 uint32_t u32RedMask, u32GreenMask, u32BlueMask;
860 switch (uBpp)
861 {
862 case 8:
863 u32RedMask = 0x07;
864 u32GreenMask = 0x38;
865 u32BlueMask = 0xc0;
866 break;
867
868 case 15:
869 u32RedMask = 0x0000001f;
870 u32GreenMask = 0x000003e0;
871 u32BlueMask = 0x00007c00;
872 break;
873
874 case 16:
875 u32RedMask = 0x0000001f;
876 u32GreenMask = 0x000007e0;
877 u32BlueMask = 0x0000f800;
878 break;
879
880 case 24:
881 case 32:
882 default:
883 u32RedMask = 0x00ff0000;
884 u32GreenMask = 0x0000ff00;
885 u32BlueMask = 0x000000ff;
886 break;
887 }
888 switch (idxReg)
889 {
890 case SVGA_REG_RED_MASK:
891 STAM_REL_COUNTER_INC(&pThis->svga.StatRegRedMaskRd);
892 *pu32 = u32RedMask;
893 break;
894
895 case SVGA_REG_GREEN_MASK:
896 STAM_REL_COUNTER_INC(&pThis->svga.StatRegGreenMaskRd);
897 *pu32 = u32GreenMask;
898 break;
899
900 case SVGA_REG_BLUE_MASK:
901 STAM_REL_COUNTER_INC(&pThis->svga.StatRegBlueMaskRd);
902 *pu32 = u32BlueMask;
903 break;
904 }
905 break;
906 }
907
908 case SVGA_REG_BYTES_PER_LINE:
909 {
910 STAM_REL_COUNTER_INC(&pThis->svga.StatRegBytesPerLineRd);
911 if ( pThis->svga.fEnabled
912 && pThis->svga.cbScanline)
913 {
914 *pu32 = pThis->svga.cbScanline;
915 }
916 else
917 {
918#ifndef IN_RING3
919 rc = VINF_IOM_R3_IOPORT_READ;
920#else
921 *pu32 = pThis->pDrv->cbScanline;
922#endif
923 }
924 break;
925 }
926
927 case SVGA_REG_VRAM_SIZE: /* VRAM size */
928 STAM_REL_COUNTER_INC(&pThis->svga.StatRegVramSizeRd);
929 *pu32 = pThis->vram_size;
930 break;
931
932 case SVGA_REG_FB_START: /* Frame buffer physical address. */
933 STAM_REL_COUNTER_INC(&pThis->svga.StatRegFbStartRd);
934 Assert(pThis->GCPhysVRAM <= 0xffffffff);
935 *pu32 = pThis->GCPhysVRAM;
936 break;
937
938 case SVGA_REG_FB_OFFSET: /* Offset of the frame buffer in VRAM */
939 STAM_REL_COUNTER_INC(&pThis->svga.StatRegFbOffsetRd);
940 /* Always zero in our case. */
941 *pu32 = 0;
942 break;
943
944 case SVGA_REG_FB_SIZE: /* Frame buffer size */
945 {
946#ifndef IN_RING3
947 rc = VINF_IOM_R3_IOPORT_READ;
948#else
949 STAM_REL_COUNTER_INC(&pThis->svga.StatRegFbSizeRd);
950
951 /* VMWare testcases want at least 4 MB in case the hardware is disabled. */
952 if ( pThis->svga.fEnabled
953 && pThis->svga.uHeight != VMSVGA_VAL_UNINITIALIZED)
954 {
955 /* Hardware enabled; return real framebuffer size .*/
956 *pu32 = (uint32_t)pThis->svga.uHeight * pThis->svga.cbScanline;
957 }
958 else
959 *pu32 = RT_MAX(0x100000, (uint32_t)pThis->pDrv->cy * pThis->pDrv->cbScanline);
960
961 *pu32 = RT_MIN(pThis->vram_size, *pu32);
962 Log(("h=%d w=%d bpp=%d\n", pThis->pDrv->cy, pThis->pDrv->cx, pThis->pDrv->cBits));
963#endif
964 break;
965 }
966
967 case SVGA_REG_CAPABILITIES:
968 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCapabilitesRd);
969 *pu32 = pThis->svga.u32RegCaps;
970 break;
971
972 case SVGA_REG_MEM_START: /* FIFO start */
973 STAM_REL_COUNTER_INC(&pThis->svga.StatRegMemStartRd);
974 Assert(pThis->svga.GCPhysFIFO <= 0xffffffff);
975 *pu32 = pThis->svga.GCPhysFIFO;
976 break;
977
978 case SVGA_REG_MEM_SIZE: /* FIFO size */
979 STAM_REL_COUNTER_INC(&pThis->svga.StatRegMemSizeRd);
980 *pu32 = pThis->svga.cbFIFO;
981 break;
982
983 case SVGA_REG_CONFIG_DONE: /* Set when memory area configured */
984 STAM_REL_COUNTER_INC(&pThis->svga.StatRegConfigDoneRd);
985 *pu32 = pThis->svga.fConfigured;
986 break;
987
988 case SVGA_REG_SYNC: /* See "FIFO Synchronization Registers" */
989 STAM_REL_COUNTER_INC(&pThis->svga.StatRegSyncRd);
990 *pu32 = 0;
991 break;
992
993 case SVGA_REG_BUSY: /* See "FIFO Synchronization Registers" */
994 STAM_REL_COUNTER_INC(&pThis->svga.StatRegBusyRd);
995 if (pThis->svga.fBusy)
996 {
997#ifndef IN_RING3
998 /* Go to ring-3 and halt the CPU. */
999 rc = VINF_IOM_R3_IOPORT_READ;
1000 break;
1001#else
1002# if defined(VMSVGA_USE_EMT_HALT_CODE)
1003 /* The guest is basically doing a HLT via the device here, but with
1004 a special wake up condition on FIFO completion. */
1005 PVMSVGAR3STATE pSVGAState = pThis->svga.pSvgaR3State;
1006 STAM_REL_PROFILE_START(&pSVGAState->StatBusyDelayEmts, EmtDelay);
1007 PVM pVM = PDMDevHlpGetVM(pThis->pDevInsR3);
1008 VMCPUID idCpu = PDMDevHlpGetCurrentCpuId(pThis->pDevInsR3);
1009 VMCPUSET_ATOMIC_ADD(&pSVGAState->BusyDelayedEmts, idCpu);
1010 ASMAtomicIncU32(&pSVGAState->cBusyDelayedEmts);
1011 if (pThis->svga.fBusy)
1012 rc = VMR3WaitForDeviceReady(pVM, idCpu);
1013 ASMAtomicDecU32(&pSVGAState->cBusyDelayedEmts);
1014 VMCPUSET_ATOMIC_DEL(&pSVGAState->BusyDelayedEmts, idCpu);
1015# else
1016
1017 /* Delay the EMT a bit so the FIFO and others can get some work done.
1018 This used to be a crude 50 ms sleep. The current code tries to be
1019 more efficient, but the consept is still very crude. */
1020 PVMSVGAR3STATE pSVGAState = pThis->svga.pSvgaR3State;
1021 STAM_REL_PROFILE_START(&pSVGAState->StatBusyDelayEmts, EmtDelay);
1022 RTThreadYield();
1023 if (pThis->svga.fBusy)
1024 {
1025 uint32_t cRefs = ASMAtomicIncU32(&pSVGAState->cBusyDelayedEmts);
1026
1027 if (pThis->svga.fBusy && cRefs == 1)
1028 RTSemEventMultiReset(pSVGAState->hBusyDelayedEmts);
1029 if (pThis->svga.fBusy)
1030 {
1031 /** @todo If this code is going to stay, we need to call into the halt/wait
1032 * code in VMEmt.cpp here, otherwise all kind of EMT interaction will
1033 * suffer when the guest is polling on a busy FIFO. */
1034 uint64_t cNsMaxWait = TMVirtualSyncGetNsToDeadline(PDMDevHlpGetVM(pThis->pDevInsR3));
1035 if (cNsMaxWait >= RT_NS_100US)
1036 RTSemEventMultiWaitEx(pSVGAState->hBusyDelayedEmts,
1037 RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_NORESUME,
1038 RT_MIN(cNsMaxWait, RT_NS_10MS));
1039 }
1040
1041 ASMAtomicDecU32(&pSVGAState->cBusyDelayedEmts);
1042 }
1043 STAM_REL_PROFILE_STOP(&pSVGAState->StatBusyDelayEmts, EmtDelay);
1044# endif
1045 *pu32 = pThis->svga.fBusy != 0;
1046#endif
1047 }
1048 else
1049 *pu32 = false;
1050 break;
1051
1052 case SVGA_REG_GUEST_ID: /* Set guest OS identifier */
1053 STAM_REL_COUNTER_INC(&pThis->svga.StatRegGuestIdRd);
1054 *pu32 = pThis->svga.u32GuestId;
1055 break;
1056
1057 case SVGA_REG_SCRATCH_SIZE: /* Number of scratch registers */
1058 STAM_REL_COUNTER_INC(&pThis->svga.StatRegScratchSizeRd);
1059 *pu32 = pThis->svga.cScratchRegion;
1060 break;
1061
1062 case SVGA_REG_MEM_REGS: /* Number of FIFO registers */
1063 STAM_REL_COUNTER_INC(&pThis->svga.StatRegMemRegsRd);
1064 *pu32 = SVGA_FIFO_NUM_REGS;
1065 break;
1066
1067 case SVGA_REG_PITCHLOCK: /* Fixed pitch for all modes */
1068 STAM_REL_COUNTER_INC(&pThis->svga.StatRegPitchLockRd);
1069 *pu32 = pThis->svga.u32PitchLock;
1070 break;
1071
1072 case SVGA_REG_IRQMASK: /* Interrupt mask */
1073 STAM_REL_COUNTER_INC(&pThis->svga.StatRegIrqMaskRd);
1074 *pu32 = pThis->svga.u32IrqMask;
1075 break;
1076
1077 /* See "Guest memory regions" below. */
1078 case SVGA_REG_GMR_ID:
1079 STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrIdRd);
1080 *pu32 = pThis->svga.u32CurrentGMRId;
1081 break;
1082
1083 case SVGA_REG_GMR_DESCRIPTOR:
1084 STAM_REL_COUNTER_INC(&pThis->svga.StatRegWriteOnlyRd);
1085 /* Write only */
1086 *pu32 = 0;
1087 break;
1088
1089 case SVGA_REG_GMR_MAX_IDS:
1090 STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrMaxIdsRd);
1091 *pu32 = VMSVGA_MAX_GMR_IDS;
1092 break;
1093
1094 case SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH:
1095 STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrMaxDescriptorLengthRd);
1096 *pu32 = VMSVGA_MAX_GMR_PAGES;
1097 break;
1098
1099 case SVGA_REG_TRACES: /* Enable trace-based updates even when FIFO is on */
1100 STAM_REL_COUNTER_INC(&pThis->svga.StatRegTracesRd);
1101 *pu32 = pThis->svga.fTraces;
1102 break;
1103
1104 case SVGA_REG_GMRS_MAX_PAGES: /* Maximum number of 4KB pages for all GMRs */
1105 STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrsMaxPagesRd);
1106 *pu32 = VMSVGA_MAX_GMR_PAGES;
1107 break;
1108
1109 case SVGA_REG_MEMORY_SIZE: /* Total dedicated device memory excluding FIFO */
1110 STAM_REL_COUNTER_INC(&pThis->svga.StatRegMemorySizeRd);
1111 *pu32 = VMSVGA_SURFACE_SIZE;
1112 break;
1113
1114 case SVGA_REG_TOP: /* Must be 1 more than the last register */
1115 STAM_REL_COUNTER_INC(&pThis->svga.StatRegTopRd);
1116 break;
1117
1118 /* Mouse cursor support. */
1119 case SVGA_REG_CURSOR_ID:
1120 case SVGA_REG_CURSOR_X:
1121 case SVGA_REG_CURSOR_Y:
1122 case SVGA_REG_CURSOR_ON:
1123 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorXxxxRd);
1124 break;
1125
1126 /* Legacy multi-monitor support */
1127 case SVGA_REG_NUM_GUEST_DISPLAYS:/* Number of guest displays in X/Y direction */
1128 STAM_REL_COUNTER_INC(&pThis->svga.StatRegNumGuestDisplaysRd);
1129 *pu32 = 1;
1130 break;
1131
1132 case SVGA_REG_DISPLAY_ID: /* Display ID for the following display attributes */
1133 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayIdRd);
1134 *pu32 = 0;
1135 break;
1136
1137 case SVGA_REG_DISPLAY_IS_PRIMARY:/* Whether this is a primary display */
1138 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayIsPrimaryRd);
1139 *pu32 = 0;
1140 break;
1141
1142 case SVGA_REG_DISPLAY_POSITION_X:/* The display position x */
1143 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayPositionXRd);
1144 *pu32 = 0;
1145 break;
1146
1147 case SVGA_REG_DISPLAY_POSITION_Y:/* The display position y */
1148 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayPositionYRd);
1149 *pu32 = 0;
1150 break;
1151
1152 case SVGA_REG_DISPLAY_WIDTH: /* The display's width */
1153 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayWidthRd);
1154 *pu32 = pThis->svga.uWidth;
1155 break;
1156
1157 case SVGA_REG_DISPLAY_HEIGHT: /* The display's height */
1158 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayHeightRd);
1159 *pu32 = pThis->svga.uHeight;
1160 break;
1161
1162 case SVGA_REG_NUM_DISPLAYS: /* (Deprecated) */
1163 STAM_REL_COUNTER_INC(&pThis->svga.StatRegNumDisplaysRd);
1164 *pu32 = 1; /* Must return something sensible here otherwise the Linux driver will take a legacy code path without 3d support. */
1165 break;
1166
1167 default:
1168 {
1169 uint32_t offReg;
1170 if ((offReg = idxReg - SVGA_SCRATCH_BASE) < pThis->svga.cScratchRegion)
1171 {
1172 *pu32 = pThis->svga.au32ScratchRegion[offReg];
1173 STAM_REL_COUNTER_INC(&pThis->svga.StatRegScratchRd);
1174 }
1175 else if ((offReg = idxReg - SVGA_PALETTE_BASE) < (uint32_t)SVGA_NUM_PALETTE_REGS)
1176 {
1177 STAM_REL_COUNTER_INC(&pThis->svga.StatRegPaletteRd);
1178 /* Next 768 (== 256*3) registers exist for colormap */
1179 }
1180 else
1181 {
1182#if !defined(IN_RING3) && defined(VBOX_STRICT)
1183 rc = VINF_IOM_R3_IOPORT_READ;
1184#else
1185 STAM_REL_COUNTER_INC(&pThis->svga.StatRegUnknownRd);
1186 AssertMsgFailed(("reg=%#x\n", idxReg));
1187#endif
1188 }
1189 break;
1190 }
1191 }
1192 Log(("vmsvgaReadPort index=%s (%d) val=%#x rc=%x\n", vmsvgaIndexToString(pThis, idxReg), idxReg, *pu32, rc));
1193 return rc;
1194}
1195
1196#ifdef IN_RING3
1197/**
1198 * Apply the current resolution settings to change the video mode.
1199 *
1200 * @returns VBox status code.
1201 * @param pThis VMSVGA State
1202 */
1203int vmsvgaChangeMode(PVGASTATE pThis)
1204{
1205 int rc;
1206
1207 if ( pThis->svga.uWidth == VMSVGA_VAL_UNINITIALIZED
1208 || pThis->svga.uHeight == VMSVGA_VAL_UNINITIALIZED
1209 || pThis->svga.uBpp == VMSVGA_VAL_UNINITIALIZED)
1210 {
1211 /* Mode change in progress; wait for all values to be set. */
1212 Log(("vmsvgaChangeMode: BOGUS sEnable LFB mode and resize to (%d,%d) bpp=%d\n", pThis->svga.uWidth, pThis->svga.uHeight, pThis->svga.uBpp));
1213 return VINF_SUCCESS;
1214 }
1215
1216 if ( pThis->svga.uWidth == 0
1217 || pThis->svga.uHeight == 0
1218 || pThis->svga.uBpp == 0)
1219 {
1220 /* Invalid mode change - BB does this early in the boot up. */
1221 Log(("vmsvgaChangeMode: BOGUS sEnable LFB mode and resize to (%d,%d) bpp=%d\n", pThis->svga.uWidth, pThis->svga.uHeight, pThis->svga.uBpp));
1222 return VINF_SUCCESS;
1223 }
1224
1225 if ( pThis->last_bpp == (unsigned)pThis->svga.uBpp
1226 && pThis->last_scr_width == (unsigned)pThis->svga.uWidth
1227 && pThis->last_scr_height == (unsigned)pThis->svga.uHeight
1228 && pThis->last_width == (unsigned)pThis->svga.uWidth
1229 && pThis->last_height == (unsigned)pThis->svga.uHeight
1230 )
1231 {
1232 /* Nothing to do. */
1233 Log(("vmsvgaChangeMode: nothing changed; ignore\n"));
1234 return VINF_SUCCESS;
1235 }
1236
1237 Log(("vmsvgaChangeMode: sEnable LFB mode and resize to (%d,%d) bpp=%d\n", pThis->svga.uWidth, pThis->svga.uHeight, pThis->svga.uBpp));
1238 pThis->svga.cbScanline = ((pThis->svga.uWidth * pThis->svga.uBpp + 7) & ~7) / 8;
1239
1240 pThis->pDrv->pfnLFBModeChange(pThis->pDrv, true);
1241 rc = pThis->pDrv->pfnResize(pThis->pDrv, pThis->svga.uBpp, pThis->CTX_SUFF(vram_ptr), pThis->svga.cbScanline, pThis->svga.uWidth, pThis->svga.uHeight);
1242 AssertRC(rc);
1243 AssertReturn(rc == VINF_SUCCESS || rc == VINF_VGA_RESIZE_IN_PROGRESS, rc);
1244
1245 /* last stuff */
1246 pThis->last_bpp = pThis->svga.uBpp;
1247 pThis->last_scr_width = pThis->svga.uWidth;
1248 pThis->last_scr_height = pThis->svga.uHeight;
1249 pThis->last_width = pThis->svga.uWidth;
1250 pThis->last_height = pThis->svga.uHeight;
1251
1252 ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE);
1253
1254 /* vmsvgaPortSetViewPort not called after state load; set sensible defaults. */
1255 if ( pThis->svga.viewport.cx == 0
1256 && pThis->svga.viewport.cy == 0)
1257 {
1258 pThis->svga.viewport.cx = pThis->svga.uWidth;
1259 pThis->svga.viewport.xRight = pThis->svga.uWidth;
1260 pThis->svga.viewport.cy = pThis->svga.uHeight;
1261 pThis->svga.viewport.yHighWC = pThis->svga.uHeight;
1262 pThis->svga.viewport.yLowWC = 0;
1263 }
1264 return VINF_SUCCESS;
1265}
1266#endif /* IN_RING3 */
1267
1268#if defined(IN_RING0) || defined(IN_RING3)
1269/**
1270 * Safely updates the SVGA_FIFO_BUSY register (in shared memory).
1271 *
1272 * @param pThis The VMSVGA state.
1273 * @param fState The busy state.
1274 */
1275DECLINLINE(void) vmsvgaSafeFifoBusyRegUpdate(PVGASTATE pThis, bool fState)
1276{
1277 ASMAtomicWriteU32(&pThis->svga.CTX_SUFF(pFIFO)[SVGA_FIFO_BUSY], fState);
1278
1279 if (RT_UNLIKELY(fState != (pThis->svga.fBusy != 0)))
1280 {
1281 /* Race / unfortunately scheduling. Highly unlikly. */
1282 uint32_t cLoops = 64;
1283 do
1284 {
1285 ASMNopPause();
1286 fState = (pThis->svga.fBusy != 0);
1287 ASMAtomicWriteU32(&pThis->svga.CTX_SUFF(pFIFO)[SVGA_FIFO_BUSY], fState != 0);
1288 } while (cLoops-- > 0 && fState != (pThis->svga.fBusy != 0));
1289 }
1290}
1291#endif
1292
1293/**
1294 * Write port register
1295 *
1296 * @returns VBox status code.
1297 * @param pThis VMSVGA State
1298 * @param u32 Value to write
1299 */
1300PDMBOTHCBDECL(int) vmsvgaWritePort(PVGASTATE pThis, uint32_t u32)
1301{
1302#ifdef IN_RING3
1303 PVMSVGAR3STATE pSVGAState = pThis->svga.pSvgaR3State;
1304#endif
1305 int rc = VINF_SUCCESS;
1306
1307 /* We must adjust the register number if we're in SVGA_ID_0 mode because the PALETTE range moved. */
1308 uint32_t idxReg = pThis->svga.u32IndexReg;
1309 if ( idxReg >= SVGA_REG_CAPABILITIES
1310 && pThis->svga.u32SVGAId == SVGA_ID_0)
1311 {
1312 idxReg += SVGA_PALETTE_BASE - SVGA_REG_CAPABILITIES;
1313 Log(("vmsvgaWritePort: SVGA_ID_0 reg adj %#x -> %#x\n", pThis->svga.u32IndexReg, idxReg));
1314 }
1315 Log(("vmsvgaWritePort index=%s (%d) val=%#x\n", vmsvgaIndexToString(pThis, idxReg), idxReg, u32));
1316 switch (idxReg)
1317 {
1318 case SVGA_REG_ID:
1319 STAM_REL_COUNTER_INC(&pThis->svga.StatRegIdWr);
1320 if ( u32 == SVGA_ID_0
1321 || u32 == SVGA_ID_1
1322 || u32 == SVGA_ID_2)
1323 pThis->svga.u32SVGAId = u32;
1324 else
1325 AssertMsgFailed(("%#x\n", u32));
1326 break;
1327
1328 case SVGA_REG_ENABLE:
1329 STAM_REL_COUNTER_INC(&pThis->svga.StatRegEnableWr);
1330 if ( pThis->svga.fEnabled == u32
1331 && pThis->last_bpp == (unsigned)pThis->svga.uBpp
1332 && pThis->last_scr_width == (unsigned)pThis->svga.uWidth
1333 && pThis->last_scr_height == (unsigned)pThis->svga.uHeight
1334 && pThis->last_width == (unsigned)pThis->svga.uWidth
1335 && pThis->last_height == (unsigned)pThis->svga.uHeight
1336 )
1337 /* Nothing to do. */
1338 break;
1339
1340#ifdef IN_RING3
1341 if ( u32 == 1
1342 && pThis->svga.fEnabled == false)
1343 {
1344 /* Make a backup copy of the first 32k in order to save font data etc. */
1345 memcpy(pThis->svga.pFrameBufferBackup, pThis->vram_ptrR3, VMSVGA_FRAMEBUFFER_BACKUP_SIZE);
1346 }
1347
1348 pThis->svga.fEnabled = u32;
1349 if (pThis->svga.fEnabled)
1350 {
1351 if ( pThis->svga.uWidth == VMSVGA_VAL_UNINITIALIZED
1352 && pThis->svga.uHeight == VMSVGA_VAL_UNINITIALIZED
1353 && pThis->svga.uBpp == VMSVGA_VAL_UNINITIALIZED)
1354 {
1355 /* Keep the current mode. */
1356 pThis->svga.uWidth = pThis->pDrv->cx;
1357 pThis->svga.uHeight = pThis->pDrv->cy;
1358 pThis->svga.uBpp = (pThis->pDrv->cBits + 7) & ~7;
1359 }
1360
1361 if ( pThis->svga.uWidth != VMSVGA_VAL_UNINITIALIZED
1362 && pThis->svga.uHeight != VMSVGA_VAL_UNINITIALIZED
1363 && pThis->svga.uBpp != VMSVGA_VAL_UNINITIALIZED)
1364 {
1365 rc = vmsvgaChangeMode(pThis);
1366 AssertRCReturn(rc, rc);
1367 }
1368# ifdef LOG_ENABLED
1369 Log(("configured=%d busy=%d\n", pThis->svga.fConfigured, pThis->svga.pFIFOR3[SVGA_FIFO_BUSY]));
1370 uint32_t *pFIFO = pThis->svga.pFIFOR3;
1371 Log(("next %x stop %x\n", pFIFO[SVGA_FIFO_NEXT_CMD], pFIFO[SVGA_FIFO_STOP]));
1372# endif
1373
1374 /* Disable or enable dirty page tracking according to the current fTraces value. */
1375 vmsvgaSetTraces(pThis, !!pThis->svga.fTraces);
1376 }
1377 else
1378 {
1379 /* Restore the text mode backup. */
1380 memcpy(pThis->vram_ptrR3, pThis->svga.pFrameBufferBackup, VMSVGA_FRAMEBUFFER_BACKUP_SIZE);
1381
1382/* pThis->svga.uHeight = -1;
1383 pThis->svga.uWidth = -1;
1384 pThis->svga.uBpp = -1;
1385 pThis->svga.cbScanline = 0; */
1386 pThis->pDrv->pfnLFBModeChange(pThis->pDrv, false);
1387
1388 /* Enable dirty page tracking again when going into legacy mode. */
1389 vmsvgaSetTraces(pThis, true);
1390 }
1391#else
1392 rc = VINF_IOM_R3_IOPORT_WRITE;
1393#endif
1394 break;
1395
1396 case SVGA_REG_WIDTH:
1397 STAM_REL_COUNTER_INC(&pThis->svga.StatRegWidthWr);
1398 if (pThis->svga.uWidth != u32)
1399 {
1400 if (pThis->svga.fEnabled)
1401 {
1402#ifdef IN_RING3
1403 pThis->svga.uWidth = u32;
1404 rc = vmsvgaChangeMode(pThis);
1405 AssertRCReturn(rc, rc);
1406#else
1407 rc = VINF_IOM_R3_IOPORT_WRITE;
1408#endif
1409 }
1410 else
1411 pThis->svga.uWidth = u32;
1412 }
1413 /* else: nop */
1414 break;
1415
1416 case SVGA_REG_HEIGHT:
1417 STAM_REL_COUNTER_INC(&pThis->svga.StatRegHeightWr);
1418 if (pThis->svga.uHeight != u32)
1419 {
1420 if (pThis->svga.fEnabled)
1421 {
1422#ifdef IN_RING3
1423 pThis->svga.uHeight = u32;
1424 rc = vmsvgaChangeMode(pThis);
1425 AssertRCReturn(rc, rc);
1426#else
1427 rc = VINF_IOM_R3_IOPORT_WRITE;
1428#endif
1429 }
1430 else
1431 pThis->svga.uHeight = u32;
1432 }
1433 /* else: nop */
1434 break;
1435
1436 case SVGA_REG_DEPTH:
1437 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDepthWr);
1438 /** @todo read-only?? */
1439 break;
1440
1441 case SVGA_REG_BITS_PER_PIXEL: /* Current bpp in the guest */
1442 STAM_REL_COUNTER_INC(&pThis->svga.StatRegBitsPerPixelWr);
1443 if (pThis->svga.uBpp != u32)
1444 {
1445 if (pThis->svga.fEnabled)
1446 {
1447#ifdef IN_RING3
1448 pThis->svga.uBpp = u32;
1449 rc = vmsvgaChangeMode(pThis);
1450 AssertRCReturn(rc, rc);
1451#else
1452 rc = VINF_IOM_R3_IOPORT_WRITE;
1453#endif
1454 }
1455 else
1456 pThis->svga.uBpp = u32;
1457 }
1458 /* else: nop */
1459 break;
1460
1461 case SVGA_REG_PSEUDOCOLOR:
1462 STAM_REL_COUNTER_INC(&pThis->svga.StatRegPseudoColorWr);
1463 break;
1464
1465 case SVGA_REG_CONFIG_DONE: /* Set when memory area configured */
1466#ifdef IN_RING3
1467 STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegConfigDoneWr);
1468 pThis->svga.fConfigured = u32;
1469 /* Disabling the FIFO enables tracing (dirty page detection) by default. */
1470 if (!pThis->svga.fConfigured)
1471 {
1472 pThis->svga.fTraces = true;
1473 }
1474 vmsvgaSetTraces(pThis, !!pThis->svga.fTraces);
1475#else
1476 rc = VINF_IOM_R3_IOPORT_WRITE;
1477#endif
1478 break;
1479
1480 case SVGA_REG_SYNC: /* See "FIFO Synchronization Registers" */
1481 STAM_REL_COUNTER_INC(&pThis->svga.StatRegSyncWr);
1482 if ( pThis->svga.fEnabled
1483 && pThis->svga.fConfigured)
1484 {
1485#if defined(IN_RING3) || defined(IN_RING0)
1486 Log(("SVGA_REG_SYNC: SVGA_FIFO_BUSY=%d\n", pThis->svga.CTX_SUFF(pFIFO)[SVGA_FIFO_BUSY]));
1487 ASMAtomicWriteU32(&pThis->svga.fBusy, VMSVGA_BUSY_F_EMT_FORCE | VMSVGA_BUSY_F_FIFO);
1488 if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_BUSY, pThis->svga.CTX_SUFF(pFIFO)[SVGA_FIFO_MIN]))
1489 vmsvgaSafeFifoBusyRegUpdate(pThis, true);
1490
1491 /* Kick the FIFO thread to start processing commands again. */
1492 SUPSemEventSignal(pThis->svga.pSupDrvSession, pThis->svga.FIFORequestSem);
1493#else
1494 rc = VINF_IOM_R3_IOPORT_WRITE;
1495#endif
1496 }
1497 /* else nothing to do. */
1498 else
1499 Log(("Sync ignored enabled=%d configured=%d\n", pThis->svga.fEnabled, pThis->svga.fConfigured));
1500
1501 break;
1502
1503 case SVGA_REG_BUSY: /* See "FIFO Synchronization Registers" (read-only) */
1504 STAM_REL_COUNTER_INC(&pThis->svga.StatRegBusyWr);
1505 break;
1506
1507 case SVGA_REG_GUEST_ID: /* Set guest OS identifier */
1508 STAM_REL_COUNTER_INC(&pThis->svga.StatRegGuestIdWr);
1509 pThis->svga.u32GuestId = u32;
1510 break;
1511
1512 case SVGA_REG_PITCHLOCK: /* Fixed pitch for all modes */
1513 STAM_REL_COUNTER_INC(&pThis->svga.StatRegPitchLockWr);
1514 pThis->svga.u32PitchLock = u32;
1515 break;
1516
1517 case SVGA_REG_IRQMASK: /* Interrupt mask */
1518 STAM_REL_COUNTER_INC(&pThis->svga.StatRegIrqMaskWr);
1519 pThis->svga.u32IrqMask = u32;
1520
1521 /* Irq pending after the above change? */
1522 if (pThis->svga.u32IrqStatus & u32)
1523 {
1524 Log(("SVGA_REG_IRQMASK: Trigger interrupt with status %x\n", pThis->svga.u32IrqStatus));
1525 PDMDevHlpPCISetIrqNoWait(pThis->CTX_SUFF(pDevIns), 0, 1);
1526 }
1527 else
1528 PDMDevHlpPCISetIrqNoWait(pThis->CTX_SUFF(pDevIns), 0, 0);
1529 break;
1530
1531 /* Mouse cursor support */
1532 case SVGA_REG_CURSOR_ID:
1533 case SVGA_REG_CURSOR_X:
1534 case SVGA_REG_CURSOR_Y:
1535 case SVGA_REG_CURSOR_ON:
1536 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorXxxxWr);
1537 break;
1538
1539 /* Legacy multi-monitor support */
1540 case SVGA_REG_NUM_GUEST_DISPLAYS:/* Number of guest displays in X/Y direction */
1541 STAM_REL_COUNTER_INC(&pThis->svga.StatRegNumGuestDisplaysWr);
1542 break;
1543 case SVGA_REG_DISPLAY_ID: /* Display ID for the following display attributes */
1544 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayIdWr);
1545 break;
1546 case SVGA_REG_DISPLAY_IS_PRIMARY:/* Whether this is a primary display */
1547 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayIsPrimaryWr);
1548 break;
1549 case SVGA_REG_DISPLAY_POSITION_X:/* The display position x */
1550 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayPositionXWr);
1551 break;
1552 case SVGA_REG_DISPLAY_POSITION_Y:/* The display position y */
1553 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayPositionYWr);
1554 break;
1555 case SVGA_REG_DISPLAY_WIDTH: /* The display's width */
1556 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayWidthWr);
1557 break;
1558 case SVGA_REG_DISPLAY_HEIGHT: /* The display's height */
1559 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayHeightWr);
1560 break;
1561#ifdef VBOX_WITH_VMSVGA3D
1562 /* See "Guest memory regions" below. */
1563 case SVGA_REG_GMR_ID:
1564 STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrIdWr);
1565 pThis->svga.u32CurrentGMRId = u32;
1566 break;
1567
1568 case SVGA_REG_GMR_DESCRIPTOR:
1569# ifndef IN_RING3
1570 rc = VINF_IOM_R3_IOPORT_WRITE;
1571 break;
1572# else /* IN_RING3 */
1573 {
1574 STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegGmrDescriptorWr);
1575
1576 /* Validate current GMR id. */
1577 uint32_t idGMR = pThis->svga.u32CurrentGMRId;
1578 AssertBreak(idGMR < VMSVGA_MAX_GMR_IDS);
1579
1580 /* Free the old GMR if present. */
1581 vmsvgaGMRFree(pThis, idGMR);
1582
1583 /* Just undefine the GMR? */
1584 RTGCPHYS GCPhys = (RTGCPHYS)u32 << PAGE_SHIFT;
1585 if (GCPhys == 0)
1586 {
1587 STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegGmrDescriptorWrFree);
1588 break;
1589 }
1590
1591
1592 /* Never cross a page boundary automatically. */
1593 const uint32_t cMaxPages = RT_MIN(VMSVGA_MAX_GMR_PAGES, UINT32_MAX / X86_PAGE_SIZE);
1594 uint32_t cPagesTotal = 0;
1595 uint32_t iDesc = 0;
1596 PVMSVGAGMRDESCRIPTOR paDescs = NULL;
1597 uint32_t cLoops = 0;
1598 RTGCPHYS GCPhysBase = GCPhys;
1599 while (PHYS_PAGE_ADDRESS(GCPhys) == PHYS_PAGE_ADDRESS(GCPhysBase))
1600 {
1601 /* Read descriptor. */
1602 SVGAGuestMemDescriptor desc;
1603 rc = PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), GCPhys, &desc, sizeof(desc));
1604 AssertRCBreak(rc);
1605
1606 if (desc.numPages != 0)
1607 {
1608 AssertBreakStmt(desc.numPages <= cMaxPages, rc = VERR_OUT_OF_RANGE);
1609 cPagesTotal += desc.numPages;
1610 AssertBreakStmt(cPagesTotal <= cMaxPages, rc = VERR_OUT_OF_RANGE);
1611
1612 if ((iDesc & 15) == 0)
1613 {
1614 void *pvNew = RTMemRealloc(paDescs, (iDesc + 16) * sizeof(VMSVGAGMRDESCRIPTOR));
1615 AssertBreakStmt(pvNew, rc = VERR_NO_MEMORY);
1616 paDescs = (PVMSVGAGMRDESCRIPTOR)pvNew;
1617 }
1618
1619 paDescs[iDesc].GCPhys = (RTGCPHYS)desc.ppn << PAGE_SHIFT;
1620 paDescs[iDesc++].numPages = desc.numPages;
1621
1622 /* Continue with the next descriptor. */
1623 GCPhys += sizeof(desc);
1624 }
1625 else if (desc.ppn == 0)
1626 break; /* terminator */
1627 else /* Pointer to the next physical page of descriptors. */
1628 GCPhys = GCPhysBase = (RTGCPHYS)desc.ppn << PAGE_SHIFT;
1629
1630 cLoops++;
1631 AssertBreakStmt(cLoops < VMSVGA_MAX_GMR_DESC_LOOP_COUNT, rc = VERR_OUT_OF_RANGE);
1632 }
1633
1634 AssertStmt(iDesc > 0 || RT_FAILURE_NP(rc), rc = VERR_OUT_OF_RANGE);
1635 if (RT_SUCCESS(rc))
1636 {
1637 /* Commit the GMR. */
1638 pSVGAState->aGMR[idGMR].paDesc = paDescs;
1639 pSVGAState->aGMR[idGMR].numDescriptors = iDesc;
1640 pSVGAState->aGMR[idGMR].cMaxPages = cPagesTotal;
1641 pSVGAState->aGMR[idGMR].cbTotal = cPagesTotal * PAGE_SIZE;
1642 Assert((pSVGAState->aGMR[idGMR].cbTotal >> PAGE_SHIFT) == cPagesTotal);
1643 Log(("Defined new gmr %x numDescriptors=%d cbTotal=%x (%#x pages)\n",
1644 idGMR, iDesc, pSVGAState->aGMR[idGMR].cbTotal, cPagesTotal));
1645 }
1646 else
1647 {
1648 RTMemFree(paDescs);
1649 STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegGmrDescriptorWrErrors);
1650 }
1651 break;
1652 }
1653# endif /* IN_RING3 */
1654#endif // VBOX_WITH_VMSVGA3D
1655
1656 case SVGA_REG_TRACES: /* Enable trace-based updates even when FIFO is on */
1657 STAM_REL_COUNTER_INC(&pThis->svga.StatRegTracesWr);
1658 if (pThis->svga.fTraces == u32)
1659 break; /* nothing to do */
1660
1661#ifdef IN_RING3
1662 vmsvgaSetTraces(pThis, !!u32);
1663#else
1664 rc = VINF_IOM_R3_IOPORT_WRITE;
1665#endif
1666 break;
1667
1668 case SVGA_REG_TOP: /* Must be 1 more than the last register */
1669 STAM_REL_COUNTER_INC(&pThis->svga.StatRegTopWr);
1670 break;
1671
1672 case SVGA_REG_NUM_DISPLAYS: /* (Deprecated) */
1673 STAM_REL_COUNTER_INC(&pThis->svga.StatRegNumDisplaysWr);
1674 Log(("Write to deprecated register %x - val %x ignored\n", idxReg, u32));
1675 break;
1676
1677 case SVGA_REG_FB_START:
1678 case SVGA_REG_MEM_START:
1679 case SVGA_REG_HOST_BITS_PER_PIXEL:
1680 case SVGA_REG_MAX_WIDTH:
1681 case SVGA_REG_MAX_HEIGHT:
1682 case SVGA_REG_VRAM_SIZE:
1683 case SVGA_REG_FB_SIZE:
1684 case SVGA_REG_CAPABILITIES:
1685 case SVGA_REG_MEM_SIZE:
1686 case SVGA_REG_SCRATCH_SIZE: /* Number of scratch registers */
1687 case SVGA_REG_MEM_REGS: /* Number of FIFO registers */
1688 case SVGA_REG_BYTES_PER_LINE:
1689 case SVGA_REG_FB_OFFSET:
1690 case SVGA_REG_RED_MASK:
1691 case SVGA_REG_GREEN_MASK:
1692 case SVGA_REG_BLUE_MASK:
1693 case SVGA_REG_GMRS_MAX_PAGES: /* Maximum number of 4KB pages for all GMRs */
1694 case SVGA_REG_MEMORY_SIZE: /* Total dedicated device memory excluding FIFO */
1695 case SVGA_REG_GMR_MAX_IDS:
1696 case SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH:
1697 /* Read only - ignore. */
1698 Log(("Write to R/O register %x - val %x ignored\n", idxReg, u32));
1699 STAM_REL_COUNTER_INC(&pThis->svga.StatRegReadOnlyWr);
1700 break;
1701
1702 default:
1703 {
1704 uint32_t offReg;
1705 if ((offReg = idxReg - SVGA_SCRATCH_BASE) < pThis->svga.cScratchRegion)
1706 {
1707 pThis->svga.au32ScratchRegion[offReg] = u32;
1708 STAM_REL_COUNTER_INC(&pThis->svga.StatRegScratchWr);
1709 }
1710 else if ((offReg = idxReg - SVGA_PALETTE_BASE) < (uint32_t)SVGA_NUM_PALETTE_REGS)
1711 {
1712 STAM_REL_COUNTER_INC(&pThis->svga.StatRegPaletteWr);
1713 /* Next 768 (== 256*3) registers exist for colormap */
1714 }
1715 else
1716 {
1717#if !defined(IN_RING3) && defined(VBOX_STRICT)
1718 rc = VINF_IOM_R3_IOPORT_WRITE;
1719#else
1720 STAM_REL_COUNTER_INC(&pThis->svga.StatRegUnknownWr);
1721 AssertMsgFailed(("reg=%#x u32=%#x\n", idxReg, u32));
1722#endif
1723 }
1724 break;
1725 }
1726 }
1727 return rc;
1728}
1729
1730/**
1731 * Port I/O Handler for IN operations.
1732 *
1733 * @returns VINF_SUCCESS or VINF_EM_*.
1734 * @returns VERR_IOM_IOPORT_UNUSED if the port is really unused and a ~0 value should be returned.
1735 *
1736 * @param pDevIns The device instance.
1737 * @param pvUser User argument.
1738 * @param uPort Port number used for the IN operation.
1739 * @param pu32 Where to store the result. This is always a 32-bit
1740 * variable regardless of what @a cb might say.
1741 * @param cb Number of bytes read.
1742 */
1743PDMBOTHCBDECL(int) vmsvgaIORead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t *pu32, unsigned cb)
1744{
1745 PVGASTATE pThis = PDMINS_2_DATA(pDevIns, PVGASTATE);
1746 RT_NOREF_PV(pvUser);
1747
1748 /* Ignore non-dword accesses. */
1749 if (cb != 4)
1750 {
1751 Log(("Ignoring non-dword read at %x cb=%d\n", uPort, cb));
1752 *pu32 = UINT32_MAX;
1753 return VINF_SUCCESS;
1754 }
1755
1756 switch (uPort - pThis->svga.BasePort)
1757 {
1758 case SVGA_INDEX_PORT:
1759 *pu32 = pThis->svga.u32IndexReg;
1760 break;
1761
1762 case SVGA_VALUE_PORT:
1763 return vmsvgaReadPort(pThis, pu32);
1764
1765 case SVGA_BIOS_PORT:
1766 Log(("Ignoring BIOS port read\n"));
1767 *pu32 = 0;
1768 break;
1769
1770 case SVGA_IRQSTATUS_PORT:
1771 LogFlow(("vmsvgaIORead: SVGA_IRQSTATUS_PORT %x\n", pThis->svga.u32IrqStatus));
1772 *pu32 = pThis->svga.u32IrqStatus;
1773 break;
1774 }
1775
1776 return VINF_SUCCESS;
1777}
1778
1779/**
1780 * Port I/O Handler for OUT operations.
1781 *
1782 * @returns VINF_SUCCESS or VINF_EM_*.
1783 *
1784 * @param pDevIns The device instance.
1785 * @param pvUser User argument.
1786 * @param uPort Port number used for the OUT operation.
1787 * @param u32 The value to output.
1788 * @param cb The value size in bytes.
1789 */
1790PDMBOTHCBDECL(int) vmsvgaIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t u32, unsigned cb)
1791{
1792 PVGASTATE pThis = PDMINS_2_DATA(pDevIns, PVGASTATE);
1793 RT_NOREF_PV(pvUser);
1794
1795 /* Ignore non-dword accesses. */
1796 if (cb != 4)
1797 {
1798 Log(("Ignoring non-dword write at %x val=%x cb=%d\n", uPort, u32, cb));
1799 return VINF_SUCCESS;
1800 }
1801
1802 switch (uPort - pThis->svga.BasePort)
1803 {
1804 case SVGA_INDEX_PORT:
1805 pThis->svga.u32IndexReg = u32;
1806 break;
1807
1808 case SVGA_VALUE_PORT:
1809 return vmsvgaWritePort(pThis, u32);
1810
1811 case SVGA_BIOS_PORT:
1812 Log(("Ignoring BIOS port write (val=%x)\n", u32));
1813 break;
1814
1815 case SVGA_IRQSTATUS_PORT:
1816 Log(("vmsvgaIOWrite SVGA_IRQSTATUS_PORT %x: status %x -> %x\n", u32, pThis->svga.u32IrqStatus, pThis->svga.u32IrqStatus & ~u32));
1817 ASMAtomicAndU32(&pThis->svga.u32IrqStatus, ~u32);
1818 /* Clear the irq in case all events have been cleared. */
1819 if (!(pThis->svga.u32IrqStatus & pThis->svga.u32IrqMask))
1820 {
1821 Log(("vmsvgaIOWrite SVGA_IRQSTATUS_PORT: clearing IRQ\n"));
1822 PDMDevHlpPCISetIrqNoWait(pDevIns, 0, 0);
1823 }
1824 break;
1825 }
1826 return VINF_SUCCESS;
1827}
1828
1829#ifdef DEBUG_FIFO_ACCESS
1830
1831# ifdef IN_RING3
1832/**
1833 * Handle LFB access.
1834 * @returns VBox status code.
1835 * @param pVM VM handle.
1836 * @param pThis VGA device instance data.
1837 * @param GCPhys The access physical address.
1838 * @param fWriteAccess Read or write access
1839 */
1840static int vmsvgaFIFOAccess(PVM pVM, PVGASTATE pThis, RTGCPHYS GCPhys, bool fWriteAccess)
1841{
1842 RT_NOREF(pVM);
1843 RTGCPHYS GCPhysOffset = GCPhys - pThis->svga.GCPhysFIFO;
1844 uint32_t *pFIFO = pThis->svga.pFIFOR3;
1845
1846 switch (GCPhysOffset >> 2)
1847 {
1848 case SVGA_FIFO_MIN:
1849 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_MIN = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1850 break;
1851 case SVGA_FIFO_MAX:
1852 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_MAX = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1853 break;
1854 case SVGA_FIFO_NEXT_CMD:
1855 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_NEXT_CMD = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1856 break;
1857 case SVGA_FIFO_STOP:
1858 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_STOP = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1859 break;
1860 case SVGA_FIFO_CAPABILITIES:
1861 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CAPABILITIES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1862 break;
1863 case SVGA_FIFO_FLAGS:
1864 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_FLAGS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1865 break;
1866 case SVGA_FIFO_FENCE:
1867 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_FENCE = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1868 break;
1869 case SVGA_FIFO_3D_HWVERSION:
1870 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_HWVERSION = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1871 break;
1872 case SVGA_FIFO_PITCHLOCK:
1873 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_PITCHLOCK = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1874 break;
1875 case SVGA_FIFO_CURSOR_ON:
1876 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_ON = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1877 break;
1878 case SVGA_FIFO_CURSOR_X:
1879 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_X = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1880 break;
1881 case SVGA_FIFO_CURSOR_Y:
1882 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_Y = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1883 break;
1884 case SVGA_FIFO_CURSOR_COUNT:
1885 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_COUNT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1886 break;
1887 case SVGA_FIFO_CURSOR_LAST_UPDATED:
1888 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_LAST_UPDATED = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1889 break;
1890 case SVGA_FIFO_RESERVED:
1891 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_RESERVED = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1892 break;
1893 case SVGA_FIFO_CURSOR_SCREEN_ID:
1894 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_SCREEN_ID = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1895 break;
1896 case SVGA_FIFO_DEAD:
1897 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_DEAD = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1898 break;
1899 case SVGA_FIFO_3D_HWVERSION_REVISED:
1900 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_HWVERSION_REVISED = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1901 break;
1902 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_3D:
1903 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_3D = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1904 break;
1905 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_LIGHTS:
1906 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_LIGHTS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1907 break;
1908 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURES:
1909 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1910 break;
1911 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_CLIP_PLANES:
1912 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_CLIP_PLANES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1913 break;
1914 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_VERTEX_SHADER_VERSION:
1915 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_VERTEX_SHADER_VERSION = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1916 break;
1917 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_VERTEX_SHADER:
1918 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_VERTEX_SHADER = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1919 break;
1920 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_FRAGMENT_SHADER_VERSION:
1921 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_FRAGMENT_SHADER_VERSION = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1922 break;
1923 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_FRAGMENT_SHADER:
1924 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_FRAGMENT_SHADER = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1925 break;
1926 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_RENDER_TARGETS:
1927 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_RENDER_TARGETS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1928 break;
1929 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_S23E8_TEXTURES:
1930 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_S23E8_TEXTURES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1931 break;
1932 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_S10E5_TEXTURES:
1933 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_S10E5_TEXTURES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1934 break;
1935 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_FIXED_VERTEXBLEND:
1936 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_FIXED_VERTEXBLEND = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1937 break;
1938 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_D16_BUFFER_FORMAT:
1939 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_D16_BUFFER_FORMAT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1940 break;
1941 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_D24S8_BUFFER_FORMAT:
1942 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_D24S8_BUFFER_FORMAT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1943 break;
1944 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_D24X8_BUFFER_FORMAT:
1945 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_D24X8_BUFFER_FORMAT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1946 break;
1947 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_QUERY_TYPES:
1948 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_QUERY_TYPES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1949 break;
1950 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_TEXTURE_GRADIENT_SAMPLING:
1951 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_TEXTURE_GRADIENT_SAMPLING = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1952 break;
1953 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_POINT_SIZE:
1954 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_POINT_SIZE = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1955 break;
1956 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_SHADER_TEXTURES:
1957 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_SHADER_TEXTURES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1958 break;
1959 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURE_WIDTH:
1960 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURE_WIDTH = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1961 break;
1962 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURE_HEIGHT:
1963 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURE_HEIGHT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1964 break;
1965 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_VOLUME_EXTENT:
1966 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_VOLUME_EXTENT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1967 break;
1968 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURE_REPEAT:
1969 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURE_REPEAT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1970 break;
1971 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURE_ASPECT_RATIO:
1972 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]));
1973 break;
1974 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURE_ANISOTROPY:
1975 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURE_ANISOTROPY = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1976 break;
1977 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_PRIMITIVE_COUNT:
1978 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_PRIMITIVE_COUNT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1979 break;
1980 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_VERTEX_INDEX:
1981 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_VERTEX_INDEX = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1982 break;
1983 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_VERTEX_SHADER_INSTRUCTIONS:
1984 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]));
1985 break;
1986 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_INSTRUCTIONS:
1987 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]));
1988 break;
1989 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEMPS:
1990 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]));
1991 break;
1992 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_TEMPS:
1993 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]));
1994 break;
1995 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_TEXTURE_OPS:
1996 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_TEXTURE_OPS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1997 break;
1998 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8:
1999 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2000 break;
2001 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8:
2002 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2003 break;
2004 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10:
2005 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2006 break;
2007 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5:
2008 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2009 break;
2010 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5:
2011 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2012 break;
2013 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4:
2014 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2015 break;
2016 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_R5G6B5:
2017 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_R5G6B5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2018 break;
2019 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE16:
2020 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2021 break;
2022 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8:
2023 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2024 break;
2025 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_ALPHA8:
2026 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_ALPHA8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2027 break;
2028 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8:
2029 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2030 break;
2031 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_D16:
2032 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_D16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2033 break;
2034 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8:
2035 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2036 break;
2037 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8:
2038 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2039 break;
2040 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_DXT1:
2041 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_DXT1 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2042 break;
2043 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_DXT2:
2044 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_DXT2 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2045 break;
2046 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_DXT3:
2047 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_DXT3 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2048 break;
2049 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_DXT4:
2050 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_DXT4 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2051 break;
2052 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_DXT5:
2053 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_DXT5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2054 break;
2055 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_BUMPX8L8V8U8:
2056 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_BUMPX8L8V8U8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2057 break;
2058 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A2W10V10U10:
2059 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A2W10V10U10 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2060 break;
2061 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_BUMPU8V8:
2062 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_BUMPU8V8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2063 break;
2064 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Q8W8V8U8:
2065 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Q8W8V8U8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2066 break;
2067 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_CxV8U8:
2068 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_CxV8U8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2069 break;
2070 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_R_S10E5:
2071 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_R_S10E5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2072 break;
2073 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_R_S23E8:
2074 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_R_S23E8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2075 break;
2076 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_RG_S10E5:
2077 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_RG_S10E5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2078 break;
2079 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_RG_S23E8:
2080 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_RG_S23E8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2081 break;
2082 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_ARGB_S10E5:
2083 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_ARGB_S10E5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2084 break;
2085 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_ARGB_S23E8:
2086 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_ARGB_S23E8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2087 break;
2088 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEXTURES:
2089 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]));
2090 break;
2091 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_SIMULTANEOUS_RENDER_TARGETS:
2092 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]));
2093 break;
2094 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_V16U16:
2095 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_V16U16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2096 break;
2097 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_G16R16:
2098 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_G16R16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2099 break;
2100 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16:
2101 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2102 break;
2103 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_UYVY:
2104 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_UYVY = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2105 break;
2106 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_YUY2:
2107 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_YUY2 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2108 break;
2109 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MULTISAMPLE_NONMASKABLESAMPLES:
2110 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MULTISAMPLE_NONMASKABLESAMPLES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2111 break;
2112 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MULTISAMPLE_MASKABLESAMPLES:
2113 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MULTISAMPLE_MASKABLESAMPLES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2114 break;
2115 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_ALPHATOCOVERAGE:
2116 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_ALPHATOCOVERAGE = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2117 break;
2118 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SUPERSAMPLE:
2119 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SUPERSAMPLE = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2120 break;
2121 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_AUTOGENMIPMAPS:
2122 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_AUTOGENMIPMAPS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2123 break;
2124 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_NV12:
2125 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_NV12 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2126 break;
2127 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_AYUV:
2128 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_AYUV = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2129 break;
2130 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_CONTEXT_IDS:
2131 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_CONTEXT_IDS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2132 break;
2133 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_SURFACE_IDS:
2134 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_SURFACE_IDS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2135 break;
2136 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_DF16:
2137 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_DF16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2138 break;
2139 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_DF24:
2140 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_DF24 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2141 break;
2142 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8_INT:
2143 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]));
2144 break;
2145 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_BC4_UNORM:
2146 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_BC4_UNORM = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2147 break;
2148 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_BC5_UNORM:
2149 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_BC5_UNORM = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2150 break;
2151 case SVGA_FIFO_3D_CAPS_LAST:
2152 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS_LAST = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2153 break;
2154 case SVGA_FIFO_GUEST_3D_HWVERSION:
2155 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_GUEST_3D_HWVERSION = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2156 break;
2157 case SVGA_FIFO_FENCE_GOAL:
2158 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_FENCE_GOAL = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2159 break;
2160 case SVGA_FIFO_BUSY:
2161 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_BUSY = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2162 break;
2163 default:
2164 Log(("vmsvgaFIFOAccess [0x%x]: %s access at offset %x = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", GCPhysOffset, pFIFO[GCPhysOffset >> 2]));
2165 break;
2166 }
2167
2168 return VINF_EM_RAW_EMULATE_INSTR;
2169}
2170
2171/**
2172 * HC access handler for the FIFO.
2173 *
2174 * @returns VINF_SUCCESS if the handler have carried out the operation.
2175 * @returns VINF_PGM_HANDLER_DO_DEFAULT if the caller should carry out the access operation.
2176 * @param pVM VM Handle.
2177 * @param pVCpu The cross context CPU structure for the calling EMT.
2178 * @param GCPhys The physical address the guest is writing to.
2179 * @param pvPhys The HC mapping of that address.
2180 * @param pvBuf What the guest is reading/writing.
2181 * @param cbBuf How much it's reading/writing.
2182 * @param enmAccessType The access type.
2183 * @param enmOrigin Who is making the access.
2184 * @param pvUser User argument.
2185 */
2186static DECLCALLBACK(VBOXSTRICTRC)
2187vmsvgaR3FIFOAccessHandler(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf,
2188 PGMACCESSTYPE enmAccessType, PGMACCESSORIGIN enmOrigin, void *pvUser)
2189{
2190 PVGASTATE pThis = (PVGASTATE)pvUser;
2191 int rc;
2192 Assert(pThis);
2193 Assert(GCPhys >= pThis->svga.GCPhysFIFO);
2194 NOREF(pVCpu); NOREF(pvPhys); NOREF(pvBuf); NOREF(cbBuf); NOREF(enmOrigin);
2195
2196 rc = vmsvgaFIFOAccess(pVM, pThis, GCPhys, enmAccessType == PGMACCESSTYPE_WRITE);
2197 if (RT_SUCCESS(rc))
2198 return VINF_PGM_HANDLER_DO_DEFAULT;
2199 AssertMsg(rc <= VINF_SUCCESS, ("rc=%Rrc\n", rc));
2200 return rc;
2201}
2202
2203# endif /* IN_RING3 */
2204#endif /* DEBUG_FIFO_ACCESS */
2205
2206#ifdef DEBUG_GMR_ACCESS
2207# ifdef IN_RING3
2208
2209/**
2210 * HC access handler for the FIFO.
2211 *
2212 * @returns VINF_SUCCESS if the handler have carried out the operation.
2213 * @returns VINF_PGM_HANDLER_DO_DEFAULT if the caller should carry out the access operation.
2214 * @param pVM VM Handle.
2215 * @param pVCpu The cross context CPU structure for the calling EMT.
2216 * @param GCPhys The physical address the guest is writing to.
2217 * @param pvPhys The HC mapping of that address.
2218 * @param pvBuf What the guest is reading/writing.
2219 * @param cbBuf How much it's reading/writing.
2220 * @param enmAccessType The access type.
2221 * @param enmOrigin Who is making the access.
2222 * @param pvUser User argument.
2223 */
2224static DECLCALLBACK(VBOXSTRICTRC)
2225vmsvgaR3GMRAccessHandler(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf,
2226 PGMACCESSTYPE enmAccessType, PGMACCESSORIGIN enmOrigin, void *pvUser)
2227{
2228 PVGASTATE pThis = (PVGASTATE)pvUser;
2229 Assert(pThis);
2230 PVMSVGAR3STATE pSVGAState = pThis->svga.pSvgaR3State;
2231 NOREF(pVCpu); NOREF(pvPhys); NOREF(pvBuf); NOREF(cbBuf); NOREF(enmAccessType); NOREF(enmOrigin);
2232
2233 Log(("vmsvgaR3GMRAccessHandler: GMR access to page %RGp\n", GCPhys));
2234
2235 for (uint32_t i = 0; i < RT_ELEMENTS(pSVGAState->aGMR); i++)
2236 {
2237 PGMR pGMR = &pSVGAState->aGMR[i];
2238
2239 if (pGMR->numDescriptors)
2240 {
2241 for (uint32_t j = 0; j < pGMR->numDescriptors; j++)
2242 {
2243 if ( GCPhys >= pGMR->paDesc[j].GCPhys
2244 && GCPhys < pGMR->paDesc[j].GCPhys + pGMR->paDesc[j].numPages * PAGE_SIZE)
2245 {
2246 /*
2247 * Turn off the write handler for this particular page and make it R/W.
2248 * Then return telling the caller to restart the guest instruction.
2249 */
2250 int rc = PGMHandlerPhysicalPageTempOff(pVM, pGMR->paDesc[j].GCPhys, GCPhys);
2251 AssertRC(rc);
2252 goto end;
2253 }
2254 }
2255 }
2256 }
2257end:
2258 return VINF_PGM_HANDLER_DO_DEFAULT;
2259}
2260
2261/* Callback handler for VMR3ReqCallWaitU */
2262static DECLCALLBACK(int) vmsvgaRegisterGMR(PPDMDEVINS pDevIns, uint32_t gmrId)
2263{
2264 PVGASTATE pThis = PDMINS_2_DATA(pDevIns, PVGASTATE);
2265 PVMSVGAR3STATE pSVGAState = pThis->svga.pSvgaR3State;
2266 PGMR pGMR = &pSVGAState->aGMR[gmrId];
2267 int rc;
2268
2269 for (uint32_t i = 0; i < pGMR->numDescriptors; i++)
2270 {
2271 rc = PGMHandlerPhysicalRegister(PDMDevHlpGetVM(pThis->pDevInsR3),
2272 pGMR->paDesc[i].GCPhys, pGMR->paDesc[i].GCPhys + pGMR->paDesc[i].numPages * PAGE_SIZE - 1,
2273 pThis->svga.hGmrAccessHandlerType, pThis, NIL_RTR0PTR, NIL_RTRCPTR, "VMSVGA GMR");
2274 AssertRC(rc);
2275 }
2276 return VINF_SUCCESS;
2277}
2278
2279/* Callback handler for VMR3ReqCallWaitU */
2280static DECLCALLBACK(int) vmsvgaDeregisterGMR(PPDMDEVINS pDevIns, uint32_t gmrId)
2281{
2282 PVGASTATE pThis = PDMINS_2_DATA(pDevIns, PVGASTATE);
2283 PVMSVGAR3STATE pSVGAState = pThis->svga.pSvgaR3State;
2284 PGMR pGMR = &pSVGAState->aGMR[gmrId];
2285
2286 for (uint32_t i = 0; i < pGMR->numDescriptors; i++)
2287 {
2288 int rc = PGMHandlerPhysicalDeregister(PDMDevHlpGetVM(pThis->pDevInsR3), pGMR->paDesc[i].GCPhys);
2289 AssertRC(rc);
2290 }
2291 return VINF_SUCCESS;
2292}
2293
2294/* Callback handler for VMR3ReqCallWaitU */
2295static DECLCALLBACK(int) vmsvgaResetGMRHandlers(PVGASTATE pThis)
2296{
2297 PVMSVGAR3STATE pSVGAState = pThis->svga.pSvgaR3State;
2298
2299 for (uint32_t i = 0; i < RT_ELEMENTS(pSVGAState->aGMR); i++)
2300 {
2301 PGMR pGMR = &pSVGAState->aGMR[i];
2302
2303 if (pGMR->numDescriptors)
2304 {
2305 for (uint32_t j = 0; j < pGMR->numDescriptors; j++)
2306 {
2307 int rc = PGMHandlerPhysicalReset(PDMDevHlpGetVM(pThis->pDevInsR3), pGMR->paDesc[j].GCPhys);
2308 AssertRC(rc);
2309 }
2310 }
2311 }
2312 return VINF_SUCCESS;
2313}
2314
2315# endif /* IN_RING3 */
2316#endif /* DEBUG_GMR_ACCESS */
2317
2318/* -=-=-=-=-=- Ring 3 -=-=-=-=-=- */
2319
2320#ifdef IN_RING3
2321
2322/**
2323 * Worker for vmsvgaR3FifoThread that handles an external command.
2324 *
2325 * @param pThis VGA device instance data.
2326 */
2327static void vmsvgaR3FifoHandleExtCmd(PVGASTATE pThis)
2328{
2329 uint8_t uExtCmd = pThis->svga.u8FIFOExtCommand;
2330 switch (pThis->svga.u8FIFOExtCommand)
2331 {
2332 case VMSVGA_FIFO_EXTCMD_RESET:
2333 Log(("vmsvgaFIFOLoop: reset the fifo thread.\n"));
2334 Assert(pThis->svga.pvFIFOExtCmdParam == NULL);
2335# ifdef VBOX_WITH_VMSVGA3D
2336 if (pThis->svga.f3DEnabled)
2337 {
2338 /* The 3d subsystem must be reset from the fifo thread. */
2339 vmsvga3dReset(pThis);
2340 }
2341# endif
2342 break;
2343
2344 case VMSVGA_FIFO_EXTCMD_TERMINATE:
2345 Log(("vmsvgaFIFOLoop: terminate the fifo thread.\n"));
2346 Assert(pThis->svga.pvFIFOExtCmdParam == NULL);
2347# ifdef VBOX_WITH_VMSVGA3D
2348 if (pThis->svga.f3DEnabled)
2349 {
2350 /* The 3d subsystem must be shut down from the fifo thread. */
2351 vmsvga3dTerminate(pThis);
2352 }
2353# endif
2354 break;
2355
2356 case VMSVGA_FIFO_EXTCMD_SAVESTATE:
2357 {
2358 Log(("vmsvgaFIFOLoop: VMSVGA_FIFO_EXTCMD_SAVESTATE.\n"));
2359# ifdef VBOX_WITH_VMSVGA3D
2360 PSSMHANDLE pSSM = (PSSMHANDLE)pThis->svga.pvFIFOExtCmdParam;
2361 AssertLogRelMsgBreak(RT_VALID_PTR(pSSM), ("pSSM=%p\n", pSSM));
2362 vmsvga3dSaveExec(pThis, pSSM);
2363# endif
2364 break;
2365 }
2366
2367 case VMSVGA_FIFO_EXTCMD_LOADSTATE:
2368 {
2369 Log(("vmsvgaFIFOLoop: VMSVGA_FIFO_EXTCMD_LOADSTATE.\n"));
2370# ifdef VBOX_WITH_VMSVGA3D
2371 PVMSVGA_STATE_LOAD pLoadState = (PVMSVGA_STATE_LOAD)pThis->svga.pvFIFOExtCmdParam;
2372 AssertLogRelMsgBreak(RT_VALID_PTR(pLoadState), ("pLoadState=%p\n", pLoadState));
2373 vmsvga3dLoadExec(pThis, pLoadState->pSSM, pLoadState->uVersion, pLoadState->uPass);
2374# endif
2375 break;
2376 }
2377
2378 case VMSVGA_FIFO_EXTCMD_UPDATE_SURFACE_HEAP_BUFFERS:
2379 {
2380# ifdef VBOX_WITH_VMSVGA3D
2381 uint32_t sid = (uint32_t)(uintptr_t)pThis->svga.pvFIFOExtCmdParam;
2382 Log(("vmsvgaFIFOLoop: VMSVGA_FIFO_EXTCMD_UPDATE_SURFACE_HEAP_BUFFERS sid=%#x\n", sid));
2383 vmsvga3dUpdateHeapBuffersForSurfaces(pThis, sid);
2384# endif
2385 break;
2386 }
2387
2388
2389 default:
2390 AssertLogRelMsgFailed(("uExtCmd=%#x pvFIFOExtCmdParam=%p\n", uExtCmd, pThis->svga.pvFIFOExtCmdParam));
2391 break;
2392 }
2393
2394 /*
2395 * Signal the end of the external command.
2396 */
2397 pThis->svga.pvFIFOExtCmdParam = NULL;
2398 pThis->svga.u8FIFOExtCommand = VMSVGA_FIFO_EXTCMD_NONE;
2399 ASMMemoryFence(); /* paranoia^2 */
2400 int rc = RTSemEventSignal(pThis->svga.FIFOExtCmdSem);
2401 AssertLogRelRC(rc);
2402}
2403
2404/**
2405 * Worker for vmsvgaR3Destruct, vmsvgaR3Reset, vmsvgaR3Save and vmsvgaR3Load for
2406 * doing a job on the FIFO thread (even when it's officially suspended).
2407 *
2408 * @returns VBox status code (fully asserted).
2409 * @param pThis VGA device instance data.
2410 * @param uExtCmd The command to execute on the FIFO thread.
2411 * @param pvParam Pointer to command parameters.
2412 * @param cMsWait The time to wait for the command, given in
2413 * milliseconds.
2414 */
2415static int vmsvgaR3RunExtCmdOnFifoThread(PVGASTATE pThis, uint8_t uExtCmd, void *pvParam, RTMSINTERVAL cMsWait)
2416{
2417 Assert(cMsWait >= RT_MS_1SEC * 5);
2418 AssertLogRelMsg(pThis->svga.u8FIFOExtCommand == VMSVGA_FIFO_EXTCMD_NONE,
2419 ("old=%d new=%d\n", pThis->svga.u8FIFOExtCommand, uExtCmd));
2420
2421 int rc;
2422 PPDMTHREAD pThread = pThis->svga.pFIFOIOThread;
2423 PDMTHREADSTATE enmState = pThread->enmState;
2424 if (enmState == PDMTHREADSTATE_SUSPENDED)
2425 {
2426 /*
2427 * The thread is suspended, we have to temporarily wake it up so it can
2428 * perform the task.
2429 * (We ASSUME not racing code here, both wrt thread state and ext commands.)
2430 */
2431 Log(("vmsvgaR3RunExtCmdOnFifoThread: uExtCmd=%d enmState=SUSPENDED\n", uExtCmd));
2432 /* Post the request. */
2433 pThis->svga.fFifoExtCommandWakeup = true;
2434 pThis->svga.pvFIFOExtCmdParam = pvParam;
2435 pThis->svga.u8FIFOExtCommand = uExtCmd;
2436 ASMMemoryFence(); /* paranoia^3 */
2437
2438 /* Resume the thread. */
2439 rc = PDMR3ThreadResume(pThread);
2440 AssertLogRelRC(rc);
2441 if (RT_SUCCESS(rc))
2442 {
2443 /* Wait. Take care in case the semaphore was already posted (same as below). */
2444 rc = RTSemEventWait(pThis->svga.FIFOExtCmdSem, cMsWait);
2445 if ( rc == VINF_SUCCESS
2446 && pThis->svga.u8FIFOExtCommand == uExtCmd)
2447 rc = RTSemEventWait(pThis->svga.FIFOExtCmdSem, cMsWait);
2448 AssertLogRelMsg(pThis->svga.u8FIFOExtCommand != uExtCmd || RT_FAILURE_NP(rc),
2449 ("%#x %Rrc\n", pThis->svga.u8FIFOExtCommand, rc));
2450
2451 /* suspend the thread */
2452 pThis->svga.fFifoExtCommandWakeup = false;
2453 int rc2 = PDMR3ThreadSuspend(pThread);
2454 AssertLogRelRC(rc2);
2455 if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
2456 rc = rc2;
2457 }
2458 pThis->svga.fFifoExtCommandWakeup = false;
2459 pThis->svga.pvFIFOExtCmdParam = NULL;
2460 }
2461 else if (enmState == PDMTHREADSTATE_RUNNING)
2462 {
2463 /*
2464 * The thread is running, should only happen during reset and vmsvga3dsfc.
2465 * We ASSUME not racing code here, both wrt thread state and ext commands.
2466 */
2467 Log(("vmsvgaR3RunExtCmdOnFifoThread: uExtCmd=%d enmState=RUNNING\n", uExtCmd));
2468 Assert(uExtCmd == VMSVGA_FIFO_EXTCMD_RESET || uExtCmd == VMSVGA_FIFO_EXTCMD_UPDATE_SURFACE_HEAP_BUFFERS);
2469
2470 /* Post the request. */
2471 pThis->svga.pvFIFOExtCmdParam = pvParam;
2472 pThis->svga.u8FIFOExtCommand = uExtCmd;
2473 ASMMemoryFence(); /* paranoia^2 */
2474 rc = SUPSemEventSignal(pThis->svga.pSupDrvSession, pThis->svga.FIFORequestSem);
2475 AssertLogRelRC(rc);
2476
2477 /* Wait. Take care in case the semaphore was already posted (same as above). */
2478 rc = RTSemEventWait(pThis->svga.FIFOExtCmdSem, cMsWait);
2479 if ( rc == VINF_SUCCESS
2480 && pThis->svga.u8FIFOExtCommand == uExtCmd)
2481 rc = RTSemEventWait(pThis->svga.FIFOExtCmdSem, cMsWait); /* it was already posted, retry the wait. */
2482 AssertLogRelMsg(pThis->svga.u8FIFOExtCommand != uExtCmd || RT_FAILURE_NP(rc),
2483 ("%#x %Rrc\n", pThis->svga.u8FIFOExtCommand, rc));
2484
2485 pThis->svga.pvFIFOExtCmdParam = NULL;
2486 }
2487 else
2488 {
2489 /*
2490 * Something is wrong with the thread!
2491 */
2492 AssertLogRelMsgFailed(("uExtCmd=%d enmState=%d\n", uExtCmd, enmState));
2493 rc = VERR_INVALID_STATE;
2494 }
2495 return rc;
2496}
2497
2498
2499/**
2500 * Marks the FIFO non-busy, notifying any waiting EMTs.
2501 *
2502 * @param pThis The VGA state.
2503 * @param pSVGAState Pointer to the ring-3 only SVGA state data.
2504 * @param offFifoMin The start byte offset of the command FIFO.
2505 */
2506static void vmsvgaFifoSetNotBusy(PVGASTATE pThis, PVMSVGAR3STATE pSVGAState, uint32_t offFifoMin)
2507{
2508 ASMAtomicAndU32(&pThis->svga.fBusy, ~VMSVGA_BUSY_F_FIFO);
2509 if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_BUSY, offFifoMin))
2510 vmsvgaSafeFifoBusyRegUpdate(pThis, pThis->svga.fBusy != 0);
2511
2512 /* Wake up any waiting EMTs. */
2513 if (pSVGAState->cBusyDelayedEmts > 0)
2514 {
2515#ifdef VMSVGA_USE_EMT_HALT_CODE
2516 PVM pVM = PDMDevHlpGetVM(pThis->pDevInsR3);
2517 VMCPUID idCpu = VMCpuSetFindLastPresentInternal(&pSVGAState->BusyDelayedEmts);
2518 if (idCpu != NIL_VMCPUID)
2519 {
2520 VMR3NotifyCpuDeviceReady(pVM, idCpu);
2521 while (idCpu-- > 0)
2522 if (VMCPUSET_IS_PRESENT(&pSVGAState->BusyDelayedEmts, idCpu))
2523 VMR3NotifyCpuDeviceReady(pVM, idCpu);
2524 }
2525#else
2526 int rc2 = RTSemEventMultiSignal(pSVGAState->hBusyDelayedEmts);
2527 AssertRC(rc2);
2528#endif
2529 }
2530}
2531
2532/**
2533 * Reads (more) payload into the command buffer.
2534 *
2535 * @returns pbBounceBuf on success
2536 * @retval (void *)1 if the thread was requested to stop.
2537 * @retval NULL on FIFO error.
2538 *
2539 * @param cbPayloadReq The number of bytes of payload requested.
2540 * @param pFIFO The FIFO.
2541 * @param offCurrentCmd The FIFO byte offset of the current command.
2542 * @param offFifoMin The start byte offset of the command FIFO.
2543 * @param offFifoMax The end byte offset of the command FIFO.
2544 * @param pbBounceBuf The bounch buffer. Same size as the entire FIFO, so
2545 * always sufficient size.
2546 * @param pcbAlreadyRead How much payload we've already read into the bounce
2547 * buffer. (We will NEVER re-read anything.)
2548 * @param pThread The calling PDM thread handle.
2549 * @param pThis The VGA state.
2550 * @param pSVGAState Pointer to the ring-3 only SVGA state data. For
2551 * statistics collection.
2552 */
2553static void *vmsvgaFIFOGetCmdPayload(uint32_t cbPayloadReq, uint32_t volatile *pFIFO,
2554 uint32_t offCurrentCmd, uint32_t offFifoMin, uint32_t offFifoMax,
2555 uint8_t *pbBounceBuf, uint32_t *pcbAlreadyRead,
2556 PPDMTHREAD pThread, PVGASTATE pThis, PVMSVGAR3STATE pSVGAState)
2557{
2558 Assert(pbBounceBuf);
2559 Assert(pcbAlreadyRead);
2560 Assert(offFifoMin < offFifoMax);
2561 Assert(offCurrentCmd >= offFifoMin && offCurrentCmd < offFifoMax);
2562 Assert(offFifoMax <= VMSVGA_FIFO_SIZE);
2563
2564 /*
2565 * Check if the requested payload size has already been satisfied .
2566 * .
2567 * When called to read more, the caller is responsible for making sure the .
2568 * new command size (cbRequsted) never is smaller than what has already .
2569 * been read.
2570 */
2571 uint32_t cbAlreadyRead = *pcbAlreadyRead;
2572 if (cbPayloadReq <= cbAlreadyRead)
2573 {
2574 AssertLogRelReturn(cbPayloadReq == cbAlreadyRead, NULL);
2575 return pbBounceBuf;
2576 }
2577
2578 /*
2579 * Commands bigger than the fifo buffer are invalid.
2580 */
2581 uint32_t const cbFifoCmd = offFifoMax - offFifoMin;
2582 AssertMsgReturnStmt(cbPayloadReq <= cbFifoCmd, ("cbPayloadReq=%#x cbFifoCmd=%#x\n", cbPayloadReq, cbFifoCmd),
2583 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoErrors),
2584 NULL);
2585
2586 /*
2587 * Move offCurrentCmd past the command dword.
2588 */
2589 offCurrentCmd += sizeof(uint32_t);
2590 if (offCurrentCmd >= offFifoMax)
2591 offCurrentCmd = offFifoMin;
2592
2593 /*
2594 * Do we have sufficient payload data available already?
2595 */
2596 uint32_t cbAfter, cbBefore;
2597 uint32_t offNextCmd = pFIFO[SVGA_FIFO_NEXT_CMD];
2598 if (offNextCmd > offCurrentCmd)
2599 {
2600 if (RT_LIKELY(offNextCmd < offFifoMax))
2601 cbAfter = offNextCmd - offCurrentCmd;
2602 else
2603 {
2604 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoErrors);
2605 LogRelMax(16, ("vmsvgaFIFOGetCmdPayload: Invalid offNextCmd=%#x (offFifoMin=%#x offFifoMax=%#x)\n",
2606 offNextCmd, offFifoMin, offFifoMax));
2607 cbAfter = offFifoMax - offCurrentCmd;
2608 }
2609 cbBefore = 0;
2610 }
2611 else
2612 {
2613 cbAfter = offFifoMax - offCurrentCmd;
2614 if (offNextCmd >= offFifoMin)
2615 cbBefore = offNextCmd - offFifoMin;
2616 else
2617 {
2618 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoErrors);
2619 LogRelMax(16, ("vmsvgaFIFOGetCmdPayload: Invalid offNextCmd=%#x (offFifoMin=%#x offFifoMax=%#x)\n",
2620 offNextCmd, offFifoMin, offFifoMax));
2621 cbBefore = 0;
2622 }
2623 }
2624 if (cbAfter + cbBefore < cbPayloadReq)
2625 {
2626 /*
2627 * Insufficient, must wait for it to arrive.
2628 */
2629/** @todo Should clear the busy flag here to maybe encourage the guest to wake us up. */
2630 STAM_REL_PROFILE_START(&pSVGAState->StatFifoStalls, Stall);
2631 for (uint32_t i = 0;; i++)
2632 {
2633 if (pThread->enmState != PDMTHREADSTATE_RUNNING)
2634 {
2635 STAM_REL_PROFILE_STOP(&pSVGAState->StatFifoStalls, Stall);
2636 return (void *)(uintptr_t)1;
2637 }
2638 Log(("Guest still copying (%x vs %x) current %x next %x stop %x loop %u; sleep a bit\n",
2639 cbPayloadReq, cbAfter + cbBefore, offCurrentCmd, offNextCmd, pFIFO[SVGA_FIFO_STOP], i));
2640
2641 SUPSemEventWaitNoResume(pThis->svga.pSupDrvSession, pThis->svga.FIFORequestSem, i < 16 ? 1 : 2);
2642
2643 offNextCmd = pFIFO[SVGA_FIFO_NEXT_CMD];
2644 if (offNextCmd > offCurrentCmd)
2645 {
2646 cbAfter = RT_MIN(offNextCmd, offFifoMax) - offCurrentCmd;
2647 cbBefore = 0;
2648 }
2649 else
2650 {
2651 cbAfter = offFifoMax - offCurrentCmd;
2652 cbBefore = RT_MAX(offNextCmd, offFifoMin) - offFifoMin;
2653 }
2654
2655 if (cbAfter + cbBefore >= cbPayloadReq)
2656 break;
2657 }
2658 STAM_REL_PROFILE_STOP(&pSVGAState->StatFifoStalls, Stall);
2659 }
2660
2661 /*
2662 * Copy out the memory and update what pcbAlreadyRead points to.
2663 */
2664 if (cbAfter >= cbPayloadReq)
2665 memcpy(pbBounceBuf + cbAlreadyRead,
2666 (uint8_t *)pFIFO + offCurrentCmd + cbAlreadyRead,
2667 cbPayloadReq - cbAlreadyRead);
2668 else
2669 {
2670 LogFlow(("Split data buffer at %x (%u-%u)\n", offCurrentCmd, cbAfter, cbBefore));
2671 if (cbAlreadyRead < cbAfter)
2672 {
2673 memcpy(pbBounceBuf + cbAlreadyRead,
2674 (uint8_t *)pFIFO + offCurrentCmd + cbAlreadyRead,
2675 cbAfter - cbAlreadyRead);
2676 cbAlreadyRead = cbAfter;
2677 }
2678 memcpy(pbBounceBuf + cbAlreadyRead,
2679 (uint8_t *)pFIFO + offFifoMin + cbAlreadyRead - cbAfter,
2680 cbPayloadReq - cbAlreadyRead);
2681 }
2682 *pcbAlreadyRead = cbPayloadReq;
2683 return pbBounceBuf;
2684}
2685
2686/* The async FIFO handling thread. */
2687static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
2688{
2689 PVGASTATE pThis = (PVGASTATE)pThread->pvUser;
2690 PVMSVGAR3STATE pSVGAState = pThis->svga.pSvgaR3State;
2691 int rc;
2692
2693 if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
2694 return VINF_SUCCESS;
2695
2696 /*
2697 * Special mode where we only execute an external command and the go back
2698 * to being suspended. Currently, all ext cmds ends up here, with the reset
2699 * one also being eligble for runtime execution further down as well.
2700 */
2701 if (pThis->svga.fFifoExtCommandWakeup)
2702 {
2703 vmsvgaR3FifoHandleExtCmd(pThis);
2704 while (pThread->enmState == PDMTHREADSTATE_RUNNING)
2705 if (pThis->svga.u8FIFOExtCommand == VMSVGA_FIFO_EXTCMD_NONE)
2706 SUPSemEventWaitNoResume(pThis->svga.pSupDrvSession, pThis->svga.FIFORequestSem, RT_MS_1MIN);
2707 else
2708 vmsvgaR3FifoHandleExtCmd(pThis);
2709 return VINF_SUCCESS;
2710 }
2711
2712
2713 /*
2714 * Signal the semaphore to make sure we don't wait for 250ms after a
2715 * suspend & resume scenario (see vmsvgaFIFOGetCmdPayload).
2716 */
2717 SUPSemEventSignal(pThis->svga.pSupDrvSession, pThis->svga.FIFORequestSem);
2718
2719 /*
2720 * Allocate a bounce buffer for command we get from the FIFO.
2721 * (All code must return via the end of the function to free this buffer.)
2722 */
2723 uint8_t *pbBounceBuf = (uint8_t *)RTMemAllocZ(VMSVGA_FIFO_SIZE);
2724 AssertReturn(pbBounceBuf, VERR_NO_MEMORY);
2725
2726 /*
2727 * Polling/sleep interval config.
2728 *
2729 * We wait for an a short interval if the guest has recently given us work
2730 * to do, but the interval increases the longer we're kept idle. With the
2731 * current parameters we'll be at a 64ms poll interval after 1 idle second,
2732 * at 90ms after 2 seconds, and reach the max 250ms interval after about
2733 * 16 seconds.
2734 */
2735 RTMSINTERVAL const cMsMinSleep = 16;
2736 RTMSINTERVAL const cMsIncSleep = 2;
2737 RTMSINTERVAL const cMsMaxSleep = 250;
2738 RTMSINTERVAL cMsSleep = cMsMaxSleep;
2739
2740 /*
2741 * The FIFO loop.
2742 */
2743 LogFlow(("vmsvgaFIFOLoop: started loop\n"));
2744 bool fBadOrDisabledFifo = false;
2745 uint32_t volatile * const pFIFO = pThis->svga.pFIFOR3;
2746 while (pThread->enmState == PDMTHREADSTATE_RUNNING)
2747 {
2748# if defined(RT_OS_DARWIN) && defined(VBOX_WITH_VMSVGA3D)
2749 /*
2750 * Should service the run loop every so often.
2751 */
2752 if (pThis->svga.f3DEnabled)
2753 vmsvga3dCocoaServiceRunLoop();
2754# endif
2755
2756 /*
2757 * Unless there's already work pending, go to sleep for a short while.
2758 * (See polling/sleep interval config above.)
2759 */
2760 if ( fBadOrDisabledFifo
2761 || pFIFO[SVGA_FIFO_NEXT_CMD] == pFIFO[SVGA_FIFO_STOP])
2762 {
2763 rc = SUPSemEventWaitNoResume(pThis->svga.pSupDrvSession, pThis->svga.FIFORequestSem, cMsSleep);
2764 AssertBreak(RT_SUCCESS(rc) || rc == VERR_TIMEOUT || rc == VERR_INTERRUPTED);
2765 if (pThread->enmState != PDMTHREADSTATE_RUNNING)
2766 {
2767 LogFlow(("vmsvgaFIFOLoop: thread state %x\n", pThread->enmState));
2768 break;
2769 }
2770 }
2771 else
2772 rc = VINF_SUCCESS;
2773 fBadOrDisabledFifo = false;
2774 if (rc == VERR_TIMEOUT)
2775 {
2776 if (pFIFO[SVGA_FIFO_NEXT_CMD] == pFIFO[SVGA_FIFO_STOP])
2777 {
2778 cMsSleep = RT_MIN(cMsSleep + cMsIncSleep, cMsMaxSleep);
2779 continue;
2780 }
2781 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoTodoTimeout);
2782
2783 Log(("vmsvgaFIFOLoop: timeout\n"));
2784 }
2785 else if (pFIFO[SVGA_FIFO_NEXT_CMD] != pFIFO[SVGA_FIFO_STOP])
2786 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoTodoWoken);
2787 cMsSleep = cMsMinSleep;
2788
2789 Log(("vmsvgaFIFOLoop: enabled=%d configured=%d busy=%d\n", pThis->svga.fEnabled, pThis->svga.fConfigured, pThis->svga.pFIFOR3[SVGA_FIFO_BUSY]));
2790 Log(("vmsvgaFIFOLoop: min %x max %x\n", pFIFO[SVGA_FIFO_MIN], pFIFO[SVGA_FIFO_MAX]));
2791 Log(("vmsvgaFIFOLoop: next %x stop %x\n", pFIFO[SVGA_FIFO_NEXT_CMD], pFIFO[SVGA_FIFO_STOP]));
2792
2793 /*
2794 * Handle external commands (currently only reset).
2795 */
2796 if (pThis->svga.u8FIFOExtCommand != VMSVGA_FIFO_EXTCMD_NONE)
2797 {
2798 vmsvgaR3FifoHandleExtCmd(pThis);
2799 continue;
2800 }
2801
2802 /*
2803 * The device must be enabled and configured.
2804 */
2805 if ( !pThis->svga.fEnabled
2806 || !pThis->svga.fConfigured)
2807 {
2808 vmsvgaFifoSetNotBusy(pThis, pSVGAState, pFIFO[SVGA_FIFO_MIN]);
2809 fBadOrDisabledFifo = true;
2810 continue;
2811 }
2812
2813 /*
2814 * Get and check the min/max values. We ASSUME that they will remain
2815 * unchanged while we process requests. A further ASSUMPTION is that
2816 * the guest won't mess with SVGA_FIFO_NEXT_CMD while we're busy, so
2817 * we don't read it back while in the loop.
2818 */
2819 uint32_t const offFifoMin = pFIFO[SVGA_FIFO_MIN];
2820 uint32_t const offFifoMax = pFIFO[SVGA_FIFO_MAX];
2821 uint32_t offCurrentCmd = pFIFO[SVGA_FIFO_STOP];
2822 if (RT_UNLIKELY( !VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_STOP, offFifoMin)
2823 || offFifoMax <= offFifoMin
2824 || offFifoMax > VMSVGA_FIFO_SIZE
2825 || (offFifoMax & 3) != 0
2826 || (offFifoMin & 3) != 0
2827 || offCurrentCmd < offFifoMin
2828 || offCurrentCmd > offFifoMax))
2829 {
2830 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoErrors);
2831 LogRelMax(8, ("vmsvgaFIFOLoop: Bad fifo: min=%#x stop=%#x max=%#x\n", offFifoMin, offCurrentCmd, offFifoMax));
2832 vmsvgaFifoSetNotBusy(pThis, pSVGAState, offFifoMin);
2833 fBadOrDisabledFifo = true;
2834 continue;
2835 }
2836 if (RT_UNLIKELY(offCurrentCmd & 3))
2837 {
2838 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoErrors);
2839 LogRelMax(8, ("vmsvgaFIFOLoop: Misaligned offCurrentCmd=%#x?\n", offCurrentCmd));
2840 offCurrentCmd = ~UINT32_C(3);
2841 }
2842
2843/** @def VMSVGAFIFO_GET_CMD_BUFFER_BREAK
2844 * Macro for shortening calls to vmsvgaFIFOGetCmdPayload.
2845 *
2846 * Will break out of the switch on failure.
2847 * Will restart and quit the loop if the thread was requested to stop.
2848 *
2849 * @param a_PtrVar Request variable pointer.
2850 * @param a_Type Request typedef (not pointer) for casting.
2851 * @param a_cbPayloadReq How much payload to fetch.
2852 * @remarks Accesses a bunch of variables in the current scope!
2853 */
2854# define VMSVGAFIFO_GET_CMD_BUFFER_BREAK(a_PtrVar, a_Type, a_cbPayloadReq) \
2855 if (1) { \
2856 (a_PtrVar) = (a_Type *)vmsvgaFIFOGetCmdPayload((a_cbPayloadReq), pFIFO, offCurrentCmd, offFifoMin, offFifoMax, \
2857 pbBounceBuf, &cbPayload, pThread, pThis, pSVGAState); \
2858 if (RT_UNLIKELY((uintptr_t)(a_PtrVar) < 2)) { if ((uintptr_t)(a_PtrVar) == 1) continue; break; } \
2859 } else do {} while (0)
2860/** @def VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK
2861 * Macro for shortening calls to vmsvgaFIFOGetCmdPayload for refetching the
2862 * buffer after figuring out the actual command size.
2863 *
2864 * Will break out of the switch on failure.
2865 *
2866 * @param a_PtrVar Request variable pointer.
2867 * @param a_Type Request typedef (not pointer) for casting.
2868 * @param a_cbPayloadReq How much payload to fetch.
2869 * @remarks Accesses a bunch of variables in the current scope!
2870 */
2871# define VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(a_PtrVar, a_Type, a_cbPayloadReq) \
2872 if (1) { \
2873 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(a_PtrVar, a_Type, a_cbPayloadReq); \
2874 } else do {} while (0)
2875
2876 /*
2877 * Mark the FIFO as busy.
2878 */
2879 ASMAtomicWriteU32(&pThis->svga.fBusy, VMSVGA_BUSY_F_FIFO);
2880 if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_BUSY, offFifoMin))
2881 ASMAtomicWriteU32(&pFIFO[SVGA_FIFO_BUSY], true);
2882
2883 /*
2884 * Execute all queued FIFO commands.
2885 * Quit if pending external command or changes in the thread state.
2886 */
2887 bool fDone = false;
2888 while ( !(fDone = (pFIFO[SVGA_FIFO_NEXT_CMD] == offCurrentCmd))
2889 && pThread->enmState == PDMTHREADSTATE_RUNNING)
2890 {
2891 uint32_t cbPayload = 0;
2892 uint32_t u32IrqStatus = 0;
2893
2894 Assert(offCurrentCmd < offFifoMax && offCurrentCmd >= offFifoMin);
2895
2896 /* First check any pending actions. */
2897 if (ASMBitTestAndClear(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE_BIT))
2898# ifdef VBOX_WITH_VMSVGA3D
2899 vmsvga3dChangeMode(pThis);
2900# else
2901 {/*nothing*/}
2902# endif
2903 /* Check for pending external commands (reset). */
2904 if (pThis->svga.u8FIFOExtCommand != VMSVGA_FIFO_EXTCMD_NONE)
2905 break;
2906
2907 /*
2908 * Process the command.
2909 */
2910 SVGAFifoCmdId const enmCmdId = (SVGAFifoCmdId)pFIFO[offCurrentCmd / sizeof(uint32_t)];
2911 LogFlow(("vmsvgaFIFOLoop: FIFO command (iCmd=0x%x) %s 0x%x\n",
2912 offCurrentCmd / sizeof(uint32_t), vmsvgaFIFOCmdToString(enmCmdId), enmCmdId));
2913 switch (enmCmdId)
2914 {
2915 case SVGA_CMD_INVALID_CMD:
2916 /* Nothing to do. */
2917 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdInvalidCmd);
2918 break;
2919
2920 case SVGA_CMD_FENCE:
2921 {
2922 SVGAFifoCmdFence *pCmdFence;
2923 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmdFence, SVGAFifoCmdFence, sizeof(*pCmdFence));
2924 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdFence);
2925 if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_FENCE, offFifoMin))
2926 {
2927 Log(("vmsvgaFIFOLoop: SVGA_CMD_FENCE %x\n", pCmdFence->fence));
2928 pFIFO[SVGA_FIFO_FENCE] = pCmdFence->fence;
2929
2930 if (pThis->svga.u32IrqMask & SVGA_IRQFLAG_ANY_FENCE)
2931 {
2932 Log(("vmsvgaFIFOLoop: any fence irq\n"));
2933 u32IrqStatus |= SVGA_IRQFLAG_ANY_FENCE;
2934 }
2935 else
2936 if ( VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_FENCE_GOAL, offFifoMin)
2937 && (pThis->svga.u32IrqMask & SVGA_IRQFLAG_FENCE_GOAL)
2938 && pFIFO[SVGA_FIFO_FENCE_GOAL] == pCmdFence->fence)
2939 {
2940 Log(("vmsvgaFIFOLoop: fence goal reached irq (fence=%x)\n", pCmdFence->fence));
2941 u32IrqStatus |= SVGA_IRQFLAG_FENCE_GOAL;
2942 }
2943 }
2944 else
2945 Log(("SVGA_CMD_FENCE is bogus when offFifoMin is %#x!\n", offFifoMin));
2946 break;
2947 }
2948 case SVGA_CMD_UPDATE:
2949 case SVGA_CMD_UPDATE_VERBOSE:
2950 {
2951 SVGAFifoCmdUpdate *pUpdate;
2952 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pUpdate, SVGAFifoCmdUpdate, sizeof(*pUpdate));
2953 if (enmCmdId == SVGA_CMD_UPDATE)
2954 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdUpdate);
2955 else
2956 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdUpdateVerbose);
2957 Log(("vmsvgaFIFOLoop: UPDATE (%d,%d)(%d,%d)\n", pUpdate->x, pUpdate->y, pUpdate->width, pUpdate->height));
2958 vgaR3UpdateDisplay(pThis, pUpdate->x, pUpdate->y, pUpdate->width, pUpdate->height);
2959 break;
2960 }
2961
2962 case SVGA_CMD_DEFINE_CURSOR:
2963 {
2964 /* Followed by bitmap data. */
2965 SVGAFifoCmdDefineCursor *pCursor;
2966 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCursor, SVGAFifoCmdDefineCursor, sizeof(*pCursor));
2967 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdDefineCursor);
2968 AssertFailed(); /** @todo implement when necessary. */
2969 break;
2970 }
2971
2972 case SVGA_CMD_DEFINE_ALPHA_CURSOR:
2973 {
2974 /* Followed by bitmap data. */
2975 uint32_t cbCursorShape, cbAndMask;
2976 uint8_t *pCursorCopy;
2977 uint32_t cbCmd;
2978
2979 SVGAFifoCmdDefineAlphaCursor *pCursor;
2980 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCursor, SVGAFifoCmdDefineAlphaCursor, sizeof(*pCursor));
2981 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdDefineAlphaCursor);
2982
2983 Log(("vmsvgaFIFOLoop: ALPHA_CURSOR id=%d size (%d,%d) hotspot (%d,%d)\n", pCursor->id, pCursor->width, pCursor->height, pCursor->hotspotX, pCursor->hotspotY));
2984
2985 /* Check against a reasonable upper limit to prevent integer overflows in the sanity checks below. */
2986 AssertBreak(pCursor->height < 2048 && pCursor->width < 2048);
2987
2988 /* Refetch the bitmap data as well. */
2989 cbCmd = sizeof(SVGAFifoCmdDefineAlphaCursor) + pCursor->width * pCursor->height * sizeof(uint32_t) /* 32-bit BRGA format */;
2990 VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pCursor, SVGAFifoCmdDefineAlphaCursor, cbCmd);
2991 /** @todo Would be more efficient to copy the data straight into pCursorCopy (memcpy below). */
2992
2993 /* The mouse pointer interface always expects an AND mask followed by the color data (XOR mask). */
2994 cbAndMask = (pCursor->width + 7) / 8 * pCursor->height; /* size of the AND mask */
2995 cbAndMask = ((cbAndMask + 3) & ~3); /* + gap for alignment */
2996 cbCursorShape = cbAndMask + pCursor->width * sizeof(uint32_t) * pCursor->height; /* + size of the XOR mask (32-bit BRGA format) */
2997
2998 pCursorCopy = (uint8_t *)RTMemAlloc(cbCursorShape);
2999 AssertBreak(pCursorCopy);
3000
3001 Log2(("Cursor data:\n%.*Rhxd\n", pCursor->width * pCursor->height * sizeof(uint32_t), pCursor+1));
3002
3003 /* Transparency is defined by the alpha bytes, so make the whole bitmap visible. */
3004 memset(pCursorCopy, 0xff, cbAndMask);
3005 /* Colour data */
3006 memcpy(pCursorCopy + cbAndMask, (pCursor + 1), pCursor->width * pCursor->height * sizeof(uint32_t));
3007
3008 rc = pThis->pDrv->pfnVBVAMousePointerShape (pThis->pDrv,
3009 true,
3010 true,
3011 pCursor->hotspotX,
3012 pCursor->hotspotY,
3013 pCursor->width,
3014 pCursor->height,
3015 pCursorCopy);
3016 AssertRC(rc);
3017
3018 if (pSVGAState->Cursor.fActive)
3019 RTMemFree(pSVGAState->Cursor.pData);
3020
3021 pSVGAState->Cursor.fActive = true;
3022 pSVGAState->Cursor.xHotspot = pCursor->hotspotX;
3023 pSVGAState->Cursor.yHotspot = pCursor->hotspotY;
3024 pSVGAState->Cursor.width = pCursor->width;
3025 pSVGAState->Cursor.height = pCursor->height;
3026 pSVGAState->Cursor.cbData = cbCursorShape;
3027 pSVGAState->Cursor.pData = pCursorCopy;
3028 break;
3029 }
3030
3031 case SVGA_CMD_ESCAPE:
3032 {
3033 /* Followed by nsize bytes of data. */
3034 SVGAFifoCmdEscape *pEscape;
3035 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pEscape, SVGAFifoCmdEscape, sizeof(*pEscape));
3036 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdEscape);
3037
3038 /* Refetch the command buffer with the variable data; undo size increase (ugly) */
3039 AssertBreak(pEscape->size < VMSVGA_FIFO_SIZE);
3040 uint32_t cbCmd = sizeof(SVGAFifoCmdEscape) + pEscape->size;
3041 VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pEscape, SVGAFifoCmdEscape, cbCmd);
3042
3043 if (pEscape->nsid == SVGA_ESCAPE_NSID_VMWARE)
3044 {
3045 AssertBreak(pEscape->size >= sizeof(uint32_t));
3046 uint32_t cmd = *(uint32_t *)(pEscape + 1);
3047 Log(("vmsvgaFIFOLoop: ESCAPE (%x %x) VMWARE cmd=%x\n", pEscape->nsid, pEscape->size, cmd));
3048
3049 switch (cmd)
3050 {
3051 case SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS:
3052 {
3053 SVGAEscapeVideoSetRegs *pVideoCmd = (SVGAEscapeVideoSetRegs *)(pEscape + 1);
3054 AssertBreak(pEscape->size >= sizeof(pVideoCmd->header));
3055 uint32_t cRegs = (pEscape->size - sizeof(pVideoCmd->header)) / sizeof(pVideoCmd->items[0]);
3056
3057 Log(("SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS: stream %x\n", pVideoCmd->header.streamId));
3058 for (uint32_t iReg = 0; iReg < cRegs; iReg++)
3059 Log(("SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS: reg %x val %x\n", pVideoCmd->items[iReg].registerId, pVideoCmd->items[iReg].value));
3060
3061 RT_NOREF_PV(pVideoCmd);
3062 break;
3063
3064 }
3065
3066 case SVGA_ESCAPE_VMWARE_VIDEO_FLUSH:
3067 {
3068 SVGAEscapeVideoFlush *pVideoCmd = (SVGAEscapeVideoFlush *)(pEscape + 1);
3069 AssertBreak(pEscape->size >= sizeof(*pVideoCmd));
3070 Log(("SVGA_ESCAPE_VMWARE_VIDEO_FLUSH: stream %x\n", pVideoCmd->streamId));
3071 RT_NOREF_PV(pVideoCmd);
3072 break;
3073 }
3074 }
3075 }
3076 else
3077 Log(("vmsvgaFIFOLoop: ESCAPE %x %x\n", pEscape->nsid, pEscape->size));
3078
3079 break;
3080 }
3081# ifdef VBOX_WITH_VMSVGA3D
3082 case SVGA_CMD_DEFINE_GMR2:
3083 {
3084 SVGAFifoCmdDefineGMR2 *pCmd;
3085 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineGMR2, sizeof(*pCmd));
3086 Log(("vmsvgaFIFOLoop: SVGA_CMD_DEFINE_GMR2 id=%x %x pages\n", pCmd->gmrId, pCmd->numPages));
3087 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdDefineGmr2);
3088
3089 /* Validate current GMR id. */
3090 AssertBreak(pCmd->gmrId < VMSVGA_MAX_GMR_IDS);
3091 AssertBreak(pCmd->numPages <= VMSVGA_MAX_GMR_PAGES);
3092
3093 if (!pCmd->numPages)
3094 {
3095 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdDefineGmr2Free);
3096 vmsvgaGMRFree(pThis, pCmd->gmrId);
3097 }
3098 else
3099 {
3100 PGMR pGMR = &pSVGAState->aGMR[pCmd->gmrId];
3101 if (pGMR->cMaxPages)
3102 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdDefineGmr2Modify);
3103
3104 /* Not sure if we should always free the descriptor, but for simplicity
3105 we do so if the new size is smaller than the current. */
3106 /** @todo always free the descriptor in SVGA_CMD_DEFINE_GMR2? */
3107 if (pGMR->cbTotal / X86_PAGE_SIZE > pGMR->cMaxPages)
3108 vmsvgaGMRFree(pThis, pCmd->gmrId);
3109
3110 pGMR->cMaxPages = pCmd->numPages;
3111 /* The rest is done by the REMAP_GMR2 command. */
3112 }
3113 break;
3114 }
3115
3116 case SVGA_CMD_REMAP_GMR2:
3117 {
3118 /* Followed by page descriptors or guest ptr. */
3119 SVGAFifoCmdRemapGMR2 *pCmd;
3120 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdRemapGMR2, sizeof(*pCmd));
3121 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdRemapGmr2);
3122
3123 Log(("vmsvgaFIFOLoop: SVGA_CMD_REMAP_GMR2 id=%x flags=%x offset=%x npages=%x\n", pCmd->gmrId, pCmd->flags, pCmd->offsetPages, pCmd->numPages));
3124 AssertBreak(pCmd->gmrId < VMSVGA_MAX_GMR_IDS);
3125
3126 /* Calculate the size of what comes after next and fetch it. */
3127 uint32_t cbCmd = sizeof(SVGAFifoCmdRemapGMR2);
3128 if (pCmd->flags & SVGA_REMAP_GMR2_VIA_GMR)
3129 cbCmd += sizeof(SVGAGuestPtr);
3130 else
3131 {
3132 uint32_t const cbPageDesc = (pCmd->flags & SVGA_REMAP_GMR2_PPN64) ? sizeof(uint64_t) : sizeof(uint32_t);
3133 if (pCmd->flags & SVGA_REMAP_GMR2_SINGLE_PPN)
3134 {
3135 cbCmd += cbPageDesc;
3136 pCmd->numPages = 1;
3137 }
3138 else
3139 {
3140 AssertBreak(pCmd->numPages <= VMSVGA_FIFO_SIZE / cbPageDesc);
3141 cbCmd += cbPageDesc * pCmd->numPages;
3142 }
3143 }
3144 VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdRemapGMR2, cbCmd);
3145
3146 /* Validate current GMR id and size. */
3147 AssertBreak(pCmd->gmrId < VMSVGA_MAX_GMR_IDS);
3148 PGMR pGMR = &pSVGAState->aGMR[pCmd->gmrId];
3149 AssertBreak( (uint64_t)pCmd->offsetPages + pCmd->numPages
3150 <= RT_MIN(pGMR->cMaxPages, RT_MIN(VMSVGA_MAX_GMR_PAGES, UINT32_MAX / X86_PAGE_SIZE)));
3151 AssertBreak(!pCmd->offsetPages || pGMR->paDesc); /** @todo */
3152
3153 if (pCmd->numPages == 0)
3154 break;
3155
3156 /* Calc new total page count so we can use it instead of cMaxPages for allocations below. */
3157 uint32_t const cNewTotalPages = RT_MAX(pGMR->cbTotal >> X86_PAGE_SHIFT, pCmd->offsetPages + pCmd->numPages);
3158
3159 /*
3160 * We flatten the existing descriptors into a page array, overwrite the
3161 * pages specified in this command and then recompress the descriptor.
3162 */
3163 /** @todo Optimize the GMR remap algorithm! */
3164
3165 /* Save the old page descriptors as an array of page frame numbers (address >> X86_PAGE_SHIFT) */
3166 uint64_t *paNewPage64 = NULL;
3167 if (pGMR->paDesc)
3168 {
3169 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdRemapGmr2Modify);
3170
3171 paNewPage64 = (uint64_t *)RTMemAllocZ(cNewTotalPages * sizeof(uint64_t));
3172 AssertBreak(paNewPage64);
3173
3174 uint32_t idxPage = 0;
3175 for (uint32_t i = 0; i < pGMR->numDescriptors; i++)
3176 for (uint32_t j = 0; j < pGMR->paDesc[i].numPages; j++)
3177 paNewPage64[idxPage++] = (pGMR->paDesc[i].GCPhys + j * X86_PAGE_SIZE) >> X86_PAGE_SHIFT;
3178 AssertBreakStmt(idxPage == pGMR->cbTotal >> X86_PAGE_SHIFT, RTMemFree(paNewPage64));
3179 }
3180
3181 /* Free the old GMR if present. */
3182 if (pGMR->paDesc)
3183 RTMemFree(pGMR->paDesc);
3184
3185 /* Allocate the maximum amount possible (everything non-continuous) */
3186 PVMSVGAGMRDESCRIPTOR paDescs;
3187 pGMR->paDesc = paDescs = (PVMSVGAGMRDESCRIPTOR)RTMemAllocZ(cNewTotalPages * sizeof(VMSVGAGMRDESCRIPTOR));
3188 AssertBreakStmt(paDescs, RTMemFree(paNewPage64));
3189
3190 if (pCmd->flags & SVGA_REMAP_GMR2_VIA_GMR)
3191 {
3192 /** @todo */
3193 AssertFailed();
3194 pGMR->numDescriptors = 0;
3195 }
3196 else
3197 {
3198 uint32_t *paPages32 = (uint32_t *)(pCmd + 1);
3199 uint64_t *paPages64 = (uint64_t *)(pCmd + 1);
3200 bool fGCPhys64 = RT_BOOL(pCmd->flags & SVGA_REMAP_GMR2_PPN64);
3201
3202 if (paNewPage64)
3203 {
3204 /* Overwrite the old page array with the new page values. */
3205 if (fGCPhys64)
3206 for (uint32_t i = pCmd->offsetPages; i < pCmd->offsetPages + pCmd->numPages; i++)
3207 paNewPage64[i] = paPages64[i - pCmd->offsetPages];
3208 else
3209 for (uint32_t i = pCmd->offsetPages; i < pCmd->offsetPages + pCmd->numPages; i++)
3210 paNewPage64[i] = paPages32[i - pCmd->offsetPages];
3211
3212 /* Use the updated page array instead of the command data. */
3213 fGCPhys64 = true;
3214 paPages64 = paNewPage64;
3215 pCmd->numPages = cNewTotalPages;
3216 }
3217
3218 /* The first page. */
3219 /** @todo The 0x00000FFFFFFFFFFF mask limits to 44 bits and should not be
3220 * applied to paNewPage64. */
3221 RTGCPHYS GCPhys;
3222 if (fGCPhys64)
3223 GCPhys = (paPages64[0] << X86_PAGE_SHIFT) & UINT64_C(0x00000FFFFFFFFFFF); /* Seeing rubbish in the top bits with certain linux guests. */
3224 else
3225 GCPhys = (RTGCPHYS)paPages32[0] << PAGE_SHIFT;
3226 paDescs[0].GCPhys = GCPhys;
3227 paDescs[0].numPages = 1;
3228
3229 /* Subsequent pages. */
3230 uint32_t iDescriptor = 0;
3231 for (uint32_t i = 1; i < pCmd->numPages; i++)
3232 {
3233 if (pCmd->flags & SVGA_REMAP_GMR2_PPN64)
3234 GCPhys = (paPages64[i] << X86_PAGE_SHIFT) & UINT64_C(0x00000FFFFFFFFFFF); /* Seeing rubbish in the top bits with certain linux guests. */
3235 else
3236 GCPhys = (RTGCPHYS)paPages32[i] << X86_PAGE_SHIFT;
3237
3238 /* Continuous physical memory? */
3239 if (GCPhys == paDescs[iDescriptor].GCPhys + paDescs[iDescriptor].numPages * X86_PAGE_SIZE)
3240 {
3241 Assert(paDescs[iDescriptor].numPages);
3242 paDescs[iDescriptor].numPages++;
3243 LogFlow(("Page %x GCPhys=%RGp successor\n", i, GCPhys));
3244 }
3245 else
3246 {
3247 iDescriptor++;
3248 paDescs[iDescriptor].GCPhys = GCPhys;
3249 paDescs[iDescriptor].numPages = 1;
3250 LogFlow(("Page %x GCPhys=%RGp\n", i, paDescs[iDescriptor].GCPhys));
3251 }
3252 }
3253
3254 pGMR->cbTotal = cNewTotalPages << X86_PAGE_SHIFT;
3255 LogFlow(("Nr of descriptors %x; cbTotal=%#x\n", iDescriptor + 1, cNewTotalPages));
3256 pGMR->numDescriptors = iDescriptor + 1;
3257 }
3258
3259 if (paNewPage64)
3260 RTMemFree(paNewPage64);
3261
3262# ifdef DEBUG_GMR_ACCESS
3263 VMR3ReqCallWaitU(PDMDevHlpGetUVM(pThis->pDevInsR3), VMCPUID_ANY, (PFNRT)vmsvgaRegisterGMR, 2, pThis->pDevInsR3, pCmd->gmrId);
3264# endif
3265 break;
3266 }
3267# endif // VBOX_WITH_VMSVGA3D
3268 case SVGA_CMD_DEFINE_SCREEN:
3269 {
3270 /* Note! The size of this command is specified by the guest and depends on capabilities. */
3271 Assert(!(pThis->svga.pFIFOR3[SVGA_FIFO_CAPABILITIES] & SVGA_FIFO_CAP_SCREEN_OBJECT));
3272 SVGAFifoCmdDefineScreen *pCmd;
3273 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineScreen, sizeof(pCmd->screen.structSize));
3274 RT_BZERO(&pCmd->screen.id, sizeof(*pCmd) - RT_OFFSETOF(SVGAFifoCmdDefineScreen, screen.structSize));
3275 VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineScreen, RT_MAX(sizeof(pCmd->screen.structSize), pCmd->screen.structSize));
3276 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdDefineScreen);
3277
3278 Log(("vmsvgaFIFOLoop: SVGA_CMD_DEFINE_SCREEN id=%x flags=%x size=(%d,%d) root=(%d,%d)\n", pCmd->screen.id, pCmd->screen.flags, pCmd->screen.size.width, pCmd->screen.size.height, pCmd->screen.root.x, pCmd->screen.root.y));
3279 if (pCmd->screen.flags & SVGA_SCREEN_HAS_ROOT)
3280 Log(("vmsvgaFIFOLoop: SVGA_CMD_DEFINE_SCREEN flags SVGA_SCREEN_HAS_ROOT\n"));
3281 if (pCmd->screen.flags & SVGA_SCREEN_IS_PRIMARY)
3282 Log(("vmsvgaFIFOLoop: SVGA_CMD_DEFINE_SCREEN flags SVGA_SCREEN_IS_PRIMARY\n"));
3283 if (pCmd->screen.flags & SVGA_SCREEN_FULLSCREEN_HINT)
3284 Log(("vmsvgaFIFOLoop: SVGA_CMD_DEFINE_SCREEN flags SVGA_SCREEN_FULLSCREEN_HINT\n"));
3285 if (pCmd->screen.flags & SVGA_SCREEN_DEACTIVATE )
3286 Log(("vmsvgaFIFOLoop: SVGA_CMD_DEFINE_SCREEN flags SVGA_SCREEN_DEACTIVATE \n"));
3287 if (pCmd->screen.flags & SVGA_SCREEN_BLANKING)
3288 Log(("vmsvgaFIFOLoop: SVGA_CMD_DEFINE_SCREEN flags SVGA_SCREEN_BLANKING\n"));
3289
3290 /** @todo multi monitor support and screen object capabilities. */
3291 pThis->svga.uWidth = pCmd->screen.size.width;
3292 pThis->svga.uHeight = pCmd->screen.size.height;
3293 vmsvgaChangeMode(pThis);
3294 break;
3295 }
3296
3297 case SVGA_CMD_DESTROY_SCREEN:
3298 {
3299 SVGAFifoCmdDestroyScreen *pCmd;
3300 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDestroyScreen, sizeof(*pCmd));
3301 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdDestroyScreen);
3302
3303 Log(("vmsvgaFIFOLoop: SVGA_CMD_DESTROY_SCREEN id=%x\n", pCmd->screenId));
3304 break;
3305 }
3306# ifdef VBOX_WITH_VMSVGA3D
3307 case SVGA_CMD_DEFINE_GMRFB:
3308 {
3309 SVGAFifoCmdDefineGMRFB *pCmd;
3310 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineGMRFB, sizeof(*pCmd));
3311 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdDefineGmrFb);
3312
3313 Log(("vmsvgaFIFOLoop: SVGA_CMD_DEFINE_GMRFB gmr=%x offset=%x bytesPerLine=%x bpp=%d color depth=%d\n", pCmd->ptr.gmrId, pCmd->ptr.offset, pCmd->bytesPerLine, pCmd->format.s.bitsPerPixel, pCmd->format.s.colorDepth));
3314 pSVGAState->GMRFB.ptr = pCmd->ptr;
3315 pSVGAState->GMRFB.bytesPerLine = pCmd->bytesPerLine;
3316 pSVGAState->GMRFB.format = pCmd->format;
3317 break;
3318 }
3319
3320 case SVGA_CMD_BLIT_GMRFB_TO_SCREEN:
3321 {
3322 uint32_t width, height;
3323 SVGAFifoCmdBlitGMRFBToScreen *pCmd;
3324 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdBlitGMRFBToScreen, sizeof(*pCmd));
3325 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdBlitGmrFbToScreen);
3326
3327 Log(("vmsvgaFIFOLoop: SVGA_CMD_BLIT_GMRFB_TO_SCREEN src=(%d,%d) dest id=%d (%d,%d)(%d,%d)\n", pCmd->srcOrigin.x, pCmd->srcOrigin.y, pCmd->destScreenId, pCmd->destRect.left, pCmd->destRect.top, pCmd->destRect.right, pCmd->destRect.bottom));
3328
3329 /** @todo Support GMRFB.format.s.bitsPerPixel != pThis->svga.uBpp */
3330 AssertBreak(pSVGAState->GMRFB.format.s.bitsPerPixel == pThis->svga.uBpp);
3331 AssertBreak(pCmd->destScreenId == 0);
3332
3333 if (pCmd->destRect.left < 0)
3334 pCmd->destRect.left = 0;
3335 if (pCmd->destRect.top < 0)
3336 pCmd->destRect.top = 0;
3337 if (pCmd->destRect.right < 0)
3338 pCmd->destRect.right = 0;
3339 if (pCmd->destRect.bottom < 0)
3340 pCmd->destRect.bottom = 0;
3341
3342 width = pCmd->destRect.right - pCmd->destRect.left;
3343 height = pCmd->destRect.bottom - pCmd->destRect.top;
3344
3345 if ( width == 0
3346 || height == 0)
3347 break; /* Nothing to do. */
3348
3349 /* Clip to screen dimensions. */
3350 if (width > pThis->svga.uWidth)
3351 width = pThis->svga.uWidth;
3352 if (height > pThis->svga.uHeight)
3353 height = pThis->svga.uHeight;
3354
3355 unsigned offsetSource = (pCmd->srcOrigin.x * pSVGAState->GMRFB.format.s.bitsPerPixel) / 8 + pSVGAState->GMRFB.bytesPerLine * pCmd->srcOrigin.y;
3356 unsigned offsetDest = (pCmd->destRect.left * RT_ALIGN(pThis->svga.uBpp, 8)) / 8 + pThis->svga.cbScanline * pCmd->destRect.top;
3357 unsigned cbCopyWidth = (width * RT_ALIGN(pThis->svga.uBpp, 8)) / 8;
3358
3359 AssertBreak(offsetDest < pThis->vram_size);
3360
3361 rc = vmsvgaGMRTransfer(pThis, SVGA3D_WRITE_HOST_VRAM, pThis->CTX_SUFF(vram_ptr) + offsetDest, pThis->svga.cbScanline, pSVGAState->GMRFB.ptr, offsetSource, pSVGAState->GMRFB.bytesPerLine, cbCopyWidth, height);
3362 AssertRC(rc);
3363 vgaR3UpdateDisplay(pThis, pCmd->destRect.left, pCmd->destRect.top, pCmd->destRect.right - pCmd->destRect.left, pCmd->destRect.bottom - pCmd->destRect.top);
3364 break;
3365 }
3366
3367 case SVGA_CMD_BLIT_SCREEN_TO_GMRFB:
3368 {
3369 SVGAFifoCmdBlitScreenToGMRFB *pCmd;
3370 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdBlitScreenToGMRFB, sizeof(*pCmd));
3371 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdBlitScreentoGmrFb);
3372
3373 /* Note! This can fetch 3d render results as well!! */
3374 Log(("vmsvgaFIFOLoop: SVGA_CMD_BLIT_SCREEN_TO_GMRFB dest=(%d,%d) src id=%d (%d,%d)(%d,%d)\n", pCmd->destOrigin.x, pCmd->destOrigin.y, pCmd->srcScreenId, pCmd->srcRect.left, pCmd->srcRect.top, pCmd->srcRect.right, pCmd->srcRect.bottom));
3375 AssertFailed();
3376 break;
3377 }
3378# endif // VBOX_WITH_VMSVGA3D
3379 case SVGA_CMD_ANNOTATION_FILL:
3380 {
3381 SVGAFifoCmdAnnotationFill *pCmd;
3382 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdAnnotationFill, sizeof(*pCmd));
3383 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdAnnotationFill);
3384
3385 Log(("vmsvgaFIFOLoop: SVGA_CMD_ANNOTATION_FILL red=%x green=%x blue=%x\n", pCmd->color.s.r, pCmd->color.s.g, pCmd->color.s.b));
3386 pSVGAState->colorAnnotation = pCmd->color;
3387 break;
3388 }
3389
3390 case SVGA_CMD_ANNOTATION_COPY:
3391 {
3392 SVGAFifoCmdAnnotationCopy *pCmd;
3393 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdAnnotationCopy, sizeof(*pCmd));
3394 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdAnnotationCopy);
3395
3396 Log(("vmsvgaFIFOLoop: SVGA_CMD_ANNOTATION_COPY\n"));
3397 AssertFailed();
3398 break;
3399 }
3400
3401 /** @todo SVGA_CMD_RECT_COPY - see with ubuntu */
3402
3403 default:
3404# ifdef VBOX_WITH_VMSVGA3D
3405 if ( (int)enmCmdId >= SVGA_3D_CMD_BASE
3406 && (int)enmCmdId < SVGA_3D_CMD_MAX)
3407 {
3408 /* All 3d commands start with a common header, which defines the size of the command. */
3409 SVGA3dCmdHeader *pHdr;
3410 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pHdr, SVGA3dCmdHeader, sizeof(*pHdr));
3411 AssertBreak(pHdr->size < VMSVGA_FIFO_SIZE);
3412 uint32_t cbCmd = sizeof(SVGA3dCmdHeader) + pHdr->size;
3413 VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pHdr, SVGA3dCmdHeader, cbCmd);
3414
3415/**
3416 * Check that the 3D command has at least a_cbMin of payload bytes after the
3417 * header. Will break out of the switch if it doesn't.
3418 */
3419# define VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(a_cbMin) \
3420 AssertMsgBreak((a_cbMin) <= pHdr->size, ("size=%#x a_cbMin=%#zx\n", pHdr->size, (size_t)(a_cbMin)))
3421 switch ((int)enmCmdId)
3422 {
3423 case SVGA_3D_CMD_SURFACE_DEFINE:
3424 {
3425 uint32_t cMipLevels;
3426 SVGA3dCmdDefineSurface *pCmd = (SVGA3dCmdDefineSurface *)(pHdr + 1);
3427 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3428 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSurfaceDefine);
3429
3430 cMipLevels = (pHdr->size - sizeof(*pCmd)) / sizeof(SVGA3dSize);
3431 rc = vmsvga3dSurfaceDefine(pThis, pCmd->sid, (uint32_t)pCmd->surfaceFlags, pCmd->format, pCmd->face, 0,
3432 SVGA3D_TEX_FILTER_NONE, cMipLevels, (SVGA3dSize *)(pCmd + 1));
3433# ifdef DEBUG_GMR_ACCESS
3434 VMR3ReqCallWaitU(PDMDevHlpGetUVM(pThis->pDevInsR3), VMCPUID_ANY, (PFNRT)vmsvgaResetGMRHandlers, 1, pThis);
3435# endif
3436 break;
3437 }
3438
3439 case SVGA_3D_CMD_SURFACE_DEFINE_V2:
3440 {
3441 uint32_t cMipLevels;
3442 SVGA3dCmdDefineSurface_v2 *pCmd = (SVGA3dCmdDefineSurface_v2 *)(pHdr + 1);
3443 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3444 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSurfaceDefineV2);
3445
3446 cMipLevels = (pHdr->size - sizeof(*pCmd)) / sizeof(SVGA3dSize);
3447 rc = vmsvga3dSurfaceDefine(pThis, pCmd->sid, pCmd->surfaceFlags, pCmd->format, pCmd->face,
3448 pCmd->multisampleCount, pCmd->autogenFilter,
3449 cMipLevels, (SVGA3dSize *)(pCmd + 1));
3450 break;
3451 }
3452
3453 case SVGA_3D_CMD_SURFACE_DESTROY:
3454 {
3455 SVGA3dCmdDestroySurface *pCmd = (SVGA3dCmdDestroySurface *)(pHdr + 1);
3456 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3457 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSurfaceDestroy);
3458 rc = vmsvga3dSurfaceDestroy(pThis, pCmd->sid);
3459 break;
3460 }
3461
3462 case SVGA_3D_CMD_SURFACE_COPY:
3463 {
3464 uint32_t cCopyBoxes;
3465 SVGA3dCmdSurfaceCopy *pCmd = (SVGA3dCmdSurfaceCopy *)(pHdr + 1);
3466 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3467 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSurfaceCopy);
3468
3469 cCopyBoxes = (pHdr->size - sizeof(pCmd)) / sizeof(SVGA3dCopyBox);
3470 rc = vmsvga3dSurfaceCopy(pThis, pCmd->dest, pCmd->src, cCopyBoxes, (SVGA3dCopyBox *)(pCmd + 1));
3471 break;
3472 }
3473
3474 case SVGA_3D_CMD_SURFACE_STRETCHBLT:
3475 {
3476 SVGA3dCmdSurfaceStretchBlt *pCmd = (SVGA3dCmdSurfaceStretchBlt *)(pHdr + 1);
3477 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3478 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSurfaceStretchBlt);
3479
3480 rc = vmsvga3dSurfaceStretchBlt(pThis, &pCmd->dest, &pCmd->boxDest, &pCmd->src, &pCmd->boxSrc, pCmd->mode);
3481 break;
3482 }
3483
3484 case SVGA_3D_CMD_SURFACE_DMA:
3485 {
3486 uint32_t cCopyBoxes;
3487 SVGA3dCmdSurfaceDMA *pCmd = (SVGA3dCmdSurfaceDMA *)(pHdr + 1);
3488 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3489 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSurfaceDma);
3490
3491 cCopyBoxes = (pHdr->size - sizeof(*pCmd)) / sizeof(SVGA3dCopyBox);
3492 STAM_PROFILE_START(&pSVGAState->StatR3Cmd3dSurfaceDmaProf, a);
3493 rc = vmsvga3dSurfaceDMA(pThis, pCmd->guest, pCmd->host, pCmd->transfer, cCopyBoxes, (SVGA3dCopyBox *)(pCmd + 1));
3494 STAM_PROFILE_STOP(&pSVGAState->StatR3Cmd3dSurfaceDmaProf, a);
3495 break;
3496 }
3497
3498 case SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN:
3499 {
3500 uint32_t cRects;
3501 SVGA3dCmdBlitSurfaceToScreen *pCmd = (SVGA3dCmdBlitSurfaceToScreen *)(pHdr + 1);
3502 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3503 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSurfaceScreen);
3504
3505 cRects = (pHdr->size - sizeof(*pCmd)) / sizeof(SVGASignedRect);
3506 rc = vmsvga3dSurfaceBlitToScreen(pThis, pCmd->destScreenId, pCmd->destRect, pCmd->srcImage, pCmd->srcRect, cRects, (SVGASignedRect *)(pCmd + 1));
3507 break;
3508 }
3509
3510 case SVGA_3D_CMD_CONTEXT_DEFINE:
3511 {
3512 SVGA3dCmdDefineContext *pCmd = (SVGA3dCmdDefineContext *)(pHdr + 1);
3513 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3514 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dContextDefine);
3515
3516 rc = vmsvga3dContextDefine(pThis, pCmd->cid);
3517 break;
3518 }
3519
3520 case SVGA_3D_CMD_CONTEXT_DESTROY:
3521 {
3522 SVGA3dCmdDestroyContext *pCmd = (SVGA3dCmdDestroyContext *)(pHdr + 1);
3523 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3524 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dContextDestroy);
3525
3526 rc = vmsvga3dContextDestroy(pThis, pCmd->cid);
3527 break;
3528 }
3529
3530 case SVGA_3D_CMD_SETTRANSFORM:
3531 {
3532 SVGA3dCmdSetTransform *pCmd = (SVGA3dCmdSetTransform *)(pHdr + 1);
3533 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3534 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSetTransform);
3535
3536 rc = vmsvga3dSetTransform(pThis, pCmd->cid, pCmd->type, pCmd->matrix);
3537 break;
3538 }
3539
3540 case SVGA_3D_CMD_SETZRANGE:
3541 {
3542 SVGA3dCmdSetZRange *pCmd = (SVGA3dCmdSetZRange *)(pHdr + 1);
3543 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3544 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSetZRange);
3545
3546 rc = vmsvga3dSetZRange(pThis, pCmd->cid, pCmd->zRange);
3547 break;
3548 }
3549
3550 case SVGA_3D_CMD_SETRENDERSTATE:
3551 {
3552 uint32_t cRenderStates;
3553 SVGA3dCmdSetRenderState *pCmd = (SVGA3dCmdSetRenderState *)(pHdr + 1);
3554 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3555 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSetRenderState);
3556
3557 cRenderStates = (pHdr->size - sizeof(*pCmd)) / sizeof(SVGA3dRenderState);
3558 rc = vmsvga3dSetRenderState(pThis, pCmd->cid, cRenderStates, (SVGA3dRenderState *)(pCmd + 1));
3559 break;
3560 }
3561
3562 case SVGA_3D_CMD_SETRENDERTARGET:
3563 {
3564 SVGA3dCmdSetRenderTarget *pCmd = (SVGA3dCmdSetRenderTarget *)(pHdr + 1);
3565 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3566 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSetRenderTarget);
3567
3568 rc = vmsvga3dSetRenderTarget(pThis, pCmd->cid, pCmd->type, pCmd->target);
3569 break;
3570 }
3571
3572 case SVGA_3D_CMD_SETTEXTURESTATE:
3573 {
3574 uint32_t cTextureStates;
3575 SVGA3dCmdSetTextureState *pCmd = (SVGA3dCmdSetTextureState *)(pHdr + 1);
3576 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3577 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSetTextureState);
3578
3579 cTextureStates = (pHdr->size - sizeof(*pCmd)) / sizeof(SVGA3dTextureState);
3580 rc = vmsvga3dSetTextureState(pThis, pCmd->cid, cTextureStates, (SVGA3dTextureState *)(pCmd + 1));
3581 break;
3582 }
3583
3584 case SVGA_3D_CMD_SETMATERIAL:
3585 {
3586 SVGA3dCmdSetMaterial *pCmd = (SVGA3dCmdSetMaterial *)(pHdr + 1);
3587 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3588 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSetMaterial);
3589
3590 rc = vmsvga3dSetMaterial(pThis, pCmd->cid, pCmd->face, &pCmd->material);
3591 break;
3592 }
3593
3594 case SVGA_3D_CMD_SETLIGHTDATA:
3595 {
3596 SVGA3dCmdSetLightData *pCmd = (SVGA3dCmdSetLightData *)(pHdr + 1);
3597 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3598 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSetLightData);
3599
3600 rc = vmsvga3dSetLightData(pThis, pCmd->cid, pCmd->index, &pCmd->data);
3601 break;
3602 }
3603
3604 case SVGA_3D_CMD_SETLIGHTENABLED:
3605 {
3606 SVGA3dCmdSetLightEnabled *pCmd = (SVGA3dCmdSetLightEnabled *)(pHdr + 1);
3607 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3608 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSetLightEnable);
3609
3610 rc = vmsvga3dSetLightEnabled(pThis, pCmd->cid, pCmd->index, pCmd->enabled);
3611 break;
3612 }
3613
3614 case SVGA_3D_CMD_SETVIEWPORT:
3615 {
3616 SVGA3dCmdSetViewport *pCmd = (SVGA3dCmdSetViewport *)(pHdr + 1);
3617 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3618 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSetViewPort);
3619
3620 rc = vmsvga3dSetViewPort(pThis, pCmd->cid, &pCmd->rect);
3621 break;
3622 }
3623
3624 case SVGA_3D_CMD_SETCLIPPLANE:
3625 {
3626 SVGA3dCmdSetClipPlane *pCmd = (SVGA3dCmdSetClipPlane *)(pHdr + 1);
3627 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3628 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSetClipPlane);
3629
3630 rc = vmsvga3dSetClipPlane(pThis, pCmd->cid, pCmd->index, pCmd->plane);
3631 break;
3632 }
3633
3634 case SVGA_3D_CMD_CLEAR:
3635 {
3636 SVGA3dCmdClear *pCmd = (SVGA3dCmdClear *)(pHdr + 1);
3637 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3638 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dClear);
3639
3640 uint32_t cRects;
3641 cRects = (pHdr->size - sizeof(*pCmd)) / sizeof(SVGA3dRect);
3642 rc = vmsvga3dCommandClear(pThis, pCmd->cid, pCmd->clearFlag, pCmd->color, pCmd->depth, pCmd->stencil, cRects, (SVGA3dRect *)(pCmd + 1));
3643 break;
3644 }
3645
3646 case SVGA_3D_CMD_PRESENT:
3647 case SVGA_3D_CMD_PRESENT_READBACK: /** @todo SVGA_3D_CMD_PRESENT_READBACK isn't quite the same as present... */
3648 {
3649 SVGA3dCmdPresent *pCmd = (SVGA3dCmdPresent *)(pHdr + 1);
3650 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3651 if ((unsigned)enmCmdId == SVGA_3D_CMD_PRESENT)
3652 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dPresent);
3653 else
3654 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dPresentReadBack);
3655
3656 uint32_t cRects = (pHdr->size - sizeof(*pCmd)) / sizeof(SVGA3dCopyRect);
3657
3658 STAM_PROFILE_START(&pSVGAState->StatR3Cmd3dPresentProf, a);
3659 rc = vmsvga3dCommandPresent(pThis, pCmd->sid, cRects, (SVGA3dCopyRect *)(pCmd + 1));
3660 STAM_PROFILE_STOP(&pSVGAState->StatR3Cmd3dPresentProf, a);
3661 break;
3662 }
3663
3664 case SVGA_3D_CMD_SHADER_DEFINE:
3665 {
3666 SVGA3dCmdDefineShader *pCmd = (SVGA3dCmdDefineShader *)(pHdr + 1);
3667 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3668 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dShaderDefine);
3669
3670 uint32_t cbData = (pHdr->size - sizeof(*pCmd));
3671 rc = vmsvga3dShaderDefine(pThis, pCmd->cid, pCmd->shid, pCmd->type, cbData, (uint32_t *)(pCmd + 1));
3672 break;
3673 }
3674
3675 case SVGA_3D_CMD_SHADER_DESTROY:
3676 {
3677 SVGA3dCmdDestroyShader *pCmd = (SVGA3dCmdDestroyShader *)(pHdr + 1);
3678 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3679 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dShaderDestroy);
3680
3681 rc = vmsvga3dShaderDestroy(pThis, pCmd->cid, pCmd->shid, pCmd->type);
3682 break;
3683 }
3684
3685 case SVGA_3D_CMD_SET_SHADER:
3686 {
3687 SVGA3dCmdSetShader *pCmd = (SVGA3dCmdSetShader *)(pHdr + 1);
3688 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3689 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSetShader);
3690
3691 rc = vmsvga3dShaderSet(pThis, NULL, pCmd->cid, pCmd->type, pCmd->shid);
3692 break;
3693 }
3694
3695 case SVGA_3D_CMD_SET_SHADER_CONST:
3696 {
3697 SVGA3dCmdSetShaderConst *pCmd = (SVGA3dCmdSetShaderConst *)(pHdr + 1);
3698 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3699 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSetShaderConst);
3700
3701 uint32_t cRegisters = (pHdr->size - sizeof(*pCmd)) / sizeof(pCmd->values) + 1;
3702 rc = vmsvga3dShaderSetConst(pThis, pCmd->cid, pCmd->reg, pCmd->type, pCmd->ctype, cRegisters, pCmd->values);
3703 break;
3704 }
3705
3706 case SVGA_3D_CMD_DRAW_PRIMITIVES:
3707 {
3708 SVGA3dCmdDrawPrimitives *pCmd = (SVGA3dCmdDrawPrimitives *)(pHdr + 1);
3709 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3710 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dDrawPrimitives);
3711
3712 uint32_t cVertexDivisor = (pHdr->size - sizeof(*pCmd) - sizeof(SVGA3dVertexDecl) * pCmd->numVertexDecls - sizeof(SVGA3dPrimitiveRange) * pCmd->numRanges);
3713 Assert(pCmd->numRanges <= SVGA3D_MAX_DRAW_PRIMITIVE_RANGES);
3714 Assert(pCmd->numVertexDecls <= SVGA3D_MAX_VERTEX_ARRAYS);
3715 Assert(!cVertexDivisor || cVertexDivisor == pCmd->numVertexDecls);
3716
3717 SVGA3dVertexDecl *pVertexDecl = (SVGA3dVertexDecl *)(pCmd + 1);
3718 SVGA3dPrimitiveRange *pNumRange = (SVGA3dPrimitiveRange *) (&pVertexDecl[pCmd->numVertexDecls]);
3719 SVGA3dVertexDivisor *pVertexDivisor = (cVertexDivisor) ? (SVGA3dVertexDivisor *)(&pNumRange[pCmd->numRanges]) : NULL;
3720
3721 STAM_PROFILE_START(&pSVGAState->StatR3Cmd3dDrawPrimitivesProf, a);
3722 rc = vmsvga3dDrawPrimitives(pThis, pCmd->cid, pCmd->numVertexDecls, pVertexDecl, pCmd->numRanges, pNumRange, cVertexDivisor, pVertexDivisor);
3723 STAM_PROFILE_STOP(&pSVGAState->StatR3Cmd3dDrawPrimitivesProf, a);
3724 break;
3725 }
3726
3727 case SVGA_3D_CMD_SETSCISSORRECT:
3728 {
3729 SVGA3dCmdSetScissorRect *pCmd = (SVGA3dCmdSetScissorRect *)(pHdr + 1);
3730 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3731 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSetScissorRect);
3732
3733 rc = vmsvga3dSetScissorRect(pThis, pCmd->cid, &pCmd->rect);
3734 break;
3735 }
3736
3737 case SVGA_3D_CMD_BEGIN_QUERY:
3738 {
3739 SVGA3dCmdBeginQuery *pCmd = (SVGA3dCmdBeginQuery *)(pHdr + 1);
3740 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3741 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dBeginQuery);
3742
3743 rc = vmsvga3dQueryBegin(pThis, pCmd->cid, pCmd->type);
3744 break;
3745 }
3746
3747 case SVGA_3D_CMD_END_QUERY:
3748 {
3749 SVGA3dCmdEndQuery *pCmd = (SVGA3dCmdEndQuery *)(pHdr + 1);
3750 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3751 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dEndQuery);
3752
3753 rc = vmsvga3dQueryEnd(pThis, pCmd->cid, pCmd->type, pCmd->guestResult);
3754 break;
3755 }
3756
3757 case SVGA_3D_CMD_WAIT_FOR_QUERY:
3758 {
3759 SVGA3dCmdWaitForQuery *pCmd = (SVGA3dCmdWaitForQuery *)(pHdr + 1);
3760 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3761 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dWaitForQuery);
3762
3763 rc = vmsvga3dQueryWait(pThis, pCmd->cid, pCmd->type, pCmd->guestResult);
3764 break;
3765 }
3766
3767 case SVGA_3D_CMD_GENERATE_MIPMAPS:
3768 {
3769 SVGA3dCmdGenerateMipmaps *pCmd = (SVGA3dCmdGenerateMipmaps *)(pHdr + 1);
3770 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3771 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dGenerateMipmaps);
3772
3773 rc = vmsvga3dGenerateMipmaps(pThis, pCmd->sid, pCmd->filter);
3774 break;
3775 }
3776
3777 case SVGA_3D_CMD_ACTIVATE_SURFACE:
3778 /* context id + surface id? */
3779 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dActivateSurface);
3780 break;
3781 case SVGA_3D_CMD_DEACTIVATE_SURFACE:
3782 /* context id + surface id? */
3783 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dDeactivateSurface);
3784 break;
3785
3786 default:
3787 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoUnkCmds);
3788 AssertMsgFailed(("enmCmdId=%d\n", enmCmdId));
3789 break;
3790 }
3791 }
3792 else
3793# endif // VBOX_WITH_VMSVGA3D
3794 {
3795 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoUnkCmds);
3796 AssertMsgFailed(("enmCmdId=%d\n", enmCmdId));
3797 }
3798 }
3799
3800 /* Go to the next slot */
3801 Assert(cbPayload + sizeof(uint32_t) <= offFifoMax - offFifoMin);
3802 offCurrentCmd += RT_ALIGN_32(cbPayload + sizeof(uint32_t), sizeof(uint32_t));
3803 if (offCurrentCmd >= offFifoMax)
3804 {
3805 offCurrentCmd -= offFifoMax - offFifoMin;
3806 Assert(offCurrentCmd >= offFifoMin);
3807 Assert(offCurrentCmd < offFifoMax);
3808 }
3809 ASMAtomicWriteU32(&pFIFO[SVGA_FIFO_STOP], offCurrentCmd);
3810 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoCommands);
3811
3812 /*
3813 * Raise IRQ if required. Must enter the critical section here
3814 * before making final decisions here, otherwise cubebench and
3815 * others may end up waiting forever.
3816 */
3817 if ( u32IrqStatus
3818 || (pThis->svga.u32IrqMask & SVGA_IRQFLAG_FIFO_PROGRESS))
3819 {
3820 int rc2 = PDMCritSectEnter(&pThis->CritSect, VERR_IGNORED);
3821 AssertRC(rc2);
3822
3823 /* FIFO progress might trigger an interrupt. */
3824 if (pThis->svga.u32IrqMask & SVGA_IRQFLAG_FIFO_PROGRESS)
3825 {
3826 Log(("vmsvgaFIFOLoop: fifo progress irq\n"));
3827 u32IrqStatus |= SVGA_IRQFLAG_FIFO_PROGRESS;
3828 }
3829
3830 /* Unmasked IRQ pending? */
3831 if (pThis->svga.u32IrqMask & u32IrqStatus)
3832 {
3833 Log(("vmsvgaFIFOLoop: Trigger interrupt with status %x\n", u32IrqStatus));
3834 ASMAtomicOrU32(&pThis->svga.u32IrqStatus, u32IrqStatus);
3835 PDMDevHlpPCISetIrq(pDevIns, 0, 1);
3836 }
3837
3838 PDMCritSectLeave(&pThis->CritSect);
3839 }
3840 }
3841
3842 /* If really done, clear the busy flag. */
3843 if (fDone)
3844 {
3845 Log(("vmsvgaFIFOLoop: emptied the FIFO next=%x stop=%x\n", pFIFO[SVGA_FIFO_NEXT_CMD], offCurrentCmd));
3846 vmsvgaFifoSetNotBusy(pThis, pSVGAState, offFifoMin);
3847 }
3848 }
3849
3850 /*
3851 * Free the bounce buffer. (There are no returns above!)
3852 */
3853 RTMemFree(pbBounceBuf);
3854
3855 return VINF_SUCCESS;
3856}
3857
3858/**
3859 * Free the specified GMR
3860 *
3861 * @param pThis VGA device instance data.
3862 * @param idGMR GMR id
3863 */
3864void vmsvgaGMRFree(PVGASTATE pThis, uint32_t idGMR)
3865{
3866 PVMSVGAR3STATE pSVGAState = pThis->svga.pSvgaR3State;
3867
3868 /* Free the old descriptor if present. */
3869 PGMR pGMR = &pSVGAState->aGMR[idGMR];
3870 if ( pGMR->numDescriptors
3871 || pGMR->paDesc /* needed till we implement SVGA_REMAP_GMR2_VIA_GMR */)
3872 {
3873# ifdef DEBUG_GMR_ACCESS
3874 VMR3ReqCallWaitU(PDMDevHlpGetUVM(pThis->pDevInsR3), VMCPUID_ANY, (PFNRT)vmsvgaDeregisterGMR, 2, pThis->pDevInsR3, idGMR);
3875# endif
3876
3877 Assert(pGMR->paDesc);
3878 RTMemFree(pGMR->paDesc);
3879 pGMR->paDesc = NULL;
3880 pGMR->numDescriptors = 0;
3881 pGMR->cbTotal = 0;
3882 pGMR->cMaxPages = 0;
3883 }
3884 Assert(!pGMR->cMaxPages);
3885 Assert(!pGMR->cbTotal);
3886}
3887
3888/**
3889 * Copy from a GMR to host memory or vice versa
3890 *
3891 * @returns VBox status code.
3892 * @param pThis VGA device instance data.
3893 * @param enmTransferType Transfer type (read/write)
3894 * @param pbDst Host destination pointer
3895 * @param cbDestPitch Destination buffer pitch
3896 * @param src GMR description
3897 * @param offSrc Source buffer offset
3898 * @param cbSrcPitch Source buffer pitch
3899 * @param cbWidth Source width in bytes
3900 * @param cHeight Source height
3901 */
3902int vmsvgaGMRTransfer(PVGASTATE pThis, const SVGA3dTransferType enmTransferType, uint8_t *pbDst, int32_t cbDestPitch,
3903 SVGAGuestPtr src, uint32_t offSrc, int32_t cbSrcPitch, uint32_t cbWidth, uint32_t cHeight)
3904{
3905 PVMSVGAR3STATE pSVGAState = pThis->svga.pSvgaR3State;
3906 PGMR pGMR;
3907 int rc;
3908 PVMSVGAGMRDESCRIPTOR pDesc;
3909 unsigned offDesc = 0;
3910
3911 Log(("vmsvgaGMRTransfer: gmr=%x offset=%x pitch=%d cbWidth=%d cHeight=%d; src offset=%d src pitch=%d\n",
3912 src.gmrId, src.offset, cbDestPitch, cbWidth, cHeight, offSrc, cbSrcPitch));
3913 Assert(cbWidth && cHeight);
3914
3915 /* Shortcut for the framebuffer. */
3916 if (src.gmrId == SVGA_GMR_FRAMEBUFFER)
3917 {
3918 offSrc += src.offset;
3919 AssertMsgReturn(src.offset < pThis->vram_size,
3920 ("src.offset=%#x offSrc=%#x cbSrcPitch=%#x cHeight=%#x cbWidth=%#x vram_size=%#x\n",
3921 src.offset, offSrc, cbSrcPitch, cHeight, cbWidth, pThis->vram_size),
3922 VERR_INVALID_PARAMETER);
3923 AssertMsgReturn(offSrc + cbSrcPitch * (cHeight - 1) + cbWidth <= pThis->vram_size,
3924 ("src.offset=%#x offSrc=%#x cbSrcPitch=%#x cHeight=%#x cbWidth=%#x vram_size=%#x\n",
3925 src.offset, offSrc, cbSrcPitch, cHeight, cbWidth, pThis->vram_size),
3926 VERR_INVALID_PARAMETER);
3927
3928 uint8_t *pSrc = pThis->CTX_SUFF(vram_ptr) + offSrc;
3929
3930 if (enmTransferType == SVGA3D_READ_HOST_VRAM)
3931 {
3932 /* switch src & dest */
3933 uint8_t *pTemp = pbDst;
3934 int32_t cbTempPitch = cbDestPitch;
3935
3936 pbDst = pSrc;
3937 pSrc = pTemp;
3938
3939 cbDestPitch = cbSrcPitch;
3940 cbSrcPitch = cbTempPitch;
3941 }
3942
3943 if ( pThis->svga.cbScanline == (uint32_t)cbDestPitch
3944 && cbWidth == (uint32_t)cbDestPitch
3945 && cbSrcPitch == cbDestPitch)
3946 {
3947 memcpy(pbDst, pSrc, cbWidth * cHeight);
3948 }
3949 else
3950 {
3951 for(uint32_t i = 0; i < cHeight; i++)
3952 {
3953 memcpy(pbDst, pSrc, cbWidth);
3954
3955 pbDst += cbDestPitch;
3956 pSrc += cbSrcPitch;
3957 }
3958 }
3959 return VINF_SUCCESS;
3960 }
3961
3962 AssertReturn(src.gmrId < VMSVGA_MAX_GMR_IDS, VERR_INVALID_PARAMETER);
3963 pGMR = &pSVGAState->aGMR[src.gmrId];
3964 pDesc = pGMR->paDesc;
3965
3966 offSrc += src.offset;
3967 AssertMsgReturn(src.offset < pGMR->cbTotal,
3968 ("src.gmrId=%#x src.offset=%#x offSrc=%#x cbSrcPitch=%#x cHeight=%#x cbWidth=%#x cbTotal=%#x\n",
3969 src.gmrId, src.offset, offSrc, cbSrcPitch, cHeight, cbWidth, pGMR->cbTotal),
3970 VERR_INVALID_PARAMETER);
3971 AssertMsgReturn(offSrc + cbSrcPitch * (cHeight - 1) + cbWidth <= pGMR->cbTotal,
3972 ("src.gmrId=%#x src.offset=%#x offSrc=%#x cbSrcPitch=%#x cHeight=%#x cbWidth=%#x cbTotal=%#x\n",
3973 src.gmrId, src.offset, offSrc, cbSrcPitch, cHeight, cbWidth, pGMR->cbTotal),
3974 VERR_INVALID_PARAMETER);
3975
3976 for (uint32_t i = 0; i < cHeight; i++)
3977 {
3978 uint32_t cbCurrentWidth = cbWidth;
3979 uint32_t offCurrent = offSrc;
3980 uint8_t *pCurrentDest = pbDst;
3981
3982 /* Find the right descriptor */
3983 while (offDesc + pDesc->numPages * PAGE_SIZE <= offCurrent)
3984 {
3985 offDesc += pDesc->numPages * PAGE_SIZE;
3986 AssertReturn(offDesc < pGMR->cbTotal, VERR_INTERNAL_ERROR); /* overflow protection */
3987 pDesc++;
3988 }
3989
3990 while (cbCurrentWidth)
3991 {
3992 uint32_t cbToCopy;
3993
3994 if (offCurrent + cbCurrentWidth <= offDesc + pDesc->numPages * PAGE_SIZE)
3995 {
3996 cbToCopy = cbCurrentWidth;
3997 }
3998 else
3999 {
4000 cbToCopy = (offDesc + pDesc->numPages * PAGE_SIZE - offCurrent);
4001 AssertReturn(cbToCopy <= cbCurrentWidth, VERR_INVALID_PARAMETER);
4002 }
4003
4004 LogFlow(("vmsvgaGMRTransfer: %s phys=%RGp\n", (enmTransferType == SVGA3D_WRITE_HOST_VRAM) ? "READ" : "WRITE", pDesc->GCPhys + offCurrent - offDesc));
4005
4006 if (enmTransferType == SVGA3D_WRITE_HOST_VRAM)
4007 rc = PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), pDesc->GCPhys + offCurrent - offDesc, pCurrentDest, cbToCopy);
4008 else
4009 rc = PDMDevHlpPhysWrite(pThis->CTX_SUFF(pDevIns), pDesc->GCPhys + offCurrent - offDesc, pCurrentDest, cbToCopy);
4010 AssertRCBreak(rc);
4011
4012 cbCurrentWidth -= cbToCopy;
4013 offCurrent += cbToCopy;
4014 pCurrentDest += cbToCopy;
4015
4016 /* Go to the next descriptor if there's anything left. */
4017 if (cbCurrentWidth)
4018 {
4019 offDesc += pDesc->numPages * PAGE_SIZE;
4020 pDesc++;
4021 }
4022 }
4023
4024 offSrc += cbSrcPitch;
4025 pbDst += cbDestPitch;
4026 }
4027
4028 return VINF_SUCCESS;
4029}
4030
4031/**
4032 * Unblock the FIFO I/O thread so it can respond to a state change.
4033 *
4034 * @returns VBox status code.
4035 * @param pDevIns The VGA device instance.
4036 * @param pThread The send thread.
4037 */
4038static DECLCALLBACK(int) vmsvgaFIFOLoopWakeUp(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
4039{
4040 RT_NOREF(pDevIns);
4041 PVGASTATE pThis = (PVGASTATE)pThread->pvUser;
4042 Log(("vmsvgaFIFOLoopWakeUp\n"));
4043 return SUPSemEventSignal(pThis->svga.pSupDrvSession, pThis->svga.FIFORequestSem);
4044}
4045
4046/**
4047 * Enables or disables dirty page tracking for the framebuffer
4048 *
4049 * @param pThis VGA device instance data.
4050 * @param fTraces Enable/disable traces
4051 */
4052static void vmsvgaSetTraces(PVGASTATE pThis, bool fTraces)
4053{
4054 if ( (!pThis->svga.fConfigured || !pThis->svga.fEnabled)
4055 && !fTraces)
4056 {
4057 //Assert(pThis->svga.fTraces);
4058 Log(("vmsvgaSetTraces: *not* allowed to disable dirty page tracking when the device is in legacy mode.\n"));
4059 return;
4060 }
4061
4062 pThis->svga.fTraces = fTraces;
4063 if (pThis->svga.fTraces)
4064 {
4065 unsigned cbFrameBuffer = pThis->vram_size;
4066
4067 Log(("vmsvgaSetTraces: enable dirty page handling for the frame buffer only (%x bytes)\n", 0));
4068 if (pThis->svga.uHeight != VMSVGA_VAL_UNINITIALIZED)
4069 {
4070#ifndef DEBUG_bird /* BB-10.3.1 triggers this as it initializes everything to zero. Better just ignore it. */
4071 Assert(pThis->svga.cbScanline);
4072#endif
4073 /* Hardware enabled; return real framebuffer size .*/
4074 cbFrameBuffer = (uint32_t)pThis->svga.uHeight * pThis->svga.cbScanline;
4075 cbFrameBuffer = RT_ALIGN(cbFrameBuffer, PAGE_SIZE);
4076 }
4077
4078 if (!pThis->svga.fVRAMTracking)
4079 {
4080 Log(("vmsvgaSetTraces: enable frame buffer dirty page tracking. (%x bytes; vram %x)\n", cbFrameBuffer, pThis->vram_size));
4081 vgaR3RegisterVRAMHandler(pThis, cbFrameBuffer);
4082 pThis->svga.fVRAMTracking = true;
4083 }
4084 }
4085 else
4086 {
4087 if (pThis->svga.fVRAMTracking)
4088 {
4089 Log(("vmsvgaSetTraces: disable frame buffer dirty page tracking\n"));
4090 vgaR3UnregisterVRAMHandler(pThis);
4091 pThis->svga.fVRAMTracking = false;
4092 }
4093 }
4094}
4095
4096/**
4097 * @callback_method_impl{FNPCIIOREGIONMAP}
4098 */
4099DECLCALLBACK(int) vmsvgaR3IORegionMap(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion,
4100 RTGCPHYS GCPhysAddress, RTGCPHYS cb, PCIADDRESSSPACE enmType)
4101{
4102 int rc;
4103 PVGASTATE pThis = PDMINS_2_DATA(pDevIns, PVGASTATE);
4104
4105 Log(("vgasvgaR3IORegionMap: iRegion=%d GCPhysAddress=%RGp cb=%RGp enmType=%d\n", iRegion, GCPhysAddress, cb, enmType));
4106 if (enmType == PCI_ADDRESS_SPACE_IO)
4107 {
4108 AssertReturn(iRegion == 0, VERR_INTERNAL_ERROR);
4109 rc = PDMDevHlpIOPortRegister(pDevIns, (RTIOPORT)GCPhysAddress, cb, 0,
4110 vmsvgaIOWrite, vmsvgaIORead, NULL /* OutStr */, NULL /* InStr */, "VMSVGA");
4111 if (RT_FAILURE(rc))
4112 return rc;
4113 if (pThis->fR0Enabled)
4114 {
4115 rc = PDMDevHlpIOPortRegisterR0(pDevIns, (RTIOPORT)GCPhysAddress, cb, 0,
4116 "vmsvgaIOWrite", "vmsvgaIORead", NULL, NULL, "VMSVGA");
4117 if (RT_FAILURE(rc))
4118 return rc;
4119 }
4120 if (pThis->fGCEnabled)
4121 {
4122 rc = PDMDevHlpIOPortRegisterRC(pDevIns, (RTIOPORT)GCPhysAddress, cb, 0,
4123 "vmsvgaIOWrite", "vmsvgaIORead", NULL, NULL, "VMSVGA");
4124 if (RT_FAILURE(rc))
4125 return rc;
4126 }
4127
4128 pThis->svga.BasePort = GCPhysAddress;
4129 Log(("vmsvgaR3IORegionMap: base port = %x\n", pThis->svga.BasePort));
4130 }
4131 else
4132 {
4133 AssertReturn(iRegion == 2 && enmType == PCI_ADDRESS_SPACE_MEM, VERR_INTERNAL_ERROR);
4134 if (GCPhysAddress != NIL_RTGCPHYS)
4135 {
4136 /*
4137 * Mapping the FIFO RAM.
4138 */
4139 rc = PDMDevHlpMMIOExMap(pDevIns, pPciDev, iRegion, GCPhysAddress);
4140 AssertRC(rc);
4141
4142# ifdef DEBUG_FIFO_ACCESS
4143 if (RT_SUCCESS(rc))
4144 {
4145 rc = PGMHandlerPhysicalRegister(PDMDevHlpGetVM(pDevIns), GCPhysAddress, GCPhysAddress + (VMSVGA_FIFO_SIZE - 1),
4146 pThis->svga.hFifoAccessHandlerType, pThis, NIL_RTR0PTR, NIL_RTRCPTR,
4147 "VMSVGA FIFO");
4148 AssertRC(rc);
4149 }
4150# endif
4151 if (RT_SUCCESS(rc))
4152 {
4153 pThis->svga.GCPhysFIFO = GCPhysAddress;
4154 Log(("vmsvgaR3IORegionMap: FIFO address = %RGp\n", GCPhysAddress));
4155 }
4156 }
4157 else
4158 {
4159 Assert(pThis->svga.GCPhysFIFO);
4160# ifdef DEBUG_FIFO_ACCESS
4161 rc = PGMHandlerPhysicalDeregister(PDMDevHlpGetVM(pDevIns), pThis->svga.GCPhysFIFO);
4162 AssertRC(rc);
4163# endif
4164 pThis->svga.GCPhysFIFO = 0;
4165 }
4166
4167 }
4168 return VINF_SUCCESS;
4169}
4170
4171# ifdef VBOX_WITH_VMSVGA3D
4172
4173/**
4174 * Used by vmsvga3dInfoSurfaceWorker to make the FIFO thread to save one or all
4175 * surfaces to VMSVGA3DMIPMAPLEVEL::pSurfaceData heap buffers.
4176 *
4177 * @param pThis The VGA device instance data.
4178 * @param sid Either UINT32_MAX or the ID of a specific
4179 * surface. If UINT32_MAX is used, all surfaces
4180 * are processed.
4181 */
4182void vmsvga3dSurfaceUpdateHeapBuffersOnFifoThread(PVGASTATE pThis, uint32_t sid)
4183{
4184 vmsvgaR3RunExtCmdOnFifoThread(pThis, VMSVGA_FIFO_EXTCMD_UPDATE_SURFACE_HEAP_BUFFERS, (void *)(uintptr_t)sid,
4185 sid == UINT32_MAX ? 10 * RT_MS_1SEC : RT_MS_1MIN);
4186}
4187
4188
4189/**
4190 * @callback_method_impl{FNDBGFHANDLERDEV, "vmsvga3dsfc"}
4191 */
4192DECLCALLBACK(void) vmsvgaR3Info3dSurface(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
4193{
4194 /* There might be a specific context ID at the start of the
4195 arguments, if not show all contexts. */
4196 uint32_t cid = UINT32_MAX;
4197 if (pszArgs)
4198 pszArgs = RTStrStripL(pszArgs);
4199 if (pszArgs && RT_C_IS_DIGIT(*pszArgs))
4200 cid = RTStrToUInt32(pszArgs);
4201
4202 /* Verbose or terse display, we default to verbose. */
4203 bool fVerbose = true;
4204 if (RTStrIStr(pszArgs, "terse"))
4205 fVerbose = false;
4206
4207 /* The size of the ascii art (x direction, y is 3/4 of x). */
4208 uint32_t cxAscii = 80;
4209 if (RTStrIStr(pszArgs, "gigantic"))
4210 cxAscii = 300;
4211 else if (RTStrIStr(pszArgs, "huge"))
4212 cxAscii = 180;
4213 else if (RTStrIStr(pszArgs, "big"))
4214 cxAscii = 132;
4215 else if (RTStrIStr(pszArgs, "normal"))
4216 cxAscii = 80;
4217 else if (RTStrIStr(pszArgs, "medium"))
4218 cxAscii = 64;
4219 else if (RTStrIStr(pszArgs, "small"))
4220 cxAscii = 48;
4221 else if (RTStrIStr(pszArgs, "tiny"))
4222 cxAscii = 24;
4223
4224 /* Y invert the image when producing the ASCII art. */
4225 bool fInvY = false;
4226 if (RTStrIStr(pszArgs, "invy"))
4227 fInvY = true;
4228
4229 vmsvga3dInfoSurfaceWorker(PDMINS_2_DATA(pDevIns, PVGASTATE), pHlp, cid, fVerbose, cxAscii, fInvY);
4230}
4231
4232
4233/**
4234 * @callback_method_impl{FNDBGFHANDLERDEV, "vmsvga3dctx"}
4235 */
4236DECLCALLBACK(void) vmsvgaR3Info3dContext(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
4237{
4238 /* There might be a specific surface ID at the start of the
4239 arguments, if not show all contexts. */
4240 uint32_t sid = UINT32_MAX;
4241 if (pszArgs)
4242 pszArgs = RTStrStripL(pszArgs);
4243 if (pszArgs && RT_C_IS_DIGIT(*pszArgs))
4244 sid = RTStrToUInt32(pszArgs);
4245
4246 /* Verbose or terse display, we default to verbose. */
4247 bool fVerbose = true;
4248 if (RTStrIStr(pszArgs, "terse"))
4249 fVerbose = false;
4250
4251 vmsvga3dInfoContextWorker(PDMINS_2_DATA(pDevIns, PVGASTATE), pHlp, sid, fVerbose);
4252}
4253
4254# endif /* VBOX_WITH_VMSVGA3D */
4255
4256/**
4257 * @callback_method_impl{FNDBGFHANDLERDEV, "vmsvga"}
4258 */
4259static DECLCALLBACK(void) vmsvgaR3Info(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
4260{
4261 RT_NOREF(pszArgs);
4262 PVGASTATE pThis = PDMINS_2_DATA(pDevIns, PVGASTATE);
4263 PVMSVGAR3STATE pSVGAState = pThis->svga.pSvgaR3State;
4264
4265 pHlp->pfnPrintf(pHlp, "Extension enabled: %RTbool\n", pThis->svga.fEnabled);
4266 pHlp->pfnPrintf(pHlp, "Configured: %RTbool\n", pThis->svga.fConfigured);
4267 pHlp->pfnPrintf(pHlp, "Base I/O port: %#x\n", pThis->svga.BasePort);
4268 pHlp->pfnPrintf(pHlp, "FIFO address: %RGp\n", pThis->svga.GCPhysFIFO);
4269 pHlp->pfnPrintf(pHlp, "FIFO size: %u (%#x)\n", pThis->svga.cbFIFO, pThis->svga.cbFIFO);
4270 pHlp->pfnPrintf(pHlp, "FIFO external cmd: %#x\n", pThis->svga.u8FIFOExtCommand);
4271 pHlp->pfnPrintf(pHlp, "FIFO extcmd wakeup: %u\n", pThis->svga.fFifoExtCommandWakeup);
4272 pHlp->pfnPrintf(pHlp, "Busy: %#x\n", pThis->svga.fBusy);
4273 pHlp->pfnPrintf(pHlp, "Traces: %RTbool (effective: %RTbool)\n", pThis->svga.fTraces, pThis->svga.fVRAMTracking);
4274 pHlp->pfnPrintf(pHlp, "Guest ID: %#x (%d)\n", pThis->svga.u32GuestId, pThis->svga.u32GuestId);
4275 pHlp->pfnPrintf(pHlp, "IRQ status: %#x\n", pThis->svga.u32IrqStatus);
4276 pHlp->pfnPrintf(pHlp, "IRQ mask: %#x\n", pThis->svga.u32IrqMask);
4277 pHlp->pfnPrintf(pHlp, "Pitch lock: %#x\n", pThis->svga.u32PitchLock);
4278 pHlp->pfnPrintf(pHlp, "Current GMR ID: %#x\n", pThis->svga.u32CurrentGMRId);
4279 pHlp->pfnPrintf(pHlp, "Capabilites reg: %#x\n", pThis->svga.u32RegCaps);
4280 pHlp->pfnPrintf(pHlp, "Index reg: %#x\n", pThis->svga.u32IndexReg);
4281 pHlp->pfnPrintf(pHlp, "Action flags: %#x\n", pThis->svga.u32ActionFlags);
4282 pHlp->pfnPrintf(pHlp, "Max display size: %ux%u\n", pThis->svga.u32MaxWidth, pThis->svga.u32MaxHeight);
4283 pHlp->pfnPrintf(pHlp, "Display size: %ux%u %ubpp\n", pThis->svga.uWidth, pThis->svga.uHeight, pThis->svga.uBpp);
4284 pHlp->pfnPrintf(pHlp, "Scanline: %u (%#x)\n", pThis->svga.cbScanline, pThis->svga.cbScanline);
4285 pHlp->pfnPrintf(pHlp, "Viewport position: %ux%u\n", pThis->svga.viewport.x, pThis->svga.viewport.y);
4286 pHlp->pfnPrintf(pHlp, "Viewport size: %ux%u\n", pThis->svga.viewport.cx, pThis->svga.viewport.cy);
4287
4288 pHlp->pfnPrintf(pHlp, "Cursor active: %RTbool\n", pSVGAState->Cursor.fActive);
4289 pHlp->pfnPrintf(pHlp, "Cursor hotspot: %ux%u\n", pSVGAState->Cursor.xHotspot, pSVGAState->Cursor.yHotspot);
4290 pHlp->pfnPrintf(pHlp, "Cursor size: %ux%u\n", pSVGAState->Cursor.width, pSVGAState->Cursor.height);
4291 pHlp->pfnPrintf(pHlp, "Cursor byte size: %u (%#x)\n", pSVGAState->Cursor.cbData, pSVGAState->Cursor.cbData);
4292
4293# ifdef VBOX_WITH_VMSVGA3D
4294 pHlp->pfnPrintf(pHlp, "3D enabled: %RTbool\n", pThis->svga.f3DEnabled);
4295 pHlp->pfnPrintf(pHlp, "Host windows ID: %#RX64\n", pThis->svga.u64HostWindowId);
4296 if (pThis->svga.u64HostWindowId != 0)
4297 vmsvga3dInfoHostWindow(pHlp, pThis->svga.u64HostWindowId);
4298# endif
4299}
4300
4301
4302/**
4303 * @copydoc FNSSMDEVLOADEXEC
4304 */
4305int vmsvgaLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
4306{
4307 RT_NOREF(uVersion, uPass);
4308 PVGASTATE pThis = PDMINS_2_DATA(pDevIns, PVGASTATE);
4309 PVMSVGAR3STATE pSVGAState = pThis->svga.pSvgaR3State;
4310 int rc;
4311
4312 /* Load our part of the VGAState */
4313 rc = SSMR3GetStructEx(pSSM, &pThis->svga, sizeof(pThis->svga), 0, g_aVGAStateSVGAFields, NULL);
4314 AssertRCReturn(rc, rc);
4315
4316 /* Load the framebuffer backup. */
4317 rc = SSMR3GetMem(pSSM, pThis->svga.pFrameBufferBackup, VMSVGA_FRAMEBUFFER_BACKUP_SIZE);
4318 AssertRCReturn(rc, rc);
4319
4320 /* Load the VMSVGA state. */
4321 rc = SSMR3GetStructEx(pSSM, pSVGAState, sizeof(*pSVGAState), 0, g_aVMSVGAR3STATEFields, NULL);
4322 AssertRCReturn(rc, rc);
4323
4324 /* Load the active cursor bitmaps. */
4325 if (pSVGAState->Cursor.fActive)
4326 {
4327 pSVGAState->Cursor.pData = RTMemAlloc(pSVGAState->Cursor.cbData);
4328 AssertReturn(pSVGAState->Cursor.pData, VERR_NO_MEMORY);
4329
4330 rc = SSMR3GetMem(pSSM, pSVGAState->Cursor.pData, pSVGAState->Cursor.cbData);
4331 AssertRCReturn(rc, rc);
4332 }
4333
4334 /* Load the GMR state */
4335 for (uint32_t i = 0; i < RT_ELEMENTS(pSVGAState->aGMR); i++)
4336 {
4337 PGMR pGMR = &pSVGAState->aGMR[i];
4338
4339 rc = SSMR3GetStructEx(pSSM, pGMR, sizeof(*pGMR), 0, g_aGMRFields, NULL);
4340 AssertRCReturn(rc, rc);
4341
4342 if (pGMR->numDescriptors)
4343 {
4344 Assert(pGMR->cMaxPages || pGMR->cbTotal);
4345 pGMR->paDesc = (PVMSVGAGMRDESCRIPTOR)RTMemAllocZ(pGMR->numDescriptors * sizeof(VMSVGAGMRDESCRIPTOR));
4346 AssertReturn(pGMR->paDesc, VERR_NO_MEMORY);
4347
4348 for (uint32_t j = 0; j < pGMR->numDescriptors; j++)
4349 {
4350 rc = SSMR3GetStructEx(pSSM, &pGMR->paDesc[j], sizeof(pGMR->paDesc[j]), 0, g_aVMSVGAGMRDESCRIPTORFields, NULL);
4351 AssertRCReturn(rc, rc);
4352 }
4353 }
4354 }
4355
4356# ifdef VBOX_WITH_VMSVGA3D
4357 if (pThis->svga.f3DEnabled)
4358 {
4359# 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. */
4360 vmsvga3dPowerOn(pThis);
4361# endif
4362
4363 VMSVGA_STATE_LOAD LoadState;
4364 LoadState.pSSM = pSSM;
4365 LoadState.uVersion = uVersion;
4366 LoadState.uPass = uPass;
4367 rc = vmsvgaR3RunExtCmdOnFifoThread(pThis, VMSVGA_FIFO_EXTCMD_LOADSTATE, &LoadState, RT_INDEFINITE_WAIT);
4368 AssertLogRelRCReturn(rc, rc);
4369 }
4370# endif
4371
4372 return VINF_SUCCESS;
4373}
4374
4375/**
4376 * Reinit the video mode after the state has been loaded.
4377 */
4378int vmsvgaLoadDone(PPDMDEVINS pDevIns)
4379{
4380 PVGASTATE pThis = PDMINS_2_DATA(pDevIns, PVGASTATE);
4381 PVMSVGAR3STATE pSVGAState = pThis->svga.pSvgaR3State;
4382
4383 pThis->last_bpp = VMSVGA_VAL_UNINITIALIZED; /* force mode reset */
4384 vmsvgaChangeMode(pThis);
4385
4386 /* Set the active cursor. */
4387 if (pSVGAState->Cursor.fActive)
4388 {
4389 int rc;
4390
4391 rc = pThis->pDrv->pfnVBVAMousePointerShape(pThis->pDrv,
4392 true,
4393 true,
4394 pSVGAState->Cursor.xHotspot,
4395 pSVGAState->Cursor.yHotspot,
4396 pSVGAState->Cursor.width,
4397 pSVGAState->Cursor.height,
4398 pSVGAState->Cursor.pData);
4399 AssertRC(rc);
4400 }
4401 return VINF_SUCCESS;
4402}
4403
4404/**
4405 * @copydoc FNSSMDEVSAVEEXEC
4406 */
4407int vmsvgaSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
4408{
4409 PVGASTATE pThis = PDMINS_2_DATA(pDevIns, PVGASTATE);
4410 PVMSVGAR3STATE pSVGAState = pThis->svga.pSvgaR3State;
4411 int rc;
4412
4413 /* Save our part of the VGAState */
4414 rc = SSMR3PutStructEx(pSSM, &pThis->svga, sizeof(pThis->svga), 0, g_aVGAStateSVGAFields, NULL);
4415 AssertLogRelRCReturn(rc, rc);
4416
4417 /* Save the framebuffer backup. */
4418 rc = SSMR3PutMem(pSSM, pThis->svga.pFrameBufferBackup, VMSVGA_FRAMEBUFFER_BACKUP_SIZE);
4419 AssertLogRelRCReturn(rc, rc);
4420
4421 /* Save the VMSVGA state. */
4422 rc = SSMR3PutStructEx(pSSM, pSVGAState, sizeof(*pSVGAState), 0, g_aVMSVGAR3STATEFields, NULL);
4423 AssertLogRelRCReturn(rc, rc);
4424
4425 /* Save the active cursor bitmaps. */
4426 if (pSVGAState->Cursor.fActive)
4427 {
4428 rc = SSMR3PutMem(pSSM, pSVGAState->Cursor.pData, pSVGAState->Cursor.cbData);
4429 AssertLogRelRCReturn(rc, rc);
4430 }
4431
4432 /* Save the GMR state */
4433 for (uint32_t i = 0; i < RT_ELEMENTS(pSVGAState->aGMR); i++)
4434 {
4435 rc = SSMR3PutStructEx(pSSM, &pSVGAState->aGMR[i], sizeof(pSVGAState->aGMR[i]), 0, g_aGMRFields, NULL);
4436 AssertLogRelRCReturn(rc, rc);
4437
4438 for (uint32_t j = 0; j < pSVGAState->aGMR[i].numDescriptors; j++)
4439 {
4440 rc = SSMR3PutStructEx(pSSM, &pSVGAState->aGMR[i].paDesc[j], sizeof(pSVGAState->aGMR[i].paDesc[j]), 0, g_aVMSVGAGMRDESCRIPTORFields, NULL);
4441 AssertLogRelRCReturn(rc, rc);
4442 }
4443 }
4444
4445# ifdef VBOX_WITH_VMSVGA3D
4446 /*
4447 * Must save the 3d state in the FIFO thread.
4448 */
4449 if (pThis->svga.f3DEnabled)
4450 {
4451 rc = vmsvgaR3RunExtCmdOnFifoThread(pThis, VMSVGA_FIFO_EXTCMD_SAVESTATE, pSSM, RT_INDEFINITE_WAIT);
4452 AssertLogRelRCReturn(rc, rc);
4453 }
4454# endif
4455 return VINF_SUCCESS;
4456}
4457
4458/**
4459 * Resets the SVGA hardware state
4460 *
4461 * @returns VBox status code.
4462 * @param pDevIns The device instance.
4463 */
4464int vmsvgaReset(PPDMDEVINS pDevIns)
4465{
4466 PVGASTATE pThis = PDMINS_2_DATA(pDevIns, PVGASTATE);
4467 PVMSVGAR3STATE pSVGAState = pThis->svga.pSvgaR3State;
4468
4469 /* Reset before init? */
4470 if (!pSVGAState)
4471 return VINF_SUCCESS;
4472
4473 Log(("vmsvgaReset\n"));
4474
4475
4476 /* Reset the FIFO processing as well as the 3d state (if we have one). */
4477 pThis->svga.pFIFOR3[SVGA_FIFO_NEXT_CMD] = pThis->svga.pFIFOR3[SVGA_FIFO_STOP] = 0; /** @todo should probably let the FIFO thread do this ... */
4478 int rc = vmsvgaR3RunExtCmdOnFifoThread(pThis, VMSVGA_FIFO_EXTCMD_RESET, NULL /*pvParam*/, 10000 /*ms*/);
4479
4480 /* Reset other stuff. */
4481 pThis->svga.cScratchRegion = VMSVGA_SCRATCH_SIZE;
4482 RT_ZERO(pThis->svga.au32ScratchRegion);
4483 RT_ZERO(*pThis->svga.pSvgaR3State);
4484 RT_BZERO(pThis->svga.pFrameBufferBackup, VMSVGA_FRAMEBUFFER_BACKUP_SIZE);
4485
4486 /* Register caps. */
4487 pThis->svga.u32RegCaps = SVGA_CAP_GMR | SVGA_CAP_GMR2 | SVGA_CAP_CURSOR | SVGA_CAP_CURSOR_BYPASS_2 | SVGA_CAP_EXTENDED_FIFO | SVGA_CAP_IRQMASK | SVGA_CAP_PITCHLOCK | SVGA_CAP_TRACES | SVGA_CAP_SCREEN_OBJECT_2 | SVGA_CAP_ALPHA_CURSOR;
4488# ifdef VBOX_WITH_VMSVGA3D
4489 pThis->svga.u32RegCaps |= SVGA_CAP_3D;
4490# endif
4491
4492 /* Setup FIFO capabilities. */
4493 pThis->svga.pFIFOR3[SVGA_FIFO_CAPABILITIES] = SVGA_FIFO_CAP_FENCE | SVGA_FIFO_CAP_CURSOR_BYPASS_3 | SVGA_FIFO_CAP_GMR2 | SVGA_FIFO_CAP_3D_HWVERSION_REVISED | SVGA_FIFO_CAP_SCREEN_OBJECT_2;
4494
4495 /* Valid with SVGA_FIFO_CAP_SCREEN_OBJECT_2 */
4496 pThis->svga.pFIFOR3[SVGA_FIFO_CURSOR_SCREEN_ID] = SVGA_ID_INVALID;
4497
4498 /* VRAM tracking is enabled by default during bootup. */
4499 pThis->svga.fVRAMTracking = true;
4500 pThis->svga.fEnabled = false;
4501
4502 /* Invalidate current settings. */
4503 pThis->svga.uWidth = VMSVGA_VAL_UNINITIALIZED;
4504 pThis->svga.uHeight = VMSVGA_VAL_UNINITIALIZED;
4505 pThis->svga.uBpp = VMSVGA_VAL_UNINITIALIZED;
4506 pThis->svga.cbScanline = 0;
4507
4508 return rc;
4509}
4510
4511/**
4512 * Cleans up the SVGA hardware state
4513 *
4514 * @returns VBox status code.
4515 * @param pDevIns The device instance.
4516 */
4517int vmsvgaDestruct(PPDMDEVINS pDevIns)
4518{
4519 PVGASTATE pThis = PDMINS_2_DATA(pDevIns, PVGASTATE);
4520
4521 /*
4522 * Ask the FIFO thread to terminate the 3d state and then terminate it.
4523 */
4524 if (pThis->svga.pFIFOIOThread)
4525 {
4526 int rc = vmsvgaR3RunExtCmdOnFifoThread(pThis, VMSVGA_FIFO_EXTCMD_TERMINATE, NULL /*pvParam*/, 30000 /*ms*/);
4527 AssertLogRelRC(rc);
4528
4529 rc = PDMR3ThreadDestroy(pThis->svga.pFIFOIOThread, NULL);
4530 AssertLogRelRC(rc);
4531 pThis->svga.pFIFOIOThread = NULL;
4532 }
4533
4534 /*
4535 * Destroy the special SVGA state.
4536 */
4537 PVMSVGAR3STATE pSVGAState = pThis->svga.pSvgaR3State;
4538 if (pSVGAState)
4539 {
4540# ifndef VMSVGA_USE_EMT_HALT_CODE
4541 if (pSVGAState->hBusyDelayedEmts != NIL_RTSEMEVENTMULTI)
4542 {
4543 RTSemEventMultiDestroy(pSVGAState->hBusyDelayedEmts);
4544 pSVGAState->hBusyDelayedEmts = NIL_RTSEMEVENT;
4545 }
4546# endif
4547 if (pSVGAState->Cursor.fActive)
4548 RTMemFree(pSVGAState->Cursor.pData);
4549
4550 for (unsigned i = 0; i < RT_ELEMENTS(pSVGAState->aGMR); i++)
4551 if (pSVGAState->aGMR[i].paDesc)
4552 RTMemFree(pSVGAState->aGMR[i].paDesc);
4553
4554 RTMemFree(pSVGAState);
4555 pThis->svga.pSvgaR3State = NULL;
4556 }
4557
4558 /*
4559 * Free our resources residing in the VGA state.
4560 */
4561 if (pThis->svga.pFrameBufferBackup)
4562 RTMemFree(pThis->svga.pFrameBufferBackup);
4563 if (pThis->svga.FIFOExtCmdSem != NIL_RTSEMEVENT)
4564 {
4565 RTSemEventDestroy(pThis->svga.FIFOExtCmdSem);
4566 pThis->svga.FIFOExtCmdSem = NIL_RTSEMEVENT;
4567 }
4568 if (pThis->svga.FIFORequestSem != NIL_SUPSEMEVENT)
4569 {
4570 SUPSemEventClose(pThis->svga.pSupDrvSession, pThis->svga.FIFORequestSem);
4571 pThis->svga.FIFORequestSem = NIL_SUPSEMEVENT;
4572 }
4573
4574 return VINF_SUCCESS;
4575}
4576
4577/**
4578 * Initialize the SVGA hardware state
4579 *
4580 * @returns VBox status code.
4581 * @param pDevIns The device instance.
4582 */
4583int vmsvgaInit(PPDMDEVINS pDevIns)
4584{
4585 PVGASTATE pThis = PDMINS_2_DATA(pDevIns, PVGASTATE);
4586 PVMSVGAR3STATE pSVGAState;
4587 PVM pVM = PDMDevHlpGetVM(pDevIns);
4588 int rc;
4589
4590 pThis->svga.cScratchRegion = VMSVGA_SCRATCH_SIZE;
4591 memset(pThis->svga.au32ScratchRegion, 0, sizeof(pThis->svga.au32ScratchRegion));
4592
4593 pThis->svga.pSvgaR3State = (PVMSVGAR3STATE)RTMemAllocZ(sizeof(VMSVGAR3STATE));
4594 AssertReturn(pThis->svga.pSvgaR3State, VERR_NO_MEMORY);
4595 pSVGAState = pThis->svga.pSvgaR3State;
4596
4597 /* Necessary for creating a backup of the text mode frame buffer when switching into svga mode. */
4598 pThis->svga.pFrameBufferBackup = RTMemAllocZ(VMSVGA_FRAMEBUFFER_BACKUP_SIZE);
4599 AssertReturn(pThis->svga.pFrameBufferBackup, VERR_NO_MEMORY);
4600
4601 /* Create event semaphore. */
4602 pThis->svga.pSupDrvSession = PDMDevHlpGetSupDrvSession(pDevIns);
4603
4604 rc = SUPSemEventCreate(pThis->svga.pSupDrvSession, &pThis->svga.FIFORequestSem);
4605 if (RT_FAILURE(rc))
4606 {
4607 Log(("%s: Failed to create event semaphore for FIFO handling.\n", __FUNCTION__));
4608 return rc;
4609 }
4610
4611 /* Create event semaphore. */
4612 rc = RTSemEventCreate(&pThis->svga.FIFOExtCmdSem);
4613 if (RT_FAILURE(rc))
4614 {
4615 Log(("%s: Failed to create event semaphore for external fifo cmd handling.\n", __FUNCTION__));
4616 return rc;
4617 }
4618
4619# ifndef VMSVGA_USE_EMT_HALT_CODE
4620 /* Create semaphore for delaying EMTs wait for the FIFO to stop being busy. */
4621 rc = RTSemEventMultiCreate(&pSVGAState->hBusyDelayedEmts);
4622 AssertRCReturn(rc, rc);
4623# endif
4624
4625 /* Register caps. */
4626 pThis->svga.u32RegCaps = SVGA_CAP_GMR | SVGA_CAP_GMR2 | SVGA_CAP_CURSOR | SVGA_CAP_CURSOR_BYPASS_2 | SVGA_CAP_EXTENDED_FIFO | SVGA_CAP_IRQMASK | SVGA_CAP_PITCHLOCK | SVGA_CAP_TRACES | SVGA_CAP_SCREEN_OBJECT_2 | SVGA_CAP_ALPHA_CURSOR;
4627# ifdef VBOX_WITH_VMSVGA3D
4628 pThis->svga.u32RegCaps |= SVGA_CAP_3D;
4629# endif
4630
4631 /* Setup FIFO capabilities. */
4632 pThis->svga.pFIFOR3[SVGA_FIFO_CAPABILITIES] = SVGA_FIFO_CAP_FENCE | SVGA_FIFO_CAP_CURSOR_BYPASS_3 | SVGA_FIFO_CAP_GMR2 | SVGA_FIFO_CAP_3D_HWVERSION_REVISED | SVGA_FIFO_CAP_SCREEN_OBJECT_2;
4633
4634 /* Valid with SVGA_FIFO_CAP_SCREEN_OBJECT_2 */
4635 pThis->svga.pFIFOR3[SVGA_FIFO_CURSOR_SCREEN_ID] = SVGA_ID_INVALID;
4636
4637 pThis->svga.pFIFOR3[SVGA_FIFO_3D_HWVERSION] = pThis->svga.pFIFOR3[SVGA_FIFO_3D_HWVERSION_REVISED] = 0; /* no 3d available. */
4638# ifdef VBOX_WITH_VMSVGA3D
4639 if (pThis->svga.f3DEnabled)
4640 {
4641 rc = vmsvga3dInit(pThis);
4642 if (RT_FAILURE(rc))
4643 {
4644 LogRel(("VMSVGA3d: 3D support disabled! (vmsvga3dInit -> %Rrc)\n", rc));
4645 pThis->svga.f3DEnabled = false;
4646 }
4647 }
4648# endif
4649 /* VRAM tracking is enabled by default during bootup. */
4650 pThis->svga.fVRAMTracking = true;
4651
4652 /* Invalidate current settings. */
4653 pThis->svga.uWidth = VMSVGA_VAL_UNINITIALIZED;
4654 pThis->svga.uHeight = VMSVGA_VAL_UNINITIALIZED;
4655 pThis->svga.uBpp = VMSVGA_VAL_UNINITIALIZED;
4656 pThis->svga.cbScanline = 0;
4657
4658 pThis->svga.u32MaxWidth = VBE_DISPI_MAX_YRES;
4659 pThis->svga.u32MaxHeight = VBE_DISPI_MAX_XRES;
4660 while (pThis->svga.u32MaxWidth * pThis->svga.u32MaxHeight * 4 /* 32 bpp */ > pThis->vram_size)
4661 {
4662 pThis->svga.u32MaxWidth -= 256;
4663 pThis->svga.u32MaxHeight -= 256;
4664 }
4665 Log(("VMSVGA: Maximum size (%d,%d)\n", pThis->svga.u32MaxWidth, pThis->svga.u32MaxHeight));
4666
4667# ifdef DEBUG_GMR_ACCESS
4668 /* Register the GMR access handler type. */
4669 rc = PGMR3HandlerPhysicalTypeRegister(PDMDevHlpGetVM(pThis->pDevInsR3), PGMPHYSHANDLERKIND_WRITE,
4670 vmsvgaR3GMRAccessHandler,
4671 NULL, NULL, NULL,
4672 NULL, NULL, NULL,
4673 "VMSVGA GMR", &pThis->svga.hGmrAccessHandlerType);
4674 AssertRCReturn(rc, rc);
4675# endif
4676# ifdef DEBUG_FIFO_ACCESS
4677 rc = PGMR3HandlerPhysicalTypeRegister(PDMDevHlpGetVM(pThis->pDevInsR3), PGMPHYSHANDLERKIND_ALL,
4678 vmsvgaR3FIFOAccessHandler,
4679 NULL, NULL, NULL,
4680 NULL, NULL, NULL,
4681 "VMSVGA FIFO", &pThis->svga.hFifoAccessHandlerType);
4682 AssertRCReturn(rc, rc);
4683#endif
4684
4685 /* Create the async IO thread. */
4686 rc = PDMDevHlpThreadCreate(pDevIns, &pThis->svga.pFIFOIOThread, pThis, vmsvgaFIFOLoop, vmsvgaFIFOLoopWakeUp, 0,
4687 RTTHREADTYPE_IO, "VMSVGA FIFO");
4688 if (RT_FAILURE(rc))
4689 {
4690 AssertMsgFailed(("%s: Async IO Thread creation for FIFO handling failed rc=%d\n", __FUNCTION__, rc));
4691 return rc;
4692 }
4693
4694 /*
4695 * Statistics.
4696 */
4697 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dActivateSurface, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dActivateSurface", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_ACTIVATE_SURFACE");
4698 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dBeginQuery, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dBeginQuery", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_BEGIN_QUERY");
4699 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dClear, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dClear", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_CLEAR");
4700 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dContextDefine, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dContextDefine", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_CONTEXT_DEFINE");
4701 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dContextDestroy, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dContextDestroy", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_CONTEXT_DESTROY");
4702 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dDeactivateSurface, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dDeactivateSurface", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_DEACTIVATE_SURFACE");
4703 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dDrawPrimitives, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dDrawPrimitives", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_DRAW_PRIMITIVES");
4704 STAM_REG(pVM, &pSVGAState->StatR3Cmd3dDrawPrimitivesProf, STAMTYPE_PROFILE, "/Devices/VMSVGA/Cmd/3dDrawPrimitivesProf", STAMUNIT_TICKS_PER_CALL, "Profiling of SVGA_3D_CMD_DRAW_PRIMITIVES.");
4705 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dEndQuery, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dEndQuery", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_END_QUERY");
4706 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dGenerateMipmaps, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dGenerateMipmaps", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_GENERATE_MIPMAPS");
4707 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dPresent, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dPresent", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_PRESENT");
4708 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dPresentReadBack, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dPresentReadBack", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_PRESENT_READBACK");
4709 STAM_REG(pVM, &pSVGAState->StatR3Cmd3dPresentProf, STAMTYPE_PROFILE, "/Devices/VMSVGA/Cmd/3dPresentProfBoth", STAMUNIT_TICKS_PER_CALL, "Profiling of SVGA_3D_CMD_PRESENT and SVGA_3D_CMD_PRESENT_READBACK.");
4710 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSetClipPlane, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSetClipPlane", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SETCLIPPLANE");
4711 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSetLightData, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSetLightData", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SETLIGHTDATA");
4712 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSetLightEnable, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSetLightEnable", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SETLIGHTENABLE");
4713 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSetMaterial, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSetMaterial", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SETMATERIAL");
4714 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSetRenderState, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSetRenderState", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SETRENDERSTATE");
4715 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSetRenderTarget, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSetRenderTarget", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SETRENDERTARGET");
4716 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSetScissorRect, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSetScissorRect", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SETSCISSORRECT");
4717 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSetShader, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSetShader", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SET_SHADER");
4718 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSetShaderConst, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSetShaderConst", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SET_SHADER_CONST");
4719 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSetTextureState, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSetTextureState", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SETTEXTURESTATE");
4720 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSetTransform, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSetTransform", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SETTRANSFORM");
4721 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSetViewPort, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSetViewPort", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SETVIEWPORT");
4722 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSetZRange, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSetZRange", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SETZRANGE");
4723 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dShaderDefine, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dShaderDefine", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SHADER_DEFINE");
4724 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dShaderDestroy, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dShaderDestroy", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SHADER_DESTROY");
4725 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSurfaceCopy, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSurfaceCopy", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SURFACE_COPY");
4726 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSurfaceDefine, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSurfaceDefine", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SURFACE_DEFINE");
4727 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSurfaceDefineV2, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSurfaceDefineV2", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SURFACE_DEFINE_V2");
4728 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSurfaceDestroy, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSurfaceDestroy", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SURFACE_DESTROY");
4729 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSurfaceDma, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSurfaceDma", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SURFACE_DMA");
4730 STAM_REG(pVM, &pSVGAState->StatR3Cmd3dSurfaceDmaProf, STAMTYPE_PROFILE, "/Devices/VMSVGA/Cmd/3dSurfaceDmaProf", STAMUNIT_TICKS_PER_CALL, "Profiling of SVGA_3D_CMD_SURFACE_DMA.");
4731 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSurfaceScreen, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSurfaceScreen", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SURFACE_SCREEN");
4732 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSurfaceStretchBlt, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSurfaceStretchBlt", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SURFACE_STRETCHBLT");
4733 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dWaitForQuery, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dWaitForQuery", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_WAIT_FOR_QUERY");
4734 STAM_REL_REG(pVM, &pSVGAState->StatR3CmdAnnotationCopy, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/AnnotationCopy", STAMUNIT_OCCURENCES, "SVGA_CMD_ANNOTATION_COPY");
4735 STAM_REL_REG(pVM, &pSVGAState->StatR3CmdAnnotationFill, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/AnnotationFill", STAMUNIT_OCCURENCES, "SVGA_CMD_ANNOTATION_FILL");
4736 STAM_REL_REG(pVM, &pSVGAState->StatR3CmdBlitGmrFbToScreen, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/BlitGmrFbToScreen", STAMUNIT_OCCURENCES, "SVGA_CMD_BLIT_GMRFB_TO_SCREEN");
4737 STAM_REL_REG(pVM, &pSVGAState->StatR3CmdBlitScreentoGmrFb, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/BlitScreentoGmrFb", STAMUNIT_OCCURENCES, "SVGA_CMD_BLIT_SCREEN_TO_GMRFB");
4738 STAM_REL_REG(pVM, &pSVGAState->StatR3CmdDefineAlphaCursor, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/DefineAlphaCursor", STAMUNIT_OCCURENCES, "SVGA_CMD_DEFINE_ALPHA_CURSOR");
4739 STAM_REL_REG(pVM, &pSVGAState->StatR3CmdDefineCursor, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/DefineCursor", STAMUNIT_OCCURENCES, "SVGA_CMD_DEFINE_CURSOR");
4740 STAM_REL_REG(pVM, &pSVGAState->StatR3CmdDefineGmr2, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/DefineGmr2", STAMUNIT_OCCURENCES, "SVGA_CMD_DEFINE_GMR2");
4741 STAM_REL_REG(pVM, &pSVGAState->StatR3CmdDefineGmr2Free, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/DefineGmr2/Free", STAMUNIT_OCCURENCES, "Number of SVGA_CMD_DEFINE_GMR2 commands that only frees.");
4742 STAM_REL_REG(pVM, &pSVGAState->StatR3CmdDefineGmr2Modify, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/DefineGmr2/Modify", STAMUNIT_OCCURENCES, "Number of SVGA_CMD_DEFINE_GMR2 commands that redefines a non-free GMR.");
4743 STAM_REL_REG(pVM, &pSVGAState->StatR3CmdDefineGmrFb, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/DefineGmrFb", STAMUNIT_OCCURENCES, "SVGA_CMD_DEFINE_GMRFB");
4744 STAM_REL_REG(pVM, &pSVGAState->StatR3CmdDefineScreen, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/DefineScreen", STAMUNIT_OCCURENCES, "SVGA_CMD_DEFINE_SCREEN");
4745 STAM_REL_REG(pVM, &pSVGAState->StatR3CmdDestroyScreen, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/DestroyScreen", STAMUNIT_OCCURENCES, "SVGA_CMD_DESTROY_SCREEN");
4746 STAM_REL_REG(pVM, &pSVGAState->StatR3CmdEscape, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/Escape", STAMUNIT_OCCURENCES, "SVGA_CMD_ESCAPE");
4747 STAM_REL_REG(pVM, &pSVGAState->StatR3CmdFence, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/Fence", STAMUNIT_OCCURENCES, "SVGA_CMD_FENCE");
4748 STAM_REL_REG(pVM, &pSVGAState->StatR3CmdInvalidCmd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/InvalidCmd", STAMUNIT_OCCURENCES, "SVGA_CMD_INVALID_CMD");
4749 STAM_REL_REG(pVM, &pSVGAState->StatR3CmdRemapGmr2, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/RemapGmr2", STAMUNIT_OCCURENCES, "SVGA_CMD_REMAP_GMR2.");
4750 STAM_REL_REG(pVM, &pSVGAState->StatR3CmdRemapGmr2Modify, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/RemapGmr2/Modify", STAMUNIT_OCCURENCES, "Number of SVGA_CMD_REMAP_GMR2 commands that modifies rather than complete the definition of a GMR.");
4751 STAM_REL_REG(pVM, &pSVGAState->StatR3CmdUpdate, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/Update", STAMUNIT_OCCURENCES, "SVGA_CMD_UPATE");
4752 STAM_REL_REG(pVM, &pSVGAState->StatR3CmdUpdateVerbose, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/UpdateVerbose", STAMUNIT_OCCURENCES, "SVGA_CMD_UPDATE_VERBOSE");
4753
4754 STAM_REL_REG(pVM, &pSVGAState->StatR3RegConfigDoneWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/ConfigDoneWrite", STAMUNIT_OCCURENCES, "SVGA_REG_CONFIG_DONE writes");
4755 STAM_REL_REG(pVM, &pSVGAState->StatR3RegGmrDescriptorWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/GmrDescriptorWrite", STAMUNIT_OCCURENCES, "SVGA_REG_GMR_DESCRIPTOR writes");
4756 STAM_REL_REG(pVM, &pSVGAState->StatR3RegGmrDescriptorWrErrors, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/GmrDescriptorWrite/Errors", STAMUNIT_OCCURENCES, "Number of erroneous SVGA_REG_GMR_DESCRIPTOR commands.");
4757 STAM_REL_REG(pVM, &pSVGAState->StatR3RegGmrDescriptorWrFree, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/GmrDescriptorWrite/Free", STAMUNIT_OCCURENCES, "Number of SVGA_REG_GMR_DESCRIPTOR commands only freeing the GMR.");
4758 STAM_REL_REG(pVM, &pThis->svga.StatRegBitsPerPixelWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/BitsPerPixelWrite", STAMUNIT_OCCURENCES, "SVGA_REG_BITS_PER_PIXEL writes.");
4759 STAM_REL_REG(pVM, &pThis->svga.StatRegBusyWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/BusyWrite", STAMUNIT_OCCURENCES, "SVGA_REG_BUSY writes.");
4760 STAM_REL_REG(pVM, &pThis->svga.StatRegCursorXxxxWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/CursorXxxxWrite", STAMUNIT_OCCURENCES, "SVGA_REG_CURSOR_XXXX writes.");
4761 STAM_REL_REG(pVM, &pThis->svga.StatRegDepthWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/DepthWrite", STAMUNIT_OCCURENCES, "SVGA_REG_DEPTH writes.");
4762 STAM_REL_REG(pVM, &pThis->svga.StatRegDisplayHeightWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/DisplayHeightWrite", STAMUNIT_OCCURENCES, "SVGA_REG_DISPLAY_HEIGHT writes.");
4763 STAM_REL_REG(pVM, &pThis->svga.StatRegDisplayIdWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/DisplayIdWrite", STAMUNIT_OCCURENCES, "SVGA_REG_DISPLAY_ID writes.");
4764 STAM_REL_REG(pVM, &pThis->svga.StatRegDisplayIsPrimaryWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/DisplayIsPrimaryWrite", STAMUNIT_OCCURENCES, "SVGA_REG_DISPLAY_IS_PRIMARY writes.");
4765 STAM_REL_REG(pVM, &pThis->svga.StatRegDisplayPositionXWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/DisplayPositionXWrite", STAMUNIT_OCCURENCES, "SVGA_REG_DISPLAY_POSITION_X writes.");
4766 STAM_REL_REG(pVM, &pThis->svga.StatRegDisplayPositionYWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/DisplayPositionYWrite", STAMUNIT_OCCURENCES, "SVGA_REG_DISPLAY_POSITION_Y writes.");
4767 STAM_REL_REG(pVM, &pThis->svga.StatRegDisplayWidthWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/DisplayWidthWrite", STAMUNIT_OCCURENCES, "SVGA_REG_DISPLAY_WIDTH writes.");
4768 STAM_REL_REG(pVM, &pThis->svga.StatRegEnableWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/EnableWrite", STAMUNIT_OCCURENCES, "SVGA_REG_ENABLE writes.");
4769 STAM_REL_REG(pVM, &pThis->svga.StatRegGmrIdWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/GmrIdWrite", STAMUNIT_OCCURENCES, "SVGA_REG_GMR_ID writes.");
4770 STAM_REL_REG(pVM, &pThis->svga.StatRegGuestIdWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/GuestIdWrite", STAMUNIT_OCCURENCES, "SVGA_REG_GUEST_ID writes.");
4771 STAM_REL_REG(pVM, &pThis->svga.StatRegHeightWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/HeightWrite", STAMUNIT_OCCURENCES, "SVGA_REG_HEIGHT writes.");
4772 STAM_REL_REG(pVM, &pThis->svga.StatRegIdWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/IdWrite", STAMUNIT_OCCURENCES, "SVGA_REG_ID writes.");
4773 STAM_REL_REG(pVM, &pThis->svga.StatRegIrqMaskWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/IrqMaskWrite", STAMUNIT_OCCURENCES, "SVGA_REG_IRQMASK writes.");
4774 STAM_REL_REG(pVM, &pThis->svga.StatRegNumDisplaysWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/NumDisplaysWrite", STAMUNIT_OCCURENCES, "SVGA_REG_NUM_DISPLAYS writes.");
4775 STAM_REL_REG(pVM, &pThis->svga.StatRegNumGuestDisplaysWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/NumGuestDisplaysWrite", STAMUNIT_OCCURENCES, "SVGA_REG_NUM_GUEST_DISPLAYS writes.");
4776 STAM_REL_REG(pVM, &pThis->svga.StatRegPaletteWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/PaletteWrite", STAMUNIT_OCCURENCES, "SVGA_PALETTE_XXXX writes.");
4777 STAM_REL_REG(pVM, &pThis->svga.StatRegPitchLockWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/PitchLockWrite", STAMUNIT_OCCURENCES, "SVGA_REG_PITCHLOCK writes.");
4778 STAM_REL_REG(pVM, &pThis->svga.StatRegPseudoColorWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/PseudoColorWrite", STAMUNIT_OCCURENCES, "SVGA_REG_PSEUDOCOLOR writes.");
4779 STAM_REL_REG(pVM, &pThis->svga.StatRegReadOnlyWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/ReadOnlyWrite", STAMUNIT_OCCURENCES, "Read-only SVGA_REG_XXXX writes.");
4780 STAM_REL_REG(pVM, &pThis->svga.StatRegScratchWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/ScratchWrite", STAMUNIT_OCCURENCES, "SVGA_REG_SCRATCH_XXXX writes.");
4781 STAM_REL_REG(pVM, &pThis->svga.StatRegSyncWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/SyncWrite", STAMUNIT_OCCURENCES, "SVGA_REG_SYNC writes.");
4782 STAM_REL_REG(pVM, &pThis->svga.StatRegTopWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/TopWrite", STAMUNIT_OCCURENCES, "SVGA_REG_TOP writes.");
4783 STAM_REL_REG(pVM, &pThis->svga.StatRegTracesWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/TracesWrite", STAMUNIT_OCCURENCES, "SVGA_REG_TRACES writes.");
4784 STAM_REL_REG(pVM, &pThis->svga.StatRegUnknownWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/UnknownWrite", STAMUNIT_OCCURENCES, "Writes to unknown register.");
4785 STAM_REL_REG(pVM, &pThis->svga.StatRegWidthWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/WidthWrite", STAMUNIT_OCCURENCES, "SVGA_REG_WIDTH writes.");
4786
4787 STAM_REL_REG(pVM, &pThis->svga.StatRegBitsPerPixelRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/BitsPerPixelRead", STAMUNIT_OCCURENCES, "SVGA_REG_BITS_PER_PIXEL reads.");
4788 STAM_REL_REG(pVM, &pThis->svga.StatRegBlueMaskRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/BlueMaskRead", STAMUNIT_OCCURENCES, "SVGA_REG_BLUE_MASK reads.");
4789 STAM_REL_REG(pVM, &pThis->svga.StatRegBusyRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/BusyRead", STAMUNIT_OCCURENCES, "SVGA_REG_BUSY reads.");
4790 STAM_REL_REG(pVM, &pThis->svga.StatRegBytesPerLineRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/BytesPerLineRead", STAMUNIT_OCCURENCES, "SVGA_REG_BYTES_PER_LINE reads.");
4791 STAM_REL_REG(pVM, &pThis->svga.StatRegCapabilitesRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/CapabilitesRead", STAMUNIT_OCCURENCES, "SVGA_REG_CAPABILITIES reads.");
4792 STAM_REL_REG(pVM, &pThis->svga.StatRegConfigDoneRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/ConfigDoneRead", STAMUNIT_OCCURENCES, "SVGA_REG_CONFIG_DONE reads.");
4793 STAM_REL_REG(pVM, &pThis->svga.StatRegCursorXxxxRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/CursorXxxxRead", STAMUNIT_OCCURENCES, "SVGA_REG_CURSOR_XXXX reads.");
4794 STAM_REL_REG(pVM, &pThis->svga.StatRegDepthRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/DepthRead", STAMUNIT_OCCURENCES, "SVGA_REG_DEPTH reads.");
4795 STAM_REL_REG(pVM, &pThis->svga.StatRegDisplayHeightRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/DisplayHeightRead", STAMUNIT_OCCURENCES, "SVGA_REG_DISPLAY_HEIGHT reads.");
4796 STAM_REL_REG(pVM, &pThis->svga.StatRegDisplayIdRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/DisplayIdRead", STAMUNIT_OCCURENCES, "SVGA_REG_DISPLAY_ID reads.");
4797 STAM_REL_REG(pVM, &pThis->svga.StatRegDisplayIsPrimaryRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/DisplayIsPrimaryRead", STAMUNIT_OCCURENCES, "SVGA_REG_DISPLAY_IS_PRIMARY reads.");
4798 STAM_REL_REG(pVM, &pThis->svga.StatRegDisplayPositionXRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/DisplayPositionXRead", STAMUNIT_OCCURENCES, "SVGA_REG_DISPLAY_POSITION_X reads.");
4799 STAM_REL_REG(pVM, &pThis->svga.StatRegDisplayPositionYRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/DisplayPositionYRead", STAMUNIT_OCCURENCES, "SVGA_REG_DISPLAY_POSITION_Y reads.");
4800 STAM_REL_REG(pVM, &pThis->svga.StatRegDisplayWidthRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/DisplayWidthRead", STAMUNIT_OCCURENCES, "SVGA_REG_DISPLAY_WIDTH reads.");
4801 STAM_REL_REG(pVM, &pThis->svga.StatRegEnableRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/EnableRead", STAMUNIT_OCCURENCES, "SVGA_REG_ENABLE reads.");
4802 STAM_REL_REG(pVM, &pThis->svga.StatRegFbOffsetRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/FbOffsetRead", STAMUNIT_OCCURENCES, "SVGA_REG_FB_OFFSET reads.");
4803 STAM_REL_REG(pVM, &pThis->svga.StatRegFbSizeRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/FbSizeRead", STAMUNIT_OCCURENCES, "SVGA_REG_FB_SIZE reads.");
4804 STAM_REL_REG(pVM, &pThis->svga.StatRegFbStartRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/FbStartRead", STAMUNIT_OCCURENCES, "SVGA_REG_FB_START reads.");
4805 STAM_REL_REG(pVM, &pThis->svga.StatRegGmrIdRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/GmrIdRead", STAMUNIT_OCCURENCES, "SVGA_REG_GMR_ID reads.");
4806 STAM_REL_REG(pVM, &pThis->svga.StatRegGmrMaxDescriptorLengthRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/GmrMaxDescriptorLengthRead", STAMUNIT_OCCURENCES, "SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH reads.");
4807 STAM_REL_REG(pVM, &pThis->svga.StatRegGmrMaxIdsRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/GmrMaxIdsRead", STAMUNIT_OCCURENCES, "SVGA_REG_GMR_MAX_IDS reads.");
4808 STAM_REL_REG(pVM, &pThis->svga.StatRegGmrsMaxPagesRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/GmrsMaxPagesRead", STAMUNIT_OCCURENCES, "SVGA_REG_GMRS_MAX_PAGES reads.");
4809 STAM_REL_REG(pVM, &pThis->svga.StatRegGreenMaskRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/GreenMaskRead", STAMUNIT_OCCURENCES, "SVGA_REG_GREEN_MASK reads.");
4810 STAM_REL_REG(pVM, &pThis->svga.StatRegGuestIdRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/GuestIdRead", STAMUNIT_OCCURENCES, "SVGA_REG_GUEST_ID reads.");
4811 STAM_REL_REG(pVM, &pThis->svga.StatRegHeightRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/HeightRead", STAMUNIT_OCCURENCES, "SVGA_REG_HEIGHT reads.");
4812 STAM_REL_REG(pVM, &pThis->svga.StatRegHostBitsPerPixelRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/HostBitsPerPixelRead", STAMUNIT_OCCURENCES, "SVGA_REG_HOST_BITS_PER_PIXEL reads.");
4813 STAM_REL_REG(pVM, &pThis->svga.StatRegIdRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/IdRead", STAMUNIT_OCCURENCES, "SVGA_REG_ID reads.");
4814 STAM_REL_REG(pVM, &pThis->svga.StatRegIrqMaskRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/IrqMaskRead", STAMUNIT_OCCURENCES, "SVGA_REG_IRQ_MASK reads.");
4815 STAM_REL_REG(pVM, &pThis->svga.StatRegMaxHeightRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/MaxHeightRead", STAMUNIT_OCCURENCES, "SVGA_REG_MAX_HEIGHT reads.");
4816 STAM_REL_REG(pVM, &pThis->svga.StatRegMaxWidthRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/MaxWidthRead", STAMUNIT_OCCURENCES, "SVGA_REG_MAX_WIDTH reads.");
4817 STAM_REL_REG(pVM, &pThis->svga.StatRegMemorySizeRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/MemorySizeRead", STAMUNIT_OCCURENCES, "SVGA_REG_MEMORY_SIZE reads.");
4818 STAM_REL_REG(pVM, &pThis->svga.StatRegMemRegsRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/MemRegsRead", STAMUNIT_OCCURENCES, "SVGA_REG_MEM_REGS reads.");
4819 STAM_REL_REG(pVM, &pThis->svga.StatRegMemSizeRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/MemSizeRead", STAMUNIT_OCCURENCES, "SVGA_REG_MEM_SIZE reads.");
4820 STAM_REL_REG(pVM, &pThis->svga.StatRegMemStartRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/MemStartRead", STAMUNIT_OCCURENCES, "SVGA_REG_MEM_START reads.");
4821 STAM_REL_REG(pVM, &pThis->svga.StatRegNumDisplaysRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/NumDisplaysRead", STAMUNIT_OCCURENCES, "SVGA_REG_NUM_DISPLAYS reads.");
4822 STAM_REL_REG(pVM, &pThis->svga.StatRegNumGuestDisplaysRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/NumGuestDisplaysRead", STAMUNIT_OCCURENCES, "SVGA_REG_NUM_GUEST_DISPLAYS reads.");
4823 STAM_REL_REG(pVM, &pThis->svga.StatRegPaletteRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/PaletteRead", STAMUNIT_OCCURENCES, "SVGA_REG_PLAETTE_XXXX reads.");
4824 STAM_REL_REG(pVM, &pThis->svga.StatRegPitchLockRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/PitchLockRead", STAMUNIT_OCCURENCES, "SVGA_REG_PITCHLOCK reads.");
4825 STAM_REL_REG(pVM, &pThis->svga.StatRegPsuedoColorRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/PsuedoColorRead", STAMUNIT_OCCURENCES, "SVGA_REG_PSEUDOCOLOR reads.");
4826 STAM_REL_REG(pVM, &pThis->svga.StatRegRedMaskRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/RedMaskRead", STAMUNIT_OCCURENCES, "SVGA_REG_RED_MASK reads.");
4827 STAM_REL_REG(pVM, &pThis->svga.StatRegScratchRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/ScratchRead", STAMUNIT_OCCURENCES, "SVGA_REG_SCRATCH reads.");
4828 STAM_REL_REG(pVM, &pThis->svga.StatRegScratchSizeRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/ScratchSizeRead", STAMUNIT_OCCURENCES, "SVGA_REG_SCRATCH_SIZE reads.");
4829 STAM_REL_REG(pVM, &pThis->svga.StatRegSyncRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/SyncRead", STAMUNIT_OCCURENCES, "SVGA_REG_SYNC reads.");
4830 STAM_REL_REG(pVM, &pThis->svga.StatRegTopRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/TopRead", STAMUNIT_OCCURENCES, "SVGA_REG_TOP reads.");
4831 STAM_REL_REG(pVM, &pThis->svga.StatRegTracesRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/TracesRead", STAMUNIT_OCCURENCES, "SVGA_REG_TRACES reads.");
4832 STAM_REL_REG(pVM, &pThis->svga.StatRegUnknownRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/UnknownRead", STAMUNIT_OCCURENCES, "SVGA_REG_UNKNOWN reads.");
4833 STAM_REL_REG(pVM, &pThis->svga.StatRegVramSizeRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/VramSizeRead", STAMUNIT_OCCURENCES, "SVGA_REG_VRAM_SIZE reads.");
4834 STAM_REL_REG(pVM, &pThis->svga.StatRegWidthRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/WidthRead", STAMUNIT_OCCURENCES, "SVGA_REG_WIDTH reads.");
4835 STAM_REL_REG(pVM, &pThis->svga.StatRegWriteOnlyRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/WriteOnlyRead", STAMUNIT_OCCURENCES, "Write-only SVGA_REG_XXXX reads.");
4836
4837 STAM_REL_REG(pVM, &pSVGAState->StatBusyDelayEmts, STAMTYPE_PROFILE, "/Devices/VMSVGA/EmtDelayOnBusyFifo", STAMUNIT_TICKS_PER_CALL, "Time we've delayed EMTs because of busy FIFO thread.");
4838 STAM_REL_REG(pVM, &pSVGAState->StatFifoCommands, STAMTYPE_COUNTER, "/Devices/VMSVGA/FifoCommands", STAMUNIT_OCCURENCES, "FIFO command counter.");
4839 STAM_REL_REG(pVM, &pSVGAState->StatFifoErrors, STAMTYPE_COUNTER, "/Devices/VMSVGA/FifoErrors", STAMUNIT_OCCURENCES, "FIFO error counter.");
4840 STAM_REL_REG(pVM, &pSVGAState->StatFifoUnkCmds, STAMTYPE_COUNTER, "/Devices/VMSVGA/FifoUnknownCommands", STAMUNIT_OCCURENCES, "FIFO unknown command counter.");
4841 STAM_REL_REG(pVM, &pSVGAState->StatFifoTodoTimeout, STAMTYPE_COUNTER, "/Devices/VMSVGA/FifoTodoTimeout", STAMUNIT_OCCURENCES, "Number of times we discovered pending work after a wait timeout.");
4842 STAM_REL_REG(pVM, &pSVGAState->StatFifoTodoWoken, STAMTYPE_COUNTER, "/Devices/VMSVGA/FifoTodoWoken", STAMUNIT_OCCURENCES, "Number of times we discovered pending work after being woken up.");
4843 STAM_REL_REG(pVM, &pSVGAState->StatFifoStalls, STAMTYPE_PROFILE, "/Devices/VMSVGA/FifoStalls", STAMUNIT_TICKS_PER_CALL, "Profiling of FIFO stalls (waiting for guest to finish copying data).");
4844
4845 /*
4846 * Info handlers.
4847 */
4848 PDMDevHlpDBGFInfoRegister(pDevIns, "vmsvga", "Basic VMSVGA device state details", vmsvgaR3Info);
4849# ifdef VBOX_WITH_VMSVGA3D
4850 PDMDevHlpDBGFInfoRegister(pDevIns, "vmsvga3dctx", "VMSVGA 3d context details. Accepts 'terse'.", vmsvgaR3Info3dContext);
4851 PDMDevHlpDBGFInfoRegister(pDevIns, "vmsvga3dsfc",
4852 "VMSVGA 3d surface details. "
4853 "Accepts 'terse', 'invy', and one of 'tiny', 'medium', 'normal', 'big', 'huge', or 'gigantic'.",
4854 vmsvgaR3Info3dSurface);
4855# endif
4856
4857 return VINF_SUCCESS;
4858}
4859
4860# ifdef VBOX_WITH_VMSVGA3D
4861/** Names for the vmsvga 3d capabilities, prefixed with format type hint char. */
4862static const char * const g_apszVmSvgaDevCapNames[] =
4863{
4864 "x3D", /* = 0 */
4865 "xMAX_LIGHTS",
4866 "xMAX_TEXTURES",
4867 "xMAX_CLIP_PLANES",
4868 "xVERTEX_SHADER_VERSION",
4869 "xVERTEX_SHADER",
4870 "xFRAGMENT_SHADER_VERSION",
4871 "xFRAGMENT_SHADER",
4872 "xMAX_RENDER_TARGETS",
4873 "xS23E8_TEXTURES",
4874 "xS10E5_TEXTURES",
4875 "xMAX_FIXED_VERTEXBLEND",
4876 "xD16_BUFFER_FORMAT",
4877 "xD24S8_BUFFER_FORMAT",
4878 "xD24X8_BUFFER_FORMAT",
4879 "xQUERY_TYPES",
4880 "xTEXTURE_GRADIENT_SAMPLING",
4881 "rMAX_POINT_SIZE",
4882 "xMAX_SHADER_TEXTURES",
4883 "xMAX_TEXTURE_WIDTH",
4884 "xMAX_TEXTURE_HEIGHT",
4885 "xMAX_VOLUME_EXTENT",
4886 "xMAX_TEXTURE_REPEAT",
4887 "xMAX_TEXTURE_ASPECT_RATIO",
4888 "xMAX_TEXTURE_ANISOTROPY",
4889 "xMAX_PRIMITIVE_COUNT",
4890 "xMAX_VERTEX_INDEX",
4891 "xMAX_VERTEX_SHADER_INSTRUCTIONS",
4892 "xMAX_FRAGMENT_SHADER_INSTRUCTIONS",
4893 "xMAX_VERTEX_SHADER_TEMPS",
4894 "xMAX_FRAGMENT_SHADER_TEMPS",
4895 "xTEXTURE_OPS",
4896 "xSURFACEFMT_X8R8G8B8",
4897 "xSURFACEFMT_A8R8G8B8",
4898 "xSURFACEFMT_A2R10G10B10",
4899 "xSURFACEFMT_X1R5G5B5",
4900 "xSURFACEFMT_A1R5G5B5",
4901 "xSURFACEFMT_A4R4G4B4",
4902 "xSURFACEFMT_R5G6B5",
4903 "xSURFACEFMT_LUMINANCE16",
4904 "xSURFACEFMT_LUMINANCE8_ALPHA8",
4905 "xSURFACEFMT_ALPHA8",
4906 "xSURFACEFMT_LUMINANCE8",
4907 "xSURFACEFMT_Z_D16",
4908 "xSURFACEFMT_Z_D24S8",
4909 "xSURFACEFMT_Z_D24X8",
4910 "xSURFACEFMT_DXT1",
4911 "xSURFACEFMT_DXT2",
4912 "xSURFACEFMT_DXT3",
4913 "xSURFACEFMT_DXT4",
4914 "xSURFACEFMT_DXT5",
4915 "xSURFACEFMT_BUMPX8L8V8U8",
4916 "xSURFACEFMT_A2W10V10U10",
4917 "xSURFACEFMT_BUMPU8V8",
4918 "xSURFACEFMT_Q8W8V8U8",
4919 "xSURFACEFMT_CxV8U8",
4920 "xSURFACEFMT_R_S10E5",
4921 "xSURFACEFMT_R_S23E8",
4922 "xSURFACEFMT_RG_S10E5",
4923 "xSURFACEFMT_RG_S23E8",
4924 "xSURFACEFMT_ARGB_S10E5",
4925 "xSURFACEFMT_ARGB_S23E8",
4926 "xMISSING62",
4927 "xMAX_VERTEX_SHADER_TEXTURES",
4928 "xMAX_SIMULTANEOUS_RENDER_TARGETS",
4929 "xSURFACEFMT_V16U16",
4930 "xSURFACEFMT_G16R16",
4931 "xSURFACEFMT_A16B16G16R16",
4932 "xSURFACEFMT_UYVY",
4933 "xSURFACEFMT_YUY2",
4934 "xMULTISAMPLE_NONMASKABLESAMPLES",
4935 "xMULTISAMPLE_MASKABLESAMPLES",
4936 "xALPHATOCOVERAGE",
4937 "xSUPERSAMPLE",
4938 "xAUTOGENMIPMAPS",
4939 "xSURFACEFMT_NV12",
4940 "xSURFACEFMT_AYUV",
4941 "xMAX_CONTEXT_IDS",
4942 "xMAX_SURFACE_IDS",
4943 "xSURFACEFMT_Z_DF16",
4944 "xSURFACEFMT_Z_DF24",
4945 "xSURFACEFMT_Z_D24S8_INT",
4946 "xSURFACEFMT_BC4_UNORM",
4947 "xSURFACEFMT_BC5_UNORM", /* 83 */
4948};
4949# endif
4950
4951
4952/**
4953 * Power On notification.
4954 *
4955 * @returns VBox status code.
4956 * @param pDevIns The device instance data.
4957 *
4958 * @remarks Caller enters the device critical section.
4959 */
4960DECLCALLBACK(void) vmsvgaR3PowerOn(PPDMDEVINS pDevIns)
4961{
4962# ifdef VBOX_WITH_VMSVGA3D
4963 PVGASTATE pThis = PDMINS_2_DATA(pDevIns, PVGASTATE);
4964 if (pThis->svga.f3DEnabled)
4965 {
4966 int rc = vmsvga3dPowerOn(pThis);
4967
4968 if (RT_SUCCESS(rc))
4969 {
4970 bool fSavedBuffering = RTLogRelSetBuffering(true);
4971 SVGA3dCapsRecord *pCaps;
4972 SVGA3dCapPair *pData;
4973 uint32_t idxCap = 0;
4974
4975 /* 3d hardware version; latest and greatest */
4976 pThis->svga.pFIFOR3[SVGA_FIFO_3D_HWVERSION_REVISED] = SVGA3D_HWVERSION_CURRENT;
4977 pThis->svga.pFIFOR3[SVGA_FIFO_3D_HWVERSION] = SVGA3D_HWVERSION_CURRENT;
4978
4979 pCaps = (SVGA3dCapsRecord *)&pThis->svga.pFIFOR3[SVGA_FIFO_3D_CAPS];
4980 pCaps->header.type = SVGA3DCAPS_RECORD_DEVCAPS;
4981 pData = (SVGA3dCapPair *)&pCaps->data;
4982
4983 /* Fill out all 3d capabilities. */
4984 for (unsigned i = 0; i < SVGA3D_DEVCAP_MAX; i++)
4985 {
4986 uint32_t val = 0;
4987
4988 rc = vmsvga3dQueryCaps(pThis, i, &val);
4989 if (RT_SUCCESS(rc))
4990 {
4991 pData[idxCap][0] = i;
4992 pData[idxCap][1] = val;
4993 idxCap++;
4994 if (g_apszVmSvgaDevCapNames[i][0] == 'x')
4995 LogRel(("VMSVGA3d: cap[%u]=%#010x {%s}\n", i, val, &g_apszVmSvgaDevCapNames[i][1]));
4996 else
4997 LogRel(("VMSVGA3d: cap[%u]=%d.%04u {%s}\n", i, (int)*(float *)&val, (unsigned)(*(float *)&val * 10000) % 10000,
4998 &g_apszVmSvgaDevCapNames[i][1]));
4999 }
5000 else
5001 LogRel(("VMSVGA3d: cap[%u]=failed rc=%Rrc! {%s}\n", i, rc, &g_apszVmSvgaDevCapNames[i][1]));
5002 }
5003 pCaps->header.length = (sizeof(pCaps->header) + idxCap * sizeof(SVGA3dCapPair)) / sizeof(uint32_t);
5004 pCaps = (SVGA3dCapsRecord *)((uint32_t *)pCaps + pCaps->header.length);
5005
5006 /* Mark end of record array. */
5007 pCaps->header.length = 0;
5008
5009 RTLogRelSetBuffering(fSavedBuffering);
5010 }
5011 }
5012# else /* !VBOX_WITH_VMSVGA3D */
5013 RT_NOREF(pDevIns);
5014# endif /* !VBOX_WITH_VMSVGA3D */
5015}
5016
5017#endif /* IN_RING3 */
5018
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