VirtualBox

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

Last change on this file since 86651 was 82968, checked in by vboxsync, 5 years ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 42.9 KB
Line 
1/* $Id: DevVGA-SVGA3d-savedstate.cpp 82968 2020-02-04 10:35:17Z vboxsync $ */
2/** @file
3 * DevSVGA3d - VMWare SVGA device, 3D parts - Saved state and assocated stuff.
4 */
5
6/*
7 * Copyright (C) 2013-2020 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
149int vmsvga3dLoadExec(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
150{
151 RT_NOREF(pDevIns, pThis, uPass);
152 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
153 AssertReturn(pState, VERR_NO_MEMORY);
154 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
155 int rc;
156 uint32_t cContexts, cSurfaces;
157 LogFlow(("vmsvga3dLoadExec:\n"));
158
159#ifndef RT_OS_DARWIN /** @todo r=bird: this is normally done on the EMT, so for DARWIN we do that when loading saved state too now. See DevVGA-SVGA.cpp */
160 /* Must initialize now as the recreation calls below rely on an initialized 3d subsystem. */
161 vmsvga3dPowerOn(pDevIns, pThis, pThisCC);
162#endif
163
164 /* Get the generic 3d state first. */
165 rc = pHlp->pfnSSMGetStructEx(pSSM, pState, sizeof(*pState), 0, g_aVMSVGA3DSTATEFields, NULL);
166 AssertRCReturn(rc, rc);
167
168 cContexts = pState->cContexts;
169 cSurfaces = pState->cSurfaces;
170 pState->cContexts = 0;
171 pState->cSurfaces = 0;
172
173 /* Fetch all active contexts. */
174 for (uint32_t i = 0; i < cContexts; i++)
175 {
176 PVMSVGA3DCONTEXT pContext;
177 uint32_t cid;
178
179 /* Get the context id */
180 rc = pHlp->pfnSSMGetU32(pSSM, &cid);
181 AssertRCReturn(rc, rc);
182
183 if (cid != SVGA3D_INVALID_ID)
184 {
185 uint32_t cPixelShaderConst, cVertexShaderConst, cPixelShaders, cVertexShaders;
186 LogFlow(("vmsvga3dLoadExec: Loading cid=%#x\n", cid));
187
188#ifdef VMSVGA3D_OPENGL
189 if (cid == VMSVGA3D_SHARED_CTX_ID)
190 {
191 i--; /* Not included in cContexts. */
192 pContext = &pState->SharedCtx;
193 if (pContext->id != VMSVGA3D_SHARED_CTX_ID)
194 {
195 rc = vmsvga3dContextDefineOgl(pThisCC, VMSVGA3D_SHARED_CTX_ID, VMSVGA3D_DEF_CTX_F_SHARED_CTX);
196 AssertRCReturn(rc, rc);
197 }
198 }
199 else
200#endif
201 {
202 rc = vmsvga3dContextDefine(pThisCC, cid);
203 AssertRCReturn(rc, rc);
204
205 pContext = pState->papContexts[i];
206 }
207 AssertReturn(pContext->id == cid, VERR_INTERNAL_ERROR);
208
209 rc = pHlp->pfnSSMGetStructEx(pSSM, pContext, sizeof(*pContext), 0, g_aVMSVGA3DCONTEXTFields, NULL);
210 AssertRCReturn(rc, rc);
211
212 cPixelShaders = pContext->cPixelShaders;
213 cVertexShaders = pContext->cVertexShaders;
214 cPixelShaderConst = pContext->state.cPixelShaderConst;
215 cVertexShaderConst = pContext->state.cVertexShaderConst;
216 pContext->cPixelShaders = 0;
217 pContext->cVertexShaders = 0;
218 pContext->state.cPixelShaderConst = 0;
219 pContext->state.cVertexShaderConst = 0;
220
221 /* Fetch all pixel shaders. */
222 for (uint32_t j = 0; j < cPixelShaders; j++)
223 {
224 VMSVGA3DSHADER shader;
225 uint32_t shid;
226
227 /* Fetch the id first. */
228 rc = pHlp->pfnSSMGetU32(pSSM, &shid);
229 AssertRCReturn(rc, rc);
230
231 if (shid != SVGA3D_INVALID_ID)
232 {
233 uint32_t *pData;
234
235 /* Fetch a copy of the shader struct. */
236 rc = pHlp->pfnSSMGetStructEx(pSSM, &shader, sizeof(shader), 0, g_aVMSVGA3DSHADERFields, NULL);
237 AssertRCReturn(rc, rc);
238
239 pData = (uint32_t *)RTMemAlloc(shader.cbData);
240 AssertReturn(pData, VERR_NO_MEMORY);
241
242 rc = pHlp->pfnSSMGetMem(pSSM, pData, shader.cbData);
243 AssertRCReturn(rc, rc);
244
245 rc = vmsvga3dShaderDefine(pThisCC, cid, shid, shader.type, shader.cbData, pData);
246 AssertRCReturn(rc, rc);
247
248 RTMemFree(pData);
249 }
250 }
251
252 /* Fetch all vertex shaders. */
253 for (uint32_t j = 0; j < cVertexShaders; j++)
254 {
255 VMSVGA3DSHADER shader;
256 uint32_t shid;
257
258 /* Fetch the id first. */
259 rc = pHlp->pfnSSMGetU32(pSSM, &shid);
260 AssertRCReturn(rc, rc);
261
262 if (shid != SVGA3D_INVALID_ID)
263 {
264 uint32_t *pData;
265
266 /* Fetch a copy of the shader struct. */
267 rc = pHlp->pfnSSMGetStructEx(pSSM, &shader, sizeof(shader), 0, g_aVMSVGA3DSHADERFields, NULL);
268 AssertRCReturn(rc, rc);
269
270 pData = (uint32_t *)RTMemAlloc(shader.cbData);
271 AssertReturn(pData, VERR_NO_MEMORY);
272
273 rc = pHlp->pfnSSMGetMem(pSSM, pData, shader.cbData);
274 AssertRCReturn(rc, rc);
275
276 rc = vmsvga3dShaderDefine(pThisCC, cid, shid, shader.type, shader.cbData, pData);
277 AssertRCReturn(rc, rc);
278
279 RTMemFree(pData);
280 }
281 }
282
283 /* Fetch pixel shader constants. */
284 for (uint32_t j = 0; j < cPixelShaderConst; j++)
285 {
286 VMSVGASHADERCONST ShaderConst;
287
288 rc = pHlp->pfnSSMGetStructEx(pSSM, &ShaderConst, sizeof(ShaderConst), 0, g_aVMSVGASHADERCONSTFields, NULL);
289 AssertRCReturn(rc, rc);
290
291 if (ShaderConst.fValid)
292 {
293 rc = vmsvga3dShaderSetConst(pThisCC, cid, j, SVGA3D_SHADERTYPE_PS, ShaderConst.ctype, 1, ShaderConst.value);
294 AssertRCReturn(rc, rc);
295 }
296 }
297
298 /* Fetch vertex shader constants. */
299 for (uint32_t j = 0; j < cVertexShaderConst; j++)
300 {
301 VMSVGASHADERCONST ShaderConst;
302
303 rc = pHlp->pfnSSMGetStructEx(pSSM, &ShaderConst, sizeof(ShaderConst), 0, g_aVMSVGASHADERCONSTFields, NULL);
304 AssertRCReturn(rc, rc);
305
306 if (ShaderConst.fValid)
307 {
308 rc = vmsvga3dShaderSetConst(pThisCC, cid, j, SVGA3D_SHADERTYPE_VS, ShaderConst.ctype, 1, ShaderConst.value);
309 AssertRCReturn(rc, rc);
310 }
311 }
312
313 if (uVersion >= VGA_SAVEDSTATE_VERSION_VMSVGA_TEX_STAGES)
314 {
315 /* Load texture stage and samplers state. */
316
317 /* Number of stages/samplers. */
318 uint32_t cStages;
319 rc = pHlp->pfnSSMGetU32(pSSM, &cStages);
320 AssertRCReturn(rc, rc);
321
322 /* Number of states. */
323 uint32_t cTextureStates;
324 rc = pHlp->pfnSSMGetU32(pSSM, &cTextureStates);
325 AssertRCReturn(rc, rc);
326
327 for (uint32_t iStage = 0; iStage < cStages; ++iStage)
328 {
329 for (uint32_t j = 0; j < cTextureStates; ++j)
330 {
331 SVGA3dTextureState textureState;
332 pHlp->pfnSSMGetU32(pSSM, &textureState.stage);
333 uint32_t u32Name;
334 pHlp->pfnSSMGetU32(pSSM, &u32Name);
335 textureState.name = (SVGA3dTextureStateName)u32Name;
336 rc = pHlp->pfnSSMGetU32(pSSM, &textureState.value);
337 AssertRCReturn(rc, rc);
338
339 if ( iStage < RT_ELEMENTS(pContext->state.aTextureStates)
340 && j < RT_ELEMENTS(pContext->state.aTextureStates[0]))
341 {
342 pContext->state.aTextureStates[iStage][j] = textureState;
343 }
344 }
345 }
346 }
347
348 if (uVersion >= VGA_SAVEDSTATE_VERSION_VMSVGA)
349 {
350 VMSVGA3DQUERY query;
351 RT_ZERO(query);
352
353 rc = pHlp->pfnSSMGetStructEx(pSSM, &query, sizeof(query), 0, g_aVMSVGA3DQUERYFields, NULL);
354 AssertRCReturn(rc, rc);
355
356 switch (query.enmQueryState)
357 {
358 case VMSVGA3DQUERYSTATE_BUILDING:
359 /* Start collecting data. */
360 vmsvga3dQueryBegin(pThisCC, cid, SVGA3D_QUERYTYPE_OCCLUSION);
361 /* Partial result. */
362 pContext->occlusion.u32QueryResult = query.u32QueryResult;
363 break;
364
365 case VMSVGA3DQUERYSTATE_ISSUED:
366 /* Guest ended the query but did not read result. Result is restored. */
367 query.enmQueryState = VMSVGA3DQUERYSTATE_SIGNALED;
368 RT_FALL_THRU();
369 case VMSVGA3DQUERYSTATE_SIGNALED:
370 /* Create the query object. */
371 vmsvga3dOcclusionQueryCreate(pState, pContext);
372
373 /* Update result and state. */
374 pContext->occlusion.enmQueryState = query.enmQueryState;
375 pContext->occlusion.u32QueryResult = query.u32QueryResult;
376 break;
377
378 default:
379 AssertFailed();
380 RT_FALL_THRU();
381 case VMSVGA3DQUERYSTATE_NULL:
382 RT_ZERO(pContext->occlusion);
383 break;
384 }
385 }
386 }
387 }
388
389#ifdef VMSVGA3D_OPENGL
390 /* Make the shared context the current one. */
391 if (pState->SharedCtx.id == VMSVGA3D_SHARED_CTX_ID)
392 VMSVGA3D_SET_CURRENT_CONTEXT(pState, &pState->SharedCtx);
393#endif
394
395 /* Fetch all surfaces. */
396 for (uint32_t i = 0; i < cSurfaces; i++)
397 {
398 uint32_t sid;
399
400 /* Fetch the id first. */
401 rc = pHlp->pfnSSMGetU32(pSSM, &sid);
402 AssertRCReturn(rc, rc);
403
404 if (sid != SVGA3D_INVALID_ID)
405 {
406 VMSVGA3DSURFACE surface;
407 LogFlow(("vmsvga3dLoadExec: Loading sid=%#x\n", sid));
408
409 /* Fetch the surface structure first. */
410 rc = pHlp->pfnSSMGetStructEx(pSSM, &surface, sizeof(surface), 0, g_aVMSVGA3DSURFACEFields, NULL);
411 AssertRCReturn(rc, rc);
412
413 {
414 uint32_t cMipLevels = surface.faces[0].numMipLevels * surface.cFaces;
415 PVMSVGA3DMIPMAPLEVEL pMipmapLevel = (PVMSVGA3DMIPMAPLEVEL)RTMemAlloc(cMipLevels * sizeof(VMSVGA3DMIPMAPLEVEL));
416 AssertReturn(pMipmapLevel, VERR_NO_MEMORY);
417 SVGA3dSize *pMipmapLevelSize = (SVGA3dSize *)RTMemAlloc(cMipLevels * sizeof(SVGA3dSize));
418 AssertReturn(pMipmapLevelSize, VERR_NO_MEMORY);
419
420 /* Load the mip map level info. */
421 for (uint32_t face=0; face < surface.cFaces; face++)
422 {
423 for (uint32_t j = 0; j < surface.faces[0].numMipLevels; j++)
424 {
425 uint32_t idx = j + face * surface.faces[0].numMipLevels;
426 /* Load the mip map level struct. */
427 rc = pHlp->pfnSSMGetStructEx(pSSM, &pMipmapLevel[idx], sizeof(pMipmapLevel[idx]), 0,
428 g_aVMSVGA3DMIPMAPLEVELFields, NULL);
429 AssertRCReturn(rc, rc);
430
431 pMipmapLevelSize[idx] = pMipmapLevel[idx].mipmapSize;
432 }
433 }
434
435 rc = vmsvga3dSurfaceDefine(pThisCC, sid, surface.surfaceFlags, surface.format, surface.faces,
436 surface.multiSampleCount, surface.autogenFilter, cMipLevels, pMipmapLevelSize);
437 AssertRCReturn(rc, rc);
438
439 RTMemFree(pMipmapLevelSize);
440 RTMemFree(pMipmapLevel);
441 }
442
443 PVMSVGA3DSURFACE pSurface = pState->papSurfaces[sid];
444 Assert(pSurface->id == sid);
445
446 pSurface->fDirty = false;
447
448 /* Load the mip map level data. */
449 for (uint32_t j = 0; j < pSurface->faces[0].numMipLevels * pSurface->cFaces; j++)
450 {
451 PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->paMipmapLevels[j];
452 bool fDataPresent = false;
453
454 /* vmsvga3dSurfaceDefine already allocated the surface data buffer. */
455 Assert(pMipmapLevel->cbSurface);
456 AssertReturn(pMipmapLevel->pSurfaceData, VERR_INTERNAL_ERROR);
457
458 /* Fetch the data present boolean first. */
459 rc = pHlp->pfnSSMGetBool(pSSM, &fDataPresent);
460 AssertRCReturn(rc, rc);
461
462 Log(("Surface sid=%u: load mipmap level %d with %x bytes data (present=%d).\n", sid, j, pMipmapLevel->cbSurface, fDataPresent));
463
464 if (fDataPresent)
465 {
466 rc = pHlp->pfnSSMGetMem(pSSM, pMipmapLevel->pSurfaceData, pMipmapLevel->cbSurface);
467 AssertRCReturn(rc, rc);
468 pMipmapLevel->fDirty = true;
469 pSurface->fDirty = true;
470 }
471 else
472 {
473 pMipmapLevel->fDirty = false;
474 }
475 }
476 }
477 }
478
479#ifdef VMSVGA3D_OPENGL
480 /* Reinitialize the shared context. */
481 LogFlow(("vmsvga3dLoadExec: pState->SharedCtx.id=%#x\n", pState->SharedCtx.id));
482 if (pState->SharedCtx.id == VMSVGA3D_SHARED_CTX_ID)
483 {
484 rc = vmsvga3dLoadReinitContext(pThisCC, &pState->SharedCtx);
485 AssertRCReturn(rc, rc);
486 }
487#endif
488
489 /* Reinitialize all active contexts. */
490 for (uint32_t i = 0; i < pState->cContexts; i++)
491 {
492 PVMSVGA3DCONTEXT pContext = pState->papContexts[i];
493 if (pContext->id != SVGA3D_INVALID_ID)
494 {
495 rc = vmsvga3dLoadReinitContext(pThisCC, pContext);
496 AssertRCReturn(rc, rc);
497 }
498 }
499
500 LogFlow(("vmsvga3dLoadExec: return success\n"));
501 return VINF_SUCCESS;
502}
503
504
505static int vmsvga3dSaveContext(PCPDMDEVHLPR3 pHlp, PVGASTATECC pThisCC, PSSMHANDLE pSSM, PVMSVGA3DCONTEXT pContext)
506{
507 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
508 uint32_t cid = pContext->id;
509
510 /* Save the id first. */
511 int rc = pHlp->pfnSSMPutU32(pSSM, cid);
512 AssertRCReturn(rc, rc);
513
514 if (cid != SVGA3D_INVALID_ID)
515 {
516 /* Save a copy of the context structure first. */
517 rc = pHlp->pfnSSMPutStructEx(pSSM, pContext, sizeof(*pContext), 0, g_aVMSVGA3DCONTEXTFields, NULL);
518 AssertRCReturn(rc, rc);
519
520 /* Save all pixel shaders. */
521 for (uint32_t j = 0; j < pContext->cPixelShaders; j++)
522 {
523 PVMSVGA3DSHADER pShader = &pContext->paPixelShader[j];
524
525 /* Save the id first. */
526 rc = pHlp->pfnSSMPutU32(pSSM, pShader->id);
527 AssertRCReturn(rc, rc);
528
529 if (pShader->id != SVGA3D_INVALID_ID)
530 {
531 uint32_t cbData = pShader->cbData;
532
533 /* Save a copy of the shader struct. */
534 rc = pHlp->pfnSSMPutStructEx(pSSM, pShader, sizeof(*pShader), 0, g_aVMSVGA3DSHADERFields, NULL);
535 AssertRCReturn(rc, rc);
536
537 Log(("Save pixelshader shid=%d with %x bytes code.\n", pShader->id, cbData));
538 rc = pHlp->pfnSSMPutMem(pSSM, pShader->pShaderProgram, cbData);
539 AssertRCReturn(rc, rc);
540 }
541 }
542
543 /* Save all vertex shaders. */
544 for (uint32_t j = 0; j < pContext->cVertexShaders; j++)
545 {
546 PVMSVGA3DSHADER pShader = &pContext->paVertexShader[j];
547
548 /* Save the id first. */
549 rc = pHlp->pfnSSMPutU32(pSSM, pShader->id);
550 AssertRCReturn(rc, rc);
551
552 if (pShader->id != SVGA3D_INVALID_ID)
553 {
554 uint32_t cbData = pShader->cbData;
555
556 /* Save a copy of the shader struct. */
557 rc = pHlp->pfnSSMPutStructEx(pSSM, pShader, sizeof(*pShader), 0, g_aVMSVGA3DSHADERFields, NULL);
558 AssertRCReturn(rc, rc);
559
560 Log(("Save vertex shader shid=%d with %x bytes code.\n", pShader->id, cbData));
561 /* Fetch the shader code and save it. */
562 rc = pHlp->pfnSSMPutMem(pSSM, pShader->pShaderProgram, cbData);
563 AssertRCReturn(rc, rc);
564 }
565 }
566
567 /* Save pixel shader constants. */
568 for (uint32_t j = 0; j < pContext->state.cPixelShaderConst; j++)
569 {
570 rc = pHlp->pfnSSMPutStructEx(pSSM, &pContext->state.paPixelShaderConst[j], sizeof(pContext->state.paPixelShaderConst[j]), 0, g_aVMSVGASHADERCONSTFields, NULL);
571 AssertRCReturn(rc, rc);
572 }
573
574 /* Save vertex shader constants. */
575 for (uint32_t j = 0; j < pContext->state.cVertexShaderConst; j++)
576 {
577 rc = pHlp->pfnSSMPutStructEx(pSSM, &pContext->state.paVertexShaderConst[j], sizeof(pContext->state.paVertexShaderConst[j]), 0, g_aVMSVGASHADERCONSTFields, NULL);
578 AssertRCReturn(rc, rc);
579 }
580
581 /* Save texture stage and samplers state. */
582
583 /* Number of stages/samplers. */
584 rc = pHlp->pfnSSMPutU32(pSSM, RT_ELEMENTS(pContext->state.aTextureStates));
585 AssertRCReturn(rc, rc);
586
587 /* Number of texture states. */
588 rc = pHlp->pfnSSMPutU32(pSSM, RT_ELEMENTS(pContext->state.aTextureStates[0]));
589 AssertRCReturn(rc, rc);
590
591 for (uint32_t iStage = 0; iStage < RT_ELEMENTS(pContext->state.aTextureStates); ++iStage)
592 {
593 for (uint32_t j = 0; j < RT_ELEMENTS(pContext->state.aTextureStates[0]); ++j)
594 {
595 SVGA3dTextureState *pTextureState = &pContext->state.aTextureStates[iStage][j];
596
597 pHlp->pfnSSMPutU32(pSSM, pTextureState->stage);
598 pHlp->pfnSSMPutU32(pSSM, pTextureState->name);
599 rc = pHlp->pfnSSMPutU32(pSSM, pTextureState->value);
600 AssertRCReturn(rc, rc);
601 }
602 }
603
604 /* Occlusion query. */
605 if (!VMSVGA3DQUERY_EXISTS(&pContext->occlusion))
606 {
607 pContext->occlusion.enmQueryState = VMSVGA3DQUERYSTATE_NULL;
608 }
609
610 switch (pContext->occlusion.enmQueryState)
611 {
612 case VMSVGA3DQUERYSTATE_BUILDING:
613 /* Stop collecting data. Fetch partial result. Save result. */
614 vmsvga3dOcclusionQueryEnd(pState, pContext);
615 RT_FALL_THRU();
616 case VMSVGA3DQUERYSTATE_ISSUED:
617 /* Fetch result. Save result. */
618 pContext->occlusion.u32QueryResult = 0;
619 vmsvga3dOcclusionQueryGetData(pState, pContext, &pContext->occlusion.u32QueryResult);
620 RT_FALL_THRU();
621 case VMSVGA3DQUERYSTATE_SIGNALED:
622 /* Save result. Nothing to do here. */
623 break;
624
625 default:
626 AssertFailed();
627 RT_FALL_THRU();
628 case VMSVGA3DQUERYSTATE_NULL:
629 pContext->occlusion.enmQueryState = VMSVGA3DQUERYSTATE_NULL;
630 pContext->occlusion.u32QueryResult = 0;
631 break;
632 }
633
634 rc = pHlp->pfnSSMPutStructEx(pSSM, &pContext->occlusion, sizeof(pContext->occlusion), 0, g_aVMSVGA3DQUERYFields, NULL);
635 AssertRCReturn(rc, rc);
636 }
637
638 return VINF_SUCCESS;
639}
640
641int vmsvga3dSaveExec(PPDMDEVINS pDevIns, PVGASTATECC pThisCC, PSSMHANDLE pSSM)
642{
643 PVMSVGA3DSTATE pState = pThisCC->svga.p3dState;
644 AssertReturn(pState, VERR_NO_MEMORY);
645 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
646 int rc;
647
648 /* Save a copy of the generic 3d state first. */
649 rc = pHlp->pfnSSMPutStructEx(pSSM, pState, sizeof(*pState), 0, g_aVMSVGA3DSTATEFields, NULL);
650 AssertRCReturn(rc, rc);
651
652#ifdef VMSVGA3D_OPENGL
653 /* Save the shared context. */
654 if (pState->SharedCtx.id == VMSVGA3D_SHARED_CTX_ID)
655 {
656 rc = vmsvga3dSaveContext(pHlp, pThisCC, pSSM, &pState->SharedCtx);
657 AssertRCReturn(rc, rc);
658 }
659#endif
660
661 /* Save all active contexts. */
662 for (uint32_t i = 0; i < pState->cContexts; i++)
663 {
664 rc = vmsvga3dSaveContext(pHlp, pThisCC, pSSM, pState->papContexts[i]);
665 AssertRCReturn(rc, rc);
666 }
667
668 /* Save all active surfaces. */
669 for (uint32_t sid = 0; sid < pState->cSurfaces; sid++)
670 {
671 PVMSVGA3DSURFACE pSurface = pState->papSurfaces[sid];
672
673 /* Save the id first. */
674 rc = pHlp->pfnSSMPutU32(pSSM, pSurface->id);
675 AssertRCReturn(rc, rc);
676
677 if (pSurface->id != SVGA3D_INVALID_ID)
678 {
679 /* Save a copy of the surface structure first. */
680 rc = pHlp->pfnSSMPutStructEx(pSSM, pSurface, sizeof(*pSurface), 0, g_aVMSVGA3DSURFACEFields, NULL);
681 AssertRCReturn(rc, rc);
682
683 /* Save the mip map level info. */
684 for (uint32_t face=0; face < pSurface->cFaces; face++)
685 {
686 for (uint32_t i = 0; i < pSurface->faces[0].numMipLevels; i++)
687 {
688 uint32_t idx = i + face * pSurface->faces[0].numMipLevels;
689 PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->paMipmapLevels[idx];
690
691 /* Save a copy of the mip map level struct. */
692 rc = pHlp->pfnSSMPutStructEx(pSSM, pMipmapLevel, sizeof(*pMipmapLevel), 0, g_aVMSVGA3DMIPMAPLEVELFields, NULL);
693 AssertRCReturn(rc, rc);
694 }
695 }
696
697 /* Save the mip map level data. */
698 for (uint32_t face=0; face < pSurface->cFaces; face++)
699 {
700 for (uint32_t i = 0; i < pSurface->faces[0].numMipLevels; i++)
701 {
702 uint32_t idx = i + face * pSurface->faces[0].numMipLevels;
703 PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->paMipmapLevels[idx];
704
705 Log(("Surface sid=%u: save mipmap level %d with %x bytes data.\n", sid, i, pMipmapLevel->cbSurface));
706
707 if (!VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface))
708 {
709 if (pMipmapLevel->fDirty)
710 {
711 /* Data follows */
712 rc = pHlp->pfnSSMPutBool(pSSM, true);
713 AssertRCReturn(rc, rc);
714
715 Assert(pMipmapLevel->cbSurface);
716 rc = pHlp->pfnSSMPutMem(pSSM, pMipmapLevel->pSurfaceData, pMipmapLevel->cbSurface);
717 AssertRCReturn(rc, rc);
718 }
719 else
720 {
721 /* No data follows */
722 rc = pHlp->pfnSSMPutBool(pSSM, false);
723 AssertRCReturn(rc, rc);
724 }
725 }
726 else
727 {
728#ifdef VMSVGA3D_DIRECT3D
729 void *pData;
730 bool fRenderTargetTexture = false;
731 bool fTexture = false;
732 bool fSkipSave = false;
733 HRESULT hr;
734
735 Assert(pMipmapLevel->cbSurface);
736 pData = RTMemAllocZ(pMipmapLevel->cbSurface);
737 AssertReturn(pData, VERR_NO_MEMORY);
738
739 switch (pSurface->enmD3DResType)
740 {
741 case VMSVGA3D_D3DRESTYPE_CUBE_TEXTURE:
742 case VMSVGA3D_D3DRESTYPE_VOLUME_TEXTURE:
743 AssertFailed(); /// @todo
744 fSkipSave = true;
745 break;
746 case VMSVGA3D_D3DRESTYPE_SURFACE:
747 case VMSVGA3D_D3DRESTYPE_TEXTURE:
748 {
749 if (pSurface->surfaceFlags & SVGA3D_SURFACE_HINT_DEPTHSTENCIL)
750 {
751 /** @todo unable to easily fetch depth surface data in d3d 9 */
752 fSkipSave = true;
753 break;
754 }
755
756 fTexture = (pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_TEXTURE);
757 fRenderTargetTexture = fTexture && (pSurface->surfaceFlags & SVGA3D_SURFACE_HINT_RENDERTARGET);
758
759 D3DLOCKED_RECT LockedRect;
760
761 if (fTexture)
762 {
763 if (pSurface->bounce.pTexture)
764 {
765 if ( !pSurface->fDirty
766 && fRenderTargetTexture
767 && i == 0 /* only the first time */)
768 {
769 IDirect3DSurface9 *pSrc, *pDest;
770
771 /** @todo stricter checks for associated context */
772 uint32_t cid = pSurface->idAssociatedContext;
773
774 PVMSVGA3DCONTEXT pContext;
775 rc = vmsvga3dContextFromCid(pState, cid, &pContext);
776 AssertRCReturn(rc, rc);
777
778 hr = pSurface->bounce.pTexture->GetSurfaceLevel(i, &pDest);
779 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: GetSurfaceLevel failed with %x\n", hr), VERR_INTERNAL_ERROR);
780
781 hr = pSurface->u.pTexture->GetSurfaceLevel(i, &pSrc);
782 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: GetSurfaceLevel failed with %x\n", hr), VERR_INTERNAL_ERROR);
783
784 hr = pContext->pDevice->GetRenderTargetData(pSrc, pDest);
785 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: GetRenderTargetData failed with %x\n", hr), VERR_INTERNAL_ERROR);
786
787 pSrc->Release();
788 pDest->Release();
789 }
790
791 hr = pSurface->bounce.pTexture->LockRect(i, /* texture level */
792 &LockedRect,
793 NULL,
794 D3DLOCK_READONLY);
795 }
796 else
797 hr = pSurface->u.pTexture->LockRect(i, /* texture level */
798 &LockedRect,
799 NULL,
800 D3DLOCK_READONLY);
801 }
802 else
803 hr = pSurface->u.pSurface->LockRect(&LockedRect,
804 NULL,
805 D3DLOCK_READONLY);
806 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: LockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
807
808 /* Copy the data one line at a time in case the internal pitch is different. */
809 for (uint32_t j = 0; j < pMipmapLevel->cBlocksY; ++j)
810 {
811 uint8_t *pu8Dst = (uint8_t *)pData + j * pMipmapLevel->cbSurfacePitch;
812 const uint8_t *pu8Src = (uint8_t *)LockedRect.pBits + j * LockedRect.Pitch;
813 memcpy(pu8Dst, pu8Src, pMipmapLevel->cbSurfacePitch);
814 }
815
816 if (fTexture)
817 {
818 if (pSurface->bounce.pTexture)
819 {
820 hr = pSurface->bounce.pTexture->UnlockRect(i);
821 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: UnlockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
822 }
823 else
824 hr = pSurface->u.pTexture->UnlockRect(i);
825 }
826 else
827 hr = pSurface->u.pSurface->UnlockRect();
828 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: UnlockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
829 break;
830 }
831
832 case VMSVGA3D_D3DRESTYPE_VERTEX_BUFFER:
833 case VMSVGA3D_D3DRESTYPE_INDEX_BUFFER:
834 {
835 /* Current type of the buffer. */
836 const bool fVertex = (pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_VERTEX_BUFFER);
837
838 uint8_t *pD3DData;
839
840 if (fVertex)
841 hr = pSurface->u.pVertexBuffer->Lock(0, 0, (void **)&pD3DData, D3DLOCK_READONLY);
842 else
843 hr = pSurface->u.pIndexBuffer->Lock(0, 0, (void **)&pD3DData, D3DLOCK_READONLY);
844 AssertMsg(hr == D3D_OK, ("vmsvga3dSaveExec: Lock %s failed with %x\n", (fVertex) ? "vertex" : "index", hr));
845
846 memcpy(pData, pD3DData, pMipmapLevel->cbSurface);
847
848 if (fVertex)
849 hr = pSurface->u.pVertexBuffer->Unlock();
850 else
851 hr = pSurface->u.pIndexBuffer->Unlock();
852 AssertMsg(hr == D3D_OK, ("vmsvga3dSaveExec: Unlock %s failed with %x\n", (fVertex) ? "vertex" : "index", hr));
853 break;
854 }
855
856 default:
857 AssertFailed();
858 break;
859 }
860
861 if (!fSkipSave)
862 {
863 /* Data follows */
864 rc = pHlp->pfnSSMPutBool(pSSM, true);
865 AssertRCReturn(rc, rc);
866
867 /* And write the surface data. */
868 rc = pHlp->pfnSSMPutMem(pSSM, pData, pMipmapLevel->cbSurface);
869 AssertRCReturn(rc, rc);
870 }
871 else
872 {
873 /* No data follows */
874 rc = pHlp->pfnSSMPutBool(pSSM, false);
875 AssertRCReturn(rc, rc);
876 }
877
878 RTMemFree(pData);
879#elif defined(VMSVGA3D_OPENGL)
880 void *pData = NULL;
881
882 PVMSVGA3DCONTEXT pContext = &pState->SharedCtx;
883 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
884
885 Assert(pMipmapLevel->cbSurface);
886
887 switch (pSurface->enmOGLResType)
888 {
889 default:
890 AssertFailed();
891 RT_FALL_THRU();
892 case VMSVGA3D_OGLRESTYPE_RENDERBUFFER:
893 /** @todo fetch data from the renderbuffer. Not used currently. */
894 /* No data follows */
895 rc = pHlp->pfnSSMPutBool(pSSM, false);
896 AssertRCReturn(rc, rc);
897 break;
898
899 case VMSVGA3D_OGLRESTYPE_TEXTURE:
900 {
901 GLint activeTexture;
902
903 pData = RTMemAllocZ(pMipmapLevel->cbSurface);
904 AssertReturn(pData, VERR_NO_MEMORY);
905
906 glGetIntegerv(GL_TEXTURE_BINDING_2D, &activeTexture);
907 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
908
909 glBindTexture(GL_TEXTURE_2D, pSurface->oglId.texture);
910 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
911
912 /* Set row length and alignment of the output data. */
913 VMSVGAPACKPARAMS SavedParams;
914 vmsvga3dOglSetPackParams(pState, pContext, pSurface, &SavedParams);
915
916 glGetTexImage(GL_TEXTURE_2D,
917 i,
918 pSurface->formatGL,
919 pSurface->typeGL,
920 pData);
921 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
922
923 vmsvga3dOglRestorePackParams(pState, pContext, pSurface, &SavedParams);
924
925 /* Data follows */
926 rc = pHlp->pfnSSMPutBool(pSSM, true);
927 AssertRCReturn(rc, rc);
928
929 /* And write the surface data. */
930 rc = pHlp->pfnSSMPutMem(pSSM, pData, pMipmapLevel->cbSurface);
931 AssertRCReturn(rc, rc);
932
933 /* Restore the old active texture. */
934 glBindTexture(GL_TEXTURE_2D, activeTexture);
935 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
936 break;
937 }
938
939 case VMSVGA3D_OGLRESTYPE_BUFFER:
940 {
941 uint8_t *pBufferData;
942
943 pState->ext.glBindBuffer(GL_ARRAY_BUFFER, pSurface->oglId.buffer);
944 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
945
946 pBufferData = (uint8_t *)pState->ext.glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
947 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
948 Assert(pBufferData);
949
950 /* Data follows */
951 rc = pHlp->pfnSSMPutBool(pSSM, true);
952 AssertRCReturn(rc, rc);
953
954 /* And write the surface data. */
955 rc = pHlp->pfnSSMPutMem(pSSM, pBufferData, pMipmapLevel->cbSurface);
956 AssertRCReturn(rc, rc);
957
958 pState->ext.glUnmapBuffer(GL_ARRAY_BUFFER);
959 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
960
961 pState->ext.glBindBuffer(GL_ARRAY_BUFFER, 0);
962 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
963
964 }
965 }
966 if (pData)
967 RTMemFree(pData);
968#else
969#error "Unexpected 3d backend"
970#endif
971 }
972 }
973 }
974 }
975 }
976 return VINF_SUCCESS;
977}
978
979int vmsvga3dSaveShaderConst(PVMSVGA3DCONTEXT pContext, uint32_t reg, SVGA3dShaderType type, SVGA3dShaderConstType ctype,
980 uint32_t val1, uint32_t val2, uint32_t val3, uint32_t val4)
981{
982 /* Choose a sane upper limit. */
983 AssertReturn(reg < _32K, VERR_INVALID_PARAMETER);
984
985 if (type == SVGA3D_SHADERTYPE_VS)
986 {
987 if (pContext->state.cVertexShaderConst <= reg)
988 {
989 pContext->state.paVertexShaderConst = (PVMSVGASHADERCONST)RTMemRealloc(pContext->state.paVertexShaderConst, sizeof(VMSVGASHADERCONST) * (reg + 1));
990 AssertReturn(pContext->state.paVertexShaderConst, VERR_NO_MEMORY);
991 for (uint32_t i = pContext->state.cVertexShaderConst; i < reg + 1; i++)
992 pContext->state.paVertexShaderConst[i].fValid = false;
993 pContext->state.cVertexShaderConst = reg + 1;
994 }
995
996 pContext->state.paVertexShaderConst[reg].fValid = true;
997 pContext->state.paVertexShaderConst[reg].ctype = ctype;
998 pContext->state.paVertexShaderConst[reg].value[0] = val1;
999 pContext->state.paVertexShaderConst[reg].value[1] = val2;
1000 pContext->state.paVertexShaderConst[reg].value[2] = val3;
1001 pContext->state.paVertexShaderConst[reg].value[3] = val4;
1002 }
1003 else
1004 {
1005 Assert(type == SVGA3D_SHADERTYPE_PS);
1006 if (pContext->state.cPixelShaderConst <= reg)
1007 {
1008 pContext->state.paPixelShaderConst = (PVMSVGASHADERCONST)RTMemRealloc(pContext->state.paPixelShaderConst, sizeof(VMSVGASHADERCONST) * (reg + 1));
1009 AssertReturn(pContext->state.paPixelShaderConst, VERR_NO_MEMORY);
1010 for (uint32_t i = pContext->state.cPixelShaderConst; i < reg + 1; i++)
1011 pContext->state.paPixelShaderConst[i].fValid = false;
1012 pContext->state.cPixelShaderConst = reg + 1;
1013 }
1014
1015 pContext->state.paPixelShaderConst[reg].fValid = true;
1016 pContext->state.paPixelShaderConst[reg].ctype = ctype;
1017 pContext->state.paPixelShaderConst[reg].value[0] = val1;
1018 pContext->state.paPixelShaderConst[reg].value[1] = val2;
1019 pContext->state.paPixelShaderConst[reg].value[2] = val3;
1020 pContext->state.paPixelShaderConst[reg].value[3] = val4;
1021 }
1022
1023 return VINF_SUCCESS;
1024}
1025
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