VirtualBox

source: vbox/trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-savedstate.cpp@ 94681

Last change on this file since 94681 was 94401, checked in by vboxsync, 3 years ago

Devices/Graphics: fixed loading a legacy saved state

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 54.1 KB
Line 
1/* $Id: DevVGA-SVGA3d-savedstate.cpp 94401 2022-03-30 17:40:28Z vboxsync $ */
2/** @file
3 * DevSVGA3d - VMWare SVGA device, 3D parts - Saved state and assocated stuff.
4 */
5
6/*
7 * Copyright (C) 2013-2022 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#define LOG_GROUP LOG_GROUP_DEV_VMSVGA
23#include <VBox/vmm/pdmdev.h>
24#include <iprt/errcore.h>
25#include <VBox/log.h>
26
27#include <iprt/assert.h>
28#include <iprt/mem.h>
29
30#include <VBox/vmm/pgm.h> /* required by DevVGA.h */
31#include <VBoxVideo.h> /* required by DevVGA.h */
32
33/* should go BEFORE any other DevVGA include to make all DevVGA.h config defines be visible */
34#include "DevVGA.h"
35
36#include "DevVGA-SVGA.h"
37#include "DevVGA-SVGA3d.h"
38#define VMSVGA3D_INCL_STRUCTURE_DESCRIPTORS
39#include "DevVGA-SVGA3d-internal.h"
40
41
42
43/**
44 * Reinitializes an active context.
45 *
46 * @returns VBox status code.
47 * @param pThisCC The VGA/VMSVGA state for ring-3.
48 * @param pContext The freshly loaded context to reinitialize.
49 */
50static int vmsvga3dLoadReinitContext(PVGASTATECC pThisCC, PVMSVGA3DCONTEXT pContext)
51{
52 int rc;
53 uint32_t cid = pContext->id;
54 Assert(cid != SVGA3D_INVALID_ID);
55
56 /* First set the render targets as they change the internal state (reset viewport etc) */
57 Log(("vmsvga3dLoadReinitContext: Recreate render targets BEGIN [cid=%#x]\n", cid));
58 for (uint32_t j = 0; j < RT_ELEMENTS(pContext->state.aRenderTargets); j++)
59 {
60 if (pContext->state.aRenderTargets[j] != SVGA3D_INVALID_ID)
61 {
62 SVGA3dSurfaceImageId target;
63
64 target.sid = pContext->state.aRenderTargets[j];
65 target.face = 0;
66 target.mipmap = 0;
67 rc = vmsvga3dSetRenderTarget(pThisCC, cid, (SVGA3dRenderTargetType)j, target);
68 AssertRCReturn(rc, rc);
69 }
70 }
71 Log(("vmsvga3dLoadReinitContext: Recreate render targets END\n"));
72
73 /* Recreate the render state */
74 Log(("vmsvga3dLoadReinitContext: Recreate render state BEGIN\n"));
75 for (uint32_t j = 0; j < RT_ELEMENTS(pContext->state.aRenderState); j++)
76 {
77 SVGA3dRenderState *pRenderState = &pContext->state.aRenderState[j];
78
79 if (pRenderState->state != SVGA3D_RS_INVALID)
80 vmsvga3dSetRenderState(pThisCC, pContext->id, 1, pRenderState);
81 }
82 Log(("vmsvga3dLoadReinitContext: Recreate render state END\n"));
83
84 /* Recreate the texture state */
85 Log(("vmsvga3dLoadReinitContext: Recreate texture state BEGIN\n"));
86 for (uint32_t iStage = 0; iStage < RT_ELEMENTS(pContext->state.aTextureStates); ++iStage)
87 {
88 for (uint32_t j = 0; j < RT_ELEMENTS(pContext->state.aTextureStates[0]); ++j)
89 {
90 SVGA3dTextureState *pTextureState = &pContext->state.aTextureStates[iStage][j];
91
92 if (pTextureState->name != SVGA3D_TS_INVALID)
93 vmsvga3dSetTextureState(pThisCC, pContext->id, 1, pTextureState);
94 }
95 }
96 Log(("vmsvga3dLoadReinitContext: Recreate texture state END\n"));
97
98 /* Reprogram the clip planes. */
99 for (uint32_t j = 0; j < RT_ELEMENTS(pContext->state.aClipPlane); j++)
100 {
101 if (pContext->state.aClipPlane[j].fValid == true)
102 vmsvga3dSetClipPlane(pThisCC, cid, j, pContext->state.aClipPlane[j].plane);
103 }
104
105 /* Reprogram the light data. */
106 for (uint32_t j = 0; j < RT_ELEMENTS(pContext->state.aLightData); j++)
107 {
108 if (pContext->state.aLightData[j].fValidData == true)
109 vmsvga3dSetLightData(pThisCC, cid, j, &pContext->state.aLightData[j].data);
110 if (pContext->state.aLightData[j].fEnabled)
111 vmsvga3dSetLightEnabled(pThisCC, cid, j, true);
112 }
113
114 /* Recreate the transform state. */
115 if (pContext->state.u32UpdateFlags & VMSVGA3D_UPDATE_TRANSFORM)
116 {
117 for (uint32_t j = 0; j < RT_ELEMENTS(pContext->state.aTransformState); j++)
118 {
119 if (pContext->state.aTransformState[j].fValid == true)
120 vmsvga3dSetTransform(pThisCC, cid, (SVGA3dTransformType)j, pContext->state.aTransformState[j].matrix);
121 }
122 }
123
124 /* Reprogram the material data. */
125 if (pContext->state.u32UpdateFlags & VMSVGA3D_UPDATE_MATERIAL)
126 {
127 for (uint32_t j = 0; j < RT_ELEMENTS(pContext->state.aMaterial); j++)
128 {
129 if (pContext->state.aMaterial[j].fValid == true)
130 vmsvga3dSetMaterial(pThisCC, cid, (SVGA3dFace)j, &pContext->state.aMaterial[j].material);
131 }
132 }
133
134 if (pContext->state.u32UpdateFlags & VMSVGA3D_UPDATE_SCISSORRECT)
135 vmsvga3dSetScissorRect(pThisCC, cid, &pContext->state.RectScissor);
136 if (pContext->state.u32UpdateFlags & VMSVGA3D_UPDATE_ZRANGE)
137 vmsvga3dSetZRange(pThisCC, cid, pContext->state.zRange);
138 if (pContext->state.u32UpdateFlags & VMSVGA3D_UPDATE_VIEWPORT)
139 vmsvga3dSetViewPort(pThisCC, cid, &pContext->state.RectViewPort);
140 if (pContext->state.u32UpdateFlags & VMSVGA3D_UPDATE_VERTEXSHADER)
141 vmsvga3dShaderSet(pThisCC, pContext, cid, SVGA3D_SHADERTYPE_VS, pContext->state.shidVertex);
142 if (pContext->state.u32UpdateFlags & VMSVGA3D_UPDATE_PIXELSHADER)
143 vmsvga3dShaderSet(pThisCC, pContext, cid, SVGA3D_SHADERTYPE_PS, pContext->state.shidPixel);
144
145 Log(("vmsvga3dLoadReinitContext: returns [cid=%#x]\n", cid));
146 return VINF_SUCCESS;
147}
148
149static int vmsvga3dLoadVMSVGA3DSURFACEPreMipLevels(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, VMSVGA3DSURFACE *pSurface)
150{
151 struct VMSVGA3DSURFACEPreMipLevels
152 {
153 uint32_t id;
154 uint32_t idAssociatedContext;
155 uint32_t surfaceFlags;
156 SVGA3dSurfaceFormat format;
157#ifdef VMSVGA3D_OPENGL
158 GLint internalFormatGL;
159 GLint formatGL;
160 GLint typeGL;
161#endif
162 SVGA3dSurfaceFace faces[SVGA3D_MAX_SURFACE_FACES];
163 uint32_t cFaces;
164 uint32_t multiSampleCount;
165 SVGA3dTextureFilter autogenFilter;
166 uint32_t cbBlock;
167 };
168
169 static SSMFIELD const s_aVMSVGA3DSURFACEFieldsPreMipLevels[] =
170 {
171 SSMFIELD_ENTRY(struct VMSVGA3DSURFACEPreMipLevels, id),
172 SSMFIELD_ENTRY(struct VMSVGA3DSURFACEPreMipLevels, idAssociatedContext),
173 SSMFIELD_ENTRY(struct VMSVGA3DSURFACEPreMipLevels, surfaceFlags),
174 SSMFIELD_ENTRY(struct VMSVGA3DSURFACEPreMipLevels, format),
175#ifdef VMSVGA3D_OPENGL
176 SSMFIELD_ENTRY(struct VMSVGA3DSURFACEPreMipLevels, internalFormatGL),
177 SSMFIELD_ENTRY(struct VMSVGA3DSURFACEPreMipLevels, formatGL),
178 SSMFIELD_ENTRY(struct VMSVGA3DSURFACEPreMipLevels, typeGL),
179#endif
180 SSMFIELD_ENTRY(struct VMSVGA3DSURFACEPreMipLevels, faces),
181 SSMFIELD_ENTRY(struct VMSVGA3DSURFACEPreMipLevels, cFaces),
182 SSMFIELD_ENTRY(struct VMSVGA3DSURFACEPreMipLevels, multiSampleCount),
183 SSMFIELD_ENTRY(struct VMSVGA3DSURFACEPreMipLevels, autogenFilter),
184#ifdef VMSVGA3D_DIRECT3D
185 SSMFIELD_ENTRY(struct VMSVGA3DSURFACEPreMipLevels, format), /* Yes, the 'format' field is duplicated. */
186#endif
187 SSMFIELD_ENTRY(struct VMSVGA3DSURFACEPreMipLevels, cbBlock),
188 SSMFIELD_ENTRY_TERM()
189 };
190
191 struct VMSVGA3DSURFACEPreMipLevels surfacePreMipLevels;
192 int rc = pDevIns->pHlpR3->pfnSSMGetStructEx(pSSM, &surfacePreMipLevels, sizeof(surfacePreMipLevels), 0, s_aVMSVGA3DSURFACEFieldsPreMipLevels, NULL);
193 if (RT_SUCCESS(rc))
194 {
195 pSurface->id = surfacePreMipLevels.id;
196 pSurface->idAssociatedContext = surfacePreMipLevels.idAssociatedContext;
197 pSurface->surfaceFlags = surfacePreMipLevels.surfaceFlags;
198 pSurface->format = surfacePreMipLevels.format;
199#ifdef VMSVGA3D_OPENGL
200 pSurface->internalFormatGL = surfacePreMipLevels.internalFormatGL;
201 pSurface->formatGL = surfacePreMipLevels.formatGL;
202 pSurface->typeGL = surfacePreMipLevels.typeGL;
203#endif
204 pSurface->cLevels = surfacePreMipLevels.faces[0].numMipLevels;
205 pSurface->cFaces = surfacePreMipLevels.cFaces;
206 pSurface->multiSampleCount = surfacePreMipLevels.multiSampleCount;
207 pSurface->autogenFilter = surfacePreMipLevels.autogenFilter;
208 pSurface->cbBlock = surfacePreMipLevels.cbBlock;
209 }
210 return rc;
211}
212
213
214/*
215 * Load the legacy VMSVGA3DCONTEXT from saved state version VGA_SAVEDSTATE_VERSION_VMSVGA_MIPLEVELS (23)
216 * or earlier, i.e. 6.1 or old trunk.
217 *
218 * The saved state incompatibility has been introduced in two revisions:
219 *
220 * - r140506: which makes sure that VMSVGA structures are tightly packed (pragma pack(1)).
221 * This caused all structures which have a member from VMSVGA headers (like VMSVGALIGHTSTATE) to be packed too.
222 * For example the size of aLightData element (VMSVGALIGHTSTATE) is 2 bytes smaller on trunk (118) than on 6.1 (120),
223 * which happens because SVGA3dLightData member offset is 2 on trunk and 4 on 6.1.
224 *
225 * - r141385: new VMSVGA device headers.
226 * SVGA3D_RS_MAX is 99 with new VMSVGA headers, but it was 100 with old headers.
227 * 6.1 always saved 100 entries; trunk before r141385 saved 100 entries; trunk at r141385 saves 99 entries.
228 *
229 * 6.1 saved state version is VGA_SAVEDSTATE_VERSION_VMSVGA_SCREENS (21).
230 * Trunk r141287 introduced VGA_SAVEDSTATE_VERSION_VMSVGA_MIPLEVELS (23).
231 *
232 * Both issues has been solved by loading a compatible context structure for saved state
233 * version < VGA_SAVEDSTATE_VERSION_VMSVGA_MIPLEVELS.
234 * This means that trunk will not be able to load states created from r140506 to r141385.
235 */
236static int vmsvga3dLoadVMSVGA3DCONTEXT23(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, VMSVGA3DCONTEXT *pContext)
237{
238#pragma pack(1)
239 struct VMSVGA3DCONTEXT23
240 {
241 uint32_t id;
242#ifdef VMSVGA3D_OPENGL
243 uint32_t lastError;
244#endif
245 uint32_t cPixelShaders;
246 uint32_t cVertexShaders;
247 struct
248 {
249 uint32_t u32UpdateFlags;
250 SVGA3dRenderState aRenderState[/*SVGA3D_RS_MAX=*/ 100];
251 SVGA3dTextureState aTextureStates[/*SVGA3D_MAX_TEXTURE_STAGE=*/ 8][/*SVGA3D_TS_MAX=*/ 30];
252 struct
253 {
254 bool fValid;
255 bool pad[3];
256 float matrix[16];
257 } aTransformState[SVGA3D_TRANSFORM_MAX];
258 struct
259 {
260 bool fValid;
261 bool pad[3];
262 SVGA3dMaterial material;
263 } aMaterial[SVGA3D_FACE_MAX];
264 struct
265 {
266 bool fValid;
267 bool pad[3];
268 float plane[4];
269 } aClipPlane[SVGA3D_CLIPPLANE_5];
270 struct
271 {
272 bool fEnabled;
273 bool fValidData;
274 bool pad[2];
275 SVGA3dLightData data;
276 } aLightData[SVGA3D_MAX_LIGHTS];
277 uint32_t aRenderTargets[SVGA3D_RT_MAX];
278 SVGA3dRect RectScissor;
279 SVGA3dRect RectViewPort;
280 SVGA3dZRange zRange;
281 uint32_t shidPixel;
282 uint32_t shidVertex;
283 uint32_t cPixelShaderConst;
284 uint32_t cVertexShaderConst;
285 } state;
286 };
287#pragma pack()
288
289 static SSMFIELD const g_aVMSVGA3DCONTEXT23Fields[] =
290 {
291 SSMFIELD_ENTRY(VMSVGA3DCONTEXT23, id),
292#ifdef VMSVGA3D_OPENGL
293 SSMFIELD_ENTRY(VMSVGA3DCONTEXT23, lastError),
294#endif
295 SSMFIELD_ENTRY(VMSVGA3DCONTEXT23, cPixelShaders),
296 SSMFIELD_ENTRY(VMSVGA3DCONTEXT23, cVertexShaders),
297 SSMFIELD_ENTRY(VMSVGA3DCONTEXT23, state.u32UpdateFlags),
298 SSMFIELD_ENTRY(VMSVGA3DCONTEXT23, state.aRenderState),
299 SSMFIELD_ENTRY(VMSVGA3DCONTEXT23, state.aTextureStates),
300 SSMFIELD_ENTRY(VMSVGA3DCONTEXT23, state.aTransformState),
301 SSMFIELD_ENTRY(VMSVGA3DCONTEXT23, state.aMaterial),
302 SSMFIELD_ENTRY(VMSVGA3DCONTEXT23, state.aClipPlane),
303 SSMFIELD_ENTRY(VMSVGA3DCONTEXT23, state.aLightData),
304 SSMFIELD_ENTRY(VMSVGA3DCONTEXT23, state.aRenderTargets),
305 SSMFIELD_ENTRY(VMSVGA3DCONTEXT23, state.RectScissor),
306 SSMFIELD_ENTRY(VMSVGA3DCONTEXT23, state.RectViewPort),
307 SSMFIELD_ENTRY(VMSVGA3DCONTEXT23, state.zRange),
308 SSMFIELD_ENTRY(VMSVGA3DCONTEXT23, state.shidPixel),
309 SSMFIELD_ENTRY(VMSVGA3DCONTEXT23, state.shidVertex),
310 SSMFIELD_ENTRY(VMSVGA3DCONTEXT23, state.cPixelShaderConst),
311 SSMFIELD_ENTRY(VMSVGA3DCONTEXT23, state.cVertexShaderConst),
312 SSMFIELD_ENTRY_TERM()
313 };
314
315 struct VMSVGA3DCONTEXT23 ctx;
316 int rc = pDevIns->pHlpR3->pfnSSMGetStructEx(pSSM, &ctx, sizeof(ctx), 0, g_aVMSVGA3DCONTEXT23Fields, NULL);
317 AssertRCReturn(rc, rc);
318
319 pContext->id = ctx.id;
320#ifdef VMSVGA3D_OPENGL
321 pContext->lastError = (GLenum)ctx.lastError;
322#endif
323
324 pContext->cPixelShaders = ctx.cPixelShaders;
325 pContext->cVertexShaders = ctx.cVertexShaders;
326 pContext->state.u32UpdateFlags = ctx.state.u32UpdateFlags;
327
328 AssertCompile(sizeof(SVGA3dRenderState) == 8);
329 AssertCompile(RT_ELEMENTS(pContext->state.aRenderState) == 99);
330 for (unsigned i = 0; i < RT_ELEMENTS(pContext->state.aRenderState); ++i)
331 pContext->state.aRenderState[i] = ctx.state.aRenderState[i];
332
333 // Skip pContext->state.aTextureStates
334 AssertCompile(sizeof(SVGA3dTextureState) == 12);
335
336 AssertCompile(sizeof(VMSVGATRANSFORMSTATE) == 68);
337 AssertCompile(RT_ELEMENTS(pContext->state.aTransformState) == 15);
338 for (unsigned i = 0; i < RT_ELEMENTS(pContext->state.aTransformState); ++i)
339 {
340 pContext->state.aTransformState[i].fValid = ctx.state.aTransformState[i].fValid;
341 memcpy(pContext->state.aTransformState[i].matrix, ctx.state.aTransformState[i].matrix, sizeof(pContext->state.aTransformState[i].matrix));
342 }
343
344 AssertCompile(sizeof(SVGA3dMaterial) == 68);
345 AssertCompile(RT_ELEMENTS(pContext->state.aMaterial) == 5);
346 for (unsigned i = 0; i < RT_ELEMENTS(pContext->state.aMaterial); ++i)
347 {
348 pContext->state.aMaterial[i].fValid = ctx.state.aMaterial[i].fValid;
349 pContext->state.aMaterial[i].material = ctx.state.aMaterial[i].material;
350 }
351
352 AssertCompile(sizeof(VMSVGACLIPPLANESTATE) == 20);
353 AssertCompile(RT_ELEMENTS(pContext->state.aClipPlane) == (1 << 5));
354 for (unsigned i = 0; i < RT_ELEMENTS(pContext->state.aClipPlane); ++i)
355 {
356 pContext->state.aClipPlane[i].fValid = ctx.state.aClipPlane[i].fValid;
357 memcpy(pContext->state.aClipPlane[i].plane, ctx.state.aClipPlane[i].plane, sizeof(pContext->state.aClipPlane[i].plane));
358 }
359
360 AssertCompile(sizeof(SVGA3dLightData) == 116);
361 AssertCompile(RT_ELEMENTS(pContext->state.aLightData) == 32);
362 for (unsigned i = 0; i < RT_ELEMENTS(pContext->state.aLightData); ++i)
363 {
364 pContext->state.aLightData[i].fEnabled = ctx.state.aLightData[i].fEnabled;
365 pContext->state.aLightData[i].fValidData = ctx.state.aLightData[i].fValidData;
366 pContext->state.aLightData[i].data = ctx.state.aLightData[i].data;
367 }
368
369 AssertCompile(RT_ELEMENTS(pContext->state.aRenderTargets) == 10);
370 memcpy(pContext->state.aRenderTargets, ctx.state.aRenderTargets, SVGA3D_RT_MAX * sizeof(uint32_t));
371
372 AssertCompile(sizeof(SVGA3dRect) == 16);
373 pContext->state.RectScissor = ctx.state.RectScissor;
374 pContext->state.RectViewPort = ctx.state.RectViewPort;
375
376 AssertCompile(sizeof(SVGA3dZRange) == 8);
377 pContext->state.zRange = ctx.state.zRange;
378
379 pContext->state.shidPixel = ctx.state.shidPixel;
380 pContext->state.shidVertex = ctx.state.shidVertex;
381 pContext->state.cPixelShaderConst = ctx.state.cPixelShaderConst;
382 pContext->state.cVertexShaderConst = ctx.state.cVertexShaderConst;
383
384 return VINF_SUCCESS;
385}
386
387int vmsvga3dLoadExec(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
388{
389 RT_NOREF(pDevIns, pThis, uPass);
390 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
391 AssertReturn(pState, VERR_NO_MEMORY);
392 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
393 int rc;
394 uint32_t cContexts, cSurfaces;
395 LogFlow(("vmsvga3dLoadExec:\n"));
396
397 /* Get the generic 3d state first. */
398 rc = pHlp->pfnSSMGetStructEx(pSSM, pState, sizeof(*pState), 0, g_aVMSVGA3DSTATEFields, NULL);
399 AssertRCReturn(rc, rc);
400
401 cContexts = pState->cContexts;
402 cSurfaces = pState->cSurfaces;
403 pState->cContexts = 0;
404 pState->cSurfaces = 0;
405
406 /* Fetch all active contexts. */
407 for (uint32_t i = 0; i < cContexts; i++)
408 {
409 PVMSVGA3DCONTEXT pContext;
410 uint32_t cid;
411
412 /* Get the context id */
413 rc = pHlp->pfnSSMGetU32(pSSM, &cid);
414 AssertRCReturn(rc, rc);
415
416 if (cid != SVGA3D_INVALID_ID)
417 {
418 uint32_t cPixelShaderConst, cVertexShaderConst, cPixelShaders, cVertexShaders;
419 LogFlow(("vmsvga3dLoadExec: Loading cid=%#x\n", cid));
420
421#ifdef VMSVGA3D_OPENGL
422 if (cid == VMSVGA3D_SHARED_CTX_ID)
423 {
424 i--; /* Not included in cContexts. */
425 pContext = &pState->SharedCtx;
426 if (pContext->id != VMSVGA3D_SHARED_CTX_ID)
427 {
428 /** @todo Separate backend */
429 rc = vmsvga3dContextDefineOgl(pThisCC, VMSVGA3D_SHARED_CTX_ID, VMSVGA3D_DEF_CTX_F_SHARED_CTX);
430 AssertRCReturn(rc, rc);
431 }
432 }
433 else
434#endif
435 {
436 rc = vmsvga3dContextDefine(pThisCC, cid);
437 AssertRCReturn(rc, rc);
438
439 pContext = pState->papContexts[i];
440 }
441 AssertReturn(pContext->id == cid, VERR_INTERNAL_ERROR);
442
443 if (uVersion >= VGA_SAVEDSTATE_VERSION_VMSVGA_MIPLEVELS)
444 rc = pHlp->pfnSSMGetStructEx(pSSM, pContext, sizeof(*pContext), 0, g_aVMSVGA3DCONTEXTFields, NULL);
445 else
446 rc = vmsvga3dLoadVMSVGA3DCONTEXT23(pDevIns, pSSM, pContext);
447 AssertRCReturn(rc, rc);
448
449 cPixelShaders = pContext->cPixelShaders;
450 cVertexShaders = pContext->cVertexShaders;
451 cPixelShaderConst = pContext->state.cPixelShaderConst;
452 cVertexShaderConst = pContext->state.cVertexShaderConst;
453 pContext->cPixelShaders = 0;
454 pContext->cVertexShaders = 0;
455 pContext->state.cPixelShaderConst = 0;
456 pContext->state.cVertexShaderConst = 0;
457
458 /* Fetch all pixel shaders. */
459 for (uint32_t j = 0; j < cPixelShaders; j++)
460 {
461 VMSVGA3DSHADER shader;
462 uint32_t shid;
463
464 /* Fetch the id first. */
465 rc = pHlp->pfnSSMGetU32(pSSM, &shid);
466 AssertRCReturn(rc, rc);
467
468 if (shid != SVGA3D_INVALID_ID)
469 {
470 uint32_t *pData;
471
472 /* Fetch a copy of the shader struct. */
473 rc = pHlp->pfnSSMGetStructEx(pSSM, &shader, sizeof(shader), 0, g_aVMSVGA3DSHADERFields, NULL);
474 AssertRCReturn(rc, rc);
475
476 pData = (uint32_t *)RTMemAlloc(shader.cbData);
477 AssertReturn(pData, VERR_NO_MEMORY);
478
479 rc = pHlp->pfnSSMGetMem(pSSM, pData, shader.cbData);
480 AssertRCReturn(rc, rc);
481
482 rc = vmsvga3dShaderDefine(pThisCC, cid, shid, shader.type, shader.cbData, pData);
483 AssertRCReturn(rc, rc);
484
485 RTMemFree(pData);
486 }
487 }
488
489 /* Fetch all vertex shaders. */
490 for (uint32_t j = 0; j < cVertexShaders; j++)
491 {
492 VMSVGA3DSHADER shader;
493 uint32_t shid;
494
495 /* Fetch the id first. */
496 rc = pHlp->pfnSSMGetU32(pSSM, &shid);
497 AssertRCReturn(rc, rc);
498
499 if (shid != SVGA3D_INVALID_ID)
500 {
501 uint32_t *pData;
502
503 /* Fetch a copy of the shader struct. */
504 rc = pHlp->pfnSSMGetStructEx(pSSM, &shader, sizeof(shader), 0, g_aVMSVGA3DSHADERFields, NULL);
505 AssertRCReturn(rc, rc);
506
507 pData = (uint32_t *)RTMemAlloc(shader.cbData);
508 AssertReturn(pData, VERR_NO_MEMORY);
509
510 rc = pHlp->pfnSSMGetMem(pSSM, pData, shader.cbData);
511 AssertRCReturn(rc, rc);
512
513 rc = vmsvga3dShaderDefine(pThisCC, cid, shid, shader.type, shader.cbData, pData);
514 AssertRCReturn(rc, rc);
515
516 RTMemFree(pData);
517 }
518 }
519
520 /* Fetch pixel shader constants. */
521 for (uint32_t j = 0; j < cPixelShaderConst; j++)
522 {
523 VMSVGASHADERCONST ShaderConst;
524
525 rc = pHlp->pfnSSMGetStructEx(pSSM, &ShaderConst, sizeof(ShaderConst), 0, g_aVMSVGASHADERCONSTFields, NULL);
526 AssertRCReturn(rc, rc);
527
528 if (ShaderConst.fValid)
529 {
530 rc = vmsvga3dShaderSetConst(pThisCC, cid, j, SVGA3D_SHADERTYPE_PS, ShaderConst.ctype, 1, ShaderConst.value);
531 AssertRCReturn(rc, rc);
532 }
533 }
534
535 /* Fetch vertex shader constants. */
536 for (uint32_t j = 0; j < cVertexShaderConst; j++)
537 {
538 VMSVGASHADERCONST ShaderConst;
539
540 rc = pHlp->pfnSSMGetStructEx(pSSM, &ShaderConst, sizeof(ShaderConst), 0, g_aVMSVGASHADERCONSTFields, NULL);
541 AssertRCReturn(rc, rc);
542
543 if (ShaderConst.fValid)
544 {
545 rc = vmsvga3dShaderSetConst(pThisCC, cid, j, SVGA3D_SHADERTYPE_VS, ShaderConst.ctype, 1, ShaderConst.value);
546 AssertRCReturn(rc, rc);
547 }
548 }
549
550 if (uVersion >= VGA_SAVEDSTATE_VERSION_VMSVGA_TEX_STAGES)
551 {
552 /* Load texture stage and samplers state. */
553
554 /* Number of stages/samplers. */
555 uint32_t cStages;
556 rc = pHlp->pfnSSMGetU32(pSSM, &cStages);
557 AssertRCReturn(rc, rc);
558
559 /* Number of states. */
560 uint32_t cTextureStates;
561 rc = pHlp->pfnSSMGetU32(pSSM, &cTextureStates);
562 AssertRCReturn(rc, rc);
563
564 for (uint32_t iStage = 0; iStage < cStages; ++iStage)
565 {
566 for (uint32_t j = 0; j < cTextureStates; ++j)
567 {
568 SVGA3dTextureState textureState;
569 pHlp->pfnSSMGetU32(pSSM, &textureState.stage);
570 uint32_t u32Name;
571 pHlp->pfnSSMGetU32(pSSM, &u32Name);
572 textureState.name = (SVGA3dTextureStateName)u32Name;
573 rc = pHlp->pfnSSMGetU32(pSSM, &textureState.value);
574 AssertRCReturn(rc, rc);
575
576 if ( iStage < RT_ELEMENTS(pContext->state.aTextureStates)
577 && j < RT_ELEMENTS(pContext->state.aTextureStates[0]))
578 {
579 pContext->state.aTextureStates[iStage][j] = textureState;
580 }
581 }
582 }
583 }
584
585 if (uVersion >= VGA_SAVEDSTATE_VERSION_VMSVGA)
586 {
587 VMSVGA3DQUERY query;
588 RT_ZERO(query);
589
590 rc = pHlp->pfnSSMGetStructEx(pSSM, &query, sizeof(query), 0, g_aVMSVGA3DQUERYFields, NULL);
591 AssertRCReturn(rc, rc);
592
593 switch (query.enmQueryState)
594 {
595 case VMSVGA3DQUERYSTATE_BUILDING:
596 /* Start collecting data. */
597 vmsvga3dQueryBegin(pThisCC, cid, SVGA3D_QUERYTYPE_OCCLUSION);
598 /* Partial result. */
599 pContext->occlusion.u32QueryResult = query.u32QueryResult;
600 break;
601
602 case VMSVGA3DQUERYSTATE_ISSUED:
603 /* Guest ended the query but did not read result. Result is restored. */
604 query.enmQueryState = VMSVGA3DQUERYSTATE_SIGNALED;
605 RT_FALL_THRU();
606 case VMSVGA3DQUERYSTATE_SIGNALED:
607 /* Create the query object. */
608 vmsvga3dQueryCreate(pThisCC, cid, SVGA3D_QUERYTYPE_OCCLUSION);
609
610 /* Update result and state. */
611 pContext->occlusion.enmQueryState = query.enmQueryState;
612 pContext->occlusion.u32QueryResult = query.u32QueryResult;
613 break;
614
615 default:
616 AssertFailed();
617 RT_FALL_THRU();
618 case VMSVGA3DQUERYSTATE_NULL:
619 RT_ZERO(pContext->occlusion);
620 break;
621 }
622 }
623 }
624 }
625
626#ifdef VMSVGA3D_OPENGL
627 /* Make the shared context the current one. */
628 if (pState->SharedCtx.id == VMSVGA3D_SHARED_CTX_ID)
629 VMSVGA3D_SET_CURRENT_CONTEXT(pState, &pState->SharedCtx);
630#endif
631
632 /* Fetch all surfaces. */
633 for (uint32_t i = 0; i < cSurfaces; i++)
634 {
635 uint32_t sid;
636
637 /* Fetch the id first. */
638 rc = pHlp->pfnSSMGetU32(pSSM, &sid);
639 AssertRCReturn(rc, rc);
640
641 if (sid != SVGA3D_INVALID_ID)
642 {
643 VMSVGA3DSURFACE surface;
644 LogFlow(("vmsvga3dLoadExec: Loading sid=%#x\n", sid));
645
646 /* Fetch the surface structure first. */
647 if (RT_LIKELY(uVersion >= VGA_SAVEDSTATE_VERSION_VMSVGA_MIPLEVELS))
648 rc = pHlp->pfnSSMGetStructEx(pSSM, &surface, sizeof(surface), 0, g_aVMSVGA3DSURFACEFields, NULL);
649 else
650 rc = vmsvga3dLoadVMSVGA3DSURFACEPreMipLevels(pDevIns, pSSM, &surface);
651 AssertRCReturn(rc, rc);
652
653 {
654 uint32_t cMipLevels = surface.cLevels * surface.cFaces;
655 PVMSVGA3DMIPMAPLEVEL pMipmapLevel = (PVMSVGA3DMIPMAPLEVEL)RTMemAlloc(cMipLevels * sizeof(VMSVGA3DMIPMAPLEVEL));
656 AssertReturn(pMipmapLevel, VERR_NO_MEMORY);
657 SVGA3dSize *pMipmapLevelSize = (SVGA3dSize *)RTMemAlloc(cMipLevels * sizeof(SVGA3dSize));
658 AssertReturn(pMipmapLevelSize, VERR_NO_MEMORY);
659
660 /* Load the mip map level info. */
661 for (uint32_t face=0; face < surface.cFaces; face++)
662 {
663 for (uint32_t j = 0; j < surface.cLevels; j++)
664 {
665 uint32_t idx = j + face * surface.cLevels;
666 /* Load the mip map level struct. */
667 rc = pHlp->pfnSSMGetStructEx(pSSM, &pMipmapLevel[idx], sizeof(pMipmapLevel[idx]), 0,
668 g_aVMSVGA3DMIPMAPLEVELFields, NULL);
669 AssertRCReturn(rc, rc);
670
671 pMipmapLevelSize[idx] = pMipmapLevel[idx].mipmapSize;
672 }
673 }
674
675 rc = vmsvga3dSurfaceDefine(pThisCC, sid, surface.surfaceFlags, surface.format, surface.multiSampleCount,
676 surface.autogenFilter, surface.cLevels, &pMipmapLevelSize[0], /* arraySize = */ 0, /* fAllocMipLevels = */ true);
677 AssertRCReturn(rc, rc);
678
679 RTMemFree(pMipmapLevelSize);
680 RTMemFree(pMipmapLevel);
681 }
682
683 PVMSVGA3DSURFACE pSurface = pState->papSurfaces[sid];
684 Assert(pSurface->id == sid);
685
686 pSurface->fDirty = false;
687
688 /* Load the mip map level data. */
689 for (uint32_t j = 0; j < pSurface->cLevels * pSurface->cFaces; j++)
690 {
691 PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->paMipmapLevels[j];
692 bool fDataPresent = false;
693
694 /* vmsvga3dSurfaceDefine already allocated the surface data buffer. */
695 Assert(pMipmapLevel->cbSurface);
696 AssertReturn(pMipmapLevel->pSurfaceData, VERR_INTERNAL_ERROR);
697
698 /* Fetch the data present boolean first. */
699 rc = pHlp->pfnSSMGetBool(pSSM, &fDataPresent);
700 AssertRCReturn(rc, rc);
701
702 Log(("Surface sid=%u: load mipmap level %d with %x bytes data (present=%d).\n", sid, j, pMipmapLevel->cbSurface, fDataPresent));
703
704 if (fDataPresent)
705 {
706 rc = pHlp->pfnSSMGetMem(pSSM, pMipmapLevel->pSurfaceData, pMipmapLevel->cbSurface);
707 AssertRCReturn(rc, rc);
708 pMipmapLevel->fDirty = true;
709 pSurface->fDirty = true;
710 }
711 else
712 {
713 pMipmapLevel->fDirty = false;
714 }
715 }
716 }
717 }
718
719#ifdef VMSVGA3D_OPENGL
720 /* Reinitialize the shared context. */
721 LogFlow(("vmsvga3dLoadExec: pState->SharedCtx.id=%#x\n", pState->SharedCtx.id));
722 if (pState->SharedCtx.id == VMSVGA3D_SHARED_CTX_ID)
723 {
724 rc = vmsvga3dLoadReinitContext(pThisCC, &pState->SharedCtx);
725 AssertRCReturn(rc, rc);
726 }
727#endif
728
729 /* Reinitialize all active contexts. */
730 for (uint32_t i = 0; i < pState->cContexts; i++)
731 {
732 PVMSVGA3DCONTEXT pContext = pState->papContexts[i];
733 if (pContext->id != SVGA3D_INVALID_ID)
734 {
735 rc = vmsvga3dLoadReinitContext(pThisCC, pContext);
736 AssertRCReturn(rc, rc);
737 }
738 }
739
740 LogFlow(("vmsvga3dLoadExec: return success\n"));
741 return VINF_SUCCESS;
742}
743
744
745static int vmsvga3dSaveContext(PCPDMDEVHLPR3 pHlp, PVGASTATECC pThisCC, PSSMHANDLE pSSM, PVMSVGA3DCONTEXT pContext)
746{
747 uint32_t cid = pContext->id;
748
749 /* Save the id first. */
750 int rc = pHlp->pfnSSMPutU32(pSSM, cid);
751 AssertRCReturn(rc, rc);
752
753 if (cid != SVGA3D_INVALID_ID)
754 {
755 /* Save a copy of the context structure first. */
756 rc = pHlp->pfnSSMPutStructEx(pSSM, pContext, sizeof(*pContext), 0, g_aVMSVGA3DCONTEXTFields, NULL);
757 AssertRCReturn(rc, rc);
758
759 /* Save all pixel shaders. */
760 for (uint32_t j = 0; j < pContext->cPixelShaders; j++)
761 {
762 PVMSVGA3DSHADER pShader = &pContext->paPixelShader[j];
763
764 /* Save the id first. */
765 rc = pHlp->pfnSSMPutU32(pSSM, pShader->id);
766 AssertRCReturn(rc, rc);
767
768 if (pShader->id != SVGA3D_INVALID_ID)
769 {
770 uint32_t cbData = pShader->cbData;
771
772 /* Save a copy of the shader struct. */
773 rc = pHlp->pfnSSMPutStructEx(pSSM, pShader, sizeof(*pShader), 0, g_aVMSVGA3DSHADERFields, NULL);
774 AssertRCReturn(rc, rc);
775
776 Log(("Save pixelshader shid=%d with %x bytes code.\n", pShader->id, cbData));
777 rc = pHlp->pfnSSMPutMem(pSSM, pShader->pShaderProgram, cbData);
778 AssertRCReturn(rc, rc);
779 }
780 }
781
782 /* Save all vertex shaders. */
783 for (uint32_t j = 0; j < pContext->cVertexShaders; j++)
784 {
785 PVMSVGA3DSHADER pShader = &pContext->paVertexShader[j];
786
787 /* Save the id first. */
788 rc = pHlp->pfnSSMPutU32(pSSM, pShader->id);
789 AssertRCReturn(rc, rc);
790
791 if (pShader->id != SVGA3D_INVALID_ID)
792 {
793 uint32_t cbData = pShader->cbData;
794
795 /* Save a copy of the shader struct. */
796 rc = pHlp->pfnSSMPutStructEx(pSSM, pShader, sizeof(*pShader), 0, g_aVMSVGA3DSHADERFields, NULL);
797 AssertRCReturn(rc, rc);
798
799 Log(("Save vertex shader shid=%d with %x bytes code.\n", pShader->id, cbData));
800 /* Fetch the shader code and save it. */
801 rc = pHlp->pfnSSMPutMem(pSSM, pShader->pShaderProgram, cbData);
802 AssertRCReturn(rc, rc);
803 }
804 }
805
806 /* Save pixel shader constants. */
807 for (uint32_t j = 0; j < pContext->state.cPixelShaderConst; j++)
808 {
809 rc = pHlp->pfnSSMPutStructEx(pSSM, &pContext->state.paPixelShaderConst[j], sizeof(pContext->state.paPixelShaderConst[j]), 0, g_aVMSVGASHADERCONSTFields, NULL);
810 AssertRCReturn(rc, rc);
811 }
812
813 /* Save vertex shader constants. */
814 for (uint32_t j = 0; j < pContext->state.cVertexShaderConst; j++)
815 {
816 rc = pHlp->pfnSSMPutStructEx(pSSM, &pContext->state.paVertexShaderConst[j], sizeof(pContext->state.paVertexShaderConst[j]), 0, g_aVMSVGASHADERCONSTFields, NULL);
817 AssertRCReturn(rc, rc);
818 }
819
820 /* Save texture stage and samplers state. */
821
822 /* Number of stages/samplers. */
823 rc = pHlp->pfnSSMPutU32(pSSM, RT_ELEMENTS(pContext->state.aTextureStates));
824 AssertRCReturn(rc, rc);
825
826 /* Number of texture states. */
827 rc = pHlp->pfnSSMPutU32(pSSM, RT_ELEMENTS(pContext->state.aTextureStates[0]));
828 AssertRCReturn(rc, rc);
829
830 for (uint32_t iStage = 0; iStage < RT_ELEMENTS(pContext->state.aTextureStates); ++iStage)
831 {
832 for (uint32_t j = 0; j < RT_ELEMENTS(pContext->state.aTextureStates[0]); ++j)
833 {
834 SVGA3dTextureState *pTextureState = &pContext->state.aTextureStates[iStage][j];
835
836 pHlp->pfnSSMPutU32(pSSM, pTextureState->stage);
837 pHlp->pfnSSMPutU32(pSSM, pTextureState->name);
838 rc = pHlp->pfnSSMPutU32(pSSM, pTextureState->value);
839 AssertRCReturn(rc, rc);
840 }
841 }
842
843 /* Occlusion query. */
844 if (!VMSVGA3DQUERY_EXISTS(&pContext->occlusion))
845 {
846 pContext->occlusion.enmQueryState = VMSVGA3DQUERYSTATE_NULL;
847 }
848
849 /* Save the current query state, because code below can change it. */
850 VMSVGA3DQUERYSTATE const enmQueryState = pContext->occlusion.enmQueryState;
851 switch (enmQueryState)
852 {
853 case VMSVGA3DQUERYSTATE_BUILDING:
854 /* Stop collecting data. Fetch partial result. Save result. */
855 vmsvga3dQueryEnd(pThisCC, cid, SVGA3D_QUERYTYPE_OCCLUSION);
856 RT_FALL_THRU();
857 case VMSVGA3DQUERYSTATE_ISSUED:
858 /* Fetch result. Save result. */
859 pContext->occlusion.u32QueryResult = 0;
860 vmsvga3dQueryWait(pThisCC, cid, SVGA3D_QUERYTYPE_OCCLUSION, NULL, NULL);
861 RT_FALL_THRU();
862 case VMSVGA3DQUERYSTATE_SIGNALED:
863 /* Save result. Nothing to do here. */
864 break;
865
866 default:
867 AssertFailed();
868 RT_FALL_THRU();
869 case VMSVGA3DQUERYSTATE_NULL:
870 pContext->occlusion.enmQueryState = VMSVGA3DQUERYSTATE_NULL;
871 pContext->occlusion.u32QueryResult = 0;
872 break;
873 }
874
875 /* Restore the current actual state. */
876 pContext->occlusion.enmQueryState = enmQueryState;
877
878 rc = pHlp->pfnSSMPutStructEx(pSSM, &pContext->occlusion, sizeof(pContext->occlusion), 0, g_aVMSVGA3DQUERYFields, NULL);
879 AssertRCReturn(rc, rc);
880 }
881
882 return VINF_SUCCESS;
883}
884
885int vmsvga3dSaveExec(PPDMDEVINS pDevIns, PVGASTATECC pThisCC, PSSMHANDLE pSSM)
886{
887 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
888 AssertReturn(pState, VERR_NO_MEMORY);
889 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
890 int rc;
891
892 /* Save a copy of the generic 3d state first. */
893 rc = pHlp->pfnSSMPutStructEx(pSSM, pState, sizeof(*pState), 0, g_aVMSVGA3DSTATEFields, NULL);
894 AssertRCReturn(rc, rc);
895
896#ifdef VMSVGA3D_OPENGL
897 /* Save the shared context. */
898 if (pState->SharedCtx.id == VMSVGA3D_SHARED_CTX_ID)
899 {
900 rc = vmsvga3dSaveContext(pHlp, pThisCC, pSSM, &pState->SharedCtx);
901 AssertRCReturn(rc, rc);
902 }
903#endif
904
905 /* Save all active contexts. */
906 for (uint32_t i = 0; i < pState->cContexts; i++)
907 {
908 rc = vmsvga3dSaveContext(pHlp, pThisCC, pSSM, pState->papContexts[i]);
909 AssertRCReturn(rc, rc);
910 }
911
912 /* Save all active surfaces. */
913 for (uint32_t sid = 0; sid < pState->cSurfaces; sid++)
914 {
915 PVMSVGA3DSURFACE pSurface = pState->papSurfaces[sid];
916
917 /* Save the id first. */
918 rc = pHlp->pfnSSMPutU32(pSSM, pSurface->id);
919 AssertRCReturn(rc, rc);
920
921 if (pSurface->id != SVGA3D_INVALID_ID)
922 {
923 /* Save a copy of the surface structure first. */
924 rc = pHlp->pfnSSMPutStructEx(pSSM, pSurface, sizeof(*pSurface), 0, g_aVMSVGA3DSURFACEFields, NULL);
925 AssertRCReturn(rc, rc);
926
927 /* Save the mip map level info. */
928 for (uint32_t face=0; face < pSurface->cFaces; face++)
929 {
930 for (uint32_t i = 0; i < pSurface->cLevels; i++)
931 {
932 uint32_t idx = i + face * pSurface->cLevels;
933 PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->paMipmapLevels[idx];
934
935 /* Save a copy of the mip map level struct. */
936 rc = pHlp->pfnSSMPutStructEx(pSSM, pMipmapLevel, sizeof(*pMipmapLevel), 0, g_aVMSVGA3DMIPMAPLEVELFields, NULL);
937 AssertRCReturn(rc, rc);
938 }
939 }
940
941 /* Save the mip map level data. */
942 for (uint32_t face=0; face < pSurface->cFaces; face++)
943 {
944 for (uint32_t i = 0; i < pSurface->cLevels; i++)
945 {
946 uint32_t idx = i + face * pSurface->cLevels;
947 PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->paMipmapLevels[idx];
948
949 Log(("Surface sid=%u: save mipmap level %d with %x bytes data.\n", sid, i, pMipmapLevel->cbSurface));
950
951 if (!VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface))
952 {
953 if (pMipmapLevel->fDirty)
954 {
955 /* Data follows */
956 rc = pHlp->pfnSSMPutBool(pSSM, true);
957 AssertRCReturn(rc, rc);
958
959 Assert(pMipmapLevel->cbSurface);
960 rc = pHlp->pfnSSMPutMem(pSSM, pMipmapLevel->pSurfaceData, pMipmapLevel->cbSurface);
961 AssertRCReturn(rc, rc);
962 }
963 else
964 {
965 /* No data follows */
966 rc = pHlp->pfnSSMPutBool(pSSM, false);
967 AssertRCReturn(rc, rc);
968 }
969 }
970 else if (vmsvga3dIsLegacyBackend(pThisCC))
971 {
972#ifdef VMSVGA3D_DIRECT3D
973 void *pData;
974 bool fRenderTargetTexture = false;
975 bool fTexture = false;
976 bool fSkipSave = false;
977 HRESULT hr;
978
979 Assert(pMipmapLevel->cbSurface);
980 pData = RTMemAllocZ(pMipmapLevel->cbSurface);
981 AssertReturn(pData, VERR_NO_MEMORY);
982
983 switch (pSurface->enmD3DResType)
984 {
985 case VMSVGA3D_D3DRESTYPE_CUBE_TEXTURE:
986 case VMSVGA3D_D3DRESTYPE_VOLUME_TEXTURE:
987 AssertFailed(); /// @todo
988 fSkipSave = true;
989 break;
990 case VMSVGA3D_D3DRESTYPE_SURFACE:
991 case VMSVGA3D_D3DRESTYPE_TEXTURE:
992 {
993 if (pSurface->surfaceFlags & SVGA3D_SURFACE_HINT_DEPTHSTENCIL)
994 {
995 /** @todo unable to easily fetch depth surface data in d3d 9 */
996 fSkipSave = true;
997 break;
998 }
999
1000 fTexture = (pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_TEXTURE);
1001 fRenderTargetTexture = fTexture && (pSurface->surfaceFlags & SVGA3D_SURFACE_HINT_RENDERTARGET);
1002
1003 D3DLOCKED_RECT LockedRect;
1004
1005 if (fTexture)
1006 {
1007 if (pSurface->bounce.pTexture)
1008 {
1009 if ( !pSurface->fDirty
1010 && fRenderTargetTexture
1011 && i == 0 /* only the first time */)
1012 {
1013 IDirect3DSurface9 *pSrc, *pDest;
1014
1015 /** @todo stricter checks for associated context */
1016 uint32_t cid = pSurface->idAssociatedContext;
1017
1018 PVMSVGA3DCONTEXT pContext;
1019 rc = vmsvga3dContextFromCid(pState, cid, &pContext);
1020 AssertRCReturn(rc, rc);
1021
1022 hr = pSurface->bounce.pTexture->GetSurfaceLevel(i, &pDest);
1023 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: GetSurfaceLevel failed with %x\n", hr), VERR_INTERNAL_ERROR);
1024
1025 hr = pSurface->u.pTexture->GetSurfaceLevel(i, &pSrc);
1026 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: GetSurfaceLevel failed with %x\n", hr), VERR_INTERNAL_ERROR);
1027
1028 hr = pContext->pDevice->GetRenderTargetData(pSrc, pDest);
1029 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: GetRenderTargetData failed with %x\n", hr), VERR_INTERNAL_ERROR);
1030
1031 pSrc->Release();
1032 pDest->Release();
1033 }
1034
1035 hr = pSurface->bounce.pTexture->LockRect(i, /* texture level */
1036 &LockedRect,
1037 NULL,
1038 D3DLOCK_READONLY);
1039 }
1040 else
1041 hr = pSurface->u.pTexture->LockRect(i, /* texture level */
1042 &LockedRect,
1043 NULL,
1044 D3DLOCK_READONLY);
1045 }
1046 else
1047 hr = pSurface->u.pSurface->LockRect(&LockedRect,
1048 NULL,
1049 D3DLOCK_READONLY);
1050 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: LockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
1051
1052 /* Copy the data one line at a time in case the internal pitch is different. */
1053 for (uint32_t j = 0; j < pMipmapLevel->cBlocksY; ++j)
1054 {
1055 uint8_t *pu8Dst = (uint8_t *)pData + j * pMipmapLevel->cbSurfacePitch;
1056 const uint8_t *pu8Src = (uint8_t *)LockedRect.pBits + j * LockedRect.Pitch;
1057 memcpy(pu8Dst, pu8Src, pMipmapLevel->cbSurfacePitch);
1058 }
1059
1060 if (fTexture)
1061 {
1062 if (pSurface->bounce.pTexture)
1063 {
1064 hr = pSurface->bounce.pTexture->UnlockRect(i);
1065 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: UnlockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
1066 }
1067 else
1068 hr = pSurface->u.pTexture->UnlockRect(i);
1069 }
1070 else
1071 hr = pSurface->u.pSurface->UnlockRect();
1072 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: UnlockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
1073 break;
1074 }
1075
1076 case VMSVGA3D_D3DRESTYPE_VERTEX_BUFFER:
1077 case VMSVGA3D_D3DRESTYPE_INDEX_BUFFER:
1078 {
1079 /* Current type of the buffer. */
1080 const bool fVertex = (pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_VERTEX_BUFFER);
1081
1082 uint8_t *pD3DData;
1083
1084 if (fVertex)
1085 hr = pSurface->u.pVertexBuffer->Lock(0, 0, (void **)&pD3DData, D3DLOCK_READONLY);
1086 else
1087 hr = pSurface->u.pIndexBuffer->Lock(0, 0, (void **)&pD3DData, D3DLOCK_READONLY);
1088 AssertMsg(hr == D3D_OK, ("vmsvga3dSaveExec: Lock %s failed with %x\n", (fVertex) ? "vertex" : "index", hr));
1089
1090 memcpy(pData, pD3DData, pMipmapLevel->cbSurface);
1091
1092 if (fVertex)
1093 hr = pSurface->u.pVertexBuffer->Unlock();
1094 else
1095 hr = pSurface->u.pIndexBuffer->Unlock();
1096 AssertMsg(hr == D3D_OK, ("vmsvga3dSaveExec: Unlock %s failed with %x\n", (fVertex) ? "vertex" : "index", hr));
1097 break;
1098 }
1099
1100 default:
1101 AssertFailed();
1102 break;
1103 }
1104
1105 if (!fSkipSave)
1106 {
1107 /* Data follows */
1108 rc = pHlp->pfnSSMPutBool(pSSM, true);
1109 AssertRCReturn(rc, rc);
1110
1111 /* And write the surface data. */
1112 rc = pHlp->pfnSSMPutMem(pSSM, pData, pMipmapLevel->cbSurface);
1113 AssertRCReturn(rc, rc);
1114 }
1115 else
1116 {
1117 /* No data follows */
1118 rc = pHlp->pfnSSMPutBool(pSSM, false);
1119 AssertRCReturn(rc, rc);
1120 }
1121
1122 RTMemFree(pData);
1123
1124#elif defined(VMSVGA3D_OPENGL)
1125 void *pData = NULL;
1126
1127 PVMSVGA3DCONTEXT pContext = &pState->SharedCtx;
1128 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
1129
1130 Assert(pMipmapLevel->cbSurface);
1131
1132 switch (pSurface->enmOGLResType)
1133 {
1134 default:
1135 AssertFailed();
1136 RT_FALL_THRU();
1137 case VMSVGA3D_OGLRESTYPE_RENDERBUFFER:
1138 /** @todo fetch data from the renderbuffer. Not used currently. */
1139 /* No data follows */
1140 rc = pHlp->pfnSSMPutBool(pSSM, false);
1141 AssertRCReturn(rc, rc);
1142 break;
1143
1144 case VMSVGA3D_OGLRESTYPE_TEXTURE:
1145 {
1146 GLint activeTexture;
1147
1148 pData = RTMemAllocZ(pMipmapLevel->cbSurface);
1149 AssertReturn(pData, VERR_NO_MEMORY);
1150
1151 glGetIntegerv(GL_TEXTURE_BINDING_2D, &activeTexture);
1152 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
1153
1154 glBindTexture(GL_TEXTURE_2D, pSurface->oglId.texture);
1155 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
1156
1157 /* Set row length and alignment of the output data. */
1158 VMSVGAPACKPARAMS SavedParams;
1159 vmsvga3dOglSetPackParams(pState, pContext, pSurface, &SavedParams);
1160
1161 glGetTexImage(GL_TEXTURE_2D,
1162 i,
1163 pSurface->formatGL,
1164 pSurface->typeGL,
1165 pData);
1166 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
1167
1168 vmsvga3dOglRestorePackParams(pState, pContext, pSurface, &SavedParams);
1169
1170 /* Data follows */
1171 rc = pHlp->pfnSSMPutBool(pSSM, true);
1172 AssertRCReturn(rc, rc);
1173
1174 /* And write the surface data. */
1175 rc = pHlp->pfnSSMPutMem(pSSM, pData, pMipmapLevel->cbSurface);
1176 AssertRCReturn(rc, rc);
1177
1178 /* Restore the old active texture. */
1179 glBindTexture(GL_TEXTURE_2D, activeTexture);
1180 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
1181 break;
1182 }
1183
1184 case VMSVGA3D_OGLRESTYPE_BUFFER:
1185 {
1186 uint8_t *pBufferData;
1187
1188 pState->ext.glBindBuffer(GL_ARRAY_BUFFER, pSurface->oglId.buffer);
1189 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
1190
1191 pBufferData = (uint8_t *)pState->ext.glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
1192 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
1193 Assert(pBufferData);
1194
1195 /* Data follows */
1196 rc = pHlp->pfnSSMPutBool(pSSM, true);
1197 AssertRCReturn(rc, rc);
1198
1199 /* And write the surface data. */
1200 rc = pHlp->pfnSSMPutMem(pSSM, pBufferData, pMipmapLevel->cbSurface);
1201 AssertRCReturn(rc, rc);
1202
1203 pState->ext.glUnmapBuffer(GL_ARRAY_BUFFER);
1204 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
1205
1206 pState->ext.glBindBuffer(GL_ARRAY_BUFFER, 0);
1207 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
1208
1209 }
1210 }
1211 if (pData)
1212 RTMemFree(pData);
1213#else
1214#error "Unexpected 3d backend"
1215#endif
1216 }
1217 else
1218 {
1219 /** @todo DX backend. */
1220 Assert(!vmsvga3dIsLegacyBackend(pThisCC));
1221
1222 /* No data follows */
1223 rc = pHlp->pfnSSMPutBool(pSSM, false);
1224 AssertRCReturn(rc, rc);
1225 }
1226 }
1227 }
1228 }
1229 }
1230 return VINF_SUCCESS;
1231}
1232
1233int vmsvga3dSaveShaderConst(PVMSVGA3DCONTEXT pContext, uint32_t reg, SVGA3dShaderType type, SVGA3dShaderConstType ctype,
1234 uint32_t val1, uint32_t val2, uint32_t val3, uint32_t val4)
1235{
1236 /* Choose a sane upper limit. */
1237 AssertReturn(reg < _32K, VERR_INVALID_PARAMETER);
1238
1239 if (type == SVGA3D_SHADERTYPE_VS)
1240 {
1241 if (pContext->state.cVertexShaderConst <= reg)
1242 {
1243 pContext->state.paVertexShaderConst = (PVMSVGASHADERCONST)RTMemRealloc(pContext->state.paVertexShaderConst, sizeof(VMSVGASHADERCONST) * (reg + 1));
1244 AssertReturn(pContext->state.paVertexShaderConst, VERR_NO_MEMORY);
1245 for (uint32_t i = pContext->state.cVertexShaderConst; i < reg + 1; i++)
1246 pContext->state.paVertexShaderConst[i].fValid = false;
1247 pContext->state.cVertexShaderConst = reg + 1;
1248 }
1249
1250 pContext->state.paVertexShaderConst[reg].fValid = true;
1251 pContext->state.paVertexShaderConst[reg].ctype = ctype;
1252 pContext->state.paVertexShaderConst[reg].value[0] = val1;
1253 pContext->state.paVertexShaderConst[reg].value[1] = val2;
1254 pContext->state.paVertexShaderConst[reg].value[2] = val3;
1255 pContext->state.paVertexShaderConst[reg].value[3] = val4;
1256 }
1257 else
1258 {
1259 Assert(type == SVGA3D_SHADERTYPE_PS);
1260 if (pContext->state.cPixelShaderConst <= reg)
1261 {
1262 pContext->state.paPixelShaderConst = (PVMSVGASHADERCONST)RTMemRealloc(pContext->state.paPixelShaderConst, sizeof(VMSVGASHADERCONST) * (reg + 1));
1263 AssertReturn(pContext->state.paPixelShaderConst, VERR_NO_MEMORY);
1264 for (uint32_t i = pContext->state.cPixelShaderConst; i < reg + 1; i++)
1265 pContext->state.paPixelShaderConst[i].fValid = false;
1266 pContext->state.cPixelShaderConst = reg + 1;
1267 }
1268
1269 pContext->state.paPixelShaderConst[reg].fValid = true;
1270 pContext->state.paPixelShaderConst[reg].ctype = ctype;
1271 pContext->state.paPixelShaderConst[reg].value[0] = val1;
1272 pContext->state.paPixelShaderConst[reg].value[1] = val2;
1273 pContext->state.paPixelShaderConst[reg].value[2] = val3;
1274 pContext->state.paPixelShaderConst[reg].value[3] = val4;
1275 }
1276
1277 return VINF_SUCCESS;
1278}
1279
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