VirtualBox

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

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

DevVGA: Darwin fixes. bugref:9218

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 42.7 KB
Line 
1/* $Id: DevVGA-SVGA3d-savedstate.cpp 82110 2019-11-22 20:40:12Z vboxsync $ */
2/** @file
3 * DevSVGA3d - VMWare SVGA device, 3D parts - Saved state and assocated stuff.
4 */
5
6/*
7 * Copyright (C) 2013-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#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 pThis The VMSVGA device state.
48 * @param pContext The freshly loaded context to reinitialize.
49 */
50static int vmsvga3dLoadReinitContext(PVGASTATE pThis, 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(pThis, 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(pThis, 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(pThis, 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(pThis, 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(pThis, cid, j, &pContext->state.aLightData[j].data);
110 if (pContext->state.aLightData[j].fEnabled)
111 vmsvga3dSetLightEnabled(pThis, 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(pThis, 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(pThis, cid, (SVGA3dFace)j, &pContext->state.aMaterial[j].material);
131 }
132 }
133
134 if (pContext->state.u32UpdateFlags & VMSVGA3D_UPDATE_SCISSORRECT)
135 vmsvga3dSetScissorRect(pThis, cid, &pContext->state.RectScissor);
136 if (pContext->state.u32UpdateFlags & VMSVGA3D_UPDATE_ZRANGE)
137 vmsvga3dSetZRange(pThis, cid, pContext->state.zRange);
138 if (pContext->state.u32UpdateFlags & VMSVGA3D_UPDATE_VIEWPORT)
139 vmsvga3dSetViewPort(pThis, cid, &pContext->state.RectViewPort);
140 if (pContext->state.u32UpdateFlags & VMSVGA3D_UPDATE_VERTEXSHADER)
141 vmsvga3dShaderSet(pThis, pContext, cid, SVGA3D_SHADERTYPE_VS, pContext->state.shidVertex);
142 if (pContext->state.u32UpdateFlags & VMSVGA3D_UPDATE_PIXELSHADER)
143 vmsvga3dShaderSet(pThis, 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, pThisCC, uPass);
152 PVMSVGA3DSTATE pState = pThis->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(pThis, VMSVGA3D_SHARED_CTX_ID, VMSVGA3D_DEF_CTX_F_SHARED_CTX);
196 AssertRCReturn(rc, rc);
197 }
198 }
199 else
200#endif
201 {
202 rc = vmsvga3dContextDefine(pThis, 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(pThis, 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(pThis, 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(pThis, 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(pThis, 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(pThis, 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, g_aVMSVGA3DMIPMAPLEVELFields, NULL);
428 AssertRCReturn(rc, rc);
429
430 pMipmapLevelSize[idx] = pMipmapLevel[idx].mipmapSize;
431 }
432 }
433
434 rc = vmsvga3dSurfaceDefine(pThis, sid, surface.surfaceFlags, surface.format, surface.faces, surface.multiSampleCount, surface.autogenFilter, cMipLevels, pMipmapLevelSize);
435 AssertRCReturn(rc, rc);
436
437 RTMemFree(pMipmapLevelSize);
438 RTMemFree(pMipmapLevel);
439 }
440
441 PVMSVGA3DSURFACE pSurface = pState->papSurfaces[sid];
442 Assert(pSurface->id == sid);
443
444 pSurface->fDirty = false;
445
446 /* Load the mip map level data. */
447 for (uint32_t j = 0; j < pSurface->faces[0].numMipLevels * pSurface->cFaces; j++)
448 {
449 PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->paMipmapLevels[j];
450 bool fDataPresent = false;
451
452 /* vmsvga3dSurfaceDefine already allocated the surface data buffer. */
453 Assert(pMipmapLevel->cbSurface);
454 AssertReturn(pMipmapLevel->pSurfaceData, VERR_INTERNAL_ERROR);
455
456 /* Fetch the data present boolean first. */
457 rc = pHlp->pfnSSMGetBool(pSSM, &fDataPresent);
458 AssertRCReturn(rc, rc);
459
460 Log(("Surface sid=%u: load mipmap level %d with %x bytes data (present=%d).\n", sid, j, pMipmapLevel->cbSurface, fDataPresent));
461
462 if (fDataPresent)
463 {
464 rc = pHlp->pfnSSMGetMem(pSSM, pMipmapLevel->pSurfaceData, pMipmapLevel->cbSurface);
465 AssertRCReturn(rc, rc);
466 pMipmapLevel->fDirty = true;
467 pSurface->fDirty = true;
468 }
469 else
470 {
471 pMipmapLevel->fDirty = false;
472 }
473 }
474 }
475 }
476
477#ifdef VMSVGA3D_OPENGL
478 /* Reinitialize the shared context. */
479 LogFlow(("vmsvga3dLoadExec: pState->SharedCtx.id=%#x\n", pState->SharedCtx.id));
480 if (pState->SharedCtx.id == VMSVGA3D_SHARED_CTX_ID)
481 {
482 rc = vmsvga3dLoadReinitContext(pThis, &pState->SharedCtx);
483 AssertRCReturn(rc, rc);
484 }
485#endif
486
487 /* Reinitialize all active contexts. */
488 for (uint32_t i = 0; i < pState->cContexts; i++)
489 {
490 PVMSVGA3DCONTEXT pContext = pState->papContexts[i];
491 if (pContext->id != SVGA3D_INVALID_ID)
492 {
493 rc = vmsvga3dLoadReinitContext(pThis, pContext);
494 AssertRCReturn(rc, rc);
495 }
496 }
497
498 LogFlow(("vmsvga3dLoadExec: return success\n"));
499 return VINF_SUCCESS;
500}
501
502
503static int vmsvga3dSaveContext(PCPDMDEVHLPR3 pHlp, PVGASTATE pThis, PSSMHANDLE pSSM, PVMSVGA3DCONTEXT pContext)
504{
505 PVMSVGA3DSTATE pState = pThis->svga.p3dState;
506 uint32_t cid = pContext->id;
507
508 /* Save the id first. */
509 int rc = pHlp->pfnSSMPutU32(pSSM, cid);
510 AssertRCReturn(rc, rc);
511
512 if (cid != SVGA3D_INVALID_ID)
513 {
514 /* Save a copy of the context structure first. */
515 rc = pHlp->pfnSSMPutStructEx(pSSM, pContext, sizeof(*pContext), 0, g_aVMSVGA3DCONTEXTFields, NULL);
516 AssertRCReturn(rc, rc);
517
518 /* Save all pixel shaders. */
519 for (uint32_t j = 0; j < pContext->cPixelShaders; j++)
520 {
521 PVMSVGA3DSHADER pShader = &pContext->paPixelShader[j];
522
523 /* Save the id first. */
524 rc = pHlp->pfnSSMPutU32(pSSM, pShader->id);
525 AssertRCReturn(rc, rc);
526
527 if (pShader->id != SVGA3D_INVALID_ID)
528 {
529 uint32_t cbData = pShader->cbData;
530
531 /* Save a copy of the shader struct. */
532 rc = pHlp->pfnSSMPutStructEx(pSSM, pShader, sizeof(*pShader), 0, g_aVMSVGA3DSHADERFields, NULL);
533 AssertRCReturn(rc, rc);
534
535 Log(("Save pixelshader shid=%d with %x bytes code.\n", pShader->id, cbData));
536 rc = pHlp->pfnSSMPutMem(pSSM, pShader->pShaderProgram, cbData);
537 AssertRCReturn(rc, rc);
538 }
539 }
540
541 /* Save all vertex shaders. */
542 for (uint32_t j = 0; j < pContext->cVertexShaders; j++)
543 {
544 PVMSVGA3DSHADER pShader = &pContext->paVertexShader[j];
545
546 /* Save the id first. */
547 rc = pHlp->pfnSSMPutU32(pSSM, pShader->id);
548 AssertRCReturn(rc, rc);
549
550 if (pShader->id != SVGA3D_INVALID_ID)
551 {
552 uint32_t cbData = pShader->cbData;
553
554 /* Save a copy of the shader struct. */
555 rc = pHlp->pfnSSMPutStructEx(pSSM, pShader, sizeof(*pShader), 0, g_aVMSVGA3DSHADERFields, NULL);
556 AssertRCReturn(rc, rc);
557
558 Log(("Save vertex shader shid=%d with %x bytes code.\n", pShader->id, cbData));
559 /* Fetch the shader code and save it. */
560 rc = pHlp->pfnSSMPutMem(pSSM, pShader->pShaderProgram, cbData);
561 AssertRCReturn(rc, rc);
562 }
563 }
564
565 /* Save pixel shader constants. */
566 for (uint32_t j = 0; j < pContext->state.cPixelShaderConst; j++)
567 {
568 rc = pHlp->pfnSSMPutStructEx(pSSM, &pContext->state.paPixelShaderConst[j], sizeof(pContext->state.paPixelShaderConst[j]), 0, g_aVMSVGASHADERCONSTFields, NULL);
569 AssertRCReturn(rc, rc);
570 }
571
572 /* Save vertex shader constants. */
573 for (uint32_t j = 0; j < pContext->state.cVertexShaderConst; j++)
574 {
575 rc = pHlp->pfnSSMPutStructEx(pSSM, &pContext->state.paVertexShaderConst[j], sizeof(pContext->state.paVertexShaderConst[j]), 0, g_aVMSVGASHADERCONSTFields, NULL);
576 AssertRCReturn(rc, rc);
577 }
578
579 /* Save texture stage and samplers state. */
580
581 /* Number of stages/samplers. */
582 rc = pHlp->pfnSSMPutU32(pSSM, RT_ELEMENTS(pContext->state.aTextureStates));
583 AssertRCReturn(rc, rc);
584
585 /* Number of texture states. */
586 rc = pHlp->pfnSSMPutU32(pSSM, RT_ELEMENTS(pContext->state.aTextureStates[0]));
587 AssertRCReturn(rc, rc);
588
589 for (uint32_t iStage = 0; iStage < RT_ELEMENTS(pContext->state.aTextureStates); ++iStage)
590 {
591 for (uint32_t j = 0; j < RT_ELEMENTS(pContext->state.aTextureStates[0]); ++j)
592 {
593 SVGA3dTextureState *pTextureState = &pContext->state.aTextureStates[iStage][j];
594
595 pHlp->pfnSSMPutU32(pSSM, pTextureState->stage);
596 pHlp->pfnSSMPutU32(pSSM, pTextureState->name);
597 rc = pHlp->pfnSSMPutU32(pSSM, pTextureState->value);
598 AssertRCReturn(rc, rc);
599 }
600 }
601
602 /* Occlusion query. */
603 if (!VMSVGA3DQUERY_EXISTS(&pContext->occlusion))
604 {
605 pContext->occlusion.enmQueryState = VMSVGA3DQUERYSTATE_NULL;
606 }
607
608 switch (pContext->occlusion.enmQueryState)
609 {
610 case VMSVGA3DQUERYSTATE_BUILDING:
611 /* Stop collecting data. Fetch partial result. Save result. */
612 vmsvga3dOcclusionQueryEnd(pState, pContext);
613 RT_FALL_THRU();
614 case VMSVGA3DQUERYSTATE_ISSUED:
615 /* Fetch result. Save result. */
616 pContext->occlusion.u32QueryResult = 0;
617 vmsvga3dOcclusionQueryGetData(pState, pContext, &pContext->occlusion.u32QueryResult);
618 RT_FALL_THRU();
619 case VMSVGA3DQUERYSTATE_SIGNALED:
620 /* Save result. Nothing to do here. */
621 break;
622
623 default:
624 AssertFailed();
625 RT_FALL_THRU();
626 case VMSVGA3DQUERYSTATE_NULL:
627 pContext->occlusion.enmQueryState = VMSVGA3DQUERYSTATE_NULL;
628 pContext->occlusion.u32QueryResult = 0;
629 break;
630 }
631
632 rc = pHlp->pfnSSMPutStructEx(pSSM, &pContext->occlusion, sizeof(pContext->occlusion), 0, g_aVMSVGA3DQUERYFields, NULL);
633 AssertRCReturn(rc, rc);
634 }
635
636 return VINF_SUCCESS;
637}
638
639int vmsvga3dSaveExec(PPDMDEVINS pDevIns, PVGASTATE pThis, PSSMHANDLE pSSM)
640{
641 PVMSVGA3DSTATE pState = pThis->svga.p3dState;
642 AssertReturn(pState, VERR_NO_MEMORY);
643 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
644 int rc;
645
646 /* Save a copy of the generic 3d state first. */
647 rc = pHlp->pfnSSMPutStructEx(pSSM, pState, sizeof(*pState), 0, g_aVMSVGA3DSTATEFields, NULL);
648 AssertRCReturn(rc, rc);
649
650#ifdef VMSVGA3D_OPENGL
651 /* Save the shared context. */
652 if (pState->SharedCtx.id == VMSVGA3D_SHARED_CTX_ID)
653 {
654 rc = vmsvga3dSaveContext(pHlp, pThis, pSSM, &pState->SharedCtx);
655 AssertRCReturn(rc, rc);
656 }
657#endif
658
659 /* Save all active contexts. */
660 for (uint32_t i = 0; i < pState->cContexts; i++)
661 {
662 rc = vmsvga3dSaveContext(pHlp, pThis, pSSM, pState->papContexts[i]);
663 AssertRCReturn(rc, rc);
664 }
665
666 /* Save all active surfaces. */
667 for (uint32_t sid = 0; sid < pState->cSurfaces; sid++)
668 {
669 PVMSVGA3DSURFACE pSurface = pState->papSurfaces[sid];
670
671 /* Save the id first. */
672 rc = pHlp->pfnSSMPutU32(pSSM, pSurface->id);
673 AssertRCReturn(rc, rc);
674
675 if (pSurface->id != SVGA3D_INVALID_ID)
676 {
677 /* Save a copy of the surface structure first. */
678 rc = pHlp->pfnSSMPutStructEx(pSSM, pSurface, sizeof(*pSurface), 0, g_aVMSVGA3DSURFACEFields, NULL);
679 AssertRCReturn(rc, rc);
680
681 /* Save the mip map level info. */
682 for (uint32_t face=0; face < pSurface->cFaces; face++)
683 {
684 for (uint32_t i = 0; i < pSurface->faces[0].numMipLevels; i++)
685 {
686 uint32_t idx = i + face * pSurface->faces[0].numMipLevels;
687 PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->paMipmapLevels[idx];
688
689 /* Save a copy of the mip map level struct. */
690 rc = pHlp->pfnSSMPutStructEx(pSSM, pMipmapLevel, sizeof(*pMipmapLevel), 0, g_aVMSVGA3DMIPMAPLEVELFields, NULL);
691 AssertRCReturn(rc, rc);
692 }
693 }
694
695 /* Save the mip map level data. */
696 for (uint32_t face=0; face < pSurface->cFaces; face++)
697 {
698 for (uint32_t i = 0; i < pSurface->faces[0].numMipLevels; i++)
699 {
700 uint32_t idx = i + face * pSurface->faces[0].numMipLevels;
701 PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->paMipmapLevels[idx];
702
703 Log(("Surface sid=%u: save mipmap level %d with %x bytes data.\n", sid, i, pMipmapLevel->cbSurface));
704
705 if (!VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface))
706 {
707 if (pMipmapLevel->fDirty)
708 {
709 /* Data follows */
710 rc = pHlp->pfnSSMPutBool(pSSM, true);
711 AssertRCReturn(rc, rc);
712
713 Assert(pMipmapLevel->cbSurface);
714 rc = pHlp->pfnSSMPutMem(pSSM, pMipmapLevel->pSurfaceData, pMipmapLevel->cbSurface);
715 AssertRCReturn(rc, rc);
716 }
717 else
718 {
719 /* No data follows */
720 rc = pHlp->pfnSSMPutBool(pSSM, false);
721 AssertRCReturn(rc, rc);
722 }
723 }
724 else
725 {
726#ifdef VMSVGA3D_DIRECT3D
727 void *pData;
728 bool fRenderTargetTexture = false;
729 bool fTexture = false;
730 bool fSkipSave = false;
731 HRESULT hr;
732
733 Assert(pMipmapLevel->cbSurface);
734 pData = RTMemAllocZ(pMipmapLevel->cbSurface);
735 AssertReturn(pData, VERR_NO_MEMORY);
736
737 switch (pSurface->enmD3DResType)
738 {
739 case VMSVGA3D_D3DRESTYPE_CUBE_TEXTURE:
740 case VMSVGA3D_D3DRESTYPE_VOLUME_TEXTURE:
741 AssertFailed(); /// @todo
742 fSkipSave = true;
743 break;
744 case VMSVGA3D_D3DRESTYPE_SURFACE:
745 case VMSVGA3D_D3DRESTYPE_TEXTURE:
746 {
747 if (pSurface->surfaceFlags & SVGA3D_SURFACE_HINT_DEPTHSTENCIL)
748 {
749 /** @todo unable to easily fetch depth surface data in d3d 9 */
750 fSkipSave = true;
751 break;
752 }
753
754 fTexture = (pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_TEXTURE);
755 fRenderTargetTexture = fTexture && (pSurface->surfaceFlags & SVGA3D_SURFACE_HINT_RENDERTARGET);
756
757 D3DLOCKED_RECT LockedRect;
758
759 if (fTexture)
760 {
761 if (pSurface->bounce.pTexture)
762 {
763 if ( !pSurface->fDirty
764 && fRenderTargetTexture
765 && i == 0 /* only the first time */)
766 {
767 IDirect3DSurface9 *pSrc, *pDest;
768
769 /** @todo stricter checks for associated context */
770 uint32_t cid = pSurface->idAssociatedContext;
771
772 PVMSVGA3DCONTEXT pContext;
773 rc = vmsvga3dContextFromCid(pState, cid, &pContext);
774 AssertRCReturn(rc, rc);
775
776 hr = pSurface->bounce.pTexture->GetSurfaceLevel(i, &pDest);
777 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: GetSurfaceLevel failed with %x\n", hr), VERR_INTERNAL_ERROR);
778
779 hr = pSurface->u.pTexture->GetSurfaceLevel(i, &pSrc);
780 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: GetSurfaceLevel failed with %x\n", hr), VERR_INTERNAL_ERROR);
781
782 hr = pContext->pDevice->GetRenderTargetData(pSrc, pDest);
783 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: GetRenderTargetData failed with %x\n", hr), VERR_INTERNAL_ERROR);
784
785 pSrc->Release();
786 pDest->Release();
787 }
788
789 hr = pSurface->bounce.pTexture->LockRect(i, /* texture level */
790 &LockedRect,
791 NULL,
792 D3DLOCK_READONLY);
793 }
794 else
795 hr = pSurface->u.pTexture->LockRect(i, /* texture level */
796 &LockedRect,
797 NULL,
798 D3DLOCK_READONLY);
799 }
800 else
801 hr = pSurface->u.pSurface->LockRect(&LockedRect,
802 NULL,
803 D3DLOCK_READONLY);
804 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: LockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
805
806 /* Copy the data one line at a time in case the internal pitch is different. */
807 for (uint32_t j = 0; j < pMipmapLevel->cBlocksY; ++j)
808 {
809 uint8_t *pu8Dst = (uint8_t *)pData + j * pMipmapLevel->cbSurfacePitch;
810 const uint8_t *pu8Src = (uint8_t *)LockedRect.pBits + j * LockedRect.Pitch;
811 memcpy(pu8Dst, pu8Src, pMipmapLevel->cbSurfacePitch);
812 }
813
814 if (fTexture)
815 {
816 if (pSurface->bounce.pTexture)
817 {
818 hr = pSurface->bounce.pTexture->UnlockRect(i);
819 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: UnlockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
820 }
821 else
822 hr = pSurface->u.pTexture->UnlockRect(i);
823 }
824 else
825 hr = pSurface->u.pSurface->UnlockRect();
826 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: UnlockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
827 break;
828 }
829
830 case VMSVGA3D_D3DRESTYPE_VERTEX_BUFFER:
831 case VMSVGA3D_D3DRESTYPE_INDEX_BUFFER:
832 {
833 /* Current type of the buffer. */
834 const bool fVertex = (pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_VERTEX_BUFFER);
835
836 uint8_t *pD3DData;
837
838 if (fVertex)
839 hr = pSurface->u.pVertexBuffer->Lock(0, 0, (void **)&pD3DData, D3DLOCK_READONLY);
840 else
841 hr = pSurface->u.pIndexBuffer->Lock(0, 0, (void **)&pD3DData, D3DLOCK_READONLY);
842 AssertMsg(hr == D3D_OK, ("vmsvga3dSaveExec: Lock %s failed with %x\n", (fVertex) ? "vertex" : "index", hr));
843
844 memcpy(pData, pD3DData, pMipmapLevel->cbSurface);
845
846 if (fVertex)
847 hr = pSurface->u.pVertexBuffer->Unlock();
848 else
849 hr = pSurface->u.pIndexBuffer->Unlock();
850 AssertMsg(hr == D3D_OK, ("vmsvga3dSaveExec: Unlock %s failed with %x\n", (fVertex) ? "vertex" : "index", hr));
851 break;
852 }
853
854 default:
855 AssertFailed();
856 break;
857 }
858
859 if (!fSkipSave)
860 {
861 /* Data follows */
862 rc = pHlp->pfnSSMPutBool(pSSM, true);
863 AssertRCReturn(rc, rc);
864
865 /* And write the surface data. */
866 rc = pHlp->pfnSSMPutMem(pSSM, pData, pMipmapLevel->cbSurface);
867 AssertRCReturn(rc, rc);
868 }
869 else
870 {
871 /* No data follows */
872 rc = pHlp->pfnSSMPutBool(pSSM, false);
873 AssertRCReturn(rc, rc);
874 }
875
876 RTMemFree(pData);
877#elif defined(VMSVGA3D_OPENGL)
878 void *pData = NULL;
879
880 PVMSVGA3DCONTEXT pContext = &pState->SharedCtx;
881 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
882
883 Assert(pMipmapLevel->cbSurface);
884
885 switch (pSurface->enmOGLResType)
886 {
887 default:
888 AssertFailed();
889 RT_FALL_THRU();
890 case VMSVGA3D_OGLRESTYPE_RENDERBUFFER:
891 /** @todo fetch data from the renderbuffer. Not used currently. */
892 /* No data follows */
893 rc = pHlp->pfnSSMPutBool(pSSM, false);
894 AssertRCReturn(rc, rc);
895 break;
896
897 case VMSVGA3D_OGLRESTYPE_TEXTURE:
898 {
899 GLint activeTexture;
900
901 pData = RTMemAllocZ(pMipmapLevel->cbSurface);
902 AssertReturn(pData, VERR_NO_MEMORY);
903
904 glGetIntegerv(GL_TEXTURE_BINDING_2D, &activeTexture);
905 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
906
907 glBindTexture(GL_TEXTURE_2D, pSurface->oglId.texture);
908 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
909
910 /* Set row length and alignment of the output data. */
911 VMSVGAPACKPARAMS SavedParams;
912 vmsvga3dOglSetPackParams(pState, pContext, pSurface, &SavedParams);
913
914 glGetTexImage(GL_TEXTURE_2D,
915 i,
916 pSurface->formatGL,
917 pSurface->typeGL,
918 pData);
919 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
920
921 vmsvga3dOglRestorePackParams(pState, pContext, pSurface, &SavedParams);
922
923 /* Data follows */
924 rc = pHlp->pfnSSMPutBool(pSSM, true);
925 AssertRCReturn(rc, rc);
926
927 /* And write the surface data. */
928 rc = pHlp->pfnSSMPutMem(pSSM, pData, pMipmapLevel->cbSurface);
929 AssertRCReturn(rc, rc);
930
931 /* Restore the old active texture. */
932 glBindTexture(GL_TEXTURE_2D, activeTexture);
933 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
934 break;
935 }
936
937 case VMSVGA3D_OGLRESTYPE_BUFFER:
938 {
939 uint8_t *pBufferData;
940
941 pState->ext.glBindBuffer(GL_ARRAY_BUFFER, pSurface->oglId.buffer);
942 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
943
944 pBufferData = (uint8_t *)pState->ext.glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
945 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
946 Assert(pBufferData);
947
948 /* Data follows */
949 rc = pHlp->pfnSSMPutBool(pSSM, true);
950 AssertRCReturn(rc, rc);
951
952 /* And write the surface data. */
953 rc = pHlp->pfnSSMPutMem(pSSM, pBufferData, pMipmapLevel->cbSurface);
954 AssertRCReturn(rc, rc);
955
956 pState->ext.glUnmapBuffer(GL_ARRAY_BUFFER);
957 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
958
959 pState->ext.glBindBuffer(GL_ARRAY_BUFFER, 0);
960 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
961
962 }
963 }
964 if (pData)
965 RTMemFree(pData);
966#else
967#error "Unexpected 3d backend"
968#endif
969 }
970 }
971 }
972 }
973 }
974 return VINF_SUCCESS;
975}
976
977int vmsvga3dSaveShaderConst(PVMSVGA3DCONTEXT pContext, uint32_t reg, SVGA3dShaderType type, SVGA3dShaderConstType ctype,
978 uint32_t val1, uint32_t val2, uint32_t val3, uint32_t val4)
979{
980 /* Choose a sane upper limit. */
981 AssertReturn(reg < _32K, VERR_INVALID_PARAMETER);
982
983 if (type == SVGA3D_SHADERTYPE_VS)
984 {
985 if (pContext->state.cVertexShaderConst <= reg)
986 {
987 pContext->state.paVertexShaderConst = (PVMSVGASHADERCONST)RTMemRealloc(pContext->state.paVertexShaderConst, sizeof(VMSVGASHADERCONST) * (reg + 1));
988 AssertReturn(pContext->state.paVertexShaderConst, VERR_NO_MEMORY);
989 for (uint32_t i = pContext->state.cVertexShaderConst; i < reg + 1; i++)
990 pContext->state.paVertexShaderConst[i].fValid = false;
991 pContext->state.cVertexShaderConst = reg + 1;
992 }
993
994 pContext->state.paVertexShaderConst[reg].fValid = true;
995 pContext->state.paVertexShaderConst[reg].ctype = ctype;
996 pContext->state.paVertexShaderConst[reg].value[0] = val1;
997 pContext->state.paVertexShaderConst[reg].value[1] = val2;
998 pContext->state.paVertexShaderConst[reg].value[2] = val3;
999 pContext->state.paVertexShaderConst[reg].value[3] = val4;
1000 }
1001 else
1002 {
1003 Assert(type == SVGA3D_SHADERTYPE_PS);
1004 if (pContext->state.cPixelShaderConst <= reg)
1005 {
1006 pContext->state.paPixelShaderConst = (PVMSVGASHADERCONST)RTMemRealloc(pContext->state.paPixelShaderConst, sizeof(VMSVGASHADERCONST) * (reg + 1));
1007 AssertReturn(pContext->state.paPixelShaderConst, VERR_NO_MEMORY);
1008 for (uint32_t i = pContext->state.cPixelShaderConst; i < reg + 1; i++)
1009 pContext->state.paPixelShaderConst[i].fValid = false;
1010 pContext->state.cPixelShaderConst = reg + 1;
1011 }
1012
1013 pContext->state.paPixelShaderConst[reg].fValid = true;
1014 pContext->state.paPixelShaderConst[reg].ctype = ctype;
1015 pContext->state.paPixelShaderConst[reg].value[0] = val1;
1016 pContext->state.paPixelShaderConst[reg].value[1] = val2;
1017 pContext->state.paPixelShaderConst[reg].value[2] = val3;
1018 pContext->state.paPixelShaderConst[reg].value[3] = val4;
1019 }
1020
1021 return VINF_SUCCESS;
1022}
1023
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette