VirtualBox

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

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

build fix

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 230.7 KB
Line 
1/* $Id: DevVGA-SVGA.cpp 65267 2017-01-12 18:35:25Z 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.215389.xyz. 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 SVGAGuestMemDescriptor desc;
1577 RTGCPHYS GCPhys = (RTGCPHYS)u32 << PAGE_SHIFT;
1578 RTGCPHYS GCPhysBase = GCPhys;
1579 uint32_t idGMR = pThis->svga.u32CurrentGMRId;
1580 uint32_t cDescriptorsAllocated = 16;
1581 uint32_t iDescriptor = 0;
1582
1583 /* Validate current GMR id. */
1584 AssertBreak(idGMR < VMSVGA_MAX_GMR_IDS);
1585
1586 /* Free the old GMR if present. */
1587 vmsvgaGMRFree(pThis, idGMR);
1588
1589 /* Just undefine the GMR? */
1590 if (GCPhys == 0)
1591 break;
1592
1593 pSVGAState->aGMR[idGMR].paDesc = (PVMSVGAGMRDESCRIPTOR)RTMemAllocZ(cDescriptorsAllocated * sizeof(VMSVGAGMRDESCRIPTOR));
1594 AssertReturn(pSVGAState->aGMR[idGMR].paDesc, VERR_NO_MEMORY);
1595
1596 /* Never cross a page boundary automatically. */
1597 while (PHYS_PAGE_ADDRESS(GCPhys) == PHYS_PAGE_ADDRESS(GCPhysBase))
1598 {
1599 /* Read descriptor. */
1600 rc = PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), GCPhys, &desc, sizeof(desc));
1601 AssertRCBreak(rc);
1602
1603 if ( desc.ppn == 0
1604 && desc.numPages == 0)
1605 break; /* terminator */
1606
1607 if ( desc.ppn != 0
1608 && desc.numPages == 0)
1609 {
1610 /* Pointer to the next physical page of descriptors. */
1611 GCPhys = GCPhysBase = (RTGCPHYS)desc.ppn << PAGE_SHIFT;
1612 }
1613 else
1614 {
1615 if (iDescriptor == cDescriptorsAllocated)
1616 {
1617 cDescriptorsAllocated += 16;
1618 pSVGAState->aGMR[idGMR].paDesc = (PVMSVGAGMRDESCRIPTOR)RTMemRealloc(pSVGAState->aGMR[idGMR].paDesc, cDescriptorsAllocated * sizeof(VMSVGAGMRDESCRIPTOR));
1619 AssertReturn(pSVGAState->aGMR[idGMR].paDesc, VERR_NO_MEMORY);
1620 }
1621
1622 pSVGAState->aGMR[idGMR].paDesc[iDescriptor].GCPhys = (RTGCPHYS)desc.ppn << PAGE_SHIFT;
1623 pSVGAState->aGMR[idGMR].paDesc[iDescriptor++].numPages = desc.numPages;
1624 pSVGAState->aGMR[idGMR].cbTotal += desc.numPages * PAGE_SIZE;
1625
1626 /* Continue with the next descriptor. */
1627 GCPhys += sizeof(desc);
1628 }
1629 }
1630 pSVGAState->aGMR[idGMR].numDescriptors = iDescriptor;
1631 Log(("Defined new gmr %x numDescriptors=%d cbTotal=%x\n", idGMR, iDescriptor, pSVGAState->aGMR[idGMR].cbTotal));
1632
1633 if (!pSVGAState->aGMR[idGMR].numDescriptors)
1634 {
1635 AssertFailed();
1636 RTMemFree(pSVGAState->aGMR[idGMR].paDesc);
1637 pSVGAState->aGMR[idGMR].paDesc = NULL;
1638 }
1639 AssertRC(rc);
1640 break;
1641 }
1642# endif /* IN_RING3 */
1643#endif // VBOX_WITH_VMSVGA3D
1644
1645 case SVGA_REG_TRACES: /* Enable trace-based updates even when FIFO is on */
1646 STAM_REL_COUNTER_INC(&pThis->svga.StatRegTracesWr);
1647 if (pThis->svga.fTraces == u32)
1648 break; /* nothing to do */
1649
1650#ifdef IN_RING3
1651 vmsvgaSetTraces(pThis, !!u32);
1652#else
1653 rc = VINF_IOM_R3_IOPORT_WRITE;
1654#endif
1655 break;
1656
1657 case SVGA_REG_TOP: /* Must be 1 more than the last register */
1658 STAM_REL_COUNTER_INC(&pThis->svga.StatRegTopWr);
1659 break;
1660
1661 case SVGA_REG_NUM_DISPLAYS: /* (Deprecated) */
1662 STAM_REL_COUNTER_INC(&pThis->svga.StatRegNumDisplaysWr);
1663 Log(("Write to deprecated register %x - val %x ignored\n", idxReg, u32));
1664 break;
1665
1666 case SVGA_REG_FB_START:
1667 case SVGA_REG_MEM_START:
1668 case SVGA_REG_HOST_BITS_PER_PIXEL:
1669 case SVGA_REG_MAX_WIDTH:
1670 case SVGA_REG_MAX_HEIGHT:
1671 case SVGA_REG_VRAM_SIZE:
1672 case SVGA_REG_FB_SIZE:
1673 case SVGA_REG_CAPABILITIES:
1674 case SVGA_REG_MEM_SIZE:
1675 case SVGA_REG_SCRATCH_SIZE: /* Number of scratch registers */
1676 case SVGA_REG_MEM_REGS: /* Number of FIFO registers */
1677 case SVGA_REG_BYTES_PER_LINE:
1678 case SVGA_REG_FB_OFFSET:
1679 case SVGA_REG_RED_MASK:
1680 case SVGA_REG_GREEN_MASK:
1681 case SVGA_REG_BLUE_MASK:
1682 case SVGA_REG_GMRS_MAX_PAGES: /* Maximum number of 4KB pages for all GMRs */
1683 case SVGA_REG_MEMORY_SIZE: /* Total dedicated device memory excluding FIFO */
1684 case SVGA_REG_GMR_MAX_IDS:
1685 case SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH:
1686 /* Read only - ignore. */
1687 Log(("Write to R/O register %x - val %x ignored\n", idxReg, u32));
1688 STAM_REL_COUNTER_INC(&pThis->svga.StatRegReadOnlyWr);
1689 break;
1690
1691 default:
1692 {
1693 uint32_t offReg;
1694 if ((offReg = idxReg - SVGA_SCRATCH_BASE) < pThis->svga.cScratchRegion)
1695 {
1696 pThis->svga.au32ScratchRegion[offReg] = u32;
1697 STAM_REL_COUNTER_INC(&pThis->svga.StatRegScratchWr);
1698 }
1699 else if ((offReg = idxReg - SVGA_PALETTE_BASE) < (uint32_t)SVGA_NUM_PALETTE_REGS)
1700 {
1701 STAM_REL_COUNTER_INC(&pThis->svga.StatRegPaletteWr);
1702 /* Next 768 (== 256*3) registers exist for colormap */
1703 }
1704 else
1705 {
1706#if !defined(IN_RING3) && defined(VBOX_STRICT)
1707 rc = VINF_IOM_R3_IOPORT_WRITE;
1708#else
1709 STAM_REL_COUNTER_INC(&pThis->svga.StatRegUnknownWr);
1710 AssertMsgFailed(("reg=%#x u32=%#x\n", idxReg, u32));
1711#endif
1712 }
1713 break;
1714 }
1715 }
1716 return rc;
1717}
1718
1719/**
1720 * Port I/O Handler for IN operations.
1721 *
1722 * @returns VINF_SUCCESS or VINF_EM_*.
1723 * @returns VERR_IOM_IOPORT_UNUSED if the port is really unused and a ~0 value should be returned.
1724 *
1725 * @param pDevIns The device instance.
1726 * @param pvUser User argument.
1727 * @param uPort Port number used for the IN operation.
1728 * @param pu32 Where to store the result. This is always a 32-bit
1729 * variable regardless of what @a cb might say.
1730 * @param cb Number of bytes read.
1731 */
1732PDMBOTHCBDECL(int) vmsvgaIORead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t *pu32, unsigned cb)
1733{
1734 PVGASTATE pThis = PDMINS_2_DATA(pDevIns, PVGASTATE);
1735 RT_NOREF_PV(pvUser);
1736
1737 /* Ignore non-dword accesses. */
1738 if (cb != 4)
1739 {
1740 Log(("Ignoring non-dword read at %x cb=%d\n", uPort, cb));
1741 *pu32 = UINT32_MAX;
1742 return VINF_SUCCESS;
1743 }
1744
1745 switch (uPort - pThis->svga.BasePort)
1746 {
1747 case SVGA_INDEX_PORT:
1748 *pu32 = pThis->svga.u32IndexReg;
1749 break;
1750
1751 case SVGA_VALUE_PORT:
1752 return vmsvgaReadPort(pThis, pu32);
1753
1754 case SVGA_BIOS_PORT:
1755 Log(("Ignoring BIOS port read\n"));
1756 *pu32 = 0;
1757 break;
1758
1759 case SVGA_IRQSTATUS_PORT:
1760 LogFlow(("vmsvgaIORead: SVGA_IRQSTATUS_PORT %x\n", pThis->svga.u32IrqStatus));
1761 *pu32 = pThis->svga.u32IrqStatus;
1762 break;
1763 }
1764
1765 return VINF_SUCCESS;
1766}
1767
1768/**
1769 * Port I/O Handler for OUT operations.
1770 *
1771 * @returns VINF_SUCCESS or VINF_EM_*.
1772 *
1773 * @param pDevIns The device instance.
1774 * @param pvUser User argument.
1775 * @param uPort Port number used for the OUT operation.
1776 * @param u32 The value to output.
1777 * @param cb The value size in bytes.
1778 */
1779PDMBOTHCBDECL(int) vmsvgaIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t u32, unsigned cb)
1780{
1781 PVGASTATE pThis = PDMINS_2_DATA(pDevIns, PVGASTATE);
1782 RT_NOREF_PV(pvUser);
1783
1784 /* Ignore non-dword accesses. */
1785 if (cb != 4)
1786 {
1787 Log(("Ignoring non-dword write at %x val=%x cb=%d\n", uPort, u32, cb));
1788 return VINF_SUCCESS;
1789 }
1790
1791 switch (uPort - pThis->svga.BasePort)
1792 {
1793 case SVGA_INDEX_PORT:
1794 pThis->svga.u32IndexReg = u32;
1795 break;
1796
1797 case SVGA_VALUE_PORT:
1798 return vmsvgaWritePort(pThis, u32);
1799
1800 case SVGA_BIOS_PORT:
1801 Log(("Ignoring BIOS port write (val=%x)\n", u32));
1802 break;
1803
1804 case SVGA_IRQSTATUS_PORT:
1805 Log(("vmsvgaIOWrite SVGA_IRQSTATUS_PORT %x: status %x -> %x\n", u32, pThis->svga.u32IrqStatus, pThis->svga.u32IrqStatus & ~u32));
1806 ASMAtomicAndU32(&pThis->svga.u32IrqStatus, ~u32);
1807 /* Clear the irq in case all events have been cleared. */
1808 if (!(pThis->svga.u32IrqStatus & pThis->svga.u32IrqMask))
1809 {
1810 Log(("vmsvgaIOWrite SVGA_IRQSTATUS_PORT: clearing IRQ\n"));
1811 PDMDevHlpPCISetIrqNoWait(pDevIns, 0, 0);
1812 }
1813 break;
1814 }
1815 return VINF_SUCCESS;
1816}
1817
1818#ifdef DEBUG_FIFO_ACCESS
1819
1820# ifdef IN_RING3
1821/**
1822 * Handle LFB access.
1823 * @returns VBox status code.
1824 * @param pVM VM handle.
1825 * @param pThis VGA device instance data.
1826 * @param GCPhys The access physical address.
1827 * @param fWriteAccess Read or write access
1828 */
1829static int vmsvgaFIFOAccess(PVM pVM, PVGASTATE pThis, RTGCPHYS GCPhys, bool fWriteAccess)
1830{
1831 RT_NOREF(pVM);
1832 RTGCPHYS GCPhysOffset = GCPhys - pThis->svga.GCPhysFIFO;
1833 uint32_t *pFIFO = pThis->svga.pFIFOR3;
1834
1835 switch (GCPhysOffset >> 2)
1836 {
1837 case SVGA_FIFO_MIN:
1838 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_MIN = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1839 break;
1840 case SVGA_FIFO_MAX:
1841 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_MAX = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1842 break;
1843 case SVGA_FIFO_NEXT_CMD:
1844 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_NEXT_CMD = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1845 break;
1846 case SVGA_FIFO_STOP:
1847 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_STOP = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1848 break;
1849 case SVGA_FIFO_CAPABILITIES:
1850 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CAPABILITIES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1851 break;
1852 case SVGA_FIFO_FLAGS:
1853 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_FLAGS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1854 break;
1855 case SVGA_FIFO_FENCE:
1856 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_FENCE = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1857 break;
1858 case SVGA_FIFO_3D_HWVERSION:
1859 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_HWVERSION = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1860 break;
1861 case SVGA_FIFO_PITCHLOCK:
1862 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_PITCHLOCK = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1863 break;
1864 case SVGA_FIFO_CURSOR_ON:
1865 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_ON = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1866 break;
1867 case SVGA_FIFO_CURSOR_X:
1868 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_X = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1869 break;
1870 case SVGA_FIFO_CURSOR_Y:
1871 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_Y = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1872 break;
1873 case SVGA_FIFO_CURSOR_COUNT:
1874 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_COUNT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1875 break;
1876 case SVGA_FIFO_CURSOR_LAST_UPDATED:
1877 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_LAST_UPDATED = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1878 break;
1879 case SVGA_FIFO_RESERVED:
1880 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_RESERVED = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1881 break;
1882 case SVGA_FIFO_CURSOR_SCREEN_ID:
1883 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_SCREEN_ID = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1884 break;
1885 case SVGA_FIFO_DEAD:
1886 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_DEAD = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1887 break;
1888 case SVGA_FIFO_3D_HWVERSION_REVISED:
1889 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_HWVERSION_REVISED = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1890 break;
1891 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_3D:
1892 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_3D = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1893 break;
1894 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_LIGHTS:
1895 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_LIGHTS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1896 break;
1897 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURES:
1898 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1899 break;
1900 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_CLIP_PLANES:
1901 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_CLIP_PLANES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1902 break;
1903 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_VERTEX_SHADER_VERSION:
1904 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_VERTEX_SHADER_VERSION = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1905 break;
1906 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_VERTEX_SHADER:
1907 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_VERTEX_SHADER = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1908 break;
1909 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_FRAGMENT_SHADER_VERSION:
1910 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_FRAGMENT_SHADER_VERSION = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1911 break;
1912 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_FRAGMENT_SHADER:
1913 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_FRAGMENT_SHADER = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1914 break;
1915 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_RENDER_TARGETS:
1916 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_RENDER_TARGETS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1917 break;
1918 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_S23E8_TEXTURES:
1919 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_S23E8_TEXTURES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1920 break;
1921 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_S10E5_TEXTURES:
1922 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_S10E5_TEXTURES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1923 break;
1924 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_FIXED_VERTEXBLEND:
1925 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_FIXED_VERTEXBLEND = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1926 break;
1927 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_D16_BUFFER_FORMAT:
1928 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_D16_BUFFER_FORMAT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1929 break;
1930 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_D24S8_BUFFER_FORMAT:
1931 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_D24S8_BUFFER_FORMAT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1932 break;
1933 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_D24X8_BUFFER_FORMAT:
1934 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_D24X8_BUFFER_FORMAT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1935 break;
1936 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_QUERY_TYPES:
1937 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_QUERY_TYPES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1938 break;
1939 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_TEXTURE_GRADIENT_SAMPLING:
1940 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_TEXTURE_GRADIENT_SAMPLING = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1941 break;
1942 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_POINT_SIZE:
1943 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_POINT_SIZE = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1944 break;
1945 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_SHADER_TEXTURES:
1946 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_SHADER_TEXTURES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1947 break;
1948 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURE_WIDTH:
1949 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURE_WIDTH = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1950 break;
1951 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURE_HEIGHT:
1952 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURE_HEIGHT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1953 break;
1954 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_VOLUME_EXTENT:
1955 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_VOLUME_EXTENT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1956 break;
1957 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURE_REPEAT:
1958 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURE_REPEAT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1959 break;
1960 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURE_ASPECT_RATIO:
1961 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]));
1962 break;
1963 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURE_ANISOTROPY:
1964 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURE_ANISOTROPY = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1965 break;
1966 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_PRIMITIVE_COUNT:
1967 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_PRIMITIVE_COUNT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1968 break;
1969 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_VERTEX_INDEX:
1970 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_VERTEX_INDEX = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1971 break;
1972 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_VERTEX_SHADER_INSTRUCTIONS:
1973 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]));
1974 break;
1975 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_INSTRUCTIONS:
1976 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]));
1977 break;
1978 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEMPS:
1979 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]));
1980 break;
1981 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_TEMPS:
1982 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]));
1983 break;
1984 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_TEXTURE_OPS:
1985 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_TEXTURE_OPS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1986 break;
1987 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8:
1988 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1989 break;
1990 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8:
1991 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1992 break;
1993 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10:
1994 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1995 break;
1996 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5:
1997 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
1998 break;
1999 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5:
2000 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2001 break;
2002 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4:
2003 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2004 break;
2005 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_R5G6B5:
2006 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_R5G6B5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2007 break;
2008 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE16:
2009 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2010 break;
2011 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8:
2012 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2013 break;
2014 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_ALPHA8:
2015 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_ALPHA8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2016 break;
2017 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8:
2018 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2019 break;
2020 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_D16:
2021 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_D16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2022 break;
2023 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8:
2024 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2025 break;
2026 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8:
2027 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2028 break;
2029 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_DXT1:
2030 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_DXT1 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2031 break;
2032 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_DXT2:
2033 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_DXT2 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2034 break;
2035 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_DXT3:
2036 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_DXT3 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2037 break;
2038 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_DXT4:
2039 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_DXT4 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2040 break;
2041 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_DXT5:
2042 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_DXT5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2043 break;
2044 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_BUMPX8L8V8U8:
2045 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_BUMPX8L8V8U8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2046 break;
2047 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A2W10V10U10:
2048 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A2W10V10U10 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2049 break;
2050 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_BUMPU8V8:
2051 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_BUMPU8V8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2052 break;
2053 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Q8W8V8U8:
2054 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Q8W8V8U8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2055 break;
2056 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_CxV8U8:
2057 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_CxV8U8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2058 break;
2059 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_R_S10E5:
2060 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_R_S10E5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2061 break;
2062 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_R_S23E8:
2063 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_R_S23E8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2064 break;
2065 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_RG_S10E5:
2066 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_RG_S10E5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2067 break;
2068 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_RG_S23E8:
2069 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_RG_S23E8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2070 break;
2071 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_ARGB_S10E5:
2072 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_ARGB_S10E5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2073 break;
2074 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_ARGB_S23E8:
2075 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_ARGB_S23E8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2076 break;
2077 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEXTURES:
2078 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]));
2079 break;
2080 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_SIMULTANEOUS_RENDER_TARGETS:
2081 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]));
2082 break;
2083 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_V16U16:
2084 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_V16U16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2085 break;
2086 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_G16R16:
2087 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_G16R16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2088 break;
2089 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16:
2090 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2091 break;
2092 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_UYVY:
2093 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_UYVY = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2094 break;
2095 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_YUY2:
2096 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_YUY2 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2097 break;
2098 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MULTISAMPLE_NONMASKABLESAMPLES:
2099 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MULTISAMPLE_NONMASKABLESAMPLES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2100 break;
2101 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MULTISAMPLE_MASKABLESAMPLES:
2102 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MULTISAMPLE_MASKABLESAMPLES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2103 break;
2104 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_ALPHATOCOVERAGE:
2105 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_ALPHATOCOVERAGE = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2106 break;
2107 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SUPERSAMPLE:
2108 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SUPERSAMPLE = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2109 break;
2110 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_AUTOGENMIPMAPS:
2111 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_AUTOGENMIPMAPS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2112 break;
2113 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_NV12:
2114 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_NV12 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2115 break;
2116 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_AYUV:
2117 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_AYUV = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2118 break;
2119 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_CONTEXT_IDS:
2120 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_CONTEXT_IDS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2121 break;
2122 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_SURFACE_IDS:
2123 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_SURFACE_IDS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2124 break;
2125 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_DF16:
2126 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_DF16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2127 break;
2128 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_DF24:
2129 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_DF24 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2130 break;
2131 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8_INT:
2132 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]));
2133 break;
2134 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_BC4_UNORM:
2135 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_BC4_UNORM = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2136 break;
2137 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_BC5_UNORM:
2138 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_BC5_UNORM = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2139 break;
2140 case SVGA_FIFO_3D_CAPS_LAST:
2141 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS_LAST = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2142 break;
2143 case SVGA_FIFO_GUEST_3D_HWVERSION:
2144 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_GUEST_3D_HWVERSION = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2145 break;
2146 case SVGA_FIFO_FENCE_GOAL:
2147 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_FENCE_GOAL = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2148 break;
2149 case SVGA_FIFO_BUSY:
2150 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_BUSY = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2151 break;
2152 default:
2153 Log(("vmsvgaFIFOAccess [0x%x]: %s access at offset %x = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", GCPhysOffset, pFIFO[GCPhysOffset >> 2]));
2154 break;
2155 }
2156
2157 return VINF_EM_RAW_EMULATE_INSTR;
2158}
2159
2160/**
2161 * HC access handler for the FIFO.
2162 *
2163 * @returns VINF_SUCCESS if the handler have carried out the operation.
2164 * @returns VINF_PGM_HANDLER_DO_DEFAULT if the caller should carry out the access operation.
2165 * @param pVM VM Handle.
2166 * @param pVCpu The cross context CPU structure for the calling EMT.
2167 * @param GCPhys The physical address the guest is writing to.
2168 * @param pvPhys The HC mapping of that address.
2169 * @param pvBuf What the guest is reading/writing.
2170 * @param cbBuf How much it's reading/writing.
2171 * @param enmAccessType The access type.
2172 * @param enmOrigin Who is making the access.
2173 * @param pvUser User argument.
2174 */
2175static DECLCALLBACK(VBOXSTRICTRC)
2176vmsvgaR3FIFOAccessHandler(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf,
2177 PGMACCESSTYPE enmAccessType, PGMACCESSORIGIN enmOrigin, void *pvUser)
2178{
2179 PVGASTATE pThis = (PVGASTATE)pvUser;
2180 int rc;
2181 Assert(pThis);
2182 Assert(GCPhys >= pThis->svga.GCPhysFIFO);
2183 NOREF(pVCpu); NOREF(pvPhys); NOREF(pvBuf); NOREF(cbBuf); NOREF(enmOrigin);
2184
2185 rc = vmsvgaFIFOAccess(pVM, pThis, GCPhys, enmAccessType == PGMACCESSTYPE_WRITE);
2186 if (RT_SUCCESS(rc))
2187 return VINF_PGM_HANDLER_DO_DEFAULT;
2188 AssertMsg(rc <= VINF_SUCCESS, ("rc=%Rrc\n", rc));
2189 return rc;
2190}
2191
2192# endif /* IN_RING3 */
2193#endif /* DEBUG_FIFO_ACCESS */
2194
2195#ifdef DEBUG_GMR_ACCESS
2196# ifdef IN_RING3
2197
2198/**
2199 * HC access handler for the FIFO.
2200 *
2201 * @returns VINF_SUCCESS if the handler have carried out the operation.
2202 * @returns VINF_PGM_HANDLER_DO_DEFAULT if the caller should carry out the access operation.
2203 * @param pVM VM Handle.
2204 * @param pVCpu The cross context CPU structure for the calling EMT.
2205 * @param GCPhys The physical address the guest is writing to.
2206 * @param pvPhys The HC mapping of that address.
2207 * @param pvBuf What the guest is reading/writing.
2208 * @param cbBuf How much it's reading/writing.
2209 * @param enmAccessType The access type.
2210 * @param enmOrigin Who is making the access.
2211 * @param pvUser User argument.
2212 */
2213static DECLCALLBACK(VBOXSTRICTRC)
2214vmsvgaR3GMRAccessHandler(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf,
2215 PGMACCESSTYPE enmAccessType, PGMACCESSORIGIN enmOrigin, void *pvUser)
2216{
2217 PVGASTATE pThis = (PVGASTATE)pvUser;
2218 Assert(pThis);
2219 PVMSVGAR3STATE pSVGAState = pThis->svga.pSvgaR3State;
2220 NOREF(pVCpu); NOREF(pvPhys); NOREF(pvBuf); NOREF(cbBuf); NOREF(enmAccessType); NOREF(enmOrigin);
2221
2222 Log(("vmsvgaR3GMRAccessHandler: GMR access to page %RGp\n", GCPhys));
2223
2224 for (uint32_t i = 0; i < RT_ELEMENTS(pSVGAState->aGMR); i++)
2225 {
2226 PGMR pGMR = &pSVGAState->aGMR[i];
2227
2228 if (pGMR->numDescriptors)
2229 {
2230 for (uint32_t j = 0; j < pGMR->numDescriptors; j++)
2231 {
2232 if ( GCPhys >= pGMR->paDesc[j].GCPhys
2233 && GCPhys < pGMR->paDesc[j].GCPhys + pGMR->paDesc[j].numPages * PAGE_SIZE)
2234 {
2235 /*
2236 * Turn off the write handler for this particular page and make it R/W.
2237 * Then return telling the caller to restart the guest instruction.
2238 */
2239 int rc = PGMHandlerPhysicalPageTempOff(pVM, pGMR->paDesc[j].GCPhys, GCPhys);
2240 AssertRC(rc);
2241 goto end;
2242 }
2243 }
2244 }
2245 }
2246end:
2247 return VINF_PGM_HANDLER_DO_DEFAULT;
2248}
2249
2250/* Callback handler for VMR3ReqCallWaitU */
2251static DECLCALLBACK(int) vmsvgaRegisterGMR(PPDMDEVINS pDevIns, uint32_t gmrId)
2252{
2253 PVGASTATE pThis = PDMINS_2_DATA(pDevIns, PVGASTATE);
2254 PVMSVGAR3STATE pSVGAState = pThis->svga.pSvgaR3State;
2255 PGMR pGMR = &pSVGAState->aGMR[gmrId];
2256 int rc;
2257
2258 for (uint32_t i = 0; i < pGMR->numDescriptors; i++)
2259 {
2260 rc = PGMHandlerPhysicalRegister(PDMDevHlpGetVM(pThis->pDevInsR3),
2261 pGMR->paDesc[i].GCPhys, pGMR->paDesc[i].GCPhys + pGMR->paDesc[i].numPages * PAGE_SIZE - 1,
2262 pThis->svga.hGmrAccessHandlerType, pThis, NIL_RTR0PTR, NIL_RTRCPTR, "VMSVGA GMR");
2263 AssertRC(rc);
2264 }
2265 return VINF_SUCCESS;
2266}
2267
2268/* Callback handler for VMR3ReqCallWaitU */
2269static DECLCALLBACK(int) vmsvgaDeregisterGMR(PPDMDEVINS pDevIns, uint32_t gmrId)
2270{
2271 PVGASTATE pThis = PDMINS_2_DATA(pDevIns, PVGASTATE);
2272 PVMSVGAR3STATE pSVGAState = pThis->svga.pSvgaR3State;
2273 PGMR pGMR = &pSVGAState->aGMR[gmrId];
2274
2275 for (uint32_t i = 0; i < pGMR->numDescriptors; i++)
2276 {
2277 int rc = PGMHandlerPhysicalDeregister(PDMDevHlpGetVM(pThis->pDevInsR3), pGMR->paDesc[i].GCPhys);
2278 AssertRC(rc);
2279 }
2280 return VINF_SUCCESS;
2281}
2282
2283/* Callback handler for VMR3ReqCallWaitU */
2284static DECLCALLBACK(int) vmsvgaResetGMRHandlers(PVGASTATE pThis)
2285{
2286 PVMSVGAR3STATE pSVGAState = pThis->svga.pSvgaR3State;
2287
2288 for (uint32_t i = 0; i < RT_ELEMENTS(pSVGAState->aGMR); i++)
2289 {
2290 PGMR pGMR = &pSVGAState->aGMR[i];
2291
2292 if (pGMR->numDescriptors)
2293 {
2294 for (uint32_t j = 0; j < pGMR->numDescriptors; j++)
2295 {
2296 int rc = PGMHandlerPhysicalReset(PDMDevHlpGetVM(pThis->pDevInsR3), pGMR->paDesc[j].GCPhys);
2297 AssertRC(rc);
2298 }
2299 }
2300 }
2301 return VINF_SUCCESS;
2302}
2303
2304# endif /* IN_RING3 */
2305#endif /* DEBUG_GMR_ACCESS */
2306
2307/* -=-=-=-=-=- Ring 3 -=-=-=-=-=- */
2308
2309#ifdef IN_RING3
2310
2311/**
2312 * Worker for vmsvgaR3FifoThread that handles an external command.
2313 *
2314 * @param pThis VGA device instance data.
2315 */
2316static void vmsvgaR3FifoHandleExtCmd(PVGASTATE pThis)
2317{
2318 uint8_t uExtCmd = pThis->svga.u8FIFOExtCommand;
2319 switch (pThis->svga.u8FIFOExtCommand)
2320 {
2321 case VMSVGA_FIFO_EXTCMD_RESET:
2322 Log(("vmsvgaFIFOLoop: reset the fifo thread.\n"));
2323 Assert(pThis->svga.pvFIFOExtCmdParam == NULL);
2324# ifdef VBOX_WITH_VMSVGA3D
2325 if (pThis->svga.f3DEnabled)
2326 {
2327 /* The 3d subsystem must be reset from the fifo thread. */
2328 vmsvga3dReset(pThis);
2329 }
2330# endif
2331 break;
2332
2333 case VMSVGA_FIFO_EXTCMD_TERMINATE:
2334 Log(("vmsvgaFIFOLoop: terminate the fifo thread.\n"));
2335 Assert(pThis->svga.pvFIFOExtCmdParam == NULL);
2336# ifdef VBOX_WITH_VMSVGA3D
2337 if (pThis->svga.f3DEnabled)
2338 {
2339 /* The 3d subsystem must be shut down from the fifo thread. */
2340 vmsvga3dTerminate(pThis);
2341 }
2342# endif
2343 break;
2344
2345 case VMSVGA_FIFO_EXTCMD_SAVESTATE:
2346 {
2347 Log(("vmsvgaFIFOLoop: VMSVGA_FIFO_EXTCMD_SAVESTATE.\n"));
2348# ifdef VBOX_WITH_VMSVGA3D
2349 PSSMHANDLE pSSM = (PSSMHANDLE)pThis->svga.pvFIFOExtCmdParam;
2350 AssertLogRelMsgBreak(RT_VALID_PTR(pSSM), ("pSSM=%p\n", pSSM));
2351 vmsvga3dSaveExec(pThis, pSSM);
2352# endif
2353 break;
2354 }
2355
2356 case VMSVGA_FIFO_EXTCMD_LOADSTATE:
2357 {
2358 Log(("vmsvgaFIFOLoop: VMSVGA_FIFO_EXTCMD_LOADSTATE.\n"));
2359# ifdef VBOX_WITH_VMSVGA3D
2360 PVMSVGA_STATE_LOAD pLoadState = (PVMSVGA_STATE_LOAD)pThis->svga.pvFIFOExtCmdParam;
2361 AssertLogRelMsgBreak(RT_VALID_PTR(pLoadState), ("pLoadState=%p\n", pLoadState));
2362 vmsvga3dLoadExec(pThis, pLoadState->pSSM, pLoadState->uVersion, pLoadState->uPass);
2363# endif
2364 break;
2365 }
2366
2367 case VMSVGA_FIFO_EXTCMD_UPDATE_SURFACE_HEAP_BUFFERS:
2368 {
2369# ifdef VBOX_WITH_VMSVGA3D
2370 uint32_t sid = (uint32_t)(uintptr_t)pThis->svga.pvFIFOExtCmdParam;
2371 Log(("vmsvgaFIFOLoop: VMSVGA_FIFO_EXTCMD_UPDATE_SURFACE_HEAP_BUFFERS sid=%#x\n", sid));
2372 vmsvga3dUpdateHeapBuffersForSurfaces(pThis, sid);
2373# endif
2374 break;
2375 }
2376
2377
2378 default:
2379 AssertLogRelMsgFailed(("uExtCmd=%#x pvFIFOExtCmdParam=%p\n", uExtCmd, pThis->svga.pvFIFOExtCmdParam));
2380 break;
2381 }
2382
2383 /*
2384 * Signal the end of the external command.
2385 */
2386 pThis->svga.pvFIFOExtCmdParam = NULL;
2387 pThis->svga.u8FIFOExtCommand = VMSVGA_FIFO_EXTCMD_NONE;
2388 ASMMemoryFence(); /* paranoia^2 */
2389 int rc = RTSemEventSignal(pThis->svga.FIFOExtCmdSem);
2390 AssertLogRelRC(rc);
2391}
2392
2393/**
2394 * Worker for vmsvgaR3Destruct, vmsvgaR3Reset, vmsvgaR3Save and vmsvgaR3Load for
2395 * doing a job on the FIFO thread (even when it's officially suspended).
2396 *
2397 * @returns VBox status code (fully asserted).
2398 * @param pThis VGA device instance data.
2399 * @param uExtCmd The command to execute on the FIFO thread.
2400 * @param pvParam Pointer to command parameters.
2401 * @param cMsWait The time to wait for the command, given in
2402 * milliseconds.
2403 */
2404static int vmsvgaR3RunExtCmdOnFifoThread(PVGASTATE pThis, uint8_t uExtCmd, void *pvParam, RTMSINTERVAL cMsWait)
2405{
2406 Assert(cMsWait >= RT_MS_1SEC * 5);
2407 AssertLogRelMsg(pThis->svga.u8FIFOExtCommand == VMSVGA_FIFO_EXTCMD_NONE,
2408 ("old=%d new=%d\n", pThis->svga.u8FIFOExtCommand, uExtCmd));
2409
2410 int rc;
2411 PPDMTHREAD pThread = pThis->svga.pFIFOIOThread;
2412 PDMTHREADSTATE enmState = pThread->enmState;
2413 if (enmState == PDMTHREADSTATE_SUSPENDED)
2414 {
2415 /*
2416 * The thread is suspended, we have to temporarily wake it up so it can
2417 * perform the task.
2418 * (We ASSUME not racing code here, both wrt thread state and ext commands.)
2419 */
2420 Log(("vmsvgaR3RunExtCmdOnFifoThread: uExtCmd=%d enmState=SUSPENDED\n", uExtCmd));
2421 /* Post the request. */
2422 pThis->svga.fFifoExtCommandWakeup = true;
2423 pThis->svga.pvFIFOExtCmdParam = pvParam;
2424 pThis->svga.u8FIFOExtCommand = uExtCmd;
2425 ASMMemoryFence(); /* paranoia^3 */
2426
2427 /* Resume the thread. */
2428 rc = PDMR3ThreadResume(pThread);
2429 AssertLogRelRC(rc);
2430 if (RT_SUCCESS(rc))
2431 {
2432 /* Wait. Take care in case the semaphore was already posted (same as below). */
2433 rc = RTSemEventWait(pThis->svga.FIFOExtCmdSem, cMsWait);
2434 if ( rc == VINF_SUCCESS
2435 && pThis->svga.u8FIFOExtCommand == uExtCmd)
2436 rc = RTSemEventWait(pThis->svga.FIFOExtCmdSem, cMsWait);
2437 AssertLogRelMsg(pThis->svga.u8FIFOExtCommand != uExtCmd || RT_FAILURE_NP(rc),
2438 ("%#x %Rrc\n", pThis->svga.u8FIFOExtCommand, rc));
2439
2440 /* suspend the thread */
2441 pThis->svga.fFifoExtCommandWakeup = false;
2442 int rc2 = PDMR3ThreadSuspend(pThread);
2443 AssertLogRelRC(rc2);
2444 if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
2445 rc = rc2;
2446 }
2447 pThis->svga.fFifoExtCommandWakeup = false;
2448 pThis->svga.pvFIFOExtCmdParam = NULL;
2449 }
2450 else if (enmState == PDMTHREADSTATE_RUNNING)
2451 {
2452 /*
2453 * The thread is running, should only happen during reset and vmsvga3dsfc.
2454 * We ASSUME not racing code here, both wrt thread state and ext commands.
2455 */
2456 Log(("vmsvgaR3RunExtCmdOnFifoThread: uExtCmd=%d enmState=RUNNING\n", uExtCmd));
2457 Assert(uExtCmd == VMSVGA_FIFO_EXTCMD_RESET || uExtCmd == VMSVGA_FIFO_EXTCMD_UPDATE_SURFACE_HEAP_BUFFERS);
2458
2459 /* Post the request. */
2460 pThis->svga.pvFIFOExtCmdParam = pvParam;
2461 pThis->svga.u8FIFOExtCommand = uExtCmd;
2462 ASMMemoryFence(); /* paranoia^2 */
2463 rc = SUPSemEventSignal(pThis->svga.pSupDrvSession, pThis->svga.FIFORequestSem);
2464 AssertLogRelRC(rc);
2465
2466 /* Wait. Take care in case the semaphore was already posted (same as above). */
2467 rc = RTSemEventWait(pThis->svga.FIFOExtCmdSem, cMsWait);
2468 if ( rc == VINF_SUCCESS
2469 && pThis->svga.u8FIFOExtCommand == uExtCmd)
2470 rc = RTSemEventWait(pThis->svga.FIFOExtCmdSem, cMsWait); /* it was already posted, retry the wait. */
2471 AssertLogRelMsg(pThis->svga.u8FIFOExtCommand != uExtCmd || RT_FAILURE_NP(rc),
2472 ("%#x %Rrc\n", pThis->svga.u8FIFOExtCommand, rc));
2473
2474 pThis->svga.pvFIFOExtCmdParam = NULL;
2475 }
2476 else
2477 {
2478 /*
2479 * Something is wrong with the thread!
2480 */
2481 AssertLogRelMsgFailed(("uExtCmd=%d enmState=%d\n", uExtCmd, enmState));
2482 rc = VERR_INVALID_STATE;
2483 }
2484 return rc;
2485}
2486
2487
2488/**
2489 * Marks the FIFO non-busy, notifying any waiting EMTs.
2490 *
2491 * @param pThis The VGA state.
2492 * @param pSVGAState Pointer to the ring-3 only SVGA state data.
2493 * @param offFifoMin The start byte offset of the command FIFO.
2494 */
2495static void vmsvgaFifoSetNotBusy(PVGASTATE pThis, PVMSVGAR3STATE pSVGAState, uint32_t offFifoMin)
2496{
2497 ASMAtomicAndU32(&pThis->svga.fBusy, ~VMSVGA_BUSY_F_FIFO);
2498 if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_BUSY, offFifoMin))
2499 vmsvgaSafeFifoBusyRegUpdate(pThis, pThis->svga.fBusy != 0);
2500
2501 /* Wake up any waiting EMTs. */
2502 if (pSVGAState->cBusyDelayedEmts > 0)
2503 {
2504#ifdef VMSVGA_USE_EMT_HALT_CODE
2505 PVM pVM = PDMDevHlpGetVM(pThis->pDevInsR3);
2506 VMCPUID idCpu = VMCpuSetFindLastPresentInternal(&pSVGAState->BusyDelayedEmts);
2507 if (idCpu != NIL_VMCPUID)
2508 {
2509 VMR3NotifyCpuDeviceReady(pVM, idCpu);
2510 while (idCpu-- > 0)
2511 if (VMCPUSET_IS_PRESENT(&pSVGAState->BusyDelayedEmts, idCpu))
2512 VMR3NotifyCpuDeviceReady(pVM, idCpu);
2513 }
2514#else
2515 int rc2 = RTSemEventMultiSignal(pSVGAState->hBusyDelayedEmts);
2516 AssertRC(rc2);
2517#endif
2518 }
2519}
2520
2521/**
2522 * Reads (more) payload into the command buffer.
2523 *
2524 * @returns pbBounceBuf on success
2525 * @retval (void *)1 if the thread was requested to stop.
2526 * @retval NULL on FIFO error.
2527 *
2528 * @param cbPayloadReq The number of bytes of payload requested.
2529 * @param pFIFO The FIFO.
2530 * @param offCurrentCmd The FIFO byte offset of the current command.
2531 * @param offFifoMin The start byte offset of the command FIFO.
2532 * @param offFifoMax The end byte offset of the command FIFO.
2533 * @param pbBounceBuf The bounch buffer. Same size as the entire FIFO, so
2534 * always sufficient size.
2535 * @param pcbAlreadyRead How much payload we've already read into the bounce
2536 * buffer. (We will NEVER re-read anything.)
2537 * @param pThread The calling PDM thread handle.
2538 * @param pThis The VGA state.
2539 * @param pSVGAState Pointer to the ring-3 only SVGA state data. For
2540 * statistics collection.
2541 */
2542static void *vmsvgaFIFOGetCmdPayload(uint32_t cbPayloadReq, uint32_t volatile *pFIFO,
2543 uint32_t offCurrentCmd, uint32_t offFifoMin, uint32_t offFifoMax,
2544 uint8_t *pbBounceBuf, uint32_t *pcbAlreadyRead,
2545 PPDMTHREAD pThread, PVGASTATE pThis, PVMSVGAR3STATE pSVGAState)
2546{
2547 Assert(pbBounceBuf);
2548 Assert(pcbAlreadyRead);
2549 Assert(offFifoMin < offFifoMax);
2550 Assert(offCurrentCmd >= offFifoMin && offCurrentCmd < offFifoMax);
2551 Assert(offFifoMax <= VMSVGA_FIFO_SIZE);
2552
2553 /*
2554 * Check if the requested payload size has already been satisfied .
2555 * .
2556 * When called to read more, the caller is responsible for making sure the .
2557 * new command size (cbRequsted) never is smaller than what has already .
2558 * been read.
2559 */
2560 uint32_t cbAlreadyRead = *pcbAlreadyRead;
2561 if (cbPayloadReq <= cbAlreadyRead)
2562 {
2563 AssertLogRelReturn(cbPayloadReq == cbAlreadyRead, NULL);
2564 return pbBounceBuf;
2565 }
2566
2567 /*
2568 * Commands bigger than the fifo buffer are invalid.
2569 */
2570 uint32_t const cbFifoCmd = offFifoMax - offFifoMin;
2571 AssertMsgReturnStmt(cbPayloadReq <= cbFifoCmd, ("cbPayloadReq=%#x cbFifoCmd=%#x\n", cbPayloadReq, cbFifoCmd),
2572 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoErrors),
2573 NULL);
2574
2575 /*
2576 * Move offCurrentCmd past the command dword.
2577 */
2578 offCurrentCmd += sizeof(uint32_t);
2579 if (offCurrentCmd >= offFifoMax)
2580 offCurrentCmd = offFifoMin;
2581
2582 /*
2583 * Do we have sufficient payload data available already?
2584 */
2585 uint32_t cbAfter, cbBefore;
2586 uint32_t offNextCmd = pFIFO[SVGA_FIFO_NEXT_CMD];
2587 if (offNextCmd > offCurrentCmd)
2588 {
2589 if (RT_LIKELY(offNextCmd < offFifoMax))
2590 cbAfter = offNextCmd - offCurrentCmd;
2591 else
2592 {
2593 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoErrors);
2594 LogRelMax(16, ("vmsvgaFIFOGetCmdPayload: Invalid offNextCmd=%#x (offFifoMin=%#x offFifoMax=%#x)\n",
2595 offNextCmd, offFifoMin, offFifoMax));
2596 cbAfter = offFifoMax - offCurrentCmd;
2597 }
2598 cbBefore = 0;
2599 }
2600 else
2601 {
2602 cbAfter = offFifoMax - offCurrentCmd;
2603 if (offNextCmd >= offFifoMin)
2604 cbBefore = offNextCmd - offFifoMin;
2605 else
2606 {
2607 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoErrors);
2608 LogRelMax(16, ("vmsvgaFIFOGetCmdPayload: Invalid offNextCmd=%#x (offFifoMin=%#x offFifoMax=%#x)\n",
2609 offNextCmd, offFifoMin, offFifoMax));
2610 cbBefore = 0;
2611 }
2612 }
2613 if (cbAfter + cbBefore < cbPayloadReq)
2614 {
2615 /*
2616 * Insufficient, must wait for it to arrive.
2617 */
2618/** @todo Should clear the busy flag here to maybe encourage the guest to wake us up. */
2619 STAM_REL_PROFILE_START(&pSVGAState->StatFifoStalls, Stall);
2620 for (uint32_t i = 0;; i++)
2621 {
2622 if (pThread->enmState != PDMTHREADSTATE_RUNNING)
2623 {
2624 STAM_REL_PROFILE_STOP(&pSVGAState->StatFifoStalls, Stall);
2625 return (void *)(uintptr_t)1;
2626 }
2627 Log(("Guest still copying (%x vs %x) current %x next %x stop %x loop %u; sleep a bit\n",
2628 cbPayloadReq, cbAfter + cbBefore, offCurrentCmd, offNextCmd, pFIFO[SVGA_FIFO_STOP], i));
2629
2630 SUPSemEventWaitNoResume(pThis->svga.pSupDrvSession, pThis->svga.FIFORequestSem, i < 16 ? 1 : 2);
2631
2632 offNextCmd = pFIFO[SVGA_FIFO_NEXT_CMD];
2633 if (offNextCmd > offCurrentCmd)
2634 {
2635 cbAfter = RT_MIN(offNextCmd, offFifoMax) - offCurrentCmd;
2636 cbBefore = 0;
2637 }
2638 else
2639 {
2640 cbAfter = offFifoMax - offCurrentCmd;
2641 cbBefore = RT_MAX(offNextCmd, offFifoMin) - offFifoMin;
2642 }
2643
2644 if (cbAfter + cbBefore >= cbPayloadReq)
2645 break;
2646 }
2647 STAM_REL_PROFILE_STOP(&pSVGAState->StatFifoStalls, Stall);
2648 }
2649
2650 /*
2651 * Copy out the memory and update what pcbAlreadyRead points to.
2652 */
2653 if (cbAfter >= cbPayloadReq)
2654 memcpy(pbBounceBuf + cbAlreadyRead,
2655 (uint8_t *)pFIFO + offCurrentCmd + cbAlreadyRead,
2656 cbPayloadReq - cbAlreadyRead);
2657 else
2658 {
2659 LogFlow(("Split data buffer at %x (%u-%u)\n", offCurrentCmd, cbAfter, cbBefore));
2660 if (cbAlreadyRead < cbAfter)
2661 {
2662 memcpy(pbBounceBuf + cbAlreadyRead,
2663 (uint8_t *)pFIFO + offCurrentCmd + cbAlreadyRead,
2664 cbAfter - cbAlreadyRead);
2665 cbAlreadyRead = cbAfter;
2666 }
2667 memcpy(pbBounceBuf + cbAlreadyRead,
2668 (uint8_t *)pFIFO + offFifoMin + cbAlreadyRead - cbAfter,
2669 cbPayloadReq - cbAlreadyRead);
2670 }
2671 *pcbAlreadyRead = cbPayloadReq;
2672 return pbBounceBuf;
2673}
2674
2675/* The async FIFO handling thread. */
2676static DECLCALLBACK(int) vmsvgaFIFOLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
2677{
2678 PVGASTATE pThis = (PVGASTATE)pThread->pvUser;
2679 PVMSVGAR3STATE pSVGAState = pThis->svga.pSvgaR3State;
2680 int rc;
2681
2682 if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
2683 return VINF_SUCCESS;
2684
2685 /*
2686 * Special mode where we only execute an external command and the go back
2687 * to being suspended. Currently, all ext cmds ends up here, with the reset
2688 * one also being eligble for runtime execution further down as well.
2689 */
2690 if (pThis->svga.fFifoExtCommandWakeup)
2691 {
2692 vmsvgaR3FifoHandleExtCmd(pThis);
2693 while (pThread->enmState == PDMTHREADSTATE_RUNNING)
2694 if (pThis->svga.u8FIFOExtCommand == VMSVGA_FIFO_EXTCMD_NONE)
2695 SUPSemEventWaitNoResume(pThis->svga.pSupDrvSession, pThis->svga.FIFORequestSem, RT_MS_1MIN);
2696 else
2697 vmsvgaR3FifoHandleExtCmd(pThis);
2698 return VINF_SUCCESS;
2699 }
2700
2701
2702 /*
2703 * Signal the semaphore to make sure we don't wait for 250ms after a
2704 * suspend & resume scenario (see vmsvgaFIFOGetCmdPayload).
2705 */
2706 SUPSemEventSignal(pThis->svga.pSupDrvSession, pThis->svga.FIFORequestSem);
2707
2708 /*
2709 * Allocate a bounce buffer for command we get from the FIFO.
2710 * (All code must return via the end of the function to free this buffer.)
2711 */
2712 uint8_t *pbBounceBuf = (uint8_t *)RTMemAllocZ(VMSVGA_FIFO_SIZE);
2713 AssertReturn(pbBounceBuf, VERR_NO_MEMORY);
2714
2715 /*
2716 * Polling/sleep interval config.
2717 *
2718 * We wait for an a short interval if the guest has recently given us work
2719 * to do, but the interval increases the longer we're kept idle. With the
2720 * current parameters we'll be at a 64ms poll interval after 1 idle second,
2721 * at 90ms after 2 seconds, and reach the max 250ms interval after about
2722 * 16 seconds.
2723 */
2724 RTMSINTERVAL const cMsMinSleep = 16;
2725 RTMSINTERVAL const cMsIncSleep = 2;
2726 RTMSINTERVAL const cMsMaxSleep = 250;
2727 RTMSINTERVAL cMsSleep = cMsMaxSleep;
2728
2729 /*
2730 * The FIFO loop.
2731 */
2732 LogFlow(("vmsvgaFIFOLoop: started loop\n"));
2733 bool fBadOrDisabledFifo = false;
2734 uint32_t volatile * const pFIFO = pThis->svga.pFIFOR3;
2735 while (pThread->enmState == PDMTHREADSTATE_RUNNING)
2736 {
2737# if defined(RT_OS_DARWIN) && defined(VBOX_WITH_VMSVGA3D)
2738 /*
2739 * Should service the run loop every so often.
2740 */
2741 if (pThis->svga.f3DEnabled)
2742 vmsvga3dCocoaServiceRunLoop();
2743# endif
2744
2745 /*
2746 * Unless there's already work pending, go to sleep for a short while.
2747 * (See polling/sleep interval config above.)
2748 */
2749 if ( fBadOrDisabledFifo
2750 || pFIFO[SVGA_FIFO_NEXT_CMD] == pFIFO[SVGA_FIFO_STOP])
2751 {
2752 rc = SUPSemEventWaitNoResume(pThis->svga.pSupDrvSession, pThis->svga.FIFORequestSem, cMsSleep);
2753 AssertBreak(RT_SUCCESS(rc) || rc == VERR_TIMEOUT || rc == VERR_INTERRUPTED);
2754 if (pThread->enmState != PDMTHREADSTATE_RUNNING)
2755 {
2756 LogFlow(("vmsvgaFIFOLoop: thread state %x\n", pThread->enmState));
2757 break;
2758 }
2759 }
2760 else
2761 rc = VINF_SUCCESS;
2762 fBadOrDisabledFifo = false;
2763 if (rc == VERR_TIMEOUT)
2764 {
2765 if (pFIFO[SVGA_FIFO_NEXT_CMD] == pFIFO[SVGA_FIFO_STOP])
2766 {
2767 cMsSleep = RT_MIN(cMsSleep + cMsIncSleep, cMsMaxSleep);
2768 continue;
2769 }
2770 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoTodoTimeout);
2771
2772 Log(("vmsvgaFIFOLoop: timeout\n"));
2773 }
2774 else if (pFIFO[SVGA_FIFO_NEXT_CMD] != pFIFO[SVGA_FIFO_STOP])
2775 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoTodoWoken);
2776 cMsSleep = cMsMinSleep;
2777
2778 Log(("vmsvgaFIFOLoop: enabled=%d configured=%d busy=%d\n", pThis->svga.fEnabled, pThis->svga.fConfigured, pThis->svga.pFIFOR3[SVGA_FIFO_BUSY]));
2779 Log(("vmsvgaFIFOLoop: min %x max %x\n", pFIFO[SVGA_FIFO_MIN], pFIFO[SVGA_FIFO_MAX]));
2780 Log(("vmsvgaFIFOLoop: next %x stop %x\n", pFIFO[SVGA_FIFO_NEXT_CMD], pFIFO[SVGA_FIFO_STOP]));
2781
2782 /*
2783 * Handle external commands (currently only reset).
2784 */
2785 if (pThis->svga.u8FIFOExtCommand != VMSVGA_FIFO_EXTCMD_NONE)
2786 {
2787 vmsvgaR3FifoHandleExtCmd(pThis);
2788 continue;
2789 }
2790
2791 /*
2792 * The device must be enabled and configured.
2793 */
2794 if ( !pThis->svga.fEnabled
2795 || !pThis->svga.fConfigured)
2796 {
2797 vmsvgaFifoSetNotBusy(pThis, pSVGAState, pFIFO[SVGA_FIFO_MIN]);
2798 fBadOrDisabledFifo = true;
2799 continue;
2800 }
2801
2802 /*
2803 * Get and check the min/max values. We ASSUME that they will remain
2804 * unchanged while we process requests. A further ASSUMPTION is that
2805 * the guest won't mess with SVGA_FIFO_NEXT_CMD while we're busy, so
2806 * we don't read it back while in the loop.
2807 */
2808 uint32_t const offFifoMin = pFIFO[SVGA_FIFO_MIN];
2809 uint32_t const offFifoMax = pFIFO[SVGA_FIFO_MAX];
2810 uint32_t offCurrentCmd = pFIFO[SVGA_FIFO_STOP];
2811 if (RT_UNLIKELY( !VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_STOP, offFifoMin)
2812 || offFifoMax <= offFifoMin
2813 || offFifoMax > VMSVGA_FIFO_SIZE
2814 || (offFifoMax & 3) != 0
2815 || (offFifoMin & 3) != 0
2816 || offCurrentCmd < offFifoMin
2817 || offCurrentCmd > offFifoMax))
2818 {
2819 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoErrors);
2820 LogRelMax(8, ("vmsvgaFIFOLoop: Bad fifo: min=%#x stop=%#x max=%#x\n", offFifoMin, offCurrentCmd, offFifoMax));
2821 vmsvgaFifoSetNotBusy(pThis, pSVGAState, offFifoMin);
2822 fBadOrDisabledFifo = true;
2823 continue;
2824 }
2825 if (RT_UNLIKELY(offCurrentCmd & 3))
2826 {
2827 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoErrors);
2828 LogRelMax(8, ("vmsvgaFIFOLoop: Misaligned offCurrentCmd=%#x?\n", offCurrentCmd));
2829 offCurrentCmd = ~UINT32_C(3);
2830 }
2831
2832/** @def VMSVGAFIFO_GET_CMD_BUFFER_BREAK
2833 * Macro for shortening calls to vmsvgaFIFOGetCmdPayload.
2834 *
2835 * Will break out of the switch on failure.
2836 * Will restart and quit the loop if the thread was requested to stop.
2837 *
2838 * @param a_PtrVar Request variable pointer.
2839 * @param a_Type Request typedef (not pointer) for casting.
2840 * @param a_cbPayloadReq How much payload to fetch.
2841 * @remarks Accesses a bunch of variables in the current scope!
2842 */
2843# define VMSVGAFIFO_GET_CMD_BUFFER_BREAK(a_PtrVar, a_Type, a_cbPayloadReq) \
2844 if (1) { \
2845 (a_PtrVar) = (a_Type *)vmsvgaFIFOGetCmdPayload((a_cbPayloadReq), pFIFO, offCurrentCmd, offFifoMin, offFifoMax, \
2846 pbBounceBuf, &cbPayload, pThread, pThis, pSVGAState); \
2847 if (RT_UNLIKELY((uintptr_t)(a_PtrVar) < 2)) { if ((uintptr_t)(a_PtrVar) == 1) continue; break; } \
2848 } else do {} while (0)
2849/** @def VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK
2850 * Macro for shortening calls to vmsvgaFIFOGetCmdPayload for refetching the
2851 * buffer after figuring out the actual command size.
2852 *
2853 * Will break out of the switch on failure.
2854 *
2855 * @param a_PtrVar Request variable pointer.
2856 * @param a_Type Request typedef (not pointer) for casting.
2857 * @param a_cbPayloadReq How much payload to fetch.
2858 * @remarks Accesses a bunch of variables in the current scope!
2859 */
2860# define VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(a_PtrVar, a_Type, a_cbPayloadReq) \
2861 if (1) { \
2862 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(a_PtrVar, a_Type, a_cbPayloadReq); \
2863 } else do {} while (0)
2864
2865 /*
2866 * Mark the FIFO as busy.
2867 */
2868 ASMAtomicWriteU32(&pThis->svga.fBusy, VMSVGA_BUSY_F_FIFO);
2869 if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_BUSY, offFifoMin))
2870 ASMAtomicWriteU32(&pFIFO[SVGA_FIFO_BUSY], true);
2871
2872 /*
2873 * Execute all queued FIFO commands.
2874 * Quit if pending external command or changes in the thread state.
2875 */
2876 bool fDone = false;
2877 while ( !(fDone = (pFIFO[SVGA_FIFO_NEXT_CMD] == offCurrentCmd))
2878 && pThread->enmState == PDMTHREADSTATE_RUNNING)
2879 {
2880 uint32_t cbPayload = 0;
2881 uint32_t u32IrqStatus = 0;
2882
2883 Assert(offCurrentCmd < offFifoMax && offCurrentCmd >= offFifoMin);
2884
2885 /* First check any pending actions. */
2886 if (ASMBitTestAndClear(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE_BIT))
2887# ifdef VBOX_WITH_VMSVGA3D
2888 vmsvga3dChangeMode(pThis);
2889# else
2890 {/*nothing*/}
2891# endif
2892 /* Check for pending external commands (reset). */
2893 if (pThis->svga.u8FIFOExtCommand != VMSVGA_FIFO_EXTCMD_NONE)
2894 break;
2895
2896 /*
2897 * Process the command.
2898 */
2899 SVGAFifoCmdId const enmCmdId = (SVGAFifoCmdId)pFIFO[offCurrentCmd / sizeof(uint32_t)];
2900 LogFlow(("vmsvgaFIFOLoop: FIFO command (iCmd=0x%x) %s 0x%x\n",
2901 offCurrentCmd / sizeof(uint32_t), vmsvgaFIFOCmdToString(enmCmdId), enmCmdId));
2902 switch (enmCmdId)
2903 {
2904 case SVGA_CMD_INVALID_CMD:
2905 /* Nothing to do. */
2906 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdInvalidCmd);
2907 break;
2908
2909 case SVGA_CMD_FENCE:
2910 {
2911 SVGAFifoCmdFence *pCmdFence;
2912 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmdFence, SVGAFifoCmdFence, sizeof(*pCmdFence));
2913 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdFence);
2914 if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_FENCE, offFifoMin))
2915 {
2916 Log(("vmsvgaFIFOLoop: SVGA_CMD_FENCE %x\n", pCmdFence->fence));
2917 pFIFO[SVGA_FIFO_FENCE] = pCmdFence->fence;
2918
2919 if (pThis->svga.u32IrqMask & SVGA_IRQFLAG_ANY_FENCE)
2920 {
2921 Log(("vmsvgaFIFOLoop: any fence irq\n"));
2922 u32IrqStatus |= SVGA_IRQFLAG_ANY_FENCE;
2923 }
2924 else
2925 if ( VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_FENCE_GOAL, offFifoMin)
2926 && (pThis->svga.u32IrqMask & SVGA_IRQFLAG_FENCE_GOAL)
2927 && pFIFO[SVGA_FIFO_FENCE_GOAL] == pCmdFence->fence)
2928 {
2929 Log(("vmsvgaFIFOLoop: fence goal reached irq (fence=%x)\n", pCmdFence->fence));
2930 u32IrqStatus |= SVGA_IRQFLAG_FENCE_GOAL;
2931 }
2932 }
2933 else
2934 Log(("SVGA_CMD_FENCE is bogus when offFifoMin is %#x!\n", offFifoMin));
2935 break;
2936 }
2937 case SVGA_CMD_UPDATE:
2938 case SVGA_CMD_UPDATE_VERBOSE:
2939 {
2940 SVGAFifoCmdUpdate *pUpdate;
2941 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pUpdate, SVGAFifoCmdUpdate, sizeof(*pUpdate));
2942 if (enmCmdId == SVGA_CMD_UPDATE)
2943 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdUpdate);
2944 else
2945 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdUpdateVerbose);
2946 Log(("vmsvgaFIFOLoop: UPDATE (%d,%d)(%d,%d)\n", pUpdate->x, pUpdate->y, pUpdate->width, pUpdate->height));
2947 vgaR3UpdateDisplay(pThis, pUpdate->x, pUpdate->y, pUpdate->width, pUpdate->height);
2948 break;
2949 }
2950
2951 case SVGA_CMD_DEFINE_CURSOR:
2952 {
2953 /* Followed by bitmap data. */
2954 SVGAFifoCmdDefineCursor *pCursor;
2955 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCursor, SVGAFifoCmdDefineCursor, sizeof(*pCursor));
2956 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdDefineCursor);
2957 AssertFailed(); /** @todo implement when necessary. */
2958 break;
2959 }
2960
2961 case SVGA_CMD_DEFINE_ALPHA_CURSOR:
2962 {
2963 /* Followed by bitmap data. */
2964 uint32_t cbCursorShape, cbAndMask;
2965 uint8_t *pCursorCopy;
2966 uint32_t cbCmd;
2967
2968 SVGAFifoCmdDefineAlphaCursor *pCursor;
2969 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCursor, SVGAFifoCmdDefineAlphaCursor, sizeof(*pCursor));
2970 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdDefineAlphaCursor);
2971
2972 Log(("vmsvgaFIFOLoop: ALPHA_CURSOR id=%d size (%d,%d) hotspot (%d,%d)\n", pCursor->id, pCursor->width, pCursor->height, pCursor->hotspotX, pCursor->hotspotY));
2973
2974 /* Check against a reasonable upper limit to prevent integer overflows in the sanity checks below. */
2975 AssertBreak(pCursor->height < 2048 && pCursor->width < 2048);
2976
2977 /* Refetch the bitmap data as well. */
2978 cbCmd = sizeof(SVGAFifoCmdDefineAlphaCursor) + pCursor->width * pCursor->height * sizeof(uint32_t) /* 32-bit BRGA format */;
2979 VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pCursor, SVGAFifoCmdDefineAlphaCursor, cbCmd);
2980 /** @todo Would be more efficient to copy the data straight into pCursorCopy (memcpy below). */
2981
2982 /* The mouse pointer interface always expects an AND mask followed by the color data (XOR mask). */
2983 cbAndMask = (pCursor->width + 7) / 8 * pCursor->height; /* size of the AND mask */
2984 cbAndMask = ((cbAndMask + 3) & ~3); /* + gap for alignment */
2985 cbCursorShape = cbAndMask + pCursor->width * sizeof(uint32_t) * pCursor->height; /* + size of the XOR mask (32-bit BRGA format) */
2986
2987 pCursorCopy = (uint8_t *)RTMemAlloc(cbCursorShape);
2988 AssertBreak(pCursorCopy);
2989
2990 Log2(("Cursor data:\n%.*Rhxd\n", pCursor->width * pCursor->height * sizeof(uint32_t), pCursor+1));
2991
2992 /* Transparency is defined by the alpha bytes, so make the whole bitmap visible. */
2993 memset(pCursorCopy, 0xff, cbAndMask);
2994 /* Colour data */
2995 memcpy(pCursorCopy + cbAndMask, (pCursor + 1), pCursor->width * pCursor->height * sizeof(uint32_t));
2996
2997 rc = pThis->pDrv->pfnVBVAMousePointerShape (pThis->pDrv,
2998 true,
2999 true,
3000 pCursor->hotspotX,
3001 pCursor->hotspotY,
3002 pCursor->width,
3003 pCursor->height,
3004 pCursorCopy);
3005 AssertRC(rc);
3006
3007 if (pSVGAState->Cursor.fActive)
3008 RTMemFree(pSVGAState->Cursor.pData);
3009
3010 pSVGAState->Cursor.fActive = true;
3011 pSVGAState->Cursor.xHotspot = pCursor->hotspotX;
3012 pSVGAState->Cursor.yHotspot = pCursor->hotspotY;
3013 pSVGAState->Cursor.width = pCursor->width;
3014 pSVGAState->Cursor.height = pCursor->height;
3015 pSVGAState->Cursor.cbData = cbCursorShape;
3016 pSVGAState->Cursor.pData = pCursorCopy;
3017 break;
3018 }
3019
3020 case SVGA_CMD_ESCAPE:
3021 {
3022 /* Followed by nsize bytes of data. */
3023 SVGAFifoCmdEscape *pEscape;
3024 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pEscape, SVGAFifoCmdEscape, sizeof(*pEscape));
3025 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdEscape);
3026
3027 /* Refetch the command buffer with the variable data; undo size increase (ugly) */
3028 AssertBreak(pEscape->size < VMSVGA_FIFO_SIZE);
3029 uint32_t cbCmd = sizeof(SVGAFifoCmdEscape) + pEscape->size;
3030 VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pEscape, SVGAFifoCmdEscape, cbCmd);
3031
3032 if (pEscape->nsid == SVGA_ESCAPE_NSID_VMWARE)
3033 {
3034 AssertBreak(pEscape->size >= sizeof(uint32_t));
3035 uint32_t cmd = *(uint32_t *)(pEscape + 1);
3036 Log(("vmsvgaFIFOLoop: ESCAPE (%x %x) VMWARE cmd=%x\n", pEscape->nsid, pEscape->size, cmd));
3037
3038 switch (cmd)
3039 {
3040 case SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS:
3041 {
3042 SVGAEscapeVideoSetRegs *pVideoCmd = (SVGAEscapeVideoSetRegs *)(pEscape + 1);
3043 AssertBreak(pEscape->size >= sizeof(pVideoCmd->header));
3044 uint32_t cRegs = (pEscape->size - sizeof(pVideoCmd->header)) / sizeof(pVideoCmd->items[0]);
3045
3046 Log(("SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS: stream %x\n", pVideoCmd->header.streamId));
3047 for (uint32_t iReg = 0; iReg < cRegs; iReg++)
3048 Log(("SVGA_ESCAPE_VMWARE_VIDEO_SET_REGS: reg %x val %x\n", pVideoCmd->items[iReg].registerId, pVideoCmd->items[iReg].value));
3049
3050 RT_NOREF_PV(pVideoCmd);
3051 break;
3052
3053 }
3054
3055 case SVGA_ESCAPE_VMWARE_VIDEO_FLUSH:
3056 {
3057 SVGAEscapeVideoFlush *pVideoCmd = (SVGAEscapeVideoFlush *)(pEscape + 1);
3058 AssertBreak(pEscape->size >= sizeof(*pVideoCmd));
3059 Log(("SVGA_ESCAPE_VMWARE_VIDEO_FLUSH: stream %x\n", pVideoCmd->streamId));
3060 RT_NOREF_PV(pVideoCmd);
3061 break;
3062 }
3063 }
3064 }
3065 else
3066 Log(("vmsvgaFIFOLoop: ESCAPE %x %x\n", pEscape->nsid, pEscape->size));
3067
3068 break;
3069 }
3070# ifdef VBOX_WITH_VMSVGA3D
3071 case SVGA_CMD_DEFINE_GMR2:
3072 {
3073 SVGAFifoCmdDefineGMR2 *pCmd;
3074 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineGMR2, sizeof(*pCmd));
3075 Log(("vmsvgaFIFOLoop: SVGA_CMD_DEFINE_GMR2 id=%x %x pages\n", pCmd->gmrId, pCmd->numPages));
3076 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdDefineGmr2);
3077
3078 /* Validate current GMR id. */
3079 AssertBreak(pCmd->gmrId < VMSVGA_MAX_GMR_IDS);
3080 AssertBreak(pCmd->numPages <= VMSVGA_MAX_GMR_PAGES);
3081
3082 if (!pCmd->numPages)
3083 {
3084 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdDefineGmr2Free);
3085 vmsvgaGMRFree(pThis, pCmd->gmrId);
3086 }
3087 else
3088 {
3089 PGMR pGMR = &pSVGAState->aGMR[pCmd->gmrId];
3090 if (pGMR->cMaxPages)
3091 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdDefineGmr2Modify);
3092
3093 pGMR->cMaxPages = pCmd->numPages;
3094 /* The rest is done by the REMAP_GMR2 command. */
3095 }
3096 break;
3097 }
3098
3099 case SVGA_CMD_REMAP_GMR2:
3100 {
3101 /* Followed by page descriptors or guest ptr. */
3102 SVGAFifoCmdRemapGMR2 *pCmd;
3103 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdRemapGMR2, sizeof(*pCmd));
3104 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdRemapGmr2);
3105
3106 uint32_t cbPageDesc = (pCmd->flags & SVGA_REMAP_GMR2_PPN64) ? sizeof(uint64_t) : sizeof(uint32_t);
3107 uint32_t cbCmd;
3108 uint64_t *paNewPage64 = NULL;
3109
3110 Log(("vmsvgaFIFOLoop: SVGA_CMD_REMAP_GMR2 id=%x flags=%x offset=%x npages=%x\n", pCmd->gmrId, pCmd->flags, pCmd->offsetPages, pCmd->numPages));
3111 AssertBreak(pCmd->gmrId < VMSVGA_MAX_GMR_IDS);
3112
3113 /* Calculate the size of what comes after next and fetch it. */
3114 cbCmd = sizeof(SVGAFifoCmdRemapGMR2);
3115 if (pCmd->flags & SVGA_REMAP_GMR2_VIA_GMR)
3116 cbCmd += sizeof(SVGAGuestPtr);
3117 else
3118 if (pCmd->flags & SVGA_REMAP_GMR2_SINGLE_PPN)
3119 {
3120 cbCmd += cbPageDesc;
3121 pCmd->numPages = 1;
3122 }
3123 else
3124 {
3125 AssertBreak(pCmd->numPages <= VMSVGA_FIFO_SIZE);
3126 cbCmd += cbPageDesc * pCmd->numPages;
3127 }
3128 VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdRemapGMR2, cbCmd);
3129
3130 /* Validate current GMR id. */
3131 AssertBreak(pCmd->gmrId < VMSVGA_MAX_GMR_IDS);
3132 PGMR pGMR = &pSVGAState->aGMR[pCmd->gmrId];
3133 AssertBreak(pCmd->offsetPages + pCmd->numPages <= pGMR->cMaxPages);
3134 AssertBreak(!pCmd->offsetPages || pGMR->paDesc); /** @todo */
3135
3136 /* Save the old page descriptors as an array of page addresses (>> PAGE_SHIFT) */
3137 if (pGMR->paDesc)
3138 {
3139 uint32_t idxPage = 0;
3140 paNewPage64 = (uint64_t *)RTMemAllocZ(pGMR->cMaxPages * sizeof(uint64_t));
3141 AssertBreak(paNewPage64);
3142
3143 for (uint32_t i = 0; i < pGMR->numDescriptors; i++)
3144 {
3145 for (uint32_t j = 0; j < pGMR->paDesc[i].numPages; j++)
3146 {
3147 paNewPage64[idxPage++] = (pGMR->paDesc[i].GCPhys + j * PAGE_SIZE) >> PAGE_SHIFT;
3148 }
3149 }
3150 AssertBreak(idxPage == pGMR->cbTotal >> PAGE_SHIFT);
3151 }
3152
3153 /* Free the old GMR if present. */
3154 if (pGMR->paDesc)
3155 RTMemFree(pGMR->paDesc);
3156
3157 /* Allocate the maximum amount possible (everything non-continuous) */
3158 pGMR->paDesc = (PVMSVGAGMRDESCRIPTOR)RTMemAllocZ(pGMR->cMaxPages * sizeof(VMSVGAGMRDESCRIPTOR));
3159 AssertBreak(pGMR->paDesc);
3160
3161 if (pCmd->flags & SVGA_REMAP_GMR2_VIA_GMR)
3162 {
3163 /** @todo */
3164 AssertFailed();
3165 }
3166 else
3167 {
3168 uint32_t *pPage32 = (uint32_t *)(pCmd + 1);
3169 uint64_t *pPage64 = (uint64_t *)(pCmd + 1);
3170 uint32_t iDescriptor = 0;
3171 RTGCPHYS GCPhys;
3172 bool fGCPhys64 = !!(pCmd->flags & SVGA_REMAP_GMR2_PPN64);
3173
3174 if (paNewPage64)
3175 {
3176 /* Overwrite the old page array with the new page values. */
3177 for (uint32_t i = pCmd->offsetPages; i < pCmd->offsetPages + pCmd->numPages; i++)
3178 {
3179 if (pCmd->flags & SVGA_REMAP_GMR2_PPN64)
3180 paNewPage64[i] = pPage64[i - pCmd->offsetPages];
3181 else
3182 paNewPage64[i] = pPage32[i - pCmd->offsetPages];
3183 }
3184 /* Use the updated page array instead of the command data. */
3185 fGCPhys64 = true;
3186 pPage64 = paNewPage64;
3187 pCmd->numPages = pGMR->cbTotal >> PAGE_SHIFT;
3188 }
3189
3190 if (fGCPhys64)
3191 GCPhys = (pPage64[0] << PAGE_SHIFT) & 0x00000FFFFFFFFFFFULL; /* seeing rubbish in the top bits with certain linux guests*/
3192 else
3193 GCPhys = (RTGCPHYS)pPage32[0] << PAGE_SHIFT;
3194
3195 pGMR->paDesc[0].GCPhys = GCPhys;
3196 pGMR->paDesc[0].numPages = 1;
3197 pGMR->cbTotal = PAGE_SIZE;
3198
3199 for (uint32_t i = 1; i < pCmd->numPages; i++)
3200 {
3201 if (pCmd->flags & SVGA_REMAP_GMR2_PPN64)
3202 GCPhys = (pPage64[i] << PAGE_SHIFT) & 0x00000FFFFFFFFFFFULL; /* seeing rubbish in the top bits with certain linux guests*/
3203 else
3204 GCPhys = (RTGCPHYS)pPage32[i] << PAGE_SHIFT;
3205
3206 /* Continuous physical memory? */
3207 if (GCPhys == pGMR->paDesc[iDescriptor].GCPhys + pGMR->paDesc[iDescriptor].numPages * PAGE_SIZE)
3208 {
3209 Assert(pGMR->paDesc[iDescriptor].numPages);
3210 pGMR->paDesc[iDescriptor].numPages++;
3211 LogFlow(("Page %x GCPhys=%RGp successor\n", i, GCPhys));
3212 }
3213 else
3214 {
3215 iDescriptor++;
3216 pGMR->paDesc[iDescriptor].GCPhys = GCPhys;
3217 pGMR->paDesc[iDescriptor].numPages = 1;
3218 LogFlow(("Page %x GCPhys=%RGp\n", i, pGMR->paDesc[iDescriptor].GCPhys));
3219 }
3220
3221 pGMR->cbTotal += PAGE_SIZE;
3222 }
3223 LogFlow(("Nr of descriptors %x\n", iDescriptor + 1));
3224 pGMR->numDescriptors = iDescriptor + 1;
3225 }
3226
3227 if (paNewPage64)
3228 RTMemFree(paNewPage64);
3229
3230# ifdef DEBUG_GMR_ACCESS
3231 VMR3ReqCallWaitU(PDMDevHlpGetUVM(pThis->pDevInsR3), VMCPUID_ANY, (PFNRT)vmsvgaRegisterGMR, 2, pThis->pDevInsR3, pCmd->gmrId);
3232# endif
3233 break;
3234 }
3235# endif // VBOX_WITH_VMSVGA3D
3236 case SVGA_CMD_DEFINE_SCREEN:
3237 {
3238 /* Note! The size of this command is specified by the guest and depends on capabilities. */
3239 Assert(!(pThis->svga.pFIFOR3[SVGA_FIFO_CAPABILITIES] & SVGA_FIFO_CAP_SCREEN_OBJECT));
3240 SVGAFifoCmdDefineScreen *pCmd;
3241 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineScreen, sizeof(pCmd->screen.structSize));
3242 RT_BZERO(&pCmd->screen.id, sizeof(*pCmd) - RT_OFFSETOF(SVGAFifoCmdDefineScreen, screen.structSize));
3243 VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineScreen, RT_MAX(sizeof(pCmd->screen.structSize), pCmd->screen.structSize));
3244 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdDefineScreen);
3245
3246 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));
3247 if (pCmd->screen.flags & SVGA_SCREEN_HAS_ROOT)
3248 Log(("vmsvgaFIFOLoop: SVGA_CMD_DEFINE_SCREEN flags SVGA_SCREEN_HAS_ROOT\n"));
3249 if (pCmd->screen.flags & SVGA_SCREEN_IS_PRIMARY)
3250 Log(("vmsvgaFIFOLoop: SVGA_CMD_DEFINE_SCREEN flags SVGA_SCREEN_IS_PRIMARY\n"));
3251 if (pCmd->screen.flags & SVGA_SCREEN_FULLSCREEN_HINT)
3252 Log(("vmsvgaFIFOLoop: SVGA_CMD_DEFINE_SCREEN flags SVGA_SCREEN_FULLSCREEN_HINT\n"));
3253 if (pCmd->screen.flags & SVGA_SCREEN_DEACTIVATE )
3254 Log(("vmsvgaFIFOLoop: SVGA_CMD_DEFINE_SCREEN flags SVGA_SCREEN_DEACTIVATE \n"));
3255 if (pCmd->screen.flags & SVGA_SCREEN_BLANKING)
3256 Log(("vmsvgaFIFOLoop: SVGA_CMD_DEFINE_SCREEN flags SVGA_SCREEN_BLANKING\n"));
3257
3258 /** @todo multi monitor support and screen object capabilities. */
3259 pThis->svga.uWidth = pCmd->screen.size.width;
3260 pThis->svga.uHeight = pCmd->screen.size.height;
3261 vmsvgaChangeMode(pThis);
3262 break;
3263 }
3264
3265 case SVGA_CMD_DESTROY_SCREEN:
3266 {
3267 SVGAFifoCmdDestroyScreen *pCmd;
3268 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDestroyScreen, sizeof(*pCmd));
3269 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdDestroyScreen);
3270
3271 Log(("vmsvgaFIFOLoop: SVGA_CMD_DESTROY_SCREEN id=%x\n", pCmd->screenId));
3272 break;
3273 }
3274# ifdef VBOX_WITH_VMSVGA3D
3275 case SVGA_CMD_DEFINE_GMRFB:
3276 {
3277 SVGAFifoCmdDefineGMRFB *pCmd;
3278 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineGMRFB, sizeof(*pCmd));
3279 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdDefineGmrFb);
3280
3281 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));
3282 pSVGAState->GMRFB.ptr = pCmd->ptr;
3283 pSVGAState->GMRFB.bytesPerLine = pCmd->bytesPerLine;
3284 pSVGAState->GMRFB.format = pCmd->format;
3285 break;
3286 }
3287
3288 case SVGA_CMD_BLIT_GMRFB_TO_SCREEN:
3289 {
3290 uint32_t width, height;
3291 SVGAFifoCmdBlitGMRFBToScreen *pCmd;
3292 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdBlitGMRFBToScreen, sizeof(*pCmd));
3293 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdBlitGmrFbToScreen);
3294
3295 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));
3296
3297 /** @todo Support GMRFB.format.s.bitsPerPixel != pThis->svga.uBpp */
3298 AssertBreak(pSVGAState->GMRFB.format.s.bitsPerPixel == pThis->svga.uBpp);
3299 AssertBreak(pCmd->destScreenId == 0);
3300
3301 if (pCmd->destRect.left < 0)
3302 pCmd->destRect.left = 0;
3303 if (pCmd->destRect.top < 0)
3304 pCmd->destRect.top = 0;
3305 if (pCmd->destRect.right < 0)
3306 pCmd->destRect.right = 0;
3307 if (pCmd->destRect.bottom < 0)
3308 pCmd->destRect.bottom = 0;
3309
3310 width = pCmd->destRect.right - pCmd->destRect.left;
3311 height = pCmd->destRect.bottom - pCmd->destRect.top;
3312
3313 if ( width == 0
3314 || height == 0)
3315 break; /* Nothing to do. */
3316
3317 /* Clip to screen dimensions. */
3318 if (width > pThis->svga.uWidth)
3319 width = pThis->svga.uWidth;
3320 if (height > pThis->svga.uHeight)
3321 height = pThis->svga.uHeight;
3322
3323 unsigned offsetSource = (pCmd->srcOrigin.x * pSVGAState->GMRFB.format.s.bitsPerPixel) / 8 + pSVGAState->GMRFB.bytesPerLine * pCmd->srcOrigin.y;
3324 unsigned offsetDest = (pCmd->destRect.left * RT_ALIGN(pThis->svga.uBpp, 8)) / 8 + pThis->svga.cbScanline * pCmd->destRect.top;
3325 unsigned cbCopyWidth = (width * RT_ALIGN(pThis->svga.uBpp, 8)) / 8;
3326
3327 AssertBreak(offsetDest < pThis->vram_size);
3328
3329 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);
3330 AssertRC(rc);
3331 vgaR3UpdateDisplay(pThis, pCmd->destRect.left, pCmd->destRect.top, pCmd->destRect.right - pCmd->destRect.left, pCmd->destRect.bottom - pCmd->destRect.top);
3332 break;
3333 }
3334
3335 case SVGA_CMD_BLIT_SCREEN_TO_GMRFB:
3336 {
3337 SVGAFifoCmdBlitScreenToGMRFB *pCmd;
3338 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdBlitScreenToGMRFB, sizeof(*pCmd));
3339 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdBlitScreentoGmrFb);
3340
3341 /* Note! This can fetch 3d render results as well!! */
3342 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));
3343 AssertFailed();
3344 break;
3345 }
3346# endif // VBOX_WITH_VMSVGA3D
3347 case SVGA_CMD_ANNOTATION_FILL:
3348 {
3349 SVGAFifoCmdAnnotationFill *pCmd;
3350 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdAnnotationFill, sizeof(*pCmd));
3351 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdAnnotationFill);
3352
3353 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));
3354 pSVGAState->colorAnnotation = pCmd->color;
3355 break;
3356 }
3357
3358 case SVGA_CMD_ANNOTATION_COPY:
3359 {
3360 SVGAFifoCmdAnnotationCopy *pCmd;
3361 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdAnnotationCopy, sizeof(*pCmd));
3362 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdAnnotationCopy);
3363
3364 Log(("vmsvgaFIFOLoop: SVGA_CMD_ANNOTATION_COPY\n"));
3365 AssertFailed();
3366 break;
3367 }
3368
3369 /** @todo SVGA_CMD_RECT_COPY - see with ubuntu */
3370
3371 default:
3372# ifdef VBOX_WITH_VMSVGA3D
3373 if ( (int)enmCmdId >= SVGA_3D_CMD_BASE
3374 && (int)enmCmdId < SVGA_3D_CMD_MAX)
3375 {
3376 /* All 3d commands start with a common header, which defines the size of the command. */
3377 SVGA3dCmdHeader *pHdr;
3378 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pHdr, SVGA3dCmdHeader, sizeof(*pHdr));
3379 AssertBreak(pHdr->size < VMSVGA_FIFO_SIZE);
3380 uint32_t cbCmd = sizeof(SVGA3dCmdHeader) + pHdr->size;
3381 VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pHdr, SVGA3dCmdHeader, cbCmd);
3382
3383/**
3384 * Check that the 3D command has at least a_cbMin of payload bytes after the
3385 * header. Will break out of the switch if it doesn't.
3386 */
3387# define VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(a_cbMin) \
3388 AssertMsgBreak((a_cbMin) <= pHdr->size, ("size=%#x a_cbMin=%#zx\n", pHdr->size, (size_t)(a_cbMin)))
3389 switch ((int)enmCmdId)
3390 {
3391 case SVGA_3D_CMD_SURFACE_DEFINE:
3392 {
3393 uint32_t cMipLevels;
3394 SVGA3dCmdDefineSurface *pCmd = (SVGA3dCmdDefineSurface *)(pHdr + 1);
3395 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3396 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSurfaceDefine);
3397
3398 cMipLevels = (pHdr->size - sizeof(*pCmd)) / sizeof(SVGA3dSize);
3399 rc = vmsvga3dSurfaceDefine(pThis, pCmd->sid, (uint32_t)pCmd->surfaceFlags, pCmd->format, pCmd->face, 0,
3400 SVGA3D_TEX_FILTER_NONE, cMipLevels, (SVGA3dSize *)(pCmd + 1));
3401# ifdef DEBUG_GMR_ACCESS
3402 VMR3ReqCallWaitU(PDMDevHlpGetUVM(pThis->pDevInsR3), VMCPUID_ANY, (PFNRT)vmsvgaResetGMRHandlers, 1, pThis);
3403# endif
3404 break;
3405 }
3406
3407 case SVGA_3D_CMD_SURFACE_DEFINE_V2:
3408 {
3409 uint32_t cMipLevels;
3410 SVGA3dCmdDefineSurface_v2 *pCmd = (SVGA3dCmdDefineSurface_v2 *)(pHdr + 1);
3411 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3412 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSurfaceDefineV2);
3413
3414 cMipLevels = (pHdr->size - sizeof(*pCmd)) / sizeof(SVGA3dSize);
3415 rc = vmsvga3dSurfaceDefine(pThis, pCmd->sid, pCmd->surfaceFlags, pCmd->format, pCmd->face,
3416 pCmd->multisampleCount, pCmd->autogenFilter,
3417 cMipLevels, (SVGA3dSize *)(pCmd + 1));
3418 break;
3419 }
3420
3421 case SVGA_3D_CMD_SURFACE_DESTROY:
3422 {
3423 SVGA3dCmdDestroySurface *pCmd = (SVGA3dCmdDestroySurface *)(pHdr + 1);
3424 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3425 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSurfaceDestroy);
3426 rc = vmsvga3dSurfaceDestroy(pThis, pCmd->sid);
3427 break;
3428 }
3429
3430 case SVGA_3D_CMD_SURFACE_COPY:
3431 {
3432 uint32_t cCopyBoxes;
3433 SVGA3dCmdSurfaceCopy *pCmd = (SVGA3dCmdSurfaceCopy *)(pHdr + 1);
3434 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3435 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSurfaceCopy);
3436
3437 cCopyBoxes = (pHdr->size - sizeof(pCmd)) / sizeof(SVGA3dCopyBox);
3438 rc = vmsvga3dSurfaceCopy(pThis, pCmd->dest, pCmd->src, cCopyBoxes, (SVGA3dCopyBox *)(pCmd + 1));
3439 break;
3440 }
3441
3442 case SVGA_3D_CMD_SURFACE_STRETCHBLT:
3443 {
3444 SVGA3dCmdSurfaceStretchBlt *pCmd = (SVGA3dCmdSurfaceStretchBlt *)(pHdr + 1);
3445 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3446 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSurfaceStretchBlt);
3447
3448 rc = vmsvga3dSurfaceStretchBlt(pThis, &pCmd->dest, &pCmd->boxDest, &pCmd->src, &pCmd->boxSrc, pCmd->mode);
3449 break;
3450 }
3451
3452 case SVGA_3D_CMD_SURFACE_DMA:
3453 {
3454 uint32_t cCopyBoxes;
3455 SVGA3dCmdSurfaceDMA *pCmd = (SVGA3dCmdSurfaceDMA *)(pHdr + 1);
3456 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3457 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSurfaceDma);
3458
3459 cCopyBoxes = (pHdr->size - sizeof(*pCmd)) / sizeof(SVGA3dCopyBox);
3460 STAM_PROFILE_START(&pSVGAState->StatR3Cmd3dSurfaceDmaProf, a);
3461 rc = vmsvga3dSurfaceDMA(pThis, pCmd->guest, pCmd->host, pCmd->transfer, cCopyBoxes, (SVGA3dCopyBox *)(pCmd + 1));
3462 STAM_PROFILE_STOP(&pSVGAState->StatR3Cmd3dSurfaceDmaProf, a);
3463 break;
3464 }
3465
3466 case SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN:
3467 {
3468 uint32_t cRects;
3469 SVGA3dCmdBlitSurfaceToScreen *pCmd = (SVGA3dCmdBlitSurfaceToScreen *)(pHdr + 1);
3470 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3471 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSurfaceScreen);
3472
3473 cRects = (pHdr->size - sizeof(*pCmd)) / sizeof(SVGASignedRect);
3474 rc = vmsvga3dSurfaceBlitToScreen(pThis, pCmd->destScreenId, pCmd->destRect, pCmd->srcImage, pCmd->srcRect, cRects, (SVGASignedRect *)(pCmd + 1));
3475 break;
3476 }
3477
3478 case SVGA_3D_CMD_CONTEXT_DEFINE:
3479 {
3480 SVGA3dCmdDefineContext *pCmd = (SVGA3dCmdDefineContext *)(pHdr + 1);
3481 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3482 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dContextDefine);
3483
3484 rc = vmsvga3dContextDefine(pThis, pCmd->cid);
3485 break;
3486 }
3487
3488 case SVGA_3D_CMD_CONTEXT_DESTROY:
3489 {
3490 SVGA3dCmdDestroyContext *pCmd = (SVGA3dCmdDestroyContext *)(pHdr + 1);
3491 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3492 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dContextDestroy);
3493
3494 rc = vmsvga3dContextDestroy(pThis, pCmd->cid);
3495 break;
3496 }
3497
3498 case SVGA_3D_CMD_SETTRANSFORM:
3499 {
3500 SVGA3dCmdSetTransform *pCmd = (SVGA3dCmdSetTransform *)(pHdr + 1);
3501 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3502 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSetTransform);
3503
3504 rc = vmsvga3dSetTransform(pThis, pCmd->cid, pCmd->type, pCmd->matrix);
3505 break;
3506 }
3507
3508 case SVGA_3D_CMD_SETZRANGE:
3509 {
3510 SVGA3dCmdSetZRange *pCmd = (SVGA3dCmdSetZRange *)(pHdr + 1);
3511 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3512 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSetZRange);
3513
3514 rc = vmsvga3dSetZRange(pThis, pCmd->cid, pCmd->zRange);
3515 break;
3516 }
3517
3518 case SVGA_3D_CMD_SETRENDERSTATE:
3519 {
3520 uint32_t cRenderStates;
3521 SVGA3dCmdSetRenderState *pCmd = (SVGA3dCmdSetRenderState *)(pHdr + 1);
3522 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3523 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSetRenderState);
3524
3525 cRenderStates = (pHdr->size - sizeof(*pCmd)) / sizeof(SVGA3dRenderState);
3526 rc = vmsvga3dSetRenderState(pThis, pCmd->cid, cRenderStates, (SVGA3dRenderState *)(pCmd + 1));
3527 break;
3528 }
3529
3530 case SVGA_3D_CMD_SETRENDERTARGET:
3531 {
3532 SVGA3dCmdSetRenderTarget *pCmd = (SVGA3dCmdSetRenderTarget *)(pHdr + 1);
3533 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3534 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSetRenderTarget);
3535
3536 rc = vmsvga3dSetRenderTarget(pThis, pCmd->cid, pCmd->type, pCmd->target);
3537 break;
3538 }
3539
3540 case SVGA_3D_CMD_SETTEXTURESTATE:
3541 {
3542 uint32_t cTextureStates;
3543 SVGA3dCmdSetTextureState *pCmd = (SVGA3dCmdSetTextureState *)(pHdr + 1);
3544 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3545 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSetTextureState);
3546
3547 cTextureStates = (pHdr->size - sizeof(*pCmd)) / sizeof(SVGA3dTextureState);
3548 rc = vmsvga3dSetTextureState(pThis, pCmd->cid, cTextureStates, (SVGA3dTextureState *)(pCmd + 1));
3549 break;
3550 }
3551
3552 case SVGA_3D_CMD_SETMATERIAL:
3553 {
3554 SVGA3dCmdSetMaterial *pCmd = (SVGA3dCmdSetMaterial *)(pHdr + 1);
3555 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3556 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSetMaterial);
3557
3558 rc = vmsvga3dSetMaterial(pThis, pCmd->cid, pCmd->face, &pCmd->material);
3559 break;
3560 }
3561
3562 case SVGA_3D_CMD_SETLIGHTDATA:
3563 {
3564 SVGA3dCmdSetLightData *pCmd = (SVGA3dCmdSetLightData *)(pHdr + 1);
3565 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3566 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSetLightData);
3567
3568 rc = vmsvga3dSetLightData(pThis, pCmd->cid, pCmd->index, &pCmd->data);
3569 break;
3570 }
3571
3572 case SVGA_3D_CMD_SETLIGHTENABLED:
3573 {
3574 SVGA3dCmdSetLightEnabled *pCmd = (SVGA3dCmdSetLightEnabled *)(pHdr + 1);
3575 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3576 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSetLightEnable);
3577
3578 rc = vmsvga3dSetLightEnabled(pThis, pCmd->cid, pCmd->index, pCmd->enabled);
3579 break;
3580 }
3581
3582 case SVGA_3D_CMD_SETVIEWPORT:
3583 {
3584 SVGA3dCmdSetViewport *pCmd = (SVGA3dCmdSetViewport *)(pHdr + 1);
3585 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3586 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSetViewPort);
3587
3588 rc = vmsvga3dSetViewPort(pThis, pCmd->cid, &pCmd->rect);
3589 break;
3590 }
3591
3592 case SVGA_3D_CMD_SETCLIPPLANE:
3593 {
3594 SVGA3dCmdSetClipPlane *pCmd = (SVGA3dCmdSetClipPlane *)(pHdr + 1);
3595 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3596 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSetClipPlane);
3597
3598 rc = vmsvga3dSetClipPlane(pThis, pCmd->cid, pCmd->index, pCmd->plane);
3599 break;
3600 }
3601
3602 case SVGA_3D_CMD_CLEAR:
3603 {
3604 SVGA3dCmdClear *pCmd = (SVGA3dCmdClear *)(pHdr + 1);
3605 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3606 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dClear);
3607
3608 uint32_t cRects;
3609 cRects = (pHdr->size - sizeof(*pCmd)) / sizeof(SVGA3dRect);
3610 rc = vmsvga3dCommandClear(pThis, pCmd->cid, pCmd->clearFlag, pCmd->color, pCmd->depth, pCmd->stencil, cRects, (SVGA3dRect *)(pCmd + 1));
3611 break;
3612 }
3613
3614 case SVGA_3D_CMD_PRESENT:
3615 case SVGA_3D_CMD_PRESENT_READBACK: /** @todo SVGA_3D_CMD_PRESENT_READBACK isn't quite the same as present... */
3616 {
3617 SVGA3dCmdPresent *pCmd = (SVGA3dCmdPresent *)(pHdr + 1);
3618 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3619 if ((unsigned)enmCmdId == SVGA_3D_CMD_PRESENT)
3620 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dPresent);
3621 else
3622 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dPresentReadBack);
3623
3624 uint32_t cRects = (pHdr->size - sizeof(*pCmd)) / sizeof(SVGA3dCopyRect);
3625
3626 STAM_PROFILE_START(&pSVGAState->StatR3Cmd3dPresentProf, a);
3627 rc = vmsvga3dCommandPresent(pThis, pCmd->sid, cRects, (SVGA3dCopyRect *)(pCmd + 1));
3628 STAM_PROFILE_STOP(&pSVGAState->StatR3Cmd3dPresentProf, a);
3629 break;
3630 }
3631
3632 case SVGA_3D_CMD_SHADER_DEFINE:
3633 {
3634 SVGA3dCmdDefineShader *pCmd = (SVGA3dCmdDefineShader *)(pHdr + 1);
3635 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3636 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dShaderDefine);
3637
3638 uint32_t cbData = (pHdr->size - sizeof(*pCmd));
3639 rc = vmsvga3dShaderDefine(pThis, pCmd->cid, pCmd->shid, pCmd->type, cbData, (uint32_t *)(pCmd + 1));
3640 break;
3641 }
3642
3643 case SVGA_3D_CMD_SHADER_DESTROY:
3644 {
3645 SVGA3dCmdDestroyShader *pCmd = (SVGA3dCmdDestroyShader *)(pHdr + 1);
3646 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3647 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dShaderDestroy);
3648
3649 rc = vmsvga3dShaderDestroy(pThis, pCmd->cid, pCmd->shid, pCmd->type);
3650 break;
3651 }
3652
3653 case SVGA_3D_CMD_SET_SHADER:
3654 {
3655 SVGA3dCmdSetShader *pCmd = (SVGA3dCmdSetShader *)(pHdr + 1);
3656 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3657 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSetShader);
3658
3659 rc = vmsvga3dShaderSet(pThis, NULL, pCmd->cid, pCmd->type, pCmd->shid);
3660 break;
3661 }
3662
3663 case SVGA_3D_CMD_SET_SHADER_CONST:
3664 {
3665 SVGA3dCmdSetShaderConst *pCmd = (SVGA3dCmdSetShaderConst *)(pHdr + 1);
3666 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3667 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSetShaderConst);
3668
3669 uint32_t cRegisters = (pHdr->size - sizeof(*pCmd)) / sizeof(pCmd->values) + 1;
3670 rc = vmsvga3dShaderSetConst(pThis, pCmd->cid, pCmd->reg, pCmd->type, pCmd->ctype, cRegisters, pCmd->values);
3671 break;
3672 }
3673
3674 case SVGA_3D_CMD_DRAW_PRIMITIVES:
3675 {
3676 SVGA3dCmdDrawPrimitives *pCmd = (SVGA3dCmdDrawPrimitives *)(pHdr + 1);
3677 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3678 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dDrawPrimitives);
3679
3680 uint32_t cVertexDivisor = (pHdr->size - sizeof(*pCmd) - sizeof(SVGA3dVertexDecl) * pCmd->numVertexDecls - sizeof(SVGA3dPrimitiveRange) * pCmd->numRanges);
3681 Assert(pCmd->numRanges <= SVGA3D_MAX_DRAW_PRIMITIVE_RANGES);
3682 Assert(pCmd->numVertexDecls <= SVGA3D_MAX_VERTEX_ARRAYS);
3683 Assert(!cVertexDivisor || cVertexDivisor == pCmd->numVertexDecls);
3684
3685 SVGA3dVertexDecl *pVertexDecl = (SVGA3dVertexDecl *)(pCmd + 1);
3686 SVGA3dPrimitiveRange *pNumRange = (SVGA3dPrimitiveRange *) (&pVertexDecl[pCmd->numVertexDecls]);
3687 SVGA3dVertexDivisor *pVertexDivisor = (cVertexDivisor) ? (SVGA3dVertexDivisor *)(&pNumRange[pCmd->numRanges]) : NULL;
3688
3689 STAM_PROFILE_START(&pSVGAState->StatR3Cmd3dDrawPrimitivesProf, a);
3690 rc = vmsvga3dDrawPrimitives(pThis, pCmd->cid, pCmd->numVertexDecls, pVertexDecl, pCmd->numRanges, pNumRange, cVertexDivisor, pVertexDivisor);
3691 STAM_PROFILE_STOP(&pSVGAState->StatR3Cmd3dDrawPrimitivesProf, a);
3692 break;
3693 }
3694
3695 case SVGA_3D_CMD_SETSCISSORRECT:
3696 {
3697 SVGA3dCmdSetScissorRect *pCmd = (SVGA3dCmdSetScissorRect *)(pHdr + 1);
3698 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3699 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dSetScissorRect);
3700
3701 rc = vmsvga3dSetScissorRect(pThis, pCmd->cid, &pCmd->rect);
3702 break;
3703 }
3704
3705 case SVGA_3D_CMD_BEGIN_QUERY:
3706 {
3707 SVGA3dCmdBeginQuery *pCmd = (SVGA3dCmdBeginQuery *)(pHdr + 1);
3708 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3709 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dBeginQuery);
3710
3711 rc = vmsvga3dQueryBegin(pThis, pCmd->cid, pCmd->type);
3712 break;
3713 }
3714
3715 case SVGA_3D_CMD_END_QUERY:
3716 {
3717 SVGA3dCmdEndQuery *pCmd = (SVGA3dCmdEndQuery *)(pHdr + 1);
3718 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3719 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dEndQuery);
3720
3721 rc = vmsvga3dQueryEnd(pThis, pCmd->cid, pCmd->type, pCmd->guestResult);
3722 break;
3723 }
3724
3725 case SVGA_3D_CMD_WAIT_FOR_QUERY:
3726 {
3727 SVGA3dCmdWaitForQuery *pCmd = (SVGA3dCmdWaitForQuery *)(pHdr + 1);
3728 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3729 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dWaitForQuery);
3730
3731 rc = vmsvga3dQueryWait(pThis, pCmd->cid, pCmd->type, pCmd->guestResult);
3732 break;
3733 }
3734
3735 case SVGA_3D_CMD_GENERATE_MIPMAPS:
3736 {
3737 SVGA3dCmdGenerateMipmaps *pCmd = (SVGA3dCmdGenerateMipmaps *)(pHdr + 1);
3738 VMSVGAFIFO_CHECK_3D_CMD_MIN_SIZE_BREAK(sizeof(*pCmd));
3739 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dGenerateMipmaps);
3740
3741 rc = vmsvga3dGenerateMipmaps(pThis, pCmd->sid, pCmd->filter);
3742 break;
3743 }
3744
3745 case SVGA_3D_CMD_ACTIVATE_SURFACE:
3746 /* context id + surface id? */
3747 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dActivateSurface);
3748 break;
3749 case SVGA_3D_CMD_DEACTIVATE_SURFACE:
3750 /* context id + surface id? */
3751 STAM_REL_COUNTER_INC(&pSVGAState->StatR3Cmd3dDeactivateSurface);
3752 break;
3753
3754 default:
3755 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoUnkCmds);
3756 AssertMsgFailed(("enmCmdId=%d\n", enmCmdId));
3757 break;
3758 }
3759 }
3760 else
3761# endif // VBOX_WITH_VMSVGA3D
3762 {
3763 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoUnkCmds);
3764 AssertMsgFailed(("enmCmdId=%d\n", enmCmdId));
3765 }
3766 }
3767
3768 /* Go to the next slot */
3769 Assert(cbPayload + sizeof(uint32_t) <= offFifoMax - offFifoMin);
3770 offCurrentCmd += RT_ALIGN_32(cbPayload + sizeof(uint32_t), sizeof(uint32_t));
3771 if (offCurrentCmd >= offFifoMax)
3772 {
3773 offCurrentCmd -= offFifoMax - offFifoMin;
3774 Assert(offCurrentCmd >= offFifoMin);
3775 Assert(offCurrentCmd < offFifoMax);
3776 }
3777 ASMAtomicWriteU32(&pFIFO[SVGA_FIFO_STOP], offCurrentCmd);
3778 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoCommands);
3779
3780 /*
3781 * Raise IRQ if required. Must enter the critical section here
3782 * before making final decisions here, otherwise cubebench and
3783 * others may end up waiting forever.
3784 */
3785 if ( u32IrqStatus
3786 || (pThis->svga.u32IrqMask & SVGA_IRQFLAG_FIFO_PROGRESS))
3787 {
3788 int rc2 = PDMCritSectEnter(&pThis->CritSect, VERR_IGNORED);
3789 AssertRC(rc2);
3790
3791 /* FIFO progress might trigger an interrupt. */
3792 if (pThis->svga.u32IrqMask & SVGA_IRQFLAG_FIFO_PROGRESS)
3793 {
3794 Log(("vmsvgaFIFOLoop: fifo progress irq\n"));
3795 u32IrqStatus |= SVGA_IRQFLAG_FIFO_PROGRESS;
3796 }
3797
3798 /* Unmasked IRQ pending? */
3799 if (pThis->svga.u32IrqMask & u32IrqStatus)
3800 {
3801 Log(("vmsvgaFIFOLoop: Trigger interrupt with status %x\n", u32IrqStatus));
3802 ASMAtomicOrU32(&pThis->svga.u32IrqStatus, u32IrqStatus);
3803 PDMDevHlpPCISetIrq(pDevIns, 0, 1);
3804 }
3805
3806 PDMCritSectLeave(&pThis->CritSect);
3807 }
3808 }
3809
3810 /* If really done, clear the busy flag. */
3811 if (fDone)
3812 {
3813 Log(("vmsvgaFIFOLoop: emptied the FIFO next=%x stop=%x\n", pFIFO[SVGA_FIFO_NEXT_CMD], offCurrentCmd));
3814 vmsvgaFifoSetNotBusy(pThis, pSVGAState, offFifoMin);
3815 }
3816 }
3817
3818 /*
3819 * Free the bounce buffer. (There are no returns above!)
3820 */
3821 RTMemFree(pbBounceBuf);
3822
3823 return VINF_SUCCESS;
3824}
3825
3826/**
3827 * Free the specified GMR
3828 *
3829 * @param pThis VGA device instance data.
3830 * @param idGMR GMR id
3831 */
3832void vmsvgaGMRFree(PVGASTATE pThis, uint32_t idGMR)
3833{
3834 PVMSVGAR3STATE pSVGAState = pThis->svga.pSvgaR3State;
3835
3836 /* Free the old descriptor if present. */
3837 if (pSVGAState->aGMR[idGMR].numDescriptors)
3838 {
3839 PGMR pGMR = &pSVGAState->aGMR[idGMR];
3840# ifdef DEBUG_GMR_ACCESS
3841 VMR3ReqCallWaitU(PDMDevHlpGetUVM(pThis->pDevInsR3), VMCPUID_ANY, (PFNRT)vmsvgaDeregisterGMR, 2, pThis->pDevInsR3, idGMR);
3842# endif
3843
3844 Assert(pGMR->paDesc);
3845 RTMemFree(pGMR->paDesc);
3846 pGMR->paDesc = NULL;
3847 pGMR->numDescriptors = 0;
3848 pGMR->cbTotal = 0;
3849 pGMR->cMaxPages = 0;
3850 }
3851 Assert(!pSVGAState->aGMR[idGMR].cbTotal);
3852}
3853
3854/**
3855 * Copy from a GMR to host memory or vice versa
3856 *
3857 * @returns VBox status code.
3858 * @param pThis VGA device instance data.
3859 * @param enmTransferType Transfer type (read/write)
3860 * @param pbDst Host destination pointer
3861 * @param cbDestPitch Destination buffer pitch
3862 * @param src GMR description
3863 * @param offSrc Source buffer offset
3864 * @param cbSrcPitch Source buffer pitch
3865 * @param cbWidth Source width in bytes
3866 * @param cHeight Source height
3867 */
3868int vmsvgaGMRTransfer(PVGASTATE pThis, const SVGA3dTransferType enmTransferType, uint8_t *pbDst, int32_t cbDestPitch,
3869 SVGAGuestPtr src, uint32_t offSrc, int32_t cbSrcPitch, uint32_t cbWidth, uint32_t cHeight)
3870{
3871 PVMSVGAR3STATE pSVGAState = pThis->svga.pSvgaR3State;
3872 PGMR pGMR;
3873 int rc;
3874 PVMSVGAGMRDESCRIPTOR pDesc;
3875 unsigned offDesc = 0;
3876
3877 Log(("vmsvgaGMRTransfer: gmr=%x offset=%x pitch=%d cbWidth=%d cHeight=%d; src offset=%d src pitch=%d\n",
3878 src.gmrId, src.offset, cbDestPitch, cbWidth, cHeight, offSrc, cbSrcPitch));
3879 Assert(cbWidth && cHeight);
3880
3881 /* Shortcut for the framebuffer. */
3882 if (src.gmrId == SVGA_GMR_FRAMEBUFFER)
3883 {
3884 offSrc += src.offset;
3885 AssertMsgReturn(src.offset < pThis->vram_size,
3886 ("src.offset=%#x offSrc=%#x cbSrcPitch=%#x cHeight=%#x cbWidth=%#x vram_size=%#x\n",
3887 src.offset, offSrc, cbSrcPitch, cHeight, cbWidth, pThis->vram_size),
3888 VERR_INVALID_PARAMETER);
3889 AssertMsgReturn(offSrc + cbSrcPitch * (cHeight - 1) + cbWidth <= pThis->vram_size,
3890 ("src.offset=%#x offSrc=%#x cbSrcPitch=%#x cHeight=%#x cbWidth=%#x vram_size=%#x\n",
3891 src.offset, offSrc, cbSrcPitch, cHeight, cbWidth, pThis->vram_size),
3892 VERR_INVALID_PARAMETER);
3893
3894 uint8_t *pSrc = pThis->CTX_SUFF(vram_ptr) + offSrc;
3895
3896 if (enmTransferType == SVGA3D_READ_HOST_VRAM)
3897 {
3898 /* switch src & dest */
3899 uint8_t *pTemp = pbDst;
3900 int32_t cbTempPitch = cbDestPitch;
3901
3902 pbDst = pSrc;
3903 pSrc = pTemp;
3904
3905 cbDestPitch = cbSrcPitch;
3906 cbSrcPitch = cbTempPitch;
3907 }
3908
3909 if ( pThis->svga.cbScanline == (uint32_t)cbDestPitch
3910 && cbWidth == (uint32_t)cbDestPitch
3911 && cbSrcPitch == cbDestPitch)
3912 {
3913 memcpy(pbDst, pSrc, cbWidth * cHeight);
3914 }
3915 else
3916 {
3917 for(uint32_t i = 0; i < cHeight; i++)
3918 {
3919 memcpy(pbDst, pSrc, cbWidth);
3920
3921 pbDst += cbDestPitch;
3922 pSrc += cbSrcPitch;
3923 }
3924 }
3925 return VINF_SUCCESS;
3926 }
3927
3928 AssertReturn(src.gmrId < VMSVGA_MAX_GMR_IDS, VERR_INVALID_PARAMETER);
3929 pGMR = &pSVGAState->aGMR[src.gmrId];
3930 pDesc = pGMR->paDesc;
3931
3932 offSrc += src.offset;
3933 AssertMsgReturn(src.offset < pGMR->cbTotal,
3934 ("src.gmrId=%#x src.offset=%#x offSrc=%#x cbSrcPitch=%#x cHeight=%#x cbWidth=%#x cbTotal=%#x\n",
3935 src.gmrId, src.offset, offSrc, cbSrcPitch, cHeight, cbWidth, pGMR->cbTotal),
3936 VERR_INVALID_PARAMETER);
3937 AssertMsgReturn(offSrc + cbSrcPitch * (cHeight - 1) + cbWidth <= pGMR->cbTotal,
3938 ("src.gmrId=%#x src.offset=%#x offSrc=%#x cbSrcPitch=%#x cHeight=%#x cbWidth=%#x cbTotal=%#x\n",
3939 src.gmrId, src.offset, offSrc, cbSrcPitch, cHeight, cbWidth, pGMR->cbTotal),
3940 VERR_INVALID_PARAMETER);
3941
3942 for (uint32_t i = 0; i < cHeight; i++)
3943 {
3944 uint32_t cbCurrentWidth = cbWidth;
3945 uint32_t offCurrent = offSrc;
3946 uint8_t *pCurrentDest = pbDst;
3947
3948 /* Find the right descriptor */
3949 while (offDesc + pDesc->numPages * PAGE_SIZE <= offCurrent)
3950 {
3951 offDesc += pDesc->numPages * PAGE_SIZE;
3952 AssertReturn(offDesc < pGMR->cbTotal, VERR_INTERNAL_ERROR); /* overflow protection */
3953 pDesc++;
3954 }
3955
3956 while (cbCurrentWidth)
3957 {
3958 uint32_t cbToCopy;
3959
3960 if (offCurrent + cbCurrentWidth <= offDesc + pDesc->numPages * PAGE_SIZE)
3961 {
3962 cbToCopy = cbCurrentWidth;
3963 }
3964 else
3965 {
3966 cbToCopy = (offDesc + pDesc->numPages * PAGE_SIZE - offCurrent);
3967 AssertReturn(cbToCopy <= cbCurrentWidth, VERR_INVALID_PARAMETER);
3968 }
3969
3970 LogFlow(("vmsvgaGMRTransfer: %s phys=%RGp\n", (enmTransferType == SVGA3D_WRITE_HOST_VRAM) ? "READ" : "WRITE", pDesc->GCPhys + offCurrent - offDesc));
3971
3972 if (enmTransferType == SVGA3D_WRITE_HOST_VRAM)
3973 rc = PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), pDesc->GCPhys + offCurrent - offDesc, pCurrentDest, cbToCopy);
3974 else
3975 rc = PDMDevHlpPhysWrite(pThis->CTX_SUFF(pDevIns), pDesc->GCPhys + offCurrent - offDesc, pCurrentDest, cbToCopy);
3976 AssertRCBreak(rc);
3977
3978 cbCurrentWidth -= cbToCopy;
3979 offCurrent += cbToCopy;
3980 pCurrentDest += cbToCopy;
3981
3982 /* Go to the next descriptor if there's anything left. */
3983 if (cbCurrentWidth)
3984 {
3985 offDesc += pDesc->numPages * PAGE_SIZE;
3986 pDesc++;
3987 }
3988 }
3989
3990 offSrc += cbSrcPitch;
3991 pbDst += cbDestPitch;
3992 }
3993
3994 return VINF_SUCCESS;
3995}
3996
3997/**
3998 * Unblock the FIFO I/O thread so it can respond to a state change.
3999 *
4000 * @returns VBox status code.
4001 * @param pDevIns The VGA device instance.
4002 * @param pThread The send thread.
4003 */
4004static DECLCALLBACK(int) vmsvgaFIFOLoopWakeUp(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
4005{
4006 RT_NOREF(pDevIns);
4007 PVGASTATE pThis = (PVGASTATE)pThread->pvUser;
4008 Log(("vmsvgaFIFOLoopWakeUp\n"));
4009 return SUPSemEventSignal(pThis->svga.pSupDrvSession, pThis->svga.FIFORequestSem);
4010}
4011
4012/**
4013 * Enables or disables dirty page tracking for the framebuffer
4014 *
4015 * @param pThis VGA device instance data.
4016 * @param fTraces Enable/disable traces
4017 */
4018static void vmsvgaSetTraces(PVGASTATE pThis, bool fTraces)
4019{
4020 if ( (!pThis->svga.fConfigured || !pThis->svga.fEnabled)
4021 && !fTraces)
4022 {
4023 //Assert(pThis->svga.fTraces);
4024 Log(("vmsvgaSetTraces: *not* allowed to disable dirty page tracking when the device is in legacy mode.\n"));
4025 return;
4026 }
4027
4028 pThis->svga.fTraces = fTraces;
4029 if (pThis->svga.fTraces)
4030 {
4031 unsigned cbFrameBuffer = pThis->vram_size;
4032
4033 Log(("vmsvgaSetTraces: enable dirty page handling for the frame buffer only (%x bytes)\n", 0));
4034 if (pThis->svga.uHeight != VMSVGA_VAL_UNINITIALIZED)
4035 {
4036#ifndef DEBUG_bird /* BB-10.3.1 triggers this as it initializes everything to zero. Better just ignore it. */
4037 Assert(pThis->svga.cbScanline);
4038#endif
4039 /* Hardware enabled; return real framebuffer size .*/
4040 cbFrameBuffer = (uint32_t)pThis->svga.uHeight * pThis->svga.cbScanline;
4041 cbFrameBuffer = RT_ALIGN(cbFrameBuffer, PAGE_SIZE);
4042 }
4043
4044 if (!pThis->svga.fVRAMTracking)
4045 {
4046 Log(("vmsvgaSetTraces: enable frame buffer dirty page tracking. (%x bytes; vram %x)\n", cbFrameBuffer, pThis->vram_size));
4047 vgaR3RegisterVRAMHandler(pThis, cbFrameBuffer);
4048 pThis->svga.fVRAMTracking = true;
4049 }
4050 }
4051 else
4052 {
4053 if (pThis->svga.fVRAMTracking)
4054 {
4055 Log(("vmsvgaSetTraces: disable frame buffer dirty page tracking\n"));
4056 vgaR3UnregisterVRAMHandler(pThis);
4057 pThis->svga.fVRAMTracking = false;
4058 }
4059 }
4060}
4061
4062/**
4063 * @callback_method_impl{FNPCIIOREGIONMAP}
4064 */
4065DECLCALLBACK(int) vmsvgaR3IORegionMap(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion,
4066 RTGCPHYS GCPhysAddress, RTGCPHYS cb, PCIADDRESSSPACE enmType)
4067{
4068 int rc;
4069 PVGASTATE pThis = PDMINS_2_DATA(pDevIns, PVGASTATE);
4070
4071 Log(("vgasvgaR3IORegionMap: iRegion=%d GCPhysAddress=%RGp cb=%RGp enmType=%d\n", iRegion, GCPhysAddress, cb, enmType));
4072 if (enmType == PCI_ADDRESS_SPACE_IO)
4073 {
4074 AssertReturn(iRegion == 0, VERR_INTERNAL_ERROR);
4075 rc = PDMDevHlpIOPortRegister(pDevIns, (RTIOPORT)GCPhysAddress, cb, 0,
4076 vmsvgaIOWrite, vmsvgaIORead, NULL /* OutStr */, NULL /* InStr */, "VMSVGA");
4077 if (RT_FAILURE(rc))
4078 return rc;
4079 if (pThis->fR0Enabled)
4080 {
4081 rc = PDMDevHlpIOPortRegisterR0(pDevIns, (RTIOPORT)GCPhysAddress, cb, 0,
4082 "vmsvgaIOWrite", "vmsvgaIORead", NULL, NULL, "VMSVGA");
4083 if (RT_FAILURE(rc))
4084 return rc;
4085 }
4086 if (pThis->fGCEnabled)
4087 {
4088 rc = PDMDevHlpIOPortRegisterRC(pDevIns, (RTIOPORT)GCPhysAddress, cb, 0,
4089 "vmsvgaIOWrite", "vmsvgaIORead", NULL, NULL, "VMSVGA");
4090 if (RT_FAILURE(rc))
4091 return rc;
4092 }
4093
4094 pThis->svga.BasePort = GCPhysAddress;
4095 Log(("vmsvgaR3IORegionMap: base port = %x\n", pThis->svga.BasePort));
4096 }
4097 else
4098 {
4099 AssertReturn(iRegion == 2 && enmType == PCI_ADDRESS_SPACE_MEM, VERR_INTERNAL_ERROR);
4100 if (GCPhysAddress != NIL_RTGCPHYS)
4101 {
4102 /*
4103 * Mapping the FIFO RAM.
4104 */
4105 rc = PDMDevHlpMMIOExMap(pDevIns, pPciDev, iRegion, GCPhysAddress);
4106 AssertRC(rc);
4107
4108# ifdef DEBUG_FIFO_ACCESS
4109 if (RT_SUCCESS(rc))
4110 {
4111 rc = PGMHandlerPhysicalRegister(PDMDevHlpGetVM(pDevIns), GCPhysAddress, GCPhysAddress + (VMSVGA_FIFO_SIZE - 1),
4112 pThis->svga.hFifoAccessHandlerType, pThis, NIL_RTR0PTR, NIL_RTRCPTR,
4113 "VMSVGA FIFO");
4114 AssertRC(rc);
4115 }
4116# endif
4117 if (RT_SUCCESS(rc))
4118 {
4119 pThis->svga.GCPhysFIFO = GCPhysAddress;
4120 Log(("vmsvgaR3IORegionMap: FIFO address = %RGp\n", GCPhysAddress));
4121 }
4122 }
4123 else
4124 {
4125 Assert(pThis->svga.GCPhysFIFO);
4126# ifdef DEBUG_FIFO_ACCESS
4127 rc = PGMHandlerPhysicalDeregister(PDMDevHlpGetVM(pDevIns), pThis->svga.GCPhysFIFO);
4128 AssertRC(rc);
4129# endif
4130 pThis->svga.GCPhysFIFO = 0;
4131 }
4132
4133 }
4134 return VINF_SUCCESS;
4135}
4136
4137# ifdef VBOX_WITH_VMSVGA3D
4138
4139/**
4140 * Used by vmsvga3dInfoSurfaceWorker to make the FIFO thread to save one or all
4141 * surfaces to VMSVGA3DMIPMAPLEVEL::pSurfaceData heap buffers.
4142 *
4143 * @param pThis The VGA device instance data.
4144 * @param sid Either UINT32_MAX or the ID of a specific
4145 * surface. If UINT32_MAX is used, all surfaces
4146 * are processed.
4147 */
4148void vmsvga3dSurfaceUpdateHeapBuffersOnFifoThread(PVGASTATE pThis, uint32_t sid)
4149{
4150 vmsvgaR3RunExtCmdOnFifoThread(pThis, VMSVGA_FIFO_EXTCMD_UPDATE_SURFACE_HEAP_BUFFERS, (void *)(uintptr_t)sid,
4151 sid == UINT32_MAX ? 10 * RT_MS_1SEC : RT_MS_1MIN);
4152}
4153
4154
4155/**
4156 * @callback_method_impl{FNDBGFHANDLERDEV, "vmsvga3dsfc"}
4157 */
4158DECLCALLBACK(void) vmsvgaR3Info3dSurface(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
4159{
4160 /* There might be a specific context ID at the start of the
4161 arguments, if not show all contexts. */
4162 uint32_t cid = UINT32_MAX;
4163 if (pszArgs)
4164 pszArgs = RTStrStripL(pszArgs);
4165 if (pszArgs && RT_C_IS_DIGIT(*pszArgs))
4166 cid = RTStrToUInt32(pszArgs);
4167
4168 /* Verbose or terse display, we default to verbose. */
4169 bool fVerbose = true;
4170 if (RTStrIStr(pszArgs, "terse"))
4171 fVerbose = false;
4172
4173 /* The size of the ascii art (x direction, y is 3/4 of x). */
4174 uint32_t cxAscii = 80;
4175 if (RTStrIStr(pszArgs, "gigantic"))
4176 cxAscii = 300;
4177 else if (RTStrIStr(pszArgs, "huge"))
4178 cxAscii = 180;
4179 else if (RTStrIStr(pszArgs, "big"))
4180 cxAscii = 132;
4181 else if (RTStrIStr(pszArgs, "normal"))
4182 cxAscii = 80;
4183 else if (RTStrIStr(pszArgs, "medium"))
4184 cxAscii = 64;
4185 else if (RTStrIStr(pszArgs, "small"))
4186 cxAscii = 48;
4187 else if (RTStrIStr(pszArgs, "tiny"))
4188 cxAscii = 24;
4189
4190 /* Y invert the image when producing the ASCII art. */
4191 bool fInvY = false;
4192 if (RTStrIStr(pszArgs, "invy"))
4193 fInvY = true;
4194
4195 vmsvga3dInfoSurfaceWorker(PDMINS_2_DATA(pDevIns, PVGASTATE), pHlp, cid, fVerbose, cxAscii, fInvY);
4196}
4197
4198
4199/**
4200 * @callback_method_impl{FNDBGFHANDLERDEV, "vmsvga3dctx"}
4201 */
4202DECLCALLBACK(void) vmsvgaR3Info3dContext(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
4203{
4204 /* There might be a specific surface ID at the start of the
4205 arguments, if not show all contexts. */
4206 uint32_t sid = UINT32_MAX;
4207 if (pszArgs)
4208 pszArgs = RTStrStripL(pszArgs);
4209 if (pszArgs && RT_C_IS_DIGIT(*pszArgs))
4210 sid = RTStrToUInt32(pszArgs);
4211
4212 /* Verbose or terse display, we default to verbose. */
4213 bool fVerbose = true;
4214 if (RTStrIStr(pszArgs, "terse"))
4215 fVerbose = false;
4216
4217 vmsvga3dInfoContextWorker(PDMINS_2_DATA(pDevIns, PVGASTATE), pHlp, sid, fVerbose);
4218}
4219
4220# endif /* VBOX_WITH_VMSVGA3D */
4221
4222/**
4223 * @callback_method_impl{FNDBGFHANDLERDEV, "vmsvga"}
4224 */
4225static DECLCALLBACK(void) vmsvgaR3Info(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
4226{
4227 RT_NOREF(pszArgs);
4228 PVGASTATE pThis = PDMINS_2_DATA(pDevIns, PVGASTATE);
4229 PVMSVGAR3STATE pSVGAState = pThis->svga.pSvgaR3State;
4230
4231 pHlp->pfnPrintf(pHlp, "Extension enabled: %RTbool\n", pThis->svga.fEnabled);
4232 pHlp->pfnPrintf(pHlp, "Configured: %RTbool\n", pThis->svga.fConfigured);
4233 pHlp->pfnPrintf(pHlp, "Base I/O port: %#x\n", pThis->svga.BasePort);
4234 pHlp->pfnPrintf(pHlp, "FIFO address: %RGp\n", pThis->svga.GCPhysFIFO);
4235 pHlp->pfnPrintf(pHlp, "FIFO size: %u (%#x)\n", pThis->svga.cbFIFO, pThis->svga.cbFIFO);
4236 pHlp->pfnPrintf(pHlp, "FIFO external cmd: %#x\n", pThis->svga.u8FIFOExtCommand);
4237 pHlp->pfnPrintf(pHlp, "FIFO extcmd wakeup: %u\n", pThis->svga.fFifoExtCommandWakeup);
4238 pHlp->pfnPrintf(pHlp, "Busy: %#x\n", pThis->svga.fBusy);
4239 pHlp->pfnPrintf(pHlp, "Traces: %RTbool (effective: %RTbool)\n", pThis->svga.fTraces, pThis->svga.fVRAMTracking);
4240 pHlp->pfnPrintf(pHlp, "Guest ID: %#x (%d)\n", pThis->svga.u32GuestId, pThis->svga.u32GuestId);
4241 pHlp->pfnPrintf(pHlp, "IRQ status: %#x\n", pThis->svga.u32IrqStatus);
4242 pHlp->pfnPrintf(pHlp, "IRQ mask: %#x\n", pThis->svga.u32IrqMask);
4243 pHlp->pfnPrintf(pHlp, "Pitch lock: %#x\n", pThis->svga.u32PitchLock);
4244 pHlp->pfnPrintf(pHlp, "Current GMR ID: %#x\n", pThis->svga.u32CurrentGMRId);
4245 pHlp->pfnPrintf(pHlp, "Capabilites reg: %#x\n", pThis->svga.u32RegCaps);
4246 pHlp->pfnPrintf(pHlp, "Index reg: %#x\n", pThis->svga.u32IndexReg);
4247 pHlp->pfnPrintf(pHlp, "Action flags: %#x\n", pThis->svga.u32ActionFlags);
4248 pHlp->pfnPrintf(pHlp, "Max display size: %ux%u\n", pThis->svga.u32MaxWidth, pThis->svga.u32MaxHeight);
4249 pHlp->pfnPrintf(pHlp, "Display size: %ux%u %ubpp\n", pThis->svga.uWidth, pThis->svga.uHeight, pThis->svga.uBpp);
4250 pHlp->pfnPrintf(pHlp, "Scanline: %u (%#x)\n", pThis->svga.cbScanline, pThis->svga.cbScanline);
4251 pHlp->pfnPrintf(pHlp, "Viewport position: %ux%u\n", pThis->svga.viewport.x, pThis->svga.viewport.y);
4252 pHlp->pfnPrintf(pHlp, "Viewport size: %ux%u\n", pThis->svga.viewport.cx, pThis->svga.viewport.cy);
4253
4254 pHlp->pfnPrintf(pHlp, "Cursor active: %RTbool\n", pSVGAState->Cursor.fActive);
4255 pHlp->pfnPrintf(pHlp, "Cursor hotspot: %ux%u\n", pSVGAState->Cursor.xHotspot, pSVGAState->Cursor.yHotspot);
4256 pHlp->pfnPrintf(pHlp, "Cursor size: %ux%u\n", pSVGAState->Cursor.width, pSVGAState->Cursor.height);
4257 pHlp->pfnPrintf(pHlp, "Cursor byte size: %u (%#x)\n", pSVGAState->Cursor.cbData, pSVGAState->Cursor.cbData);
4258
4259# ifdef VBOX_WITH_VMSVGA3D
4260 pHlp->pfnPrintf(pHlp, "3D enabled: %RTbool\n", pThis->svga.f3DEnabled);
4261 pHlp->pfnPrintf(pHlp, "Host windows ID: %#RX64\n", pThis->svga.u64HostWindowId);
4262 if (pThis->svga.u64HostWindowId != 0)
4263 vmsvga3dInfoHostWindow(pHlp, pThis->svga.u64HostWindowId);
4264# endif
4265}
4266
4267
4268/**
4269 * @copydoc FNSSMDEVLOADEXEC
4270 */
4271int vmsvgaLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
4272{
4273 RT_NOREF(uVersion, uPass);
4274 PVGASTATE pThis = PDMINS_2_DATA(pDevIns, PVGASTATE);
4275 PVMSVGAR3STATE pSVGAState = pThis->svga.pSvgaR3State;
4276 int rc;
4277
4278 /* Load our part of the VGAState */
4279 rc = SSMR3GetStructEx(pSSM, &pThis->svga, sizeof(pThis->svga), 0, g_aVGAStateSVGAFields, NULL);
4280 AssertRCReturn(rc, rc);
4281
4282 /* Load the framebuffer backup. */
4283 rc = SSMR3GetMem(pSSM, pThis->svga.pFrameBufferBackup, VMSVGA_FRAMEBUFFER_BACKUP_SIZE);
4284 AssertRCReturn(rc, rc);
4285
4286 /* Load the VMSVGA state. */
4287 rc = SSMR3GetStructEx(pSSM, pSVGAState, sizeof(*pSVGAState), 0, g_aVMSVGAR3STATEFields, NULL);
4288 AssertRCReturn(rc, rc);
4289
4290 /* Load the active cursor bitmaps. */
4291 if (pSVGAState->Cursor.fActive)
4292 {
4293 pSVGAState->Cursor.pData = RTMemAlloc(pSVGAState->Cursor.cbData);
4294 AssertReturn(pSVGAState->Cursor.pData, VERR_NO_MEMORY);
4295
4296 rc = SSMR3GetMem(pSSM, pSVGAState->Cursor.pData, pSVGAState->Cursor.cbData);
4297 AssertRCReturn(rc, rc);
4298 }
4299
4300 /* Load the GMR state */
4301 for (uint32_t i = 0; i < RT_ELEMENTS(pSVGAState->aGMR); i++)
4302 {
4303 PGMR pGMR = &pSVGAState->aGMR[i];
4304
4305 rc = SSMR3GetStructEx(pSSM, pGMR, sizeof(*pGMR), 0, g_aGMRFields, NULL);
4306 AssertRCReturn(rc, rc);
4307
4308 if (pGMR->numDescriptors)
4309 {
4310 /* Allocate the maximum amount possible (everything non-continuous) */
4311 Assert(pGMR->cMaxPages || pGMR->cbTotal);
4312 pGMR->paDesc = (PVMSVGAGMRDESCRIPTOR)RTMemAllocZ((pGMR->cMaxPages) ? pGMR->cMaxPages : (pGMR->cbTotal >> PAGE_SHIFT) * sizeof(VMSVGAGMRDESCRIPTOR));
4313 AssertReturn(pGMR->paDesc, VERR_NO_MEMORY);
4314
4315 for (uint32_t j = 0; j < pGMR->numDescriptors; j++)
4316 {
4317 rc = SSMR3GetStructEx(pSSM, &pGMR->paDesc[j], sizeof(pGMR->paDesc[j]), 0, g_aVMSVGAGMRDESCRIPTORFields, NULL);
4318 AssertRCReturn(rc, rc);
4319 }
4320 }
4321 }
4322
4323# ifdef VBOX_WITH_VMSVGA3D
4324 if (pThis->svga.f3DEnabled)
4325 {
4326# 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. */
4327 vmsvga3dPowerOn(pThis);
4328# endif
4329
4330 VMSVGA_STATE_LOAD LoadState;
4331 LoadState.pSSM = pSSM;
4332 LoadState.uVersion = uVersion;
4333 LoadState.uPass = uPass;
4334 rc = vmsvgaR3RunExtCmdOnFifoThread(pThis, VMSVGA_FIFO_EXTCMD_LOADSTATE, &LoadState, RT_INDEFINITE_WAIT);
4335 AssertLogRelRCReturn(rc, rc);
4336 }
4337# endif
4338
4339 return VINF_SUCCESS;
4340}
4341
4342/**
4343 * Reinit the video mode after the state has been loaded.
4344 */
4345int vmsvgaLoadDone(PPDMDEVINS pDevIns)
4346{
4347 PVGASTATE pThis = PDMINS_2_DATA(pDevIns, PVGASTATE);
4348 PVMSVGAR3STATE pSVGAState = pThis->svga.pSvgaR3State;
4349
4350 pThis->last_bpp = VMSVGA_VAL_UNINITIALIZED; /* force mode reset */
4351 vmsvgaChangeMode(pThis);
4352
4353 /* Set the active cursor. */
4354 if (pSVGAState->Cursor.fActive)
4355 {
4356 int rc;
4357
4358 rc = pThis->pDrv->pfnVBVAMousePointerShape(pThis->pDrv,
4359 true,
4360 true,
4361 pSVGAState->Cursor.xHotspot,
4362 pSVGAState->Cursor.yHotspot,
4363 pSVGAState->Cursor.width,
4364 pSVGAState->Cursor.height,
4365 pSVGAState->Cursor.pData);
4366 AssertRC(rc);
4367 }
4368 return VINF_SUCCESS;
4369}
4370
4371/**
4372 * @copydoc FNSSMDEVSAVEEXEC
4373 */
4374int vmsvgaSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
4375{
4376 PVGASTATE pThis = PDMINS_2_DATA(pDevIns, PVGASTATE);
4377 PVMSVGAR3STATE pSVGAState = pThis->svga.pSvgaR3State;
4378 int rc;
4379
4380 /* Save our part of the VGAState */
4381 rc = SSMR3PutStructEx(pSSM, &pThis->svga, sizeof(pThis->svga), 0, g_aVGAStateSVGAFields, NULL);
4382 AssertLogRelRCReturn(rc, rc);
4383
4384 /* Save the framebuffer backup. */
4385 rc = SSMR3PutMem(pSSM, pThis->svga.pFrameBufferBackup, VMSVGA_FRAMEBUFFER_BACKUP_SIZE);
4386 AssertLogRelRCReturn(rc, rc);
4387
4388 /* Save the VMSVGA state. */
4389 rc = SSMR3PutStructEx(pSSM, pSVGAState, sizeof(*pSVGAState), 0, g_aVMSVGAR3STATEFields, NULL);
4390 AssertLogRelRCReturn(rc, rc);
4391
4392 /* Save the active cursor bitmaps. */
4393 if (pSVGAState->Cursor.fActive)
4394 {
4395 rc = SSMR3PutMem(pSSM, pSVGAState->Cursor.pData, pSVGAState->Cursor.cbData);
4396 AssertLogRelRCReturn(rc, rc);
4397 }
4398
4399 /* Save the GMR state */
4400 for (uint32_t i = 0; i < RT_ELEMENTS(pSVGAState->aGMR); i++)
4401 {
4402 rc = SSMR3PutStructEx(pSSM, &pSVGAState->aGMR[i], sizeof(pSVGAState->aGMR[i]), 0, g_aGMRFields, NULL);
4403 AssertLogRelRCReturn(rc, rc);
4404
4405 for (uint32_t j = 0; j < pSVGAState->aGMR[i].numDescriptors; j++)
4406 {
4407 rc = SSMR3PutStructEx(pSSM, &pSVGAState->aGMR[i].paDesc[j], sizeof(pSVGAState->aGMR[i].paDesc[j]), 0, g_aVMSVGAGMRDESCRIPTORFields, NULL);
4408 AssertLogRelRCReturn(rc, rc);
4409 }
4410 }
4411
4412# ifdef VBOX_WITH_VMSVGA3D
4413 /*
4414 * Must save the 3d state in the FIFO thread.
4415 */
4416 if (pThis->svga.f3DEnabled)
4417 {
4418 rc = vmsvgaR3RunExtCmdOnFifoThread(pThis, VMSVGA_FIFO_EXTCMD_SAVESTATE, pSSM, RT_INDEFINITE_WAIT);
4419 AssertLogRelRCReturn(rc, rc);
4420 }
4421# endif
4422 return VINF_SUCCESS;
4423}
4424
4425/**
4426 * Resets the SVGA hardware state
4427 *
4428 * @returns VBox status code.
4429 * @param pDevIns The device instance.
4430 */
4431int vmsvgaReset(PPDMDEVINS pDevIns)
4432{
4433 PVGASTATE pThis = PDMINS_2_DATA(pDevIns, PVGASTATE);
4434 PVMSVGAR3STATE pSVGAState = pThis->svga.pSvgaR3State;
4435
4436 /* Reset before init? */
4437 if (!pSVGAState)
4438 return VINF_SUCCESS;
4439
4440 Log(("vmsvgaReset\n"));
4441
4442
4443 /* Reset the FIFO processing as well as the 3d state (if we have one). */
4444 pThis->svga.pFIFOR3[SVGA_FIFO_NEXT_CMD] = pThis->svga.pFIFOR3[SVGA_FIFO_STOP] = 0; /** @todo should probably let the FIFO thread do this ... */
4445 int rc = vmsvgaR3RunExtCmdOnFifoThread(pThis, VMSVGA_FIFO_EXTCMD_RESET, NULL /*pvParam*/, 10000 /*ms*/);
4446
4447 /* Reset other stuff. */
4448 pThis->svga.cScratchRegion = VMSVGA_SCRATCH_SIZE;
4449 RT_ZERO(pThis->svga.au32ScratchRegion);
4450 RT_ZERO(*pThis->svga.pSvgaR3State);
4451 RT_BZERO(pThis->svga.pFrameBufferBackup, VMSVGA_FRAMEBUFFER_BACKUP_SIZE);
4452
4453 /* Register caps. */
4454 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;
4455# ifdef VBOX_WITH_VMSVGA3D
4456 pThis->svga.u32RegCaps |= SVGA_CAP_3D;
4457# endif
4458
4459 /* Setup FIFO capabilities. */
4460 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;
4461
4462 /* Valid with SVGA_FIFO_CAP_SCREEN_OBJECT_2 */
4463 pThis->svga.pFIFOR3[SVGA_FIFO_CURSOR_SCREEN_ID] = SVGA_ID_INVALID;
4464
4465 /* VRAM tracking is enabled by default during bootup. */
4466 pThis->svga.fVRAMTracking = true;
4467 pThis->svga.fEnabled = false;
4468
4469 /* Invalidate current settings. */
4470 pThis->svga.uWidth = VMSVGA_VAL_UNINITIALIZED;
4471 pThis->svga.uHeight = VMSVGA_VAL_UNINITIALIZED;
4472 pThis->svga.uBpp = VMSVGA_VAL_UNINITIALIZED;
4473 pThis->svga.cbScanline = 0;
4474
4475 return rc;
4476}
4477
4478/**
4479 * Cleans up the SVGA hardware state
4480 *
4481 * @returns VBox status code.
4482 * @param pDevIns The device instance.
4483 */
4484int vmsvgaDestruct(PPDMDEVINS pDevIns)
4485{
4486 PVGASTATE pThis = PDMINS_2_DATA(pDevIns, PVGASTATE);
4487
4488 /*
4489 * Ask the FIFO thread to terminate the 3d state and then terminate it.
4490 */
4491 if (pThis->svga.pFIFOIOThread)
4492 {
4493 int rc = vmsvgaR3RunExtCmdOnFifoThread(pThis, VMSVGA_FIFO_EXTCMD_TERMINATE, NULL /*pvParam*/, 30000 /*ms*/);
4494 AssertLogRelRC(rc);
4495
4496 rc = PDMR3ThreadDestroy(pThis->svga.pFIFOIOThread, NULL);
4497 AssertLogRelRC(rc);
4498 pThis->svga.pFIFOIOThread = NULL;
4499 }
4500
4501 /*
4502 * Destroy the special SVGA state.
4503 */
4504 PVMSVGAR3STATE pSVGAState = pThis->svga.pSvgaR3State;
4505 if (pSVGAState)
4506 {
4507# ifndef VMSVGA_USE_EMT_HALT_CODE
4508 if (pSVGAState->hBusyDelayedEmts != NIL_RTSEMEVENTMULTI)
4509 {
4510 RTSemEventMultiDestroy(pSVGAState->hBusyDelayedEmts);
4511 pSVGAState->hBusyDelayedEmts = NIL_RTSEMEVENT;
4512 }
4513# endif
4514 if (pSVGAState->Cursor.fActive)
4515 RTMemFree(pSVGAState->Cursor.pData);
4516
4517 for (unsigned i = 0; i < RT_ELEMENTS(pSVGAState->aGMR); i++)
4518 if (pSVGAState->aGMR[i].paDesc)
4519 RTMemFree(pSVGAState->aGMR[i].paDesc);
4520
4521 RTMemFree(pSVGAState);
4522 pThis->svga.pSvgaR3State = NULL;
4523 }
4524
4525 /*
4526 * Free our resources residing in the VGA state.
4527 */
4528 if (pThis->svga.pFrameBufferBackup)
4529 RTMemFree(pThis->svga.pFrameBufferBackup);
4530 if (pThis->svga.FIFOExtCmdSem != NIL_RTSEMEVENT)
4531 {
4532 RTSemEventDestroy(pThis->svga.FIFOExtCmdSem);
4533 pThis->svga.FIFOExtCmdSem = NIL_RTSEMEVENT;
4534 }
4535 if (pThis->svga.FIFORequestSem != NIL_SUPSEMEVENT)
4536 {
4537 SUPSemEventClose(pThis->svga.pSupDrvSession, pThis->svga.FIFORequestSem);
4538 pThis->svga.FIFORequestSem = NIL_SUPSEMEVENT;
4539 }
4540
4541 return VINF_SUCCESS;
4542}
4543
4544/**
4545 * Initialize the SVGA hardware state
4546 *
4547 * @returns VBox status code.
4548 * @param pDevIns The device instance.
4549 */
4550int vmsvgaInit(PPDMDEVINS pDevIns)
4551{
4552 PVGASTATE pThis = PDMINS_2_DATA(pDevIns, PVGASTATE);
4553 PVMSVGAR3STATE pSVGAState;
4554 PVM pVM = PDMDevHlpGetVM(pDevIns);
4555 int rc;
4556
4557 pThis->svga.cScratchRegion = VMSVGA_SCRATCH_SIZE;
4558 memset(pThis->svga.au32ScratchRegion, 0, sizeof(pThis->svga.au32ScratchRegion));
4559
4560 pThis->svga.pSvgaR3State = (PVMSVGAR3STATE)RTMemAllocZ(sizeof(VMSVGAR3STATE));
4561 AssertReturn(pThis->svga.pSvgaR3State, VERR_NO_MEMORY);
4562 pSVGAState = pThis->svga.pSvgaR3State;
4563
4564 /* Necessary for creating a backup of the text mode frame buffer when switching into svga mode. */
4565 pThis->svga.pFrameBufferBackup = RTMemAllocZ(VMSVGA_FRAMEBUFFER_BACKUP_SIZE);
4566 AssertReturn(pThis->svga.pFrameBufferBackup, VERR_NO_MEMORY);
4567
4568 /* Create event semaphore. */
4569 pThis->svga.pSupDrvSession = PDMDevHlpGetSupDrvSession(pDevIns);
4570
4571 rc = SUPSemEventCreate(pThis->svga.pSupDrvSession, &pThis->svga.FIFORequestSem);
4572 if (RT_FAILURE(rc))
4573 {
4574 Log(("%s: Failed to create event semaphore for FIFO handling.\n", __FUNCTION__));
4575 return rc;
4576 }
4577
4578 /* Create event semaphore. */
4579 rc = RTSemEventCreate(&pThis->svga.FIFOExtCmdSem);
4580 if (RT_FAILURE(rc))
4581 {
4582 Log(("%s: Failed to create event semaphore for external fifo cmd handling.\n", __FUNCTION__));
4583 return rc;
4584 }
4585
4586# ifndef VMSVGA_USE_EMT_HALT_CODE
4587 /* Create semaphore for delaying EMTs wait for the FIFO to stop being busy. */
4588 rc = RTSemEventMultiCreate(&pSVGAState->hBusyDelayedEmts);
4589 AssertRCReturn(rc, rc);
4590# endif
4591
4592 /* Register caps. */
4593 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;
4594# ifdef VBOX_WITH_VMSVGA3D
4595 pThis->svga.u32RegCaps |= SVGA_CAP_3D;
4596# endif
4597
4598 /* Setup FIFO capabilities. */
4599 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;
4600
4601 /* Valid with SVGA_FIFO_CAP_SCREEN_OBJECT_2 */
4602 pThis->svga.pFIFOR3[SVGA_FIFO_CURSOR_SCREEN_ID] = SVGA_ID_INVALID;
4603
4604 pThis->svga.pFIFOR3[SVGA_FIFO_3D_HWVERSION] = pThis->svga.pFIFOR3[SVGA_FIFO_3D_HWVERSION_REVISED] = 0; /* no 3d available. */
4605# ifdef VBOX_WITH_VMSVGA3D
4606 if (pThis->svga.f3DEnabled)
4607 {
4608 rc = vmsvga3dInit(pThis);
4609 if (RT_FAILURE(rc))
4610 {
4611 LogRel(("VMSVGA3d: 3D support disabled! (vmsvga3dInit -> %Rrc)\n", rc));
4612 pThis->svga.f3DEnabled = false;
4613 }
4614 }
4615# endif
4616 /* VRAM tracking is enabled by default during bootup. */
4617 pThis->svga.fVRAMTracking = true;
4618
4619 /* Invalidate current settings. */
4620 pThis->svga.uWidth = VMSVGA_VAL_UNINITIALIZED;
4621 pThis->svga.uHeight = VMSVGA_VAL_UNINITIALIZED;
4622 pThis->svga.uBpp = VMSVGA_VAL_UNINITIALIZED;
4623 pThis->svga.cbScanline = 0;
4624
4625 pThis->svga.u32MaxWidth = VBE_DISPI_MAX_YRES;
4626 pThis->svga.u32MaxHeight = VBE_DISPI_MAX_XRES;
4627 while (pThis->svga.u32MaxWidth * pThis->svga.u32MaxHeight * 4 /* 32 bpp */ > pThis->vram_size)
4628 {
4629 pThis->svga.u32MaxWidth -= 256;
4630 pThis->svga.u32MaxHeight -= 256;
4631 }
4632 Log(("VMSVGA: Maximum size (%d,%d)\n", pThis->svga.u32MaxWidth, pThis->svga.u32MaxHeight));
4633
4634# ifdef DEBUG_GMR_ACCESS
4635 /* Register the GMR access handler type. */
4636 rc = PGMR3HandlerPhysicalTypeRegister(PDMDevHlpGetVM(pThis->pDevInsR3), PGMPHYSHANDLERKIND_WRITE,
4637 vmsvgaR3GMRAccessHandler,
4638 NULL, NULL, NULL,
4639 NULL, NULL, NULL,
4640 "VMSVGA GMR", &pThis->svga.hGmrAccessHandlerType);
4641 AssertRCReturn(rc, rc);
4642# endif
4643# ifdef DEBUG_FIFO_ACCESS
4644 rc = PGMR3HandlerPhysicalTypeRegister(PDMDevHlpGetVM(pThis->pDevInsR3), PGMPHYSHANDLERKIND_ALL,
4645 vmsvgaR3FIFOAccessHandler,
4646 NULL, NULL, NULL,
4647 NULL, NULL, NULL,
4648 "VMSVGA FIFO", &pThis->svga.hFifoAccessHandlerType);
4649 AssertRCReturn(rc, rc);
4650#endif
4651
4652 /* Create the async IO thread. */
4653 rc = PDMDevHlpThreadCreate(pDevIns, &pThis->svga.pFIFOIOThread, pThis, vmsvgaFIFOLoop, vmsvgaFIFOLoopWakeUp, 0,
4654 RTTHREADTYPE_IO, "VMSVGA FIFO");
4655 if (RT_FAILURE(rc))
4656 {
4657 AssertMsgFailed(("%s: Async IO Thread creation for FIFO handling failed rc=%d\n", __FUNCTION__, rc));
4658 return rc;
4659 }
4660
4661 /*
4662 * Statistics.
4663 */
4664 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dActivateSurface, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dActivateSurface", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_ACTIVATE_SURFACE");
4665 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dBeginQuery, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dBeginQuery", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_BEGIN_QUERY");
4666 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dClear, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dClear", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_CLEAR");
4667 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dContextDefine, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dContextDefine", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_CONTEXT_DEFINE");
4668 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dContextDestroy, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dContextDestroy", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_CONTEXT_DESTROY");
4669 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dDeactivateSurface, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dDeactivateSurface", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_DEACTIVATE_SURFACE");
4670 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dDrawPrimitives, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dDrawPrimitives", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_DRAW_PRIMITIVES");
4671 STAM_REG(pVM, &pSVGAState->StatR3Cmd3dDrawPrimitivesProf, STAMTYPE_PROFILE, "/Devices/VMSVGA/Cmd/3dDrawPrimitivesProf", STAMUNIT_TICKS_PER_CALL, "Profiling of SVGA_3D_CMD_DRAW_PRIMITIVES.");
4672 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dEndQuery, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dEndQuery", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_END_QUERY");
4673 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dGenerateMipmaps, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dGenerateMipmaps", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_GENERATE_MIPMAPS");
4674 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dPresent, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dPresent", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_PRESENT");
4675 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dPresentReadBack, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dPresentReadBack", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_PRESENT_READBACK");
4676 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.");
4677 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSetClipPlane, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSetClipPlane", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SETCLIPPLANE");
4678 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSetLightData, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSetLightData", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SETLIGHTDATA");
4679 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSetLightEnable, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSetLightEnable", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SETLIGHTENABLE");
4680 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSetMaterial, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSetMaterial", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SETMATERIAL");
4681 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSetRenderState, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSetRenderState", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SETRENDERSTATE");
4682 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSetRenderTarget, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSetRenderTarget", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SETRENDERTARGET");
4683 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSetScissorRect, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSetScissorRect", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SETSCISSORRECT");
4684 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSetShader, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSetShader", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SET_SHADER");
4685 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSetShaderConst, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSetShaderConst", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SET_SHADER_CONST");
4686 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSetTextureState, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSetTextureState", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SETTEXTURESTATE");
4687 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSetTransform, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSetTransform", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SETTRANSFORM");
4688 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSetViewPort, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSetViewPort", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SETVIEWPORT");
4689 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSetZRange, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSetZRange", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SETZRANGE");
4690 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dShaderDefine, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dShaderDefine", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SHADER_DEFINE");
4691 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dShaderDestroy, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dShaderDestroy", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SHADER_DESTROY");
4692 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSurfaceCopy, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSurfaceCopy", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SURFACE_COPY");
4693 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSurfaceDefine, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSurfaceDefine", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SURFACE_DEFINE");
4694 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSurfaceDefineV2, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSurfaceDefineV2", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SURFACE_DEFINE_V2");
4695 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSurfaceDestroy, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSurfaceDestroy", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SURFACE_DESTROY");
4696 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSurfaceDma, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSurfaceDma", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SURFACE_DMA");
4697 STAM_REG(pVM, &pSVGAState->StatR3Cmd3dSurfaceDmaProf, STAMTYPE_PROFILE, "/Devices/VMSVGA/Cmd/3dSurfaceDmaProf", STAMUNIT_TICKS_PER_CALL, "Profiling of SVGA_3D_CMD_SURFACE_DMA.");
4698 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSurfaceScreen, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSurfaceScreen", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SURFACE_SCREEN");
4699 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dSurfaceStretchBlt, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dSurfaceStretchBlt", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_SURFACE_STRETCHBLT");
4700 STAM_REL_REG(pVM, &pSVGAState->StatR3Cmd3dWaitForQuery, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/3dWaitForQuery", STAMUNIT_OCCURENCES, "SVGA_3D_CMD_WAIT_FOR_QUERY");
4701 STAM_REL_REG(pVM, &pSVGAState->StatR3CmdAnnotationCopy, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/AnnotationCopy", STAMUNIT_OCCURENCES, "SVGA_CMD_ANNOTATION_COPY");
4702 STAM_REL_REG(pVM, &pSVGAState->StatR3CmdAnnotationFill, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/AnnotationFill", STAMUNIT_OCCURENCES, "SVGA_CMD_ANNOTATION_FILL");
4703 STAM_REL_REG(pVM, &pSVGAState->StatR3CmdBlitGmrFbToScreen, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/BlitGmrFbToScreen", STAMUNIT_OCCURENCES, "SVGA_CMD_BLIT_GMRFB_TO_SCREEN");
4704 STAM_REL_REG(pVM, &pSVGAState->StatR3CmdBlitScreentoGmrFb, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/BlitScreentoGmrFb", STAMUNIT_OCCURENCES, "SVGA_CMD_BLIT_SCREEN_TO_GMRFB");
4705 STAM_REL_REG(pVM, &pSVGAState->StatR3CmdDefineAlphaCursor, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/DefineAlphaCursor", STAMUNIT_OCCURENCES, "SVGA_CMD_DEFINE_ALPHA_CURSOR");
4706 STAM_REL_REG(pVM, &pSVGAState->StatR3CmdDefineCursor, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/DefineCursor", STAMUNIT_OCCURENCES, "SVGA_CMD_DEFINE_CURSOR");
4707 STAM_REL_REG(pVM, &pSVGAState->StatR3CmdDefineGmr2, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/DefineGmr2", STAMUNIT_OCCURENCES, "SVGA_CMD_DEFINE_GMR2");
4708 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.");
4709 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.");
4710 STAM_REL_REG(pVM, &pSVGAState->StatR3CmdDefineGmrFb, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/DefineGmrFb", STAMUNIT_OCCURENCES, "SVGA_CMD_DEFINE_GMRFB");
4711 STAM_REL_REG(pVM, &pSVGAState->StatR3CmdDefineScreen, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/DefineScreen", STAMUNIT_OCCURENCES, "SVGA_CMD_DEFINE_SCREEN");
4712 STAM_REL_REG(pVM, &pSVGAState->StatR3CmdDestroyScreen, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/DestroyScreen", STAMUNIT_OCCURENCES, "SVGA_CMD_DESTROY_SCREEN");
4713 STAM_REL_REG(pVM, &pSVGAState->StatR3CmdEscape, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/Escape", STAMUNIT_OCCURENCES, "SVGA_CMD_ESCAPE");
4714 STAM_REL_REG(pVM, &pSVGAState->StatR3CmdFence, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/Fence", STAMUNIT_OCCURENCES, "SVGA_CMD_FENCE");
4715 STAM_REL_REG(pVM, &pSVGAState->StatR3CmdInvalidCmd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/InvalidCmd", STAMUNIT_OCCURENCES, "SVGA_CMD_INVALID_CMD");
4716 STAM_REL_REG(pVM, &pSVGAState->StatR3CmdRemapGmr2, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/RemapGmr2", STAMUNIT_OCCURENCES, "SVGA_CMD_REMAP_GMR2.");
4717 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.");
4718 STAM_REL_REG(pVM, &pSVGAState->StatR3CmdUpdate, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/Update", STAMUNIT_OCCURENCES, "SVGA_CMD_UPATE");
4719 STAM_REL_REG(pVM, &pSVGAState->StatR3CmdUpdateVerbose, STAMTYPE_COUNTER, "/Devices/VMSVGA/Cmd/UpdateVerbose", STAMUNIT_OCCURENCES, "SVGA_CMD_UPDATE_VERBOSE");
4720
4721 STAM_REL_REG(pVM, &pSVGAState->StatR3RegConfigDoneWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/ConfigDoneWrite", STAMUNIT_OCCURENCES, "SVGA_REG_CONFIG_DONE writes");
4722 STAM_REL_REG(pVM, &pSVGAState->StatR3RegGmrDescriptorWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/GmrDescriptorWrite", STAMUNIT_OCCURENCES, "SVGA_REG_GMR_DESCRIPTOR writes");
4723 STAM_REL_REG(pVM, &pSVGAState->StatR3RegGmrDescriptorWrErrors, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/GmrDescriptorWrite/Errors", STAMUNIT_OCCURENCES, "Number of erroneous SVGA_REG_GMR_DESCRIPTOR commands.");
4724 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.");
4725 STAM_REL_REG(pVM, &pThis->svga.StatRegBitsPerPixelWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/BitsPerPixelWrite", STAMUNIT_OCCURENCES, "SVGA_REG_BITS_PER_PIXEL writes.");
4726 STAM_REL_REG(pVM, &pThis->svga.StatRegBusyWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/BusyWrite", STAMUNIT_OCCURENCES, "SVGA_REG_BUSY writes.");
4727 STAM_REL_REG(pVM, &pThis->svga.StatRegCursorXxxxWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/CursorXxxxWrite", STAMUNIT_OCCURENCES, "SVGA_REG_CURSOR_XXXX writes.");
4728 STAM_REL_REG(pVM, &pThis->svga.StatRegDepthWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/DepthWrite", STAMUNIT_OCCURENCES, "SVGA_REG_DEPTH writes.");
4729 STAM_REL_REG(pVM, &pThis->svga.StatRegDisplayHeightWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/DisplayHeightWrite", STAMUNIT_OCCURENCES, "SVGA_REG_DISPLAY_HEIGHT writes.");
4730 STAM_REL_REG(pVM, &pThis->svga.StatRegDisplayIdWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/DisplayIdWrite", STAMUNIT_OCCURENCES, "SVGA_REG_DISPLAY_ID writes.");
4731 STAM_REL_REG(pVM, &pThis->svga.StatRegDisplayIsPrimaryWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/DisplayIsPrimaryWrite", STAMUNIT_OCCURENCES, "SVGA_REG_DISPLAY_IS_PRIMARY writes.");
4732 STAM_REL_REG(pVM, &pThis->svga.StatRegDisplayPositionXWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/DisplayPositionXWrite", STAMUNIT_OCCURENCES, "SVGA_REG_DISPLAY_POSITION_X writes.");
4733 STAM_REL_REG(pVM, &pThis->svga.StatRegDisplayPositionYWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/DisplayPositionYWrite", STAMUNIT_OCCURENCES, "SVGA_REG_DISPLAY_POSITION_Y writes.");
4734 STAM_REL_REG(pVM, &pThis->svga.StatRegDisplayWidthWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/DisplayWidthWrite", STAMUNIT_OCCURENCES, "SVGA_REG_DISPLAY_WIDTH writes.");
4735 STAM_REL_REG(pVM, &pThis->svga.StatRegEnableWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/EnableWrite", STAMUNIT_OCCURENCES, "SVGA_REG_ENABLE writes.");
4736 STAM_REL_REG(pVM, &pThis->svga.StatRegGmrIdWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/GmrIdWrite", STAMUNIT_OCCURENCES, "SVGA_REG_GMR_ID writes.");
4737 STAM_REL_REG(pVM, &pThis->svga.StatRegGuestIdWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/GuestIdWrite", STAMUNIT_OCCURENCES, "SVGA_REG_GUEST_ID writes.");
4738 STAM_REL_REG(pVM, &pThis->svga.StatRegHeightWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/HeightWrite", STAMUNIT_OCCURENCES, "SVGA_REG_HEIGHT writes.");
4739 STAM_REL_REG(pVM, &pThis->svga.StatRegIdWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/IdWrite", STAMUNIT_OCCURENCES, "SVGA_REG_ID writes.");
4740 STAM_REL_REG(pVM, &pThis->svga.StatRegIrqMaskWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/IrqMaskWrite", STAMUNIT_OCCURENCES, "SVGA_REG_IRQMASK writes.");
4741 STAM_REL_REG(pVM, &pThis->svga.StatRegNumDisplaysWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/NumDisplaysWrite", STAMUNIT_OCCURENCES, "SVGA_REG_NUM_DISPLAYS writes.");
4742 STAM_REL_REG(pVM, &pThis->svga.StatRegNumGuestDisplaysWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/NumGuestDisplaysWrite", STAMUNIT_OCCURENCES, "SVGA_REG_NUM_GUEST_DISPLAYS writes.");
4743 STAM_REL_REG(pVM, &pThis->svga.StatRegPaletteWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/PaletteWrite", STAMUNIT_OCCURENCES, "SVGA_PALETTE_XXXX writes.");
4744 STAM_REL_REG(pVM, &pThis->svga.StatRegPitchLockWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/PitchLockWrite", STAMUNIT_OCCURENCES, "SVGA_REG_PITCHLOCK writes.");
4745 STAM_REL_REG(pVM, &pThis->svga.StatRegPseudoColorWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/PseudoColorWrite", STAMUNIT_OCCURENCES, "SVGA_REG_PSEUDOCOLOR writes.");
4746 STAM_REL_REG(pVM, &pThis->svga.StatRegReadOnlyWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/ReadOnlyWrite", STAMUNIT_OCCURENCES, "Read-only SVGA_REG_XXXX writes.");
4747 STAM_REL_REG(pVM, &pThis->svga.StatRegScratchWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/ScratchWrite", STAMUNIT_OCCURENCES, "SVGA_REG_SCRATCH_XXXX writes.");
4748 STAM_REL_REG(pVM, &pThis->svga.StatRegSyncWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/SyncWrite", STAMUNIT_OCCURENCES, "SVGA_REG_SYNC writes.");
4749 STAM_REL_REG(pVM, &pThis->svga.StatRegTopWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/TopWrite", STAMUNIT_OCCURENCES, "SVGA_REG_TOP writes.");
4750 STAM_REL_REG(pVM, &pThis->svga.StatRegTracesWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/TracesWrite", STAMUNIT_OCCURENCES, "SVGA_REG_TRACES writes.");
4751 STAM_REL_REG(pVM, &pThis->svga.StatRegUnknownWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/UnknownWrite", STAMUNIT_OCCURENCES, "Writes to unknown register.");
4752 STAM_REL_REG(pVM, &pThis->svga.StatRegWidthWr, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/WidthWrite", STAMUNIT_OCCURENCES, "SVGA_REG_WIDTH writes.");
4753
4754 STAM_REL_REG(pVM, &pThis->svga.StatRegBitsPerPixelRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/BitsPerPixelRead", STAMUNIT_OCCURENCES, "SVGA_REG_BITS_PER_PIXEL reads.");
4755 STAM_REL_REG(pVM, &pThis->svga.StatRegBlueMaskRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/BlueMaskRead", STAMUNIT_OCCURENCES, "SVGA_REG_BLUE_MASK reads.");
4756 STAM_REL_REG(pVM, &pThis->svga.StatRegBusyRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/BusyRead", STAMUNIT_OCCURENCES, "SVGA_REG_BUSY reads.");
4757 STAM_REL_REG(pVM, &pThis->svga.StatRegBytesPerLineRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/BytesPerLineRead", STAMUNIT_OCCURENCES, "SVGA_REG_BYTES_PER_LINE reads.");
4758 STAM_REL_REG(pVM, &pThis->svga.StatRegCapabilitesRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/CapabilitesRead", STAMUNIT_OCCURENCES, "SVGA_REG_CAPABILITIES reads.");
4759 STAM_REL_REG(pVM, &pThis->svga.StatRegConfigDoneRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/ConfigDoneRead", STAMUNIT_OCCURENCES, "SVGA_REG_CONFIG_DONE reads.");
4760 STAM_REL_REG(pVM, &pThis->svga.StatRegCursorXxxxRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/CursorXxxxRead", STAMUNIT_OCCURENCES, "SVGA_REG_CURSOR_XXXX reads.");
4761 STAM_REL_REG(pVM, &pThis->svga.StatRegDepthRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/DepthRead", STAMUNIT_OCCURENCES, "SVGA_REG_DEPTH reads.");
4762 STAM_REL_REG(pVM, &pThis->svga.StatRegDisplayHeightRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/DisplayHeightRead", STAMUNIT_OCCURENCES, "SVGA_REG_DISPLAY_HEIGHT reads.");
4763 STAM_REL_REG(pVM, &pThis->svga.StatRegDisplayIdRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/DisplayIdRead", STAMUNIT_OCCURENCES, "SVGA_REG_DISPLAY_ID reads.");
4764 STAM_REL_REG(pVM, &pThis->svga.StatRegDisplayIsPrimaryRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/DisplayIsPrimaryRead", STAMUNIT_OCCURENCES, "SVGA_REG_DISPLAY_IS_PRIMARY reads.");
4765 STAM_REL_REG(pVM, &pThis->svga.StatRegDisplayPositionXRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/DisplayPositionXRead", STAMUNIT_OCCURENCES, "SVGA_REG_DISPLAY_POSITION_X reads.");
4766 STAM_REL_REG(pVM, &pThis->svga.StatRegDisplayPositionYRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/DisplayPositionYRead", STAMUNIT_OCCURENCES, "SVGA_REG_DISPLAY_POSITION_Y reads.");
4767 STAM_REL_REG(pVM, &pThis->svga.StatRegDisplayWidthRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/DisplayWidthRead", STAMUNIT_OCCURENCES, "SVGA_REG_DISPLAY_WIDTH reads.");
4768 STAM_REL_REG(pVM, &pThis->svga.StatRegEnableRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/EnableRead", STAMUNIT_OCCURENCES, "SVGA_REG_ENABLE reads.");
4769 STAM_REL_REG(pVM, &pThis->svga.StatRegFbOffsetRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/FbOffsetRead", STAMUNIT_OCCURENCES, "SVGA_REG_FB_OFFSET reads.");
4770 STAM_REL_REG(pVM, &pThis->svga.StatRegFbSizeRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/FbSizeRead", STAMUNIT_OCCURENCES, "SVGA_REG_FB_SIZE reads.");
4771 STAM_REL_REG(pVM, &pThis->svga.StatRegFbStartRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/FbStartRead", STAMUNIT_OCCURENCES, "SVGA_REG_FB_START reads.");
4772 STAM_REL_REG(pVM, &pThis->svga.StatRegGmrIdRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/GmrIdRead", STAMUNIT_OCCURENCES, "SVGA_REG_GMR_ID reads.");
4773 STAM_REL_REG(pVM, &pThis->svga.StatRegGmrMaxDescriptorLengthRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/GmrMaxDescriptorLengthRead", STAMUNIT_OCCURENCES, "SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH reads.");
4774 STAM_REL_REG(pVM, &pThis->svga.StatRegGmrMaxIdsRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/GmrMaxIdsRead", STAMUNIT_OCCURENCES, "SVGA_REG_GMR_MAX_IDS reads.");
4775 STAM_REL_REG(pVM, &pThis->svga.StatRegGmrsMaxPagesRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/GmrsMaxPagesRead", STAMUNIT_OCCURENCES, "SVGA_REG_GMRS_MAX_PAGES reads.");
4776 STAM_REL_REG(pVM, &pThis->svga.StatRegGreenMaskRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/GreenMaskRead", STAMUNIT_OCCURENCES, "SVGA_REG_GREEN_MASK reads.");
4777 STAM_REL_REG(pVM, &pThis->svga.StatRegGuestIdRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/GuestIdRead", STAMUNIT_OCCURENCES, "SVGA_REG_GUEST_ID reads.");
4778 STAM_REL_REG(pVM, &pThis->svga.StatRegHeightRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/HeightRead", STAMUNIT_OCCURENCES, "SVGA_REG_HEIGHT reads.");
4779 STAM_REL_REG(pVM, &pThis->svga.StatRegHostBitsPerPixelRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/HostBitsPerPixelRead", STAMUNIT_OCCURENCES, "SVGA_REG_HOST_BITS_PER_PIXEL reads.");
4780 STAM_REL_REG(pVM, &pThis->svga.StatRegIdRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/IdRead", STAMUNIT_OCCURENCES, "SVGA_REG_ID reads.");
4781 STAM_REL_REG(pVM, &pThis->svga.StatRegIrqMaskRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/IrqMaskRead", STAMUNIT_OCCURENCES, "SVGA_REG_IRQ_MASK reads.");
4782 STAM_REL_REG(pVM, &pThis->svga.StatRegMaxHeightRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/MaxHeightRead", STAMUNIT_OCCURENCES, "SVGA_REG_MAX_HEIGHT reads.");
4783 STAM_REL_REG(pVM, &pThis->svga.StatRegMaxWidthRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/MaxWidthRead", STAMUNIT_OCCURENCES, "SVGA_REG_MAX_WIDTH reads.");
4784 STAM_REL_REG(pVM, &pThis->svga.StatRegMemorySizeRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/MemorySizeRead", STAMUNIT_OCCURENCES, "SVGA_REG_MEMORY_SIZE reads.");
4785 STAM_REL_REG(pVM, &pThis->svga.StatRegMemRegsRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/MemRegsRead", STAMUNIT_OCCURENCES, "SVGA_REG_MEM_REGS reads.");
4786 STAM_REL_REG(pVM, &pThis->svga.StatRegMemSizeRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/MemSizeRead", STAMUNIT_OCCURENCES, "SVGA_REG_MEM_SIZE reads.");
4787 STAM_REL_REG(pVM, &pThis->svga.StatRegMemStartRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/MemStartRead", STAMUNIT_OCCURENCES, "SVGA_REG_MEM_START reads.");
4788 STAM_REL_REG(pVM, &pThis->svga.StatRegNumDisplaysRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/NumDisplaysRead", STAMUNIT_OCCURENCES, "SVGA_REG_NUM_DISPLAYS reads.");
4789 STAM_REL_REG(pVM, &pThis->svga.StatRegNumGuestDisplaysRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/NumGuestDisplaysRead", STAMUNIT_OCCURENCES, "SVGA_REG_NUM_GUEST_DISPLAYS reads.");
4790 STAM_REL_REG(pVM, &pThis->svga.StatRegPaletteRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/PaletteRead", STAMUNIT_OCCURENCES, "SVGA_REG_PLAETTE_XXXX reads.");
4791 STAM_REL_REG(pVM, &pThis->svga.StatRegPitchLockRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/PitchLockRead", STAMUNIT_OCCURENCES, "SVGA_REG_PITCHLOCK reads.");
4792 STAM_REL_REG(pVM, &pThis->svga.StatRegPsuedoColorRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/PsuedoColorRead", STAMUNIT_OCCURENCES, "SVGA_REG_PSEUDOCOLOR reads.");
4793 STAM_REL_REG(pVM, &pThis->svga.StatRegRedMaskRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/RedMaskRead", STAMUNIT_OCCURENCES, "SVGA_REG_RED_MASK reads.");
4794 STAM_REL_REG(pVM, &pThis->svga.StatRegScratchRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/ScratchRead", STAMUNIT_OCCURENCES, "SVGA_REG_SCRATCH reads.");
4795 STAM_REL_REG(pVM, &pThis->svga.StatRegScratchSizeRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/ScratchSizeRead", STAMUNIT_OCCURENCES, "SVGA_REG_SCRATCH_SIZE reads.");
4796 STAM_REL_REG(pVM, &pThis->svga.StatRegSyncRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/SyncRead", STAMUNIT_OCCURENCES, "SVGA_REG_SYNC reads.");
4797 STAM_REL_REG(pVM, &pThis->svga.StatRegTopRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/TopRead", STAMUNIT_OCCURENCES, "SVGA_REG_TOP reads.");
4798 STAM_REL_REG(pVM, &pThis->svga.StatRegTracesRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/TracesRead", STAMUNIT_OCCURENCES, "SVGA_REG_TRACES reads.");
4799 STAM_REL_REG(pVM, &pThis->svga.StatRegUnknownRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/UnknownRead", STAMUNIT_OCCURENCES, "SVGA_REG_UNKNOWN reads.");
4800 STAM_REL_REG(pVM, &pThis->svga.StatRegVramSizeRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/VramSizeRead", STAMUNIT_OCCURENCES, "SVGA_REG_VRAM_SIZE reads.");
4801 STAM_REL_REG(pVM, &pThis->svga.StatRegWidthRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/WidthRead", STAMUNIT_OCCURENCES, "SVGA_REG_WIDTH reads.");
4802 STAM_REL_REG(pVM, &pThis->svga.StatRegWriteOnlyRd, STAMTYPE_COUNTER, "/Devices/VMSVGA/Reg/WriteOnlyRead", STAMUNIT_OCCURENCES, "Write-only SVGA_REG_XXXX reads.");
4803
4804 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.");
4805 STAM_REL_REG(pVM, &pSVGAState->StatFifoCommands, STAMTYPE_COUNTER, "/Devices/VMSVGA/FifoCommands", STAMUNIT_OCCURENCES, "FIFO command counter.");
4806 STAM_REL_REG(pVM, &pSVGAState->StatFifoErrors, STAMTYPE_COUNTER, "/Devices/VMSVGA/FifoErrors", STAMUNIT_OCCURENCES, "FIFO error counter.");
4807 STAM_REL_REG(pVM, &pSVGAState->StatFifoUnkCmds, STAMTYPE_COUNTER, "/Devices/VMSVGA/FifoUnknownCommands", STAMUNIT_OCCURENCES, "FIFO unknown command counter.");
4808 STAM_REL_REG(pVM, &pSVGAState->StatFifoTodoTimeout, STAMTYPE_COUNTER, "/Devices/VMSVGA/FifoTodoTimeout", STAMUNIT_OCCURENCES, "Number of times we discovered pending work after a wait timeout.");
4809 STAM_REL_REG(pVM, &pSVGAState->StatFifoTodoWoken, STAMTYPE_COUNTER, "/Devices/VMSVGA/FifoTodoWoken", STAMUNIT_OCCURENCES, "Number of times we discovered pending work after being woken up.");
4810 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).");
4811
4812 /*
4813 * Info handlers.
4814 */
4815 PDMDevHlpDBGFInfoRegister(pDevIns, "vmsvga", "Basic VMSVGA device state details", vmsvgaR3Info);
4816# ifdef VBOX_WITH_VMSVGA3D
4817 PDMDevHlpDBGFInfoRegister(pDevIns, "vmsvga3dctx", "VMSVGA 3d context details. Accepts 'terse'.", vmsvgaR3Info3dContext);
4818 PDMDevHlpDBGFInfoRegister(pDevIns, "vmsvga3dsfc",
4819 "VMSVGA 3d surface details. "
4820 "Accepts 'terse', 'invy', and one of 'tiny', 'medium', 'normal', 'big', 'huge', or 'gigantic'.",
4821 vmsvgaR3Info3dSurface);
4822# endif
4823
4824 return VINF_SUCCESS;
4825}
4826
4827# ifdef VBOX_WITH_VMSVGA3D
4828/** Names for the vmsvga 3d capabilities, prefixed with format type hint char. */
4829static const char * const g_apszVmSvgaDevCapNames[] =
4830{
4831 "x3D", /* = 0 */
4832 "xMAX_LIGHTS",
4833 "xMAX_TEXTURES",
4834 "xMAX_CLIP_PLANES",
4835 "xVERTEX_SHADER_VERSION",
4836 "xVERTEX_SHADER",
4837 "xFRAGMENT_SHADER_VERSION",
4838 "xFRAGMENT_SHADER",
4839 "xMAX_RENDER_TARGETS",
4840 "xS23E8_TEXTURES",
4841 "xS10E5_TEXTURES",
4842 "xMAX_FIXED_VERTEXBLEND",
4843 "xD16_BUFFER_FORMAT",
4844 "xD24S8_BUFFER_FORMAT",
4845 "xD24X8_BUFFER_FORMAT",
4846 "xQUERY_TYPES",
4847 "xTEXTURE_GRADIENT_SAMPLING",
4848 "rMAX_POINT_SIZE",
4849 "xMAX_SHADER_TEXTURES",
4850 "xMAX_TEXTURE_WIDTH",
4851 "xMAX_TEXTURE_HEIGHT",
4852 "xMAX_VOLUME_EXTENT",
4853 "xMAX_TEXTURE_REPEAT",
4854 "xMAX_TEXTURE_ASPECT_RATIO",
4855 "xMAX_TEXTURE_ANISOTROPY",
4856 "xMAX_PRIMITIVE_COUNT",
4857 "xMAX_VERTEX_INDEX",
4858 "xMAX_VERTEX_SHADER_INSTRUCTIONS",
4859 "xMAX_FRAGMENT_SHADER_INSTRUCTIONS",
4860 "xMAX_VERTEX_SHADER_TEMPS",
4861 "xMAX_FRAGMENT_SHADER_TEMPS",
4862 "xTEXTURE_OPS",
4863 "xSURFACEFMT_X8R8G8B8",
4864 "xSURFACEFMT_A8R8G8B8",
4865 "xSURFACEFMT_A2R10G10B10",
4866 "xSURFACEFMT_X1R5G5B5",
4867 "xSURFACEFMT_A1R5G5B5",
4868 "xSURFACEFMT_A4R4G4B4",
4869 "xSURFACEFMT_R5G6B5",
4870 "xSURFACEFMT_LUMINANCE16",
4871 "xSURFACEFMT_LUMINANCE8_ALPHA8",
4872 "xSURFACEFMT_ALPHA8",
4873 "xSURFACEFMT_LUMINANCE8",
4874 "xSURFACEFMT_Z_D16",
4875 "xSURFACEFMT_Z_D24S8",
4876 "xSURFACEFMT_Z_D24X8",
4877 "xSURFACEFMT_DXT1",
4878 "xSURFACEFMT_DXT2",
4879 "xSURFACEFMT_DXT3",
4880 "xSURFACEFMT_DXT4",
4881 "xSURFACEFMT_DXT5",
4882 "xSURFACEFMT_BUMPX8L8V8U8",
4883 "xSURFACEFMT_A2W10V10U10",
4884 "xSURFACEFMT_BUMPU8V8",
4885 "xSURFACEFMT_Q8W8V8U8",
4886 "xSURFACEFMT_CxV8U8",
4887 "xSURFACEFMT_R_S10E5",
4888 "xSURFACEFMT_R_S23E8",
4889 "xSURFACEFMT_RG_S10E5",
4890 "xSURFACEFMT_RG_S23E8",
4891 "xSURFACEFMT_ARGB_S10E5",
4892 "xSURFACEFMT_ARGB_S23E8",
4893 "xMISSING62",
4894 "xMAX_VERTEX_SHADER_TEXTURES",
4895 "xMAX_SIMULTANEOUS_RENDER_TARGETS",
4896 "xSURFACEFMT_V16U16",
4897 "xSURFACEFMT_G16R16",
4898 "xSURFACEFMT_A16B16G16R16",
4899 "xSURFACEFMT_UYVY",
4900 "xSURFACEFMT_YUY2",
4901 "xMULTISAMPLE_NONMASKABLESAMPLES",
4902 "xMULTISAMPLE_MASKABLESAMPLES",
4903 "xALPHATOCOVERAGE",
4904 "xSUPERSAMPLE",
4905 "xAUTOGENMIPMAPS",
4906 "xSURFACEFMT_NV12",
4907 "xSURFACEFMT_AYUV",
4908 "xMAX_CONTEXT_IDS",
4909 "xMAX_SURFACE_IDS",
4910 "xSURFACEFMT_Z_DF16",
4911 "xSURFACEFMT_Z_DF24",
4912 "xSURFACEFMT_Z_D24S8_INT",
4913 "xSURFACEFMT_BC4_UNORM",
4914 "xSURFACEFMT_BC5_UNORM", /* 83 */
4915};
4916# endif
4917
4918
4919/**
4920 * Power On notification.
4921 *
4922 * @returns VBox status code.
4923 * @param pDevIns The device instance data.
4924 *
4925 * @remarks Caller enters the device critical section.
4926 */
4927DECLCALLBACK(void) vmsvgaR3PowerOn(PPDMDEVINS pDevIns)
4928{
4929# ifdef VBOX_WITH_VMSVGA3D
4930 PVGASTATE pThis = PDMINS_2_DATA(pDevIns, PVGASTATE);
4931 if (pThis->svga.f3DEnabled)
4932 {
4933 int rc = vmsvga3dPowerOn(pThis);
4934
4935 if (RT_SUCCESS(rc))
4936 {
4937 bool fSavedBuffering = RTLogRelSetBuffering(true);
4938 SVGA3dCapsRecord *pCaps;
4939 SVGA3dCapPair *pData;
4940 uint32_t idxCap = 0;
4941
4942 /* 3d hardware version; latest and greatest */
4943 pThis->svga.pFIFOR3[SVGA_FIFO_3D_HWVERSION_REVISED] = SVGA3D_HWVERSION_CURRENT;
4944 pThis->svga.pFIFOR3[SVGA_FIFO_3D_HWVERSION] = SVGA3D_HWVERSION_CURRENT;
4945
4946 pCaps = (SVGA3dCapsRecord *)&pThis->svga.pFIFOR3[SVGA_FIFO_3D_CAPS];
4947 pCaps->header.type = SVGA3DCAPS_RECORD_DEVCAPS;
4948 pData = (SVGA3dCapPair *)&pCaps->data;
4949
4950 /* Fill out all 3d capabilities. */
4951 for (unsigned i = 0; i < SVGA3D_DEVCAP_MAX; i++)
4952 {
4953 uint32_t val = 0;
4954
4955 rc = vmsvga3dQueryCaps(pThis, i, &val);
4956 if (RT_SUCCESS(rc))
4957 {
4958 pData[idxCap][0] = i;
4959 pData[idxCap][1] = val;
4960 idxCap++;
4961 if (g_apszVmSvgaDevCapNames[i][0] == 'x')
4962 LogRel(("VMSVGA3d: cap[%u]=%#010x {%s}\n", i, val, &g_apszVmSvgaDevCapNames[i][1]));
4963 else
4964 LogRel(("VMSVGA3d: cap[%u]=%d.%04u {%s}\n", i, (int)*(float *)&val, (unsigned)(*(float *)&val * 10000) % 10000,
4965 &g_apszVmSvgaDevCapNames[i][1]));
4966 }
4967 else
4968 LogRel(("VMSVGA3d: cap[%u]=failed rc=%Rrc! {%s}\n", i, rc, &g_apszVmSvgaDevCapNames[i][1]));
4969 }
4970 pCaps->header.length = (sizeof(pCaps->header) + idxCap * sizeof(SVGA3dCapPair)) / sizeof(uint32_t);
4971 pCaps = (SVGA3dCapsRecord *)((uint32_t *)pCaps + pCaps->header.length);
4972
4973 /* Mark end of record array. */
4974 pCaps->header.length = 0;
4975
4976 RTLogRelSetBuffering(fSavedBuffering);
4977 }
4978 }
4979# else /* !VBOX_WITH_VMSVGA3D */
4980 RT_NOREF(pDevIns);
4981# endif /* !VBOX_WITH_VMSVGA3D */
4982}
4983
4984#endif /* IN_RING3 */
4985
Note: See TracBrowser for help on using the repository browser.

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