VirtualBox

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

Last change on this file since 94205 was 94205, checked in by vboxsync, 3 years ago

Devices/Graphics: saved state: 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 94205 2022-03-12 20:12:21Z 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 /* fAllocMipLevels = */ true);
67 AssertRCReturn(rc, rc);
68
69 PVMSVGA3DSURFACE pSurface = p3dState->papSurfaces[sid];
70 AssertReturn(pSurface->id == sid, VERR_INTERNAL_ERROR);
71
72 /* Load the surface fields which are not part of SVGAOTableSurfaceEntry. */
73 pHlp->pfnSSMGetU32(pSSM, &pSurface->idAssociatedContext);
74
75 /* Load miplevels data to the surface buffers. */
76 for (uint32_t j = 0; j < pSurface->cLevels * pSurface->cFaces; j++)
77 {
78 PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->paMipmapLevels[j];
79
80 /* vmsvga3dSurfaceDefine already allocated the surface data buffer. */
81 Assert(pMipmapLevel->cbSurface);
82 AssertReturn(pMipmapLevel->pSurfaceData, VERR_INTERNAL_ERROR);
83
84 /* Fetch the data present boolean first. */
85 bool fDataPresent;
86 rc = pHlp->pfnSSMGetBool(pSSM, &fDataPresent);
87 AssertRCReturn(rc, rc);
88
89 if (fDataPresent)
90 {
91 rc = pHlp->pfnSSMGetMem(pSSM, pMipmapLevel->pSurfaceData, pMipmapLevel->cbSurface);
92 AssertRCReturn(rc, rc);
93
94 pMipmapLevel->fDirty = true;
95 pSurface->fDirty = true;
96 }
97 else
98 pMipmapLevel->fDirty = false;
99 }
100
101 return VINF_SUCCESS;
102}
103
104static int vmsvga3dDXLoadContext(PCPDMDEVHLPR3 pHlp, PVGASTATECC pThisCC, PSSMHANDLE pSSM)
105{
106 PVMSVGAR3STATE pSvgaR3State = pThisCC->svga.pSvgaR3State;
107 PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState;
108 uint32_t u32;
109 int rc;
110
111 uint32_t cid;
112 rc = pHlp->pfnSSMGetU32(pSSM, &cid);
113 AssertRCReturn(rc, rc);
114
115 if (cid == SVGA3D_INVALID_ID)
116 return VINF_SUCCESS;
117
118 /* Define the context. */
119 rc = vmsvga3dDXDefineContext(pThisCC, cid);
120 AssertRCReturn(rc, rc);
121
122 PVMSVGA3DDXCONTEXT pDXContext = p3dState->papDXContexts[cid];
123 AssertReturn(pDXContext->cid == cid, VERR_INTERNAL_ERROR);
124
125 /* Load the context. */
126 rc = pHlp->pfnSSMGetU32(pSSM, &u32);
127 AssertRCReturn(rc, rc);
128 AssertReturn(u32 == sizeof(SVGADXContextMobFormat), VERR_INVALID_STATE);
129
130 pHlp->pfnSSMGetMem(pSSM, &pDXContext->svgaDXContext, sizeof(SVGADXContextMobFormat));
131
132 rc = pHlp->pfnSSMGetU32(pSSM, &u32);
133 AssertLogRelRCReturn(rc, rc);
134 AssertReturn(u32 == RT_ELEMENTS(pDXContext->aCOTMobs), VERR_INVALID_STATE);
135
136 for (unsigned i = 0; i < RT_ELEMENTS(pDXContext->aCOTMobs); ++i)
137 {
138 rc = pHlp->pfnSSMGetU32(pSSM, &u32);
139 AssertLogRelRCReturn(rc, rc);
140 pDXContext->aCOTMobs[i] = vmsvgaR3MobGet(pSvgaR3State, u32);
141 Assert(pDXContext->aCOTMobs[i] || u32 == SVGA_ID_INVALID);
142 }
143
144 struct
145 {
146 SVGACOTableType COTableType;
147 uint32_t cbEntry;
148 uint32_t *pcEntries;
149 void **ppaEntries;
150 } cot[] =
151 {
152 {SVGA_COTABLE_RTVIEW, sizeof(SVGACOTableDXRTViewEntry), &pDXContext->cot.cRTView, (void **)&pDXContext->cot.paRTView},
153 {SVGA_COTABLE_DSVIEW, sizeof(SVGACOTableDXDSViewEntry), &pDXContext->cot.cDSView, (void **)&pDXContext->cot.paDSView},
154 {SVGA_COTABLE_SRVIEW, sizeof(SVGACOTableDXSRViewEntry), &pDXContext->cot.cSRView, (void **)&pDXContext->cot.paSRView},
155 {SVGA_COTABLE_ELEMENTLAYOUT, sizeof(SVGACOTableDXElementLayoutEntry), &pDXContext->cot.cElementLayout, (void **)&pDXContext->cot.paElementLayout},
156 {SVGA_COTABLE_BLENDSTATE, sizeof(SVGACOTableDXBlendStateEntry), &pDXContext->cot.cBlendState, (void **)&pDXContext->cot.paBlendState},
157 {SVGA_COTABLE_DEPTHSTENCIL, sizeof(SVGACOTableDXDepthStencilEntry), &pDXContext->cot.cDepthStencil, (void **)&pDXContext->cot.paDepthStencil},
158 {SVGA_COTABLE_RASTERIZERSTATE, sizeof(SVGACOTableDXRasterizerStateEntry), &pDXContext->cot.cRasterizerState, (void **)&pDXContext->cot.paRasterizerState},
159 {SVGA_COTABLE_SAMPLER, sizeof(SVGACOTableDXSamplerEntry), &pDXContext->cot.cSampler, (void **)&pDXContext->cot.paSampler},
160 {SVGA_COTABLE_STREAMOUTPUT, sizeof(SVGACOTableDXStreamOutputEntry), &pDXContext->cot.cStreamOutput, (void **)&pDXContext->cot.paStreamOutput},
161 {SVGA_COTABLE_DXQUERY, sizeof(SVGACOTableDXQueryEntry), &pDXContext->cot.cQuery, (void **)&pDXContext->cot.paQuery},
162 {SVGA_COTABLE_DXSHADER, sizeof(SVGACOTableDXShaderEntry), &pDXContext->cot.cShader, (void **)&pDXContext->cot.paShader},
163 {SVGA_COTABLE_UAVIEW, sizeof(SVGACOTableDXUAViewEntry), &pDXContext->cot.cUAView, (void **)&pDXContext->cot.paUAView},
164 };
165
166 AssertCompile(RT_ELEMENTS(cot) == RT_ELEMENTS(pDXContext->aCOTMobs));
167 for (unsigned i = 0; i < RT_ELEMENTS(cot); ++i)
168 {
169 uint32_t cEntries;
170 pHlp->pfnSSMGetU32(pSSM, &cEntries);
171 rc = pHlp->pfnSSMGetU32(pSSM, &u32);
172 AssertRCReturn(rc, rc);
173 AssertReturn(u32 == cot[i].cbEntry, VERR_INVALID_STATE);
174
175 *cot[i].pcEntries = cEntries;
176 *cot[i].ppaEntries = vmsvgaR3MobBackingStorePtr(pDXContext->aCOTMobs[cot[i].COTableType], 0);
177
178 if (cEntries)
179 {
180 rc = pSvgaR3State->pFuncsDX->pfnDXSetCOTable(pThisCC, pDXContext, cot[i].COTableType, cEntries);
181 AssertLogRelRCReturn(rc, rc);
182 }
183 }
184
185 rc = pSvgaR3State->pFuncsDX->pfnDXLoadState(pThisCC, pDXContext, pHlp, pSSM);
186 AssertRCReturn(rc, rc);
187
188 return VINF_SUCCESS;
189}
190
191int vmsvga3dDXLoadExec(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
192{
193 RT_NOREF(pThis, uPass);
194
195 if (uVersion < VGA_SAVEDSTATE_VERSION_VMSVGA_DX)
196 AssertFailedReturn(VERR_INVALID_STATE);
197
198 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
199 PVMSVGAR3STATE pSvgaR3State = pThisCC->svga.pSvgaR3State;
200 PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState;
201 int rc;
202
203 /*
204 * VMSVGA3DSTATE
205 */
206 pHlp->pfnSSMGetU32(pSSM, &p3dState->cSurfaces);
207 rc = pHlp->pfnSSMGetU32(pSSM, &p3dState->cDXContexts);
208 AssertRCReturn(rc, rc);
209
210 /*
211 * Surfaces
212 */
213 p3dState->papSurfaces = (PVMSVGA3DSURFACE *)RTMemAlloc(p3dState->cSurfaces * sizeof(VMSVGA3DSURFACE));
214 AssertReturn(p3dState->papSurfaces, VERR_NO_MEMORY);
215 for (uint32_t i = 0; i < p3dState->cSurfaces; ++i)
216 {
217 p3dState->papSurfaces[i] = (PVMSVGA3DSURFACE)RTMemAllocZ(sizeof(VMSVGA3DSURFACE));
218 AssertPtrReturn(p3dState->papSurfaces[i], VERR_NO_MEMORY);
219 p3dState->papSurfaces[i]->id = SVGA3D_INVALID_ID;
220 }
221
222 for (uint32_t i = 0; i < p3dState->cSurfaces; ++i)
223 {
224 rc = vmsvga3dDXLoadSurface(pHlp, pThisCC, pSSM);
225 AssertRCReturn(rc, rc);
226 }
227
228 /*
229 * DX contexts
230 */
231 p3dState->papDXContexts = (PVMSVGA3DDXCONTEXT *)RTMemAlloc(p3dState->cDXContexts * sizeof(VMSVGA3DDXCONTEXT));
232 AssertReturn(p3dState->papDXContexts, VERR_NO_MEMORY);
233 for (uint32_t i = 0; i < p3dState->cDXContexts; ++i)
234 {
235 p3dState->papDXContexts[i] = (PVMSVGA3DDXCONTEXT)RTMemAllocZ(sizeof(VMSVGA3DDXCONTEXT));
236 AssertPtrReturn(p3dState->papDXContexts[i], VERR_NO_MEMORY);
237 p3dState->papDXContexts[i]->cid = SVGA3D_INVALID_ID;
238 }
239
240 for (uint32_t i = 0; i < p3dState->cDXContexts; ++i)
241 {
242 rc = vmsvga3dDXLoadContext(pHlp, pThisCC, pSSM);
243 AssertRCReturn(rc, rc);
244 }
245
246 if (pSvgaR3State->idDXContextCurrent != SVGA_ID_INVALID)
247 vmsvga3dDXSwitchContext(pThisCC, pSvgaR3State->idDXContextCurrent);
248
249 return VINF_SUCCESS;
250}
251
252/*
253 * Save
254 */
255
256static int vmsvga3dDXSaveSurface(PCPDMDEVHLPR3 pHlp, PVGASTATECC pThisCC, PSSMHANDLE pSSM, PVMSVGA3DSURFACE pSurface)
257{
258 RT_NOREF(pThisCC);
259 int rc;
260
261 rc = pHlp->pfnSSMPutU32(pSSM, pSurface->id);
262 AssertRCReturn(rc, rc);
263
264 if (pSurface->id == SVGA3D_INVALID_ID)
265 return VINF_SUCCESS;
266
267 /* Save the surface fields which are not part of SVGAOTableSurfaceEntry. */
268 pHlp->pfnSSMPutU32(pSSM, pSurface->idAssociatedContext);
269
270 for (uint32_t iArray = 0; iArray < pSurface->cFaces; ++iArray) /* Texture array index or face for cube textures */
271 {
272 for (uint32_t iMipmap = 0; iMipmap < pSurface->cLevels; ++iMipmap)
273 {
274 uint32_t idx = iMipmap + iArray * pSurface->cLevels;
275 PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->paMipmapLevels[idx];
276
277 if (!VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface))
278 {
279 if (pMipmapLevel->fDirty && pMipmapLevel->pSurfaceData)
280 {
281 /* Data follows */
282 rc = pHlp->pfnSSMPutBool(pSSM, true);
283 AssertRCReturn(rc, rc);
284
285 Assert(pMipmapLevel->cbSurface);
286 rc = pHlp->pfnSSMPutMem(pSSM, pMipmapLevel->pSurfaceData, pMipmapLevel->cbSurface);
287 AssertRCReturn(rc, rc);
288 }
289 else
290 {
291 /* No data follows */
292 rc = pHlp->pfnSSMPutBool(pSSM, false);
293 AssertRCReturn(rc, rc);
294 }
295 }
296 else
297 {
298 SVGA3dSurfaceImageId image;
299 image.sid = pSurface->id;
300 image.face = iArray;
301 image.mipmap = iMipmap;
302
303 VMSGA3D_BOX_DIMENSIONS dims;
304 rc = vmsvga3dGetBoxDimensions(pThisCC, &image, NULL, &dims);
305 AssertRCReturn(rc, rc);
306
307 VMSVGA3D_MAPPED_SURFACE map;
308 rc = vmsvga3dSurfaceMap(pThisCC, &image, NULL, VMSVGA3D_SURFACE_MAP_READ, &map);
309 if (RT_SUCCESS(rc))
310 {
311 /* Save mapped surface data. */
312 pHlp->pfnSSMPutBool(pSSM, true);
313 if (map.box.w * map.cbPixel == map.cbRowPitch)
314 {
315 rc = pHlp->pfnSSMPutMem(pSSM, map.pvData, pMipmapLevel->cbSurface);
316 AssertRCReturn(rc, rc);
317 }
318 else
319 {
320 uint8_t *pu8Map = (uint8_t *)map.pvData;
321 for (uint32_t z = 0; z < dims.cDepth; ++z)
322 {
323 uint8_t *pu8MapPlane = pu8Map;
324 for (uint32_t y = 0; y < dims.cyBlocks; ++y)
325 {
326 rc = pHlp->pfnSSMPutMem(pSSM, pu8MapPlane, dims.cbRow);
327 AssertRCReturn(rc, rc);
328
329 pu8MapPlane += map.cbRowPitch;
330 }
331 pu8Map += map.cbDepthPitch;
332 }
333 }
334
335 vmsvga3dSurfaceUnmap(pThisCC, &image, &map, false);
336 }
337 else
338 {
339 AssertFailed();
340
341 /* No data follows */
342 rc = pHlp->pfnSSMPutBool(pSSM, false);
343 AssertRCReturn(rc, rc);
344 }
345 }
346 }
347 }
348
349 return VINF_SUCCESS;
350}
351
352static int vmsvga3dDXSaveContext(PCPDMDEVHLPR3 pHlp, PVGASTATECC pThisCC, PSSMHANDLE pSSM, PVMSVGA3DDXCONTEXT pDXContext)
353{
354 PVMSVGAR3STATE pSvgaR3State = pThisCC->svga.pSvgaR3State;
355 int rc;
356
357 rc = pHlp->pfnSSMPutU32(pSSM, pDXContext->cid);
358 AssertRCReturn(rc, rc);
359
360 if (pDXContext->cid == SVGA3D_INVALID_ID)
361 return VINF_SUCCESS;
362
363 /* Save the context. */
364 pHlp->pfnSSMPutU32(pSSM, sizeof(SVGADXContextMobFormat));
365 pHlp->pfnSSMPutMem(pSSM, &pDXContext->svgaDXContext, sizeof(SVGADXContextMobFormat));
366
367 rc = pHlp->pfnSSMPutU32(pSSM, RT_ELEMENTS(pDXContext->aCOTMobs));
368 AssertLogRelRCReturn(rc, rc);
369 for (unsigned i = 0; i < RT_ELEMENTS(pDXContext->aCOTMobs); ++i)
370 {
371 uint32_t const mobId = vmsvgaR3MobId(pDXContext->aCOTMobs[i]);
372 rc = pHlp->pfnSSMPutU32(pSSM, mobId);
373 AssertLogRelRCReturn(rc, rc);
374 }
375
376 struct
377 {
378 uint32_t cEntries;
379 uint32_t cbEntry;
380 void *paEntries;
381 } cot[] =
382 {
383 {pDXContext->cot.cRTView, sizeof(SVGACOTableDXRTViewEntry), pDXContext->cot.paRTView},
384 {pDXContext->cot.cDSView, sizeof(SVGACOTableDXDSViewEntry), pDXContext->cot.paDSView},
385 {pDXContext->cot.cSRView, sizeof(SVGACOTableDXSRViewEntry), pDXContext->cot.paSRView},
386 {pDXContext->cot.cElementLayout, sizeof(SVGACOTableDXElementLayoutEntry), pDXContext->cot.paElementLayout},
387 {pDXContext->cot.cBlendState, sizeof(SVGACOTableDXBlendStateEntry), pDXContext->cot.paBlendState},
388 {pDXContext->cot.cDepthStencil, sizeof(SVGACOTableDXDepthStencilEntry), pDXContext->cot.paDepthStencil},
389 {pDXContext->cot.cRasterizerState, sizeof(SVGACOTableDXRasterizerStateEntry), pDXContext->cot.paRasterizerState},
390 {pDXContext->cot.cSampler, sizeof(SVGACOTableDXSamplerEntry), pDXContext->cot.paSampler},
391 {pDXContext->cot.cStreamOutput, sizeof(SVGACOTableDXStreamOutputEntry), pDXContext->cot.paStreamOutput},
392 {pDXContext->cot.cQuery, sizeof(SVGACOTableDXQueryEntry), pDXContext->cot.paQuery},
393 {pDXContext->cot.cShader, sizeof(SVGACOTableDXShaderEntry), pDXContext->cot.paShader},
394 {pDXContext->cot.cUAView, sizeof(SVGACOTableDXUAViewEntry), pDXContext->cot.paUAView},
395 };
396
397 AssertCompile(RT_ELEMENTS(cot) == RT_ELEMENTS(pDXContext->aCOTMobs));
398 for (unsigned i = 0; i < RT_ELEMENTS(cot); ++i)
399 {
400 pHlp->pfnSSMPutU32(pSSM, cot[i].cEntries);
401 rc = pHlp->pfnSSMPutU32(pSSM, cot[i].cbEntry);
402 AssertLogRelRCReturn(rc, rc);
403 }
404
405 rc = pSvgaR3State->pFuncsDX->pfnDXSaveState(pThisCC, pDXContext, pHlp, pSSM);
406 AssertRCReturn(rc, rc);
407
408 return VINF_SUCCESS;
409}
410
411int vmsvga3dDXSaveExec(PPDMDEVINS pDevIns, PVGASTATECC pThisCC, PSSMHANDLE pSSM)
412{
413 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
414 PVMSVGA3DSTATE p3dState = pThisCC->svga.p3dState;
415 int rc;
416
417 /*
418 * VMSVGA3DSTATE
419 */
420 pHlp->pfnSSMPutU32(pSSM, p3dState->cSurfaces);
421 rc = pHlp->pfnSSMPutU32(pSSM, p3dState->cDXContexts);
422 AssertRCReturn(rc, rc);
423
424 /*
425 * Surfaces
426 */
427 for (uint32_t sid = 0; sid < p3dState->cSurfaces; ++sid)
428 {
429 rc = vmsvga3dDXSaveSurface(pHlp, pThisCC, pSSM, p3dState->papSurfaces[sid]);
430 AssertRCReturn(rc, rc);
431 }
432
433 /*
434 * DX contexts
435 */
436 for (uint32_t cid = 0; cid < p3dState->cDXContexts; ++cid)
437 {
438 rc = vmsvga3dDXSaveContext(pHlp, pThisCC, pSSM, p3dState->papDXContexts[cid]);
439 AssertRCReturn(rc, rc);
440 }
441
442 return VINF_SUCCESS;
443}
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