~ubuntu-branches/ubuntu/trusty/virtualbox-lts-xenial/trusty-proposed

« back to all changes in this revision

Viewing changes to src/VBox/Devices/Graphics/DevVGA-SVGA3d-savedstate.cpp

  • Committer: Package Import Robot
  • Author(s): Gianfranco Costamagna
  • Date: 2016-02-23 14:28:26 UTC
  • Revision ID: package-import@ubuntu.com-20160223142826-bdu69el2z6wa2a44
Tags: upstream-4.3.36-dfsg
ImportĀ upstreamĀ versionĀ 4.3.36-dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: DevVGA-SVGA3d-savedstate.cpp $ */
 
2
/** @file
 
3
 * DevSVGA3d - VMWare SVGA device, 3D parts - Saved state and assocated stuff.
 
4
 */
 
5
 
 
6
/*
 
7
 * Copyright (C) 2013-2015 Oracle Corporation
 
8
 *
 
9
 * This file is part of VirtualBox Open Source Edition (OSE), as
 
10
 * available from http://www.virtualbox.org. This file is free software;
 
11
 * you can redistribute it and/or modify it under the terms of the GNU
 
12
 * General Public License (GPL) as published by the Free Software
 
13
 * Foundation, in version 2 as it comes in the "COPYING" file of the
 
14
 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
 
15
 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
 
16
 */
 
17
 
 
18
 
 
19
/*********************************************************************************************************************************
 
20
*   Header Files                                                                                                                 *
 
21
*********************************************************************************************************************************/
 
22
#define LOG_GROUP LOG_GROUP_DEV_VMSVGA
 
23
#include <VBox/vmm/pdmdev.h>
 
24
#include <VBox/err.h>
 
25
#include <VBox/log.h>
 
26
 
 
27
#include <iprt/assert.h>
 
28
#include <iprt/mem.h>
 
29
 
 
30
#include <VBox/vmm/pgm.h> /* required by DevVGA.h */
 
31
#include <VBox/VBoxVideo.h> /* required by DevVGA.h */
 
32
 
 
33
/* should go BEFORE any other DevVGA include to make all DevVGA.h config defines be visible */
 
34
#include "DevVGA.h"
 
35
 
 
36
#include "DevVGA-SVGA.h"
 
37
#include "DevVGA-SVGA3d.h"
 
38
#define VMSVGA3D_INCL_STRUCTURE_DESCRIPTORS
 
39
#include "DevVGA-SVGA3d-internal.h"
 
40
 
 
41
 
 
42
 
 
43
/**
 
44
 * Reinitializes an active context.
 
45
 *
 
46
 * @returns VBox status code.
 
47
 * @param   pThis               The VMSVGA device state.
 
48
 * @param   pContext            The freshly loaded context to reinitialize.
 
49
 */
 
50
static int vmsvga3dLoadReinitContext(PVGASTATE pThis, PVMSVGA3DCONTEXT pContext)
 
51
{
 
52
    int      rc;
 
53
    uint32_t cid = pContext->id;
 
54
    Assert(cid != SVGA3D_INVALID_ID);
 
55
 
 
56
    /* First set the render targets as they change the internal state (reset viewport etc) */
 
57
    Log(("vmsvga3dLoadReinitContext: Recreate render targets BEGIN [cid=%#x]\n", cid));
 
58
    for (uint32_t j = 0; j < RT_ELEMENTS(pContext->state.aRenderTargets); j++)
 
59
    {
 
60
        if (pContext->state.aRenderTargets[j] != SVGA3D_INVALID_ID)
 
61
        {
 
62
            SVGA3dSurfaceImageId target;
 
63
 
 
64
            target.sid      = pContext->state.aRenderTargets[j];
 
65
            target.face     = 0;
 
66
            target.mipmap   = 0;
 
67
            rc = vmsvga3dSetRenderTarget(pThis, cid, (SVGA3dRenderTargetType)j, target);
 
68
            AssertRCReturn(rc, rc);
 
69
        }
 
70
    }
 
71
    Log(("vmsvga3dLoadReinitContext: Recreate render targets END\n"));
 
72
 
 
73
    /* Recreate the render state */
 
74
    Log(("vmsvga3dLoadReinitContext: Recreate render state BEGIN\n"));
 
75
    for (uint32_t j = 0; j < RT_ELEMENTS(pContext->state.aRenderState); j++)
 
76
    {
 
77
        SVGA3dRenderState *pRenderState = &pContext->state.aRenderState[j];
 
78
 
 
79
        if (pRenderState->state != SVGA3D_RS_INVALID)
 
80
            vmsvga3dSetRenderState(pThis, pContext->id, 1, pRenderState);
 
81
    }
 
82
    Log(("vmsvga3dLoadReinitContext: Recreate render state END\n"));
 
83
 
 
84
    /* Recreate the texture state */
 
85
    Log(("vmsvga3dLoadReinitContext: Recreate texture state BEGIN\n"));
 
86
    for (uint32_t iStage = 0; iStage < SVGA3D_MAX_TEXTURE_STAGE; iStage++)
 
87
    {
 
88
        for (uint32_t j = 0; j < SVGA3D_TS_MAX; j++)
 
89
        {
 
90
            SVGA3dTextureState *pTextureState = &pContext->state.aTextureState[iStage][j];
 
91
 
 
92
            if (pTextureState->name != SVGA3D_TS_INVALID)
 
93
                vmsvga3dSetTextureState(pThis, pContext->id, 1, pTextureState);
 
94
        }
 
95
    }
 
96
    Log(("vmsvga3dLoadReinitContext: Recreate texture state END\n"));
 
97
 
 
98
    /* Reprogram the clip planes. */
 
99
    for (uint32_t j = 0; j < RT_ELEMENTS(pContext->state.aClipPlane); j++)
 
100
    {
 
101
        if (pContext->state.aClipPlane[j].fValid == true)
 
102
            vmsvga3dSetClipPlane(pThis, cid, j, pContext->state.aClipPlane[j].plane);
 
103
    }
 
104
 
 
105
    /* Reprogram the light data. */
 
106
    for (uint32_t j = 0; j < RT_ELEMENTS(pContext->state.aLightData); j++)
 
107
    {
 
108
        if (pContext->state.aLightData[j].fValidData == true)
 
109
            vmsvga3dSetLightData(pThis, cid, j, &pContext->state.aLightData[j].data);
 
110
        if (pContext->state.aLightData[j].fEnabled)
 
111
            vmsvga3dSetLightEnabled(pThis, cid, j, true);
 
112
    }
 
113
 
 
114
    /* Recreate the transform state. */
 
115
    if (pContext->state.u32UpdateFlags & VMSVGA3D_UPDATE_TRANSFORM)
 
116
    {
 
117
        for (uint32_t j = 0; j < RT_ELEMENTS(pContext->state.aTransformState); j++)
 
118
        {
 
119
            if (pContext->state.aTransformState[j].fValid == true)
 
120
                vmsvga3dSetTransform(pThis, cid, (SVGA3dTransformType)j, pContext->state.aTransformState[j].matrix);
 
121
        }
 
122
    }
 
123
 
 
124
    /* Reprogram the material data. */
 
125
    if (pContext->state.u32UpdateFlags & VMSVGA3D_UPDATE_MATERIAL)
 
126
    {
 
127
        for (uint32_t j = 0; j < RT_ELEMENTS(pContext->state.aMaterial); j++)
 
128
        {
 
129
            if (pContext->state.aMaterial[j].fValid == true)
 
130
                vmsvga3dSetMaterial(pThis, cid, (SVGA3dFace)j, &pContext->state.aMaterial[j].material);
 
131
        }
 
132
    }
 
133
 
 
134
    if (pContext->state.u32UpdateFlags & VMSVGA3D_UPDATE_SCISSORRECT)
 
135
        vmsvga3dSetScissorRect(pThis, cid, &pContext->state.RectScissor);
 
136
    if (pContext->state.u32UpdateFlags & VMSVGA3D_UPDATE_ZRANGE)
 
137
        vmsvga3dSetZRange(pThis, cid, pContext->state.zRange);
 
138
    if (pContext->state.u32UpdateFlags & VMSVGA3D_UPDATE_VIEWPORT)
 
139
        vmsvga3dSetViewPort(pThis, cid, &pContext->state.RectViewPort);
 
140
    if (pContext->state.u32UpdateFlags & VMSVGA3D_UPDATE_VERTEXSHADER)
 
141
        vmsvga3dShaderSet(pThis, pContext, cid, SVGA3D_SHADERTYPE_VS, pContext->state.shidVertex);
 
142
    if (pContext->state.u32UpdateFlags & VMSVGA3D_UPDATE_PIXELSHADER)
 
143
        vmsvga3dShaderSet(pThis, pContext, cid, SVGA3D_SHADERTYPE_PS, pContext->state.shidPixel);
 
144
 
 
145
    Log(("vmsvga3dLoadReinitContext: returns [cid=%#x]\n", cid));
 
146
    return VINF_SUCCESS;
 
147
}
 
