VirtualBox

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

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

DevVGA-SVGA.cpp: Use RT_FROM_MEMBER.

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