VirtualBox

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

Last change on this file since 106221 was 106061, checked in by vboxsync, 3 months ago

Copyright year updates by scm.

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