VirtualBox

Changeset 35770 in vbox for trunk/src


Ignore:
Timestamp:
Jan 28, 2011 3:23:22 PM (14 years ago)
Author:
vboxsync
Message:

crOpenGL: fix deadlock with multiply screens (#5462)

Location:
trunk/src/VBox/HostServices/SharedOpenGL
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostServices/SharedOpenGL/crserver/crservice.cpp

    r35347 r35770  
    5858
    5959#include <VBox/com/errorprint.h>
     60#include <iprt/thread.h>
     61#include <iprt/critsect.h>
     62#include <iprt/semaphore.h>
     63#include <iprt/asm.h>
     64
     65#include "cr_mem.h"
    6066
    6167PVBOXHGCMSVCHELPERS g_pHelpers;
     
    7379static const char* gszVBoxOGLSSMMagic = "***OpenGL state data***";
    7480
     81/* Used to process guest calls exceeding maximum allowed HGCM call size in a sequence of smaller calls */
    7582typedef struct _CRVBOXSVCBUFFER_t {
    7683    uint32_t uiId;
     
    8390static uint32_t g_CRVBoxSVCBufferID = 0;
    8491
     92/* svcPresentFBO related data */
     93typedef struct _CRVBOXSVCPRESENTFBOCMD_t {
     94    void *pData;
     95    int32_t screenId, x, y, w, h;
     96    _CRVBOXSVCPRESENTFBOCMD_t *pNext;
     97} CRVBOXSVCPRESENTFBOCMD_t, *PCRVBOXSVCPRESENTFBOCMD_t;
     98
     99typedef struct _CRVBOXSVCPRESENTFBO_t {
     100    PCRVBOXSVCPRESENTFBOCMD_t pQueueHead, pQueueTail;   /* Head/Tail of FIFO cmds queue */
     101    RTCRITSECT                hQueueLock;       /* Queue lock */
     102    RTTHREAD                  hWorkerThread;    /* Worker thread */
     103    bool volatile             bShutdownWorker;  /* Shutdown flag */
     104    RTSEMEVENT                hEventProcess;    /* Signalled when worker thread should process data or exit */
     105} CRVBOXSVCPRESENTFBO_t;
     106
     107static CRVBOXSVCPRESENTFBO_t g_SvcPresentFBO;
     108
     109/* Schedule a call to a separate worker thread to avoid deadlock on EMT thread when the screen configuration changes
     110   and we're processing crServerPresentFBO caused by guest application command.
     111   To avoid unnecessary memcpy, worker thread frees the data passed.
     112*/
     113static DECLCALLBACK(void) svcPresentFBO(void *data, int32_t screenId, int32_t x, int32_t y, uint32_t w, uint32_t h)
     114{
     115    PCRVBOXSVCPRESENTFBOCMD_t pCmd;
     116
     117    pCmd = (PCRVBOXSVCPRESENTFBOCMD_t) RTMemAlloc(sizeof(CRVBOXSVCPRESENTFBOCMD_t));
     118    if (!pCmd)
     119    {
     120        LogRel(("SHARED_CROPENGL svcPresentFBO: not enough memory (%d)\n", sizeof(CRVBOXSVCPRESENTFBOCMD_t)));
     121        return;
     122    }
     123    pCmd->pData = data;
     124    pCmd->screenId = screenId;
     125    pCmd->x = x;
     126    pCmd->y = y;
     127    pCmd->w = w;
     128    pCmd->h = h;
     129    pCmd->pNext = NULL;
     130
     131    RTCritSectEnter(&g_SvcPresentFBO.hQueueLock);
     132
     133    if (g_SvcPresentFBO.pQueueTail)
     134    {
     135        g_SvcPresentFBO.pQueueTail->pNext = pCmd;
     136    }
     137    else
     138    {
     139        Assert(!g_SvcPresentFBO.pQueueHead);
     140        g_SvcPresentFBO.pQueueHead = pCmd;
     141    }
     142    g_SvcPresentFBO.pQueueTail = pCmd;
     143
     144    RTCritSectLeave(&g_SvcPresentFBO.hQueueLock);
     145
     146    RTSemEventSignal(g_SvcPresentFBO.hEventProcess);
     147    /*
     148    HRESULT rc;
     149    ComPtr<IDisplay> pDisplay;
     150
     151    CHECK_ERROR(g_pConsole, COMGETTER(Display)(pDisplay.asOutParam()));
     152    CHECK_ERROR(pDisplay, DrawToScreen(screenId, (BYTE*)data, x, y, w, h));
     153    */
     154}
     155
     156static DECLCALLBACK(int) svcPresentFBOWorkerThreadProc(RTTHREAD ThreadSelf, void *pvUser)
     157{
     158    int rc = VINF_SUCCESS;
     159    PCRVBOXSVCPRESENTFBOCMD_t pCmd;
     160
     161    Log(("SHARED_CROPENGL svcPresentFBOWorkerThreadProc started\n"));
     162
     163    for (;;)
     164    {
     165        rc = RTSemEventWait(g_SvcPresentFBO.hEventProcess, RT_INDEFINITE_WAIT);
     166        AssertRCReturn(rc, rc);
     167
     168        if (g_SvcPresentFBO.bShutdownWorker)
     169        {
     170            break;
     171        }
     172
     173        rc = RTCritSectEnter(&g_SvcPresentFBO.hQueueLock);
     174        AssertRCReturn(rc, rc);
     175
     176        pCmd = g_SvcPresentFBO.pQueueHead;
     177        while (pCmd)
     178        {
     179            ComPtr<IDisplay> pDisplay;
     180
     181            /*remove from queue*/
     182            g_SvcPresentFBO.pQueueHead = pCmd->pNext;
     183            if (!g_SvcPresentFBO.pQueueHead)
     184            {
     185                g_SvcPresentFBO.pQueueTail = NULL;
     186            }
     187
     188            CHECK_ERROR_RET(g_pConsole, COMGETTER(Display)(pDisplay.asOutParam()), rc);
     189
     190            RTCritSectLeave(&g_SvcPresentFBO.hQueueLock);
     191
     192            CHECK_ERROR_RET(pDisplay, DrawToScreen(pCmd->screenId, (BYTE*)pCmd->pData, pCmd->x, pCmd->y, pCmd->w, pCmd->h), rc);
     193
     194            crFree(pCmd->pData);
     195            RTMemFree(pCmd);
     196
     197            rc = RTCritSectEnter(&g_SvcPresentFBO.hQueueLock);
     198            AssertRCReturn(rc, rc);
     199            pCmd = g_SvcPresentFBO.pQueueHead;
     200        }
     201
     202        RTCritSectLeave(&g_SvcPresentFBO.hQueueLock);
     203    }
     204
     205    Log(("SHARED_CROPENGL svcPresentFBOWorkerThreadProc finished\n"));
     206
     207    return rc;
     208}
     209
     210static int svcPresentFBOInit(void)
     211{
     212    int rc = VINF_SUCCESS;
     213
     214    g_SvcPresentFBO.pQueueHead = NULL;
     215    g_SvcPresentFBO.pQueueTail = NULL;
     216    g_SvcPresentFBO.bShutdownWorker = false;
     217
     218    rc = RTCritSectInit(&g_SvcPresentFBO.hQueueLock);
     219    AssertRCReturn(rc, rc);
     220
     221    rc = RTSemEventCreate(&g_SvcPresentFBO.hEventProcess);
     222    AssertRCReturn(rc, rc);
     223
     224    rc = RTThreadCreate(&g_SvcPresentFBO.hWorkerThread, svcPresentFBOWorkerThreadProc, NULL, 0,
     225                        RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "OpenGLWorker");
     226    AssertRCReturn(rc, rc);
     227
     228    crVBoxServerSetPresentFBOCB(svcPresentFBO);
     229
     230    return rc;
     231}
     232
     233static int svcPresentFBOTearDown(void)
     234{
     235    int rc = VINF_SUCCESS;
     236    PCRVBOXSVCPRESENTFBOCMD_t pQueue, pTmp;
     237
     238    ASMAtomicWriteBool(&g_SvcPresentFBO.bShutdownWorker, true);
     239    RTSemEventSignal(g_SvcPresentFBO.hEventProcess);
     240    rc = RTThreadWait(g_SvcPresentFBO.hWorkerThread, 5000, NULL);
     241    AssertRCReturn(rc, rc);
     242
     243    RTCritSectDelete(&g_SvcPresentFBO.hQueueLock);
     244    RTSemEventDestroy(g_SvcPresentFBO.hEventProcess);
     245
     246    pQueue = g_SvcPresentFBO.pQueueHead;
     247    while (pQueue)
     248    {
     249        pTmp = pQueue->pNext;
     250        crFree(pQueue->pData);
     251        RTMemFree(pQueue);
     252        pQueue = pTmp;
     253    }
     254    g_SvcPresentFBO.pQueueHead = NULL;
     255    g_SvcPresentFBO.pQueueTail = NULL;
     256
     257    return rc;
     258}
     259
    85260static DECLCALLBACK(int) svcUnload (void *)
    86261{
     
    90265
    91266    crVBoxServerTearDown();
     267
     268    svcPresentFBOTearDown();
    92269
    93270    return rc;
     
    303480        shown = 1;
    304481    }
    305 }
    306 
    307 static DECLCALLBACK(void) svcPresentFBO(void *data, int32_t screenId, int32_t x, int32_t y, uint32_t w, uint32_t h)
    308 {
    309 #if 0
    310     ComPtr<IDisplay> pDisplay;
    311     BYTE *data;
    312     int i,j;
    313     CHECK_ERROR(g_pConsole, COMGETTER(Display)(pDisplay.asOutParam()));
    314 
    315     data = (BYTE*) RTMemTmpAllocZ(100*100*4);
    316 
    317     for (i=0; i<100; i+=2)
    318     {
    319         for (j=0; j<100; ++j)
    320         {
    321             *(data+i*100*4+j*4+0) = 0xFF;
    322             *(data+i*100*4+j*4+1) = 0xFF;
    323             *(data+i*100*4+j*4+2) = 0xFF;
    324             *(data+i*100*4+j*4+3) = 0xFF;
    325         }
    326     }
    327 
    328     CHECK_ERROR(pDisplay, DrawToScreen(screenId, data, 0, 0, 100, 100));
    329 
    330     RTMemTmpFree(data);
    331 #endif
    332     HRESULT rc;
    333     ComPtr<IDisplay> pDisplay;
    334 
    335     CHECK_ERROR(g_pConsole, COMGETTER(Display)(pDisplay.asOutParam()));
    336     CHECK_ERROR(pDisplay, DrawToScreen(screenId, (BYTE*)data, x, y, w, h));
    337482}
    338483
     
    12581403                return VERR_NOT_SUPPORTED;
    12591404
    1260             crVBoxServerSetPresentFBOCB(svcPresentFBO);
     1405            rc = svcPresentFBOInit();
    12611406        }
    12621407    }
  • trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_muralfbo.c

    r34270 r35770  
    337337        if (crServerIntersectScreen(mural, i, &rect))
    338338        {
    339             tmppixels = crAlloc(4*(rect.x2-rect.x1)*(rect.y2-rect.y1));
    340             if (!tmppixels)
    341             {
    342                 crWarning("Out of memory in crServerPresentFBO");
    343                 crFree(pixels);
    344                 return;
    345             }
    346 
    347339            /* rect in window relative coords */
    348340            crServerTransformRect(&rectwr, &rect, -mural->gX, -mural->gY);
     
    350342            if (!mural->pVisibleRects)
    351343            {
     344                tmppixels = crAlloc(4*(rect.x2-rect.x1)*(rect.y2-rect.y1));
     345                if (!tmppixels)
     346                {
     347                    crWarning("Out of memory in crServerPresentFBO");
     348                    crFree(pixels);
     349                    return;
     350                }
     351
    352352                crServerCopySubImage(tmppixels, pixels, &rectwr, mural->fboWidth, mural->fboHeight);
     353                /*Note: pfnPresentFBO would free tmppixels*/
    353354                cr_server.pfnPresentFBO(tmppixels, i, rect.x1-cr_server.screen[i].x, rect.y1-cr_server.screen[i].y, rect.x2-rect.x1, rect.y2-rect.y1);
    354355            }
     
    359360                    if (crServerIntersectRect(&rectwr, (CRrecti*) &mural->pVisibleRects[4*j], &sectr))
    360361                    {
     362                        tmppixels = crAlloc(4*(sectr.x2-sectr.x1)*(sectr.y2-sectr.y1));
     363                        if (!tmppixels)
     364                        {
     365                            crWarning("Out of memory in crServerPresentFBO");
     366                            crFree(pixels);
     367                            return;
     368                        }
     369
    361370                        crServerCopySubImage(tmppixels, pixels, &sectr, mural->fboWidth, mural->fboHeight);
     371                        /*Note: pfnPresentFBO would free tmppixels*/
    362372                        cr_server.pfnPresentFBO(tmppixels, i,
    363373                                                sectr.x1+mural->gX-cr_server.screen[i].x,
     
    367377                }
    368378            }
    369 
    370             crFree(tmppixels);
    371379        }
    372380    }
Note: See TracChangeset for help on using the changeset viewer.

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