VirtualBox

Changeset 50274 in vbox


Ignore:
Timestamp:
Jan 29, 2014 4:46:57 PM (11 years ago)
Author:
vboxsync
Message:

crOpenGL/osx: impl async window modifications & present handling to prevent deadlocking

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

Legend:

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

    r50241 r50274  
    323323    mural->height = height;
    324324
    325     cr_server.head_spu->dispatch_table.WindowSize(mural->spuWindow, mural->width, mural->height);
    326 
    327325    if (cr_server.curClient && cr_server.curClient->currentMural == mural
    328326            && !mural->fRedirected)
  • trunk/src/VBox/HostServices/SharedOpenGL/render/renderspu.c

    r50184 r50274  
    17051705        }
    17061706
     1707        if (!context)
     1708            return (const GLubyte *)nativeExt;
     1709
    17071710        crExt = crStrjoin3(crExtensions, " ", crAppOnlyExtensions);
    17081711        s1 = crStrIntersect(nativeExt, crExt);
  • trunk/src/VBox/HostServices/SharedOpenGL/render/renderspu_cocoa_helper.m

    r50095 r50274  
    348348    bool m_fNeedViewportUpdate;
    349349    bool m_fNeedCtxUpdate;
     350    bool m_fDataVisible;
     351    bool m_fEverSized;
    350352}
    351353- (id)initWithFrame:(NSRect)frame thread:(RTTHREAD)aThread parentView:(NSView*)pParentView winInfo:(WindowInfo*)pWinInfo;
     
    360362- (void)setPos:(NSPoint)pos;
    361363- (NSPoint)pos;
     364- (bool)isEverSized;
    362365- (void)setSize:(NSSize)size;
    363366- (NSSize)size;
    364367- (void)updateViewportCS;
    365 - (void)reshape;
    366 - (void)reshapeLocked;
     368- (void)vboxReshapePerform;
     369- (void)vboxReshapeOnResizePerform;
     370- (void)vboxReshapeOnReparentPerform;
    367371
    368372- (void)createDockTile;
     
    719723     * call in the OpenGL thread. */
    720724    /*
    721     [m_pOverlayView performSelector:@selector(reshape) onThread:m_Thread withObject:nil waitUntilDone:YES];
     725    [m_pOverlayView performSelector:@selector(vboxReshapePerform) onThread:m_Thread withObject:nil waitUntilDone:YES];
    722726    */
    723727
    724     [m_pOverlayView reshape];
     728    if ([m_pOverlayView isEverSized])
     729    {   
     730        if([NSThread isMainThread])
     731            [m_pOverlayView vboxReshapePerform];
     732        else
     733            [self performSelectorOnMainThread:@selector(vboxReshapePerform) withObject:nil waitUntilDone:NO];
     734    }
    725735}
    726736
     
    744754         * window resize itself properly. */
    745755        /*
    746         [m_pOverlayView performSelector:@selector(reshape) withObject:nil afterDelay:0.2];
    747         [NSTimer scheduledTimerWithTimeInterval:0.2 target:m_pOverlayView selector:@selector(reshape) userInfo:nil repeats:NO];
     756        [m_pOverlayView performSelector:@selector(vboxReshapePerform) withObject:nil afterDelay:0.2];
     757        [NSTimer scheduledTimerWithTimeInterval:0.2 target:m_pOverlayView selector:@selector(vboxReshapePerform) userInfo:nil repeats:NO];
    748758        */
    749         [m_pOverlayView reshape];
     759
     760        if ([m_pOverlayView isEverSized])
     761        {   
     762            if([NSThread isMainThread])
     763                [m_pOverlayView vboxReshapePerform];
     764            else
     765                [self performSelectorOnMainThread:@selector(vboxReshapePerform) withObject:nil waitUntilDone:NO];
     766        }       
    750767    }
    751768}
     
    778795    m_fNeedViewportUpdate     = true;       
    779796    m_fNeedCtxUpdate          = true;
     797    m_fDataVisible            = false;
     798    m_fEverSized              = false;
    780799   
    781800    self = [super initWithFrame:frame];
     
    879898    m_Pos = pos;
    880899
    881     [self reshape];
     900    if (m_fEverSized)
     901        [self performSelectorOnMainThread:@selector(vboxReshapePerform) withObject:nil waitUntilDone:NO];
    882902   
    883903    /* we need to redwar on regions change, however the compositor now is cleared
     
    895915}
    896916
     917- (bool)isEverSized
     918{
     919    return m_fEverSized;
     920}
     921
    897922- (void)setSize:(NSSize)size
    898923{
     
    900925    NSView *pCurView;
    901926    m_Size = size;
     927   
     928    m_fEverSized = true;
    902929
    903930    DEBUG_MSG(("OVIW(%p): setSize: new size: %dx%d\n", (void*)self, (int)size.width, (int)size.height));
    904     [self reshape];
    905     [self createDockTile];
    906     /* have to rebind GL_TEXTURE_RECTANGLE_ARB as m_FBOTexId could be changed in updateFBO call */
    907     m_fNeedViewportUpdate = true;
    908     pCurCtx = [NSOpenGLContext currentContext];
    909     if (pCurCtx && pCurCtx == m_pGLCtx && (pCurView = [pCurCtx view]) == self)
    910     {
    911         [m_pGLCtx update];
    912         m_fNeedCtxUpdate = false;
    913     }
    914     else
    915     {
    916         /* do it in a lazy way */
    917         m_fNeedCtxUpdate = true;
    918     }
    919    
     931    [self performSelectorOnMainThread:@selector(vboxReshapeOnResizePerform) withObject:nil waitUntilDone:NO];
     932
    920933    /* we need to redwar on regions change, however the compositor now is cleared
    921934     * because all compositor&window data-related modifications are performed with compositor cleared
     
    942955       
    943956    /* Clear background to transparent */
    944     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);}
    945 
    946 - (void)reshapeLocked
     957    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
     958}
     959
     960- (void)vboxReshapeOnResizePerform
     961{
     962    [self vboxReshapePerform];
     963   
     964    [self createDockTile];
     965    /* have to rebind GL_TEXTURE_RECTANGLE_ARB as m_FBOTexId could be changed in updateFBO call */
     966    m_fNeedViewportUpdate = true;
     967#if 0
     968    pCurCtx = [NSOpenGLContext currentContext];
     969    if (pCurCtx && pCurCtx == m_pGLCtx && (pCurView = [pCurCtx view]) == self)
     970    {
     971        [m_pGLCtx update];
     972        m_fNeedCtxUpdate = false;
     973    }
     974    else
     975    {
     976        /* do it in a lazy way */
     977        m_fNeedCtxUpdate = true;
     978    }
     979#endif
     980}
     981
     982- (void)vboxReshapeOnReparentPerform
     983{
     984    [self createDockTile];
     985}
     986
     987- (void)vboxReshapePerform
    947988{
    948989    NSRect parentFrame = NSZeroRect;
     
    952993    NSRect newFrame    = NSZeroRect;
    953994
    954     DEBUG_MSG(("OVIW(%p): reshape\n", (void*)self));
     995    DEBUG_MSG(("OVIW(%p): vboxReshapePerform\n", (void*)self));
    955996   
    956997    parentFrame = [m_pParentView frame];
     
    10361077   
    10371078        vboxCtxLeave(&CtxInfo);
    1038     }
    1039 }
    1040 
    1041 - (void)reshape
    1042 {
    1043     int rc = renderspuVBoxCompositorLock(m_pWinInfo);
    1044     if (RT_SUCCESS(rc))
    1045     {
    1046         [self reshapeLocked];
    1047         renderspuVBoxCompositorUnlock(m_pWinInfo);
    10481079    }
    10491080}
     
    11111142}
    11121143
     1144- (bool)vboxSharedCtxCreate
     1145{
     1146    if (m_pSharedGLCtx)
     1147        return true;
     1148       
     1149    Assert(!m_pBlitter);
     1150    m_pBlitter = RTMemAlloc(sizeof (*m_pBlitter));
     1151    if (!m_pBlitter)
     1152    {
     1153        DEBUG_WARN(("m_pBlitter allocation failed"));
     1154        return false;
     1155    }
     1156       
     1157    int rc = CrBltInit(m_pBlitter, NULL, false, false, &render_spu.GlobalShaders, &render_spu.blitterDispatch);
     1158    if (RT_SUCCESS(rc))
     1159    {
     1160        DEBUG_MSG(("blitter created successfully for view 0x%p\n", (void*)self));
     1161    }
     1162    else
     1163    {
     1164        DEBUG_WARN(("CrBltInit failed, rc %d", rc));
     1165        RTMemFree(m_pBlitter);
     1166        m_pBlitter = NULL;
     1167        return false;
     1168    }       
     1169   
     1170    GLint opaque       = 0;
     1171    /* Create a shared context out of the main context. Use the same pixel format. */
     1172    NSOpenGLContext *pSharedGLCtx = [[NSOpenGLContext alloc] initWithFormat:[(OverlayOpenGLContext*)m_pGLCtx openGLPixelFormat] shareContext:m_pGLCtx];
     1173       
     1174    /* Set the new context as non opaque */
     1175    [pSharedGLCtx setValues:&opaque forParameter:NSOpenGLCPSurfaceOpacity];
     1176    /* Set this view as the drawable for the new context */
     1177    [pSharedGLCtx setView: self];
     1178    m_fNeedViewportUpdate = true;
     1179   
     1180    m_pSharedGLCtx = pSharedGLCtx;
     1181   
     1182    return true;
     1183}
     1184
    11131185- (void)vboxTryDraw
    11141186{
    1115     GLint opaque       = 0;
     1187    glFlush();
     1188                       
     1189    /* issue to the gui thread */
     1190    [self setNeedsDisplay:YES];
     1191}
     1192
     1193- (void)vboxTryDrawUI
     1194{
     1195    const VBOXVR_SCR_COMPOSITOR *pCompositor = renderspuVBoxCompositorAcquire(m_pWinInfo);
     1196    if (!m_fDataVisible && !pCompositor)
     1197        return;
     1198
     1199    VBOXVR_SCR_COMPOSITOR TmpCompositor;
     1200   
     1201    if (pCompositor)
     1202    {
     1203        if (!m_pSharedGLCtx)
     1204        {
     1205            Assert(!m_fDataVisible);
     1206            renderspuVBoxCompositorRelease(m_pWinInfo);
     1207            if (![self vboxSharedCtxCreate])
     1208            {
     1209                DEBUG_WARN(("vboxSharedCtxCreate failed\n"));
     1210                return;
     1211            }
     1212           
     1213            Assert(m_pSharedGLCtx);
     1214           
     1215            pCompositor = renderspuVBoxCompositorAcquire(m_pWinInfo);
     1216            Assert(!m_fDataVisible);
     1217            if (!pCompositor)
     1218                return;
     1219        }
     1220    }
     1221    else
     1222    {
     1223        CrVrScrCompositorInit(&TmpCompositor, NULL);
     1224        pCompositor = &TmpCompositor;
     1225    }
     1226   
    11161227    if ([self lockFocusIfCanDraw])
    11171228    {
    1118         const const VBOXVR_SCR_COMPOSITOR *pCompositor = NULL;
    1119         if (!m_pSharedGLCtx)
    1120             {
    1121                 pCompositor = renderspuVBoxCompositorAcquire(m_pWinInfo);
    1122                 if (pCompositor)
    1123                 {
    1124                     Assert(!m_pBlitter);
    1125                 m_pBlitter = RTMemAlloc(sizeof (*m_pBlitter));
    1126                 if (m_pBlitter)
    1127                 {
    1128                     int rc = CrBltInit(m_pBlitter, NULL, false, false, &render_spu.GlobalShaders, &render_spu.blitterDispatch);
    1129                     if (RT_SUCCESS(rc))
    1130                     {
    1131                         DEBUG_MSG(("blitter created successfully for view 0x%p\n", (void*)self));
    1132                     }
    1133                     else
    1134                     {
    1135                         DEBUG_WARN(("CrBltInit failed, rc %d", rc));
    1136                         RTMemFree(m_pBlitter);
    1137                         m_pBlitter = NULL;
    1138                     }       
    1139                 }
    1140                 else
    1141                 {
    1142                     DEBUG_WARN(("m_pBlitter allocation failed"));
    1143                 }
    1144                    
    1145                     if (m_pBlitter)
    1146                     {
    1147                         /* Create a shared context out of the main context. Use the same pixel format. */
    1148                         m_pSharedGLCtx = [[NSOpenGLContext alloc] initWithFormat:[(OverlayOpenGLContext*)m_pGLCtx openGLPixelFormat] shareContext:m_pGLCtx];
    1149                
    1150                         /* Set the new context as non opaque */
    1151                         [m_pSharedGLCtx setValues:&opaque forParameter:NSOpenGLCPSurfaceOpacity];
    1152                         /* Set this view as the drawable for the new context */
    1153                         [m_pSharedGLCtx setView: self];
    1154                         m_fNeedViewportUpdate = true;
    1155                     }
    1156 #ifdef CR_RENDER_FORCE_PRESENT_MAIN_THREAD
    1157                                 renderspuVBoxCompositorRelease(m_pWinInfo);
    1158                                 pCompositor = NULL;
    1159 #endif
    1160                     }
    1161                 }
    1162                
    1163                 if (m_pSharedGLCtx)
    1164                 {
    1165                         if (!pCompositor)
    1166                         {
    1167 #ifndef CR_RENDER_FORCE_PRESENT_MAIN_THREAD
    1168                                 /* we do not want to be blocked with the GUI thread here, so only draw her eif we are really able to do that w/o bllocking */
    1169                                 int rc = renderspuVBoxCompositorTryAcquire(m_pWinInfo, &pCompositor);
    1170                                 if (RT_SUCCESS(rc))
    1171                                 {
    1172                                         Assert(pCompositor);
    1173                                 }
    1174                             else if (rc == VERR_SEM_BUSY)
    1175 #endif
    1176                             {
    1177                                 glFlush();
    1178                                    
    1179                                 /* issue to the gui thread */
    1180                                 [self setNeedsDisplay:YES];
    1181                             }
    1182 #ifndef CR_RENDER_FORCE_PRESENT_MAIN_THREAD
    1183                             else
    1184                             {
    1185                                 /* this is somewhat we do not expect */
    1186                                 DEBUG_MSG(("renderspuVBoxCompositorTryAcquire failed rc %d", rc));
    1187                             }
    1188 #endif
    1189                         }
    1190                
    1191 #ifdef CR_RENDER_FORCE_PRESENT_MAIN_THREAD
    1192                         Assert(!pCompositor);
    1193 #endif 
    1194                         if (pCompositor)
    1195                         {
    1196                                 [self vboxPresent:pCompositor];
    1197                                 renderspuVBoxCompositorRelease(m_pWinInfo);
    1198                         }
    1199                 }
    1200                 else
    1201                 {
    1202                         AssertRelease(!pCompositor);
    1203                 }
     1229        [self vboxPresent:pCompositor];
     1230        if (pCompositor != &TmpCompositor)
     1231            renderspuVBoxCompositorRelease(m_pWinInfo);
     1232           
    12041233        [self unlockFocus];
    12051234    }
    12061235    else
    12071236    {
    1208         [self setNeedsDisplay:YES];
    1209     }
    1210 }
    1211 
    1212 - (void)vboxTryDrawUI
    1213 {
    1214     if ([self lockFocusIfCanDraw])
    1215     {
    1216         if (m_pSharedGLCtx)
    1217             {
    1218 #if 1
    1219             /* tmp workaround to prevent potential deadlock:
    1220              * crOpenGL service thread does compositor lock acquire and calls cocoa NS methods that could synchronize on the GUI thread
    1221              * while here we do a reverse order: acquire compositor lock being in gui thread.
    1222              * this is why we do only try acquire and re-submit repaint event if compositor lock is busy */
    1223             const VBOXVR_SCR_COMPOSITOR *pCompositor = NULL;
    1224             int rc = renderspuVBoxCompositorTryAcquire(m_pWinInfo, &pCompositor);
    1225             if (RT_SUCCESS(rc))
    1226             {
    1227                 Assert(pCompositor);
    1228                 [self vboxPresent:pCompositor];
    1229                 renderspuVBoxCompositorRelease(m_pWinInfo);
    1230             }
    1231             else if (rc == VERR_SEM_BUSY)
    1232             {
    1233                 Assert(!pCompositor);
    1234                 /* re-issue to the gui thread */
    1235 # ifdef DEBUG_misha
    1236                 DEBUG_WARN(("renderspuVBoxCompositorTryAcquire busy\n"));
    1237 # endif
    1238                 [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(vboxTryDrawUI) userInfo:nil repeats:NO];
    1239             }
    1240             else if (rc != VERR_INVALID_STATE) /* VERR_INVALID_STATE means no compositor, which is ok */
    1241             {
    1242                 Assert(!pCompositor);
    1243                 /* this is somewhat we do not expect */
    1244                 DEBUG_WARN(("renderspuVBoxCompositorTryAcquire failed rc %d", rc));
    1245             }
    1246 #else
    1247                 const VBOXVR_SCR_COMPOSITOR *pCompositor = renderspuVBoxCompositorAcquire(m_pWinInfo);
    1248                 if (pCompositor)
    1249                 {
    1250                         [self vboxPresent:pCompositor];
    1251                                 renderspuVBoxCompositorRelease(m_pWinInfo);
    1252                         }
    1253 #endif
    1254                 }
    1255         [self unlockFocus];
    1256     }
    1257     else
    1258     {
    1259         [self setNeedsDisplay:YES];
     1237        [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(vboxTryDrawUI) userInfo:nil repeats:NO];
    12601238    }
    12611239}
     
    12731251   
    12741252    Assert(pCompositor);
    1275    
    1276 #if 0 //def DEBUG
    1277             {
    1278                 NSOpenGLContext *pTstOldCtx = [NSOpenGLContext currentContext];
    1279                 NSView *pTstOldView = (pTstOldCtx ? [pTstOldCtx view] : nil);
    1280                 Assert(pTstOldCtx == m_pGLCtx);
    1281                 Assert(pTstOldView == self);
    1282             }
    1283 #endif
    12841253
    12851254    vboxCtxEnter(m_pSharedGLCtx, &CtxInfo);
     
    13611330    glClear(GL_COLOR_BUFFER_BIT);
    13621331   
     1332    m_fDataVisible = false;
     1333   
    13631334    CrVrScrCompositorGetStretching(pCompositor, &xStretch, &yStretch);
    13641335       
     
    14031374                   
    14041375                    CrBltBlitTexMural(m_pBlitter, true, CrTdTexGet(pTexData), pSrcRect, pDstRect, 1, fFlags | CRBLT_F_NOALPHA);
     1376                   
     1377                    m_fDataVisible = true;
    14051378                }
    14061379                CrBltLeave(m_pBlitter);
     
    14441417    WinInfo.height = r.size.height;
    14451418   
    1446     Assert(WinInfo.width = m_RootRect.size.width);
    1447     Assert(WinInfo.height = m_RootRect.size.height);
     1419    Assert(WinInfo.width == m_RootRect.size.width);
     1420    Assert(WinInfo.height == m_RootRect.size.height);
    14481421
    14491422    /*CrBltMuralSetCurrentInfo(m_pBlitter, NULL);*/
     
    18091782        {
    18101783            [[pParentView window] addChildWindow:[pOView overlayWin] ordered:NSWindowAbove];
    1811             [pOView createDockTile];
     1784            if ([pOView isEverSized])
     1785                [pOView performSelectorOnMainThread:@selector(vboxReshapeOnReparentPerform) withObject:nil waitUntilDone:NO];
    18121786        }
    18131787    }
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