VirtualBox

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

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

Improved the ugly SVGA_REG_BUSY read hack a bit.

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

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