VirtualBox

Ignore:
Timestamp:
Jul 30, 2015 3:13:06 PM (9 years ago)
Author:
vboxsync
Message:

vmsvga3d/mac: back/front buffer clearing fixes and hiding contexts that are not using their front buffers. When VMSVGA3D_OGL_WITH_SHARED_CTX is in play, we always use the shared context when PRESENTing surfaces to the user.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Graphics/DevVGA-SVGA3d-cocoa.m

    r56419 r57131  
    7878{
    7979@private
    80     NSView          *m_pParentView;
    81     /** Set if the buffers needs clearing. */
    82     bool            m_fClear;
     80    /** This points to the parent view, if there is one.  If there isn't a parent
     81     * the view will be hidden and never used for displaying stuff.  We only have
     82     * one visible context per guest screen that is visible to the user and
     83     * subject to buffer swapping. */
     84    NSView         *m_pParentView;
     85    /** Indicates that buffers (back+front) needs clearing before use because
     86     * the view changed size.  There are two buffers, so this is set to two
     87     * each time when the view area increases. */
     88    uint32_t        m_cClears;
     89    /** Set if the OpenGL context needs updating after a resize. */
     90    bool            m_fUpdateCtx;
    8391
    8492#ifndef USE_NSOPENGLVIEW
     
    8795#endif
    8896
    89     /* Position/Size tracking */
    90     NSPoint          m_Pos;
    91     NSSize           m_Size;
    92 
    93     /** This is necessary for clipping on the root window */
    94     NSRect           m_RootRect;
     97    /** The desired view position relative to super. */
     98    NSPoint         m_Pos;
     99    /** The desired view size. */
     100    NSSize          m_Size;
    95101}
    96102+ (void)createViewAndContext:(VMSVGA3DCreateViewAndContext *)pParams;
    97103- (id)initWithFrameAndFormat:(NSRect)frame parentView:(NSView*)pparentView pixelFormat:(NSOpenGLPixelFormat *)pFmt;
    98 - (void)setPos:(NSPoint)pos;
    99 - (void)setSize:(NSSize)size;
     104- (void)vboxSetPos:(NSPoint)pos;
     105- (void)vboxSetSize:(NSSize)size;
     106- (void)vboxReshapePerform;
    100107- (void)vboxReshape;
     108#if 0 // doesn't work or isn't needed :/
     109- (void)vboxFrameDidChange;
     110- (BOOL)postsFrameChangedNotifications;
     111#endif
     112- (void)vboxRemoveFromSuperviewAndHide;
    101113- (void)vboxClearBuffers;
     114- (void)vboxUpdateCtxIfNecessary;
     115- (void)vboxClearBackBufferIfNecessary;
    102116- (NSOpenGLContext *)makeCurrentGLContext;
    103117- (void)restoreSavedGLContext:(NSOpenGLContext *)pSavedCtx;
     
    191205            {
    192206                /*
    193                  * Attach the view to the parent.
     207                 * Attach the view to the parent if we have one.  Otherwise make sure its invisible.
    194208                 */
    195                 [pParams->pParentView addSubview:pView];
     209                if (pParams->pParentView)
     210                    [pParams->pParentView addSubview:pView];
     211                else
     212                    [pView setHidden:YES];
    196213
    197214                /*
    198215                 * Resize and return.
    199216                 */
    200                 //[pView setSize:Frame.size];
     217                //[pView vboxSetSize:Frame.size];
    201218
    202219                NSOpenGLContext *pSavedCtx = [pView makeCurrentGLContext];
     
    208225                x = 0; [pCtx setValues:&x forParameter:NSOpenGLCPSurfaceOpacity];
    209226
    210                 [pView setHidden:NO];
     227                if (pParams->pParentView)
     228                    [pView setHidden:NO];
     229                else
     230                    [pView setHidden:YES];
    211231
    212232                [pView restoreSavedGLContext:pSavedCtx];
     
    217237
    218238                [pFmt release];
     239
     240#if 0 // doesn't work or isn't needed :/
     241                /*
     242                 * Get notifications when we're moved...
     243                 */
     244                if (pParams->pParentView)
     245                {
     246                    [[NSNotificationCenter defaultCenter] addObserver:self
     247                                                             selector:@selector(vboxFrameDidChange)
     248                                                                 name:NSViewFrameDidChangeNotification
     249                                                               object:self];
     250                }
     251#endif
     252
    219253                LogFlow(("OvlView createViewAndContext: returns successfully\n"));
    220254                return;
     
    239273    m_Pos            = NSZeroPoint;
    240274    m_Size           = frame.size;
    241     m_RootRect       = NSMakeRect(0, 0, m_Size.width, m_Size.height);
     275    m_cClears        = 2;
     276    m_fUpdateCtx     = true;
    242277
    243278#ifdef USE_NSOPENGLVIEW
     
    248283    if (self)
    249284    {
    250         self.autoresizingMask = NSViewMinXMargin | NSViewMaxXMargin | NSViewMinYMargin | NSViewMaxYMargin;
     285        //self.autoresizingMask = NSViewMinXMargin | NSViewMaxXMargin | NSViewMinYMargin | NSViewMaxYMargin;
     286        self.autoresizingMask = NSViewNotSizable;
    251287    }
    252288    LogFlow(("OvlView(%p) initWithFrameAndFormat: returns %p\n", (void *)self, (void *)self));
     
    275311
    276312
    277 - (void)setPos:(NSPoint)pos
    278 {
    279     Log(("OvlView(%p) setPos: (%d,%d)\n", (void *)self, (int)pos.x, (int)pos.y));
     313- (void)vboxSetPos:(NSPoint)pos
     314{
     315    Log(("OvlView(%p) vboxSetPos: (%d,%d)\n", (void *)self, (int)pos.x, (int)pos.y));
    280316
    281317    m_Pos = pos;
    282318    [self vboxReshape];
    283319
    284     LogFlow(("OvlView(%p) setPos: returns\n", (void *)self));
    285 }
    286 
    287 
    288 - (void)setSize:(NSSize)size
    289 {
    290     Log(("OvlView(%p) setSize: (%d,%d):\n", (void *)self, (int)size.width, (int)size.height));
     320    LogFlow(("OvlView(%p) vboxSetPos: returns\n", (void *)self));
     321}
     322
     323
     324- (void)vboxSetSize:(NSSize)size
     325{
     326    Log(("OvlView(%p) vboxSetSize: (%d,%d):\n", (void *)self, (int)size.width, (int)size.height));
    291327    m_Size = size;
    292328    [self vboxReshape];
    293     LogFlow(("OvlView(%p) setSize: returns\n", (void *)self));
     329    LogFlow(("OvlView(%p) vboxSetSize: returns\n", (void *)self));
    294330}
    295331
     
    305341        NSOpenGLContext *pSavedCtx = [self makeCurrentGLContext];
    306342
     343        /* Clear errors. */
     344        GLenum rc;
     345        while ((rc = glGetError()) != GL_NO_ERROR)
     346            continue;
     347
     348        /* Save the old buffer setting and make it GL_BACK (shall be GL_BACK already actually). */
    307349        GLint iOldDrawBuf = GL_BACK;
    308350        glGetIntegerv(GL_DRAW_BUFFER, &iOldDrawBuf);
    309         glDrawBuffer(GL_FRONT_AND_BACK);
     351        glDrawBuffer(GL_BACK);
     352        while ((rc = glGetError()) != GL_NO_ERROR)
     353            AssertMsgFailed(("rc=%x\n", rc));
     354
     355        /* Clear the current GL_BACK. */
    310356        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    311357        glClear(GL_COLOR_BUFFER_BIT /*|GL_DEPTH_BUFFER_BIT*/ );
    312358        [[self openGLContext] flushBuffer];
     359        while ((rc = glGetError()) != GL_NO_ERROR)
     360            AssertMsgFailed(("rc=%x\n", rc));
     361
     362        /* Clear the previous GL_FRONT. */
     363        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
     364        glClear(GL_COLOR_BUFFER_BIT /*|GL_DEPTH_BUFFER_BIT*/ );
     365        [[self openGLContext] flushBuffer];
     366        while ((rc = glGetError()) != GL_NO_ERROR)
     367            AssertMsgFailed(("rc=%x\n", rc));
     368
     369        /* We're back to the orignal back buffer now. Just restore GL_DRAW_BUFFER. */
    313370        glDrawBuffer(iOldDrawBuf);
    314371
     372        while ((rc = glGetError()) != GL_NO_ERROR)
     373            AssertMsgFailed(("rc=%x\n", rc));
     374
    315375        [self restoreSavedGLContext:pSavedCtx];
    316376    }
     
    318378}
    319379
     380- (void)vboxUpdateCtxIfNecessary
     381{
     382    if (m_fUpdateCtx)
     383    {
     384        Log(("OvlView(%p) vboxUpdateCtxIfNecessary: m_fUpdateCtx\n", (void *)self));
     385        [[self openGLContext] update];
     386        m_fUpdateCtx = false;
     387    }
     388}
     389
     390
     391- (void)vboxClearBackBufferIfNecessary
     392{
     393#if 1 /* experiment */
     394    if (m_cClears > 0)
     395    {
     396        Assert(![NSThread isMainThread]);
     397        Assert([self openGLContext] == [NSOpenGLContext currentContext]);
     398        Log(("OvlView(%p) vboxClearBackBufferIfNecessary: m_cClears=%d\n", (void *)self, m_cClears));
     399        m_cClears--;
     400
     401        /* Clear errors. */
     402        GLenum rc;
     403        while ((rc = glGetError()) != GL_NO_ERROR)
     404            continue;
     405
     406        /* Save the old buffer setting and make it GL_BACK (shall be GL_BACK already actually). */
     407        GLint iOldDrawBuf = GL_BACK;
     408        glGetIntegerv(GL_DRAW_BUFFER, &iOldDrawBuf);
     409        if (iOldDrawBuf != GL_BACK)
     410            glDrawBuffer(GL_BACK);
     411        while ((rc = glGetError()) != GL_NO_ERROR)
     412            AssertMsgFailed(("rc=%x\n", rc));
     413
     414        /* Clear the current GL_BACK. */
     415        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
     416        glClear(GL_COLOR_BUFFER_BIT /*|GL_DEPTH_BUFFER_BIT*/ );
     417        while ((rc = glGetError()) != GL_NO_ERROR)
     418            AssertMsgFailed(("rc=%x\n", rc));
     419
     420        /* We're back to the orignal back buffer now. Just restore GL_DRAW_BUFFER. */
     421        if (iOldDrawBuf != GL_BACK)
     422            glDrawBuffer(iOldDrawBuf);
     423
     424        while ((rc = glGetError()) != GL_NO_ERROR)
     425            AssertMsgFailed(("rc=%x\n", rc));
     426    }
     427#endif
     428}
     429
     430
     431
     432- (void)vboxReshapePerform
     433{
     434    /*
     435     * Change the size and position if necessary.
     436     */
     437    NSRect CurFrameRect = [self frame];
     438    /** @todo conversions?   */
     439    if (   m_Pos.x != CurFrameRect.origin.x
     440        || m_Pos.y != CurFrameRect.origin.y)
     441    {
     442        LogFlow(("OvlView(%p) vboxReshapePerform: moving (%d,%d) -> (%d,%d)\n",
     443                 (void *)self,  CurFrameRect.origin.x, CurFrameRect.origin.y, m_Pos.x, m_Pos.y));
     444        [self setFrameOrigin:m_Pos];
     445    }
     446
     447    if (   CurFrameRect.size.width != m_Size.width
     448        || CurFrameRect.size.height != m_Size.height)
     449    {                   
     450        LogFlow(("OvlView(%p) vboxReshapePerform: resizing (%d,%d) -> (%d,%d)\n",
     451                 (void *)self,  CurFrameRect.size.width, CurFrameRect.size.height, m_Size.width, m_Size.height));
     452        [self setFrameSize:m_Size];
     453
     454        /*
     455         * Schedule two clears and a context update for now.
     456         * Really though, we should just clear any new surface area.
     457         */
     458        m_cClears = 2;
     459    }
     460    m_fUpdateCtx = true;
     461    LogFlow(("OvlView(%p) vboxReshapePerform: returns\n", self));
     462}
     463
    320464
    321465- (void)vboxReshape
     
    324468
    325469    /*
    326      * Not doing any complicate stuff here yet, hoping that we'll get correctly
    327      * resized when the parent view changes...
     470     * Resize the view.
    328471     */
    329 
    330     /*
    331      * Tell the GL context.
    332      */
    333     //[[self openGLContext] setView:self];
    334     [[self openGLContext] update];
    335 
    336     [self vboxClearBuffers];
     472    if ([NSThread isMainThread])
     473        [self vboxReshapePerform];
     474    else
     475    {
     476        [self performSelectorOnMainThread:@selector(vboxReshapePerform) withObject:nil waitUntilDone:NO];
     477        vmsvga3dCocoaServiceRunLoop();
     478
     479        /*
     480         * Try update the opengl context.
     481         */
     482        [[self openGLContext] update];
     483    }
    337484
    338485    LogFlow(("OvlView(%p) vboxReshape: returns\n", (void *)self));
     486}
     487
     488#if 0 // doesn't work or isn't needed :/
     489- (void)vboxFrameDidChange
     490{
     491    LogFlow(("OvlView(%p) vboxFrameDidChange:\n", (void *)self));
     492}
     493
     494- (BOOL)postsFrameChangedNotifications
     495{
     496    LogFlow(("OvlView(%p) postsFrameChangedNotifications:\n", (void *)self));
     497    return YES;
     498}
     499#endif
     500
     501/**
     502 * Removes the view from the parent, if it has one, and makes sure it's hidden.
     503 * 
     504 * This is callbed before destroying it.
     505 */
     506- (void)vboxRemoveFromSuperviewAndHide
     507{
     508    LogFlow(("OvlView(%p) vboxRemoveFromSuperviewAndHide:\n", (void *)self));
     509    if (m_pParentView)
     510    {
     511        [self removeFromSuperview];
     512        [self setHidden:YES];
     513        [[NSNotificationCenter defaultCenter] removeObserver:self];
     514    }
    339515}
    340516
     
    419595 */
    420596
     597/** @todo do we need this?  */
    421598-(void)viewDidMoveToWindow
    422599{
     
    443620- (void)drawRect:(NSRect)rect
    444621{
    445     if (m_fClear)
    446     {
    447         m_fClear = false;
    448         [self vboxClearBuffers];
    449     }
     622//    if (m_fClear)
     623//    {
     624//        m_fClear = false;
     625//        [self vboxClearBuffers];
     626//    }
    450627}
    451628
     
    470647
    471648
     649/**
     650 * Document me later.
     651 *
     652 * @param   pParentView     The parent view if this is a context we'll be
     653 *                          presenting to.
     654 */
    472655VMSVGA3DCOCOA_DECL(bool) vmsvga3dCocoaCreateViewAndContext(NativeNSViewRef *ppView, NativeNSOpenGLContextRef *ppCtx,
    473656                                                           NativeNSViewRef pParentView, uint32_t cx, uint32_t cy,
     
    513696
    514697    /* The view */
    515     [pView removeFromSuperview];
    516     [pView setHidden: YES];
     698    [(VMSVGA3DOverlayView *)pView vboxRemoveFromSuperviewAndHide];
     699
    517700    Log(("vmsvga3dCocoaDestroyViewAndContext: view %p ref count=%d\n", (void *)pView, [pView retainCount]));
    518701    [pView release];
     
    527710
    528711
     712/** @note Not currently used. */
    529713VMSVGA3DCOCOA_DECL(void) vmsvga3dCocoaViewSetPosition(NativeNSViewRef pView, NativeNSViewRef pParentView, int x, int y)
    530714{
     
    532716    NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
    533717
    534     [(VMSVGA3DOverlayView *)pView setPos:NSMakePoint(x, y)];
     718    [(VMSVGA3DOverlayView *)pView vboxSetPos:NSMakePoint(x, y)];
    535719
    536720    [pPool release];
     
    545729    VMSVGA3DOverlayView *pOverlayView = (VMSVGA3DOverlayView *)pView;
    546730
    547     [pOverlayView setSize:NSMakeSize(cx, cy)];
     731    [pOverlayView vboxSetSize:NSMakeSize(cx, cy)];
    548732
    549733    [pPool release];
     
    554738void vmsvga3dCocoaViewMakeCurrentContext(NativeNSViewRef pView, NativeNSOpenGLContextRef pCtx)
    555739{
    556     LogFlow(("vmsvga3dCocoaViewSetSize: pView=%p, pCtx=%p\n", (void*)pView, (void*)pCtx));
     740    LogFlow(("vmsvga3dCocoaViewMakeCurrentContext: pView=%p, pCtx=%p\n", (void*)pView, (void*)pCtx));
    557741    NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
    558742    VMSVGA3DOverlayView *pOverlayView = (VMSVGA3DOverlayView *)pView;
     
    569753        AssertRelease([pOverlayView openGLContext] == pCtx);
    570754        [pCtx makeCurrentContext];
     755        [pOverlayView vboxUpdateCtxIfNecessary];
    571756    }
    572757    else
     
    582767    LogFlow(("vmsvga3dCocoaSwapBuffers: pView=%p, pCtx=%p\n", (void*)pView, (void*)pCtx));
    583768    NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
     769    VMSVGA3DOverlayView *pMyView = (VMSVGA3DOverlayView *)pView;
    584770
    585771#ifndef USE_NSOPENGLVIEW
    586772    /* Hack alert! setView fails early on so call openGLContext to try again. */
    587     VMSVGA3DOverlayView *pMyView = (VMSVGA3DOverlayView *)pView;
    588773    if ([pCtx view] == NULL)
    589774        [pMyView openGLContext];
    590 #elif defined(RT_STRICT)
    591     NSOpenGLView *pMyView = (NSOpenGLView *)pView;
    592775#endif
    593776
     
    600783    vmsvga3dCocoaServiceRunLoop();
    601784
     785    /* If buffer clearing or/and context updates are pending, execute that now. */
     786    [pMyView vboxUpdateCtxIfNecessary];
     787    [pMyView vboxClearBackBufferIfNecessary];
     788
    602789    [pPool release];
    603790    LogFlow(("vmsvga3dCocoaSwapBuffers: returns\n"));
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