VirtualBox

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

Last change on this file since 86899 was 86839, checked in by vboxsync, 4 years ago

Devices/Graphics: A couple of new commands; a more generic handler for creating a surface; cleaned saved state data for a surface; increased saved state version; possibility to build DX11 backend. bugref:9830 (build fix)

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