VirtualBox

Ignore:
Timestamp:
Oct 17, 2013 6:17:16 PM (11 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
90040
Message:

FE/Qt: Runtime UI: Reworking frame-buffer synchronization logic.

Location:
trunk/src/VBox/Frontends/VirtualBox/src/runtime
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIFrameBuffer.cpp

    r48705 r49167  
    11/* $Id$ */
    22/** @file
    3  *
    4  * VBox frontends: Qt GUI ("VirtualBox"):
    5  * UIFrameBuffer class and subclasses implementation
     3 * VBox Qt GUI - UIFrameBuffer class implementation.
    64 */
    75
     
    4644    : m_pMachineView(pMachineView)
    4745    , m_width(0), m_height(0)
    48     , m_fIsScheduledToDelete(false)
     46    , m_fIsMarkedAsUnused(false)
    4947#ifdef Q_OS_WIN
    5048    , m_iRefCnt(0)
     
    5250{
    5351    /* Assign mahine-view: */
    54     AssertMsg(m_pMachineView, ("UIMachineView must not be null\n"));
     52    AssertMsg(m_pMachineView, ("UIMachineView must not be NULL\n"));
    5553    m_WinId = (m_pMachineView && m_pMachineView->viewport()) ? (LONG64)m_pMachineView->viewport()->winId() : 0;
     54
     55    /* Initialize critical-section: */
     56    int rc = RTCritSectInit(&m_critSect);
     57    AssertRC(rc);
    5658
    5759    /* Connect handlers: */
    5860    if (m_pMachineView)
    5961        prepareConnections();
    60 
    61     /* Initialize critical-section: */
    62     int rc = RTCritSectInit(&m_critSect);
    63     AssertRC(rc);
    6462}
    6563
    6664UIFrameBuffer::~UIFrameBuffer()
    6765{
    68     /* Deinitialize critical-section: */
    69     RTCritSectDelete(&m_critSect);
    70 
    7166    /* Disconnect handlers: */
    7267    if (m_pMachineView)
    7368        cleanupConnections();
     69
     70    /* Deinitialize critical-section: */
     71    RTCritSectDelete(&m_critSect);
     72}
     73
     74/**
     75 * Checks if the framebuffer marked as <b>unused</b>.
     76 * @returns @c true if framebuffer ingores EMT events, @c false otherwise.
     77 * @note    Any call to this (and #setMarkAsUnused method) is synchronized between calling threads.
     78 */
     79bool UIFrameBuffer::isMarkedAsUnused() const
     80{
     81    lock();
     82    bool fIsMarkedAsUnused = m_fIsMarkedAsUnused;
     83    unlock();
     84    return fIsMarkedAsUnused;
     85}
     86
     87/**
     88 * Sets the framebuffer <b>unused</b> status.
     89 * @param fIsMarkAsUnused determines whether framebuffer should ignore EMT events or not.
     90 * @note  Any call to this (and #isMarkedAsUnused method) is synchronized between calling threads.
     91 */
     92void UIFrameBuffer::setMarkAsUnused(bool fIsMarkAsUnused)
     93{
     94    lock();
     95    m_fIsMarkedAsUnused = fIsMarkAsUnused;
     96    unlock();
    7497}
    7598
     
    180203                (unsigned long)uWidth, (unsigned long)uHeight));
    181204
    182     /* Make sure frame-buffer is not yet scheduled for removal: */
    183     if (m_fIsScheduledToDelete)
     205    /* Make sure result pointer is valid: */
     206    if (!pbFinished)
     207        return E_POINTER;
     208
     209    /* Make sure frame-buffer is used: */
     210    if (isMarkedAsUnused())
     211    {
     212        LogRelFlow(("UIFrameBuffer::RequestResize: Ignored!\n"));
     213
     214        /* Mark request as finished.
     215         * It is required to report to the VM thread that we finished resizing and rely on the
     216         * later synchronisation when the new view is attached. */
     217        *pbFinished = TRUE;
     218
     219        /* Ignore RequestResize: */
    184220        return E_FAIL;
    185 
    186     /* Currently screen ID is not used: */
    187     Q_UNUSED(uScreenId);
     221    }
    188222
    189223    /* Mark request as not-yet-finished: */
    190224    *pbFinished = FALSE;
    191225
    192     /* See comment in setView(): */
    193     lock();
    194 
    195     /* Widget resize is NOT thread safe and never will be,
    196      * We have to notify the machine-view with the async signal to perform resize operation. */
    197     if (m_pMachineView)
    198         emit sigRequestResize(uPixelFormat, pVRAM, uBitsPerPixel, uBytesPerLine, uWidth, uHeight);
    199     else
    200         /* Mark request as finished.
    201          * It is required to report to the VM thread that we finished resizing and rely on the
    202          * synchronisation when the new view is attached. */
    203         *pbFinished = TRUE;
    204 
    205     /* Unlock thread finally: */
    206     unlock();
     226    /* Widget resize is NOT thread-safe and *probably* never will be,
     227     * We have to notify machine-view with the async-signal to perform resize operation. */
     228    LogRelFlow(("UIFrameBuffer::RequestResize: Sending to async-handler...\n"));
     229    emit sigRequestResize(uPixelFormat, pVRAM, uBitsPerPixel, uBytesPerLine, uWidth, uHeight);
    207230
    208231    /* Confirm RequestResize: */
     
    212235STDMETHODIMP UIFrameBuffer::NotifyUpdate(ULONG uX, ULONG uY, ULONG uWidth, ULONG uHeight)
    213236{
    214     LogRelFlow(("UIFrameBuffer::NotifyUpdate: Origin=%lux%lu, Size=%lux%lu\n",
    215                 (unsigned long)uX, (unsigned long)uY,
    216                 (unsigned long)uWidth, (unsigned long)uHeight));
    217 
    218     /* Make sure frame-buffer is not yet scheduled for removal: */
    219     if (m_fIsScheduledToDelete)
     237    LogRel2(("UIFrameBuffer::NotifyUpdate: Origin=%lux%lu, Size=%lux%lu\n",
     238             (unsigned long)uX, (unsigned long)uY,
     239             (unsigned long)uWidth, (unsigned long)uHeight));
     240
     241    /* Make sure frame-buffer is used: */
     242    if (isMarkedAsUnused())
     243    {
     244        LogRel2(("UIFrameBuffer::NotifyUpdate: Ignored!\n"));
     245
     246        /* Ignore NotifyUpdate: */
    220247        return E_FAIL;
    221 
    222     /* See comment in setView(): */
    223     lock();
    224 
    225     /* QWidget::update() is NOT thread safe and seems never will be,
    226      * So we have to notify the machine-view with the async signal to perform update operation. */
    227     if (m_pMachineView)
    228         emit sigNotifyUpdate(uX, uY, uWidth, uHeight);
    229 
    230     /* Unlock thread finally: */
    231     unlock();
     248    }
     249
     250    /* Widget update is NOT thread-safe and *seems* never will be,
     251     * We have to notify machine-view with the async-signal to perform update operation. */
     252    LogRel2(("UIFrameBuffer::NotifyUpdate: Sending to async-handler...\n"));
     253    emit sigNotifyUpdate(uX, uY, uWidth, uHeight);
    232254
    233255    /* Confirm NotifyUpdate: */
     
    237259STDMETHODIMP UIFrameBuffer::VideoModeSupported(ULONG uWidth, ULONG uHeight, ULONG uBPP, BOOL *pbSupported)
    238260{
    239     LogRelFlow(("UIFrameBuffer::VideoModeSupported: Mode: BPP=%lu, Size=%lux%lu\n",
    240                 (unsigned long)uBPP, (unsigned long)uWidth, (unsigned long)uHeight));
    241 
    242     /* Make sure frame-buffer is not yet scheduled for removal: */
    243     if (m_fIsScheduledToDelete)
     261    LogRel2(("UIFrameBuffer::IsVideoModeSupported: Mode: BPP=%lu, Size=%lux%lu\n",
     262             (unsigned long)uBPP, (unsigned long)uWidth, (unsigned long)uHeight));
     263
     264    /* Make sure frame-buffer is used: */
     265    if (isMarkedAsUnused())
     266    {
     267        LogRel2(("UIFrameBuffer::IsVideoModeSupported: Ignored!\n"));
     268
     269        /* Ignore VideoModeSupported: */
    244270        return E_FAIL;
    245 
     271    }
     272
     273    /* Make sure result pointer is valid: */
    246274    if (!pbSupported)
    247275        return E_POINTER;
     276
     277    /* Determine if supported: */
    248278    *pbSupported = TRUE;
    249 
    250     /* Currently BPP is not used: */
    251     Q_UNUSED(uBPP);
    252 
    253     /* See comment in setView(): */
    254     lock();
    255 
    256     QSize screenSize;
    257     if (m_pMachineView)
    258         screenSize = m_pMachineView->maxGuestSize();
    259 
    260     /* Unlock thread finally: */
    261     unlock();
    262 
     279    QSize screenSize = m_pMachineView->maxGuestSize();
    263280    if (   (screenSize.width() != 0)
    264281        && (uWidth > (ULONG)screenSize.width())
    265282        && (uWidth > (ULONG)width()))
    266283        *pbSupported = FALSE;
    267 
    268284    if (   (screenSize.height() != 0)
    269285        && (uHeight > (ULONG)screenSize.height())
     
    271287        *pbSupported = FALSE;
    272288
    273     LogRelFlow(("UIFrameBuffer::VideoModeSupported: Verdict: Supported=%s\n",
    274                 *pbSupported ? "TRUE" : "FALSE"));
     289    LogRel2(("UIFrameBuffer::IsVideoModeSupported: %s\n", *pbSupported ? "TRUE" : "FALSE"));
    275290
    276291    /* Confirm VideoModeSupported: */
     
    293308STDMETHODIMP UIFrameBuffer::SetVisibleRegion(BYTE *pRectangles, ULONG uCount)
    294309{
    295     LogRelFlow(("UIFrameBuffer::SetVisibleRegion: Rectangle count=%lu\n", (unsigned long)uCount));
    296 
    297     /* Make sure frame-buffer is not yet scheduled for removal: */
    298     if (m_fIsScheduledToDelete)
     310    LogRel2(("UIFrameBuffer::SetVisibleRegion: Rectangle count=%lu\n",
     311             (unsigned long)uCount));
     312
     313    /* Make sure frame-buffer is used: */
     314    if (isMarkedAsUnused())
     315    {
     316        LogRel2(("UIFrameBuffer::SetVisibleRegion: Ignored!\n"));
     317
     318        /* Ignore SetVisibleRegion: */
    299319        return E_FAIL;
     320    }
    300321
    301322    /* Make sure rectangles were passed: */
     
    320341    }
    321342
    322     /* See comment in setView(): */
    323     lock();
    324 
    325343    /* We are directly updating synchronous visible-region: */
    326344    m_syncVisibleRegion = region;
    327     /* And send async signal to update asynchronous one: */
    328     if (m_pMachineView)
    329         emit sigSetVisibleRegion(region);
    330 
    331     /* Unlock thread finally: */
    332     unlock();
     345    /* And send async-signal to update asynchronous one: */
     346    LogRel2(("UIFrameBuffer::SetVisibleRegion: Sending to async-handler...\n"));
     347    emit sigSetVisibleRegion(region);
    333348
    334349    /* Confirm SetVisibleRegion: */
     
    344359STDMETHODIMP UIFrameBuffer::Notify3DEvent(ULONG uType, BYTE *pData)
    345360{
     361    LogRel2(("UIFrameBuffer::Notify3DEvent\n"));
     362
     363    /* Make sure frame-buffer is used: */
     364    if (isMarkedAsUnused())
     365    {
     366        LogRel2(("UIFrameBuffer::Notify3DEvent: Ignored!\n"));
     367
     368        /* Ignore Notify3DEvent: */
     369        return E_FAIL;
     370    }
     371
    346372    switch (uType)
    347373    {
    348374        case VBOX3D_NOTIFY_EVENT_TYPE_VISIBLE_3DDATA:
    349375        {
    350             /* Notify GUI about 3D overlay visibility change: */
     376            /* Notify machine-view with the async-signal
     377             * about 3D overlay visibility change: */
    351378            BOOL fVisible = !!pData;
    352             LogRelFlow(("UIFrameBuffer::Notify3DEvent: "
    353                         "VBOX3D_NOTIFY_EVENT_TYPE_VISIBLE_3DDATA=%s\n",
    354                         fVisible ? "TRUE" : "FALSE"));
     379            LogRel2(("UIFrameBuffer::Notify3DEvent: Sending to async-handler: "
     380                     "(VBOX3D_NOTIFY_EVENT_TYPE_VISIBLE_3DDATA = %s)\n",
     381                     fVisible ? "TRUE" : "FALSE"));
    355382            emit sigNotifyAbout3DOverlayVisibilityChange(fVisible);
     383
     384            /* Confirm Notify3DEvent: */
    356385            return S_OK;
    357386        }
    358387        default:
    359             return E_INVALIDARG;
    360     }
     388            break;
     389    }
     390
     391    /* Ignore Notify3DEvent: */
     392    return E_INVALIDARG;
    361393}
    362394
     
    392424void UIFrameBuffer::setView(UIMachineView * pView)
    393425{
    394     /* We are not supposed to use locking for things which are done
    395      * on the GUI thread.  Unfortunately I am not clever enough to
    396      * understand the original author's wise synchronisation logic
    397      * so I will do it anyway. */
    398     lock();
    399 
    400426    /* Disconnect handlers: */
    401427    if (m_pMachineView)
     
    409435    if (m_pMachineView)
    410436        prepareConnections();
    411 
    412     /* Unlock thread finally: */
    413     unlock();
    414437}
    415438
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIFrameBuffer.h

    r47493 r49167  
    11/** @file
    2  *
    3  * VBox frontends: Qt GUI ("VirtualBox"):
    4  * UIFrameBuffer class and subclasses declarations
     2 * VBox Qt GUI - UIFrameBuffer class declaration.
    53 */
    64
     
    106104    virtual ~UIFrameBuffer();
    107105
    108     void setScheduledToDelete(bool fIsScheduledToDelete) { m_fIsScheduledToDelete = fIsScheduledToDelete; }
     106    /* API: [Un]used status stuff: */
     107    bool isMarkedAsUnused() const;
     108    void setMarkAsUnused(bool fIsMarkAsUnused);
    109109
    110110    NS_DECL_ISUPPORTS
     
    180180    }
    181181
    182     void lock() { RTCritSectEnter(&m_critSect); }
    183     void unlock() { RTCritSectLeave(&m_critSect); }
     182    void lock() const { RTCritSectEnter(&m_critSect); }
     183    void unlock() const { RTCritSectLeave(&m_critSect); }
    184184
    185185    virtual uchar *address() = 0;
     
    209209
    210210    UIMachineView *m_pMachineView;
    211     RTCRITSECT m_critSect;
     211    mutable RTCRITSECT m_critSect;
    212212    ulong m_width;
    213213    ulong m_height;
    214214    QSize m_scaledSize;
    215215    int64_t m_WinId;
    216     bool m_fIsScheduledToDelete;
     216    bool m_fIsMarkedAsUnused;
    217217
    218218    /* To avoid a seamless flicker,
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.cpp

    r49008 r49167  
    284284    /* Emit a signal about guest was resized: */
    285285    emit resizeHintDone();
     286
     287    LogRelFlow(("UIMachineView::ResizeHandled: "
     288                "Screen=%d, Format=%d, "
     289                "BitsPerPixel=%d, BytesPerLine=%d, "
     290                "Size=%dx%d.\n\n",
     291                (unsigned long)m_uScreenId, iPixelFormat,
     292                iBitsPerPixel, iBytesPerLine, iWidth, iHeight));
    286293}
    287294
     
    412419        case QImageMode:
    413420        {
    414             UIFrameBuffer* pFrameBuffer = uisession()->frameBuffer(screenId());
     421            UIFrameBuffer *pFrameBuffer = uisession()->frameBuffer(screenId());
    415422            if (pFrameBuffer)
     423            {
    416424                pFrameBuffer->setView(this);
     425                /* Mark framebuffer as used again: */
     426                LogRelFlow(("UIMachineView::prepareFrameBuffer: Start EMT callbacks accepting for screen: %d.\n", screenId()));
     427                pFrameBuffer->setMarkAsUnused(false);
     428            }
    417429            else
    418430            {
     
    442454            /* Indicate that we are doing all drawing stuff ourself: */
    443455            viewport()->setAttribute(Qt::WA_PaintOnScreen);
    444             UIFrameBuffer* pFrameBuffer = uisession()->frameBuffer(screenId());
     456            UIFrameBuffer *pFrameBuffer = uisession()->frameBuffer(screenId());
    445457            if (pFrameBuffer)
     458            {
    446459                pFrameBuffer->setView(this);
     460                /* Mark framebuffer as used again: */
     461                LogRelFlow(("UIMachineView::prepareFrameBuffer: Start EMT callbacks accepting for screen: %d.\n", screenId()));
     462                pFrameBuffer->setMarkAsUnused(false);
     463            }
    447464            else
    448465            {
     
    595612void UIMachineView::cleanupFrameBuffer()
    596613{
    597     if (m_pFrameBuffer)
    598     {
    599         /* Process pending frame-buffer resize events: */
    600         QApplication::sendPostedEvents(this, ResizeEventType);
    601         if (   0
    602 #ifdef VBOX_GUI_USE_QIMAGE
    603             || vboxGlobal().vmRenderMode() == QImageMode
    604 #endif /* VBOX_GUI_USE_QIMAGE */
    605 #ifdef VBOX_GUI_USE_QUARTZ2D
    606             || vboxGlobal().vmRenderMode() == Quartz2DMode
    607 #endif /* VBOX_GUI_USE_QUARTZ2D */
    608 #ifdef VBOX_WITH_VIDEOHWACCEL
    609             || m_fAccelerate2DVideo
    610 #endif /* VBOX_WITH_VIDEOHWACCEL */
    611            )
    612         {
    613             Assert(m_pFrameBuffer == uisession()->frameBuffer(screenId()));
    614             CDisplay display = session().GetConsole().GetDisplay();
    615             /* Temporarily remove the framebuffer in Display while unsetting
    616              * the view in order to respect the thread synchonisation logic
    617              * (see UIFrameBuffer.h). */
    618             /* Note! VBOX_WITH_CROGL additionally requires us to call
    619              * SetFramebuffer to ensure 3D gets notified of view being
    620              * destroyed */
    621             display.SetFramebuffer(m_uScreenId, CFramebuffer(NULL));
    622             m_pFrameBuffer->setView(NULL);
    623             display.SetFramebuffer(m_uScreenId, CFramebuffer(m_pFrameBuffer));
    624         }
    625         else
    626         {
    627             /* Warn framebuffer about its no more necessary: */
    628             m_pFrameBuffer->setScheduledToDelete(true);
    629             /* Detach framebuffer from Display: */
    630             CDisplay display = session().GetConsole().GetDisplay();
    631             display.SetFramebuffer(m_uScreenId, CFramebuffer(NULL));
    632             /* Release the reference: */
    633             m_pFrameBuffer->Release();
    634 //          delete m_pFrameBuffer; // TODO_NEW_CORE: possibly necessary to really cleanup
    635             m_pFrameBuffer = NULL;
    636         }
    637     }
     614    /* Make sure proper framebuffer assigned: */
     615    AssertReturnVoid(m_pFrameBuffer);
     616    AssertReturnVoid(m_pFrameBuffer == uisession()->frameBuffer(screenId()));
     617
     618    /* Mark framebuffer as unused: */
     619    LogRelFlow(("UIMachineView::cleanupFrameBuffer: Stop EMT callbacks accepting for screen: %d.\n", screenId()));
     620    m_pFrameBuffer->setMarkAsUnused(true);
     621
     622    /* Process pending framebuffer events: */
     623    QApplication::sendPostedEvents(this, QEvent::MetaCall);
     624
     625    /* Temporarily detach the framebuffer from IDisplay before detaching
     626     * from view in order to respect the thread synchonisation logic (see UIFrameBuffer.h).
     627     * Note: VBOX_WITH_CROGL additionally requires us to call SetFramebuffer
     628     * to ensure 3D gets notified of view being destroyed... */
     629    CDisplay display = session().GetConsole().GetDisplay();
     630    display.SetFramebuffer(m_uScreenId, CFramebuffer(NULL));
     631
     632    /* Detach framebuffer from view: */
     633    m_pFrameBuffer->setView(NULL);
     634
     635    /* Attach frambuffer back to IDisplay: */
     636    display.SetFramebuffer(m_uScreenId, CFramebuffer(m_pFrameBuffer));
    638637}
    639638
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UISession.cpp

    r49121 r49167  
    11501150        if (pFb)
    11511151        {
    1152             /* Warn framebuffer about its no more necessary: */
    1153             pFb->setScheduledToDelete(true);
     1152            /* Mark framebuffer as unused: */
     1153            pFb->setMarkAsUnused(true);
    11541154            /* Detach framebuffer from Display: */
    11551155            CDisplay display = session().GetConsole().GetDisplay();
    11561156            display.SetFramebuffer(i, CFramebuffer(NULL));
    1157             /* Release the reference: */
     1157            /* Release framebuffer reference: */
    11581158            pFb->Release();
    11591159        }
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