VirtualBox

source: vbox/trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-info.cpp@ 76553

Last change on this file since 76553 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 95.2 KB
Line 
1/* $Id: DevVGA-SVGA3d-info.cpp 76553 2019-01-01 01:45:53Z vboxsync $ */
2/** @file
3 * DevSVGA3d - VMWare SVGA device, 3D parts - Introspection and debugging.
4 */
5
6/*
7 * Copyright (C) 2013-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#include <stdio.h>
23#define LOG_GROUP LOG_GROUP_DEV_VMSVGA
24#include <VBox/vmm/pdmdev.h>
25#include <VBox/err.h>
26#include <VBox/log.h>
27
28#include <iprt/assert.h>
29#include <iprt/mem.h>
30
31#include <VBox/vmm/pgm.h> /* required by DevVGA.h */
32#include <VBoxVideo.h> /* required by DevVGA.h */
33
34/* should go BEFORE any other DevVGA include to make all DevVGA.h config defines be visible */
35#include "DevVGA.h"
36
37#include "DevVGA-SVGA.h"
38#include "DevVGA-SVGA3d.h"
39#define VMSVGA3D_INCL_STRUCTURE_DESCRIPTORS
40#include "DevVGA-SVGA3d-internal.h"
41
42
43/*********************************************************************************************************************************
44* Global Variables *
45*********************************************************************************************************************************/
46/** Enum value to string mappings for SVGA3dSurfaceFormat, prefix "SVGA3D_". */
47static const VMSVGAINFOENUM g_aSVGA3dSurfaceFormats[] =
48{
49 { SVGA3D_FORMAT_INVALID , "FORMAT_INVALID" },
50 { SVGA3D_X8R8G8B8 , "X8R8G8B8" },
51 { SVGA3D_A8R8G8B8 , "A8R8G8B8" },
52 { SVGA3D_R5G6B5 , "R5G6B5" },
53 { SVGA3D_X1R5G5B5 , "X1R5G5B5" },
54 { SVGA3D_A1R5G5B5 , "A1R5G5B5" },
55 { SVGA3D_A4R4G4B4 , "A4R4G4B4" },
56 { SVGA3D_Z_D32 , "Z_D32" },
57 { SVGA3D_Z_D16 , "Z_D16" },
58 { SVGA3D_Z_D24S8 , "Z_D24S8" },
59 { SVGA3D_Z_D15S1 , "Z_D15S1" },
60 { SVGA3D_LUMINANCE8 , "LUMINANCE8" },
61 { SVGA3D_LUMINANCE4_ALPHA4 , "LUMINANCE4_ALPHA4" },
62 { SVGA3D_LUMINANCE16 , "LUMINANCE16" },
63 { SVGA3D_LUMINANCE8_ALPHA8 , "LUMINANCE8_ALPHA8" },
64 { SVGA3D_DXT1 , "DXT1" },
65 { SVGA3D_DXT2 , "DXT2" },
66 { SVGA3D_DXT3 , "DXT3" },
67 { SVGA3D_DXT4 , "DXT4" },
68 { SVGA3D_DXT5 , "DXT5" },
69 { SVGA3D_BUMPU8V8 , "BUMPU8V8" },
70 { SVGA3D_BUMPL6V5U5 , "BUMPL6V5U5" },
71 { SVGA3D_BUMPX8L8V8U8 , "BUMPX8L8V8U8" },
72 { SVGA3D_BUMPL8V8U8 , "BUMPL8V8U8" },
73 { SVGA3D_ARGB_S10E5 , "ARGB_S10E5" },
74 { SVGA3D_ARGB_S23E8 , "ARGB_S23E8" },
75 { SVGA3D_A2R10G10B10 , "A2R10G10B10" },
76 { SVGA3D_V8U8 , "V8U8" },
77 { SVGA3D_Q8W8V8U8 , "Q8W8V8U8" },
78 { SVGA3D_CxV8U8 , "CxV8U8" },
79 { SVGA3D_X8L8V8U8 , "X8L8V8U8" },
80 { SVGA3D_A2W10V10U10 , "A2W10V10U10" },
81 { SVGA3D_ALPHA8 , "ALPHA8" },
82 { SVGA3D_R_S10E5 , "R_S10E5" },
83 { SVGA3D_R_S23E8 , "R_S23E8" },
84 { SVGA3D_RG_S10E5 , "RG_S10E5" },
85 { SVGA3D_RG_S23E8 , "RG_S23E8" },
86 { SVGA3D_BUFFER , "BUFFER" },
87 { SVGA3D_Z_D24X8 , "Z_D24X8" },
88 { SVGA3D_V16U16 , "V16U16" },
89 { SVGA3D_G16R16 , "G16R16" },
90 { SVGA3D_A16B16G16R16 , "A16B16G16R16" },
91 { SVGA3D_UYVY , "UYVY" },
92 { SVGA3D_YUY2 , "YUY2" },
93 { SVGA3D_NV12 , "NV12" },
94 { SVGA3D_AYUV , "AYUV" },
95 { SVGA3D_BC4_UNORM , "BC4_UNORM" },
96 { SVGA3D_BC5_UNORM , "BC5_UNORM" },
97 { SVGA3D_Z_DF16 , "Z_DF16" },
98 { SVGA3D_Z_DF24 , "Z_DF24" },
99 { SVGA3D_Z_D24S8_INT , "Z_D24S8_INT" },
100 { SVGA3D_R8G8B8A8_SNORM , "R8G8B8A8_SNORM" },
101 { SVGA3D_R16G16_UNORM , "R16G16_UNORM" },
102};
103VMSVGAINFOENUMMAP_MAKE(RT_NOTHING, g_SVGA3dSurfaceFormat2String, g_aSVGA3dSurfaceFormats, "SVGA3D_");
104
105/** Values for SVGA3dTextureFilter, prefix SVGA3D_TEX_FILTER_. */
106static const char * const g_apszTexureFilters[] =
107{
108 "NONE",
109 "NEAREST",
110 "LINEAR",
111 "ANISOTROPIC",
112 "FLATCUBIC",
113 "GAUSSIANCUBIC",
114 "PYRAMIDALQUAD",
115 "GAUSSIANQUAD",
116};
117
118/** SVGA3dSurfaceFlags values, prefix SVGA3D_SURFACE_. */
119static VMSVGAINFOFLAGS32 const g_aSvga3DSurfaceFlags[] =
120{
121 { SVGA3D_SURFACE_CUBEMAP , "CUBEMAP" },
122 { SVGA3D_SURFACE_HINT_STATIC , "HINT_STATIC" },
123 { SVGA3D_SURFACE_HINT_DYNAMIC , "HINT_DYNAMIC" },
124 { SVGA3D_SURFACE_HINT_INDEXBUFFER , "HINT_INDEXBUFFER" },
125 { SVGA3D_SURFACE_HINT_VERTEXBUFFER , "HINT_VERTEXBUFFER" },
126 { SVGA3D_SURFACE_HINT_TEXTURE , "HINT_TEXTURE" },
127 { SVGA3D_SURFACE_HINT_RENDERTARGET , "HINT_RENDERTARGET" },
128 { SVGA3D_SURFACE_HINT_DEPTHSTENCIL , "HINT_DEPTHSTENCIL" },
129 { SVGA3D_SURFACE_HINT_WRITEONLY , "HINT_WRITEONLY" },
130 { SVGA3D_SURFACE_MASKABLE_ANTIALIAS , "MASKABLE_ANTIALIAS" },
131 { SVGA3D_SURFACE_AUTOGENMIPMAPS , "AUTOGENMIPMAPS" },
132};
133
134
135#ifdef VMSVGA3D_DIRECT3D
136
137/** Values for D3DFORMAT, prefix D3DFMT_. */
138static VMSVGAINFOENUM const g_aD3DFormats[] =
139{
140 { D3DFMT_UNKNOWN , "UNKNOWN" },
141 { D3DFMT_R8G8B8 , "R8G8B8" },
142 { D3DFMT_A8R8G8B8 , "A8R8G8B8" },
143 { D3DFMT_X8R8G8B8 , "X8R8G8B8" },
144 { D3DFMT_R5G6B5 , "R5G6B5" },
145 { D3DFMT_X1R5G5B5 , "X1R5G5B5" },
146 { D3DFMT_A1R5G5B5 , "A1R5G5B5" },
147 { D3DFMT_A4R4G4B4 , "A4R4G4B4" },
148 { D3DFMT_R3G3B2 , "R3G3B2" },
149 { D3DFMT_A8 , "A8" },
150 { D3DFMT_A8R3G3B2 , "A8R3G3B2" },
151 { D3DFMT_X4R4G4B4 , "X4R4G4B4" },
152 { D3DFMT_A2B10G10R10 , "A2B10G10R10" },
153 { D3DFMT_A8B8G8R8 , "A8B8G8R8" },
154 { D3DFMT_X8B8G8R8 , "X8B8G8R8" },
155 { D3DFMT_G16R16 , "G16R16" },
156 { D3DFMT_A2R10G10B10 , "A2R10G10B10" },
157 { D3DFMT_A16B16G16R16 , "A16B16G16R16" },
158 { D3DFMT_A8P8 , "A8P8" },
159 { D3DFMT_P8 , "P8" },
160 { D3DFMT_L8 , "L8" },
161 { D3DFMT_A8L8 , "A8L8" },
162 { D3DFMT_A4L4 , "A4L4" },
163 { D3DFMT_V8U8 , "V8U8" },
164 { D3DFMT_L6V5U5 , "L6V5U5" },
165 { D3DFMT_X8L8V8U8 , "X8L8V8U8" },
166 { D3DFMT_Q8W8V8U8 , "Q8W8V8U8" },
167 { D3DFMT_V16U16 , "V16U16" },
168 { D3DFMT_A2W10V10U10 , "A2W10V10U10" },
169 { D3DFMT_D16_LOCKABLE , "D16_LOCKABLE" },
170 { D3DFMT_D32 , "D32" },
171 { D3DFMT_D15S1 , "D15S1" },
172 { D3DFMT_D24S8 , "D24S8" },
173 { D3DFMT_D24X8 , "D24X8" },
174 { D3DFMT_D24X4S4 , "D24X4S4" },
175 { D3DFMT_D16 , "D16" },
176 { D3DFMT_L16 , "L16" },
177 { D3DFMT_D32F_LOCKABLE , "D32F_LOCKABLE" },
178 { D3DFMT_D24FS8 , "D24FS8" },
179 { D3DFMT_VERTEXDATA , "VERTEXDATA" },
180 { D3DFMT_INDEX16 , "INDEX16" },
181 { D3DFMT_INDEX32 , "INDEX32" },
182 { D3DFMT_Q16W16V16U16 , "Q16W16V16U16" },
183 { D3DFMT_R16F , "R16F" },
184 { D3DFMT_G16R16F , "G16R16F" },
185 { D3DFMT_A16B16G16R16F , "A16B16G16R16F" },
186 { D3DFMT_R32F , "R32F" },
187 { D3DFMT_G32R32F , "G32R32F" },
188 { D3DFMT_A32B32G32R32F , "A32B32G32R32F" },
189 { D3DFMT_CxV8U8 , "CxV8U8" },
190 /* Fourcc values, MSB is in the right most char: */
191 { D3DFMT_MULTI2_ARGB8 , "MULTI2_ARGB8" },
192 { D3DFMT_DXT1 , "DXT1" },
193 { D3DFMT_DXT2 , "DXT2" },
194 { D3DFMT_YUY2 , "YUY2" },
195 { D3DFMT_DXT3 , "DXT3" },
196 { D3DFMT_DXT4 , "DXT4" },
197 { D3DFMT_DXT5 , "DXT5" },
198 { D3DFMT_G8R8_G8B8 , "G8R8_G8B8" },
199 { D3DFMT_R8G8_B8G8 , "R8G8_B8G8" },
200 { D3DFMT_UYVY , "UYVY" },
201 { D3DFMT_FORCE_DWORD , "FORCE_DWORD" }, /* UINT32_MAX */
202};
203VMSVGAINFOENUMMAP_MAKE(static, g_D3DFormat2String, g_aD3DFormats, "D3DFMT_");
204
205/** Values for D3DMULTISAMPLE_TYPE, prefix D3DMULTISAMPLE_. */
206static VMSVGAINFOENUM const g_aD3DMultiSampleTypes[] =
207{
208 { D3DMULTISAMPLE_NONE , "NONE" },
209 { D3DMULTISAMPLE_NONMASKABLE , "NONMASKABLE" },
210 { D3DMULTISAMPLE_2_SAMPLES , "2_SAMPLES" },
211 { D3DMULTISAMPLE_3_SAMPLES , "3_SAMPLES" },
212 { D3DMULTISAMPLE_4_SAMPLES , "4_SAMPLES" },
213 { D3DMULTISAMPLE_5_SAMPLES , "5_SAMPLES" },
214 { D3DMULTISAMPLE_6_SAMPLES , "6_SAMPLES" },
215 { D3DMULTISAMPLE_7_SAMPLES , "7_SAMPLES" },
216 { D3DMULTISAMPLE_8_SAMPLES , "8_SAMPLES" },
217 { D3DMULTISAMPLE_9_SAMPLES , "9_SAMPLES" },
218 { D3DMULTISAMPLE_10_SAMPLES , "10_SAMPLES" },
219 { D3DMULTISAMPLE_11_SAMPLES , "11_SAMPLES" },
220 { D3DMULTISAMPLE_12_SAMPLES , "12_SAMPLES" },
221 { D3DMULTISAMPLE_13_SAMPLES , "13_SAMPLES" },
222 { D3DMULTISAMPLE_14_SAMPLES , "14_SAMPLES" },
223 { D3DMULTISAMPLE_15_SAMPLES , "15_SAMPLES" },
224 { D3DMULTISAMPLE_16_SAMPLES , "16_SAMPLES" },
225 { D3DMULTISAMPLE_FORCE_DWORD , "FORCE_DWORD" },
226};
227VMSVGAINFOENUMMAP_MAKE(static, g_D3DMultiSampleType2String, g_aD3DMultiSampleTypes, "D3DMULTISAMPLE_");
228
229/** D3DUSAGE_XXX flag value, prefix D3DUSAGE_. */
230static VMSVGAINFOFLAGS32 const g_aD3DUsageFlags[] =
231{
232 { D3DUSAGE_RENDERTARGET , "RENDERTARGET" },
233 { D3DUSAGE_DEPTHSTENCIL , "DEPTHSTENCIL" },
234 { D3DUSAGE_WRITEONLY , "WRITEONLY" },
235 { D3DUSAGE_SOFTWAREPROCESSING , "SOFTWAREPROCESSING" },
236 { D3DUSAGE_DONOTCLIP , "DONOTCLIP" },
237 { D3DUSAGE_POINTS , "POINTS" },
238 { D3DUSAGE_RTPATCHES , "RTPATCHES" },
239 { D3DUSAGE_NPATCHES , "NPATCHES" },
240 { D3DUSAGE_DYNAMIC , "DYNAMIC" },
241 { D3DUSAGE_AUTOGENMIPMAP , "AUTOGENMIPMAP" },
242 { D3DUSAGE_RESTRICTED_CONTENT , "RESTRICTED_CONTENT" },
243 { D3DUSAGE_RESTRICT_SHARED_RESOURCE_DRIVER , "RESTRICT_SHARED_RESOURCE_DRIVER" },
244 { D3DUSAGE_RESTRICT_SHARED_RESOURCE , "RESTRICT_SHARED_RESOURCE" },
245 { D3DUSAGE_DMAP , "DMAP" },
246 { D3DUSAGE_NONSECURE , "NONSECURE" },
247 { D3DUSAGE_TEXTAPI , "TEXTAPI" },
248};
249
250#endif /* VMSVGA3D_DIRECT3D */
251
252
253/**
254 * Worker for vmsvga3dUpdateHeapBuffersForSurfaces.
255 *
256 * This will allocate heap buffers if necessary, thus increasing the memory
257 * usage of the process.
258 *
259 * @todo Would be interesting to share this code with the saved state code.
260 *
261 * @returns VBox status code.
262 * @param pState The 3D state structure.
263 * @param pSurface The surface to refresh the heap buffers for.
264 */
265static int vmsvga3dSurfaceUpdateHeapBuffers(PVMSVGA3DSTATE pState, PVMSVGA3DSURFACE pSurface)
266{
267 /*
268 * Currently we've got trouble retreving bit for DEPTHSTENCIL
269 * surfaces both for OpenGL and D3D, so skip these here (don't
270 * wast memory on them).
271 */
272 uint32_t const fSwitchFlags = pSurface->surfaceFlags & VMSVGA3D_SURFACE_HINT_SWITCH_MASK;
273 if ( fSwitchFlags != SVGA3D_SURFACE_HINT_DEPTHSTENCIL
274 && fSwitchFlags != (SVGA3D_SURFACE_HINT_DEPTHSTENCIL | SVGA3D_SURFACE_HINT_TEXTURE))
275 {
276
277#ifdef VMSVGA3D_OPENGL
278 /*
279 * Change OpenGL context to the one the surface is associated with.
280 */
281 PVMSVGA3DCONTEXT pContext = &pState->SharedCtx;
282 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
283#endif
284
285 /*
286 * Work thru each mipmap level for each face.
287 */
288 for (uint32_t iFace = 0; iFace < pSurface->cFaces; iFace++)
289 {
290 Assert(pSurface->faces[iFace].numMipLevels <= pSurface->faces[0].numMipLevels);
291 PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->pMipmapLevels[iFace * pSurface->faces[0].numMipLevels];
292 for (uint32_t i = 0; i < pSurface->faces[iFace].numMipLevels; i++, pMipmapLevel++)
293 {
294#ifdef VMSVGA3D_DIRECT3D
295 if (pSurface->u.pSurface)
296#else
297 if (pSurface->oglId.texture != OPENGL_INVALID_ID)
298#endif
299 {
300 Assert(pMipmapLevel->cbSurface);
301 Assert(pMipmapLevel->cbSurface == pMipmapLevel->cbSurfacePlane * pMipmapLevel->mipmapSize.depth);
302
303 /*
304 * Make sure we've got surface memory buffer.
305 */
306 uint8_t *pbDst = (uint8_t *)pMipmapLevel->pSurfaceData;
307 if (!pbDst)
308 {
309 pMipmapLevel->pSurfaceData = pbDst = (uint8_t *)RTMemAllocZ(pMipmapLevel->cbSurface);
310 AssertReturn(pbDst, VERR_NO_MEMORY);
311 }
312
313#ifdef VMSVGA3D_DIRECT3D
314 /*
315 * D3D specifics.
316 */
317 Assert(pSurface->enmD3DResType != VMSVGA3D_D3DRESTYPE_NONE);
318
319 HRESULT hr;
320 switch (pSurface->enmD3DResType)
321 {
322 case VMSVGA3D_D3DRESTYPE_VOLUME_TEXTURE:
323 AssertFailed(); /// @todo
324 break;
325
326 case VMSVGA3D_D3DRESTYPE_SURFACE:
327 case VMSVGA3D_D3DRESTYPE_TEXTURE:
328 case VMSVGA3D_D3DRESTYPE_CUBE_TEXTURE:
329 {
330 /*
331 * Lock the buffer and make it accessible to memcpy.
332 */
333 D3DLOCKED_RECT LockedRect;
334 if (pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_CUBE_TEXTURE)
335 {
336 hr = pSurface->u.pCubeTexture->LockRect(vmsvga3dCubemapFaceFromIndex(iFace),
337 i, /* texture level */
338 &LockedRect,
339 NULL,
340 D3DLOCK_READONLY);
341 }
342 else if (pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_TEXTURE)
343 {
344 if (pSurface->bounce.pTexture)
345 {
346 if ( !pSurface->fDirty
347 && RT_BOOL(fSwitchFlags & SVGA3D_SURFACE_HINT_RENDERTARGET)
348 && i == 0 /* only the first time */)
349 {
350 /** @todo stricter checks for associated context */
351 uint32_t cid = pSurface->idAssociatedContext;
352 if ( cid >= pState->cContexts
353 || pState->papContexts[cid]->id != cid)
354 {
355 Log(("vmsvga3dSurfaceUpdateHeapBuffers: invalid context id (%x - %x)!\n", cid, (cid >= pState->cContexts) ? -1 : pState->papContexts[cid]->id));
356 AssertFailedReturn(VERR_INVALID_PARAMETER);
357 }
358 PVMSVGA3DCONTEXT pContext = pState->papContexts[cid];
359
360 IDirect3DSurface9 *pDst = NULL;
361 hr = pSurface->bounce.pTexture->GetSurfaceLevel(i, &pDst);
362 AssertMsgReturn(hr == D3D_OK, ("GetSurfaceLevel failed with %#x\n", hr), VERR_INTERNAL_ERROR);
363
364 IDirect3DSurface9 *pSrc = NULL;
365 hr = pSurface->u.pTexture->GetSurfaceLevel(i, &pSrc);
366 AssertMsgReturn(hr == D3D_OK, ("GetSurfaceLevel failed with %#x\n", hr), VERR_INTERNAL_ERROR);
367
368 hr = pContext->pDevice->GetRenderTargetData(pSrc, pDst);
369 AssertMsgReturn(hr == D3D_OK, ("GetRenderTargetData failed with %#x\n", hr), VERR_INTERNAL_ERROR);
370
371 pSrc->Release();
372 pDst->Release();
373 }
374
375 hr = pSurface->bounce.pTexture->LockRect(i, /* texture level */
376 &LockedRect,
377 NULL,
378 D3DLOCK_READONLY);
379 }
380 else
381 hr = pSurface->u.pTexture->LockRect(i, /* texture level */
382 &LockedRect,
383 NULL,
384 D3DLOCK_READONLY);
385 }
386 else
387 hr = pSurface->u.pSurface->LockRect(&LockedRect,
388 NULL,
389 D3DLOCK_READONLY);
390 AssertMsgReturn(hr == D3D_OK, ("LockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
391
392 /*
393 * Copy the data. Take care in case the pitch differs.
394 */
395 if (pMipmapLevel->cbSurfacePitch == (uint32_t)LockedRect.Pitch)
396 memcpy(pbDst, LockedRect.pBits, pMipmapLevel->cbSurface);
397 else
398 for (uint32_t j = 0; j < pMipmapLevel->cBlocksY; j++)
399 memcpy(pbDst + j * pMipmapLevel->cbSurfacePitch,
400 (uint8_t *)LockedRect.pBits + j * LockedRect.Pitch,
401 pMipmapLevel->cbSurfacePitch);
402
403 /*
404 * Release the buffer.
405 */
406 if (fSwitchFlags & SVGA3D_SURFACE_HINT_TEXTURE)
407 {
408 if (pSurface->bounce.pTexture)
409 {
410 hr = pSurface->bounce.pTexture->UnlockRect(i);
411 AssertMsgReturn(hr == D3D_OK, ("UnlockRect failed with %#x\n", hr), VERR_INTERNAL_ERROR);
412 }
413 else
414 hr = pSurface->u.pTexture->UnlockRect(i);
415 }
416 else
417 hr = pSurface->u.pSurface->UnlockRect();
418 AssertMsgReturn(hr == D3D_OK, ("UnlockRect failed with %#x\n", hr), VERR_INTERNAL_ERROR);
419 break;
420 }
421
422 case VMSVGA3D_D3DRESTYPE_VERTEX_BUFFER:
423 case VMSVGA3D_D3DRESTYPE_INDEX_BUFFER:
424 {
425 /* Current type of the buffer. */
426 const bool fVertex = (pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_VERTEX_BUFFER);
427
428 void *pvD3DData = NULL;
429 if (fVertex)
430 hr = pSurface->u.pVertexBuffer->Lock(0, 0, &pvD3DData, D3DLOCK_READONLY);
431 else
432 hr = pSurface->u.pIndexBuffer->Lock(0, 0, &pvD3DData, D3DLOCK_READONLY);
433 AssertMsgReturn(hr == D3D_OK, ("Lock %s failed with %x\n", fVertex ? "vertex" : "index", hr), VERR_INTERNAL_ERROR);
434
435 memcpy(pbDst, pvD3DData, pMipmapLevel->cbSurface);
436
437 if (fVertex)
438 hr = pSurface->u.pVertexBuffer->Unlock();
439 else
440 hr = pSurface->u.pIndexBuffer->Unlock();
441 AssertMsg(hr == D3D_OK, ("Unlock %s failed with %x\n", fVertex ? "vertex" : "index", hr));
442 break;
443 }
444
445 default:
446 AssertMsgFailed(("flags %#x, type %d\n", fSwitchFlags, pSurface->enmD3DResType));
447 }
448
449#elif defined(VMSVGA3D_OPENGL)
450 /*
451 * OpenGL specifics.
452 */
453 switch (fSwitchFlags)
454 {
455 case SVGA3D_SURFACE_HINT_TEXTURE:
456 case SVGA3D_SURFACE_HINT_RENDERTARGET:
457 case SVGA3D_SURFACE_HINT_TEXTURE | SVGA3D_SURFACE_HINT_RENDERTARGET:
458 {
459 GLint activeTexture;
460 glGetIntegerv(GL_TEXTURE_BINDING_2D, &activeTexture);
461 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
462
463 glBindTexture(GL_TEXTURE_2D, pSurface->oglId.texture);
464 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
465
466 /* Set row length and alignment of the output data. */
467 VMSVGAPACKPARAMS SavedParams;
468 vmsvga3dOglSetPackParams(pState, pContext, pSurface, &SavedParams);
469
470 glGetTexImage(GL_TEXTURE_2D,
471 i,
472 pSurface->formatGL,
473 pSurface->typeGL,
474 pbDst);
475 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
476
477 vmsvga3dOglRestorePackParams(pState, pContext, pSurface, &SavedParams);
478
479 /* Restore the old active texture. */
480 glBindTexture(GL_TEXTURE_2D, activeTexture);
481 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
482 break;
483 }
484
485 case SVGA3D_SURFACE_HINT_VERTEXBUFFER | SVGA3D_SURFACE_HINT_INDEXBUFFER:
486 case SVGA3D_SURFACE_HINT_VERTEXBUFFER:
487 case SVGA3D_SURFACE_HINT_INDEXBUFFER:
488 {
489 pState->ext.glBindBuffer(GL_ARRAY_BUFFER, pSurface->oglId.buffer);
490 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
491
492 void *pvSrc = pState->ext.glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
493 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
494 if (RT_VALID_PTR(pvSrc))
495 memcpy(pbDst, pvSrc, pMipmapLevel->cbSurface);
496 else
497 AssertPtr(pvSrc);
498
499 pState->ext.glUnmapBuffer(GL_ARRAY_BUFFER);
500 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
501
502 pState->ext.glBindBuffer(GL_ARRAY_BUFFER, 0);
503 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
504 break;
505 }
506
507 default:
508 AssertMsgFailed(("%#x\n", fSwitchFlags));
509 }
510#else
511# error "misconfigured"
512#endif
513 }
514 /* else: There is no data in hardware yet, so whatever we got is already current. */
515 }
516 }
517 }
518
519 return VINF_SUCCESS;
520}
521
522
523/**
524 * Updates the heap buffers for all surfaces or one specific one.
525 *
526 * @param pThis The VGA device instance data.
527 * @param sid The surface ID, UINT32_MAX if all.
528 * @thread VMSVGAFIFO
529 */
530void vmsvga3dUpdateHeapBuffersForSurfaces(PVGASTATE pThis, uint32_t sid)
531{
532 PVMSVGA3DSTATE pState = pThis->svga.p3dState;
533 AssertReturnVoid(pState);
534
535 if (sid == UINT32_MAX)
536 {
537 uint32_t cSurfaces = pState->cSurfaces;
538 for (sid = 0; sid < cSurfaces; sid++)
539 {
540 PVMSVGA3DSURFACE pSurface = pState->papSurfaces[sid];
541 if (pSurface && pSurface->id == sid)
542 vmsvga3dSurfaceUpdateHeapBuffers(pState, pSurface);
543 }
544 }
545 else if (sid < pState->cSurfaces)
546 {
547 PVMSVGA3DSURFACE pSurface = pState->papSurfaces[sid];
548 if (pSurface && pSurface->id == sid)
549 vmsvga3dSurfaceUpdateHeapBuffers(pState, pSurface);
550 }
551}
552
553
554
555
556void vmsvga3dInfoU32Flags(PCDBGFINFOHLP pHlp, uint32_t fFlags, const char *pszPrefix, PCVMSVGAINFOFLAGS32 paFlags, uint32_t cFlags)
557{
558 for (uint32_t i = 0; i < cFlags; i++)
559 if ((paFlags[i].fFlags & fFlags) == paFlags[i].fFlags)
560 {
561 Assert(paFlags[i].fFlags);
562 pHlp->pfnPrintf(pHlp, " %s%s", pszPrefix, paFlags[i].pszJohnny);
563 fFlags &= ~paFlags[i].fFlags;
564 if (!fFlags)
565 return;
566 }
567 if (fFlags)
568 pHlp->pfnPrintf(pHlp, " UNKNOWN_%#x", fFlags);
569}
570
571
572/**
573 * Worker for vmsvgaR3Info that display details of a host window.
574 *
575 * @param pHlp The output methods.
576 * @param idHostWindow The host window handle/id/whatever.
577 */
578void vmsvga3dInfoHostWindow(PCDBGFINFOHLP pHlp, uint64_t idHostWindow)
579{
580#ifdef RT_OS_WINDOWS
581 HWND hwnd = (HWND)(uintptr_t)idHostWindow;
582 Assert((uintptr_t)hwnd == idHostWindow);
583 if (hwnd != NULL)
584 {
585 WINDOWINFO Info;
586 RT_ZERO(Info);
587 Info.cbSize = sizeof(Info);
588 if (GetWindowInfo(hwnd, &Info))
589 {
590 pHlp->pfnPrintf(pHlp, " Window rect: xLeft=%d, yTop=%d, xRight=%d, yBottom=%d (cx=%d, cy=%d)\n",
591 Info.rcWindow.left, Info.rcWindow.top, Info.rcWindow.right, Info.rcWindow.bottom,
592 Info.rcWindow.right - Info.rcWindow.left, Info.rcWindow.bottom - Info.rcWindow.top);
593 pHlp->pfnPrintf(pHlp, " Client rect: xLeft=%d, yTop=%d, xRight=%d, yBottom=%d (cx=%d, cy=%d)\n",
594 Info.rcClient.left, Info.rcClient.top, Info.rcClient.right, Info.rcClient.bottom,
595 Info.rcClient.right - Info.rcClient.left, Info.rcClient.bottom - Info.rcClient.top);
596 pHlp->pfnPrintf(pHlp, " Style: %#x", Info.dwStyle);
597 static const VMSVGAINFOFLAGS32 g_aStyles[] =
598 {
599 { WS_POPUP , "POPUP" },
600 { WS_CHILD , "CHILD" },
601 { WS_MINIMIZE , "MINIMIZE" },
602 { WS_VISIBLE , "VISIBLE" },
603 { WS_DISABLED , "DISABLED" },
604 { WS_CLIPSIBLINGS , "CLIPSIBLINGS" },
605 { WS_CLIPCHILDREN , "CLIPCHILDREN" },
606 { WS_MAXIMIZE , "MAXIMIZE" },
607 { WS_BORDER , "BORDER" },
608 { WS_DLGFRAME , "DLGFRAME" },
609 { WS_VSCROLL , "VSCROLL" },
610 { WS_HSCROLL , "HSCROLL" },
611 { WS_SYSMENU , "SYSMENU" },
612 { WS_THICKFRAME , "THICKFRAME" },
613 { WS_GROUP , "GROUP" },
614 { WS_TABSTOP , "TABSTOP" },
615 };
616 vmsvga3dInfoU32Flags(pHlp, Info.dwStyle, "", g_aStyles, RT_ELEMENTS(g_aStyles));
617 pHlp->pfnPrintf(pHlp, "\n");
618
619 pHlp->pfnPrintf(pHlp, " ExStyle: %#x", Info.dwExStyle);
620 static const VMSVGAINFOFLAGS32 g_aExStyles[] =
621 {
622 { WS_EX_DLGMODALFRAME, "DLGMODALFRAME" },
623 { 0x00000002, "DRAGDETECT" },
624 { WS_EX_NOPARENTNOTIFY, "NOPARENTNOTIFY" },
625 { WS_EX_TOPMOST, "TOPMOST" },
626 { WS_EX_ACCEPTFILES, "ACCEPTFILES" },
627 { WS_EX_TRANSPARENT, "TRANSPARENT" },
628 { WS_EX_MDICHILD, "MDICHILD" },
629 { WS_EX_TOOLWINDOW, "TOOLWINDOW" },
630 { WS_EX_WINDOWEDGE, "WINDOWEDGE" },
631 { WS_EX_CLIENTEDGE, "CLIENTEDGE" },
632 { WS_EX_CONTEXTHELP, "CONTEXTHELP" },
633 { WS_EX_RIGHT, "RIGHT" },
634 /*{ WS_EX_LEFT, "LEFT" }, = 0 */
635 { WS_EX_RTLREADING, "RTLREADING" },
636 /*{ WS_EX_LTRREADING, "LTRREADING" }, = 0 */
637 { WS_EX_LEFTSCROLLBAR, "LEFTSCROLLBAR" },
638 /*{ WS_EX_RIGHTSCROLLBAR, "RIGHTSCROLLBAR" }, = 0 */
639 { WS_EX_CONTROLPARENT, "CONTROLPARENT" },
640 { WS_EX_STATICEDGE, "STATICEDGE" },
641 { WS_EX_APPWINDOW, "APPWINDOW" },
642 { WS_EX_LAYERED, "LAYERED" },
643 { WS_EX_NOINHERITLAYOUT, "NOINHERITLAYOUT" },
644 { WS_EX_LAYOUTRTL, "LAYOUTRTL" },
645 { WS_EX_COMPOSITED, "COMPOSITED" },
646 { WS_EX_NOACTIVATE, "NOACTIVATE" },
647 };
648 vmsvga3dInfoU32Flags(pHlp, Info.dwExStyle, "", g_aExStyles, RT_ELEMENTS(g_aExStyles));
649 pHlp->pfnPrintf(pHlp, "\n");
650
651 pHlp->pfnPrintf(pHlp, " Window Status: %#x\n", Info.dwWindowStatus);
652 if (Info.cxWindowBorders || Info.cyWindowBorders)
653 pHlp->pfnPrintf(pHlp, " Borders: cx=%u, cy=%u\n", Info.cxWindowBorders, Info.cyWindowBorders);
654 pHlp->pfnPrintf(pHlp, " Window Type: %#x\n", Info.atomWindowType);
655 pHlp->pfnPrintf(pHlp, " Creator Ver: %#x\n", Info.wCreatorVersion);
656 }
657 else
658 pHlp->pfnPrintf(pHlp, " GetWindowInfo: last error %d\n", GetLastError());
659 }
660
661#elif defined(RT_OS_DARWIN)
662 int rc = ExplicitlyLoadVBoxSVGA3DObjC(false /*fResolveAllImports*/, NULL /*pErrInfo*/);
663 if (RT_SUCCESS(rc))
664 vmsvga3dCocoaViewInfo(pHlp, (NativeNSViewRef)(uintptr_t)idHostWindow);
665 else
666 pHlp->pfnPrintf(pHlp, " Windows info: vmsvga3dCocoaViewInfo failed to load (%Rrc)\n", rc);
667
668#else
669 RT_NOREF(idHostWindow);
670 pHlp->pfnPrintf(pHlp, " Windows info: Not implemented on this platform\n");
671#endif
672}
673
674
675/**
676 * Looks up an enum value in a translation table.
677 *
678 * @returns The value name.
679 * @param iValue The value to name.
680 * @param pEnumMap Enum value to string mapping.
681 */
682const char *vmsvgaLookupEnum(int32_t iValue, PCVMSVGAINFOENUMMAP pEnumMap)
683{
684 PCVMSVGAINFOENUM paValues = pEnumMap->paValues;
685
686#ifdef VBOX_STRICT
687 /*
688 * Check that it's really sorted, or the binary lookup won't work right.
689 */
690 if (!*pEnumMap->pfAsserted)
691 {
692 *pEnumMap->pfAsserted = true;
693 for (uint32_t i = 1; i < pEnumMap->cValues; i++)
694 Assert(paValues[i - 1].iValue <= paValues[i].iValue);
695 }
696#endif
697
698 /*
699 * Binary search
700 */
701 uint32_t iStart = 0;
702 uint32_t iEnd = (uint32_t)pEnumMap->cValues;
703 for (;;)
704 {
705 uint32_t i = iStart + (iEnd - iStart) / 2;
706 if (iValue < paValues[i].iValue)
707 {
708 if (i > iStart)
709 iEnd = i;
710 else
711 break;
712 }
713 else if (iValue > paValues[i].iValue)
714 {
715 i++;
716 if (i < iEnd)
717 iStart = i;
718 else
719 break;
720 }
721 else
722 return paValues[i].pszName;
723 }
724 return NULL;
725}
726
727
728/**
729 * Formats an enum value as a string, sparse mapping table.
730 *
731 * @returns pszBuffer.
732 * @param pszBuffer The output buffer.
733 * @param cbBuffer The size of the output buffer.
734 * @param pszName The variable name, optional.
735 * @param iValue The enum value.
736 * @param fPrefix Whether to prepend the prefix or not.
737 * @param pEnumMap Enum value to string mapping.
738 */
739char *vmsvgaFormatEnumValueEx(char *pszBuffer, size_t cbBuffer, const char *pszName, int32_t iValue,
740 bool fPrefix, PCVMSVGAINFOENUMMAP pEnumMap)
741{
742 const char *pszValueName = vmsvgaLookupEnum(iValue, pEnumMap);
743 const char *pszPrefix = fPrefix ? pEnumMap->pszPrefix : "";
744 if (pszValueName)
745 {
746 if (pszName)
747 RTStrPrintf(pszBuffer, cbBuffer, "%s = %s%s (%#x)", pszName, pszPrefix, pszValueName, iValue);
748 else
749 RTStrPrintf(pszBuffer, cbBuffer, "%s%s (%#x)", pszPrefix, pszValueName, iValue);
750 return pszBuffer;
751 }
752
753 if (pszName)
754 RTStrPrintf(pszBuffer, cbBuffer, "%s = %sUNKNOWN_%d (%#x)", pszName, pszPrefix, iValue, iValue);
755 else
756 RTStrPrintf(pszBuffer, cbBuffer, "%sUNKNOWN_%d (%#x)", pszPrefix, iValue, iValue);
757 return pszBuffer;
758}
759
760
761/**
762 * Formats an enum value as a string.
763 *
764 * @returns pszBuffer.
765 * @param pszBuffer The output buffer.
766 * @param cbBuffer The size of the output buffer.
767 * @param pszName The variable name, optional.
768 * @param uValue The enum value.
769 * @param pszPrefix The prefix of the enum values. Empty string if
770 * none. This helps reduce the memory footprint
771 * as well as the source code size.
772 * @param papszValues One to one string mapping of the enum values.
773 * @param cValues The number of values in the mapping.
774 */
775char *vmsvgaFormatEnumValue(char *pszBuffer, size_t cbBuffer, const char *pszName, uint32_t uValue,
776 const char *pszPrefix, const char * const *papszValues, size_t cValues)
777{
778 if (uValue < cValues)
779 {
780 if (pszName)
781 RTStrPrintf(pszBuffer, cbBuffer, "%s = %s%s (%#x)", pszName, pszPrefix, papszValues[uValue], uValue);
782 else
783 RTStrPrintf(pszBuffer, cbBuffer, "%s%s (%#x)", pszPrefix, papszValues[uValue], uValue);
784 }
785 else
786 {
787 if (pszName)
788 RTStrPrintf(pszBuffer, cbBuffer, "%s = %sUNKNOWN_%d (%#x)", pszName, pszPrefix, uValue, uValue);
789 else
790 RTStrPrintf(pszBuffer, cbBuffer, "%sUNKNOWN_%d (%#x)", pszPrefix, uValue, uValue);
791 }
792 return pszBuffer;
793}
794
795
796/**
797 * DBGF info printer for vmsvga3dAsciiPrint.
798 *
799 * @param pszLine The line to print.
800 * @param pvUser The debug info helpers.
801 */
802DECLCALLBACK(void) vmsvga3dAsciiPrintlnInfo(const char *pszLine, void *pvUser)
803{
804 PCDBGFINFOHLP pHlp = (PCDBGFINFOHLP)pvUser;
805 pHlp->pfnPrintf(pHlp, ">%s<\n", pszLine);
806}
807
808
809/**
810 * Log printer for vmsvga3dAsciiPrint.
811 *
812 * @param pszLine The line to print.
813 * @param pvUser Ignored.
814 */
815DECLCALLBACK(void) vmsvga3dAsciiPrintlnLog(const char *pszLine, void *pvUser)
816{
817 size_t cch = strlen(pszLine);
818 while (cch > 0 && pszLine[cch - 1] == ' ')
819 cch--;
820 RTLogPrintf("%.*s\n", cch, pszLine);
821 NOREF(pvUser);
822}
823
824
825void vmsvga3dAsciiPrint(PFMVMSVGAASCIIPRINTLN pfnPrintLine, void *pvUser, void const *pvImage, size_t cbImage,
826 uint32_t cx, uint32_t cy, uint32_t cbScanline, SVGA3dSurfaceFormat enmFormat, bool fInvY,
827 uint32_t cchMaxX, uint32_t cchMaxY)
828{
829 RT_NOREF(cbImage);
830
831 /*
832 * Skip stuff we can't or won't need to handle.
833 */
834 if (!cx || !cy || !cchMaxX || !cchMaxY)
835 return;
836 switch (enmFormat)
837 {
838 /* Compressed. */
839 case SVGA3D_DXT1:
840 case SVGA3D_DXT2:
841 case SVGA3D_DXT3:
842 case SVGA3D_DXT4:
843 case SVGA3D_DXT5:
844 return;
845 /* Generic. */
846 case SVGA3D_BUFFER:
847 return;
848 default:
849 break; /* ok */
850 }
851
852 /*
853 * Figure the pixel conversion factors.
854 */
855 uint32_t cxPerChar = cx / cchMaxX + 1;
856 uint32_t cyPerChar = cy / cchMaxY + 1;
857 /** @todo try keep aspect... */
858 uint32_t const cchLine = (cx + cxPerChar - 1) / cxPerChar;
859 uint32_t const cbSrcPixel = vmsvga3dSurfaceFormatSize(enmFormat, NULL, NULL);
860
861 /*
862 * The very simple conversion we're doing in this function is based on
863 * mapping a block of converted pixels to an ASCII character of similar
864 * weigth. We do that by summing up all the 8-bit gray scale pixels in
865 * that block, applying a conversion factor and getting an index into an
866 * array of increasingly weighty characters.
867 */
868 static const char s_szPalette[] = " ..`',:;icodxkO08XNWM";
869 static const uint32_t s_cchPalette = sizeof(s_szPalette) - 1;
870 uint32_t const cPixelsWeightPerChar = cxPerChar * cyPerChar * 256;
871
872 /*
873 * Do the work
874 */
875 uint32_t *pauScanline = (uint32_t *)RTMemTmpAllocZ(sizeof(pauScanline[0]) * cchLine + cchLine + 1);
876 if (!pauScanline)
877 return;
878 char *pszLine = (char *)&pauScanline[cchLine];
879 RTCPTRUNION uSrc;
880 uSrc.pv = pvImage;
881 if (fInvY)
882 uSrc.pu8 += (cy - 1) * cbScanline;
883 uint32_t cyLeft = cy;
884 uint32_t cyLeftInScanline = cyPerChar;
885 bool fHitFormatAssert = false;
886 for (;;)
887 {
888 /*
889 * Process the scanline. This is tedious because of all the
890 * different formats. We generally ignore alpha, unless it's
891 * all we've got to work with.
892 * Color to 8-bit grayscale conversion is done by averaging.
893 */
894#define CONVERT_SCANLINE(a_RdExpr, a_AddExpr) \
895 do { \
896 for (uint32_t xSrc = 0, xDst = 0, cxLeftInChar = cxPerChar; xSrc < cx; xSrc++) \
897 { \
898 a_RdExpr; \
899 pauScanline[xDst] += (a_AddExpr) & 0xff; \
900 Assert(pauScanline[xDst] <= cPixelsWeightPerChar); \
901 if (--cxLeftInChar == 0) \
902 { \
903 xDst++; \
904 cxLeftInChar = cxPerChar; \
905 } \
906 } \
907 } while (0)
908
909 switch (enmFormat)
910 {
911 /* Unsigned RGB and super/subsets. */
912 case SVGA3D_X8R8G8B8:
913 case SVGA3D_A8R8G8B8:
914 CONVERT_SCANLINE(uint32_t const u32Tmp = uSrc.pu32[xSrc],
915 ( ( u32Tmp & 0xff) /* B */
916 + ((u32Tmp >> 8) & 0xff) /* G */
917 + ((u32Tmp >> 16) & 0xff) /* R */) / 3);
918 break;
919 case SVGA3D_R5G6B5:
920 CONVERT_SCANLINE(uint16_t const u16Tmp = uSrc.pu16[xSrc],
921 ( ( u16Tmp & 0x1f) * 8
922 + ((u16Tmp >> 5) & 0x3f) * 4
923 + ( u16Tmp >> 11) * 8 ) / 3 );
924 break;
925 case SVGA3D_X1R5G5B5:
926 case SVGA3D_A1R5G5B5:
927 CONVERT_SCANLINE(uint16_t const u16Tmp = uSrc.pu16[xSrc],
928 ( ( u16Tmp & 0x1f) * 8
929 + ((u16Tmp >> 5) & 0x1f) * 8
930 + ((u16Tmp >> 10) & 0x1f) * 8) / 3 );
931 break;
932 case SVGA3D_A4R4G4B4:
933 CONVERT_SCANLINE(uint16_t const u16Tmp = uSrc.pu16[xSrc],
934 ( ( u16Tmp & 0xf) * 16
935 + ((u16Tmp >> 4) & 0xf) * 16
936 + ((u16Tmp >> 8) & 0xf) * 16) / 3 );
937 break;
938 case SVGA3D_A16B16G16R16:
939 CONVERT_SCANLINE(uint64_t const u64Tmp = uSrc.pu64[xSrc],
940 ( ((u64Tmp >> 8) & 0xff) /* R */
941 + ((u64Tmp >> 24) & 0xff) /* G */
942 + ((u64Tmp >> 40) & 0xff) /* B */ ) / 3);
943 break;
944 case SVGA3D_A2R10G10B10:
945 CONVERT_SCANLINE(uint32_t const u32Tmp = uSrc.pu32[xSrc],
946 ( ( u32Tmp & 0x3ff) /* B */
947 + ((u32Tmp >> 10) & 0x3ff) /* G */
948 + ((u32Tmp >> 20) & 0x3ff) /* R */ ) / (3 * 4));
949 break;
950 case SVGA3D_G16R16:
951 CONVERT_SCANLINE(uint32_t const u32Tmp = uSrc.pu32[xSrc],
952 ( (u32Tmp & 0xffff) /* R */
953 + (u32Tmp >> 16 ) /* G */) / 0x200);
954 break;
955
956 /* Depth. */
957 case SVGA3D_Z_D32:
958 CONVERT_SCANLINE(uint32_t const u32Tmp = ~((uSrc.pu32[xSrc] >> 1) | uSrc.pu32[xSrc]) & UINT32_C(0x44444444),
959 (( u32Tmp >> (2 - 0)) & RT_BIT_32(0))
960 | ((u32Tmp >> ( 6 - 1)) & RT_BIT_32(1))
961 | ((u32Tmp >> (10 - 2)) & RT_BIT_32(2))
962 | ((u32Tmp >> (14 - 3)) & RT_BIT_32(3))
963 | ((u32Tmp >> (18 - 4)) & RT_BIT_32(4))
964 | ((u32Tmp >> (22 - 5)) & RT_BIT_32(5))
965 | ((u32Tmp >> (26 - 6)) & RT_BIT_32(6))
966 | ((u32Tmp >> (30 - 7)) & RT_BIT_32(7)) );
967 break;
968 case SVGA3D_Z_D16:
969 CONVERT_SCANLINE(uint16_t const u16Tmp = ~uSrc.pu16[xSrc],
970 ((u16Tmp >> ( 1 - 0)) & RT_BIT_32(0))
971 | ((u16Tmp >> ( 3 - 1)) & RT_BIT_32(1))
972 | ((u16Tmp >> ( 5 - 2)) & RT_BIT_32(2))
973 | ((u16Tmp >> ( 7 - 3)) & RT_BIT_32(3))
974 | ((u16Tmp >> ( 9 - 4)) & RT_BIT_32(4))
975 | ((u16Tmp >> (11 - 5)) & RT_BIT_32(5))
976 | ((u16Tmp >> (13 - 6)) & RT_BIT_32(6))
977 | ((u16Tmp >> (15 - 7)) & RT_BIT_32(7)) );
978 break;
979 case SVGA3D_Z_D24S8:
980 CONVERT_SCANLINE(uint32_t const u32Tmp = uSrc.pu32[xSrc],
981 ( u32Tmp & 0xff) /* stencile */
982 | ((~u32Tmp >> 18) & 0x3f));
983 break;
984 case SVGA3D_Z_D15S1:
985 CONVERT_SCANLINE(uint16_t const u16Tmp = uSrc.pu16[xSrc],
986 ( (u16Tmp & 0x01) << 7) /* stencile */
987 | ((~u16Tmp >> 8) & 0x7f));
988 break;
989
990 /* Pure alpha. */
991 case SVGA3D_ALPHA8:
992 CONVERT_SCANLINE(RT_NOTHING, uSrc.pu8[xSrc]);
993 break;
994
995 /* Luminance */
996 case SVGA3D_LUMINANCE8:
997 CONVERT_SCANLINE(RT_NOTHING, uSrc.pu8[xSrc]);
998 break;
999 case SVGA3D_LUMINANCE4_ALPHA4:
1000 CONVERT_SCANLINE(RT_NOTHING, uSrc.pu8[xSrc] & 0xf0);
1001 break;
1002 case SVGA3D_LUMINANCE16:
1003 CONVERT_SCANLINE(RT_NOTHING, uSrc.pu16[xSrc] >> 8);
1004 break;
1005 case SVGA3D_LUMINANCE8_ALPHA8:
1006 CONVERT_SCANLINE(RT_NOTHING, uSrc.pu16[xSrc] >> 8);
1007 break;
1008
1009 /* Not supported. */
1010 case SVGA3D_DXT1:
1011 case SVGA3D_DXT2:
1012 case SVGA3D_DXT3:
1013 case SVGA3D_DXT4:
1014 case SVGA3D_DXT5:
1015 case SVGA3D_BUFFER:
1016 AssertFailedBreak();
1017
1018 /* Not considered for implementation yet. */
1019 case SVGA3D_BUMPU8V8:
1020 case SVGA3D_BUMPL6V5U5:
1021 case SVGA3D_BUMPX8L8V8U8:
1022 case SVGA3D_BUMPL8V8U8:
1023 case SVGA3D_ARGB_S10E5:
1024 case SVGA3D_ARGB_S23E8:
1025 case SVGA3D_V8U8:
1026 case SVGA3D_Q8W8V8U8:
1027 case SVGA3D_CxV8U8:
1028 case SVGA3D_X8L8V8U8:
1029 case SVGA3D_A2W10V10U10:
1030 case SVGA3D_R_S10E5:
1031 case SVGA3D_R_S23E8:
1032 case SVGA3D_RG_S10E5:
1033 case SVGA3D_RG_S23E8:
1034 case SVGA3D_Z_D24X8:
1035 case SVGA3D_V16U16:
1036 case SVGA3D_UYVY:
1037 case SVGA3D_YUY2:
1038 case SVGA3D_NV12:
1039 case SVGA3D_AYUV:
1040 case SVGA3D_BC4_UNORM:
1041 case SVGA3D_BC5_UNORM:
1042 case SVGA3D_Z_DF16:
1043 case SVGA3D_Z_DF24:
1044 case SVGA3D_Z_D24S8_INT:
1045 if (!fHitFormatAssert)
1046 {
1047 AssertMsgFailed(("%s is not implemented\n", vmsvgaLookupEnum((int)enmFormat, &g_SVGA3dSurfaceFormat2String)));
1048 fHitFormatAssert = true;
1049 }
1050 RT_FALL_THRU();
1051 default:
1052 /* Lazy programmer fallbacks. */
1053 if (cbSrcPixel == 4)
1054 CONVERT_SCANLINE(uint32_t const u32Tmp = uSrc.pu32[xSrc],
1055 ( ( u32Tmp & 0xff)
1056 + ((u32Tmp >> 8) & 0xff)
1057 + ((u32Tmp >> 16) & 0xff)
1058 + ((u32Tmp >> 24) & 0xff) ) / 4);
1059 else if (cbSrcPixel == 3)
1060 CONVERT_SCANLINE(RT_NOTHING,
1061 ( (uint32_t)uSrc.pu8[xSrc * 4]
1062 + (uint32_t)uSrc.pu8[xSrc * 4 + 1]
1063 + (uint32_t)uSrc.pu8[xSrc * 4 + 2] ) / 3);
1064 else if (cbSrcPixel == 2)
1065 CONVERT_SCANLINE(uint16_t const u16Tmp = uSrc.pu16[xSrc],
1066 ( ( u16Tmp & 0xf)
1067 + ((u16Tmp >> 4) & 0xf)
1068 + ((u16Tmp >> 8) & 0xf)
1069 + ((u16Tmp >> 12) & 0xf) ) * 4 /* mul 16 div 4 */ );
1070 else if (cbSrcPixel == 1)
1071 CONVERT_SCANLINE(RT_NOTHING, uSrc.pu8[xSrc]);
1072 else
1073 AssertFailed();
1074 break;
1075
1076 }
1077
1078 /*
1079 * Print we've reached the end of a block in y direction or if we're at
1080 * the end of the image.
1081 */
1082 cyLeft--;
1083 if (--cyLeftInScanline == 0 || cyLeft == 0)
1084 {
1085 for (uint32_t i = 0; i < cchLine; i++)
1086 {
1087 uint32_t off = pauScanline[i] * s_cchPalette / cPixelsWeightPerChar; Assert(off < s_cchPalette);
1088 pszLine[i] = s_szPalette[off < sizeof(s_szPalette) - 1 ? off : sizeof(s_szPalette) - 1];
1089 }
1090 pszLine[cchLine] = '\0';
1091 pfnPrintLine(pszLine, pvUser);
1092
1093 if (!cyLeft)
1094 break;
1095 cyLeftInScanline = cyPerChar;
1096 RT_BZERO(pauScanline, sizeof(pauScanline[0]) * cchLine);
1097 }
1098
1099 /*
1100 * Advance.
1101 */
1102 if (!fInvY)
1103 uSrc.pu8 += cbScanline;
1104 else
1105 uSrc.pu8 -= cbScanline;
1106 }
1107}
1108
1109
1110
1111/**
1112 * Formats a SVGA3dRenderState structure as a string.
1113 *
1114 * @returns pszBuffer.
1115 * @param pszBuffer Output string buffer.
1116 * @param cbBuffer Size of output buffer.
1117 * @param pRenderState The SVGA3d render state to format.
1118 */
1119char *vmsvga3dFormatRenderState(char *pszBuffer, size_t cbBuffer, SVGA3dRenderState const *pRenderState)
1120{
1121 /*
1122 * List of render state names with type prefix.
1123 *
1124 * First char in the name is a type indicator:
1125 * - '*' = requires special handling.
1126 * - 'f' = SVGA3dbool
1127 * - 'd' = uint32_t
1128 * - 'r' = float
1129 * - 'b' = SVGA3dBlendOp
1130 * - 'c' = SVGA3dColor, SVGA3dColorMask
1131 * - 'e' = SVGA3dBlendEquation
1132 * - 'm' = SVGA3dColorMask
1133 * - 'p' = SVGA3dCmpFunc
1134 * - 's' = SVGA3dStencilOp
1135 * - 'v' = SVGA3dVertexMaterial
1136 * - 'w' = SVGA3dWrapFlags
1137 */
1138 static const char * const s_apszRenderStateNamesAndType[] =
1139 {
1140 "*" "INVALID", /* invalid */
1141 "f" "ZENABLE", /* SVGA3dBool */
1142 "f" "ZWRITEENABLE", /* SVGA3dBool */
1143 "f" "ALPHATESTENABLE", /* SVGA3dBool */
1144 "f" "DITHERENABLE", /* SVGA3dBool */
1145 "f" "BLENDENABLE", /* SVGA3dBool */
1146 "f" "FOGENABLE", /* SVGA3dBool */
1147 "f" "SPECULARENABLE", /* SVGA3dBool */
1148 "f" "STENCILENABLE", /* SVGA3dBool */
1149 "f" "LIGHTINGENABLE", /* SVGA3dBool */
1150 "f" "NORMALIZENORMALS", /* SVGA3dBool */
1151 "f" "POINTSPRITEENABLE", /* SVGA3dBool */
1152 "f" "POINTSCALEENABLE", /* SVGA3dBool */
1153 "x" "STENCILREF", /* uint32_t */
1154 "x" "STENCILMASK", /* uint32_t */
1155 "x" "STENCILWRITEMASK", /* uint32_t */
1156 "r" "FOGSTART", /* float */
1157 "r" "FOGEND", /* float */
1158 "r" "FOGDENSITY", /* float */
1159 "r" "POINTSIZE", /* float */
1160 "r" "POINTSIZEMIN", /* float */
1161 "r" "POINTSIZEMAX", /* float */
1162 "r" "POINTSCALE_A", /* float */
1163 "r" "POINTSCALE_B", /* float */
1164 "r" "POINTSCALE_C", /* float */
1165 "c" "FOGCOLOR", /* SVGA3dColor */
1166 "c" "AMBIENT", /* SVGA3dColor */
1167 "*" "CLIPPLANEENABLE", /* SVGA3dClipPlanes */
1168 "*" "FOGMODE", /* SVGA3dFogMode */
1169 "*" "FILLMODE", /* SVGA3dFillMode */
1170 "*" "SHADEMODE", /* SVGA3dShadeMode */
1171 "*" "LINEPATTERN", /* SVGA3dLinePattern */
1172 "b" "SRCBLEND", /* SVGA3dBlendOp */
1173 "b" "DSTBLEND", /* SVGA3dBlendOp */
1174 "e" "BLENDEQUATION", /* SVGA3dBlendEquation */
1175 "*" "CULLMODE", /* SVGA3dFace */
1176 "p" "ZFUNC", /* SVGA3dCmpFunc */
1177 "p" "ALPHAFUNC", /* SVGA3dCmpFunc */
1178 "p" "STENCILFUNC", /* SVGA3dCmpFunc */
1179 "s" "STENCILFAIL", /* SVGA3dStencilOp */
1180 "s" "STENCILZFAIL", /* SVGA3dStencilOp */
1181 "s" "STENCILPASS", /* SVGA3dStencilOp */
1182 "r" "ALPHAREF", /* float */
1183 "*" "FRONTWINDING", /* SVGA3dFrontWinding */
1184 "*" "COORDINATETYPE", /* SVGA3dCoordinateType */
1185 "r" "ZBIAS", /* float */
1186 "f" "RANGEFOGENABLE", /* SVGA3dBool */
1187 "c" "COLORWRITEENABLE", /* SVGA3dColorMask */
1188 "f" "VERTEXMATERIALENABLE", /* SVGA3dBool */
1189 "v" "DIFFUSEMATERIALSOURCE", /* SVGA3dVertexMaterial */
1190 "v" "SPECULARMATERIALSOURCE", /* SVGA3dVertexMaterial */
1191 "v" "AMBIENTMATERIALSOURCE", /* SVGA3dVertexMaterial */
1192 "v" "EMISSIVEMATERIALSOURCE", /* SVGA3dVertexMaterial */
1193 "c" "TEXTUREFACTOR", /* SVGA3dColor */
1194 "f" "LOCALVIEWER", /* SVGA3dBool */
1195 "f" "SCISSORTESTENABLE", /* SVGA3dBool */
1196 "c" "BLENDCOLOR", /* SVGA3dColor */
1197 "f" "STENCILENABLE2SIDED", /* SVGA3dBool */
1198 "p" "CCWSTENCILFUNC", /* SVGA3dCmpFunc */
1199 "s" "CCWSTENCILFAIL", /* SVGA3dStencilOp */
1200 "s" "CCWSTENCILZFAIL", /* SVGA3dStencilOp */
1201 "s" "CCWSTENCILPASS", /* SVGA3dStencilOp */
1202 "*" "VERTEXBLEND", /* SVGA3dVertexBlendFlags */
1203 "r" "SLOPESCALEDEPTHBIAS", /* float */
1204 "r" "DEPTHBIAS", /* float */
1205 "r" "OUTPUTGAMMA", /* float */
1206 "f" "ZVISIBLE", /* SVGA3dBool */
1207 "f" "LASTPIXEL", /* SVGA3dBool */
1208 "f" "CLIPPING", /* SVGA3dBool */
1209 "w" "WRAP0", /* SVGA3dWrapFlags */
1210 "w" "WRAP1", /* SVGA3dWrapFlags */
1211 "w" "WRAP2", /* SVGA3dWrapFlags */
1212 "w" "WRAP3", /* SVGA3dWrapFlags */
1213 "w" "WRAP4", /* SVGA3dWrapFlags */
1214 "w" "WRAP5", /* SVGA3dWrapFlags */
1215 "w" "WRAP6", /* SVGA3dWrapFlags */
1216 "w" "WRAP7", /* SVGA3dWrapFlags */
1217 "w" "WRAP8", /* SVGA3dWrapFlags */
1218 "w" "WRAP9", /* SVGA3dWrapFlags */
1219 "w" "WRAP10", /* SVGA3dWrapFlags */
1220 "w" "WRAP11", /* SVGA3dWrapFlags */
1221 "w" "WRAP12", /* SVGA3dWrapFlags */
1222 "w" "WRAP13", /* SVGA3dWrapFlags */
1223 "w" "WRAP14", /* SVGA3dWrapFlags */
1224 "w" "WRAP15", /* SVGA3dWrapFlags */
1225 "f" "MULTISAMPLEANTIALIAS", /* SVGA3dBool */
1226 "x" "MULTISAMPLEMASK", /* uint32_t */
1227 "f" "INDEXEDVERTEXBLENDENABLE", /* SVGA3dBool */
1228 "r" "TWEENFACTOR", /* float */
1229 "f" "ANTIALIASEDLINEENABLE", /* SVGA3dBool */
1230 "c" "COLORWRITEENABLE1", /* SVGA3dColorMask */
1231 "c" "COLORWRITEENABLE2", /* SVGA3dColorMask */
1232 "c" "COLORWRITEENABLE3", /* SVGA3dColorMask */
1233 "f" "SEPARATEALPHABLENDENABLE", /* SVGA3dBool */
1234 "b" "SRCBLENDALPHA", /* SVGA3dBlendOp */
1235 "b" "DSTBLENDALPHA", /* SVGA3dBlendOp */
1236 "e" "BLENDEQUATIONALPHA", /* SVGA3dBlendEquation */
1237 "*" "TRANSPARENCYANTIALIAS", /* SVGA3dTransparencyAntialiasType */
1238 "f" "LINEAA", /* SVGA3dBool */
1239 "r" "LINEWIDTH", /* float */
1240 };
1241
1242 uint32_t iState = pRenderState->state;
1243 if (iState != SVGA3D_RS_INVALID)
1244 {
1245 if (iState < RT_ELEMENTS(s_apszRenderStateNamesAndType))
1246 {
1247 const char *pszName = s_apszRenderStateNamesAndType[iState];
1248 char const chType = *pszName++;
1249
1250 union
1251 {
1252 uint32_t u;
1253 float r;
1254 SVGA3dColorMask Color;
1255 } uValue;
1256 uValue.u = pRenderState->uintValue;
1257
1258 switch (chType)
1259 {
1260 case 'f':
1261 if (uValue.u == 0)
1262 RTStrPrintf(pszBuffer, cbBuffer, "%s = false", pszName);
1263 else if (uValue.u == 1)
1264 RTStrPrintf(pszBuffer, cbBuffer, "%s = true", pszName);
1265 else
1266 RTStrPrintf(pszBuffer, cbBuffer, "%s = true (%#x)", pszName, uValue.u);
1267 break;
1268 case 'x':
1269 RTStrPrintf(pszBuffer, cbBuffer, "%s = %#x (%d)", pszName, uValue.u, uValue.u);
1270 break;
1271 case 'r':
1272 RTStrPrintf(pszBuffer, cbBuffer, "%s = %d.%06u (%#x)",
1273 pszName, (int)uValue.r, (unsigned)(uValue.r * 1000000) % 1000000U, uValue.u);
1274 break;
1275 case 'c': //SVGA3dColor, SVGA3dColorMask
1276 RTStrPrintf(pszBuffer, cbBuffer, "%s = RGBA(%d,%d,%d,%d) (%#x)", pszName,
1277 uValue.Color.s.red, uValue.Color.s.green, uValue.Color.s.blue, uValue.Color.s.alpha, uValue.u);
1278 break;
1279 case 'w': //SVGA3dWrapFlags
1280 RTStrPrintf(pszBuffer, cbBuffer, "%s = %#x%s", pszName, uValue.u,
1281 uValue.u <= SVGA3D_WRAPCOORD_ALL ? " (out of bounds" : "");
1282 break;
1283 default:
1284 AssertFailed(); RT_FALL_THRU();
1285 case 'b': //SVGA3dBlendOp
1286 case 'e': //SVGA3dBlendEquation
1287 case 'p': //SVGA3dCmpFunc
1288 case 's': //SVGA3dStencilOp
1289 case 'v': //SVGA3dVertexMaterial
1290 case '*':
1291 RTStrPrintf(pszBuffer, cbBuffer, "%s = %#x", pszName, uValue.u);
1292 break;
1293 }
1294 }
1295 else
1296 RTStrPrintf(pszBuffer, cbBuffer, "UNKNOWN_%d_%#x = %#x", iState, iState, pRenderState->uintValue);
1297 }
1298 else
1299 RTStrPrintf(pszBuffer, cbBuffer, "INVALID");
1300 return pszBuffer;
1301}
1302
1303
1304/**
1305 * Formats a SVGA3dTextureState structure as a string.
1306 *
1307 * @returns pszBuffer.
1308 * @param pszBuffer Output string buffer.
1309 * @param cbBuffer Size of output buffer.
1310 * @param pTextureState The SVGA3d texture state to format.
1311 */
1312char *vmsvga3dFormatTextureState(char *pszBuffer, size_t cbBuffer, SVGA3dTextureState const *pTextureState)
1313{
1314 static const char * const s_apszTextureStateNamesAndType[] =
1315 {
1316 "*" "INVALID", /* invalid */
1317 "x" "BIND_TEXTURE", /* SVGA3dSurfaceId */
1318 "m" "COLOROP", /* SVGA3dTextureCombiner */
1319 "a" "COLORARG1", /* SVGA3dTextureArgData */
1320 "a" "COLORARG2", /* SVGA3dTextureArgData */
1321 "m" "ALPHAOP", /* SVGA3dTextureCombiner */
1322 "a" "ALPHAARG1", /* SVGA3dTextureArgData */
1323 "a" "ALPHAARG2", /* SVGA3dTextureArgData */
1324 "e" "ADDRESSU", /* SVGA3dTextureAddress */
1325 "e" "ADDRESSV", /* SVGA3dTextureAddress */
1326 "l" "MIPFILTER", /* SVGA3dTextureFilter */
1327 "l" "MAGFILTER", /* SVGA3dTextureFilter */
1328 "m" "MINFILTER", /* SVGA3dTextureFilter */
1329 "c" "BORDERCOLOR", /* SVGA3dColor */
1330 "r" "TEXCOORDINDEX", /* uint32_t */
1331 "t" "TEXTURETRANSFORMFLAGS", /* SVGA3dTexTransformFlags */
1332 "g" "TEXCOORDGEN", /* SVGA3dTextureCoordGen */
1333 "r" "BUMPENVMAT00", /* float */
1334 "r" "BUMPENVMAT01", /* float */
1335 "r" "BUMPENVMAT10", /* float */
1336 "r" "BUMPENVMAT11", /* float */
1337 "x" "TEXTURE_MIPMAP_LEVEL", /* uint32_t */
1338 "r" "TEXTURE_LOD_BIAS", /* float */
1339 "x" "TEXTURE_ANISOTROPIC_LEVEL", /* uint32_t */
1340 "e" "ADDRESSW", /* SVGA3dTextureAddress */
1341 "r" "GAMMA", /* float */
1342 "r" "BUMPENVLSCALE", /* float */
1343 "r" "BUMPENVLOFFSET", /* float */
1344 "a" "COLORARG0", /* SVGA3dTextureArgData */
1345 "a" "ALPHAARG0" /* SVGA3dTextureArgData */
1346 };
1347
1348 /*
1349 * Format the stage first.
1350 */
1351 char *pszRet = pszBuffer;
1352 size_t cchPrefix = RTStrPrintf(pszBuffer, cbBuffer, "[%u] ", pTextureState->stage);
1353 if (cchPrefix < cbBuffer)
1354 {
1355 cbBuffer -= cchPrefix;
1356 pszBuffer += cchPrefix;
1357 }
1358 else
1359 cbBuffer = 0;
1360
1361 /*
1362 * Format the name and value.
1363 */
1364 uint32_t iName = pTextureState->name;
1365 if (iName != SVGA3D_TS_INVALID)
1366 {
1367 if (iName < RT_ELEMENTS(s_apszTextureStateNamesAndType))
1368 {
1369 const char *pszName = s_apszTextureStateNamesAndType[iName];
1370 char chType = *pszName++;
1371
1372 union
1373 {
1374 uint32_t u;
1375 float r;
1376 SVGA3dColorMask Color;
1377 } uValue;
1378 uValue.u = pTextureState->value;
1379
1380 switch (chType)
1381 {
1382 case 'x':
1383 RTStrPrintf(pszBuffer, cbBuffer, "%s = %#x (%d)", pszName, uValue.u, uValue.u);
1384 break;
1385
1386 case 'r':
1387 RTStrPrintf(pszBuffer, cbBuffer, "%s = %d.%06u (%#x)",
1388 pszName, (int)uValue.r, (unsigned)(uValue.r * 1000000) % 1000000U, uValue.u);
1389 break;
1390
1391 case 'a': //SVGA3dTextureArgData
1392 {
1393 static const char * const s_apszValues[] =
1394 {
1395 "INVALID", "CONSTANT", "PREVIOUS", "DIFFUSE", "TEXTURE", "SPECULAR"
1396 };
1397 vmsvgaFormatEnumValue(pszBuffer, cbBuffer, pszName, uValue.u,
1398 "SVGA3D_TA_", s_apszValues, RT_ELEMENTS(s_apszValues));
1399 break;
1400 }
1401
1402 case 'c': //SVGA3dColor, SVGA3dColorMask
1403 RTStrPrintf(pszBuffer, cbBuffer, "%s = RGBA(%d,%d,%d,%d) (%#x)", pszName,
1404 uValue.Color.s.red, uValue.Color.s.green, uValue.Color.s.blue, uValue.Color.s.alpha, uValue.u);
1405 break;
1406
1407 case 'e': //SVGA3dTextureAddress
1408 {
1409 static const char * const s_apszValues[] =
1410 {
1411 "INVALID", "WRAP", "MIRROR", "CLAMP", "BORDER", "MIRRORONCE", "EDGE",
1412 };
1413 vmsvgaFormatEnumValue(pszBuffer, cbBuffer, pszName, uValue.u,
1414 "SVGA3D_TEX_ADDRESS_", s_apszValues, RT_ELEMENTS(s_apszValues));
1415 break;
1416 }
1417
1418 case 'l': //SVGA3dTextureFilter
1419 {
1420 static const char * const s_apszValues[] =
1421 {
1422 "NONE", "NEAREST", "LINEAR", "ANISOTROPIC", "FLATCUBIC", "GAUSSIANCUBIC", "PYRAMIDALQUAD", "GAUSSIANQUAD",
1423 };
1424 vmsvgaFormatEnumValue(pszBuffer, cbBuffer, pszName, uValue.u,
1425 "SVGA3D_TEX_FILTER_", s_apszValues, RT_ELEMENTS(s_apszValues));
1426 break;
1427 }
1428
1429 case 'g': //SVGA3dTextureCoordGen
1430 {
1431 static const char * const s_apszValues[] =
1432 {
1433 "OFF", "EYE_POSITION", "EYE_NORMAL", "REFLECTIONVECTOR", "SPHERE",
1434 };
1435 vmsvgaFormatEnumValue(pszBuffer, cbBuffer, pszName, uValue.u,
1436 "SVGA3D_TEXCOORD_GEN_", s_apszValues, RT_ELEMENTS(s_apszValues));
1437 break;
1438 }
1439
1440 case 'm': //SVGA3dTextureCombiner
1441 {
1442 static const char * const s_apszValues[] =
1443 {
1444 "INVALID", "DISABLE", "SELECTARG1", "SELECTARG2", "MODULATE", "ADD", "ADDSIGNED", "SUBTRACT",
1445 "BLENDTEXTUREALPHA", "BLENDDIFFUSEALPHA", "BLENDCURRENTALPHA", "BLENDFACTORALPHA", "MODULATE2X",
1446 "MODULATE4X", "DSDT", "DOTPRODUCT3", "BLENDTEXTUREALPHAPM", "ADDSIGNED2X", "ADDSMOOTH", "PREMODULATE",
1447 "MODULATEALPHA_ADDCOLOR", "MODULATECOLOR_ADDALPHA", "MODULATEINVALPHA_ADDCOLOR",
1448 "MODULATEINVCOLOR_ADDALPHA", "BUMPENVMAPLUMINANCE", "MULTIPLYADD", "LERP",
1449 };
1450 vmsvgaFormatEnumValue(pszBuffer, cbBuffer, pszName, uValue.u,
1451 "SVGA3D_TC_", s_apszValues, RT_ELEMENTS(s_apszValues));
1452 break;
1453 }
1454
1455 default:
1456 AssertFailed();
1457 RTStrPrintf(pszBuffer, cbBuffer, "%s = %#x\n", pszName, uValue.u);
1458 break;
1459 }
1460 }
1461 else
1462 RTStrPrintf(pszBuffer, cbBuffer, "UNKNOWN_%d_%#x = %#x\n", iName, iName, pTextureState->value);
1463 }
1464 else
1465 RTStrPrintf(pszBuffer, cbBuffer, "INVALID");
1466 return pszRet;
1467}
1468
1469
1470
1471static const char * const g_apszTransformTypes[] =
1472{
1473 "SVGA3D_TRANSFORM_INVALID",
1474 "SVGA3D_TRANSFORM_WORLD",
1475 "SVGA3D_TRANSFORM_VIEW",
1476 "SVGA3D_TRANSFORM_PROJECTION",
1477 "SVGA3D_TRANSFORM_TEXTURE0",
1478 "SVGA3D_TRANSFORM_TEXTURE1",
1479 "SVGA3D_TRANSFORM_TEXTURE2",
1480 "SVGA3D_TRANSFORM_TEXTURE3",
1481 "SVGA3D_TRANSFORM_TEXTURE4",
1482 "SVGA3D_TRANSFORM_TEXTURE5",
1483 "SVGA3D_TRANSFORM_TEXTURE6",
1484 "SVGA3D_TRANSFORM_TEXTURE7",
1485 "SVGA3D_TRANSFORM_WORLD1",
1486 "SVGA3D_TRANSFORM_WORLD2",
1487 "SVGA3D_TRANSFORM_WORLD3",
1488};
1489
1490static const char * const g_apszFaces[] =
1491{
1492 "SVGA3D_FACE_INVALID",
1493 "SVGA3D_FACE_NONE",
1494 "SVGA3D_FACE_FRONT",
1495 "SVGA3D_FACE_BACK",
1496 "SVGA3D_FACE_FRONT_BACK",
1497};
1498
1499static const char * const g_apszLightTypes[] =
1500{
1501 "SVGA3D_LIGHTTYPE_INVALID",
1502 "SVGA3D_LIGHTTYPE_POINT",
1503 "SVGA3D_LIGHTTYPE_SPOT1",
1504 "SVGA3D_LIGHTTYPE_SPOT2",
1505 "SVGA3D_LIGHTTYPE_DIRECTIONAL",
1506};
1507
1508static const char * const g_apszRenderTargets[] =
1509{
1510 "SVGA3D_RT_DEPTH",
1511 "SVGA3D_RT_STENCIL",
1512 "SVGA3D_RT_COLOR0",
1513 "SVGA3D_RT_COLOR1",
1514 "SVGA3D_RT_COLOR2",
1515 "SVGA3D_RT_COLOR3",
1516 "SVGA3D_RT_COLOR4",
1517 "SVGA3D_RT_COLOR5",
1518 "SVGA3D_RT_COLOR6",
1519 "SVGA3D_RT_COLOR7",
1520};
1521
1522static void vmsvga3dInfoContextWorkerOne(PCDBGFINFOHLP pHlp, PVMSVGA3DCONTEXT pContext, bool fVerbose)
1523{
1524 RT_NOREF(fVerbose);
1525 char szTmp[128];
1526
1527 pHlp->pfnPrintf(pHlp, "*** VMSVGA 3d context %#x (%d) ***\n", pContext->id, pContext->id);
1528#ifdef RT_OS_WINDOWS
1529 pHlp->pfnPrintf(pHlp, "hwnd: %p\n", pContext->hwnd);
1530 if (fVerbose)
1531 vmsvga3dInfoHostWindow(pHlp, (uintptr_t)pContext->hwnd);
1532# ifdef VMSVGA3D_DIRECT3D
1533 pHlp->pfnPrintf(pHlp, "pDevice: %p\n", pContext->pDevice);
1534# else
1535 pHlp->pfnPrintf(pHlp, "hdc: %p\n", pContext->hdc);
1536 pHlp->pfnPrintf(pHlp, "hglrc: %p\n", pContext->hglrc);
1537# endif
1538
1539#elif defined(RT_OS_DARWIN)
1540 pHlp->pfnPrintf(pHlp, "cocoaView: %p\n", pContext->cocoaView);
1541 if (pContext->cocoaView)
1542 vmsvga3dInfoHostWindow(pHlp, (uintptr_t)pContext->cocoaView);
1543 pHlp->pfnPrintf(pHlp, "cocoaContext: %p\n", pContext->cocoaContext);
1544 if (pContext->fOtherProfile)
1545 pHlp->pfnPrintf(pHlp, "fOtherProfile: true\n");
1546
1547#else
1548 pHlp->pfnPrintf(pHlp, "window: %p\n", pContext->window);
1549 if (pContext->window)
1550 vmsvga3dInfoHostWindow(pHlp, (uintptr_t)pContext->window);
1551 pHlp->pfnPrintf(pHlp, "glxContext: %p\n", pContext->glxContext);
1552
1553#endif
1554
1555 for (uint32_t i = 0; i < RT_ELEMENTS(pContext->aSidActiveTextures); i++)
1556 if (pContext->aSidActiveTextures[i] != SVGA3D_INVALID_ID)
1557 pHlp->pfnPrintf(pHlp, "aSidActiveTextures[%u]: %#x\n", i, pContext->aSidActiveTextures[i]);
1558
1559 pHlp->pfnPrintf(pHlp, "fUpdateFlags: %#x\n", pContext->state.u32UpdateFlags);
1560
1561 for (uint32_t i = 0; i < RT_ELEMENTS(pContext->state.aRenderState); i++)
1562 if (pContext->state.aRenderState[i].state != SVGA3D_RS_INVALID)
1563 pHlp->pfnPrintf(pHlp, "aRenderState[%3d]: %s\n", i,
1564 vmsvga3dFormatRenderState(szTmp, sizeof(szTmp), &pContext->state.aRenderState[i]));
1565
1566 for (uint32_t i = 0; i < RT_ELEMENTS(pContext->state.aTextureStates); i++)
1567 for (uint32_t j = 0; j < RT_ELEMENTS(pContext->state.aTextureStates[i]); j++)
1568 if (pContext->state.aTextureStates[i][j].name != SVGA3D_TS_INVALID)
1569 pHlp->pfnPrintf(pHlp, "aTextureStates[%3d][%3d]: %s\n", i, j,
1570 vmsvga3dFormatTextureState(szTmp, sizeof(szTmp), &pContext->state.aTextureStates[i][j]));
1571
1572 AssertCompile(RT_ELEMENTS(g_apszTransformTypes) == SVGA3D_TRANSFORM_MAX);
1573 for (uint32_t i = 0; i < RT_ELEMENTS(pContext->state.aTransformState); i++)
1574 if (pContext->state.aTransformState[i].fValid)
1575 {
1576 pHlp->pfnPrintf(pHlp, "aTransformState[%s(%u)]:\n", g_apszTransformTypes[i], i);
1577 for (uint32_t j = 0; j < RT_ELEMENTS(pContext->state.aTransformState[i].matrix); j++)
1578 pHlp->pfnPrintf(pHlp,
1579 (j % 4) == 0 ? " [ " FLOAT_FMT_STR : (j % 4) < 3 ? ", " FLOAT_FMT_STR : ", " FLOAT_FMT_STR "]\n",
1580 FLOAT_FMT_ARGS(pContext->state.aTransformState[i].matrix[j]));
1581 }
1582
1583 AssertCompile(RT_ELEMENTS(g_apszFaces) == SVGA3D_FACE_MAX);
1584 for (uint32_t i = 0; i < RT_ELEMENTS(pContext->state.aMaterial); i++)
1585 if (pContext->state.aMaterial[i].fValid)
1586 {
1587 pHlp->pfnPrintf(pHlp, "aTransformState[%s(%u)]: shininess=" FLOAT_FMT_STR "\n",
1588 g_apszFaces[i], i, FLOAT_FMT_ARGS(pContext->state.aMaterial[i].material.shininess));
1589 pHlp->pfnPrintf(pHlp, " diffuse =[ " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR " ]\n",
1590 FLOAT_FMT_ARGS(pContext->state.aMaterial[i].material.diffuse[0]),
1591 FLOAT_FMT_ARGS(pContext->state.aMaterial[i].material.diffuse[1]),
1592 FLOAT_FMT_ARGS(pContext->state.aMaterial[i].material.diffuse[2]),
1593 FLOAT_FMT_ARGS(pContext->state.aMaterial[i].material.diffuse[3]));
1594 pHlp->pfnPrintf(pHlp, " ambient =[ " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR " ]\n",
1595 FLOAT_FMT_ARGS(pContext->state.aMaterial[i].material.ambient[0]),
1596 FLOAT_FMT_ARGS(pContext->state.aMaterial[i].material.ambient[1]),
1597 FLOAT_FMT_ARGS(pContext->state.aMaterial[i].material.ambient[2]),
1598 FLOAT_FMT_ARGS(pContext->state.aMaterial[i].material.ambient[3]));
1599 pHlp->pfnPrintf(pHlp, " specular=[ " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR " ]\n",
1600 FLOAT_FMT_ARGS(pContext->state.aMaterial[i].material.specular[0]),
1601 FLOAT_FMT_ARGS(pContext->state.aMaterial[i].material.specular[1]),
1602 FLOAT_FMT_ARGS(pContext->state.aMaterial[i].material.specular[2]),
1603 FLOAT_FMT_ARGS(pContext->state.aMaterial[i].material.specular[3]));
1604 pHlp->pfnPrintf(pHlp, " emissive=[ " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR " ]\n",
1605 FLOAT_FMT_ARGS(pContext->state.aMaterial[i].material.emissive[0]),
1606 FLOAT_FMT_ARGS(pContext->state.aMaterial[i].material.emissive[1]),
1607 FLOAT_FMT_ARGS(pContext->state.aMaterial[i].material.emissive[2]),
1608 FLOAT_FMT_ARGS(pContext->state.aMaterial[i].material.emissive[3]));
1609 }
1610
1611 for (uint32_t i = 0; i < RT_ELEMENTS(pContext->state.aClipPlane); i++)
1612 if (pContext->state.aClipPlane[i].fValid)
1613 pHlp->pfnPrintf(pHlp, "aClipPlane[%#04x]: [ " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR " ]\n",
1614 i,
1615 FLOAT_FMT_ARGS(pContext->state.aClipPlane[i].plane[0]),
1616 FLOAT_FMT_ARGS(pContext->state.aClipPlane[i].plane[1]),
1617 FLOAT_FMT_ARGS(pContext->state.aClipPlane[i].plane[2]),
1618 FLOAT_FMT_ARGS(pContext->state.aClipPlane[i].plane[3]));
1619
1620 for (uint32_t i = 0; i < RT_ELEMENTS(pContext->state.aLightData); i++)
1621 if (pContext->state.aLightData[i].fValidData)
1622 {
1623 pHlp->pfnPrintf(pHlp, "aLightData[%#04x]: enabled=%RTbool inWorldSpace=%RTbool type=%s(%u)\n",
1624 i,
1625 pContext->state.aLightData[i].fEnabled,
1626 pContext->state.aLightData[i].data.inWorldSpace,
1627 (uint32_t)pContext->state.aLightData[i].data.type < RT_ELEMENTS(g_apszLightTypes)
1628 ? g_apszLightTypes[pContext->state.aLightData[i].data.type] : "UNKNOWN",
1629 pContext->state.aLightData[i].data.type);
1630 pHlp->pfnPrintf(pHlp, " diffuse =[ " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR " ]\n",
1631 FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.diffuse[0]),
1632 FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.diffuse[1]),
1633 FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.diffuse[2]),
1634 FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.diffuse[3]));
1635 pHlp->pfnPrintf(pHlp, " specular =[ " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR " ]\n",
1636 FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.specular[0]),
1637 FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.specular[1]),
1638 FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.specular[2]),
1639 FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.specular[3]));
1640 pHlp->pfnPrintf(pHlp, " ambient =[ " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR " ]\n",
1641 FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.ambient[0]),
1642 FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.ambient[1]),
1643 FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.ambient[2]),
1644 FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.ambient[3]));
1645 pHlp->pfnPrintf(pHlp, " position =[ " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR " ]\n",
1646 FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.position[0]),
1647 FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.position[1]),
1648 FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.position[2]),
1649 FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.position[3]));
1650 pHlp->pfnPrintf(pHlp, " direction=[ " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR " ]\n",
1651 FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.direction[0]),
1652 FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.direction[1]),
1653 FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.direction[2]),
1654 FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.direction[3]));
1655 pHlp->pfnPrintf(pHlp, " range=" FLOAT_FMT_STR " falloff=" FLOAT_FMT_STR "\n",
1656 FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.range),
1657 FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.falloff));
1658 pHlp->pfnPrintf(pHlp, " attenuation0=" FLOAT_FMT_STR " attenuation1=" FLOAT_FMT_STR " attenuation2=" FLOAT_FMT_STR "\n",
1659 FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.attenuation0),
1660 FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.attenuation1),
1661 FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.attenuation2));
1662 pHlp->pfnPrintf(pHlp, " theta=" FLOAT_FMT_STR " phi=" FLOAT_FMT_STR "\n",
1663 FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.theta),
1664 FLOAT_FMT_ARGS(pContext->state.aLightData[i].data.phi));
1665 }
1666
1667 for (uint32_t i = 0; i < RT_ELEMENTS(pContext->state.aRenderTargets); i++)
1668 if (pContext->state.aRenderTargets[i] != SVGA3D_INVALID_ID)
1669 pHlp->pfnPrintf(pHlp, "aRenderTargets[%s/%u] = %#x (%d)\n",
1670 i < RT_ELEMENTS(g_apszRenderTargets) ? g_apszRenderTargets[i] : "UNKNOWN", i,
1671 pContext->state.aRenderTargets[i], pContext->state.aRenderTargets[i]);
1672
1673 pHlp->pfnPrintf(pHlp, "RectScissor: (x,y,cx,cy)=(%u,%u,%u,%u)\n",
1674 pContext->state.RectViewPort.x, pContext->state.RectViewPort.y,
1675 pContext->state.RectViewPort.w, pContext->state.RectViewPort.h);
1676 pHlp->pfnPrintf(pHlp, "zRange: (min,max)=(" FLOAT_FMT_STR ", " FLOAT_FMT_STR ")\n",
1677 FLOAT_FMT_ARGS(pContext->state.zRange.min),
1678 FLOAT_FMT_ARGS(pContext->state.zRange.max));
1679 pHlp->pfnPrintf(pHlp, "fUpdateFlags: %#x\n", pContext->state.u32UpdateFlags);
1680 pHlp->pfnPrintf(pHlp, "shidPixel: %#x (%d)\n", pContext->state.shidPixel, pContext->state.shidPixel);
1681 pHlp->pfnPrintf(pHlp, "shidVertex: %#x (%d)\n", pContext->state.shidVertex, pContext->state.shidVertex);
1682
1683 for (uint32_t iWhich = 0; iWhich < 2; iWhich++)
1684 {
1685 uint32_t cConsts = iWhich == 0 ? pContext->state.cPixelShaderConst : pContext->state.cVertexShaderConst;
1686 PVMSVGASHADERCONST paConsts = iWhich == 0 ? pContext->state.paPixelShaderConst : pContext->state.paVertexShaderConst;
1687 const char *pszName = iWhich ? "paPixelShaderConst" : "paVertexShaderConst";
1688
1689 for (uint32_t i = 0; i < cConsts; i++)
1690 if (paConsts[i].fValid)
1691 {
1692 if (paConsts[i].ctype == SVGA3D_CONST_TYPE_FLOAT)
1693 pHlp->pfnPrintf(pHlp, "%s[%#x(%u)] = [" FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR ", " FLOAT_FMT_STR "] ctype=FLOAT\n",
1694 pszName, i, i,
1695 FLOAT_FMT_ARGS(*(float *)&paConsts[i].value[0]), FLOAT_FMT_ARGS(*(float *)&paConsts[i].value[1]),
1696 FLOAT_FMT_ARGS(*(float *)&paConsts[i].value[2]), FLOAT_FMT_ARGS(*(float *)&paConsts[i].value[3]));
1697 else
1698 pHlp->pfnPrintf(pHlp, "%s[%#x(%u)] = [%#x, %#x, %#x, %#x] ctype=%s\n",
1699 pszName, i, i,
1700 paConsts[i].value[0], paConsts[i].value[1],
1701 paConsts[i].value[2], paConsts[i].value[3],
1702 paConsts[i].ctype == SVGA3D_CONST_TYPE_INT ? "INT"
1703 : paConsts[i].ctype == SVGA3D_CONST_TYPE_BOOL ? "BOOL" : "UNKNOWN");
1704 }
1705 }
1706
1707 for (uint32_t iWhich = 0; iWhich < 2; iWhich++)
1708 {
1709 uint32_t cShaders = iWhich == 0 ? pContext->cPixelShaders : pContext->cVertexShaders;
1710 PVMSVGA3DSHADER paShaders = iWhich == 0 ? pContext->paPixelShader : pContext->paVertexShader;
1711 const char *pszName = iWhich == 0 ? "paPixelShaders" : "paVertexShaders";
1712 for (uint32_t i = 0; i < cShaders; i++)
1713 if (paShaders[i].id == i)
1714 {
1715 pHlp->pfnPrintf(pHlp, "%s[%u]: id=%#x cid=%#x type=%s(%d) cbData=%#x pvData=%p\n",
1716 pszName, i,
1717 paShaders[i].id,
1718 paShaders[i].cid,
1719 paShaders[i].type == SVGA3D_SHADERTYPE_VS ? "VS"
1720 : paShaders[i].type == SVGA3D_SHADERTYPE_PS ? "PS" : "UNKNOWN",
1721 paShaders[i].type,
1722 paShaders[i].cbData,
1723 paShaders[i].pShaderProgram);
1724 }
1725 }
1726}
1727
1728
1729void vmsvga3dInfoContextWorker(PVGASTATE pThis, PCDBGFINFOHLP pHlp, uint32_t cid, bool fVerbose)
1730{
1731 /* Warning! This code is currently racing papContexts reallocation! */
1732 /* Warning! This code is currently racing papContexts reallocation! */
1733 /* Warning! This code is currently racing papContexts reallocation! */
1734 VMSVGA3DSTATE volatile *pState = pThis->svga.p3dState;
1735 if (pState)
1736 {
1737 /*
1738 * Deal with a specific request first.
1739 */
1740 if (cid != UINT32_MAX)
1741 {
1742 if (cid < pState->cContexts)
1743 {
1744 PVMSVGA3DCONTEXT pContext = pState->papContexts[cid];
1745 if (pContext && pContext->id == cid)
1746 {
1747 vmsvga3dInfoContextWorkerOne(pHlp, pContext, fVerbose);
1748 return;
1749 }
1750 }
1751#ifdef VMSVGA3D_OPENGL
1752 else if ( cid == VMSVGA3D_SHARED_CTX_ID
1753 && pState->SharedCtx.id == cid)
1754 {
1755 vmsvga3dInfoContextWorkerOne(pHlp, &((PVMSVGA3DSTATE)pState)->SharedCtx, fVerbose);
1756 return;
1757 }
1758#endif
1759 pHlp->pfnPrintf(pHlp, "Context ID %#x not found.\n", cid);
1760 }
1761 else
1762 {
1763#ifdef VMSVGA3D_OPENGL
1764 /*
1765 * Dump the shared context.
1766 */
1767 if (pState->SharedCtx.id == VMSVGA3D_SHARED_CTX_ID)
1768 {
1769 pHlp->pfnPrintf(pHlp, "Shared context:\n");
1770 vmsvga3dInfoContextWorkerOne(pHlp, &((PVMSVGA3DSTATE)pState)->SharedCtx, fVerbose);
1771 }
1772#endif
1773
1774 /*
1775 * Dump the per-screen contexts.
1776 */
1777 /** @todo multi screen */
1778
1779 /*
1780 * Dump all.
1781 */
1782 uint32_t cContexts = pState->cContexts;
1783 pHlp->pfnPrintf(pHlp, "cContexts=%d\n", cContexts);
1784 for (cid = 0; cid < cContexts; cid++)
1785 {
1786 PVMSVGA3DCONTEXT pContext = pState->papContexts[cid];
1787 if (pContext && pContext->id == cid)
1788 {
1789 pHlp->pfnPrintf(pHlp, "\n");
1790 vmsvga3dInfoContextWorkerOne(pHlp, pContext, fVerbose);
1791 }
1792 }
1793 }
1794 }
1795}
1796
1797
1798#ifdef VMSVGA3D_DIRECT3D
1799/**
1800 * Release all shared surface objects.
1801 */
1802static DECLCALLBACK(int) vmsvga3dInfoSharedObjectCallback(PAVLU32NODECORE pNode, void *pvUser)
1803{
1804 PVMSVGA3DSHAREDSURFACE pSharedSurface = (PVMSVGA3DSHAREDSURFACE)pNode;
1805 PCDBGFINFOHLP pHlp = (PCDBGFINFOHLP)pvUser;
1806
1807 pHlp->pfnPrintf(pHlp, "Shared surface: %#x pv=%p\n", pSharedSurface->Core.Key, pSharedSurface->u.pCubeTexture);
1808
1809 return 0;
1810}
1811#endif /* VMSVGA3D_DIRECT3D */
1812
1813
1814static int vmsvga3dInfoBmpWrite(const char *pszFilename, const void *pvBits, int w, int h, uint32_t cbPixel, uint32_t u32Mask)
1815{
1816#ifdef RT_OS_WINDOWS
1817 if ( cbPixel != 4
1818 && cbPixel != 2
1819 && cbPixel != 1)
1820 return VERR_NOT_SUPPORTED;
1821
1822 /* Always write BGRX bitmap for now. */
1823 const int cbBitmap = w * h * 4;
1824
1825 FILE *f = fopen(pszFilename, "wb");
1826 if (!f)
1827 return VERR_FILE_NOT_FOUND;
1828
1829 if (cbPixel == 4)
1830 {
1831 BITMAPV4HEADER bh;
1832 RT_ZERO(bh);
1833 bh.bV4Size = sizeof(bh);
1834 bh.bV4Width = w;
1835 bh.bV4Height = -h;
1836 bh.bV4Planes = 1;
1837 bh.bV4BitCount = 32;
1838 bh.bV4V4Compression = BI_BITFIELDS;
1839 bh.bV4SizeImage = cbBitmap;
1840 bh.bV4XPelsPerMeter = 2835;
1841 bh.bV4YPelsPerMeter = 2835;
1842 // bh.bV4ClrUsed = 0;
1843 // bh.bV4ClrImportant = 0;
1844 bh.bV4RedMask = 0x00ff0000;
1845 bh.bV4GreenMask = 0x0000ff00;
1846 bh.bV4BlueMask = 0x000000ff;
1847 bh.bV4AlphaMask = 0xff000000;
1848 bh.bV4CSType = LCS_WINDOWS_COLOR_SPACE;
1849 // bh.bV4Endpoints = {0};
1850 // bh.bV4GammaRed = 0;
1851 // bh.bV4GammaGreen = 0;
1852 // bh.bV4GammaBlue = 0;
1853
1854 BITMAPFILEHEADER bf;
1855 bf.bfType = 'MB';
1856 bf.bfSize = sizeof(bf) + sizeof(bh) + cbBitmap;
1857 bf.bfReserved1 = 0;
1858 bf.bfReserved2 = 0;
1859 bf.bfOffBits = sizeof(bf) + sizeof(bh);
1860
1861 fwrite(&bf, 1, sizeof(bf), f);
1862 fwrite(&bh, 1, sizeof(bh), f);
1863 }
1864 else
1865 {
1866 BITMAPFILEHEADER bf;
1867 bf.bfType = 'MB';
1868 bf.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + cbBitmap;
1869 bf.bfReserved1 = 0;
1870 bf.bfReserved2 = 0;
1871 bf.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
1872
1873 BITMAPINFOHEADER bi;
1874 bi.biSize = sizeof(bi);
1875 bi.biWidth = w;
1876 bi.biHeight = -h;
1877 bi.biPlanes = 1;
1878 bi.biBitCount = 32;
1879 bi.biCompression = 0;
1880 bi.biSizeImage = cbBitmap;
1881 bi.biXPelsPerMeter = 0;
1882 bi.biYPelsPerMeter = 0;
1883 bi.biClrUsed = 0;
1884 bi.biClrImportant = 0;
1885
1886 fwrite(&bf, 1, sizeof(bf), f);
1887 fwrite(&bi, 1, sizeof(bi), f);
1888 }
1889
1890 if (cbPixel == 4)
1891 {
1892 const uint32_t *s = (uint32_t *)pvBits;
1893 int i;
1894 for (i = 0; i < w * h; ++i)
1895 {
1896 const uint32_t u32 = *s++;
1897 uint32_t u = u32 & u32Mask;
1898 fwrite(&u, 1, 4, f);
1899 }
1900 }
1901 else if (cbPixel == 2)
1902 {
1903 const uint16_t *s = (uint16_t *)pvBits;
1904 int i;
1905 for (i = 0; i < w * h; ++i)
1906 {
1907 const uint16_t u16 = *s++;
1908 uint32_t u32 = u16;
1909 uint32_t u = u32 & u32Mask;
1910 fwrite(&u, 1, 4, f);
1911 }
1912 }
1913 else if (cbPixel == 1)
1914 {
1915 const uint8_t *s = (uint8_t *)pvBits;
1916 int i;
1917 for (i = 0; i < w * h; ++i)
1918 {
1919 const uint8_t u8 = *s++;
1920 uint32_t u32 = u8 * 0x10000 + u8 * 0x100 + u8;
1921 uint32_t u = u32 & u32Mask;
1922 fwrite(&u, 1, 4, f);
1923 }
1924 }
1925
1926 fclose(f);
1927
1928 return VINF_SUCCESS;
1929#else /* !RT_OS_WINDOWS */
1930 RT_NOREF6(pszFilename, pvBits, w, h, cbPixel, u32Mask);
1931 return VERR_NOT_SUPPORTED;
1932#endif
1933}
1934
1935void vmsvga3dInfoSurfaceToBitmap(PCDBGFINFOHLP pHlp, PVMSVGA3DSURFACE pSurface,
1936 const char *pszPath, const char *pszNamePrefix, const char *pszNameSuffix)
1937{
1938 static volatile uint32_t sSeq = 0;
1939
1940 if (!pSurface->pMipmapLevels[0].pSurfaceData)
1941 return;
1942
1943 const uint32_t u32Seq = ASMAtomicIncU32(&sSeq);
1944
1945 char szFilepath[4096];
1946 RTStrPrintf(szFilepath, sizeof(szFilepath),
1947 "%s\\%s-%u-sid%u%s.bmp",
1948 pszPath, pszNamePrefix, u32Seq, pSurface->id, pszNameSuffix);
1949
1950 const uint32_t cbPixel = vmsvga3dSurfaceFormatSize(pSurface->format, NULL, NULL);
1951 int rc = vmsvga3dInfoBmpWrite(szFilepath,
1952 pSurface->pMipmapLevels[0].pSurfaceData,
1953 pSurface->pMipmapLevels[0].mipmapSize.width,
1954 pSurface->pMipmapLevels[0].mipmapSize.height,
1955 cbPixel, 0xFFFFFFFF);
1956 if (RT_SUCCESS(rc))
1957 {
1958 Log(("Bitmap: %s\n", szFilepath));
1959 if (pHlp)
1960 pHlp->pfnPrintf(pHlp, "Bitmap: %s\n", szFilepath);
1961 }
1962 else
1963 {
1964 Log(("Bitmap: %s %Rrc\n", szFilepath, rc));
1965 if (pHlp)
1966 pHlp->pfnPrintf(pHlp, "Bitmap: %s %Rrc\n", szFilepath, rc);
1967 }
1968
1969#if 0
1970 /* Alpha channel alone. */
1971 RTStrPrintf(szFilepath, sizeof(szFilepath),
1972 "%s\\%s-%u-sid%u%s-a.bmp",
1973 pszPath, pszNamePrefix, u32Seq, pSurface->id, pszNameSuffix);
1974 vmsvga3dInfoBmpWrite(szFilepath,
1975 pSurface->pMipmapLevels[0].pSurfaceData,
1976 pSurface->pMipmapLevels[0].mipmapSize.width,
1977 pSurface->pMipmapLevels[0].mipmapSize.height,
1978 cbPixel, 0xFF000000);
1979#endif
1980}
1981
1982static void vmsvga3dInfoSurfaceWorkerOne(PCDBGFINFOHLP pHlp, PVMSVGA3DSURFACE pSurface,
1983 bool fVerbose, uint32_t cxAscii, bool fInvY)
1984{
1985 char szTmp[128];
1986
1987 pHlp->pfnPrintf(pHlp, "*** VMSVGA 3d surface %#x (%d)%s ***\n", pSurface->id, pSurface->id, pSurface->fDirty ? " - dirty" : "");
1988#ifdef VMSVGA3D_OPENGL
1989 pHlp->pfnPrintf(pHlp, "idWeakContextAssociation: %#x\n", pSurface->idWeakContextAssociation);
1990#else
1991 pHlp->pfnPrintf(pHlp, "idAssociatedContext: %#x\n", pSurface->idAssociatedContext);
1992#endif
1993 pHlp->pfnPrintf(pHlp, "Format: %s\n",
1994 vmsvgaFormatEnumValueEx(szTmp, sizeof(szTmp), NULL, (int)pSurface->format, false, &g_SVGA3dSurfaceFormat2String));
1995 pHlp->pfnPrintf(pHlp, "Flags: %#x", pSurface->surfaceFlags);
1996 vmsvga3dInfoU32Flags(pHlp, pSurface->surfaceFlags, "SVGA3D_SURFACE_", g_aSvga3DSurfaceFlags, RT_ELEMENTS(g_aSvga3DSurfaceFlags));
1997 pHlp->pfnPrintf(pHlp, "\n");
1998 if (pSurface->cFaces == 0)
1999 pHlp->pfnPrintf(pHlp, "Faces: %u\n", pSurface->cFaces);
2000 for (uint32_t iFace = 0; iFace < pSurface->cFaces; iFace++)
2001 {
2002 Assert(pSurface->faces[iFace].numMipLevels <= pSurface->faces[0].numMipLevels);
2003 if (pSurface->faces[iFace].numMipLevels == 0)
2004 pHlp->pfnPrintf(pHlp, "Faces[%u] Mipmap levels: %u\n", iFace, pSurface->faces[iFace].numMipLevels);
2005
2006 uint32_t iMipmap = iFace * pSurface->faces[0].numMipLevels;
2007 for (uint32_t iLevel = 0; iLevel < pSurface->faces[iFace].numMipLevels; iLevel++, iMipmap++)
2008 {
2009 pHlp->pfnPrintf(pHlp, "Face #%u, mipmap #%u[%u]:%s cx=%u, cy=%u, cz=%u, cbSurface=%#x, cbPitch=%#x",
2010 iFace, iLevel, iMipmap, iMipmap < 10 ? " " : "",
2011 pSurface->pMipmapLevels[iMipmap].mipmapSize.width,
2012 pSurface->pMipmapLevels[iMipmap].mipmapSize.height,
2013 pSurface->pMipmapLevels[iMipmap].mipmapSize.depth,
2014 pSurface->pMipmapLevels[iMipmap].cbSurface,
2015 pSurface->pMipmapLevels[iMipmap].cbSurfacePitch);
2016 if (pSurface->pMipmapLevels[iMipmap].pSurfaceData)
2017 pHlp->pfnPrintf(pHlp, " pvData=%p", pSurface->pMipmapLevels[iMipmap].pSurfaceData);
2018 if (pSurface->pMipmapLevels[iMipmap].fDirty)
2019 pHlp->pfnPrintf(pHlp, " dirty");
2020 pHlp->pfnPrintf(pHlp, "\n");
2021 }
2022 }
2023
2024 pHlp->pfnPrintf(pHlp, "cbBlock: %u (%#x)\n", pSurface->cbBlock, pSurface->cbBlock);
2025 pHlp->pfnPrintf(pHlp, "Multi-sample count: %u\n", pSurface->multiSampleCount);
2026 pHlp->pfnPrintf(pHlp, "Autogen filter: %s\n",
2027 vmsvgaFormatEnumValue(szTmp, sizeof(szTmp), NULL, pSurface->autogenFilter,
2028 "SVGA3D_TEX_FILTER_", g_apszTexureFilters, RT_ELEMENTS(g_apszTexureFilters)));
2029
2030#ifdef VMSVGA3D_DIRECT3D
2031 pHlp->pfnPrintf(pHlp, "formatD3D: %s\n",
2032 vmsvgaFormatEnumValueEx(szTmp, sizeof(szTmp), NULL, pSurface->formatD3D, true, &g_D3DFormat2String));
2033 pHlp->pfnPrintf(pHlp, "fUsageD3D: %#x", pSurface->fUsageD3D);
2034 vmsvga3dInfoU32Flags(pHlp, pSurface->fUsageD3D, "D3DUSAGE_", g_aD3DUsageFlags, RT_ELEMENTS(g_aD3DUsageFlags));
2035 pHlp->pfnPrintf(pHlp, "\n");
2036 pHlp->pfnPrintf(pHlp, "multiSampleTypeD3D: %s\n",
2037 vmsvgaFormatEnumValueEx(szTmp, sizeof(szTmp), NULL, pSurface->multiSampleTypeD3D,
2038 true, &g_D3DMultiSampleType2String));
2039 if (pSurface->hSharedObject != NULL)
2040 pHlp->pfnPrintf(pHlp, "hSharedObject: %p\n", pSurface->hSharedObject);
2041 if (pSurface->pQuery)
2042 pHlp->pfnPrintf(pHlp, "pQuery: %p\n", pSurface->pQuery);
2043 if (pSurface->u.pSurface)
2044 pHlp->pfnPrintf(pHlp, "u.pXxxx: %p\n", pSurface->u.pSurface);
2045 if (pSurface->bounce.pTexture)
2046 pHlp->pfnPrintf(pHlp, "bounce.pXxxx: %p\n", pSurface->bounce.pTexture);
2047 RTAvlU32DoWithAll(&pSurface->pSharedObjectTree, true /*fFromLeft*/, vmsvga3dInfoSharedObjectCallback, (void *)pHlp);
2048 pHlp->pfnPrintf(pHlp, "fStencilAsTexture: %RTbool\n", pSurface->fStencilAsTexture);
2049
2050#elif defined(VMSVGA3D_OPENGL)
2051 /** @todo */
2052#else
2053# error "Build config error."
2054#endif
2055
2056 if (fVerbose)
2057 for (uint32_t iFace = 0; iFace < pSurface->cFaces; iFace++)
2058 {
2059 uint32_t iMipmap = iFace * pSurface->faces[0].numMipLevels;
2060 for (uint32_t iLevel = 0; iLevel < pSurface->faces[iFace].numMipLevels; iLevel++, iMipmap++)
2061 if (pSurface->pMipmapLevels[iMipmap].pSurfaceData)
2062 {
2063 if (ASMMemIsZero(pSurface->pMipmapLevels[iMipmap].pSurfaceData,
2064 pSurface->pMipmapLevels[iMipmap].cbSurface))
2065 pHlp->pfnPrintf(pHlp, "--- Face #%u, mipmap #%u[%u]: all zeros ---\n", iFace, iLevel, iMipmap);
2066 else
2067 {
2068 pHlp->pfnPrintf(pHlp, "--- Face #%u, mipmap #%u[%u]: cx=%u, cy=%u, cz=%u ---\n",
2069 iFace, iLevel, iMipmap,
2070 pSurface->pMipmapLevels[iMipmap].mipmapSize.width,
2071 pSurface->pMipmapLevels[iMipmap].mipmapSize.height,
2072 pSurface->pMipmapLevels[iMipmap].mipmapSize.depth);
2073 vmsvga3dAsciiPrint(vmsvga3dAsciiPrintlnInfo, (void *)pHlp,
2074 pSurface->pMipmapLevels[iMipmap].pSurfaceData,
2075 pSurface->pMipmapLevels[iMipmap].cbSurface,
2076 pSurface->pMipmapLevels[iMipmap].mipmapSize.width,
2077 pSurface->pMipmapLevels[iMipmap].mipmapSize.height,
2078 pSurface->pMipmapLevels[iMipmap].cbSurfacePitch,
2079 pSurface->format,
2080 fInvY,
2081 cxAscii, cxAscii * 3 / 4);
2082 }
2083 }
2084 }
2085}
2086
2087
2088void vmsvga3dInfoSurfaceWorker(PVGASTATE pThis, PCDBGFINFOHLP pHlp, uint32_t sid, bool fVerbose, uint32_t cxAscii, bool fInvY, const char *pszBitmapPath)
2089{
2090 /* Warning! This code is currently racing papSurfaces reallocation! */
2091 /* Warning! This code is currently racing papSurfaces reallocation! */
2092 /* Warning! This code is currently racing papSurfaces reallocation! */
2093 VMSVGA3DSTATE volatile *pState = pThis->svga.p3dState;
2094 if (pState)
2095 {
2096 /*
2097 * Deal with a specific request first.
2098 */
2099 if (sid != UINT32_MAX)
2100 {
2101 if (sid < pState->cSurfaces)
2102 {
2103 PVMSVGA3DSURFACE pSurface = pState->papSurfaces[sid];
2104 if (pSurface && pSurface->id == sid)
2105 {
2106 if (fVerbose)
2107 vmsvga3dSurfaceUpdateHeapBuffersOnFifoThread(pThis, sid);
2108 vmsvga3dInfoSurfaceWorkerOne(pHlp, pSurface, fVerbose, cxAscii, fInvY);
2109 if (pszBitmapPath && *pszBitmapPath)
2110 vmsvga3dInfoSurfaceToBitmap(pHlp, pSurface, pszBitmapPath, "info", "");
2111 return;
2112 }
2113 }
2114 pHlp->pfnPrintf(pHlp, "Surface ID %#x not found.\n", sid);
2115 }
2116 else
2117 {
2118 /*
2119 * Dump all.
2120 */
2121 if (fVerbose)
2122 vmsvga3dSurfaceUpdateHeapBuffersOnFifoThread(pThis, UINT32_MAX);
2123 uint32_t cSurfaces = pState->cSurfaces;
2124 pHlp->pfnPrintf(pHlp, "cSurfaces=%d\n", cSurfaces);
2125 for (sid = 0; sid < cSurfaces; sid++)
2126 {
2127 PVMSVGA3DSURFACE pSurface = pState->papSurfaces[sid];
2128 if (pSurface && pSurface->id == sid)
2129 {
2130 pHlp->pfnPrintf(pHlp, "\n");
2131 vmsvga3dInfoSurfaceWorkerOne(pHlp, pSurface, fVerbose, cxAscii, fInvY);
2132 }
2133 }
2134 }
2135 }
2136
2137}
2138
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