VirtualBox

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

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

Devices/Graphics: VMSVGA support for cubemaps and compressed textures (incomplete, only D3D backend); vertex/index buffer fixes; saved state fixes; cleanup.

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette