VirtualBox

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

Last change on this file since 57064 was 57011, checked in by vboxsync, 9 years ago

vmsvga: Combined the external FIFO command submission into one function and make sure we only execute the external command when we temporarily resume the FIFO thread.

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

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