VirtualBox

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

Last change on this file since 55840 was 55840, checked in by vboxsync, 10 years ago

vmsvga3d/mac: Fixed problem with missing back/front buffers. Stop use renderspu_cocoa_helper.m and use DevVGA-SVGA3d-cocoa.m, only now its even more stripped down that earlier.

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