VirtualBox

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

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

Devices/Main: vmsvga updates

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

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