VirtualBox

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

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

Devices/Graphics: Function tables for 3D backends. bugref:9830

  • 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 89121 2021-05-17 19:30:44Z 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 /* Get the generic 3d state first. */
236 rc = pHlp->pfnSSMGetStructEx(pSSM, pState, sizeof(*pState), 0, g_aVMSVGA3DSTATEFields, NULL);
237 AssertRCReturn(rc, rc);
238
239 cContexts = pState->cContexts;
240 cSurfaces = pState->cSurfaces;
241 pState->cContexts = 0;
242 pState->cSurfaces = 0;
243
244 /* Fetch all active contexts. */
245 for (uint32_t i = 0; i < cContexts; i++)
246 {
247 PVMSVGA3DCONTEXT pContext;
248 uint32_t cid;
249
250 /* Get the context id */
251 rc = pHlp->pfnSSMGetU32(pSSM, &cid);
252 AssertRCReturn(rc, rc);
253
254 if (cid != SVGA3D_INVALID_ID)
255 {
256 uint32_t cPixelShaderConst, cVertexShaderConst, cPixelShaders, cVertexShaders;
257 LogFlow(("vmsvga3dLoadExec: Loading cid=%#x\n", cid));
258
259#ifdef VMSVGA3D_OPENGL
260 if (cid == VMSVGA3D_SHARED_CTX_ID)
261 {
262 i--; /* Not included in cContexts. */
263 pContext = &pState->SharedCtx;
264 if (pContext->id != VMSVGA3D_SHARED_CTX_ID)
265 {
266 /** @todo Separate backend */
267 rc = vmsvga3dContextDefineOgl(pThisCC, VMSVGA3D_SHARED_CTX_ID, VMSVGA3D_DEF_CTX_F_SHARED_CTX);
268 AssertRCReturn(rc, rc);
269 }
270 }
271 else
272#endif
273 {
274 rc = vmsvga3dContextDefine(pThisCC, cid);
275 AssertRCReturn(rc, rc);
276
277 pContext = pState->papContexts[i];
278 }
279 AssertReturn(pContext->id == cid, VERR_INTERNAL_ERROR);
280
281 rc = pHlp->pfnSSMGetStructEx(pSSM, pContext, sizeof(*pContext), 0, g_aVMSVGA3DCONTEXTFields, NULL);
282 AssertRCReturn(rc, rc);
283
284 cPixelShaders = pContext->cPixelShaders;
285 cVertexShaders = pContext->cVertexShaders;
286 cPixelShaderConst = pContext->state.cPixelShaderConst;
287 cVertexShaderConst = pContext->state.cVertexShaderConst;
288 pContext->cPixelShaders = 0;
289 pContext->cVertexShaders = 0;
290 pContext->state.cPixelShaderConst = 0;
291 pContext->state.cVertexShaderConst = 0;
292
293 /* Fetch all pixel shaders. */
294 for (uint32_t j = 0; j < cPixelShaders; j++)
295 {
296 VMSVGA3DSHADER shader;
297 uint32_t shid;
298
299 /* Fetch the id first. */
300 rc = pHlp->pfnSSMGetU32(pSSM, &shid);
301 AssertRCReturn(rc, rc);
302
303 if (shid != SVGA3D_INVALID_ID)
304 {
305 uint32_t *pData;
306
307 /* Fetch a copy of the shader struct. */
308 rc = pHlp->pfnSSMGetStructEx(pSSM, &shader, sizeof(shader), 0, g_aVMSVGA3DSHADERFields, NULL);
309 AssertRCReturn(rc, rc);
310
311 pData = (uint32_t *)RTMemAlloc(shader.cbData);
312 AssertReturn(pData, VERR_NO_MEMORY);
313
314 rc = pHlp->pfnSSMGetMem(pSSM, pData, shader.cbData);
315 AssertRCReturn(rc, rc);
316
317 rc = vmsvga3dShaderDefine(pThisCC, cid, shid, shader.type, shader.cbData, pData);
318 AssertRCReturn(rc, rc);
319
320 RTMemFree(pData);
321 }
322 }
323
324 /* Fetch all vertex shaders. */
325 for (uint32_t j = 0; j < cVertexShaders; j++)
326 {
327 VMSVGA3DSHADER shader;
328 uint32_t shid;
329
330 /* Fetch the id first. */
331 rc = pHlp->pfnSSMGetU32(pSSM, &shid);
332 AssertRCReturn(rc, rc);
333
334 if (shid != SVGA3D_INVALID_ID)
335 {
336 uint32_t *pData;
337
338 /* Fetch a copy of the shader struct. */
339 rc = pHlp->pfnSSMGetStructEx(pSSM, &shader, sizeof(shader), 0, g_aVMSVGA3DSHADERFields, NULL);
340 AssertRCReturn(rc, rc);
341
342 pData = (uint32_t *)RTMemAlloc(shader.cbData);
343 AssertReturn(pData, VERR_NO_MEMORY);
344
345 rc = pHlp->pfnSSMGetMem(pSSM, pData, shader.cbData);
346 AssertRCReturn(rc, rc);
347
348 rc = vmsvga3dShaderDefine(pThisCC, cid, shid, shader.type, shader.cbData, pData);
349 AssertRCReturn(rc, rc);
350
351 RTMemFree(pData);
352 }
353 }
354
355 /* Fetch pixel shader constants. */
356 for (uint32_t j = 0; j < cPixelShaderConst; j++)
357 {
358 VMSVGASHADERCONST ShaderConst;
359
360 rc = pHlp->pfnSSMGetStructEx(pSSM, &ShaderConst, sizeof(ShaderConst), 0, g_aVMSVGASHADERCONSTFields, NULL);
361 AssertRCReturn(rc, rc);
362
363 if (ShaderConst.fValid)
364 {
365 rc = vmsvga3dShaderSetConst(pThisCC, cid, j, SVGA3D_SHADERTYPE_PS, ShaderConst.ctype, 1, ShaderConst.value);
366 AssertRCReturn(rc, rc);
367 }
368 }
369
370 /* Fetch vertex shader constants. */
371 for (uint32_t j = 0; j < cVertexShaderConst; j++)
372 {
373 VMSVGASHADERCONST ShaderConst;
374
375 rc = pHlp->pfnSSMGetStructEx(pSSM, &ShaderConst, sizeof(ShaderConst), 0, g_aVMSVGASHADERCONSTFields, NULL);
376 AssertRCReturn(rc, rc);
377
378 if (ShaderConst.fValid)
379 {
380 rc = vmsvga3dShaderSetConst(pThisCC, cid, j, SVGA3D_SHADERTYPE_VS, ShaderConst.ctype, 1, ShaderConst.value);
381 AssertRCReturn(rc, rc);
382 }
383 }
384
385 if (uVersion >= VGA_SAVEDSTATE_VERSION_VMSVGA_TEX_STAGES)
386 {
387 /* Load texture stage and samplers state. */
388
389 /* Number of stages/samplers. */
390 uint32_t cStages;
391 rc = pHlp->pfnSSMGetU32(pSSM, &cStages);
392 AssertRCReturn(rc, rc);
393
394 /* Number of states. */
395 uint32_t cTextureStates;
396 rc = pHlp->pfnSSMGetU32(pSSM, &cTextureStates);
397 AssertRCReturn(rc, rc);
398
399 for (uint32_t iStage = 0; iStage < cStages; ++iStage)
400 {
401 for (uint32_t j = 0; j < cTextureStates; ++j)
402 {
403 SVGA3dTextureState textureState;
404 pHlp->pfnSSMGetU32(pSSM, &textureState.stage);
405 uint32_t u32Name;
406 pHlp->pfnSSMGetU32(pSSM, &u32Name);
407 textureState.name = (SVGA3dTextureStateName)u32Name;
408 rc = pHlp->pfnSSMGetU32(pSSM, &textureState.value);
409 AssertRCReturn(rc, rc);
410
411 if ( iStage < RT_ELEMENTS(pContext->state.aTextureStates)
412 && j < RT_ELEMENTS(pContext->state.aTextureStates[0]))
413 {
414 pContext->state.aTextureStates[iStage][j] = textureState;
415 }
416 }
417 }
418 }
419
420 if (uVersion >= VGA_SAVEDSTATE_VERSION_VMSVGA)
421 {
422 VMSVGA3DQUERY query;
423 RT_ZERO(query);
424
425 rc = pHlp->pfnSSMGetStructEx(pSSM, &query, sizeof(query), 0, g_aVMSVGA3DQUERYFields, NULL);
426 AssertRCReturn(rc, rc);
427
428 switch (query.enmQueryState)
429 {
430 case VMSVGA3DQUERYSTATE_BUILDING:
431 /* Start collecting data. */
432 vmsvga3dQueryBegin(pThisCC, cid, SVGA3D_QUERYTYPE_OCCLUSION);
433 /* Partial result. */
434 pContext->occlusion.u32QueryResult = query.u32QueryResult;
435 break;
436
437 case VMSVGA3DQUERYSTATE_ISSUED:
438 /* Guest ended the query but did not read result. Result is restored. */
439 query.enmQueryState = VMSVGA3DQUERYSTATE_SIGNALED;
440 RT_FALL_THRU();
441 case VMSVGA3DQUERYSTATE_SIGNALED:
442 /* Create the query object. */
443 vmsvga3dQueryCreate(pThisCC, cid, SVGA3D_QUERYTYPE_OCCLUSION);
444
445 /* Update result and state. */
446 pContext->occlusion.enmQueryState = query.enmQueryState;
447 pContext->occlusion.u32QueryResult = query.u32QueryResult;
448 break;
449
450 default:
451 AssertFailed();
452 RT_FALL_THRU();
453 case VMSVGA3DQUERYSTATE_NULL:
454 RT_ZERO(pContext->occlusion);
455 break;
456 }
457 }
458 }
459 }
460
461#ifdef VMSVGA3D_OPENGL
462 /* Make the shared context the current one. */
463 if (pState->SharedCtx.id == VMSVGA3D_SHARED_CTX_ID)
464 VMSVGA3D_SET_CURRENT_CONTEXT(pState, &pState->SharedCtx);
465#endif
466
467 /* Fetch all surfaces. */
468 for (uint32_t i = 0; i < cSurfaces; i++)
469 {
470 uint32_t sid;
471
472 /* Fetch the id first. */
473 rc = pHlp->pfnSSMGetU32(pSSM, &sid);
474 AssertRCReturn(rc, rc);
475
476 if (sid != SVGA3D_INVALID_ID)
477 {
478 VMSVGA3DSURFACE surface;
479 LogFlow(("vmsvga3dLoadExec: Loading sid=%#x\n", sid));
480
481 /* Fetch the surface structure first. */
482 if (RT_LIKELY(uVersion >= VGA_SAVEDSTATE_VERSION_VMSVGA_MIPLEVELS))
483 rc = pHlp->pfnSSMGetStructEx(pSSM, &surface, sizeof(surface), 0, g_aVMSVGA3DSURFACEFields, NULL);
484 else
485 rc = vmsvga3dLoadVMSVGA3DSURFACEPreMipLevels(pDevIns, pSSM, &surface);
486 AssertRCReturn(rc, rc);
487
488 {
489 uint32_t cMipLevels = surface.cLevels * surface.cFaces;
490 PVMSVGA3DMIPMAPLEVEL pMipmapLevel = (PVMSVGA3DMIPMAPLEVEL)RTMemAlloc(cMipLevels * sizeof(VMSVGA3DMIPMAPLEVEL));
491 AssertReturn(pMipmapLevel, VERR_NO_MEMORY);
492 SVGA3dSize *pMipmapLevelSize = (SVGA3dSize *)RTMemAlloc(cMipLevels * sizeof(SVGA3dSize));
493 AssertReturn(pMipmapLevelSize, VERR_NO_MEMORY);
494
495 /* Load the mip map level info. */
496 for (uint32_t face=0; face < surface.cFaces; face++)
497 {
498 for (uint32_t j = 0; j < surface.cLevels; j++)
499 {
500 uint32_t idx = j + face * surface.cLevels;
501 /* Load the mip map level struct. */
502 rc = pHlp->pfnSSMGetStructEx(pSSM, &pMipmapLevel[idx], sizeof(pMipmapLevel[idx]), 0,
503 g_aVMSVGA3DMIPMAPLEVELFields, NULL);
504 AssertRCReturn(rc, rc);
505
506 pMipmapLevelSize[idx] = pMipmapLevel[idx].mipmapSize;
507 }
508 }
509
510 rc = vmsvga3dSurfaceDefine(pThisCC, sid, surface.surfaceFlags, surface.format, surface.multiSampleCount,
511 surface.autogenFilter, surface.cLevels, &pMipmapLevelSize[0]);
512 AssertRCReturn(rc, rc);
513
514 RTMemFree(pMipmapLevelSize);
515 RTMemFree(pMipmapLevel);
516 }
517
518 PVMSVGA3DSURFACE pSurface = pState->papSurfaces[sid];
519 Assert(pSurface->id == sid);
520
521 pSurface->fDirty = false;
522
523 /* Load the mip map level data. */
524 for (uint32_t j = 0; j < pSurface->cLevels * pSurface->cFaces; j++)
525 {
526 PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->paMipmapLevels[j];
527 bool fDataPresent = false;
528
529 /* vmsvga3dSurfaceDefine already allocated the surface data buffer. */
530 Assert(pMipmapLevel->cbSurface);
531 AssertReturn(pMipmapLevel->pSurfaceData, VERR_INTERNAL_ERROR);
532
533 /* Fetch the data present boolean first. */
534 rc = pHlp->pfnSSMGetBool(pSSM, &fDataPresent);
535 AssertRCReturn(rc, rc);
536
537 Log(("Surface sid=%u: load mipmap level %d with %x bytes data (present=%d).\n", sid, j, pMipmapLevel->cbSurface, fDataPresent));
538
539 if (fDataPresent)
540 {
541 rc = pHlp->pfnSSMGetMem(pSSM, pMipmapLevel->pSurfaceData, pMipmapLevel->cbSurface);
542 AssertRCReturn(rc, rc);
543 pMipmapLevel->fDirty = true;
544 pSurface->fDirty = true;
545 }
546 else
547 {
548 pMipmapLevel->fDirty = false;
549 }
550 }
551 }
552 }
553
554#ifdef VMSVGA3D_OPENGL
555 /* Reinitialize the shared context. */
556 LogFlow(("vmsvga3dLoadExec: pState->SharedCtx.id=%#x\n", pState->SharedCtx.id));
557 if (pState->SharedCtx.id == VMSVGA3D_SHARED_CTX_ID)
558 {
559 rc = vmsvga3dLoadReinitContext(pThisCC, &pState->SharedCtx);
560 AssertRCReturn(rc, rc);
561 }
562#endif
563
564 /* Reinitialize all active contexts. */
565 for (uint32_t i = 0; i < pState->cContexts; i++)
566 {
567 PVMSVGA3DCONTEXT pContext = pState->papContexts[i];
568 if (pContext->id != SVGA3D_INVALID_ID)
569 {
570 rc = vmsvga3dLoadReinitContext(pThisCC, pContext);
571 AssertRCReturn(rc, rc);
572 }
573 }
574
575 LogFlow(("vmsvga3dLoadExec: return success\n"));
576 return VINF_SUCCESS;
577}
578
579
580static int vmsvga3dSaveContext(PCPDMDEVHLPR3 pHlp, PVGASTATECC pThisCC, PSSMHANDLE pSSM, PVMSVGA3DCONTEXT pContext)
581{
582 uint32_t cid = pContext->id;
583
584 /* Save the id first. */
585 int rc = pHlp->pfnSSMPutU32(pSSM, cid);
586 AssertRCReturn(rc, rc);
587
588 if (cid != SVGA3D_INVALID_ID)
589 {
590 /* Save a copy of the context structure first. */
591 rc = pHlp->pfnSSMPutStructEx(pSSM, pContext, sizeof(*pContext), 0, g_aVMSVGA3DCONTEXTFields, NULL);
592 AssertRCReturn(rc, rc);
593
594 /* Save all pixel shaders. */
595 for (uint32_t j = 0; j < pContext->cPixelShaders; j++)
596 {
597 PVMSVGA3DSHADER pShader = &pContext->paPixelShader[j];
598
599 /* Save the id first. */
600 rc = pHlp->pfnSSMPutU32(pSSM, pShader->id);
601 AssertRCReturn(rc, rc);
602
603 if (pShader->id != SVGA3D_INVALID_ID)
604 {
605 uint32_t cbData = pShader->cbData;
606
607 /* Save a copy of the shader struct. */
608 rc = pHlp->pfnSSMPutStructEx(pSSM, pShader, sizeof(*pShader), 0, g_aVMSVGA3DSHADERFields, NULL);
609 AssertRCReturn(rc, rc);
610
611 Log(("Save pixelshader shid=%d with %x bytes code.\n", pShader->id, cbData));
612 rc = pHlp->pfnSSMPutMem(pSSM, pShader->pShaderProgram, cbData);
613 AssertRCReturn(rc, rc);
614 }
615 }
616
617 /* Save all vertex shaders. */
618 for (uint32_t j = 0; j < pContext->cVertexShaders; j++)
619 {
620 PVMSVGA3DSHADER pShader = &pContext->paVertexShader[j];
621
622 /* Save the id first. */
623 rc = pHlp->pfnSSMPutU32(pSSM, pShader->id);
624 AssertRCReturn(rc, rc);
625
626 if (pShader->id != SVGA3D_INVALID_ID)
627 {
628 uint32_t cbData = pShader->cbData;
629
630 /* Save a copy of the shader struct. */
631 rc = pHlp->pfnSSMPutStructEx(pSSM, pShader, sizeof(*pShader), 0, g_aVMSVGA3DSHADERFields, NULL);
632 AssertRCReturn(rc, rc);
633
634 Log(("Save vertex shader shid=%d with %x bytes code.\n", pShader->id, cbData));
635 /* Fetch the shader code and save it. */
636 rc = pHlp->pfnSSMPutMem(pSSM, pShader->pShaderProgram, cbData);
637 AssertRCReturn(rc, rc);
638 }
639 }
640
641 /* Save pixel shader constants. */
642 for (uint32_t j = 0; j < pContext->state.cPixelShaderConst; j++)
643 {
644 rc = pHlp->pfnSSMPutStructEx(pSSM, &pContext->state.paPixelShaderConst[j], sizeof(pContext->state.paPixelShaderConst[j]), 0, g_aVMSVGASHADERCONSTFields, NULL);
645 AssertRCReturn(rc, rc);
646 }
647
648 /* Save vertex shader constants. */
649 for (uint32_t j = 0; j < pContext->state.cVertexShaderConst; j++)
650 {
651 rc = pHlp->pfnSSMPutStructEx(pSSM, &pContext->state.paVertexShaderConst[j], sizeof(pContext->state.paVertexShaderConst[j]), 0, g_aVMSVGASHADERCONSTFields, NULL);
652 AssertRCReturn(rc, rc);
653 }
654
655 /* Save texture stage and samplers state. */
656
657 /* Number of stages/samplers. */
658 rc = pHlp->pfnSSMPutU32(pSSM, RT_ELEMENTS(pContext->state.aTextureStates));
659 AssertRCReturn(rc, rc);
660
661 /* Number of texture states. */
662 rc = pHlp->pfnSSMPutU32(pSSM, RT_ELEMENTS(pContext->state.aTextureStates[0]));
663 AssertRCReturn(rc, rc);
664
665 for (uint32_t iStage = 0; iStage < RT_ELEMENTS(pContext->state.aTextureStates); ++iStage)
666 {
667 for (uint32_t j = 0; j < RT_ELEMENTS(pContext->state.aTextureStates[0]); ++j)
668 {
669 SVGA3dTextureState *pTextureState = &pContext->state.aTextureStates[iStage][j];
670
671 pHlp->pfnSSMPutU32(pSSM, pTextureState->stage);
672 pHlp->pfnSSMPutU32(pSSM, pTextureState->name);
673 rc = pHlp->pfnSSMPutU32(pSSM, pTextureState->value);
674 AssertRCReturn(rc, rc);
675 }
676 }
677
678 /* Occlusion query. */
679 if (!VMSVGA3DQUERY_EXISTS(&pContext->occlusion))
680 {
681 pContext->occlusion.enmQueryState = VMSVGA3DQUERYSTATE_NULL;
682 }
683
684 /* Save the current query state, because code below can change it. */
685 VMSVGA3DQUERYSTATE const enmQueryState = pContext->occlusion.enmQueryState;
686 switch (enmQueryState)
687 {
688 case VMSVGA3DQUERYSTATE_BUILDING:
689 /* Stop collecting data. Fetch partial result. Save result. */
690 vmsvga3dQueryEnd(pThisCC, cid, SVGA3D_QUERYTYPE_OCCLUSION);
691 RT_FALL_THRU();
692 case VMSVGA3DQUERYSTATE_ISSUED:
693 /* Fetch result. Save result. */
694 pContext->occlusion.u32QueryResult = 0;
695 vmsvga3dQueryWait(pThisCC, cid, SVGA3D_QUERYTYPE_OCCLUSION, NULL, NULL);
696 RT_FALL_THRU();
697 case VMSVGA3DQUERYSTATE_SIGNALED:
698 /* Save result. Nothing to do here. */
699 break;
700
701 default:
702 AssertFailed();
703 RT_FALL_THRU();
704 case VMSVGA3DQUERYSTATE_NULL:
705 pContext->occlusion.enmQueryState = VMSVGA3DQUERYSTATE_NULL;
706 pContext->occlusion.u32QueryResult = 0;
707 break;
708 }
709
710 /* Restore the current actual state. */
711 pContext->occlusion.enmQueryState = enmQueryState;
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_D3D11)
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