VirtualBox

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

Last change on this file since 69222 was 69163, checked in by vboxsync, 7 years ago

Devices/Graphics: VMSVGA: texture and sampler states.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 40.0 KB
Line 
1/* $Id: DevVGA-SVGA3d-savedstate.cpp 69163 2017-10-23 11:54:35Z 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 }
348
349#ifdef VMSVGA3D_OPENGL
350 /* Make the shared context the current one. */
351 if (pState->SharedCtx.id == VMSVGA3D_SHARED_CTX_ID)
352 VMSVGA3D_SET_CURRENT_CONTEXT(pState, &pState->SharedCtx);
353#endif
354
355 /* Fetch all surfaces. */
356 for (uint32_t i = 0; i < cSurfaces; i++)
357 {
358 uint32_t sid;
359
360 /* Fetch the id first. */
361 rc = SSMR3GetU32(pSSM, &sid);
362 AssertRCReturn(rc, rc);
363
364 if (sid != SVGA3D_INVALID_ID)
365 {
366 VMSVGA3DSURFACE surface;
367 LogFlow(("vmsvga3dLoadExec: Loading sid=%#x\n", sid));
368
369 /* Fetch the surface structure first. */
370 rc = SSMR3GetStructEx(pSSM, &surface, sizeof(surface), 0, g_aVMSVGA3DSURFACEFields, NULL);
371 AssertRCReturn(rc, rc);
372
373 {
374 uint32_t cMipLevels = surface.faces[0].numMipLevels * surface.cFaces;
375 PVMSVGA3DMIPMAPLEVEL pMipmapLevel = (PVMSVGA3DMIPMAPLEVEL)RTMemAlloc(cMipLevels * sizeof(VMSVGA3DMIPMAPLEVEL));
376 AssertReturn(pMipmapLevel, VERR_NO_MEMORY);
377 SVGA3dSize *pMipmapLevelSize = (SVGA3dSize *)RTMemAlloc(cMipLevels * sizeof(SVGA3dSize));
378 AssertReturn(pMipmapLevelSize, VERR_NO_MEMORY);
379
380 /* Load the mip map level info. */
381 for (uint32_t face=0; face < surface.cFaces; face++)
382 {
383 for (uint32_t j = 0; j < surface.faces[0].numMipLevels; j++)
384 {
385 uint32_t idx = j + face * surface.faces[0].numMipLevels;
386 /* Load the mip map level struct. */
387 rc = SSMR3GetStructEx(pSSM, &pMipmapLevel[idx], sizeof(pMipmapLevel[idx]), 0, g_aVMSVGA3DMIPMAPLEVELFields, NULL);
388 AssertRCReturn(rc, rc);
389
390 pMipmapLevelSize[idx] = pMipmapLevel[idx].mipmapSize;
391 }
392 }
393
394 rc = vmsvga3dSurfaceDefine(pThis, sid, surface.surfaceFlags, surface.format, surface.faces, surface.multiSampleCount, surface.autogenFilter, cMipLevels, pMipmapLevelSize);
395 AssertRCReturn(rc, rc);
396
397 RTMemFree(pMipmapLevelSize);
398 RTMemFree(pMipmapLevel);
399 }
400
401 PVMSVGA3DSURFACE pSurface = pState->papSurfaces[sid];
402 Assert(pSurface->id == sid);
403
404 pSurface->fDirty = false;
405
406 /* Load the mip map level data. */
407 for (uint32_t j = 0; j < pSurface->faces[0].numMipLevels * pSurface->cFaces; j++)
408 {
409 PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->pMipmapLevels[j];
410 bool fDataPresent = false;
411
412 /* vmsvga3dSurfaceDefine already allocated the surface data buffer. */
413 Assert(pMipmapLevel->cbSurface);
414 AssertReturn(pMipmapLevel->pSurfaceData, VERR_INTERNAL_ERROR);
415
416 /* Fetch the data present boolean first. */
417 rc = SSMR3GetBool(pSSM, &fDataPresent);
418 AssertRCReturn(rc, rc);
419
420 Log(("Surface sid=%x: load mipmap level %d with %x bytes data (present=%d).\n", sid, j, pMipmapLevel->cbSurface, fDataPresent));
421
422 if (fDataPresent)
423 {
424 rc = SSMR3GetMem(pSSM, pMipmapLevel->pSurfaceData, pMipmapLevel->cbSurface);
425 AssertRCReturn(rc, rc);
426 pMipmapLevel->fDirty = true;
427 pSurface->fDirty = true;
428 }
429 else
430 {
431 pMipmapLevel->fDirty = false;
432 }
433 }
434 }
435 }
436
437#ifdef VMSVGA3D_OPENGL
438 /* Reinitialize the shared context. */
439 LogFlow(("vmsvga3dLoadExec: pState->SharedCtx.id=%#x\n", pState->SharedCtx.id));
440 if (pState->SharedCtx.id == VMSVGA3D_SHARED_CTX_ID)
441 {
442 rc = vmsvga3dLoadReinitContext(pThis, &pState->SharedCtx);
443 AssertRCReturn(rc, rc);
444 }
445#endif
446
447 /* Reinitialize all active contexts. */
448 for (uint32_t i = 0; i < pState->cContexts; i++)
449 {
450 PVMSVGA3DCONTEXT pContext = pState->papContexts[i];
451 if (pContext->id != SVGA3D_INVALID_ID)
452 {
453 rc = vmsvga3dLoadReinitContext(pThis, pContext);
454 AssertRCReturn(rc, rc);
455 }
456 }
457
458 LogFlow(("vmsvga3dLoadExec: return success\n"));
459 return VINF_SUCCESS;
460}
461
462
463static int vmsvga3dSaveContext(PVGASTATE pThis, PSSMHANDLE pSSM, PVMSVGA3DCONTEXT pContext)
464{
465 RT_NOREF(pThis);
466 uint32_t cid = pContext->id;
467
468 /* Save the id first. */
469 int rc = SSMR3PutU32(pSSM, cid);
470 AssertRCReturn(rc, rc);
471
472 if (cid != SVGA3D_INVALID_ID)
473 {
474 /* Save a copy of the context structure first. */
475 rc = SSMR3PutStructEx(pSSM, pContext, sizeof(*pContext), 0, g_aVMSVGA3DCONTEXTFields, NULL);
476 AssertRCReturn(rc, rc);
477
478 /* Save all pixel shaders. */
479 for (uint32_t j = 0; j < pContext->cPixelShaders; j++)
480 {
481 PVMSVGA3DSHADER pShader = &pContext->paPixelShader[j];
482
483 /* Save the id first. */
484 rc = SSMR3PutU32(pSSM, pShader->id);
485 AssertRCReturn(rc, rc);
486
487 if (pShader->id != SVGA3D_INVALID_ID)
488 {
489 uint32_t cbData = pShader->cbData;
490
491 /* Save a copy of the shader struct. */
492 rc = SSMR3PutStructEx(pSSM, pShader, sizeof(*pShader), 0, g_aVMSVGA3DSHADERFields, NULL);
493 AssertRCReturn(rc, rc);
494
495 Log(("Save pixelshader shid=%d with %x bytes code.\n", pShader->id, cbData));
496 rc = SSMR3PutMem(pSSM, pShader->pShaderProgram, cbData);
497 AssertRCReturn(rc, rc);
498 }
499 }
500
501 /* Save all vertex shaders. */
502 for (uint32_t j = 0; j < pContext->cVertexShaders; j++)
503 {
504 PVMSVGA3DSHADER pShader = &pContext->paVertexShader[j];
505
506 /* Save the id first. */
507 rc = SSMR3PutU32(pSSM, pShader->id);
508 AssertRCReturn(rc, rc);
509
510 if (pShader->id != SVGA3D_INVALID_ID)
511 {
512 uint32_t cbData = pShader->cbData;
513
514 /* Save a copy of the shader struct. */
515 rc = SSMR3PutStructEx(pSSM, pShader, sizeof(*pShader), 0, g_aVMSVGA3DSHADERFields, NULL);
516 AssertRCReturn(rc, rc);
517
518 Log(("Save vertex shader shid=%d with %x bytes code.\n", pShader->id, cbData));
519 /* Fetch the shader code and save it. */
520 rc = SSMR3PutMem(pSSM, pShader->pShaderProgram, cbData);
521 AssertRCReturn(rc, rc);
522 }
523 }
524
525 /* Save pixel shader constants. */
526 for (uint32_t j = 0; j < pContext->state.cPixelShaderConst; j++)
527 {
528 rc = SSMR3PutStructEx(pSSM, &pContext->state.paPixelShaderConst[j], sizeof(pContext->state.paPixelShaderConst[j]), 0, g_aVMSVGASHADERCONSTFields, NULL);
529 AssertRCReturn(rc, rc);
530 }
531
532 /* Save vertex shader constants. */
533 for (uint32_t j = 0; j < pContext->state.cVertexShaderConst; j++)
534 {
535 rc = SSMR3PutStructEx(pSSM, &pContext->state.paVertexShaderConst[j], sizeof(pContext->state.paVertexShaderConst[j]), 0, g_aVMSVGASHADERCONSTFields, NULL);
536 AssertRCReturn(rc, rc);
537 }
538
539 /* Save texture stage and samplers state. */
540
541 /* Number of stages/samplers. */
542 rc = SSMR3PutU32(pSSM, RT_ELEMENTS(pContext->state.aTextureStates));
543 AssertRCReturn(rc, rc);
544
545 /* Number of texture states. */
546 rc = SSMR3PutU32(pSSM, RT_ELEMENTS(pContext->state.aTextureStates[0]));
547 AssertRCReturn(rc, rc);
548
549 for (uint32_t iStage = 0; iStage < RT_ELEMENTS(pContext->state.aTextureStates); ++iStage)
550 {
551 for (uint32_t j = 0; j < RT_ELEMENTS(pContext->state.aTextureStates[0]); ++j)
552 {
553 SVGA3dTextureState *pTextureState = &pContext->state.aTextureStates[iStage][j];
554
555 SSMR3PutU32(pSSM, pTextureState->stage);
556 SSMR3PutU32(pSSM, pTextureState->name);
557 rc = SSMR3PutU32(pSSM, pTextureState->value);
558 AssertRCReturn(rc, rc);
559 }
560 }
561 }
562
563 return VINF_SUCCESS;
564}
565
566int vmsvga3dSaveExec(PVGASTATE pThis, PSSMHANDLE pSSM)
567{
568 PVMSVGA3DSTATE pState = pThis->svga.p3dState;
569 AssertReturn(pState, VERR_NO_MEMORY);
570 int rc;
571
572 /* Save a copy of the generic 3d state first. */
573 rc = SSMR3PutStructEx(pSSM, pState, sizeof(*pState), 0, g_aVMSVGA3DSTATEFields, NULL);
574 AssertRCReturn(rc, rc);
575
576#ifdef VMSVGA3D_OPENGL
577 /* Save the shared context. */
578 if (pState->SharedCtx.id == VMSVGA3D_SHARED_CTX_ID)
579 {
580 rc = vmsvga3dSaveContext(pThis, pSSM, &pState->SharedCtx);
581 AssertRCReturn(rc, rc);
582 }
583#endif
584
585 /* Save all active contexts. */
586 for (uint32_t i = 0; i < pState->cContexts; i++)
587 {
588 rc = vmsvga3dSaveContext(pThis, pSSM, pState->papContexts[i]);
589 AssertRCReturn(rc, rc);
590 }
591
592 /* Save all active surfaces. */
593 for (uint32_t sid = 0; sid < pState->cSurfaces; sid++)
594 {
595 PVMSVGA3DSURFACE pSurface = pState->papSurfaces[sid];
596
597 /* Save the id first. */
598 rc = SSMR3PutU32(pSSM, pSurface->id);
599 AssertRCReturn(rc, rc);
600
601 if (pSurface->id != SVGA3D_INVALID_ID)
602 {
603 /* Save a copy of the surface structure first. */
604 rc = SSMR3PutStructEx(pSSM, pSurface, sizeof(*pSurface), 0, g_aVMSVGA3DSURFACEFields, NULL);
605 AssertRCReturn(rc, rc);
606
607 /* Save the mip map level info. */
608 for (uint32_t face=0; face < pSurface->cFaces; face++)
609 {
610 for (uint32_t i = 0; i < pSurface->faces[0].numMipLevels; i++)
611 {
612 uint32_t idx = i + face * pSurface->faces[0].numMipLevels;
613 PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->pMipmapLevels[idx];
614
615 /* Save a copy of the mip map level struct. */
616 rc = SSMR3PutStructEx(pSSM, pMipmapLevel, sizeof(*pMipmapLevel), 0, g_aVMSVGA3DMIPMAPLEVELFields, NULL);
617 AssertRCReturn(rc, rc);
618 }
619 }
620
621 /* Save the mip map level data. */
622 for (uint32_t face=0; face < pSurface->cFaces; face++)
623 {
624 for (uint32_t i = 0; i < pSurface->faces[0].numMipLevels; i++)
625 {
626 uint32_t idx = i + face * pSurface->faces[0].numMipLevels;
627 PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->pMipmapLevels[idx];
628
629 Log(("Surface sid=%d: save mipmap level %d with %x bytes data.\n", sid, i, pMipmapLevel->cbSurface));
630
631#ifdef VMSVGA3D_DIRECT3D
632 if (!pSurface->u.pSurface)
633#else
634 if (pSurface->oglId.texture == OPENGL_INVALID_ID)
635#endif
636 {
637 if (pMipmapLevel->fDirty)
638 {
639 /* Data follows */
640 rc = SSMR3PutBool(pSSM, true);
641 AssertRCReturn(rc, rc);
642
643 Assert(pMipmapLevel->cbSurface);
644 rc = SSMR3PutMem(pSSM, pMipmapLevel->pSurfaceData, pMipmapLevel->cbSurface);
645 AssertRCReturn(rc, rc);
646 }
647 else
648 {
649 /* No data follows */
650 rc = SSMR3PutBool(pSSM, false);
651 AssertRCReturn(rc, rc);
652 }
653 }
654 else
655 {
656#ifdef VMSVGA3D_DIRECT3D
657 void *pData;
658 bool fRenderTargetTexture = false;
659 bool fTexture = false;
660 bool fSkipSave = false;
661 HRESULT hr;
662
663 Assert(pMipmapLevel->cbSurface);
664 pData = RTMemAllocZ(pMipmapLevel->cbSurface);
665 AssertReturn(pData, VERR_NO_MEMORY);
666
667 switch (pSurface->enmD3DResType)
668 {
669 case VMSVGA3D_D3DRESTYPE_CUBE_TEXTURE:
670 case VMSVGA3D_D3DRESTYPE_VOLUME_TEXTURE:
671 AssertFailed(); ///@todo
672 fSkipSave = true;
673 break;
674 case VMSVGA3D_D3DRESTYPE_SURFACE:
675 case VMSVGA3D_D3DRESTYPE_TEXTURE:
676 {
677 if (pSurface->surfaceFlags & SVGA3D_SURFACE_HINT_DEPTHSTENCIL)
678 {
679 /** @todo unable to easily fetch depth surface data in d3d 9 */
680 fSkipSave = true;
681 break;
682 }
683
684 fTexture = (pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_TEXTURE);
685 fRenderTargetTexture = fTexture && (pSurface->surfaceFlags & SVGA3D_SURFACE_HINT_RENDERTARGET);
686
687 D3DLOCKED_RECT LockedRect;
688
689 if (fTexture)
690 {
691 if (pSurface->bounce.pTexture)
692 {
693 if ( !pSurface->fDirty
694 && fRenderTargetTexture
695 && i == 0 /* only the first time */)
696 {
697 IDirect3DSurface9 *pSrc, *pDest;
698
699 /** @todo stricter checks for associated context */
700 uint32_t cid = pSurface->idAssociatedContext;
701 if ( cid >= pState->cContexts
702 || pState->papContexts[cid]->id != cid)
703 {
704 Log(("vmsvga3dSaveExec invalid context id (%x - %x)!\n", cid, (cid >= pState->cContexts) ? -1 : pState->papContexts[cid]->id));
705 AssertFailedReturn(VERR_INVALID_PARAMETER);
706 }
707 PVMSVGA3DCONTEXT pContext = pState->papContexts[cid];
708
709 hr = pSurface->bounce.pTexture->GetSurfaceLevel(i, &pDest);
710 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: GetSurfaceLevel failed with %x\n", hr), VERR_INTERNAL_ERROR);
711
712 hr = pSurface->u.pTexture->GetSurfaceLevel(i, &pSrc);
713 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: GetSurfaceLevel failed with %x\n", hr), VERR_INTERNAL_ERROR);
714
715 hr = pContext->pDevice->GetRenderTargetData(pSrc, pDest);
716 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: GetRenderTargetData failed with %x\n", hr), VERR_INTERNAL_ERROR);
717
718 pSrc->Release();
719 pDest->Release();
720 }
721
722 hr = pSurface->bounce.pTexture->LockRect(i, /* texture level */
723 &LockedRect,
724 NULL,
725 D3DLOCK_READONLY);
726 }
727 else
728 hr = pSurface->u.pTexture->LockRect(i, /* texture level */
729 &LockedRect,
730 NULL,
731 D3DLOCK_READONLY);
732 }
733 else
734 hr = pSurface->u.pSurface->LockRect(&LockedRect,
735 NULL,
736 D3DLOCK_READONLY);
737 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: LockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
738
739 /* Copy the data one line at a time in case the internal pitch is different. */
740 for (uint32_t j = 0; j < pMipmapLevel->cBlocksY; ++j)
741 {
742 uint8_t *pu8Dst = (uint8_t *)pData + j * pMipmapLevel->cbSurfacePitch;
743 const uint8_t *pu8Src = (uint8_t *)LockedRect.pBits + j * LockedRect.Pitch;
744 memcpy(pu8Dst, pu8Src, pMipmapLevel->cbSurfacePitch);
745 }
746
747 if (fTexture)
748 {
749 if (pSurface->bounce.pTexture)
750 {
751 hr = pSurface->bounce.pTexture->UnlockRect(i);
752 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: UnlockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
753 }
754 else
755 hr = pSurface->u.pTexture->UnlockRect(i);
756 }
757 else
758 hr = pSurface->u.pSurface->UnlockRect();
759 AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: UnlockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
760 break;
761 }
762
763 case VMSVGA3D_D3DRESTYPE_VERTEX_BUFFER:
764 case VMSVGA3D_D3DRESTYPE_INDEX_BUFFER:
765 {
766 /* Current type of the buffer. */
767 const bool fVertex = (pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_VERTEX_BUFFER);
768
769 uint8_t *pD3DData;
770
771 if (fVertex)
772 hr = pSurface->u.pVertexBuffer->Lock(0, 0, (void **)&pD3DData, D3DLOCK_READONLY);
773 else
774 hr = pSurface->u.pIndexBuffer->Lock(0, 0, (void **)&pD3DData, D3DLOCK_READONLY);
775 AssertMsg(hr == D3D_OK, ("vmsvga3dSaveExec: Lock %s failed with %x\n", (fVertex) ? "vertex" : "index", hr));
776
777 memcpy(pData, pD3DData, pMipmapLevel->cbSurface);
778
779 if (fVertex)
780 hr = pSurface->u.pVertexBuffer->Unlock();
781 else
782 hr = pSurface->u.pIndexBuffer->Unlock();
783 AssertMsg(hr == D3D_OK, ("vmsvga3dSaveExec: Unlock %s failed with %x\n", (fVertex) ? "vertex" : "index", hr));
784 break;
785 }
786
787 default:
788 AssertFailed();
789 break;
790 }
791
792 if (!fSkipSave)
793 {
794 /* Data follows */
795 rc = SSMR3PutBool(pSSM, true);
796 AssertRCReturn(rc, rc);
797
798 /* And write the surface data. */
799 rc = SSMR3PutMem(pSSM, pData, pMipmapLevel->cbSurface);
800 AssertRCReturn(rc, rc);
801 }
802 else
803 {
804 /* No data follows */
805 rc = SSMR3PutBool(pSSM, false);
806 AssertRCReturn(rc, rc);
807 }
808
809 RTMemFree(pData);
810#elif defined(VMSVGA3D_OPENGL)
811 void *pData = NULL;
812
813 PVMSVGA3DCONTEXT pContext = &pState->SharedCtx;
814 VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
815
816 Assert(pMipmapLevel->cbSurface);
817
818 switch (pSurface->surfaceFlags & VMSVGA3D_SURFACE_HINT_SWITCH_MASK)
819 {
820 default:
821 AssertFailed();
822 RT_FALL_THRU();
823 case SVGA3D_SURFACE_HINT_DEPTHSTENCIL:
824 case SVGA3D_SURFACE_HINT_DEPTHSTENCIL | SVGA3D_SURFACE_HINT_TEXTURE:
825 /** @todo fetch data from the renderbuffer */
826 /* No data follows */
827 rc = SSMR3PutBool(pSSM, false);
828 AssertRCReturn(rc, rc);
829 break;
830
831 case SVGA3D_SURFACE_HINT_TEXTURE | SVGA3D_SURFACE_HINT_RENDERTARGET:
832 case SVGA3D_SURFACE_HINT_TEXTURE:
833 case SVGA3D_SURFACE_HINT_RENDERTARGET:
834 {
835 GLint activeTexture;
836
837 pData = RTMemAllocZ(pMipmapLevel->cbSurface);
838 AssertReturn(pData, VERR_NO_MEMORY);
839
840 glGetIntegerv(GL_TEXTURE_BINDING_2D, &activeTexture);
841 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
842
843 glBindTexture(GL_TEXTURE_2D, pSurface->oglId.texture);
844 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
845
846 /* Set row length and alignment of the output data. */
847 VMSVGAPACKPARAMS SavedParams;
848 vmsvga3dOglSetPackParams(pState, pContext, pSurface, &SavedParams);
849
850 glGetTexImage(GL_TEXTURE_2D,
851 i,
852 pSurface->formatGL,
853 pSurface->typeGL,
854 pData);
855 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
856
857 vmsvga3dOglRestorePackParams(pState, pContext, pSurface, &SavedParams);
858
859 /* Data follows */
860 rc = SSMR3PutBool(pSSM, true);
861 AssertRCReturn(rc, rc);
862
863 /* And write the surface data. */
864 rc = SSMR3PutMem(pSSM, pData, pMipmapLevel->cbSurface);
865 AssertRCReturn(rc, rc);
866
867 /* Restore the old active texture. */
868 glBindTexture(GL_TEXTURE_2D, activeTexture);
869 VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
870 break;
871 }
872
873 case SVGA3D_SURFACE_HINT_VERTEXBUFFER | SVGA3D_SURFACE_HINT_INDEXBUFFER:
874 case SVGA3D_SURFACE_HINT_VERTEXBUFFER:
875 case SVGA3D_SURFACE_HINT_INDEXBUFFER:
876 {
877 uint8_t *pBufferData;
878
879 pState->ext.glBindBuffer(GL_ARRAY_BUFFER, pSurface->oglId.buffer);
880 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
881
882 pBufferData = (uint8_t *)pState->ext.glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
883 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
884 Assert(pBufferData);
885
886 /* Data follows */
887 rc = SSMR3PutBool(pSSM, true);
888 AssertRCReturn(rc, rc);
889
890 /* And write the surface data. */
891 rc = SSMR3PutMem(pSSM, pBufferData, pMipmapLevel->cbSurface);
892 AssertRCReturn(rc, rc);
893
894 pState->ext.glUnmapBuffer(GL_ARRAY_BUFFER);
895 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
896
897 pState->ext.glBindBuffer(GL_ARRAY_BUFFER, 0);
898 VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
899
900 }
901 }
902 if (pData)
903 RTMemFree(pData);
904#else
905#error "Unexpected 3d backend"
906#endif
907 }
908 }
909 }
910 }
911 }
912 return VINF_SUCCESS;
913}
914
915int vmsvga3dSaveShaderConst(PVMSVGA3DCONTEXT pContext, uint32_t reg, SVGA3dShaderType type, SVGA3dShaderConstType ctype,
916 uint32_t val1, uint32_t val2, uint32_t val3, uint32_t val4)
917{
918 /* Choose a sane upper limit. */
919 AssertReturn(reg < _32K, VERR_INVALID_PARAMETER);
920
921 if (type == SVGA3D_SHADERTYPE_VS)
922 {
923 if (pContext->state.cVertexShaderConst <= reg)
924 {
925 pContext->state.paVertexShaderConst = (PVMSVGASHADERCONST)RTMemRealloc(pContext->state.paVertexShaderConst, sizeof(VMSVGASHADERCONST) * (reg + 1));
926 AssertReturn(pContext->state.paVertexShaderConst, VERR_NO_MEMORY);
927 for (uint32_t i = pContext->state.cVertexShaderConst; i < reg + 1; i++)
928 pContext->state.paVertexShaderConst[i].fValid = false;
929 pContext->state.cVertexShaderConst = reg + 1;
930 }
931
932 pContext->state.paVertexShaderConst[reg].fValid = true;
933 pContext->state.paVertexShaderConst[reg].ctype = ctype;
934 pContext->state.paVertexShaderConst[reg].value[0] = val1;
935 pContext->state.paVertexShaderConst[reg].value[1] = val2;
936 pContext->state.paVertexShaderConst[reg].value[2] = val3;
937 pContext->state.paVertexShaderConst[reg].value[3] = val4;
938 }
939 else
940 {
941 Assert(type == SVGA3D_SHADERTYPE_PS);
942 if (pContext->state.cPixelShaderConst <= reg)
943 {
944 pContext->state.paPixelShaderConst = (PVMSVGASHADERCONST)RTMemRealloc(pContext->state.paPixelShaderConst, sizeof(VMSVGASHADERCONST) * (reg + 1));
945 AssertReturn(pContext->state.paPixelShaderConst, VERR_NO_MEMORY);
946 for (uint32_t i = pContext->state.cPixelShaderConst; i < reg + 1; i++)
947 pContext->state.paPixelShaderConst[i].fValid = false;
948 pContext->state.cPixelShaderConst = reg + 1;
949 }
950
951 pContext->state.paPixelShaderConst[reg].fValid = true;
952 pContext->state.paPixelShaderConst[reg].ctype = ctype;
953 pContext->state.paPixelShaderConst[reg].value[0] = val1;
954 pContext->state.paPixelShaderConst[reg].value[1] = val2;
955 pContext->state.paPixelShaderConst[reg].value[2] = val3;
956 pContext->state.paPixelShaderConst[reg].value[3] = val4;
957 }
958
959 return VINF_SUCCESS;
960}
961
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