VirtualBox

Ignore:
Timestamp:
Jan 14, 2013 9:49:11 PM (12 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
83199
Message:

crOpenGL: saved state fixes & improvements

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_main.c

    r44196 r44290  
    1414#include "cr_hash.h"
    1515#include "cr_environment.h"
     16#include "cr_pixeldata.h"
    1617#include "server_dispatch.h"
    1718#include "state/cr_texture.h"
     
    119120}
    120121
     122static void deleteMuralInfoCallback( void *data )
     123{
     124    CRMuralInfo *m = (CRMuralInfo *) data;
     125    if (m->spuWindow) /* <- do not do term for default mural as it does not contain any info to be freed,
     126                       * and renderspu will destroy it up itself*/
     127    {
     128        crServerMuralTerm(m);
     129    }
     130    crFree(m);
     131}
    121132
    122133static void crServerTearDown( void )
     
    152163    /* Free vertex programs */
    153164    crFreeHashtable(cr_server.programTable, crFree);
     165
     166    /* Free dummy murals */
     167    crFreeHashtable(cr_server.dummyMuralTable, deleteMuralInfoCallback);
     168
     169    /* Free murals */
     170    crFreeHashtable(cr_server.muralTable, deleteMuralInfoCallback);
    154171
    155172    for (i = 0; i < cr_server.numClients; i++) {
     
    309326    cr_server.curClient->currentCtxInfo = &cr_server.MainContextInfo;
    310327
     328    cr_server.dummyMuralTable = crAllocHashtable();
     329
    311330    crServerInitDispatch();
    312331    crStateDiffAPI( &(cr_server.head_spu->dispatch_table) );
     
    383402     */
    384403    cr_server.contextTable = crAllocHashtable();
     404
     405    cr_server.dummyMuralTable = crAllocHashtable();
    385406
    386407    crServerSetVBoxConfigurationHGCM();
     
    693714        rc = SSMR3PutMem(pSSM, pMI->pVisibleRects, 4*sizeof(GLint)*pMI->cVisibleRects);
    694715    }
     716
     717    rc = SSMR3PutMem(pSSM, pMI->ctxUsage, sizeof (pMI->ctxUsage));
     718    CRASSERT(rc == VINF_SUCCESS);
    695719}
    696720
     
    745769}
    746770
     771typedef struct CRVBOX_SAVE_STATE_GLOBAL
     772{
     773    /* context id -> mural association
     774     * on context data save, each context will be made current with the corresponding mural from this table
     775     * thus saving the mural front & back buffer data */
     776    CRHashTable *contextMuralTable;
     777    /* mural id -> context info
     778     * for murals that do not have associated context in contextMuralTable
     779     * we still need to save*/
     780    CRHashTable *additionalMuralContextTable;
     781
     782    PSSMHANDLE pSSM;
     783
     784    int rc;
     785} CRVBOX_SAVE_STATE_GLOBAL, *PCRVBOX_SAVE_STATE_GLOBAL;
     786
     787
     788typedef struct CRVBOX_CTXWND_CTXWALKER_CB
     789{
     790    PCRVBOX_SAVE_STATE_GLOBAL pGlobal;
     791    CRHashTable *usedMuralTable;
     792    GLuint cAdditionalMurals;
     793} CRVBOX_CTXWND_CTXWALKER_CB, *PCRVBOX_CTXWND_CTXWALKER_CB;
     794
     795static void crVBoxServerBuildAdditionalWindowContextMapCB(unsigned long key, void *data1, void *data2)
     796{
     797    CRMuralInfo * pMural = (CRMuralInfo *) data1;
     798    PCRVBOX_CTXWND_CTXWALKER_CB pData = (PCRVBOX_CTXWND_CTXWALKER_CB)data2;
     799    CRContextInfo *pContextInfo = NULL;
     800
     801    if (!pMural->CreateInfo.externalID)
     802        return;
     803
     804    if (crHashtableSearch(pData->usedMuralTable, pMural->CreateInfo.externalID))
     805    {
     806        Assert(crHashtableGetDataKey(pData->pGlobal->contextMuralTable, pMural, NULL));
     807        return;
     808    }
     809
     810    Assert(!crHashtableGetDataKey(pData->pGlobal->contextMuralTable, pMural, NULL));
     811
     812    if (cr_server.MainContextInfo.CreateInfo.visualBits == pMural->CreateInfo.visualBits)
     813    {
     814        pContextInfo = &cr_server.MainContextInfo;
     815    }
     816    else
     817    {
     818        crWarning("different visual bits not implemented!");
     819        pContextInfo = &cr_server.MainContextInfo;
     820    }
     821
     822    crHashtableAdd(pData->pGlobal->additionalMuralContextTable, pMural->CreateInfo.externalID, pContextInfo);
     823}
     824
     825
     826typedef struct CRVBOX_CTXWND_WNDWALKER_CB
     827{
     828    PCRVBOX_SAVE_STATE_GLOBAL pGlobal;
     829    CRHashTable *usedMuralTable;
     830    CRContextInfo *pContextInfo;
     831    CRMuralInfo * pMural;
     832} CRVBOX_CTXWND_WNDWALKER_CB, *PCRVBOX_CTXWND_WNDWALKER_CB;
     833
     834static void crVBoxServerBuildContextWindowMapWindowWalkerCB(unsigned long key, void *data1, void *data2)
     835{
     836    CRMuralInfo * pMural = (CRMuralInfo *) data1;
     837    PCRVBOX_CTXWND_WNDWALKER_CB pData = (PCRVBOX_CTXWND_WNDWALKER_CB)data2;
     838
     839    Assert(pData->pMural != pMural);
     840    Assert(pData->pContextInfo);
     841
     842    if (pData->pMural)
     843        return;
     844
     845    if (!pMural->CreateInfo.externalID)
     846        return;
     847
     848    if (!CR_STATE_SHAREDOBJ_USAGE_IS_SET(pMural, pData->pContextInfo->pContext))
     849        return;
     850
     851    if (crHashtableSearch(pData->usedMuralTable, pMural->CreateInfo.externalID))
     852        return;
     853
     854    CRASSERT(pMural->CreateInfo.visualBits == pData->pContextInfo->CreateInfo.visualBits);
     855    pData->pMural = pMural;
     856}
     857
     858static void crVBoxServerBuildContextUsedWindowMapCB(unsigned long key, void *data1, void *data2)
     859{
     860    CRContextInfo *pContextInfo = (CRContextInfo *)data1;
     861    PCRVBOX_CTXWND_CTXWALKER_CB pData = (PCRVBOX_CTXWND_CTXWALKER_CB)data2;
     862
     863    if (!pContextInfo->currentMural)
     864        return;
     865
     866    crHashtableAdd(pData->pGlobal->contextMuralTable, pContextInfo->CreateInfo.externalID, pContextInfo->currentMural);
     867    crHashtableAdd(pData->usedMuralTable, pContextInfo->currentMural->CreateInfo.externalID, pContextInfo->currentMural);
     868}
     869
     870CRMuralInfo * crServerGetDummyMural(GLint visualBits)
     871{
     872    CRMuralInfo * pMural = (CRMuralInfo *)crHashtableSearch(cr_server.dummyMuralTable, visualBits);
     873    if (!pMural)
     874    {
     875        GLint id;
     876        pMural = (CRMuralInfo *) crCalloc(sizeof(CRMuralInfo));
     877        if (!pMural)
     878        {
     879            crWarning("crCalloc failed!");
     880            return NULL;
     881        }
     882        id = crServerMuralInit(pMural, "", visualBits, -1);
     883        if (id < 0)
     884        {
     885            crWarning("crServerMuralInit failed!");
     886            crFree(pMural);
     887            return NULL;
     888        }
     889
     890        crHashtableAdd(cr_server.dummyMuralTable, visualBits, pMural);
     891    }
     892
     893    return pMural;
     894}
     895
     896static void crVBoxServerBuildContextUnusedWindowMapCB(unsigned long key, void *data1, void *data2)
     897{
     898    CRContextInfo *pContextInfo = (CRContextInfo *)data1;
     899    PCRVBOX_CTXWND_CTXWALKER_CB pData = (PCRVBOX_CTXWND_CTXWALKER_CB)data2;
     900    CRMuralInfo * pMural = NULL;
     901
     902    if (pContextInfo->currentMural)
     903        return;
     904
     905    Assert(crHashtableNumElements(pData->pGlobal->contextMuralTable) <= crHashtableNumElements(cr_server.muralTable) - 1);
     906    if (crHashtableNumElements(pData->pGlobal->contextMuralTable) < crHashtableNumElements(cr_server.muralTable) - 1)
     907    {
     908        CRVBOX_CTXWND_WNDWALKER_CB MuralData;
     909        MuralData.pGlobal = pData->pGlobal;
     910        MuralData.usedMuralTable = pData->usedMuralTable;
     911        MuralData.pContextInfo = pContextInfo;
     912        MuralData.pMural = NULL;
     913
     914        crHashtableWalk(cr_server.muralTable, crVBoxServerBuildContextWindowMapWindowWalkerCB, &MuralData);
     915
     916        pMural = MuralData.pMural;
     917
     918    }
     919
     920    if (!pMural)
     921    {
     922        pMural = crServerGetDummyMural(pContextInfo->CreateInfo.visualBits);
     923        if (!pMural)
     924        {
     925            crWarning("crServerGetDummyMural failed");
     926            return;
     927        }
     928    }
     929    else
     930    {
     931        crHashtableAdd(pData->usedMuralTable, pMural->CreateInfo.externalID, pMural);
     932        ++pData->cAdditionalMurals;
     933    }
     934
     935    crHashtableAdd(pData->pGlobal->contextMuralTable, pContextInfo->CreateInfo.externalID, pMural);
     936}
     937
     938static void crVBoxServerBuildSaveStateGlobal(PCRVBOX_SAVE_STATE_GLOBAL pGlobal)
     939{
     940    CRVBOX_CTXWND_CTXWALKER_CB Data;
     941    GLuint cMurals;
     942    pGlobal->contextMuralTable = crAllocHashtable();
     943    pGlobal->additionalMuralContextTable = crAllocHashtable();
     944    /* 1. go through all contexts and match all having currentMural set */
     945    Data.pGlobal = pGlobal;
     946    Data.usedMuralTable = crAllocHashtable();
     947    Data.cAdditionalMurals = 0;
     948    crHashtableWalk(cr_server.contextTable, crVBoxServerBuildContextUsedWindowMapCB, &Data);
     949
     950    cMurals = crHashtableNumElements(pGlobal->contextMuralTable);
     951    CRASSERT(cMurals <= crHashtableNumElements(cr_server.contextTable));
     952    CRASSERT(cMurals <= crHashtableNumElements(cr_server.muralTable) - 1);
     953    CRASSERT(cMurals == crHashtableNumElements(Data.usedMuralTable));
     954    if (cMurals < crHashtableNumElements(cr_server.contextTable))
     955    {
     956        Data.cAdditionalMurals = 0;
     957        crHashtableWalk(cr_server.contextTable, crVBoxServerBuildContextUnusedWindowMapCB, &Data);
     958    }
     959
     960    CRASSERT(crHashtableNumElements(pGlobal->contextMuralTable) == crHashtableNumElements(cr_server.contextTable));
     961    CRASSERT(cMurals + Data.cAdditionalMurals <= crHashtableNumElements(cr_server.muralTable) - 1);
     962    if (cMurals + Data.cAdditionalMurals < crHashtableNumElements(cr_server.muralTable) - 1)
     963    {
     964        crHashtableWalk(cr_server.muralTable, crVBoxServerBuildAdditionalWindowContextMapCB, &Data);
     965        CRASSERT(cMurals + Data.cAdditionalMurals + crHashtableNumElements(pGlobal->additionalMuralContextTable) == crHashtableNumElements(cr_server.muralTable) - 1);
     966    }
     967}
     968
     969static int crVBoxServerSaveFBImage(PSSMHANDLE pSSM)
     970{
     971    int32_t rc;
     972    CRContext *pContext;
     973    CRMuralInfo *pMural;
     974    GLint cbData;
     975
     976    CRASSERT(cr_server.currentCtxInfo);
     977    CRASSERT(cr_server.currentCtxInfo->currentMural);
     978
     979    pContext = cr_server.currentCtxInfo->pContext;
     980    pMural = cr_server.currentCtxInfo->currentMural;
     981    /* do crStateAcquireFBImage no matter whether offscreen drawing is used or not
     982     * in the former case this would just free pContext->buffer.pFrontImg and pContext->buffer.pFrontImg
     983     */
     984    rc = crStateAcquireFBImage(pContext);
     985    AssertRCReturn(rc, rc);
     986
     987    if (!pMural->width || !pMural->height)
     988        return VINF_SUCCESS;
     989
     990
     991    cbData = crPixelSize(GL_RGBA, GL_UNSIGNED_BYTE) * pMural->width * pMural->height;
     992
     993    if (!pMural->fUseFBO)
     994    {
     995        CRASSERT(pMural->width == pContext->buffer.storedWidth);
     996        CRASSERT(pMural->width == pContext->buffer.width);
     997        CRASSERT(pMural->height == pContext->buffer.storedHeight);
     998        CRASSERT(pMural->height == pContext->buffer.height);
     999
     1000        rc = SSMR3PutMem(pSSM, pContext->buffer.pFrontImg, cbData);
     1001        AssertRCReturn(rc, rc);
     1002        rc = SSMR3PutMem(pSSM, pContext->buffer.pBackImg, cbData);
     1003        AssertRCReturn(rc, rc);
     1004
     1005        crStateFreeFBImage(pContext);
     1006    }
     1007    else
     1008    {
     1009        CR_BLITTER_TEXTURE Tex;
     1010        void *pvData;
     1011        GLuint idPBO = cr_server.bUsePBOForReadback ? pMural->idPBO : 0;
     1012
     1013        if (idPBO)
     1014        {
     1015            CRASSERT(pMural->fboWidth == pMural->width);
     1016            CRASSERT(pMural->fboHeight == pMural->height);
     1017        }
     1018
     1019        Tex.width = pMural->width;
     1020        Tex.height = pMural->height;
     1021        Tex.target = GL_TEXTURE_2D;
     1022        Tex.hwid = pMural->aidColorTexs[CR_SERVER_FBO_FB_IDX(pMural)];
     1023
     1024        CRASSERT(Tex.hwid);
     1025
     1026        pvData = CrHlpGetTexImage(pContext, &Tex, idPBO);
     1027        if (!pvData)
     1028        {
     1029            crWarning("CrHlpGetTexImage failed for frontbuffer");
     1030            return VERR_NO_MEMORY;
     1031        }
     1032
     1033        rc = SSMR3PutMem(pSSM, pvData, cbData);
     1034
     1035        CrHlpFreeTexImage(pContext, idPBO, pvData);
     1036
     1037        AssertRCReturn(rc, rc);
     1038
     1039        Tex.hwid = pMural->aidColorTexs[CR_SERVER_FBO_BB_IDX(pMural)];
     1040
     1041        CRASSERT(Tex.hwid);
     1042
     1043        pvData = CrHlpGetTexImage(pContext, &Tex, idPBO);
     1044        if (!pvData)
     1045        {
     1046            crWarning("CrHlpGetTexImage failed for backbuffer");
     1047            return VERR_NO_MEMORY;
     1048        }
     1049
     1050        rc = SSMR3PutMem(pSSM, pvData, cbData);
     1051
     1052        CrHlpFreeTexImage(pContext, idPBO, pvData);
     1053
     1054        AssertRCReturn(rc, rc);
     1055    }
     1056
     1057    return VINF_SUCCESS;
     1058}
     1059
     1060#define CRSERVER_ASSERTRC_RETURN_VOID(_rc) do { \
     1061        if(!RT_SUCCESS((_rc))) { \
     1062            AssertFailed(); \
     1063            return; \
     1064        } \
     1065    } while (0)
     1066
     1067static void crVBoxServerSaveAdditionalMuralsCB(unsigned long key, void *data1, void *data2)
     1068{
     1069    CRContextInfo *pContextInfo = (CRContextInfo *) data1;
     1070    PCRVBOX_SAVE_STATE_GLOBAL pData = (PCRVBOX_SAVE_STATE_GLOBAL)data2;
     1071    CRMuralInfo *pMural = (CRMuralInfo*)crHashtableSearch(cr_server.muralTable, key);
     1072    PSSMHANDLE pSSM = pData->pSSM;
     1073    CRbitvalue initialCtxUsage[CR_MAX_BITARRAY];
     1074    CRMuralInfo *pInitialCurMural = pContextInfo->currentMural;
     1075
     1076    crMemcpy(initialCtxUsage, pMural->ctxUsage, sizeof (initialCtxUsage));
     1077
     1078    CRSERVER_ASSERTRC_RETURN_VOID(pData->rc);
     1079
     1080    pData->rc = SSMR3PutMem(pSSM, &key, sizeof(key));
     1081    CRSERVER_ASSERTRC_RETURN_VOID(pData->rc);
     1082
     1083    pData->rc = SSMR3PutMem(pSSM, &pContextInfo->CreateInfo.externalID, sizeof(pContextInfo->CreateInfo.externalID));
     1084    CRSERVER_ASSERTRC_RETURN_VOID(pData->rc);
     1085
     1086    crServerPerformMakeCurrent(pMural, pContextInfo);
     1087
     1088    pData->rc = crVBoxServerSaveFBImage(pSSM);
     1089
     1090    /* restore the reference data, we synchronize it with the HW state in a later crServerPerformMakeCurrent call */
     1091    crMemcpy(pMural->ctxUsage, initialCtxUsage, sizeof (initialCtxUsage));
     1092    pContextInfo->currentMural = pInitialCurMural;
     1093
     1094    CRSERVER_ASSERTRC_RETURN_VOID(pData->rc);
     1095}
     1096
    7471097static void crVBoxServerSaveContextStateCB(unsigned long key, void *data1, void *data2)
    7481098{
    7491099    CRContextInfo *pContextInfo = (CRContextInfo *) data1;
    7501100    CRContext *pContext = pContextInfo->pContext;
    751     PSSMHANDLE pSSM = (PSSMHANDLE) data2;
    752     int32_t rc;
     1101    PCRVBOX_SAVE_STATE_GLOBAL pData = (PCRVBOX_SAVE_STATE_GLOBAL)data2;
     1102    PSSMHANDLE pSSM = pData->pSSM;
     1103    CRMuralInfo *pMural = (CRMuralInfo*)crHashtableSearch(pData->contextMuralTable, key);
     1104    CRMuralInfo *pContextCurrentMural = pContextInfo->currentMural;
     1105    const int32_t i32Dummy = 0;
     1106
     1107    AssertCompile(sizeof (i32Dummy) == sizeof (pMural->CreateInfo.externalID));
     1108    CRSERVER_ASSERTRC_RETURN_VOID(pData->rc);
    7531109
    7541110    CRASSERT(pContext && pSSM);
     1111    CRASSERT(pMural);
    7551112
    7561113    /* We could have skipped saving the key and use similar callback to load context states back,
    7571114     * but there's no guarantee we'd traverse hashtable in same order after loading.
    7581115     */
    759     rc = SSMR3PutMem(pSSM, &key, sizeof(key));
    760     CRASSERT(rc == VINF_SUCCESS);
    761 
    762 #ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
    763     CRASSERT(cr_server.curClient);
    764     if (cr_server.curClient)
    765     {
    766 # ifdef DEBUG_misha
    767         {
     1116    pData->rc = SSMR3PutMem(pSSM, &key, sizeof(key));
     1117    CRSERVER_ASSERTRC_RETURN_VOID(pData->rc);
     1118
     1119#ifdef DEBUG_misha
     1120    {
    7681121            unsigned long id;
    7691122            if (!crHashtableGetDataKey(cr_server.contextTable, pContextInfo, &id))
    770                 crWarning("No client id for server ctx %d", pContext->id);
     1123                crWarning("No client id for server ctx %d", pContextInfo->CreateInfo.externalID);
    7711124            else
    7721125                CRASSERT(id == key);
    773         }
    774 # endif
    775         crServerDispatchMakeCurrent(cr_server.curClient->currentWindow, 0, key);
    776     }
    777 #endif
    778 
    779     rc = crStateSaveContext(pContext, pSSM);
    780     CRASSERT(rc == VINF_SUCCESS);
     1126    }
     1127#endif
     1128
     1129#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
     1130    if (pContextInfo->currentMural || crHashtableSearch(cr_server.muralTable, key))
     1131    {
     1132        CRASSERT(pMural->CreateInfo.externalID);
     1133        pData->rc = SSMR3PutMem(pSSM, &pMural->CreateInfo.externalID, sizeof(pMural->CreateInfo.externalID));
     1134    }
     1135    else
     1136    {
     1137        CRASSERT(!pMural->width);
     1138        CRASSERT(!pMural->height);
     1139        CRASSERT(crHashtableSearch(cr_server.dummyMuralTable, key));
     1140        pData->rc = SSMR3PutMem(pSSM, &i32Dummy, sizeof(pMural->CreateInfo.externalID));
     1141    }
     1142    CRSERVER_ASSERTRC_RETURN_VOID(pData->rc);
     1143
     1144    CRASSERT(CR_STATE_SHAREDOBJ_USAGE_IS_SET(pMural, pContext));
     1145    CRASSERT(pContextInfo->currentMural == pMural || !pContextInfo->currentMural);
     1146    CRASSERT(cr_server.curClient);
     1147
     1148    crServerPerformMakeCurrent(pMural, pContextInfo);
     1149#endif
     1150
     1151    pData->rc = crStateSaveContext(pContext, pSSM);
     1152    CRSERVER_ASSERTRC_RETURN_VOID(pData->rc);
     1153
     1154    pData->rc = crVBoxServerSaveFBImage(pSSM);
     1155    CRSERVER_ASSERTRC_RETURN_VOID(pData->rc);
     1156
     1157    /* restore the initial current mural */
     1158    pContextInfo->currentMural = pContextCurrentMural;
    7811159}
    7821160
     
    9101288    GLenum err;
    9111289#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
    912     unsigned long ctxID=-1, winID=-1;
    913 #endif
     1290    CRClient *curClient;
     1291    CRMuralInfo *curMural = NULL;
     1292    CRContextInfo *curCtxInfo = NULL;
     1293#endif
     1294    CRVBOX_SAVE_STATE_GLOBAL Data = {0};
    9141295
    9151296#if 0
     
    9501331
    9511332#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
     1333    curClient = cr_server.curClient;
    9521334    /* Save current win and ctx IDs, as we'd rebind contexts when saving textures */
    953     if (cr_server.curClient)
    954     {
    955         ctxID = cr_server.curClient->currentContextNumber;
    956         winID = cr_server.curClient->currentWindow;
    957     }
    958 #endif
    959 
    960     /* Save contexts state tracker data */
    961     /* @todo For now just some blind data dumps,
    962      * but I've a feeling those should be saved/restored in a very strict sequence to
    963      * allow diff_api to work correctly.
    964      * Should be tested more with multiply guest opengl apps working when saving VM snapshot.
    965      */
    966     crHashtableWalk(cr_server.contextTable, crVBoxServerSaveContextStateCB, pSSM);
    967 
    968 #ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
    969     /* Restore original win and ctx IDs*/
    970     if (cr_server.curClient)
    971     {
    972         crServerDispatchMakeCurrent(winID, 0, ctxID);
    973     }
    974 #endif
    975 
     1335    if (curClient)
     1336    {
     1337        curCtxInfo = cr_server.curClient->currentCtxInfo;
     1338        curMural = cr_server.curClient->currentMural;
     1339    }
     1340    else if (cr_server.numClients)
     1341    {
     1342        cr_server.curClient = cr_server.clients[0];
     1343    }
     1344#endif
     1345
     1346    /* first save windows info */
    9761347    /* Save windows creation info */
    9771348    ui32 = crHashtableNumElements(cr_server.muralTable);
     
    9891360    crHashtableWalk(cr_server.muralTable, crVBoxServerSaveMuralCB, pSSM);
    9901361
    991     /* Save starting free context and window IDs */
    992     rc = SSMR3PutMem(pSSM, &cr_server.idsPool, sizeof(cr_server.idsPool));
     1362    /* we need to save front & backbuffer data for each mural first create a context -> mural association */
     1363    crVBoxServerBuildSaveStateGlobal(&Data);
     1364
     1365    rc = crStateSaveGlobals(pSSM);
    9931366    AssertRCReturn(rc, rc);
     1367
     1368    Data.pSSM = pSSM;
     1369    /* Save contexts state tracker data */
     1370    /* @todo For now just some blind data dumps,
     1371     * but I've a feeling those should be saved/restored in a very strict sequence to
     1372     * allow diff_api to work correctly.
     1373     * Should be tested more with multiply guest opengl apps working when saving VM snapshot.
     1374     */
     1375    crHashtableWalk(cr_server.contextTable, crVBoxServerSaveContextStateCB, &Data);
     1376    AssertRCReturn(Data.rc, Data.rc);
     1377
     1378    ui32 = crHashtableNumElements(Data.additionalMuralContextTable);
     1379    rc = SSMR3PutU32(pSSM, (uint32_t) ui32);
     1380    AssertRCReturn(rc, rc);
     1381
     1382    crHashtableWalk(Data.additionalMuralContextTable, crVBoxServerSaveAdditionalMuralsCB, &Data);
     1383    AssertRCReturn(Data.rc, Data.rc);
     1384
     1385#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
     1386    cr_server.curClient = curClient;
     1387    /* Restore original win and ctx IDs*/
     1388    if (curClient && curMural && curCtxInfo)
     1389    {
     1390        crServerPerformMakeCurrent(curMural, curCtxInfo);
     1391    }
     1392    else
     1393    {
     1394        cr_server.bForceMakeCurrentOnClientSwitch = GL_TRUE;
     1395    }
     1396#endif
    9941397
    9951398    /* Save clients info */
     
    10481451}
    10491452
     1453static int32_t crVBoxServerLoadMurals(PSSMHANDLE pSSM, uint32_t version)
     1454{
     1455    unsigned long key;
     1456    uint32_t ui, uiNumElems;
     1457    /* Load windows */
     1458    int32_t rc = SSMR3GetU32(pSSM, &uiNumElems);
     1459    AssertRCReturn(rc, rc);
     1460    for (ui=0; ui<uiNumElems; ++ui)
     1461    {
     1462        CRCreateInfo_t createInfo;
     1463        char psz[200];
     1464        GLint winID;
     1465        unsigned long key;
     1466
     1467        rc = SSMR3GetMem(pSSM, &key, sizeof(key));
     1468        AssertRCReturn(rc, rc);
     1469        rc = SSMR3GetMem(pSSM, &createInfo, sizeof(createInfo));
     1470        AssertRCReturn(rc, rc);
     1471
     1472        if (createInfo.pszDpyName)
     1473        {
     1474            rc = SSMR3GetStrZEx(pSSM, psz, 200, NULL);
     1475            AssertRCReturn(rc, rc);
     1476            createInfo.pszDpyName = psz;
     1477        }
     1478
     1479        winID = crServerDispatchWindowCreateEx(createInfo.pszDpyName, createInfo.visualBits, key);
     1480        CRASSERT((int64_t)winID == (int64_t)key);
     1481    }
     1482
     1483    /* Load cr_server.muralTable */
     1484    rc = SSMR3GetU32(pSSM, &uiNumElems);
     1485    AssertRCReturn(rc, rc);
     1486    for (ui=0; ui<uiNumElems; ++ui)
     1487    {
     1488        CRMuralInfo muralInfo;
     1489
     1490        rc = SSMR3GetMem(pSSM, &key, sizeof(key));
     1491        AssertRCReturn(rc, rc);
     1492        rc = SSMR3GetMem(pSSM, &muralInfo, RT_OFFSETOF(CRMuralInfo, CreateInfo));
     1493        AssertRCReturn(rc, rc);
     1494
     1495        if (version <= SHCROGL_SSM_VERSION_BEFORE_FRONT_DRAW_TRACKING)
     1496            muralInfo.bFbDraw = GL_TRUE;
     1497
     1498        if (muralInfo.pVisibleRects)
     1499        {
     1500            muralInfo.pVisibleRects = crAlloc(4*sizeof(GLint)*muralInfo.cVisibleRects);
     1501            if (!muralInfo.pVisibleRects)
     1502            {
     1503                return VERR_NO_MEMORY;
     1504            }
     1505
     1506            rc = SSMR3GetMem(pSSM, muralInfo.pVisibleRects, 4*sizeof(GLint)*muralInfo.cVisibleRects);
     1507            AssertRCReturn(rc, rc);
     1508        }
     1509
     1510        if (version >= SHCROGL_SSM_VERSION_WITH_WINDOW_CTX_USAGE)
     1511        {
     1512            CRMuralInfo *pActualMural = (CRMuralInfo *)crHashtableSearch(cr_server.muralTable, key);;
     1513            CRASSERT(pActualMural);
     1514            rc = SSMR3GetMem(pSSM, pActualMural->ctxUsage, sizeof (pActualMural->ctxUsage));
     1515            CRASSERT(rc == VINF_SUCCESS);
     1516        }
     1517
     1518        /* Restore windows geometry info */
     1519        crServerDispatchWindowSize(key, muralInfo.width, muralInfo.height);
     1520        crServerDispatchWindowPosition(key, muralInfo.gX, muralInfo.gY);
     1521        /* Same workaround as described in stub.c:stubUpdateWindowVisibileRegions for compiz on a freshly booted VM*/
     1522        if (muralInfo.bReceivedRects)
     1523        {
     1524            crServerDispatchWindowVisibleRegion(key, muralInfo.cVisibleRects, muralInfo.pVisibleRects);
     1525        }
     1526        crServerDispatchWindowShow(key, muralInfo.bVisible);
     1527
     1528        if (muralInfo.pVisibleRects)
     1529        {
     1530            crFree(muralInfo.pVisibleRects);
     1531        }
     1532    }
     1533
     1534    CRASSERT(RT_SUCCESS(rc));
     1535    return VINF_SUCCESS;
     1536}
     1537
     1538static int crVBoxServerLoadFBImage(PSSMHANDLE pSSM, uint32_t version,
     1539        CRContextInfo* pContextInfo, CRMuralInfo *pMural)
     1540{
     1541    CRContext *pContext = pContextInfo->pContext;
     1542    GLint storedWidth, storedHeight;
     1543    int32_t rc = VINF_SUCCESS;
     1544
     1545    if (version > SHCROGL_SSM_VERSION_WITH_BUGGY_FB_IMAGE_DATA)
     1546    {
     1547        CRASSERT(cr_server.currentCtxInfo == pContextInfo);
     1548        CRASSERT(cr_server.currentMural = pMural);
     1549        storedWidth = pMural->width;
     1550        storedHeight = pMural->height;
     1551        CRASSERT(pContext->buffer.storedWidth == storedWidth);
     1552        CRASSERT(pContext->buffer.storedHeight == storedHeight);
     1553    }
     1554    else
     1555    {
     1556        storedWidth = pContext->buffer.storedWidth;
     1557        storedHeight = pContext->buffer.storedHeight;
     1558    }
     1559
     1560    if (storedWidth && storedHeight)
     1561    {
     1562        CRBufferState *pBuf = &pContext->buffer;
     1563        GLint cbData;
     1564        void *pData;
     1565
     1566        cbData = crPixelSize(GL_RGBA, GL_UNSIGNED_BYTE) * storedWidth * storedHeight;
     1567
     1568        pData = crAlloc(cbData);
     1569        if (!pData)
     1570        {
     1571            crWarning("crAlloc failed trying to allocate %d of fb data", cbData);
     1572            pBuf->pFrontImg = NULL;
     1573            pBuf->pBackImg = NULL;
     1574            return VERR_NO_MEMORY;
     1575        }
     1576
     1577        rc = SSMR3GetMem(pSSM, pData, cbData);
     1578        AssertRCReturn(rc, rc);
     1579
     1580        pBuf->pFrontImg = pData;
     1581
     1582        pData = crAlloc(cbData);
     1583        if (!pData)
     1584        {
     1585            crWarning("crAlloc failed trying to allocate %d of bb data", cbData);
     1586            pBuf->pBackImg = NULL;
     1587            return VERR_NO_MEMORY;
     1588        }
     1589
     1590        rc = SSMR3GetMem(pSSM, pData, cbData);
     1591        AssertRCReturn(rc, rc);
     1592
     1593        pBuf->pBackImg = pData;
     1594
     1595        if (version > SHCROGL_SSM_VERSION_WITH_BUGGY_FB_IMAGE_DATA)
     1596        {
     1597            /* can apply the data right away */
     1598            crStateApplyFBImage(pContext);
     1599            CRASSERT(!pBuf->pFrontImg);
     1600            CRASSERT(!pBuf->pBackImg);
     1601        }
     1602    }
     1603
     1604    CRASSERT(RT_SUCCESS(rc));
     1605    return VINF_SUCCESS;
     1606}
     1607
    10501608DECLEXPORT(int32_t) crVBoxServerLoadState(PSSMHANDLE pSSM, uint32_t version)
    10511609{
     
    11111669    }
    11121670
     1671    if (version > SHCROGL_SSM_VERSION_WITH_BUGGY_FB_IMAGE_DATA)
     1672    {
     1673        /* we have a mural data here */
     1674        rc = crVBoxServerLoadMurals(pSSM, version);
     1675        AssertRCReturn(rc, rc);
     1676    }
     1677
     1678    if (version > SHCROGL_SSM_VERSION_WITH_BUGGY_FB_IMAGE_DATA && uiNumElems)
     1679    {
     1680        /* set the current client to allow doing crServerPerformMakeCurrent later */
     1681        CRASSERT(cr_server.numClients);
     1682        cr_server.curClient = cr_server.clients[0];
     1683    }
     1684
     1685    rc = crStateLoadGlobals(pSSM, version);
     1686    AssertRCReturn(rc, rc);
     1687
    11131688    /* Restore context state data */
    11141689    for (ui=0; ui<uiNumElems; ++ui)
     
    11161691        CRContextInfo* pContextInfo;
    11171692        CRContext *pContext;
     1693        CRMuralInfo *pMural = NULL;
     1694        int32_t winId = 0;
    11181695
    11191696        rc = SSMR3GetMem(pSSM, &key, sizeof(key));
     
    11251702        pContext = pContextInfo->pContext;
    11261703
     1704        if (version > SHCROGL_SSM_VERSION_WITH_BUGGY_FB_IMAGE_DATA)
     1705        {
     1706            rc = SSMR3GetMem(pSSM, &winId, sizeof(winId));
     1707            AssertRCReturn(rc, rc);
     1708
     1709            if (winId)
     1710            {
     1711                pMural = (CRMuralInfo*)crHashtableSearch(cr_server.muralTable, winId);
     1712                CRASSERT(pMural);
     1713            }
     1714            else
     1715            {
     1716                /* null winId means a dummy mural, get it */
     1717                pMural = crServerGetDummyMural(pContextInfo->CreateInfo.visualBits);
     1718                CRASSERT(pMural);
     1719            }
     1720
     1721            crServerPerformMakeCurrent(pMural, pContextInfo);
     1722        }
     1723
    11271724        rc = crStateLoadContext(pContext, cr_server.contextTable, crVBoxServerGetContextCB, pSSM, version);
    11281725        AssertRCReturn(rc, rc);
    1129     }
    1130 
    1131     /* Load windows */
    1132     rc = SSMR3GetU32(pSSM, &uiNumElems);
    1133     AssertRCReturn(rc, rc);
    1134     for (ui=0; ui<uiNumElems; ++ui)
    1135     {
    1136         CRCreateInfo_t createInfo;
    1137         char psz[200];
    1138         GLint winID;
    1139         unsigned long key;
    1140 
    1141         rc = SSMR3GetMem(pSSM, &key, sizeof(key));
     1726
     1727        /*Restore front/back buffer images*/
     1728        rc = crVBoxServerLoadFBImage(pSSM, version, pContextInfo, pMural);
    11421729        AssertRCReturn(rc, rc);
    1143         rc = SSMR3GetMem(pSSM, &createInfo, sizeof(createInfo));
     1730    }
     1731
     1732    if (version > SHCROGL_SSM_VERSION_WITH_BUGGY_FB_IMAGE_DATA)
     1733    {
     1734        CRContextInfo *pContextInfo;
     1735        CRMuralInfo *pMural;
     1736        GLint ctxId;
     1737
     1738        rc = SSMR3GetU32(pSSM, &uiNumElems);
    11441739        AssertRCReturn(rc, rc);
    1145 
    1146         if (createInfo.pszDpyName)
    1147         {
    1148             rc = SSMR3GetStrZEx(pSSM, psz, 200, NULL);
     1740        for (ui=0; ui<uiNumElems; ++ui)
     1741        {
     1742            CRbitvalue initialCtxUsage[CR_MAX_BITARRAY];
     1743            CRMuralInfo *pInitialCurMural;
     1744
     1745            rc = SSMR3GetMem(pSSM, &key, sizeof(key));
    11491746            AssertRCReturn(rc, rc);
    1150             createInfo.pszDpyName = psz;
    1151         }
    1152 
    1153         winID = crServerDispatchWindowCreateEx(createInfo.pszDpyName, createInfo.visualBits, key);
    1154         CRASSERT((int64_t)winID == (int64_t)key);
    1155     }
    1156 
    1157     /* Load cr_server.muralTable */
    1158     rc = SSMR3GetU32(pSSM, &uiNumElems);
    1159     AssertRCReturn(rc, rc);
    1160     for (ui=0; ui<uiNumElems; ++ui)
    1161     {
    1162         CRMuralInfo muralInfo;
    1163 
    1164         rc = SSMR3GetMem(pSSM, &key, sizeof(key));
     1747
     1748            rc = SSMR3GetMem(pSSM, &ctxId, sizeof(ctxId));
     1749            AssertRCReturn(rc, rc);
     1750
     1751            pMural = (CRMuralInfo*)crHashtableSearch(cr_server.muralTable, key);
     1752            CRASSERT(pMural);
     1753            if (ctxId)
     1754            {
     1755                pContextInfo = (CRContextInfo *)crHashtableSearch(cr_server.contextTable, ctxId);
     1756                CRASSERT(pContextInfo);
     1757            }
     1758            else
     1759                pContextInfo =  &cr_server.MainContextInfo;
     1760
     1761            crMemcpy(initialCtxUsage, pMural->ctxUsage, sizeof (initialCtxUsage));
     1762            pInitialCurMural = pContextInfo->currentMural;
     1763
     1764            crServerPerformMakeCurrent(pMural, pContextInfo);
     1765
     1766            rc = crVBoxServerLoadFBImage(pSSM, version, pContextInfo, pMural);
     1767            AssertRCReturn(rc, rc);
     1768
     1769            /* restore the reference data, we synchronize it with the HW state in a later crServerPerformMakeCurrent call */
     1770            crMemcpy(pMural->ctxUsage, initialCtxUsage, sizeof (initialCtxUsage));
     1771            pContextInfo->currentMural = pInitialCurMural;
     1772        }
     1773
     1774        if (cr_server.currentCtxInfo != &cr_server.MainContextInfo)
     1775        {
     1776            /* most ogl data gets loaded to hw on chromium 3D state switch, i.e. inside crStateMakeCurrent -> crStateSwitchContext
     1777             * to force the crStateSwitchContext being called later, we need to  set the current context to our dummy one */
     1778            pMural = crServerGetDummyMural(cr_server.MainContextInfo.CreateInfo.visualBits);
     1779            CRASSERT(pMural);
     1780            crServerPerformMakeCurrent(pMural, &cr_server.MainContextInfo);
     1781        }
     1782
     1783        cr_server.curClient = NULL;
     1784        cr_server.bForceMakeCurrentOnClientSwitch = GL_TRUE;
     1785    }
     1786    else
     1787    {
     1788        CRServerFreeIDsPool_t dummyIdsPool;
     1789
     1790        /* we have a mural data here */
     1791        rc = crVBoxServerLoadMurals(pSSM, version);
    11651792        AssertRCReturn(rc, rc);
    1166         rc = SSMR3GetMem(pSSM, &muralInfo, RT_OFFSETOF(CRMuralInfo, CreateInfo));
    1167         AssertRCReturn(rc, rc);
    1168 
    1169         if (version <= SHCROGL_SSM_VERSION_BEFORE_FRONT_DRAW_TRACKING)
    1170             muralInfo.bFbDraw = GL_TRUE;
    1171 
    1172         if (muralInfo.pVisibleRects)
    1173         {
    1174             muralInfo.pVisibleRects = crAlloc(4*sizeof(GLint)*muralInfo.cVisibleRects);
    1175             if (!muralInfo.pVisibleRects)
    1176             {
    1177                 return VERR_NO_MEMORY;
    1178             }
    1179 
    1180             rc = SSMR3GetMem(pSSM, muralInfo.pVisibleRects, 4*sizeof(GLint)*muralInfo.cVisibleRects);
    1181             AssertRCReturn(rc, rc);
    1182         }
    1183 
    1184         /* Restore windows geometry info */
    1185         crServerDispatchWindowSize(key, muralInfo.width, muralInfo.height);
    1186         crServerDispatchWindowPosition(key, muralInfo.gX, muralInfo.gY);
    1187         /* Same workaround as described in stub.c:stubUpdateWindowVisibileRegions for compiz on a freshly booted VM*/
    1188         if (muralInfo.bReceivedRects)
    1189         {
    1190             crServerDispatchWindowVisibleRegion(key, muralInfo.cVisibleRects, muralInfo.pVisibleRects);
    1191         }
    1192         crServerDispatchWindowShow(key, muralInfo.bVisible);
    1193 
    1194         if (muralInfo.pVisibleRects)
    1195         {
    1196             crFree(muralInfo.pVisibleRects);
    1197         }
    1198     }
    1199 
    1200     /* Load starting free context and window IDs */
    1201     rc = SSMR3GetMem(pSSM, &cr_server.idsPool, sizeof(cr_server.idsPool));
    1202     CRASSERT(rc == VINF_SUCCESS);
     1793
     1794        /* not used any more, just read it out and ignore */
     1795        rc = SSMR3GetMem(pSSM, &dummyIdsPool, sizeof(dummyIdsPool));
     1796        CRASSERT(rc == VINF_SUCCESS);
     1797    }
    12031798
    12041799    /* Load clients info */
Note: See TracChangeset for help on using the changeset viewer.

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