VirtualBox

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

Last change on this file since 97441 was 96407, checked in by vboxsync, 2 years ago

scm copyright and license note update

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 54.4 KB
Line 
1/* $Id: DevVGA-SVGA3d-savedstate.cpp 96407 2022-08-22 17:43:14Z vboxsync $ */
2/** @file
3 * DevSVGA3d - VMWare SVGA device, 3D parts - Saved state and assocated stuff.
4 */
5
6/*
7 * Copyright (C) 2013-2022 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 surface.autogenFilter, surface.cLevels, &pMipmapLevelSize[0], /* arraySize = */ 0, /* fAllocMipLevels = */ true);
688 AssertRCReturn(rc, rc);
689
690 RTMemFree(pMipmapLevelSize);
691 RTMemFree(pMipmapLevel);
692 }
693
694 PVMSVGA3DSURFACE pSurface = pState->papSurfaces[sid];
695 Assert(pSurface->id == sid);
696
697 pSurface->fDirty = false;
698
699 /* Load the mip map level data. */
700 for (uint32_t j = 0; j < pSurface->cLevels * pSurface->cFaces; j++)
701 {
702 PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->paMipmapLevels[j];
703 bool fDataPresent = false;
704
705 /* vmsvga3dSurfaceDefine already allocated the surface data buffer. */
706 Assert(pMipmapLevel->cbSurface);
707 AssertReturn(pMipmapLevel->pSurfaceData, VERR_INTERNAL_ERROR);
708
709 /* Fetch the data present boolean first. */
710 rc = pHlp->pfnSSMGetBool(pSSM, &fDataPresent);
711 AssertRCReturn(rc, rc);
712
713 Log(("Surface sid=%u: load mipmap level %d with %x bytes data (present=%d).\n", sid, j, pMipmapLevel->cbSurface, fDataPresent));
714
715 if (fDataPresent)
716 {
717 rc = pHlp->pfnSSMGetMem(pSSM, pMipmapLevel->pSurfaceData, pMipmapLevel->cbSurface);
718 AssertRCReturn(rc, rc);
719 pMipmapLevel->fDirty = true;
720 pSurface->fDirty = true;
721 }
722 else
723 {
724 pMipmapLevel->fDirty = false;
725 }
726 }
727 }
728 }
729
730#ifdef VMSVGA3D_OPENGL
731 /* Reinitialize the shared context. */
732 LogFlow(("vmsvga3dLoadExec: pState->SharedCtx.id=%#x\n", pState->SharedCtx.id));
733 if (pState->SharedCtx.id == VMSVGA3D_SHARED_CTX_ID)
734 {
735 rc = vmsvga3dLoadReinitContext(pThisCC, &pState->SharedCtx);
736 AssertRCReturn(rc, rc);
737 }
738#endif
739
740 /* Reinitialize all active contexts. */
741 for (uint32_t i = 0; i < pState->cContexts; i++)
742 {
743 PVMSVGA3DCONTEXT pContext = pState->papContexts[i];
744 if (pContext->id != SVGA3D_INVALID_ID)
745 {
746 rc = vmsvga3dLoadReinitContext(pThisCC, pContext);
747 AssertRCReturn(rc, rc);
748 }
749 }
750
751 LogFlow(("vmsvga3dLoadExec: return success\n"));
752 return VINF_SUCCESS;
753}
754
755
756static int vmsvga3dSaveContext(PCPDMDEVHLPR3 pHlp, PVGASTATECC pThisCC, PSSMHANDLE pSSM, PVMSVGA3DCONTEXT pContext)
757{
758 uint32_t cid = pContext->id;
759
760 /* Save the id first. */
761 int rc = pHlp->pfnSSMPutU32(pSSM, cid);
762 AssertRCReturn(rc, rc);
763
764 if (cid != SVGA3D_INVALID_ID)
765 {
766 /* Save a copy of the context structure first. */
767 rc = pHlp->pfnSSMPutStructEx(pSSM, pContext, sizeof(*pContext), 0, g_aVMSVGA3DCONTEXTFields, NULL);
768 AssertRCReturn(rc, rc);
769
770 /* Save all pixel shaders. */
771 for (uint32_t j = 0; j < pContext->cPixelShaders; j++)
772 {
773 PVMSVGA3DSHADER pShader = &pContext->paPixelShader[j];
774
775 /* Save the id first. */
776 rc = pHlp->pfnSSMPutU32(pSSM, pShader->id);
777 AssertRCReturn(rc, rc);
778
779 if (pShader->id != SVGA3D_INVALID_ID)
780 {
781 uint32_t cbData = pShader->cbData;
782
783 /* Save a copy of the shader struct. */
784 rc = pHlp->pfnSSMPutStructEx(pSSM, pShader, sizeof(*pShader), 0, g_aVMSVGA3DSHADERFields, NULL);
785 AssertRCReturn(rc, rc);
786
787 Log(("Save pixelshader shid=%d with %x bytes code.\n", pShader->id, cbData));
788 rc = pHlp->pfnSSMPutMem(pSSM, pShader->pShaderProgram, cbData);
789 AssertRCReturn(rc, rc);
790 }
791 }
792
793 /* Save all vertex shaders. */
794 for (uint32_t j = 0; j < pContext->cVertexShaders; j++)
795 {
796 PVMSVGA3DSHADER pShader = &pContext->paVertexShader[j];
797
798 /* Save the id first. */
799 rc = pHlp->pfnSSMPutU32(pSSM, pShader->id);
800 AssertRCReturn(rc, rc);
801
802 if (pShader->id != SVGA3D_INVALID_ID)
803 {
804 uint32_t cbData = pShader->cbData;
805
806 /* Save a copy of the shader struct. */
807 rc = pHlp->pfnSSMPutStructEx(pSSM, pShader, sizeof(*pShader), 0, g_aVMSVGA3DSHADERFields, NULL);
808 AssertRCReturn(rc, rc);
809
810 Log(("Save vertex shader shid=%d with %x bytes code.\n", pShader->id, cbData));
811 /* Fetch the shader code and save it. */
812 rc = pHlp->pfnSSMPutMem(pSSM, pShader->pShaderProgram, cbData);
813 AssertRCReturn(rc, rc);
814 }
815 }
816
817 /* Save pixel shader constants. */
818 for (uint32_t j = 0; j < pContext->state.cPixelShaderConst; j++)
819 {
820 rc = pHlp->pfnSSMPutStructEx(pSSM, &pContext->state.paPixelShaderConst[j], sizeof(pContext->state.paPixelShaderConst[j]), 0, g_aVMSVGASHADERCONSTFields, NULL);
821 AssertRCReturn(rc, rc);
822 }
823
824 /* Save vertex shader constants. */
825 for (uint32_t j = 0; j < pContext->state.cVertexShaderConst; j++)
826 {
827 rc = pHlp->pfnSSMPutStructEx(pSSM, &pContext->state.paVertexShaderConst[j], sizeof(pContext->state.paVertexShaderConst[j]), 0, g_aVMSVGASHADERCONSTFields, NULL);
828 AssertRCReturn(rc, rc);
829 }
830
831 /* Save texture stage and samplers state. */
832
833 /* Number of stages/samplers. */
834 rc = pHlp->pfnSSMPutU32(pSSM, RT_ELEMENTS(pContext->state.aTextureStates));
835 AssertRCReturn(rc, rc);
836
837 /* Number of texture states. */
838 rc = pHlp->pfnSSMPutU32(pSSM, RT_ELEMENTS(pContext->state.aTextureStates[0]));
839 AssertRCReturn(rc, rc);
840
841 for (uint32_t iStage = 0; iStage < RT_ELEMENTS(pContext->state.aTextureStates); ++iStage)
842 {
843 for (uint32_t j = 0; j < RT_ELEMENTS(pContext->state.aTextureStates[0]); ++j)
844 {
845 SVGA3dTextureState *pTextureState = &pContext->state.aTextureStates[iStage][j];
846
847 pHlp->pfnSSMPutU32(pSSM, pTextureState->stage);
848 pHlp->pfnSSMPutU32(pSSM, pTextureState->name);
849 rc = pHlp->pfnSSMPutU32(pSSM, pTextureState->value);
850 AssertRCReturn(rc, rc);
851 }
852 }
853
854 /* Occlusion query. */
855 if (!VMSVGA3DQUERY_EXISTS(&pContext->occlusion))
856 {
857 pContext->occlusion.enmQueryState = VMSVGA3DQUERYSTATE_NULL;
858 }
859
860 /* Save the current query state, because code below can change it. */
861 VMSVGA3DQUERYSTATE const enmQueryState = pContext->occlusion.enmQueryState;
862 switch (enmQueryState)
863 {
864 case VMSVGA3DQUERYSTATE_BUILDING:
865 /* Stop collecting data. Fetch partial result. Save result. */
866 vmsvga3dQueryEnd(pThisCC, cid, SVGA3D_QUERYTYPE_OCCLUSION);
867 RT_FALL_THRU();
868 case VMSVGA3DQUERYSTATE_ISSUED:
869 /* Fetch result. Save result. */
870 pContext->occlusion.u32QueryResult = 0;
871 vmsvga3dQueryWait(pThisCC, cid, SVGA3D_QUERYTYPE_OCCLUSION, NULL, NULL);
872 RT_FALL_THRU();
873 case VMSVGA3DQUERYSTATE_SIGNALED:
874 /* Save result. Nothing to do here. */
875 break;
876
877 default:
878 AssertFailed();
879 RT_FALL_THRU();
880 case VMSVGA3DQUERYSTATE_NULL:
881 pContext->occlusion.enmQueryState = VMSVGA3DQUERYSTATE_NULL;
882 pContext->occlusion.u32QueryResult = 0;
883 break;
884 }
885
886 /* Restore the current actual state. */
887 pContext->occlusion.enmQueryState = enmQueryState;
888
889 rc = pHlp->pfnSSMPutStructEx(pSSM, &pContext->occlusion, sizeof(pContext->occlusion), 0, g_aVMSVGA3DQUERYFields, NULL);
890 AssertRCReturn(rc, rc);
891 }
892
893 return VINF_SUCCESS;
894}
895
896int vmsvga3dSaveExec(PPDMDEVINS pDevIns, PVGASTATECC pThisCC, PSSMHANDLE pSSM)
897{
898 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
899 AssertReturn(pState, VERR_NO_MEMORY);
900 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
901 int rc;
902
903 /* Save a copy of the generic 3d state first. */
904 rc = pHlp->pfnSSMPutStructEx(pSSM, pState, sizeof(*pState), 0, g_aVMSVGA3DSTATEFields, NULL);
905 AssertRCReturn(rc, rc);
906
907#ifdef VMSVGA3D_OPENGL
908 /* Save the shared context. */
909 if (pState->SharedCtx.id == VMSVGA3D_SHARED_CTX_ID)
910 {
911 rc = vmsvga3dSaveContext(pHlp, pThisCC, pSSM, &pState->SharedCtx);
912 AssertRCReturn(rc, rc);
913 }
914#endif
915
916 /* Save all active contexts. */
917 for (uint32_t i = 0; i < pState->cContexts; i++)
918 {
919 rc = vmsvga3dSaveContext(pHlp, pThisCC, pSSM, pState->papContexts[i]);
920 AssertRCReturn(rc, rc);
921 }
922
923 /* Save all active surfaces. */
924 for (uint32_t sid = 0; sid < pState->cSurfaces; sid++)
925 {
926 PVMSVGA3DSURFACE pSurface = pState->papSurfaces[sid];
927
928 /* Save the id first. */
929 rc = pHlp->pfnSSMPutU32(pSSM, pSurface->id);
930 AssertRCReturn(rc, rc);
931
932 if (pSurface->id != SVGA3D_INVALID_ID)
933 {
934 /* Save a copy of the surface structure first. */
935 rc = pHlp->pfnSSMPutStructEx(pSSM, pSurface, sizeof(*pSurface), 0, g_aVMSVGA3DSURFACEFields, NULL);
936 AssertRCReturn(rc, rc);
937
938 /* Save the mip map level info. */
939 for (uint32_t face=0; face < pSurface->cFaces; face++)
940 {
941 for (uint32_t i = 0; i < pSurface->cLevels; i++)
942 {
943 uint32_t idx = i + face * pSurface->cLevels;
944 PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->paMipmapLevels[idx];
945
946 /* Save a copy of the mip map level struct. */
947 rc = pHlp->pfnSSMPutStructEx(pSSM, pMipmapLevel, sizeof(*pMipmapLevel), 0, g_aVMSVGA3DMIPMAPLEVELFields, NULL);
948 AssertRCReturn(rc, rc);
949 }
950 }
951
952 /* Save the mip map level data. */
953 for (uint32_t face=0; face < pSurface->cFaces; face++)
954 {
955 for (uint32_t i = 0; i < pSurface->cLevels; i++)
956 {
957 uint32_t idx = i + face * pSurface->cLevels;
958 PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->paMipmapLevels[idx];
959
960 Log(("Surface sid=%u: save mipmap level %d with %x bytes data.\n", sid, i, pMipmapLevel->cbSurface));
961
962 if (!VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface))
963 {
964 if (pMipmapLevel->fDirty)
965 {
966 /* Data follows */
967 rc = pHlp->pfnSSMPutBool(pSSM, true);
968 AssertRCReturn(rc, rc);
969
970 Assert(pMipmapLevel->cbSurface);
971 rc = pHlp->pfnSSMPutMem(pSSM, pMipmapLevel->pSurfaceData, pMipmapLevel->cbSurface);
972 AssertRCReturn(rc, rc);
973 }
974 else
975 {
976 /* No data follows */
977 rc = pHlp->pfnSSMPutBool(pSSM, false);
978 AssertRCReturn(rc, rc);
979 }
980 }
981 else if (vmsvga3dIsLegacyBackend(pThisCC))
982 {
983#ifdef VMSVGA3D_DIRECT3D
984 void *pData;
985 bool fRenderTargetTexture = false;
986 bool fTexture = false;
987 bool fSkipSave = false;
988 HRESULT hr;
989
990 Assert(pMipmapLevel->cbSurface);
991 pData = RTMemAllocZ(pMipmapLevel->cbSurface);
992 AssertReturn(pData, VERR_NO_MEMORY);
993
994 switch (pSurface->enmD3DResType)
995 {
996 case VMSVGA3D_D3DRESTYPE_CUBE_TEXTURE:
997 case VMSVGA3D_D3DRESTYPE_VOLUME_TEXTURE:
998 AssertFailed(); /// @todo
999 fSkipSave = true;
1000 break;
1001 case VMSVGA3D_D3DRESTYPE_SURFACE:
1002 case VMSVGA3D_D3DRESTYPE_TEXTURE:
1003 {
1004 if (pSurface->f.surfaceFlags & SVGA3D_SURFACE_HINT_DEPTHSTENCIL)
1005 {
1006 /** @todo unable to easily fetch depth surface data in d3d 9 */
1007 fSkipSave = true;
1008 break;
1009 }
1010
1011 fTexture = (pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_TEXTURE);
1012 fRenderTargetTexture = fTexture && (pSurface->f.surfaceFlags & SVGA3D_SURFACE_HINT_RENDERTARGET);
1013
1014 D3DLOCKED_RECT LockedRect;
1015
1016 if (fTexture)
1017 {
1018 if (pSurface->bounce.pTexture)
1019 {
1020 if ( !pSurface->fDirty
1021 && fRenderTargetTexture
1022 && i == 0 /* only the first time */)
1023 {
1024 IDirect3DSurface9 *pSrc, *pDest;
1025
1026 /** @todo stricter checks for associated context */
1027 uint32_t cid = pSurface->idAssociatedContext;
1028
1029 PVMSVGA3DCONTEXT pContext;
1030 rc = vmsvga3dContextFromCid(pState, cid, &pContext);
1031 AssertRCReturn(rc, rc);
1032
1033 hr = pSurface->bounce.pTexture->GetSurfaceLevel(i, &pDest);
1034 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: GetSurfaceLevel failed with %x\n", hr), VERR_INTERNAL_ERROR);
1035
1036 hr = pSurface->u.pTexture->GetSurfaceLevel(i, &pSrc);
1037 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: GetSurfaceLevel failed with %x\n", hr), VERR_INTERNAL_ERROR);
1038
1039 hr = pContext->pDevice->GetRenderTargetData(pSrc, pDest);
1040 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: GetRenderTargetData failed with %x\n", hr), VERR_INTERNAL_ERROR);
1041
1042 pSrc->Release();
1043 pDest->Release();
1044 }
1045
1046 hr = pSurface->bounce.pTexture->LockRect(i, /* texture level */
1047 &LockedRect,
1048 NULL,
1049 D3DLOCK_READONLY);
1050 }
1051 else
1052 hr = pSurface->u.pTexture->LockRect(i, /* texture level */
1053 &LockedRect,
1054 NULL,
1055 D3DLOCK_READONLY);
1056 }
1057 else
1058 hr = pSurface->u.pSurface->LockRect(&LockedRect,
1059 NULL,
1060 D3DLOCK_READONLY);
1061 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: LockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
1062
1063 /* Copy the data one line at a time in case the internal pitch is different. */
1064 for (uint32_t j = 0; j < pMipmapLevel->cBlocksY; ++j)
1065 {
1066 uint8_t *pu8Dst = (uint8_t *)pData + j * pMipmapLevel->cbSurfacePitch;
1067 const uint8_t *pu8Src = (uint8_t *)LockedRect.pBits + j * LockedRect.Pitch;
1068 memcpy(pu8Dst, pu8Src, pMipmapLevel->cbSurfacePitch);
1069 }
1070
1071 if (fTexture)
1072 {
1073 if (pSurface->bounce.pTexture)
1074 {
1075 hr = pSurface->bounce.pTexture->UnlockRect(i);
1076 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: UnlockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
1077 }
1078 else
1079 hr = pSurface->u.pTexture->UnlockRect(i);
1080 }
1081 else
1082 hr = pSurface->u.pSurface->UnlockRect();
1083 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: UnlockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
1084 break;
1085 }
1086
1087 case VMSVGA3D_D3DRESTYPE_VERTEX_BUFFER:
1088 case VMSVGA3D_D3DRESTYPE_INDEX_BUFFER:
1089 {
1090 /* Current type of the buffer. */
1091 const bool fVertex = (pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_VERTEX_BUFFER);
1092
1093 uint8_t *pD3DData;
1094
1095 if (fVertex)
1096 hr = pSurface->u.pVertexBuffer->Lock(0, 0, (void **)&pD3DData, D3DLOCK_READONLY);
1097 else
1098 hr = pSurface->u.pIndexBuffer->Lock(0, 0, (void **)&pD3DData, D3DLOCK_READONLY);
1099 AssertMsg(hr == D3D_OK, ("vmsvga3dSaveExec: Lock %s failed with %x\n", (fVertex) ? "vertex" : "index", hr));
1100
1101 memcpy(pData, pD3DData, pMipmapLevel->cbSurface);
1102
1103 if (fVertex)
1104 hr = pSurface->u.pVertexBuffer->Unlock();
1105 else
1106 hr = pSurface->u.pIndexBuffer->Unlock();
1107 AssertMsg(hr == D3D_OK, ("vmsvga3dSaveExec: Unlock %s failed with %x\n", (fVertex) ? "vertex" : "index", hr));
1108 break;
1109 }
1110
1111 default:
1112 AssertFailed();
1113 break;
1114 }
1115
1116 if (!fSkipSave)
1117 {
1118 /* Data follows */
1119 rc = pHlp->pfnSSMPutBool(pSSM, true);
1120 AssertRCReturn(rc, rc);
1121
1122 /* And write the surface data. */
1123 rc = pHlp->pfnSSMPutMem(pSSM, pData, pMipmapLevel->cbSurface);
1124 AssertRCReturn(rc, rc);
1125 }
1126 else
1127 {
1128 /* No data follows */
1129 rc = pHlp->pfnSSMPutBool(pSSM, false);
1130 AssertRCReturn(rc, rc);
1131 }
1132
1133 RTMemFree(pData);
1134
1135#elif defined(VMSVGA3D_OPENGL)
1136 void *pData = NULL;
1137
1138 PVMSVGA3DCONTEXT pContext = &pState->SharedCtx;
1139 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
1140
1141 Assert(pMipmapLevel->cbSurface);
1142
1143 switch (pSurface->enmOGLResType)
1144 {
1145 default:
1146 AssertFailed();
1147 RT_FALL_THRU();
1148 case VMSVGA3D_OGLRESTYPE_RENDERBUFFER:
1149 /** @todo fetch data from the renderbuffer. Not used currently. */
1150 /* No data follows */
1151 rc = pHlp->pfnSSMPutBool(pSSM, false);
1152 AssertRCReturn(rc, rc);
1153 break;
1154
1155 case VMSVGA3D_OGLRESTYPE_TEXTURE:
1156 {
1157 GLint activeTexture;
1158
1159 pData = RTMemAllocZ(pMipmapLevel->cbSurface);
1160 AssertReturn(pData, VERR_NO_MEMORY);
1161
1162 glGetIntegerv(GL_TEXTURE_BINDING_2D, &activeTexture);
1163 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
1164
1165 glBindTexture(GL_TEXTURE_2D, pSurface->oglId.texture);
1166 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
1167
1168 /* Set row length and alignment of the output data. */
1169 VMSVGAPACKPARAMS SavedParams;
1170 vmsvga3dOglSetPackParams(pState, pContext, pSurface, &SavedParams);
1171
1172 glGetTexImage(GL_TEXTURE_2D,
1173 i,
1174 pSurface->formatGL,
1175 pSurface->typeGL,
1176 pData);
1177 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
1178
1179 vmsvga3dOglRestorePackParams(pState, pContext, pSurface, &SavedParams);
1180
1181 /* Data follows */
1182 rc = pHlp->pfnSSMPutBool(pSSM, true);
1183 AssertRCReturn(rc, rc);
1184
1185 /* And write the surface data. */
1186 rc = pHlp->pfnSSMPutMem(pSSM, pData, pMipmapLevel->cbSurface);
1187 AssertRCReturn(rc, rc);
1188
1189 /* Restore the old active texture. */
1190 glBindTexture(GL_TEXTURE_2D, activeTexture);
1191 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
1192 break;
1193 }
1194
1195 case VMSVGA3D_OGLRESTYPE_BUFFER:
1196 {
1197 uint8_t *pBufferData;
1198
1199 pState->ext.glBindBuffer(GL_ARRAY_BUFFER, pSurface->oglId.buffer);
1200 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
1201
1202 pBufferData = (uint8_t *)pState->ext.glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
1203 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
1204 Assert(pBufferData);
1205
1206 /* Data follows */
1207 rc = pHlp->pfnSSMPutBool(pSSM, true);
1208 AssertRCReturn(rc, rc);
1209
1210 /* And write the surface data. */
1211 rc = pHlp->pfnSSMPutMem(pSSM, pBufferData, pMipmapLevel->cbSurface);
1212 AssertRCReturn(rc, rc);
1213
1214 pState->ext.glUnmapBuffer(GL_ARRAY_BUFFER);
1215 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
1216
1217 pState->ext.glBindBuffer(GL_ARRAY_BUFFER, 0);
1218 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
1219
1220 }
1221 }
1222 if (pData)
1223 RTMemFree(pData);
1224#else
1225#error "Unexpected 3d backend"
1226#endif
1227 }
1228 else
1229 {
1230 /** @todo DX backend. */
1231 Assert(!vmsvga3dIsLegacyBackend(pThisCC));
1232
1233 /* No data follows */
1234 rc = pHlp->pfnSSMPutBool(pSSM, false);
1235 AssertRCReturn(rc, rc);
1236 }
1237 }
1238 }
1239 }
1240 }
1241 return VINF_SUCCESS;
1242}
1243
1244int vmsvga3dSaveShaderConst(PVMSVGA3DCONTEXT pContext, uint32_t reg, SVGA3dShaderType type, SVGA3dShaderConstType ctype,
1245 uint32_t val1, uint32_t val2, uint32_t val3, uint32_t val4)
1246{
1247 /* Choose a sane upper limit. */
1248 AssertReturn(reg < _32K, VERR_INVALID_PARAMETER);
1249
1250 if (type == SVGA3D_SHADERTYPE_VS)
1251 {
1252 if (pContext->state.cVertexShaderConst <= reg)
1253 {
1254 pContext->state.paVertexShaderConst = (PVMSVGASHADERCONST)RTMemRealloc(pContext->state.paVertexShaderConst, sizeof(VMSVGASHADERCONST) * (reg + 1));
1255 AssertReturn(pContext->state.paVertexShaderConst, VERR_NO_MEMORY);
1256 for (uint32_t i = pContext->state.cVertexShaderConst; i < reg + 1; i++)
1257 pContext->state.paVertexShaderConst[i].fValid = false;
1258 pContext->state.cVertexShaderConst = reg + 1;
1259 }
1260
1261 pContext->state.paVertexShaderConst[reg].fValid = true;
1262 pContext->state.paVertexShaderConst[reg].ctype = ctype;
1263 pContext->state.paVertexShaderConst[reg].value[0] = val1;
1264 pContext->state.paVertexShaderConst[reg].value[1] = val2;
1265 pContext->state.paVertexShaderConst[reg].value[2] = val3;
1266 pContext->state.paVertexShaderConst[reg].value[3] = val4;
1267 }
1268 else
1269 {
1270 Assert(type == SVGA3D_SHADERTYPE_PS);
1271 if (pContext->state.cPixelShaderConst <= reg)
1272 {
1273 pContext->state.paPixelShaderConst = (PVMSVGASHADERCONST)RTMemRealloc(pContext->state.paPixelShaderConst, sizeof(VMSVGASHADERCONST) * (reg + 1));
1274 AssertReturn(pContext->state.paPixelShaderConst, VERR_NO_MEMORY);
1275 for (uint32_t i = pContext->state.cPixelShaderConst; i < reg + 1; i++)
1276 pContext->state.paPixelShaderConst[i].fValid = false;
1277 pContext->state.cPixelShaderConst = reg + 1;
1278 }
1279
1280 pContext->state.paPixelShaderConst[reg].fValid = true;
1281 pContext->state.paPixelShaderConst[reg].ctype = ctype;
1282 pContext->state.paPixelShaderConst[reg].value[0] = val1;
1283 pContext->state.paPixelShaderConst[reg].value[1] = val2;
1284 pContext->state.paPixelShaderConst[reg].value[2] = val3;
1285 pContext->state.paPixelShaderConst[reg].value[3] = val4;
1286 }
1287
1288 return VINF_SUCCESS;
1289}
1290
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