VirtualBox

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

Last change on this file since 61541 was 57358, checked in by vboxsync, 9 years ago

*: scm cleanup run.

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