VirtualBox

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

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

SVGA/SVGA3d: Moved hexdumps from LogFlow() to Log2(), Log3(), and Log4().

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