148
 
 
149
int vmsvga3dLoadExec(PVGASTATE pThis, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
 
150
{
 
151
    PVMSVGA3DSTATE pState = pThis->svga.p3dState;
 
152
    AssertReturn(pState, VERR_NO_MEMORY);
 
153
    int            rc;
 
154
    uint32_t       cContexts, cSurfaces;
 
155
    LogFlow(("vmsvga3dLoadExec:\n"));
 
156
 
 
157
#ifndef RT_OS_DARWIN /** @todo r=bird: this is normally done on the EMT, so for DARWIN we do that when loading saved state too now. See DevVGA-SVGA.cpp */
 
158
    /* Must initialize now as the recreation calls below rely on an initialized 3d subsystem. */
 
159
    vmsvga3dPowerOn(pThis);
 
160
#endif
 
161
 
 
162
    /* Get the generic 3d state first. */
 
163
    rc = SSMR3GetStructEx(pSSM, pState, sizeof(*pState), 0, g_aVMSVGA3DSTATEFields, NULL);
 
164
    AssertRCReturn(rc, rc);
 
165
 
 
166
    cContexts                           = pState->cContexts;
 
167
    cSurfaces                           = pState->cSurfaces;
 
168
    pState->cContexts                   = 0;
 
169
    pState->cSurfaces                   = 0;
 
170
 
 
171
    /* Fetch all active contexts. */
 
172
    for (uint32_t i = 0; i < cContexts; i++)
 
173
    {
 
174
        PVMSVGA3DCONTEXT pContext;
 
175
        uint32_t         cid;
 
176
 
 
177
        /* Get the context id */
 
178
        rc = SSMR3GetU32(pSSM, &cid);
 
179
        AssertRCReturn(rc, rc);
 
180
 
 
181
        if (cid != SVGA3D_INVALID_ID)
 
182
        {
 
183
            uint32_t cPixelShaderConst, cVertexShaderConst, cPixelShaders, cVertexShaders;
 
184
            LogFlow(("vmsvga3dLoadExec: Loading cid=%#x\n", cid));
 
185
 
 
186
#ifdef VMSVGA3D_OPENGL
 
187
            if (cid == VMSVGA3D_SHARED_CTX_ID)
 
188
            {
 
189
                i--; /* Not included in cContexts. */
 
190
                pContext = &pState->SharedCtx;
 
191
                if (pContext->id != VMSVGA3D_SHARED_CTX_ID)
 
192
                {
 
193
                    rc = vmsvga3dContextDefineOgl(pThis, VMSVGA3D_SHARED_CTX_ID, VMSVGA3D_DEF_CTX_F_SHARED_CTX);
 
194
                    AssertRCReturn(rc, rc);
 
195
                }
 
196
            }
 
197
            else
 
198
#endif
 
199
            {
 
200
                rc = vmsvga3dContextDefine(pThis, cid);
 
201
                AssertRCReturn(rc, rc);
 
202
 
 
203
                pContext = pState->papContexts[i];
 
204
            }
 
205
            AssertReturn(pContext->id == cid, VERR_INTERNAL_ERROR);
 
206
 
 
207
            rc = SSMR3GetStructEx(pSSM, pContext, sizeof(*pContext), 0, g_aVMSVGA3DCONTEXTFields, NULL);
 
208
            AssertRCReturn(rc, rc);
 
209
 
 
210
            cPixelShaders                       = pContext->cPixelShaders;
 
211
            cVertexShaders                      = pContext->cVertexShaders;
 
212
            cPixelShaderConst                   = pContext->state.cPixelShaderConst;
 
213
            cVertexShaderConst                  = pContext->state.cVertexShaderConst;
 
214
            pContext->cPixelShaders             = 0;
 
215
            pContext->cVertexShaders            = 0;
 
216
            pContext->state.cPixelShaderConst   = 0;
 
217
            pContext->state.cVertexShaderConst  = 0;
 
218
 
 
219
            /* Fetch all pixel shaders. */
 
220
            for (uint32_t j = 0; j < cPixelShaders; j++)
 
221
            {
 
222
                VMSVGA3DSHADER  shader;
 
223
                uint32_t        shid;
 
224
 
 
225
                /* Fetch the id first. */
 
226
                rc = SSMR3GetU32(pSSM, &shid);
 
227
                AssertRCReturn(rc, rc);
 
228
 
 
229
                if (shid != SVGA3D_INVALID_ID)
 
230
                {
 
231
                    uint32_t *pData;
 
232
 
 
233
                    /* Fetch a copy of the shader struct. */
 
234
                    rc = SSMR3GetStructEx(pSSM, &shader, sizeof(shader), 0, g_aVMSVGA3DSHADERFields, NULL);
 
235
                    AssertRCReturn(rc, rc);
 
236
 
 
237
                    pData = (uint32_t *)RTMemAlloc(shader.cbData);
 
238
                    AssertReturn(pData, VERR_NO_MEMORY);
 
239
 
 
240
                    rc = SSMR3GetMem(pSSM, pData, shader.cbData);
 
241
                    AssertRCReturn(rc, rc);
 
242
 
 
243
                    rc = vmsvga3dShaderDefine(pThis, cid, shid, shader.type, shader.cbData, pData);
 
244
                    AssertRCReturn(rc, rc);
 
245
 
 
246
                    RTMemFree(pData);
 
247
                }
 
248
            }
 
249
 
 
250
            /* Fetch all vertex shaders. */
 
251
            for (uint32_t j = 0; j < cVertexShaders; j++)
 
252
            {
 
253
                VMSVGA3DSHADER  shader;
 
254
                uint32_t        shid;
 
255
 
 
256
                /* Fetch the id first. */
 
257
                rc = SSMR3GetU32(pSSM, &shid);
 
258
                AssertRCReturn(rc, rc);
 
259
 
 
260
                if (shid != SVGA3D_INVALID_ID)
 
261
                {
 
262
                    uint32_t *pData;
 
263
 
 
264
                    /* Fetch a copy of the shader struct. */
 
265
                    rc = SSMR3GetStructEx(pSSM, &shader, sizeof(shader), 0, g_aVMSVGA3DSHADERFields, NULL);
 
266
                    AssertRCReturn(rc, rc);
 
267
 
 
268
                    pData = (uint32_t *)RTMemAlloc(shader.cbData);
 
269
                    AssertReturn(pData, VERR_NO_MEMORY);
 
270
 
 
271
                    rc = SSMR3GetMem(pSSM, pData, shader.cbData);
 
272
                    AssertRCReturn(rc, rc);
 
273
 
 
274
                    rc = vmsvga3dShaderDefine(pThis, cid, shid, shader.type, shader.cbData, pData);
 
275
                    AssertRCReturn(rc, rc);
 
276
 
 
277
                    RTMemFree(pData);
 
278
                }
 
279
            }
 
280
 
 
281
            /* Fetch pixel shader constants. */
 
282
            for (uint32_t j = 0; j < cPixelShaderConst; j++)
 
283
            {
 
284
                VMSVGASHADERCONST ShaderConst;
 
285
 
 
286
                rc = SSMR3GetStructEx(pSSM, &ShaderConst, sizeof(ShaderConst), 0, g_aVMSVGASHADERCONSTFields, NULL);
 
287
                AssertRCReturn(rc, rc);
 
288
 
 
289
                if (ShaderConst.fValid)
 
290
                {
 
291
                    rc = vmsvga3dShaderSetConst(pThis, cid, j, SVGA3D_SHADERTYPE_PS, ShaderConst.ctype, 1, ShaderConst.value);
 
292
                    AssertRCReturn(rc, rc);
 
293
                }
 
294
            }
 
295
 
 
296
            /* Fetch vertex shader constants. */
 
297
            for (uint32_t j = 0; j < cVertexShaderConst; j++)
 
298
            {
 
299
                VMSVGASHADERCONST ShaderConst;
 
300
 
 
301
                rc = SSMR3GetStructEx(pSSM, &ShaderConst, sizeof(ShaderConst), 0, g_aVMSVGASHADERCONSTFields, NULL);
 
302
                AssertRCReturn(rc, rc);
 
303
 
 
304
                if (ShaderConst.fValid)
 
305
                {
 
306
                    rc = vmsvga3dShaderSetConst(pThis, cid, j, SVGA3D_SHADERTYPE_VS, ShaderConst.ctype, 1, ShaderConst.value);
 
307
                    AssertRCReturn(rc, rc);
 
308
                }
 
309
            }
 
310
        }
 
311
    }
 
312
 
 
313
#ifdef VMSVGA3D_OPENGL
 
314
    /* Make the shared context the current one. */
 
315
    if (pState->SharedCtx.id == VMSVGA3D_SHARED_CTX_ID)
 
316
        VMSVGA3D_SET_CURRENT_CONTEXT(pState, &pState->SharedCtx);
 
317
#endif
 
318
 
 
319
    /* Fetch all surfaces. */
 
320
    for (uint32_t i = 0; i < cSurfaces; i++)
 
321
    {
 
322
        uint32_t sid;
 
323
 
 
324
        /* Fetch the id first. */
 
325
        rc = SSMR3GetU32(pSSM, &sid);
 
326
        AssertRCReturn(rc, rc);
 
327
 
 
328
        if (sid != SVGA3D_INVALID_ID)
 
329
        {
 
330
            VMSVGA3DSURFACE  surface;
 
331
            LogFlow(("vmsvga3dLoadExec: Loading sid=%#x\n", sid));
 
332
 
 
333
            /* Fetch the surface structure first. */
 
334
            rc = SSMR3GetStructEx(pSSM, &surface, sizeof(surface), 0, g_aVMSVGA3DSURFACEFields, NULL);
 
335
            AssertRCReturn(rc, rc);
 
336
 
 
337
            {
 
338
                uint32_t             cMipLevels = surface.faces[0].numMipLevels * surface.cFaces;
 
339
                PVMSVGA3DMIPMAPLEVEL pMipmapLevel = (PVMSVGA3DMIPMAPLEVEL)RTMemAlloc(cMipLevels * sizeof(VMSVGA3DMIPMAPLEVEL));
 
340
                AssertReturn(pMipmapLevel, VERR_NO_MEMORY);
 
341
                SVGA3dSize *pMipmapLevelSize = (SVGA3dSize *)RTMemAlloc(cMipLevels * sizeof(SVGA3dSize));
 
342
                AssertReturn(pMipmapLevelSize, VERR_NO_MEMORY);
 
343
 
 
344
                /* Load the mip map level info. */
 
345
                for (uint32_t face=0; face < surface.cFaces; face++)
 
346
                {
 
347
                    for (uint32_t j = 0; j < surface.faces[0].numMipLevels; j++)
 
348
                    {
 
349
                        uint32_t idx = j + face * surface.faces[0].numMipLevels;
 
350
                        /* Load the mip map level struct. */
 
351
                        rc = SSMR3GetStructEx(pSSM, &pMipmapLevel[idx], sizeof(pMipmapLevel[idx]), 0, g_aVMSVGA3DMIPMAPLEVELFields, NULL);
 
352
                        AssertRCReturn(rc, rc);
 
353
 
 
354
                        pMipmapLevelSize[idx] = pMipmapLevel[idx].size;
 
355
                    }
 
356
                }
 
357
 
 
358
                rc = vmsvga3dSurfaceDefine(pThis, sid, surface.flags, surface.format, surface.faces, surface.multiSampleCount, surface.autogenFilter, cMipLevels, pMipmapLevelSize);
 
359
                AssertRCReturn(rc, rc);
 
360
 
 
361
                RTMemFree(pMipmapLevelSize);
 
362
                RTMemFree(pMipmapLevel);
 
363
            }
 
364
 
 
365
            PVMSVGA3DSURFACE pSurface = pState->papSurfaces[sid];
 
366
            Assert(pSurface->id == sid);
 
367
 
 
368
            pSurface->fDirty = false;
 
369
 
 
370
            /* Load the mip map level data. */
 
371
            for (uint32_t j = 0; j < pSurface->faces[0].numMipLevels * pSurface->cFaces; j++)
 
372
            {
 
373
                PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->pMipmapLevels[j];
 
374
                bool fDataPresent = false;
 
375
 
 
376
                Assert(pMipmapLevel->cbSurface);
 
377
                pMipmapLevel->pSurfaceData = RTMemAllocZ(pMipmapLevel->cbSurface);
 
378
                AssertReturn(pMipmapLevel->pSurfaceData, VERR_NO_MEMORY);
 
379
 
 
380
                /* Fetch the data present boolean first. */
 
381
                rc = SSMR3GetBool(pSSM, &fDataPresent);
 
382
                AssertRCReturn(rc, rc);
 
383
 
 
384
                Log(("Surface sid=%x: load mipmap level %d with %x bytes data (present=%d).\n", sid, j, pMipmapLevel->cbSurface, fDataPresent));
 
385
 
 
386
                if (fDataPresent)
 
387
                {
 
388
                    rc = SSMR3GetMem(pSSM, pMipmapLevel->pSurfaceData, pMipmapLevel->cbSurface);
 
389
                    AssertRCReturn(rc, rc);
 
390
                    pMipmapLevel->fDirty = true;
 
391
                    pSurface->fDirty     = true;
 
392
                }
 
393
                else
 
394
                {
 
395
                    pMipmapLevel->fDirty = false;
 
396
                }
 
397
            }
 
398
        }
 
399
    }
 
400
 
 
401
#ifdef VMSVGA3D_OPENGL
 
402
    /* Reinitialize the shared context. */
 
403
    LogFlow(("vmsvga3dLoadExec: pState->SharedCtx.id=%#x\n", pState->SharedCtx.id));
 
404
    if (pState->SharedCtx.id == VMSVGA3D_SHARED_CTX_ID)
 
405
    {
 
406
        rc = vmsvga3dLoadReinitContext(pThis, &pState->SharedCtx);
 
407
        AssertRCReturn(rc, rc);
 
408
    }
 
409
#endif
 
410
 
 
411
    /* Reinitialize all active contexts. */
 
412
    for (uint32_t i = 0; i < pState->cContexts; i++)
 
413
    {
 
414
        PVMSVGA3DCONTEXT pContext = pState->papContexts[i];
 
415
        if (pContext->id != SVGA3D_INVALID_ID)
 
416
        {
 
417
            rc = vmsvga3dLoadReinitContext(pThis, pContext);
 
418
            AssertRCReturn(rc, rc);
 
419
        }
 
420
    }
 
421
 
 
422
    LogFlow(("vmsvga3dLoadExec: return success\n"));
 
423
    return VINF_SUCCESS;
 
424
}
 
425
 
 
426
 
 
427
static int vmsvga3dSaveContext(PVGASTATE pThis, PSSMHANDLE pSSM, PVMSVGA3DCONTEXT pContext)
 
428
{
 
429
    uint32_t cid = pContext->id;
 
430
 
 
431
    /* Save the id first. */
 
432
    int rc = SSMR3PutU32(pSSM, cid);
 
433
    AssertRCReturn(rc, rc);
 
434
 
 
435
    if (cid != SVGA3D_INVALID_ID)
 
436
    {
 
437
        /* Save a copy of the context structure first. */
 
438
        rc = SSMR3PutStructEx(pSSM, pContext, sizeof(*pContext), 0, g_aVMSVGA3DCONTEXTFields, NULL);
 
439
        AssertRCReturn(rc, rc);
 
440
 
 
441
        /* Save all pixel shaders. */
 
442
        for (uint32_t j = 0; j < pContext->cPixelShaders; j++)
 
443
        {
 
444
            PVMSVGA3DSHADER pShader = &pContext->paPixelShader[j];
 
445
 
 
446
            /* Save the id first. */
 
447
            rc = SSMR3PutU32(pSSM, pShader->id);
 
448
            AssertRCReturn(rc, rc);
 
449
 
 
450
            if (pShader->id != SVGA3D_INVALID_ID)
 
451
            {
 
452
                uint32_t cbData = pShader->cbData;
 
453
 
 
454
                /* Save a copy of the shader struct. */
 
455
                rc = SSMR3PutStructEx(pSSM, pShader, sizeof(*pShader), 0, g_aVMSVGA3DSHADERFields, NULL);
 
456
                AssertRCReturn(rc, rc);
 
457
 
 
458
                Log(("Save pixelshader shid=%d with %x bytes code.\n", pShader->id, cbData));
 
459
                rc = SSMR3PutMem(pSSM, pShader->pShaderProgram, cbData);
 
460
                AssertRCReturn(rc, rc);
 
461
            }
 
462
        }
 
463
 
 
464
        /* Save all vertex shaders. */
 
465
        for (uint32_t j = 0; j < pContext->cVertexShaders; j++)
 
466
        {
 
467
            PVMSVGA3DSHADER pShader = &pContext->paVertexShader[j];
 
468
 
 
469
            /* Save the id first. */
 
470
            rc = SSMR3PutU32(pSSM, pShader->id);
 
471
            AssertRCReturn(rc, rc);
 
472
 
 
473
            if (pShader->id != SVGA3D_INVALID_ID)
 
474
            {
 
475
                uint32_t cbData = pShader->cbData;
 
476
 
 
477
                /* Save a copy of the shader struct. */
 
478
                rc = SSMR3PutStructEx(pSSM, pShader, sizeof(*pShader), 0, g_aVMSVGA3DSHADERFields, NULL);
 
479
                AssertRCReturn(rc, rc);
 
480
 
 
481
                Log(("Save vertex shader shid=%d with %x bytes code.\n", pShader->id, cbData));
 
482
                /* Fetch the shader code and save it. */
 
483
                rc = SSMR3PutMem(pSSM, pShader->pShaderProgram, cbData);
 
484
                AssertRCReturn(rc, rc);
 
485
            }
 
486
        }
 
487
 
 
488
        /* Save pixel shader constants. */
 
489
        for (uint32_t j = 0; j < pContext->state.cPixelShaderConst; j++)
 
490
        {
 
491
            rc = SSMR3PutStructEx(pSSM, &pContext->state.paPixelShaderConst[j], sizeof(pContext->state.paPixelShaderConst[j]), 0, g_aVMSVGASHADERCONSTFields, NULL);
 
492
            AssertRCReturn(rc, rc);
 
493
        }
 
494
 
 
495
        /* Save vertex shader constants. */
 
496
        for (uint32_t j = 0; j < pContext->state.cVertexShaderConst; j++)
 
497
        {
 
498
            rc = SSMR3PutStructEx(pSSM, &pContext->state.paVertexShaderConst[j], sizeof(pContext->state.paVertexShaderConst[j]), 0, g_aVMSVGASHADERCONSTFields, NULL);
 
499
            AssertRCReturn(rc, rc);
 
500
        }
 
501
    }
 
502
 
 
503
    return VINF_SUCCESS;
 
504
}
 
505
 
 
506
int vmsvga3dSaveExec(PVGASTATE pThis, PSSMHANDLE pSSM)
 
507
{
 
508
    PVMSVGA3DSTATE pState = pThis->svga.p3dState;
 
509
    AssertReturn(pState, VERR_NO_MEMORY);
 
510
    int            rc;
 
511
 
 
512
    /* Save a copy of the generic 3d state first. */
 
513
    rc = SSMR3PutStructEx(pSSM, pState, sizeof(*pState), 0, g_aVMSVGA3DSTATEFields, NULL);
 
514
    AssertRCReturn(rc, rc);
 
515
 
 
516
#ifdef VMSVGA3D_OPENGL
 
517
    /* Save the shared context. */
 
518
    if (pState->SharedCtx.id == VMSVGA3D_SHARED_CTX_ID)
 
519
    {
 
520
        rc = vmsvga3dSaveContext(pThis, pSSM, &pState->SharedCtx);
 
521
        AssertRCReturn(rc, rc);
 
522
    }
 
523
#endif
 
524
 
 
525
    /* Save all active contexts. */
 
526
    for (uint32_t i = 0; i < pState->cContexts; i++)
 
527
    {
 
528
        rc = vmsvga3dSaveContext(pThis, pSSM, pState->papContexts[i]);
 
529
        AssertRCReturn(rc, rc);
 
530
    }
 
531
 
 
532
    /* Save all active surfaces. */
 
533
    for (uint32_t sid = 0; sid < pState->cSurfaces; sid++)
 
534
    {
 
535
        PVMSVGA3DSURFACE pSurface = pState->papSurfaces[sid];
 
536
 
 
537
        /* Save the id first. */
 
538
        rc = SSMR3PutU32(pSSM, pSurface->id);
 
539
        AssertRCReturn(rc, rc);
 
540
 
 
541
        if (pSurface->id != SVGA3D_INVALID_ID)
 
542
        {
 
543
            /* Save a copy of the surface structure first. */
 
544
            rc = SSMR3PutStructEx(pSSM, pSurface, sizeof(*pSurface), 0, g_aVMSVGA3DSURFACEFields, NULL);
 
545
            AssertRCReturn(rc, rc);
 
546
 
 
547
            /* Save the mip map level info. */
 
548
            for (uint32_t face=0; face < pSurface->cFaces; face++)
 
549
            {
 
550
                for (uint32_t i = 0; i < pSurface->faces[0].numMipLevels; i++)
 
551
                {
 
552
                    uint32_t idx = i + face * pSurface->faces[0].numMipLevels;
 
553
                    PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->pMipmapLevels[idx];
 
554
 
 
555
                    /* Save a copy of the mip map level struct. */
 
556
                    rc = SSMR3PutStructEx(pSSM, pMipmapLevel, sizeof(*pMipmapLevel), 0, g_aVMSVGA3DMIPMAPLEVELFields, NULL);
 
557
                    AssertRCReturn(rc, rc);
 
558
                }
 
559
            }
 
560
 
 
561
            /* Save the mip map level data. */
 
562
            for (uint32_t face=0; face < pSurface->cFaces; face++)
 
563
            {
 
564
                for (uint32_t i = 0; i < pSurface->faces[0].numMipLevels; i++)
 
565
                {
 
566
                    uint32_t idx = i + face * pSurface->faces[0].numMipLevels;
 
567
                    PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->pMipmapLevels[idx];
 
568
 
 
569
                    Log(("Surface sid=%d: save mipmap level %d with %x bytes data.\n", sid, i, pMipmapLevel->cbSurface));
 
570
 
 
571
#ifdef VMSVGA3D_DIRECT3D
 
572
                    if (!pSurface->u.pSurface)
 
573
#else
 
574
                    if (pSurface->oglId.texture == OPENGL_INVALID_ID)
 
575
#endif
 
576
                    {
 
577
                        if (pMipmapLevel->fDirty)
 
578
                        {
 
579
                            /* Data follows */
 
580
                            rc = SSMR3PutBool(pSSM, true);
 
581
                            AssertRCReturn(rc, rc);
 
582
 
 
583
                            Assert(pMipmapLevel->cbSurface);
 
584
                            rc = SSMR3PutMem(pSSM, pMipmapLevel->pSurfaceData, pMipmapLevel->cbSurface);
 
585
                            AssertRCReturn(rc, rc);
 
586
                        }
 
587
                        else
 
588
                        {
 
589
                            /* No data follows */
 
590
                            rc = SSMR3PutBool(pSSM, false);
 
591
                            AssertRCReturn(rc, rc);
 
592
                        }
 
593
                    }
 
594
                    else
 
595
                    {
 
596
#ifdef VMSVGA3D_DIRECT3D
 
597
                        void            *pData;
 
598
                        bool             fRenderTargetTexture = false;
 
599
                        bool             fTexture = false;
 
600
                        bool             fVertex = false;
 
601
                        bool             fSkipSave = false;
 
602
                        HRESULT          hr;
 
603
 
 
604
                        Assert(pMipmapLevel->cbSurface);
 
605
                        pData = RTMemAllocZ(pMipmapLevel->cbSurface);
 
606
                        AssertReturn(pData, VERR_NO_MEMORY);
 
607
 
 
608
                        switch (pSurface->flags & (SVGA3D_SURFACE_HINT_INDEXBUFFER | SVGA3D_SURFACE_HINT_VERTEXBUFFER | SVGA3D_SURFACE_HINT_TEXTURE | SVGA3D_SURFACE_HINT_RENDERTARGET | SVGA3D_SURFACE_HINT_DEPTHSTENCIL | SVGA3D_SURFACE_CUBEMAP))
 
609
                        {
 
610
                        case SVGA3D_SURFACE_HINT_DEPTHSTENCIL:
 
611
                        case SVGA3D_SURFACE_HINT_DEPTHSTENCIL | SVGA3D_SURFACE_HINT_TEXTURE:
 
612
                            /* @todo unable to easily fetch depth surface data in d3d 9 */
 
613
                            fSkipSave = true;
 
614
                            break;
 
615
                        case SVGA3D_SURFACE_HINT_TEXTURE | SVGA3D_SURFACE_HINT_RENDERTARGET:
 
616
                            fRenderTargetTexture = true;
 
617
                            /* no break */
 
618
                        case SVGA3D_SURFACE_HINT_TEXTURE:
 
619
                            fTexture = true;
 
620
                            /* no break */
 
621
                        case SVGA3D_SURFACE_HINT_RENDERTARGET:
 
622
                        {
 
623
                            D3DLOCKED_RECT LockedRect;
 
624
 
 
625
                            if (fTexture)
 
626
                            {
 
627
                                if (pSurface->bounce.pTexture)
 
628
                                {
 
629
                                    if (    !pSurface->fDirty
 
630
                                        &&  fRenderTargetTexture
 
631
                                        &&  i == 0 /* only the first time */)
 
632
                                    {
 
633
                                        IDirect3DSurface9 *pSrc, *pDest;
 
634
 
 
635
                                        /* @todo stricter checks for associated context */
 
636
                                        uint32_t cid = pSurface->idAssociatedContext;
 
637
                                        if (    cid >= pState->cContexts
 
638
                                            ||  pState->papContexts[cid]->id != cid)
 
639
                                        {
 
640
                                            Log(("vmsvga3dSaveExec invalid context id (%x - %x)!\n", cid, (cid >= pState->cContexts) ? -1 : pState->papContexts[cid]->id));
 
641
                                            AssertFailedReturn(VERR_INVALID_PARAMETER);
 
642
                                        }
 
643
                                        PVMSVGA3DCONTEXT pContext = pState->papContexts[cid];
 
644
 
 
645
                                        hr = pSurface->bounce.pTexture->GetSurfaceLevel(i, &pDest);
 
646
                                        AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: GetSurfaceLevel failed with %x\n", hr), VERR_INTERNAL_ERROR);
 
647
 
 
648
                                        hr = pSurface->u.pTexture->GetSurfaceLevel(i, &pSrc);
 
649
                                        AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: GetSurfaceLevel failed with %x\n", hr), VERR_INTERNAL_ERROR);
 
650
 
 
651
                                        hr = pContext->pDevice->GetRenderTargetData(pSrc, pDest);
 
652
                                        AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: GetRenderTargetData failed with %x\n", hr), VERR_INTERNAL_ERROR);
 
653
 
 
654
                                        pSrc->Release();
 
655
                                        pDest->Release();
 
656
                                    }
 
657
 
 
658
                                    hr = pSurface->bounce.pTexture->LockRect(i, /* texture level */
 
659
                                                                             &LockedRect,
 
660
                                                                             NULL,
 
661
                                                                             D3DLOCK_READONLY);
 
662
                                }
 
663
                                else
 
664
                                    hr = pSurface->u.pTexture->LockRect(i, /* texture level */
 
665
                                                                        &LockedRect,
 
666
                                                                        NULL,
 
667
                                                                        D3DLOCK_READONLY);
 
668
                            }
 
669
                            else
 
670
                                hr = pSurface->u.pSurface->LockRect(&LockedRect,
 
671
                                                                    NULL,
 
672
                                                                    D3DLOCK_READONLY);
 
673
                            AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: LockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
 
674
 
 
675
                            /* Copy the data one line at a time in case the internal pitch is different. */
 
676
                            for (uint32_t j = 0; j < pMipmapLevel->size.height; j++)
 
677
                            {
 
678
                                memcpy((uint8_t *)pData + j * pMipmapLevel->cbSurfacePitch, (uint8_t *)LockedRect.pBits + j * LockedRect.Pitch, pMipmapLevel->cbSurfacePitch);
 
679
                            }
 
680
 
 
681
                            if (fTexture)
 
682
                            {
 
683
                                if (pSurface->bounce.pTexture)
 
684
                                {
 
685
                                    hr = pSurface->bounce.pTexture->UnlockRect(i);
 
686
                                    AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: UnlockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
 
687
                                }
 
688
                                else
 
689
                                    hr = pSurface->u.pTexture->UnlockRect(i);
 
690
                            }
 
691
                            else
 
692
                                hr = pSurface->u.pSurface->UnlockRect();
 
693
                            AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: UnlockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
 
694
                            break;
 
695
                        }
 
696
 
 
697
                        case SVGA3D_SURFACE_HINT_VERTEXBUFFER:
 
698
                            fVertex = true;
 
699
                            /* no break */
 
700
 
 
701
                        case SVGA3D_SURFACE_HINT_INDEXBUFFER:
 
702
                        {
 
703
                            uint8_t *pD3DData;
 
704
 
 
705
                            if (fVertex)
 
706
                                hr = pSurface->u.pVertexBuffer->Lock(0, 0, (void **)&pD3DData, D3DLOCK_READONLY);
 
707
                            else
 
708
                                hr = pSurface->u.pIndexBuffer->Lock(0, 0, (void **)&pD3DData, D3DLOCK_READONLY);
 
709
                            AssertMsg(hr == D3D_OK, ("vmsvga3dSaveExec: Lock %s failed with %x\n", (fVertex) ? "vertex" : "index", hr));
 
710
 
 
711
                            memcpy(pData, pD3DData, pMipmapLevel->cbSurface);
 
712
 
 
713
                            if (fVertex)
 
714
                                hr = pSurface->u.pVertexBuffer->Unlock();
 
715
                            else
 
716
                                hr = pSurface->u.pIndexBuffer->Unlock();
 
717
                            AssertMsg(hr == D3D_OK, ("vmsvga3dSaveExec: Unlock %s failed with %x\n", (fVertex) ? "vertex" : "index", hr));
 
718
                            break;
 
719
                        }
 
720
 
 
721
                        default:
 
722
                            AssertFailed();
 
723
                            break;
 
724
                        }
 
725
 
 
726
                        if (!fSkipSave)
 
727
                        {
 
728
                            /* Data follows */
 
729
                            rc = SSMR3PutBool(pSSM, true);
 
730
                            AssertRCReturn(rc, rc);
 
731
 
 
732
                            /* And write the surface data. */
 
733
                            rc = SSMR3PutMem(pSSM, pData, pMipmapLevel->cbSurface);
 
734
                            AssertRCReturn(rc, rc);
 
735
                        }
 
736
                        else
 
737
                        {
 
738
                            /* No data follows */
 
739
                            rc = SSMR3PutBool(pSSM, false);
 
740
                            AssertRCReturn(rc, rc);
 
741
                        }
 
742
 
 
743
                        RTMemFree(pData);
 
744
#elif defined(VMSVGA3D_OPENGL)
 
745
                        void *pData = NULL;
 
746
 
 
747
                        PVMSVGA3DCONTEXT pContext = &pState->SharedCtx;
 
748
                        VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);
 
749
 
 
750
                        Assert(pMipmapLevel->cbSurface);
 
751
 
 
752
                        switch (pSurface->flags & (SVGA3D_SURFACE_HINT_INDEXBUFFER | SVGA3D_SURFACE_HINT_VERTEXBUFFER | SVGA3D_SURFACE_HINT_TEXTURE | SVGA3D_SURFACE_HINT_RENDERTARGET | SVGA3D_SURFACE_HINT_DEPTHSTENCIL | SVGA3D_SURFACE_CUBEMAP))
 
753
                        {
 
754
                        default:
 
755
                            AssertFailed();
 
756
                            /* no break */
 
757
                        case SVGA3D_SURFACE_HINT_DEPTHSTENCIL:
 
758
                        case SVGA3D_SURFACE_HINT_DEPTHSTENCIL | SVGA3D_SURFACE_HINT_TEXTURE:
 
759
                            /* @todo fetch data from the renderbuffer */
 
760
                            /* No data follows */
 
761
                            rc = SSMR3PutBool(pSSM, false);
 
762
                            AssertRCReturn(rc, rc);
 
763
                            break;
 
764
 
 
765
                        case SVGA3D_SURFACE_HINT_TEXTURE | SVGA3D_SURFACE_HINT_RENDERTARGET:
 
766
                        case SVGA3D_SURFACE_HINT_TEXTURE:
 
767
                        case SVGA3D_SURFACE_HINT_RENDERTARGET:
 
768
                        {
 
769
                            GLint activeTexture;
 
770
 
 
771
                            pData = RTMemAllocZ(pMipmapLevel->cbSurface);
 
772
                            AssertReturn(pData, VERR_NO_MEMORY);
 
773
 
 
774
                            glGetIntegerv(GL_TEXTURE_BINDING_2D, &activeTexture);
 
775
                            VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
 
776
 
 
777
                            glBindTexture(GL_TEXTURE_2D, pSurface->oglId.texture);
 
778
                            VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
 
779
 
 
780
                            /* Set row length and alignment of the output data. */
 
781
                            VMSVGAPACKPARAMS SavedParams;
 
782
                            vmsvga3dOglSetPackParams(pState, pContext, pSurface, &SavedParams);
 
783
 
 
784
                            glGetTexImage(GL_TEXTURE_2D,
 
785
                                          i,
 
786
                                          pSurface->formatGL,
 
787
                                          pSurface->typeGL,
 
788
                                          pData);
 
789
                            VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
 
790
 
 
791
                            vmsvga3dOglRestorePackParams(pState, pContext, pSurface, &SavedParams);
 
792
 
 
793
                            /* Data follows */
 
794
                            rc = SSMR3PutBool(pSSM, true);
 
795
                            AssertRCReturn(rc, rc);
 
796
 
 
797
                            /* And write the surface data. */
 
798
                            rc = SSMR3PutMem(pSSM, pData, pMipmapLevel->cbSurface);
 
799
                            AssertRCReturn(rc, rc);
 
800
 
 
801
                            /* Restore the old active texture. */
 
802
                            glBindTexture(GL_TEXTURE_2D, activeTexture);
 
803
                            VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
 
804
                            break;
 
805
                        }
 
806
 
 
807
                        case SVGA3D_SURFACE_HINT_VERTEXBUFFER:
 
808
                        case SVGA3D_SURFACE_HINT_INDEXBUFFER:
 
809
                        {
 
810
                            uint8_t *pBufferData;
 
811
 
 
812
                            pState->ext.glBindBuffer(GL_ARRAY_BUFFER, pSurface->oglId.buffer);
 
813
                            VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
 
814
 
 
815
                            pBufferData = (uint8_t *)pState->ext.glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
 
816
                            VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
 
817
                            Assert(pBufferData);
 
818
 
 
819
                            /* Data follows */
 
820
                            rc = SSMR3PutBool(pSSM, true);
 
821
                            AssertRCReturn(rc, rc);
 
822
 
 
823
                            /* And write the surface data. */
 
824
                            rc = SSMR3PutMem(pSSM, pBufferData, pMipmapLevel->cbSurface);
 
825
                            AssertRCReturn(rc, rc);
 
826
 
 
827
                            pState->ext.glUnmapBuffer(GL_ARRAY_BUFFER);
 
828
                            VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
 
829
 
 
830
                            pState->ext.glBindBuffer(GL_ARRAY_BUFFER, 0);
 
831
                            VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
 
832
 
 
833
                        }
 
834
                        }
 
835
                        if (pData)
 
836
                            RTMemFree(pData);
 
837
#else
 
838
#error "Unexpected 3d backend"
 
839
#endif
 
840
                    }
 
841
                }
 
842
            }
 
843
        }
 
844
    }
 
845
    return VINF_SUCCESS;
 
846
}
 
