VirtualBox

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

Last change on this file since 95685 was 95588, checked in by vboxsync, 2 years ago

Devices/Graphics: saved state fixes. bugref:9830

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 16.8 KB
Line 
1/* $Id: DevVGA-SVGA3d-dx-savedstate.cpp 95588 2022-07-11 12:40:55Z vboxsync $ */
2/** @file
3 * DevSVGA3d - VMWare SVGA device, 3D parts - DX backend saved state.
4 */
5
6/*
7 * Copyright (C) 2022 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_DEV_VMSVGA
23#include <VBox/AssertGuest.h>
24#include <iprt/errcore.h>
25#include <VBox/log.h>
26#include <VBox/vmm/pdmdev.h>
27
28#include <iprt/assert.h>
29#include <iprt/mem.h>
30
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#include "DevVGA-SVGA3d-internal.h"
39#include "DevVGA-SVGA-internal.h"
40
41/*
42 * Load
43 */
44
45static int vmsvga3dDXLoadSurface(PCPDMDEVHLPR3 pHlp, PVGASTATECC pThisCC, PSSMHANDLE pSSM)
46{
47 PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState;
48 int rc;
49
50 uint32_t sid;
51 rc = pHlp->pfnSSMGetU32(pSSM, &sid);
52 AssertRCReturn(rc, rc);
53
54 if (sid == SVGA3D_INVALID_ID)
55 return VINF_SUCCESS;
56
57 /* Define the surface. */
58 SVGAOTableSurfaceEntry entrySurface;
59 rc = vmsvgaR3OTableReadSurface(pThisCC->svga.pSvgaR3State, sid, &entrySurface);
60 AssertRCReturn(rc, rc);
61
62 /** @todo fAllocMipLevels=false and alloc miplevels if there is data to be loaded. */
63 rc = vmsvga3dSurfaceDefine(pThisCC, sid, entrySurface.surface1Flags, entrySurface.format,
64 entrySurface.multisampleCount, entrySurface.autogenFilter,
65 entrySurface.numMipLevels, &entrySurface.size,
66 entrySurface.arraySize,
67 /* fAllocMipLevels = */ true);
68 AssertRCReturn(rc, rc);
69
70 PVMSVGA3DSURFACE pSurface = p3dState->papSurfaces[sid];
71 AssertReturn(pSurface->id == sid, VERR_INTERNAL_ERROR);
72
73 /* Load the surface fields which are not part of SVGAOTableSurfaceEntry. */
74 pHlp->pfnSSMGetU32(pSSM, &pSurface->idAssociatedContext);
75
76 /* Load miplevels data to the surface buffers. */
77 for (uint32_t j = 0; j < pSurface->cLevels * pSurface->surfaceDesc.numArrayElements; j++)
78 {
79 PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->paMipmapLevels[j];
80
81 /* vmsvga3dSurfaceDefine already allocated the surface data buffer. */
82 Assert(pMipmapLevel->cbSurface);
83 AssertReturn(pMipmapLevel->pSurfaceData, VERR_INTERNAL_ERROR);
84
85 /* Fetch the data present boolean first. */
86 bool fDataPresent;
87 rc = pHlp->pfnSSMGetBool(pSSM, &fDataPresent);
88 AssertRCReturn(rc, rc);
89
90 if (fDataPresent)
91 {
92 rc = pHlp->pfnSSMGetMem(pSSM, pMipmapLevel->pSurfaceData, pMipmapLevel->cbSurface);
93 AssertRCReturn(rc, rc);
94
95 pMipmapLevel->fDirty = true;
96 pSurface->fDirty = true;
97 }
98 else
99 pMipmapLevel->fDirty = false;
100 }
101
102 return VINF_SUCCESS;
103}
104
105static int vmsvga3dDXLoadContext(PCPDMDEVHLPR3 pHlp, PVGASTATECC pThisCC, PSSMHANDLE pSSM)
106{
107 PVMSVGAR3STATE pSvgaR3State = pThisCC->svga.pSvgaR3State;
108 PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState;
109 uint32_t u32;
110 int rc;
111
112 uint32_t cid;
113 rc = pHlp->pfnSSMGetU32(pSSM, &cid);
114 AssertRCReturn(rc, rc);
115
116 if (cid == SVGA3D_INVALID_ID)
117 return VINF_SUCCESS;
118
119 /* Define the context. */
120 rc = vmsvga3dDXDefineContext(pThisCC, cid);
121 AssertRCReturn(rc, rc);
122
123 PVMSVGA3DDXCONTEXT pDXContext = p3dState->papDXContexts[cid];
124 AssertReturn(pDXContext->cid == cid, VERR_INTERNAL_ERROR);
125
126 /* Load the context. */
127 rc = pHlp->pfnSSMGetU32(pSSM, &u32);
128 AssertRCReturn(rc, rc);
129 AssertReturn(u32 == sizeof(SVGADXContextMobFormat), VERR_INVALID_STATE);
130
131 pHlp->pfnSSMGetMem(pSSM, &pDXContext->svgaDXContext, sizeof(SVGADXContextMobFormat));
132
133 rc = pHlp->pfnSSMGetU32(pSSM, &u32);
134 AssertLogRelRCReturn(rc, rc);
135 AssertReturn(u32 == RT_ELEMENTS(pDXContext->aCOTMobs), VERR_INVALID_STATE);
136
137 for (unsigned i = 0; i < RT_ELEMENTS(pDXContext->aCOTMobs); ++i)
138 {
139 rc = pHlp->pfnSSMGetU32(pSSM, &u32);
140 AssertLogRelRCReturn(rc, rc);
141 pDXContext->aCOTMobs[i] = vmsvgaR3MobGet(pSvgaR3State, u32);
142 Assert(pDXContext->aCOTMobs[i] || u32 == SVGA_ID_INVALID);
143 }
144
145 struct
146 {
147 SVGACOTableType COTableType;
148 uint32_t cbEntry;
149 uint32_t *pcEntries;
150 void **ppaEntries;
151 } cot[] =
152 {
153 {SVGA_COTABLE_RTVIEW, sizeof(SVGACOTableDXRTViewEntry), &pDXContext->cot.cRTView, (void **)&pDXContext->cot.paRTView},
154 {SVGA_COTABLE_DSVIEW, sizeof(SVGACOTableDXDSViewEntry), &pDXContext->cot.cDSView, (void **)&pDXContext->cot.paDSView},
155 {SVGA_COTABLE_SRVIEW, sizeof(SVGACOTableDXSRViewEntry), &pDXContext->cot.cSRView, (void **)&pDXContext->cot.paSRView},
156 {SVGA_COTABLE_ELEMENTLAYOUT, sizeof(SVGACOTableDXElementLayoutEntry), &pDXContext->cot.cElementLayout, (void **)&pDXContext->cot.paElementLayout},
157 {SVGA_COTABLE_BLENDSTATE, sizeof(SVGACOTableDXBlendStateEntry), &pDXContext->cot.cBlendState, (void **)&pDXContext->cot.paBlendState},
158 {SVGA_COTABLE_DEPTHSTENCIL, sizeof(SVGACOTableDXDepthStencilEntry), &pDXContext->cot.cDepthStencil, (void **)&pDXContext->cot.paDepthStencil},
159 {SVGA_COTABLE_RASTERIZERSTATE, sizeof(SVGACOTableDXRasterizerStateEntry), &pDXContext->cot.cRasterizerState, (void **)&pDXContext->cot.paRasterizerState},
160 {SVGA_COTABLE_SAMPLER, sizeof(SVGACOTableDXSamplerEntry), &pDXContext->cot.cSampler, (void **)&pDXContext->cot.paSampler},
161 {SVGA_COTABLE_STREAMOUTPUT, sizeof(SVGACOTableDXStreamOutputEntry), &pDXContext->cot.cStreamOutput, (void **)&pDXContext->cot.paStreamOutput},
162 {SVGA_COTABLE_DXQUERY, sizeof(SVGACOTableDXQueryEntry), &pDXContext->cot.cQuery, (void **)&pDXContext->cot.paQuery},
163 {SVGA_COTABLE_DXSHADER, sizeof(SVGACOTableDXShaderEntry), &pDXContext->cot.cShader, (void **)&pDXContext->cot.paShader},
164 {SVGA_COTABLE_UAVIEW, sizeof(SVGACOTableDXUAViewEntry), &pDXContext->cot.cUAView, (void **)&pDXContext->cot.paUAView},
165 };
166
167 AssertCompile(RT_ELEMENTS(cot) == RT_ELEMENTS(pDXContext->aCOTMobs));
168 for (unsigned i = 0; i < RT_ELEMENTS(cot); ++i)
169 {
170 uint32_t cEntries;
171 pHlp->pfnSSMGetU32(pSSM, &cEntries);
172 rc = pHlp->pfnSSMGetU32(pSSM, &u32);
173 AssertRCReturn(rc, rc);
174 AssertReturn(u32 == cot[i].cbEntry, VERR_INVALID_STATE);
175
176 *cot[i].pcEntries = cEntries;
177 *cot[i].ppaEntries = vmsvgaR3MobBackingStorePtr(pDXContext->aCOTMobs[cot[i].COTableType], 0);
178
179 if (cEntries)
180 {
181 rc = pSvgaR3State->pFuncsDX->pfnDXSetCOTable(pThisCC, pDXContext, cot[i].COTableType, cEntries);
182 AssertLogRelRCReturn(rc, rc);
183 }
184 }
185
186 rc = pSvgaR3State->pFuncsDX->pfnDXLoadState(pThisCC, pDXContext, pHlp, pSSM);
187 AssertRCReturn(rc, rc);
188
189 return VINF_SUCCESS;
190}
191
192int vmsvga3dDXLoadExec(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
193{
194 RT_NOREF(pThis, uPass);
195
196 if (uVersion < VGA_SAVEDSTATE_VERSION_VMSVGA_DX)
197 AssertFailedReturn(VERR_INVALID_STATE);
198
199 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
200 PVMSVGAR3STATE pSvgaR3State = pThisCC->svga.pSvgaR3State;
201 PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState;
202 int rc;
203
204 /*
205 * VMSVGA3DSTATE
206 */
207 pHlp->pfnSSMGetU32(pSSM, &p3dState->cSurfaces);
208 rc = pHlp->pfnSSMGetU32(pSSM, &p3dState->cDXContexts);
209 AssertRCReturn(rc, rc);
210
211 /*
212 * Surfaces
213 */
214 p3dState->papSurfaces = (PVMSVGA3DSURFACE *)RTMemAlloc(p3dState->cSurfaces * sizeof(PVMSVGA3DSURFACE));
215 AssertReturn(p3dState->papSurfaces, VERR_NO_MEMORY);
216 for (uint32_t i = 0; i < p3dState->cSurfaces; ++i)
217 {
218 p3dState->papSurfaces[i] = (PVMSVGA3DSURFACE)RTMemAllocZ(sizeof(VMSVGA3DSURFACE));
219 AssertPtrReturn(p3dState->papSurfaces[i], VERR_NO_MEMORY);
220 p3dState->papSurfaces[i]->id = SVGA3D_INVALID_ID;
221 }
222
223 for (uint32_t i = 0; i < p3dState->cSurfaces; ++i)
224 {
225 rc = vmsvga3dDXLoadSurface(pHlp, pThisCC, pSSM);
226 AssertRCReturn(rc, rc);
227 }
228
229 /*
230 * DX contexts
231 */
232 p3dState->papDXContexts = (PVMSVGA3DDXCONTEXT *)RTMemAlloc(p3dState->cDXContexts * sizeof(PVMSVGA3DDXCONTEXT));
233 AssertReturn(p3dState->papDXContexts, VERR_NO_MEMORY);
234 for (uint32_t i = 0; i < p3dState->cDXContexts; ++i)
235 {
236 p3dState->papDXContexts[i] = (PVMSVGA3DDXCONTEXT)RTMemAllocZ(sizeof(VMSVGA3DDXCONTEXT));
237 AssertPtrReturn(p3dState->papDXContexts[i], VERR_NO_MEMORY);
238 p3dState->papDXContexts[i]->cid = SVGA3D_INVALID_ID;
239 }
240
241 for (uint32_t i = 0; i < p3dState->cDXContexts; ++i)
242 {
243 rc = vmsvga3dDXLoadContext(pHlp, pThisCC, pSSM);
244 AssertRCReturn(rc, rc);
245 }
246
247 if (pSvgaR3State->idDXContextCurrent != SVGA_ID_INVALID)
248 vmsvga3dDXSwitchContext(pThisCC, pSvgaR3State->idDXContextCurrent);
249
250 return VINF_SUCCESS;
251}
252
253/*
254 * Save
255 */
256
257static int vmsvga3dDXSaveSurface(PCPDMDEVHLPR3 pHlp, PVGASTATECC pThisCC, PSSMHANDLE pSSM, PVMSVGA3DSURFACE pSurface)
258{
259 RT_NOREF(pThisCC);
260 int rc;
261
262 rc = pHlp->pfnSSMPutU32(pSSM, pSurface->id);
263 AssertRCReturn(rc, rc);
264
265 if (pSurface->id == SVGA3D_INVALID_ID)
266 return VINF_SUCCESS;
267
268 /* Save the surface fields which are not part of SVGAOTableSurfaceEntry. */
269 pHlp->pfnSSMPutU32(pSSM, pSurface->idAssociatedContext);
270
271 for (uint32_t iArray = 0; iArray < pSurface->surfaceDesc.numArrayElements; ++iArray)
272 {
273 for (uint32_t iMipmap = 0; iMipmap < pSurface->cLevels; ++iMipmap)
274 {
275 uint32_t idx = iMipmap + iArray * pSurface->cLevels;
276 PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->paMipmapLevels[idx];
277
278 if (!VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface))
279 {
280 if (pMipmapLevel->pSurfaceData)
281 {
282 /* Data follows */
283 rc = pHlp->pfnSSMPutBool(pSSM, true);
284 AssertRCReturn(rc, rc);
285
286 Assert(pMipmapLevel->cbSurface);
287 rc = pHlp->pfnSSMPutMem(pSSM, pMipmapLevel->pSurfaceData, pMipmapLevel->cbSurface);
288 AssertRCReturn(rc, rc);
289 }
290 else
291 {
292 /* No data follows */
293 rc = pHlp->pfnSSMPutBool(pSSM, false);
294 AssertRCReturn(rc, rc);
295 }
296 }
297 else
298 {
299 SVGA3dSurfaceImageId image;
300 image.sid = pSurface->id;
301 image.face = iArray;
302 image.mipmap = iMipmap;
303
304 VMSGA3D_BOX_DIMENSIONS dims;
305 rc = vmsvga3dGetBoxDimensions(pThisCC, &image, NULL, &dims);
306 AssertRCReturn(rc, rc);
307
308 VMSVGA3D_MAPPED_SURFACE map;
309 rc = vmsvga3dSurfaceMap(pThisCC, &image, NULL, VMSVGA3D_SURFACE_MAP_READ, &map);
310 if (RT_SUCCESS(rc))
311 {
312 /* Save mapped surface data. */
313 pHlp->pfnSSMPutBool(pSSM, true);
314 if (map.cbRow == map.cbRowPitch)
315 {
316 rc = pHlp->pfnSSMPutMem(pSSM, map.pvData, pMipmapLevel->cbSurface);
317 AssertRCReturn(rc, rc);
318 }
319 else
320 {
321 uint8_t *pu8Map = (uint8_t *)map.pvData;
322 for (uint32_t z = 0; z < map.box.d; ++z)
323 {
324 uint8_t *pu8MapPlane = pu8Map;
325 for (uint32_t y = 0; y < dims.cyBlocks; ++y)
326 {
327 rc = pHlp->pfnSSMPutMem(pSSM, pu8MapPlane, dims.cbRow);
328 AssertRCReturn(rc, rc);
329
330 pu8MapPlane += map.cbRowPitch;
331 }
332 pu8Map += map.cbDepthPitch;
333 }
334 }
335
336 vmsvga3dSurfaceUnmap(pThisCC, &image, &map, false);
337 }
338 else
339 {
340 AssertFailed();
341
342 /* No data follows */
343 rc = pHlp->pfnSSMPutBool(pSSM, false);
344 AssertRCReturn(rc, rc);
345 }
346 }
347 }
348 }
349
350 return VINF_SUCCESS;
351}
352
353static int vmsvga3dDXSaveContext(PCPDMDEVHLPR3 pHlp, PVGASTATECC pThisCC, PSSMHANDLE pSSM, PVMSVGA3DDXCONTEXT pDXContext)
354{
355 PVMSVGAR3STATE pSvgaR3State = pThisCC->svga.pSvgaR3State;
356 int rc;
357
358 rc = pHlp->pfnSSMPutU32(pSSM, pDXContext->cid);
359 AssertRCReturn(rc, rc);
360
361 if (pDXContext->cid == SVGA3D_INVALID_ID)
362 return VINF_SUCCESS;
363
364 /* Save the context. */
365 pHlp->pfnSSMPutU32(pSSM, sizeof(SVGADXContextMobFormat));
366 pHlp->pfnSSMPutMem(pSSM, &pDXContext->svgaDXContext, sizeof(SVGADXContextMobFormat));
367
368 rc = pHlp->pfnSSMPutU32(pSSM, RT_ELEMENTS(pDXContext->aCOTMobs));
369 AssertLogRelRCReturn(rc, rc);
370 for (unsigned i = 0; i < RT_ELEMENTS(pDXContext->aCOTMobs); ++i)
371 {
372 uint32_t const mobId = vmsvgaR3MobId(pDXContext->aCOTMobs[i]);
373 rc = pHlp->pfnSSMPutU32(pSSM, mobId);
374 AssertLogRelRCReturn(rc, rc);
375 }
376
377 struct
378 {
379 uint32_t cEntries;
380 uint32_t cbEntry;
381 void *paEntries;
382 } cot[] =
383 {
384 {pDXContext->cot.cRTView, sizeof(SVGACOTableDXRTViewEntry), pDXContext->cot.paRTView},
385 {pDXContext->cot.cDSView, sizeof(SVGACOTableDXDSViewEntry), pDXContext->cot.paDSView},
386 {pDXContext->cot.cSRView, sizeof(SVGACOTableDXSRViewEntry), pDXContext->cot.paSRView},
387 {pDXContext->cot.cElementLayout, sizeof(SVGACOTableDXElementLayoutEntry), pDXContext->cot.paElementLayout},
388 {pDXContext->cot.cBlendState, sizeof(SVGACOTableDXBlendStateEntry), pDXContext->cot.paBlendState},
389 {pDXContext->cot.cDepthStencil, sizeof(SVGACOTableDXDepthStencilEntry), pDXContext->cot.paDepthStencil},
390 {pDXContext->cot.cRasterizerState, sizeof(SVGACOTableDXRasterizerStateEntry), pDXContext->cot.paRasterizerState},
391 {pDXContext->cot.cSampler, sizeof(SVGACOTableDXSamplerEntry), pDXContext->cot.paSampler},
392 {pDXContext->cot.cStreamOutput, sizeof(SVGACOTableDXStreamOutputEntry), pDXContext->cot.paStreamOutput},
393 {pDXContext->cot.cQuery, sizeof(SVGACOTableDXQueryEntry), pDXContext->cot.paQuery},
394 {pDXContext->cot.cShader, sizeof(SVGACOTableDXShaderEntry), pDXContext->cot.paShader},
395 {pDXContext->cot.cUAView, sizeof(SVGACOTableDXUAViewEntry), pDXContext->cot.paUAView},
396 };
397
398 AssertCompile(RT_ELEMENTS(cot) == RT_ELEMENTS(pDXContext->aCOTMobs));
399 for (unsigned i = 0; i < RT_ELEMENTS(cot); ++i)
400 {
401 pHlp->pfnSSMPutU32(pSSM, cot[i].cEntries);
402 rc = pHlp->pfnSSMPutU32(pSSM, cot[i].cbEntry);
403 AssertLogRelRCReturn(rc, rc);
404 }
405
406 rc = pSvgaR3State->pFuncsDX->pfnDXSaveState(pThisCC, pDXContext, pHlp, pSSM);
407 AssertRCReturn(rc, rc);
408
409 return VINF_SUCCESS;
410}
411
412int vmsvga3dDXSaveExec(PPDMDEVINS pDevIns, PVGASTATECC pThisCC, PSSMHANDLE pSSM)
413{
414 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
415 PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState;
416 int rc;
417
418 /*
419 * VMSVGA3DSTATE
420 */
421 pHlp->pfnSSMPutU32(pSSM, p3dState->cSurfaces);
422 rc = pHlp->pfnSSMPutU32(pSSM, p3dState->cDXContexts);
423 AssertRCReturn(rc, rc);
424
425 /*
426 * Surfaces
427 */
428 for (uint32_t sid = 0; sid < p3dState->cSurfaces; ++sid)
429 {
430 rc = vmsvga3dDXSaveSurface(pHlp, pThisCC, pSSM, p3dState->papSurfaces[sid]);
431 AssertRCReturn(rc, rc);
432 }
433
434 /*
435 * DX contexts
436 */
437 for (uint32_t cid = 0; cid < p3dState->cDXContexts; ++cid)
438 {
439 rc = vmsvga3dDXSaveContext(pHlp, pThisCC, pSSM, p3dState->papDXContexts[cid]);
440 AssertRCReturn(rc, rc);
441 }
442
443 return VINF_SUCCESS;
444}
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