VirtualBox

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

Last change on this file since 72919 was 69904, checked in by vboxsync, 7 years ago

Devices/Graphics: VMSVGA: take screen offset into account; saved state for occlusion query; increase saved state version.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 43.0 KB
Line 
1/* $Id: DevVGA-SVGA3d-savedstate.cpp 69904 2017-12-01 20:29:24Z vboxsync $ */
2/** @file
3 * DevSVGA3d - VMWare SVGA device, 3D parts - Saved state and assocated stuff.
4 */
5
6/*
7 * Copyright (C) 2013-2017 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 <VBox/err.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#ifdef VMSVGA3D_DIRECT3D
704 if (!pSurface->u.pSurface)
705#else
706 if (pSurface->oglId.texture == OPENGL_INVALID_ID)
707#endif
708 {
709 if (pMipmapLevel->fDirty)
710 {
711 /* Data follows */
712 rc = SSMR3PutBool(pSSM, true);
713 AssertRCReturn(rc, rc);
714
715 Assert(pMipmapLevel->cbSurface);
716 rc = SSMR3PutMem(pSSM, pMipmapLevel->pSurfaceData, pMipmapLevel->cbSurface);
717 AssertRCReturn(rc, rc);
718 }
719 else
720 {
721 /* No data follows */
722 rc = SSMR3PutBool(pSSM, false);
723 AssertRCReturn(rc, rc);
724 }
725 }
726 else
727 {
728#ifdef VMSVGA3D_DIRECT3D
729 void *pData;
730 bool fRenderTargetTexture = false;
731 bool fTexture = false;
732 bool fSkipSave = false;
733 HRESULT hr;
734
735 Assert(pMipmapLevel->cbSurface);
736 pData = RTMemAllocZ(pMipmapLevel->cbSurface);
737 AssertReturn(pData, VERR_NO_MEMORY);
738
739 switch (pSurface->enmD3DResType)
740 {
741 case VMSVGA3D_D3DRESTYPE_CUBE_TEXTURE:
742 case VMSVGA3D_D3DRESTYPE_VOLUME_TEXTURE:
743 AssertFailed(); /// @todo
744 fSkipSave = true;
745 break;
746 case VMSVGA3D_D3DRESTYPE_SURFACE:
747 case VMSVGA3D_D3DRESTYPE_TEXTURE:
748 {
749 if (pSurface->surfaceFlags & SVGA3D_SURFACE_HINT_DEPTHSTENCIL)
750 {
751 /** @todo unable to easily fetch depth surface data in d3d 9 */
752 fSkipSave = true;
753 break;
754 }
755
756 fTexture = (pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_TEXTURE);
757 fRenderTargetTexture = fTexture && (pSurface->surfaceFlags & SVGA3D_SURFACE_HINT_RENDERTARGET);
758
759 D3DLOCKED_RECT LockedRect;
760
761 if (fTexture)
762 {
763 if (pSurface->bounce.pTexture)
764 {
765 if ( !pSurface->fDirty
766 && fRenderTargetTexture
767 && i == 0 /* only the first time */)
768 {
769 IDirect3DSurface9 *pSrc, *pDest;
770
771 /** @todo stricter checks for associated context */
772 uint32_t cid = pSurface->idAssociatedContext;
773 if ( cid >= pState->cContexts
774 || pState->papContexts[cid]->id != cid)
775 {
776 Log(("vmsvga3dSaveExec invalid context id (%x - %x)!\n", cid, (cid >= pState->cContexts) ? -1 : pState->papContexts[cid]->id));
777 AssertFailedReturn(VERR_INVALID_PARAMETER);
778 }
779 PVMSVGA3DCONTEXT pContext = pState->papContexts[cid];
780
781 hr = pSurface->bounce.pTexture->GetSurfaceLevel(i, &pDest);
782 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: GetSurfaceLevel failed with %x\n", hr), VERR_INTERNAL_ERROR);
783
784 hr = pSurface->u.pTexture->GetSurfaceLevel(i, &pSrc);
785 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: GetSurfaceLevel failed with %x\n", hr), VERR_INTERNAL_ERROR);
786
787 hr = pContext->pDevice->GetRenderTargetData(pSrc, pDest);
788 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: GetRenderTargetData failed with %x\n", hr), VERR_INTERNAL_ERROR);
789
790 pSrc->Release();
791 pDest->Release();
792 }
793
794 hr = pSurface->bounce.pTexture->LockRect(i, /* texture level */
795 &LockedRect,
796 NULL,
797 D3DLOCK_READONLY);
798 }
799 else
800 hr = pSurface->u.pTexture->LockRect(i, /* texture level */
801 &LockedRect,
802 NULL,
803 D3DLOCK_READONLY);
804 }
805 else
806 hr = pSurface->u.pSurface->LockRect(&LockedRect,
807 NULL,
808 D3DLOCK_READONLY);
809 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: LockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
810
811 /* Copy the data one line at a time in case the internal pitch is different. */
812 for (uint32_t j = 0; j < pMipmapLevel->cBlocksY; ++j)
813 {
814 uint8_t *pu8Dst = (uint8_t *)pData + j * pMipmapLevel->cbSurfacePitch;
815 const uint8_t *pu8Src = (uint8_t *)LockedRect.pBits + j * LockedRect.Pitch;
816 memcpy(pu8Dst, pu8Src, pMipmapLevel->cbSurfacePitch);
817 }
818
819 if (fTexture)
820 {
821 if (pSurface->bounce.pTexture)
822 {
823 hr = pSurface->bounce.pTexture->UnlockRect(i);
824 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: UnlockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
825 }
826 else
827 hr = pSurface->u.pTexture->UnlockRect(i);
828 }
829 else
830 hr = pSurface->u.pSurface->UnlockRect();
831 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: UnlockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
832 break;
833 }
834
835 case VMSVGA3D_D3DRESTYPE_VERTEX_BUFFER:
836 case VMSVGA3D_D3DRESTYPE_INDEX_BUFFER:
837 {
838 /* Current type of the buffer. */
839 const bool fVertex = (pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_VERTEX_BUFFER);
840
841 uint8_t *pD3DData;
842
843 if (fVertex)
844 hr = pSurface->u.pVertexBuffer->Lock(0, 0, (void **)&pD3DData, D3DLOCK_READONLY);
845 else
846 hr = pSurface->u.pIndexBuffer->Lock(0, 0, (void **)&pD3DData, D3DLOCK_READONLY);
847 AssertMsg(hr == D3D_OK, ("vmsvga3dSaveExec: Lock %s failed with %x\n", (fVertex) ? "vertex" : "index", hr));
848
849 memcpy(pData, pD3DData, pMipmapLevel->cbSurface);
850
851 if (fVertex)
852 hr = pSurface->u.pVertexBuffer->Unlock();
853 else
854 hr = pSurface->u.pIndexBuffer->Unlock();
855 AssertMsg(hr == D3D_OK, ("vmsvga3dSaveExec: Unlock %s failed with %x\n", (fVertex) ? "vertex" : "index", hr));
856 break;
857 }
858
859 default:
860 AssertFailed();
861 break;
862 }
863
864 if (!fSkipSave)
865 {
866 /* Data follows */
867 rc = SSMR3PutBool(pSSM, true);
868 AssertRCReturn(rc, rc);
869
870 /* And write the surface data. */
871 rc = SSMR3PutMem(pSSM, pData, pMipmapLevel->cbSurface);
872 AssertRCReturn(rc, rc);
873 }
874 else
875 {
876 /* No data follows */
877 rc = SSMR3PutBool(pSSM, false);
878 AssertRCReturn(rc, rc);
879 }
880
881 RTMemFree(pData);
882#elif defined(VMSVGA3D_OPENGL)
883 void *pData = NULL;
884
885 PVMSVGA3DCONTEXT pContext = &pState->SharedCtx;
886 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
887
888 Assert(pMipmapLevel->cbSurface);
889
890 switch (pSurface->surfaceFlags & VMSVGA3D_SURFACE_HINT_SWITCH_MASK)
891 {
892 default:
893 AssertFailed();
894 RT_FALL_THRU();
895 case SVGA3D_SURFACE_HINT_DEPTHSTENCIL:
896 case SVGA3D_SURFACE_HINT_DEPTHSTENCIL | SVGA3D_SURFACE_HINT_TEXTURE:
897 /** @todo fetch data from the renderbuffer */
898 /* No data follows */
899 rc = SSMR3PutBool(pSSM, false);
900 AssertRCReturn(rc, rc);
901 break;
902
903 case SVGA3D_SURFACE_HINT_TEXTURE | SVGA3D_SURFACE_HINT_RENDERTARGET:
904 case SVGA3D_SURFACE_HINT_TEXTURE:
905 case SVGA3D_SURFACE_HINT_RENDERTARGET:
906 {
907 GLint activeTexture;
908
909 pData = RTMemAllocZ(pMipmapLevel->cbSurface);
910 AssertReturn(pData, VERR_NO_MEMORY);
911
912 glGetIntegerv(GL_TEXTURE_BINDING_2D, &activeTexture);
913 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
914
915 glBindTexture(GL_TEXTURE_2D, pSurface->oglId.texture);
916 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
917
918 /* Set row length and alignment of the output data. */
919 VMSVGAPACKPARAMS SavedParams;
920 vmsvga3dOglSetPackParams(pState, pContext, pSurface, &SavedParams);
921
922 glGetTexImage(GL_TEXTURE_2D,
923 i,
924 pSurface->formatGL,
925 pSurface->typeGL,
926 pData);
927 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
928
929 vmsvga3dOglRestorePackParams(pState, pContext, pSurface, &SavedParams);
930
931 /* Data follows */
932 rc = SSMR3PutBool(pSSM, true);
933 AssertRCReturn(rc, rc);
934
935 /* And write the surface data. */
936 rc = SSMR3PutMem(pSSM, pData, pMipmapLevel->cbSurface);
937 AssertRCReturn(rc, rc);
938
939 /* Restore the old active texture. */
940 glBindTexture(GL_TEXTURE_2D, activeTexture);
941 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
942 break;
943 }
944
945 case SVGA3D_SURFACE_HINT_VERTEXBUFFER | SVGA3D_SURFACE_HINT_INDEXBUFFER:
946 case SVGA3D_SURFACE_HINT_VERTEXBUFFER:
947 case SVGA3D_SURFACE_HINT_INDEXBUFFER:
948 {
949 uint8_t *pBufferData;
950
951 pState->ext.glBindBuffer(GL_ARRAY_BUFFER, pSurface->oglId.buffer);
952 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
953
954 pBufferData = (uint8_t *)pState->ext.glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
955 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
956 Assert(pBufferData);
957
958 /* Data follows */
959 rc = SSMR3PutBool(pSSM, true);
960 AssertRCReturn(rc, rc);
961
962 /* And write the surface data. */
963 rc = SSMR3PutMem(pSSM, pBufferData, pMipmapLevel->cbSurface);
964 AssertRCReturn(rc, rc);
965
966 pState->ext.glUnmapBuffer(GL_ARRAY_BUFFER);
967 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
968
969 pState->ext.glBindBuffer(GL_ARRAY_BUFFER, 0);
970 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
971
972 }
973 }
974 if (pData)
975 RTMemFree(pData);
976#else
977#error "Unexpected 3d backend"
978#endif
979 }
980 }
981 }
982 }
983 }
984 return VINF_SUCCESS;
985}
986
987int vmsvga3dSaveShaderConst(PVMSVGA3DCONTEXT pContext, uint32_t reg, SVGA3dShaderType type, SVGA3dShaderConstType ctype,
988 uint32_t val1, uint32_t val2, uint32_t val3, uint32_t val4)
989{
990 /* Choose a sane upper limit. */
991 AssertReturn(reg < _32K, VERR_INVALID_PARAMETER);
992
993 if (type == SVGA3D_SHADERTYPE_VS)
994 {
995 if (pContext->state.cVertexShaderConst <= reg)
996 {
997 pContext->state.paVertexShaderConst = (PVMSVGASHADERCONST)RTMemRealloc(pContext->state.paVertexShaderConst, sizeof(VMSVGASHADERCONST) * (reg + 1));
998 AssertReturn(pContext->state.paVertexShaderConst, VERR_NO_MEMORY);
999 for (uint32_t i = pContext->state.cVertexShaderConst; i < reg + 1; i++)
1000 pContext->state.paVertexShaderConst[i].fValid = false;
1001 pContext->state.cVertexShaderConst = reg + 1;
1002 }
1003
1004 pContext->state.paVertexShaderConst[reg].fValid = true;
1005 pContext->state.paVertexShaderConst[reg].ctype = ctype;
1006 pContext->state.paVertexShaderConst[reg].value[0] = val1;
1007 pContext->state.paVertexShaderConst[reg].value[1] = val2;
1008 pContext->state.paVertexShaderConst[reg].value[2] = val3;
1009 pContext->state.paVertexShaderConst[reg].value[3] = val4;
1010 }
1011 else
1012 {
1013 Assert(type == SVGA3D_SHADERTYPE_PS);
1014 if (pContext->state.cPixelShaderConst <= reg)
1015 {
1016 pContext->state.paPixelShaderConst = (PVMSVGASHADERCONST)RTMemRealloc(pContext->state.paPixelShaderConst, sizeof(VMSVGASHADERCONST) * (reg + 1));
1017 AssertReturn(pContext->state.paPixelShaderConst, VERR_NO_MEMORY);
1018 for (uint32_t i = pContext->state.cPixelShaderConst; i < reg + 1; i++)
1019 pContext->state.paPixelShaderConst[i].fValid = false;
1020 pContext->state.cPixelShaderConst = reg + 1;
1021 }
1022
1023 pContext->state.paPixelShaderConst[reg].fValid = true;
1024 pContext->state.paPixelShaderConst[reg].ctype = ctype;
1025 pContext->state.paPixelShaderConst[reg].value[0] = val1;
1026 pContext->state.paPixelShaderConst[reg].value[1] = val2;
1027 pContext->state.paPixelShaderConst[reg].value[2] = val3;
1028 pContext->state.paPixelShaderConst[reg].value[3] = val4;
1029 }
1030
1031 return VINF_SUCCESS;
1032}
1033
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