VirtualBox

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

Last change on this file since 93115 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

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