VirtualBox

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

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

DevVGA-SVGA3d-ogl: remember type of created resource; CopySurface/StretchBlt fixes; vmsvga3dBackSurfaceDMACopyBox support for 3D textures; occlusion query functions should set current context.

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