847
 
 
848
uint32_t vmsvga3dSaveShaderConst(PVMSVGA3DCONTEXT pContext, uint32_t reg, SVGA3dShaderType type, SVGA3dShaderConstType ctype, uint32_t val1, uint32_t val2, uint32_t val3, uint32_t val4)
 
849
{
 
850
    /* Choose a sane upper limit. */
 
851
    AssertReturn(reg < _32K, VERR_INVALID_PARAMETER);
 
852
 
 
853
    if (type == SVGA3D_SHADERTYPE_VS)
 
854
    {
 
855
        if (pContext->state.cVertexShaderConst <= reg)
 
856
        {
 
857
            pContext->state.paVertexShaderConst = (PVMSVGASHADERCONST)RTMemRealloc(pContext->state.paVertexShaderConst, sizeof(VMSVGASHADERCONST) * (reg + 1));
 
858
            AssertReturn(pContext->state.paVertexShaderConst, VERR_NO_MEMORY);
 
859
            for (uint32_t i = pContext->state.cVertexShaderConst; i < reg + 1; i++)
 
860
                pContext->state.paVertexShaderConst[i].fValid = false;
 
861
            pContext->state.cVertexShaderConst = reg + 1;
 
862
        }
 
863
 
 
864
        pContext->state.paVertexShaderConst[reg].fValid   = true;
 
865
        pContext->state.paVertexShaderConst[reg].ctype    = ctype;
 
866
        pContext->state.paVertexShaderConst[reg].value[0] = val1;
 
867
        pContext->state.paVertexShaderConst[reg].value[1] = val2;
 
868
        pContext->state.paVertexShaderConst[reg].value[2] = val3;
 
869
        pContext->state.paVertexShaderConst[reg].value[3] = val4;
 
870
    }
 
871
    else
 
872
    {
 
873
        Assert(type == SVGA3D_SHADERTYPE_PS);
 
874
        if (pContext->state.cPixelShaderConst <= reg)
 
875
        {
 
876
            pContext->state.paPixelShaderConst = (PVMSVGASHADERCONST)RTMemRealloc(pContext->state.paPixelShaderConst, sizeof(VMSVGASHADERCONST) * (reg + 1));
 
877
            AssertReturn(pContext->state.paPixelShaderConst, VERR_NO_MEMORY);
 
878
            for (uint32_t i = pContext->state.cPixelShaderConst; i < reg + 1; i++)
 
879
                pContext->state.paPixelShaderConst[i].fValid = false;
 
880
            pContext->state.cPixelShaderConst = reg + 1;
 
881
        }
 
882
 
 
883
        pContext->state.paPixelShaderConst[reg].fValid   = true;
 
884
        pContext->state.paPixelShaderConst[reg].ctype    = ctype;
 
885
        pContext->state.paPixelShaderConst[reg].value[0] = val1;
 
886
        pContext->state.paPixelShaderConst[reg].value[1] = val2;
 
887
        pContext->state.paPixelShaderConst[reg].value[2] = val3;
 
888
        pContext->state.paPixelShaderConst[reg].value[3] = val4;
 
889
    }
 
890
 
 
891
    return VINF_SUCCESS;
 
892
}
 
893