VirtualBox

Changeset 51487 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Jun 2, 2014 2:15:35 PM (11 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
94096
Message:

FE/Qt: Runtime UI: Large frame-buffer cleanup; preparing for QImage frame-buffer consumption.

Location:
trunk/src/VBox/Frontends/VirtualBox/src
Files:
6 edited

Legend:

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

    r51401 r51487  
    44004400{
    44014401    /* we do not to miss notify updates, because we have to update bg textures for it,
    4402      * so no not check for m_fIsMarkedAsUnused here,
     4402     * so no not check for m_fUnused here,
    44034403     * mOverlay will store the required info for us */
    44044404    QRect r(aX, aY, aW, aH);
  • trunk/src/VBox/Frontends/VirtualBox/src/VBoxFBOverlay.h

    r51459 r51487  
    18391839        T::lock();
    18401840        /* Make sure frame-buffer is used: */
    1841         if (T::m_fIsMarkedAsUnused)
     1841        if (T::m_fUnused)
    18421842        {
    18431843            LogRel2(("ProcessVHWACommand: Postponed!\n"));
     
    18691869        T::lock();
    18701870        /* Make sure frame-buffer is used: */
    1871         if (T::m_fIsMarkedAsUnused)
     1871        if (T::m_fUnused)
    18721872        {
    18731873            LogRel2(("NotifyUpdate: Ignored!\n"));
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIFrameBuffer.cpp

    r51459 r51487  
    55
    66/*
    7  * Copyright (C) 2010-2013 Oracle Corporation
     7 * Copyright (C) 2010-2014 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    1919# include "precomp.h"
    2020#else  /* !VBOX_WITH_PRECOMPILED_HEADERS */
    21 
    2221/* GUI includes: */
     22# include "UIFrameBuffer.h"
    2323# include "UIMachineView.h"
    24 # include "UIFrameBuffer.h"
    2524# include "UIMessageCenter.h"
    2625# include "VBoxGlobal.h"
     
    2827#  include "UIMachineWindow.h"
    2928# endif /* !VBOX_WITH_TRANSLUCENT_SEAMLESS */
    30 
     29/* COM includes: */
     30#include "CConsole.h"
     31#include "CDisplay.h"
    3132/* Other VBox includes: */
    3233# include <VBox/VBoxVideo3D.h>
    33 
    3434#endif /* !VBOX_WITH_PRECOMPILED_HEADERS */
    3535
    36 #include "CConsole.h"
    37 #include "CDisplay.h"
    38 
    39 #if defined (Q_OS_WIN32)
     36/* COM stuff: */
     37#ifdef Q_WS_WIN
    4038static CComModule _Module;
    41 #else
    42 NS_DECL_CLASSINFO (UIFrameBuffer)
    43 NS_IMPL_THREADSAFE_ISUPPORTS1_CI (UIFrameBuffer, IFramebuffer)
    44 #endif
     39#else /* !Q_WS_WIN */
     40NS_DECL_CLASSINFO(UIFrameBuffer)
     41NS_IMPL_THREADSAFE_ISUPPORTS1_CI(UIFrameBuffer, IFramebuffer)
     42#endif /* !Q_WS_WIN */
    4543
    4644UIFrameBuffer::UIFrameBuffer(UIMachineView *pMachineView)
    4745    : m_pMachineView(pMachineView)
    4846    , m_width(0), m_height(0)
    49     , m_fIsMarkedAsUnused(false)
    50     , m_fIsAutoEnabled(false)
     47    , m_fUnused(false)
     48    , m_fAutoEnabled(false)
    5149    , m_fIsUpdatesAllowed(true)
    5250#ifdef Q_OS_WIN
     
    5856    /* Assign mahine-view: */
    5957    AssertMsg(m_pMachineView, ("UIMachineView must not be NULL\n"));
    60     m_WinId = (m_pMachineView && m_pMachineView->viewport()) ? (LONG64)m_pMachineView->viewport()->winId() : 0;
     58    /* Cache window ID: */
     59    m_winId = (m_pMachineView && m_pMachineView->viewport()) ? (LONG64)m_pMachineView->viewport()->winId() : 0;
    6160
    6261    /* Initialize critical-section: */
     
    7978}
    8079
    81 /**
    82  * Sets the framebuffer <b>unused</b> status.
    83  * @param fIsMarkAsUnused determines whether framebuffer should ignore EMT events or not.
    84  * @note  Call to this (and any EMT callback) method is synchronized between calling threads (from GUI side).
    85  */
    86 void UIFrameBuffer::setMarkAsUnused(bool fIsMarkAsUnused)
    87 {
    88     lock();
    89     m_fIsMarkedAsUnused = fIsMarkAsUnused;
    90     unlock();
    91 }
    92 
    93 /**
    94  * Returns the framebuffer <b>auto-enabled</b> status.
    95  * @returns @c true if guest-screen corresponding to this framebuffer was automatically enabled by
    96             the auto-mount guest-screen auto-pilot, @c false otherwise.
    97  * @note    <i>Auto-enabled</i> status means the framebuffer was automatically enabled by the multi-screen layout
    98  *          and so have potentially incorrect guest size hint posted into guest event queue. Machine-view will try to
    99  *          automatically adjust guest-screen size as soon as possible.
    100  */
    101 bool UIFrameBuffer::isAutoEnabled() const
    102 {
    103     return m_fIsAutoEnabled;
    104 }
    105 
    106 /**
    107  * Sets the framebuffer <b>auto-enabled</b> status.
    108  * @param fIsAutoEnabled determines whether guest-screen corresponding to this framebuffer
    109  *        was automatically enabled by the auto-mount guest-screen auto-pilot.
    110  * @note  <i>Auto-enabled</i> status means the framebuffer was automatically enabled by the multi-screen layout
    111  *        and so have potentially incorrect guest size hint posted into guest event queue. Machine-view will try to
    112  *        automatically adjust guest-screen size as soon as possible.
    113  */
    114 void UIFrameBuffer::setAutoEnabled(bool fIsAutoEnabled)
    115 {
    116     m_fIsAutoEnabled = fIsAutoEnabled;
    117 }
    118 
    119 STDMETHODIMP UIFrameBuffer::COMGETTER(Address) (BYTE **ppAddress)
     80void UIFrameBuffer::setView(UIMachineView *pMachineView)
     81{
     82    /* Disconnect old handlers: */
     83    if (m_pMachineView)
     84        cleanupConnections();
     85
     86    /* Reassign machine-view: */
     87    m_pMachineView = pMachineView;
     88    /* Recache window ID: */
     89    m_winId = (m_pMachineView && m_pMachineView->viewport()) ? (LONG64)m_pMachineView->viewport()->winId() : 0;
     90
     91    /* Connect new handlers: */
     92    if (m_pMachineView)
     93        prepareConnections();
     94}
     95
     96void UIFrameBuffer::setMarkAsUnused(bool fUnused)
     97{
     98    lock();
     99    m_fUnused = fUnused;
     100    unlock();
     101}
     102
     103STDMETHODIMP UIFrameBuffer::COMGETTER(Address)(BYTE **ppAddress)
    120104{
    121105    if (!ppAddress)
     
    125109}
    126110
    127 STDMETHODIMP UIFrameBuffer::COMGETTER(Width) (ULONG *puWidth)
     111STDMETHODIMP UIFrameBuffer::COMGETTER(Width)(ULONG *puWidth)
    128112{
    129113    if (!puWidth)
     
    133117}
    134118
    135 STDMETHODIMP UIFrameBuffer::COMGETTER(Height) (ULONG *puHeight)
     119STDMETHODIMP UIFrameBuffer::COMGETTER(Height)(ULONG *puHeight)
    136120{
    137121    if (!puHeight)
     
    141125}
    142126
    143 STDMETHODIMP UIFrameBuffer::COMGETTER(BitsPerPixel) (ULONG *puBitsPerPixel)
     127STDMETHODIMP UIFrameBuffer::COMGETTER(BitsPerPixel)(ULONG *puBitsPerPixel)
    144128{
    145129    if (!puBitsPerPixel)
     
    149133}
    150134
    151 STDMETHODIMP UIFrameBuffer::COMGETTER(BytesPerLine) (ULONG *puBytesPerLine)
     135STDMETHODIMP UIFrameBuffer::COMGETTER(BytesPerLine)(ULONG *puBytesPerLine)
    152136{
    153137    if (!puBytesPerLine)
     
    157141}
    158142
    159 STDMETHODIMP UIFrameBuffer::COMGETTER(PixelFormat) (ULONG *puPixelFormat)
     143STDMETHODIMP UIFrameBuffer::COMGETTER(PixelFormat)(ULONG *puPixelFormat)
    160144{
    161145    if (!puPixelFormat)
     
    165149}
    166150
    167 STDMETHODIMP UIFrameBuffer::COMGETTER(UsesGuestVRAM) (BOOL *pbUsesGuestVRAM)
     151STDMETHODIMP UIFrameBuffer::COMGETTER(UsesGuestVRAM)(BOOL *pbUsesGuestVRAM)
    168152{
    169153    if (!pbUsesGuestVRAM)
     
    173157}
    174158
    175 STDMETHODIMP UIFrameBuffer::COMGETTER(HeightReduction) (ULONG *puHeightReduction)
     159STDMETHODIMP UIFrameBuffer::COMGETTER(HeightReduction)(ULONG *puHeightReduction)
    176160{
    177161    if (!puHeightReduction)
     
    181165}
    182166
    183 STDMETHODIMP UIFrameBuffer::COMGETTER(Overlay) (IFramebufferOverlay **ppOverlay)
     167STDMETHODIMP UIFrameBuffer::COMGETTER(Overlay)(IFramebufferOverlay **ppOverlay)
    184168{
    185169    if (!ppOverlay)
    186170        return E_POINTER;
    187     /* not yet implemented */
    188171    *ppOverlay = 0;
    189172    return S_OK;
    190173}
    191174
    192 STDMETHODIMP UIFrameBuffer::COMGETTER(WinId) (LONG64 *pWinId)
     175STDMETHODIMP UIFrameBuffer::COMGETTER(WinId)(LONG64 *pWinId)
    193176{
    194177    if (!pWinId)
    195178        return E_POINTER;
    196     *pWinId = m_WinId;
     179    *pWinId = m_winId;
    197180    return S_OK;
    198181}
     
    210193}
    211194
    212 /**
    213  * EMT callback: Requests a size and pixel format change.
    214  * @param uScreenId     Guest screen number. Must be used in the corresponding call to CDisplay::ResizeCompleted if this call is made.
    215  * @param uPixelFormat  Pixel format of the memory buffer pointed to by @a pVRAM.
    216  * @param pVRAM         Pointer to the virtual video card's VRAM (may be <i>null</i>).
    217  * @param uBitsPerPixel Color depth, bits per pixel.
    218  * @param uBytesPerLine Size of one scan line, in bytes.
    219  * @param uWidth        Width of the guest display, in pixels.
    220  * @param uHeight       Height of the guest display, in pixels.
    221  * @param pfFinished    Can the VM start using the new frame buffer immediately after this method returns or it should wait for CDisplay::ResizeCompleted.
    222  * @note  Any EMT callback is subsequent. No any other EMT callback can be called until this one processed.
    223  * @note  Calls to this and #setMarkAsUnused method are synchronized between calling threads (from GUI side).
    224  */
    225 STDMETHODIMP UIFrameBuffer::RequestResize(ULONG uScreenId, ULONG uPixelFormat,
    226                                           BYTE *pVRAM, ULONG uBitsPerPixel, ULONG uBytesPerLine,
    227                                           ULONG uWidth, ULONG uHeight,
    228                                           BOOL *pfFinished)
    229 {
    230     /* Make sure result pointer is valid: */
    231     if (!pfFinished)
    232     {
    233         LogRel(("UIFrameBuffer::RequestResize: "
    234                 "Screen=%lu, Format=%lu, "
    235                 "BitsPerPixel=%lu, BytesPerLine=%lu, "
    236                 "Size=%lux%lu, Invalid pfFinished pointer!\n",
    237                 (unsigned long)uScreenId, (unsigned long)uPixelFormat,
    238                 (unsigned long)uBitsPerPixel, (unsigned long)uBytesPerLine,
     195STDMETHODIMP UIFrameBuffer::NotifyChange(ULONG uScreenId, ULONG uX, ULONG uY, ULONG uWidth, ULONG uHeight)
     196{
     197    /* Lock access to frame-buffer: */
     198    lock();
     199
     200    /* Make sure frame-buffer is used: */
     201    if (m_fUnused)
     202    {
     203        LogRel(("UIFrameBuffer::NotifyChange: Screen=%lu, Origin=%lux%lu, Size=%lux%lu, Ignored!\n",
     204                (unsigned long)uScreenId,
     205                (unsigned long)uX, (unsigned long)uY,
    239206                (unsigned long)uWidth, (unsigned long)uHeight));
    240 
    241         return E_POINTER;
    242     }
    243 
    244     /* Lock access to frame-buffer: */
    245     lock();
    246 
    247     /* Make sure frame-buffer is used: */
    248     if (m_fIsMarkedAsUnused)
    249     {
    250         LogRel(("UIFrameBuffer::RequestResize: "
    251                 "Screen=%lu, Format=%lu, "
    252                 "BitsPerPixel=%lu, BytesPerLine=%lu, "
    253                 "Size=%lux%lu, Ignored!\n",
    254                 (unsigned long)uScreenId, (unsigned long)uPixelFormat,
    255                 (unsigned long)uBitsPerPixel, (unsigned long)uBytesPerLine,
    256                 (unsigned long)uWidth, (unsigned long)uHeight));
    257 
    258         /* Mark request as finished.
    259          * It is required to report to the VM thread that we finished resizing and rely on the
    260          * later synchronisation when the new view is attached. */
    261         *pfFinished = TRUE;
    262207
    263208        /* Unlock access to frame-buffer: */
    264209        unlock();
    265210
    266         /* Ignore RequestResize: */
     211        /* Ignore NotifyChange: */
    267212        return E_FAIL;
    268213    }
    269214
    270     /* Mark request as not-yet-finished: */
    271     *pfFinished = FALSE;
     215    /* Acquire new pending bitmap: */
     216    m_pendingSourceBitmap = 0;
     217    m_pMachineView->session().GetConsole().GetDisplay().QuerySourceBitmap(uScreenId, m_pendingSourceBitmap);
    272218
    273219    /* Widget resize is NOT thread-safe and *probably* never will be,
    274220     * We have to notify machine-view with the async-signal to perform resize operation. */
    275     LogRel(("UIFrameBuffer::RequestResize: "
    276             "Screen=%lu, Format=%lu, "
    277             "BitsPerPixel=%lu, BytesPerLine=%lu, "
    278             "Size=%lux%lu, Sending to async-handler..\n",
    279             (unsigned long)uScreenId, (unsigned long)uPixelFormat,
    280             (unsigned long)uBitsPerPixel, (unsigned long)uBytesPerLine,
     221    LogRel(("UIFrameBuffer::NotifyChange: Screen=%lu, Origin=%lux%lu, Size=%lux%lu, Sending to async-handler..\n",
     222            (unsigned long)uScreenId,
     223            (unsigned long)uX, (unsigned long)uY,
    281224            (unsigned long)uWidth, (unsigned long)uHeight));
    282     emit sigRequestResize(uPixelFormat, pVRAM, uBitsPerPixel, uBytesPerLine, uWidth, uHeight);
     225    emit sigNotifyChange(uScreenId, uWidth, uHeight);
    283226
    284227    /* Unlock access to frame-buffer: */
    285228    unlock();
    286229
    287     /* Confirm RequestResize: */
    288     return S_OK;
     230    /* Give up control token to other thread: */
     231    RTThreadYield();
     232
     233    /* Confirm NotifyChange: */
     234    return S_OK;
     235}
     236
     237STDMETHODIMP UIFrameBuffer::NotifyUpdate(ULONG uX, ULONG uY, ULONG uWidth, ULONG uHeight)
     238{
     239    /* Retina screens with physical-to-logical scaling requires
     240     * odd/even pixel updates to be taken into account,
     241     * otherwise we have artifacts on the borders of incoming rectangle. */
     242    uX = qMax(0, (int)uX - 1);
     243    uY = qMax(0, (int)uY - 1);
     244    uWidth = qMin((int)m_width, (int)uWidth + 2);
     245    uHeight = qMin((int)m_height, (int)uHeight + 2);
     246
     247    /* Lock access to frame-buffer: */
     248    lock();
     249
     250    /* Make sure frame-buffer is used: */
     251    if (m_fUnused)
     252    {
     253        LogRel2(("UIFrameBuffer::NotifyUpdate: Origin=%lux%lu, Size=%lux%lu, Ignored!\n",
     254                 (unsigned long)uX, (unsigned long)uY,
     255                 (unsigned long)uWidth, (unsigned long)uHeight));
     256
     257        /* Unlock access to frame-buffer: */
     258        unlock();
     259
     260        /* Ignore NotifyUpdate: */
     261        return E_FAIL;
     262    }
     263
     264    /* Widget update is NOT thread-safe and *seems* never will be,
     265     * We have to notify machine-view with the async-signal to perform update operation. */
     266    LogRel2(("UIFrameBuffer::NotifyUpdate: Origin=%lux%lu, Size=%lux%lu, Sending to async-handler..\n",
     267             (unsigned long)uX, (unsigned long)uY,
     268             (unsigned long)uWidth, (unsigned long)uHeight));
     269    emit sigNotifyUpdate(uX, uY, uWidth, uHeight);
     270
     271    /* Unlock access to frame-buffer: */
     272    unlock();
     273
     274    /* Confirm NotifyUpdate: */
     275    return S_OK;
     276}
     277
     278STDMETHODIMP UIFrameBuffer::VideoModeSupported(ULONG uWidth, ULONG uHeight, ULONG uBPP, BOOL *pfSupported)
     279{
     280    /* Make sure result pointer is valid: */
     281    if (!pfSupported)
     282    {
     283        LogRel2(("UIFrameBuffer::IsVideoModeSupported: Mode: BPP=%lu, Size=%lux%lu, Invalid pfSupported pointer!\n",
     284                 (unsigned long)uBPP, (unsigned long)uWidth, (unsigned long)uHeight));
     285
     286        return E_POINTER;
     287    }
     288
     289    /* Lock access to frame-buffer: */
     290    lock();
     291
     292    /* Make sure frame-buffer is used: */
     293    if (m_fUnused)
     294    {
     295        LogRel2(("UIFrameBuffer::IsVideoModeSupported: Mode: BPP=%lu, Size=%lux%lu, Ignored!\n",
     296                 (unsigned long)uBPP, (unsigned long)uWidth, (unsigned long)uHeight));
     297
     298        /* Unlock access to frame-buffer: */
     299        unlock();
     300
     301        /* Ignore VideoModeSupported: */
     302        return E_FAIL;
     303    }
     304
     305    /* Determine if supported: */
     306    *pfSupported = TRUE;
     307    QSize screenSize = m_pMachineView->maxGuestSize();
     308    if (   (screenSize.width() != 0)
     309        && (uWidth > (ULONG)screenSize.width())
     310        && (uWidth > (ULONG)width()))
     311        *pfSupported = FALSE;
     312    if (   (screenSize.height() != 0)
     313        && (uHeight > (ULONG)screenSize.height())
     314        && (uHeight > (ULONG)height()))
     315        *pfSupported = FALSE;
     316    LogRel2(("UIFrameBuffer::IsVideoModeSupported: Mode: BPP=%lu, Size=%lux%lu, Supported=%s\n",
     317             (unsigned long)uBPP, (unsigned long)uWidth, (unsigned long)uHeight, *pfSupported ? "TRUE" : "FALSE"));
     318
     319    /* Unlock access to frame-buffer: */
     320    unlock();
     321
     322    /* Confirm VideoModeSupported: */
     323    return S_OK;
     324}
     325
     326STDMETHODIMP UIFrameBuffer::GetVisibleRegion(BYTE *pRectangles, ULONG uCount, ULONG *puCountCopied)
     327{
     328    PRTRECT rects = (PRTRECT)pRectangles;
     329
     330    if (!rects)
     331        return E_POINTER;
     332
     333    Q_UNUSED(uCount);
     334    Q_UNUSED(puCountCopied);
     335
     336    return S_OK;
     337}
     338
     339STDMETHODIMP UIFrameBuffer::SetVisibleRegion(BYTE *pRectangles, ULONG uCount)
     340{
     341    /* Make sure rectangles were passed: */
     342    if (!pRectangles)
     343    {
     344        LogRel2(("UIFrameBuffer::SetVisibleRegion: Rectangle count=%lu, Invalid pRectangles pointer!\n",
     345                 (unsigned long)uCount));
     346
     347        return E_POINTER;
     348    }
     349
     350    /* Lock access to frame-buffer: */
     351    lock();
     352
     353    /* Make sure frame-buffer is used: */
     354    if (m_fUnused)
     355    {
     356        LogRel2(("UIFrameBuffer::SetVisibleRegion: Rectangle count=%lu, Ignored!\n",
     357                 (unsigned long)uCount));
     358
     359        /* Unlock access to frame-buffer: */
     360        unlock();
     361
     362        /* Ignore SetVisibleRegion: */
     363        return E_FAIL;
     364    }
     365
     366    /* Compose region: */
     367    QRegion region;
     368    PRTRECT rects = (PRTRECT)pRectangles;
     369    for (ULONG ind = 0; ind < uCount; ++ind)
     370    {
     371        /* Get current rectangle: */
     372        QRect rect;
     373        rect.setLeft(rects->xLeft);
     374        rect.setTop(rects->yTop);
     375        /* Which is inclusive: */
     376        rect.setRight(rects->xRight - 1);
     377        rect.setBottom(rects->yBottom - 1);
     378        /* Append region: */
     379        region += rect;
     380        ++rects;
     381    }
     382
     383    /* We are directly updating synchronous visible-region: */
     384    m_syncVisibleRegion = region;
     385    /* And send async-signal to update asynchronous one: */
     386    LogRel2(("UIFrameBuffer::SetVisibleRegion: Rectangle count=%lu, Sending to async-handler..\n",
     387             (unsigned long)uCount));
     388    emit sigSetVisibleRegion(region);
     389
     390    /* Unlock access to frame-buffer: */
     391    unlock();
     392
     393    /* Confirm SetVisibleRegion: */
     394    return S_OK;
     395}
     396
     397STDMETHODIMP UIFrameBuffer::ProcessVHWACommand(BYTE *pCommand)
     398{
     399    Q_UNUSED(pCommand);
     400    return E_NOTIMPL;
     401}
     402
     403STDMETHODIMP UIFrameBuffer::Notify3DEvent(ULONG uType, BYTE *pData)
     404{
     405    /* Lock access to frame-buffer: */
     406    lock();
     407
     408    /* Make sure frame-buffer is used: */
     409    if (m_fUnused)
     410    {
     411        LogRel2(("UIFrameBuffer::Notify3DEvent: Ignored!\n"));
     412
     413        /* Unlock access to frame-buffer: */
     414        unlock();
     415
     416        /* Ignore Notify3DEvent: */
     417        return E_FAIL;
     418    }
     419
     420    switch (uType)
     421    {
     422        case VBOX3D_NOTIFY_EVENT_TYPE_VISIBLE_3DDATA:
     423        {
     424            /* Notify machine-view with the async-signal
     425             * about 3D overlay visibility change: */
     426            BOOL fVisible = !!pData;
     427            LogRel2(("UIFrameBuffer::Notify3DEvent: Sending to async-handler: "
     428                     "(VBOX3D_NOTIFY_EVENT_TYPE_VISIBLE_3DDATA = %s)\n",
     429                     fVisible ? "TRUE" : "FALSE"));
     430            emit sigNotifyAbout3DOverlayVisibilityChange(fVisible);
     431
     432            /* Unlock access to frame-buffer: */
     433            unlock();
     434
     435            /* Confirm Notify3DEvent: */
     436            return S_OK;
     437        }
     438
     439        case VBOX3D_NOTIFY_EVENT_TYPE_TEST_FUNCTIONAL:
     440        {
     441            HRESULT hr = m_fUnused ? E_FAIL : S_OK;
     442            unlock();
     443            return hr;
     444        }
     445
     446        default:
     447            break;
     448    }
     449
     450    /* Unlock access to frame-buffer: */
     451    unlock();
     452
     453    /* Ignore Notify3DEvent: */
     454    return E_INVALIDARG;
    289455}
    290456
     
    335501}
    336502
    337 /**
    338  * EMT callback: Informs about source bitmap change.
    339  * @param uScreenId Guest screen number.
    340  * @param uX        Horizontal origin of the update rectangle, in pixels.
    341  * @param uY        Vertical origin of the update rectangle, in pixels.
    342  * @param uWidth    Width of the guest display, in pixels.
    343  * @param uHeight   Height of the guest display, in pixels.
    344  * @note  Any EMT callback is subsequent. No any other EMT callback can be called until this one processed.
    345  * @note  Calls to this and #setMarkAsUnused method are synchronized between calling threads (from GUI side).
    346  */
    347 STDMETHODIMP UIFrameBuffer::NotifyChange(ULONG uScreenId,
    348                                          ULONG uX,
    349                                          ULONG uY,
    350                                          ULONG uWidth,
    351                                          ULONG uHeight)
    352 {
    353     /* Lock access to frame-buffer: */
    354     lock();
    355 
    356     /* Make sure frame-buffer is used: */
    357     if (m_fIsMarkedAsUnused)
    358     {
    359         LogRel(("UIFrameBuffer::NotifyChange: Screen=%lu, Origin=%lux%lu, Size=%lux%lu, Ignored!\n",
    360                 (unsigned long)uScreenId,
    361                 (unsigned long)uX, (unsigned long)uY,
    362                 (unsigned long)uWidth, (unsigned long)uHeight));
    363 
    364         /* Unlock access to frame-buffer: */
    365         unlock();
    366 
    367         /* Ignore NotifyChange: */
    368         return E_FAIL;
    369     }
    370 
    371     /* Acquire new pending bitmap: */
    372     m_pendingSourceBitmap = 0;
    373     m_pMachineView->session().GetConsole().GetDisplay().QuerySourceBitmap(uScreenId, m_pendingSourceBitmap);
    374 
    375     /* Widget resize is NOT thread-safe and *probably* never will be,
    376      * We have to notify machine-view with the async-signal to perform resize operation. */
    377     LogRel(("UIFrameBuffer::NotifyChange: Screen=%lu, Origin=%lux%lu, Size=%lux%lu, Sending to async-handler..\n",
    378             (unsigned long)uScreenId,
    379             (unsigned long)uX, (unsigned long)uY,
    380             (unsigned long)uWidth, (unsigned long)uHeight));
    381     emit sigNotifyChange(uScreenId, uWidth, uHeight);
    382 
    383     /* Unlock access to frame-buffer: */
    384     unlock();
    385 
    386     /* Give up control token to other thread: */
    387     RTThreadYield();
    388 
    389     /* Confirm NotifyChange: */
    390     return S_OK;
    391 }
    392 
    393 /**
    394  * EMT callback: Informs about an update.
    395  * @param uX      Horizontal origin of the update rectangle, in pixels.
    396  * @param uY      Vertical origin of the update rectangle, in pixels.
    397  * @param uWidth  Width of the update rectangle, in pixels.
    398  * @param uHeight Height of the update rectangle, in pixels.
    399  * @note  Any EMT callback is subsequent. No any other EMT callback can be called until this one processed.
    400  * @note  Calls to this and #setMarkAsUnused method are synchronized between calling threads (from GUI side).
    401  */
    402 STDMETHODIMP UIFrameBuffer::NotifyUpdate(ULONG uX, ULONG uY, ULONG uWidth, ULONG uHeight)
    403 {
    404     /* Retina screens with physical-to-logical scaling requires
    405      * odd/even pixel updates to be taken into account,
    406      * otherwise we have artifacts on the borders of incoming rectangle. */
    407     uX = qMax(0, (int)uX - 1);
    408     uY = qMax(0, (int)uY - 1);
    409     uWidth = qMin((int)m_width, (int)uWidth + 2);
    410     uHeight = qMin((int)m_height, (int)uHeight + 2);
    411 
    412     /* Lock access to frame-buffer: */
    413     lock();
    414 
    415     /* Make sure frame-buffer is used: */
    416     if (m_fIsMarkedAsUnused)
    417     {
    418         LogRel2(("UIFrameBuffer::NotifyUpdate: Origin=%lux%lu, Size=%lux%lu, Ignored!\n",
    419                  (unsigned long)uX, (unsigned long)uY,
    420                  (unsigned long)uWidth, (unsigned long)uHeight));
    421 
    422         /* Unlock access to frame-buffer: */
    423         unlock();
    424 
    425         /* Ignore NotifyUpdate: */
    426         return E_FAIL;
    427     }
    428 
    429     /* Widget update is NOT thread-safe and *seems* never will be,
    430      * We have to notify machine-view with the async-signal to perform update operation. */
    431     LogRel2(("UIFrameBuffer::NotifyUpdate: Origin=%lux%lu, Size=%lux%lu, Sending to async-handler..\n",
    432              (unsigned long)uX, (unsigned long)uY,
    433              (unsigned long)uWidth, (unsigned long)uHeight));
    434     emit sigNotifyUpdate(uX, uY, uWidth, uHeight);
    435 
    436     /* Unlock access to frame-buffer: */
    437     unlock();
    438 
    439     /* Confirm NotifyUpdate: */
    440     return S_OK;
    441 }
    442 
    443 /**
    444  * EMT callback: Returns whether the framebuffer implementation is willing to support a given video mode.
    445  * @param uWidth      Width of the guest display, in pixels.
    446  * @param uHeight     Height of the guest display, in pixels.
    447  * @param uBPP        Color depth, bits per pixel.
    448  * @param pfSupported Is framebuffer able/willing to render the video mode or not.
    449  * @note  Any EMT callback is subsequent. No any other EMT callback can be called until this one processed.
    450  * @note  Calls to this and #setMarkAsUnused method are synchronized between calling threads (from GUI side).
    451  */
    452 STDMETHODIMP UIFrameBuffer::VideoModeSupported(ULONG uWidth, ULONG uHeight, ULONG uBPP, BOOL *pfSupported)
    453 {
    454     /* Make sure result pointer is valid: */
    455     if (!pfSupported)
    456     {
    457         LogRel2(("UIFrameBuffer::IsVideoModeSupported: Mode: BPP=%lu, Size=%lux%lu, Invalid pfSupported pointer!\n",
    458                  (unsigned long)uBPP, (unsigned long)uWidth, (unsigned long)uHeight));
    459 
    460         return E_POINTER;
    461     }
    462 
    463     /* Lock access to frame-buffer: */
    464     lock();
    465 
    466     /* Make sure frame-buffer is used: */
    467     if (m_fIsMarkedAsUnused)
    468     {
    469         LogRel2(("UIFrameBuffer::IsVideoModeSupported: Mode: BPP=%lu, Size=%lux%lu, Ignored!\n",
    470                  (unsigned long)uBPP, (unsigned long)uWidth, (unsigned long)uHeight));
    471 
    472         /* Unlock access to frame-buffer: */
    473         unlock();
    474 
    475         /* Ignore VideoModeSupported: */
    476         return E_FAIL;
    477     }
    478 
    479     /* Determine if supported: */
    480     *pfSupported = TRUE;
    481     QSize screenSize = m_pMachineView->maxGuestSize();
    482     if (   (screenSize.width() != 0)
    483         && (uWidth > (ULONG)screenSize.width())
    484         && (uWidth > (ULONG)width()))
    485         *pfSupported = FALSE;
    486     if (   (screenSize.height() != 0)
    487         && (uHeight > (ULONG)screenSize.height())
    488         && (uHeight > (ULONG)height()))
    489         *pfSupported = FALSE;
    490     LogRel2(("UIFrameBuffer::IsVideoModeSupported: Mode: BPP=%lu, Size=%lux%lu, Supported=%s\n",
    491              (unsigned long)uBPP, (unsigned long)uWidth, (unsigned long)uHeight, *pfSupported ? "TRUE" : "FALSE"));
    492 
    493     /* Unlock access to frame-buffer: */
    494     unlock();
    495 
    496     /* Confirm VideoModeSupported: */
    497     return S_OK;
    498 }
    499 
    500 STDMETHODIMP UIFrameBuffer::GetVisibleRegion(BYTE *pRectangles, ULONG uCount, ULONG *puCountCopied)
    501 {
    502     PRTRECT rects = (PRTRECT)pRectangles;
    503 
    504     if (!rects)
    505         return E_POINTER;
    506 
    507     Q_UNUSED(uCount);
    508     Q_UNUSED(puCountCopied);
    509 
    510     return S_OK;
    511 }
    512 
    513 /**
    514  * EMT callback: Suggests a new visible region to this framebuffer.
    515  * @param pRectangles Pointer to the RTRECT array.
    516  * @param uCount      Number of RTRECT elements in the rectangles array.
    517  * @note  Any EMT callback is subsequent. No any other EMT callback can be called until this one processed.
    518  * @note  Calls to this and #setMarkAsUnused method are synchronized between calling threads (from GUI side).
    519  */
    520 STDMETHODIMP UIFrameBuffer::SetVisibleRegion(BYTE *pRectangles, ULONG uCount)
    521 {
    522     /* Make sure rectangles were passed: */
    523     if (!pRectangles)
    524     {
    525         LogRel2(("UIFrameBuffer::SetVisibleRegion: Rectangle count=%lu, Invalid pRectangles pointer!\n",
    526                  (unsigned long)uCount));
    527 
    528         return E_POINTER;
    529     }
    530 
    531     /* Lock access to frame-buffer: */
    532     lock();
    533 
    534     /* Make sure frame-buffer is used: */
    535     if (m_fIsMarkedAsUnused)
    536     {
    537         LogRel2(("UIFrameBuffer::SetVisibleRegion: Rectangle count=%lu, Ignored!\n",
    538                  (unsigned long)uCount));
    539 
    540         /* Unlock access to frame-buffer: */
    541         unlock();
    542 
    543         /* Ignore SetVisibleRegion: */
    544         return E_FAIL;
    545     }
    546 
    547     /* Compose region: */
    548     QRegion region;
    549     PRTRECT rects = (PRTRECT)pRectangles;
    550     for (ULONG ind = 0; ind < uCount; ++ind)
    551     {
    552         /* Get current rectangle: */
    553         QRect rect;
    554         rect.setLeft(rects->xLeft);
    555         rect.setTop(rects->yTop);
    556         /* Which is inclusive: */
    557         rect.setRight(rects->xRight - 1);
    558         rect.setBottom(rects->yBottom - 1);
    559         /* Append region: */
    560         region += rect;
    561         ++rects;
    562     }
    563 
    564     /* We are directly updating synchronous visible-region: */
    565     m_syncVisibleRegion = region;
    566     /* And send async-signal to update asynchronous one: */
    567     LogRel2(("UIFrameBuffer::SetVisibleRegion: Rectangle count=%lu, Sending to async-handler..\n",
    568              (unsigned long)uCount));
    569     emit sigSetVisibleRegion(region);
    570 
    571     /* Unlock access to frame-buffer: */
    572     unlock();
    573 
    574     /* Confirm SetVisibleRegion: */
    575     return S_OK;
    576 }
    577 
    578 STDMETHODIMP UIFrameBuffer::ProcessVHWACommand(BYTE *pCommand)
    579 {
    580     Q_UNUSED(pCommand);
    581     return E_NOTIMPL;
    582 }
    583 
    584 /**
    585  * EMT callback: Notifies framebuffer about 3D backend event.
    586  * @param uType Event type. Currently only VBOX3D_NOTIFY_EVENT_TYPE_VISIBLE_3DDATA is supported.
    587  * @param pData Event-specific data, depends on the supplied event type.
    588  * @note  Any EMT callback is subsequent. No any other EMT callback can be called until this one processed.
    589  * @note  Calls to this and #setMarkAsUnused method are synchronized between calling threads (from GUI side).
    590  */
    591 STDMETHODIMP UIFrameBuffer::Notify3DEvent(ULONG uType, BYTE *pData)
    592 {
    593     /* Lock access to frame-buffer: */
    594     lock();
    595 
    596     /* Make sure frame-buffer is used: */
    597     if (m_fIsMarkedAsUnused)
    598     {
    599         LogRel2(("UIFrameBuffer::Notify3DEvent: Ignored!\n"));
    600 
    601         /* Unlock access to frame-buffer: */
    602         unlock();
    603 
    604         /* Ignore Notify3DEvent: */
    605         return E_FAIL;
    606     }
    607 
    608     switch (uType)
    609     {
    610         case VBOX3D_NOTIFY_EVENT_TYPE_VISIBLE_3DDATA:
    611         {
    612             /* Notify machine-view with the async-signal
    613              * about 3D overlay visibility change: */
    614             BOOL fVisible = !!pData;
    615             LogRel2(("UIFrameBuffer::Notify3DEvent: Sending to async-handler: "
    616                      "(VBOX3D_NOTIFY_EVENT_TYPE_VISIBLE_3DDATA = %s)\n",
    617                      fVisible ? "TRUE" : "FALSE"));
    618             emit sigNotifyAbout3DOverlayVisibilityChange(fVisible);
    619 
    620             /* Unlock access to frame-buffer: */
    621             unlock();
    622 
    623             /* Confirm Notify3DEvent: */
    624             return S_OK;
    625         }
    626 
    627         case VBOX3D_NOTIFY_EVENT_TYPE_TEST_FUNCTIONAL:
    628         {
    629             HRESULT hr = m_fIsMarkedAsUnused ? E_FAIL : S_OK;
    630             unlock();
    631             return hr;
    632         }
    633 
    634         default:
    635             break;
    636     }
    637 
    638     /* Unlock access to frame-buffer: */
    639     unlock();
    640 
    641     /* Ignore Notify3DEvent: */
    642     return E_INVALIDARG;
    643 }
    644 
    645503void UIFrameBuffer::applyVisibleRegion(const QRegion &region)
    646504{
     
    669527    /* should never be here */
    670528    AssertBreakpoint();
     529    // TODO: Is this required? ^
    671530}
    672531#endif /* VBOX_WITH_VIDEOHWACCEL */
    673532
    674 void UIFrameBuffer::setView(UIMachineView * pView)
    675 {
    676     /* Disconnect handlers: */
    677     if (m_pMachineView)
    678         cleanupConnections();
    679 
    680     /* Reassign machine-view: */
    681     m_pMachineView = pView;
    682     m_WinId = (m_pMachineView && m_pMachineView->viewport()) ? (LONG64)m_pMachineView->viewport()->winId() : 0;
    683 
    684     /* Connect handlers: */
    685     if (m_pMachineView)
    686         prepareConnections();
    687 }
    688 
    689 void UIFrameBuffer::setHiDPIOptimizationType(HiDPIOptimizationType optimizationType)
    690 {
    691     /* Make sure 'HiDPI optimization type' changed: */
    692     if (m_hiDPIOptimizationType == optimizationType)
    693         return;
    694 
    695     /* Update 'HiDPI optimization type': */
    696     m_hiDPIOptimizationType = optimizationType;
    697 }
    698 
    699 void UIFrameBuffer::setBackingScaleFactor(double dBackingScaleFactor)
    700 {
    701     /* Make sure 'backing scale factor' changed: */
    702     if (m_dBackingScaleFactor == dBackingScaleFactor)
    703         return;
    704 
    705     /* Update 'backing scale factor': */
    706     m_dBackingScaleFactor = dBackingScaleFactor;
    707 }
    708 
    709533void UIFrameBuffer::prepareConnections()
    710534{
    711     connect(this, SIGNAL(sigRequestResize(int, uchar*, int, int, int, int)),
    712             m_pMachineView, SLOT(sltHandleRequestResize(int, uchar*, int, int, int, int)),
    713             Qt::QueuedConnection);
    714535    connect(this, SIGNAL(sigNotifyChange(ulong, int, int)),
    715536            m_pMachineView, SLOT(sltHandleNotifyChange(ulong, int, int)),
     
    728549void UIFrameBuffer::cleanupConnections()
    729550{
    730     disconnect(this, SIGNAL(sigRequestResize(int, uchar*, int, int, int, int)),
    731                m_pMachineView, SLOT(sltHandleRequestResize(int, uchar*, int, int, int, int)));
    732551    disconnect(this, SIGNAL(sigNotifyChange(ulong, int, int)),
    733552               m_pMachineView, SLOT(sltHandleNotifyChange(ulong, int, int)));
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIFrameBuffer.h

    r51459 r51487  
    44
    55/*
    6  * Copyright (C) 2010-2013 Oracle Corporation
     6 * Copyright (C) 2010-2014 Oracle Corporation
    77 *
    88 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2020/* Qt includes: */
    2121#include <QRegion>
    22 #include <QPaintEvent>
    2322
    2423/* GUI includes: */
     
    3433
    3534/* Forward declarations: */
     35class QResizeEvent;
     36class QPaintEvent;
    3637class UIMachineView;
    3738
    38 /**
    39  *  Frame buffer resize event.
    40  */
     39/** Frame-buffer resize-event. */
    4140class UIResizeEvent : public QEvent
    4241{
     
    6665};
    6766
    68 /**
    69  *  Common IFramebuffer implementation for all methods used by GUI to maintain
    70  *  the VM display video memory.
    71  *
    72  *  Note that although this class can be called from multiple threads
    73  *  (in particular, the GUI thread and EMT) it doesn't protect access to every
    74  *  data field using its mutex lock. This is because all synchronization between
    75  *  the GUI and the EMT thread is supposed to be done using the
    76  *  IFramebuffer::NotifyUpdate() and IFramebuffer::RequestResize() methods
    77  *  (in particular, the \a aFinished parameter of these methods is responsible
    78  *  for the synchronization). These methods are always called on EMT and
    79  *  therefore always follow one another but never in parallel.
    80  *
    81  *  Using this object's mutex lock (exposed also in IFramebuffer::Lock() and
    82  *  IFramebuffer::Unlock() implementations) usually makes sense only if some
    83  *  third-party thread (i.e. other than GUI or EMT) needs to make sure that
    84  *  *no* VM display update or resize event can occur while it is accessing
    85  *  IFramebuffer properties or the underlying display memory storage area.
    86  *
    87  *  See IFramebuffer documentation for more info.
    88  */
     67/** Common IFramebuffer implementation used to maintain VM display video memory. */
    8968class UIFrameBuffer : public QObject, VBOX_SCRIPTABLE_IMPL(IFramebuffer)
    9069{
     
    9372signals:
    9473
    95     /* Notifiers: EMT<->GUI interthread stuff: */
    96     void sigRequestResize(int iPixelFormat, uchar *pVRAM,
    97                           int iBitsPerPixel, int iBytesPerLine,
    98                           int iWidth, int iHeight);
     74    /** Notifies listener about guest-screen resolution changes. */
    9975    void sigNotifyChange(ulong uScreenId, int iWidth, int iHeight);
     76    /** Notifies listener about guest-screen updates. */
    10077    void sigNotifyUpdate(int iX, int iY, int iWidth, int iHeight);
     78    /** Notifies listener about guest-screen visible-region changes. */
    10179    void sigSetVisibleRegion(QRegion region);
     80    /** Notifies listener about guest 3D capability changes. */
    10281    void sigNotifyAbout3DOverlayVisibilityChange(bool fVisible);
    10382
    10483public:
    10584
    106     UIFrameBuffer(UIMachineView *aView);
    107     virtual ~UIFrameBuffer();
    108 
    109     /* API: [Un]used status stuff: */
    110     void setMarkAsUnused(bool fIsMarkAsUnused);
    111 
    112     /* API: Auto-enabled stuff: */
    113     bool isAutoEnabled() const;
    114     void setAutoEnabled(bool fIsAutoEnabled);
     85    /** Frame-buffer constructor.
     86      * @param pMachineView defines machine-view this frame-buffer is bounded to. */
     87    UIFrameBuffer(UIMachineView *pMachineView);
     88    /** Frame-buffer destructor. */
     89    ~UIFrameBuffer();
     90
     91    /** Assigns machine-view frame-buffer will be bounded to.
     92      * @param pMachineView defines machine-view this frame-buffer is bounded to. */
     93    void setView(UIMachineView *pMachineView);
     94
     95    /** Defines whether frame-buffer is <b>unused</b>.
     96      * @note Refer to m_fUnused for more information.
     97      * @note Calls to this and any other EMT callback are synchronized (from GUI side). */
     98    void setMarkAsUnused(bool fUnused);
     99
     100    /** Returns whether frame-buffer is <b>auto-enabled</b>.
     101      * @note Refer to m_fAutoEnabled for more information. */
     102    bool isAutoEnabled() const { return m_fAutoEnabled; }
     103    /** Defines whether frame-buffer is <b>auto-enabled</b>.
     104      * @note Refer to m_fAutoEnabled for more information. */
     105    void setAutoEnabled(bool fAutoEnabled) { m_fAutoEnabled = fAutoEnabled; }
    115106
    116107    NS_DECL_ISUPPORTS
    117108
    118109#ifdef Q_OS_WIN
     110    /** Windows: Increments reference-counter. */
    119111    STDMETHOD_(ULONG, AddRef)()
    120112    {
     
    122114    }
    123115
     116    /** Windows: Decrements reference-counter. */
    124117    STDMETHOD_(ULONG, Release)()
    125118    {
    126         long cnt = ::InterlockedDecrement(&m_iRefCnt);
    127         if (cnt == 0)
     119        long iCounter = ::InterlockedDecrement(&m_iRefCnt);
     120        if (iCounter == 0)
    128121            delete this;
    129         return cnt;
     122        return iCounter;
    130123    }
    131124#endif /* Q_OS_WIN */
     
    133126    VBOX_SCRIPTABLE_DISPATCH_IMPL(IFramebuffer)
    134127
    135     /* IFramebuffer COM methods */
    136     STDMETHOD(COMGETTER(Address)) (BYTE **ppAddress);
    137     STDMETHOD(COMGETTER(Width)) (ULONG *puWidth);
    138     STDMETHOD(COMGETTER(Height)) (ULONG *puHeight);
    139     STDMETHOD(COMGETTER(BitsPerPixel)) (ULONG *puBitsPerPixel);
    140     STDMETHOD(COMGETTER(BytesPerLine)) (ULONG *puBytesPerLine);
    141     STDMETHOD(COMGETTER(PixelFormat)) (ULONG *puPixelFormat);
    142     STDMETHOD(COMGETTER(UsesGuestVRAM)) (BOOL *pbUsesGuestVRAM);
    143     STDMETHOD(COMGETTER(HeightReduction)) (ULONG *puHeightReduction);
    144     STDMETHOD(COMGETTER(Overlay)) (IFramebufferOverlay **ppOverlay);
    145     STDMETHOD(COMGETTER(WinId)) (LONG64 *pWinId);
    146 
     128    /* IFramebuffer COM methods: */
     129    STDMETHOD(COMGETTER(Address))(BYTE **ppAddress);
     130    STDMETHOD(COMGETTER(Width))(ULONG *puWidth);
     131    STDMETHOD(COMGETTER(Height))(ULONG *puHeight);
     132    STDMETHOD(COMGETTER(BitsPerPixel))(ULONG *puBitsPerPixel);
     133    STDMETHOD(COMGETTER(BytesPerLine))(ULONG *puBytesPerLine);
     134    STDMETHOD(COMGETTER(PixelFormat))(ULONG *puPixelFormat);
     135    STDMETHOD(COMGETTER(UsesGuestVRAM))(BOOL *pbUsesGuestVRAM);
     136    STDMETHOD(COMGETTER(HeightReduction))(ULONG *puHeightReduction);
     137    STDMETHOD(COMGETTER(Overlay))(IFramebufferOverlay **ppOverlay);
     138    STDMETHOD(COMGETTER(WinId))(LONG64 *pWinId);
     139
     140    /* IFramebuffer sync methods: */
    147141    STDMETHOD(Lock)();
    148142    STDMETHOD(Unlock)();
    149143
    150     STDMETHOD(RequestResize) (ULONG uScreenId, ULONG uPixelFormat,
    151                               BYTE *pVRAM, ULONG uBitsPerPixel, ULONG uBytesPerLine,
    152                               ULONG uWidth, ULONG uHeight,
    153                               BOOL *pbFinished);
    154     STDMETHOD(NotifyChange)(ULONG uScreenId,
    155                             ULONG uX,
    156                             ULONG uY,
    157                             ULONG uWidth,
    158                             ULONG uHeight);
    159 
    160     STDMETHOD(NotifyUpdate) (ULONG uX, ULONG uY, ULONG uWidth, ULONG uHeight);
    161 
    162     STDMETHOD(VideoModeSupported) (ULONG uWidth, ULONG uHeight, ULONG uBPP,
    163                                    BOOL *pbSupported);
    164 
     144    /** EMT callback: Notifies frame-buffer about guest-screen size change.
     145      * @param        uScreenId Guest screen number.
     146      * @param        uX        Horizontal origin of the update rectangle, in pixels.
     147      * @param        uY        Vertical origin of the update rectangle, in pixels.
     148      * @param        uWidth    Width of the guest display, in pixels.
     149      * @param        uHeight   Height of the guest display, in pixels.
     150      * @note         Any EMT callback is subsequent. No any other EMT callback can be called until this one processed.
     151      * @note         Calls to this and #setMarkAsUnused method are synchronized (from GUI side). */
     152    STDMETHOD(NotifyChange)(ULONG uScreenId, ULONG uX, ULONG uY, ULONG uWidth, ULONG uHeight);
     153
     154    /** EMT callback: Notifies frame-buffer about guest-screen update.
     155      * @param        uX      Horizontal origin of the update rectangle, in pixels.
     156      * @param        uY      Vertical origin of the update rectangle, in pixels.
     157      * @param        uWidth  Width of the update rectangle, in pixels.
     158      * @param        uHeight Height of the update rectangle, in pixels.
     159      * @note         Any EMT callback is subsequent. No any other EMT callback can be called until this one processed.
     160      * @note         Calls to this and #setMarkAsUnused method are synchronized (from GUI side). */
     161    STDMETHOD(NotifyUpdate)(ULONG uX, ULONG uY, ULONG uWidth, ULONG uHeight);
     162
     163    /** EMT callback: Returns whether the frame-buffer implementation is willing to support a given video-mode.
     164      * @param        uWidth      Width of the guest display, in pixels.
     165      * @param        uHeight     Height of the guest display, in pixels.
     166      * @param        uBPP        Color depth, bits per pixel.
     167      * @param        pfSupported Is frame-buffer able/willing to render the video mode or not.
     168      * @note         Any EMT callback is subsequent. No any other EMT callback can be called until this one processed.
     169      * @note         Calls to this and #setMarkAsUnused method are synchronized (from GUI side). */
     170    STDMETHOD(VideoModeSupported)(ULONG uWidth, ULONG uHeight, ULONG uBPP, BOOL *pbSupported);
     171
     172    /** EMT callback which is not used in current implementation. */
    165173    STDMETHOD(GetVisibleRegion)(BYTE *pRectangles, ULONG uCount, ULONG *puCountCopied);
     174    /** EMT callback: Suggests new visible-region to this frame-buffer.
     175      * @param        pRectangles Pointer to the RTRECT array.
     176      * @param        uCount      Number of RTRECT elements in the rectangles array.
     177      * @note         Any EMT callback is subsequent. No any other EMT callback can be called until this one processed.
     178      * @note         Calls to this and #setMarkAsUnused method are synchronized (from GUI side). */
    166179    STDMETHOD(SetVisibleRegion)(BYTE *pRectangles, ULONG uCount);
    167180
     181    /** EMT callback which is not used in current implementation. */
    168182    STDMETHOD(ProcessVHWACommand)(BYTE *pCommand);
    169183
     184    /** EMT callback: Notifies frame-buffer about 3D backend event.
     185      * @param        uType Event type. Currently only VBOX3D_NOTIFY_EVENT_TYPE_VISIBLE_3DDATA is supported.
     186      * @param        pData Event-specific data, depends on the supplied event type.
     187      * @note         Any EMT callback is subsequent. No any other EMT callback can be called until this one processed.
     188      * @note         Calls to this and #setMarkAsUnused method are synchronized (from GUI side). */
    170189    STDMETHOD(Notify3DEvent)(ULONG uType, BYTE *pData);
    171190
     191    /** Returns frame-buffer data address. */
     192    virtual uchar *address() = 0;
     193    /** Returns frame-buffer width. */
    172194    ulong width() { return m_width; }
     195    /** Returns frame-buffer height. */
    173196    ulong height() { return m_height; }
    174 
     197    /** Returns frame-buffer bits-per-pixel value. */
     198    virtual ulong bitsPerPixel() = 0;
     199    /** Returns frame-buffer bytes-per-line value. */
     200    virtual ulong bytesPerLine() = 0;
     201    /** Returns default frame-buffer pixel-format. */
     202    virtual ulong pixelFormat() { return FramebufferPixelFormat_FOURCC_RGB; }
     203
     204    /** Locks frame-buffer access. */
     205    void lock() const { RTCritSectEnter(&m_critSect); }
     206    /** Unlocks frame-buffer access. */
     207    void unlock() const { RTCritSectLeave(&m_critSect); }
     208
     209    /** Returns host-to-guest scale ratio. */
     210    QSize scaledSize() const { return m_scaledSize; }
     211    /** Defines host-to-guest scale ratio as @a size. */
     212    void setScaledSize(const QSize &size = QSize()) { m_scaledSize = size; }
     213    /** Returns x-origin of the host (scaled) content corresponding to x-origin of guest (actual) content. */
    175214    inline int convertGuestXTo(int x) const { return m_scaledSize.isValid() ? qRound((double)m_scaledSize.width() / m_width * x) : x; }
     215    /** Returns y-origin of the host (scaled) content corresponding to y-origin of guest (actual) content. */
    176216    inline int convertGuestYTo(int y) const { return m_scaledSize.isValid() ? qRound((double)m_scaledSize.height() / m_height * y) : y; }
     217    /** Returns x-origin of the guest (actual) content corresponding to x-origin of host (scaled) content. */
    177218    inline int convertHostXTo(int x) const  { return m_scaledSize.isValid() ? qRound((double)m_width / m_scaledSize.width() * x) : x; }
     219    /** Returns y-origin of the guest (actual) content corresponding to y-origin of host (scaled) content. */
    178220    inline int convertHostYTo(int y) const  { return m_scaledSize.isValid() ? qRound((double)m_height / m_scaledSize.height() * y) : y; }
    179221
    180     virtual QSize scaledSize() const { return m_scaledSize; }
    181     virtual void setScaledSize(const QSize &size = QSize()) { m_scaledSize = size; }
    182 
    183     virtual ulong pixelFormat()
    184     {
    185         return FramebufferPixelFormat_FOURCC_RGB;
    186     }
    187 
    188     void lock() const { RTCritSectEnter(&m_critSect); }
    189     void unlock() const { RTCritSectLeave(&m_critSect); }
    190 
    191     virtual uchar *address() = 0;
    192     virtual ulong bitsPerPixel() = 0;
    193     virtual ulong bytesPerLine() = 0;
    194 
    195     /* API: Event-delegate stuff: */
    196     virtual void moveEvent(QMoveEvent* /*pEvent*/) {}
     222    /** Handles frame-buffer notify-change-event. */
     223    void notifyChange();
     224    /** Handles frame-buffer resize-event. */
    197225    virtual void resizeEvent(UIResizeEvent *pEvent) = 0;
     226    /** Handles frame-buffer paint-event. */
    198227    virtual void paintEvent(QPaintEvent *pEvent) = 0;
    199     virtual void applyVisibleRegion(const QRegion &region);
    200 
    201     void notifyChange();
     228    /** Handles frame-buffer apply-visible-region-event. */
     229    void applyVisibleRegion(const QRegion &region);
    202230
    203231#ifdef VBOX_WITH_VIDEOHWACCEL
    204     /* this method is called from the GUI thread
    205      * to perform the actual Video HW Acceleration command processing
    206      * the event is framebuffer implementation specific */
    207     virtual void doProcessVHWACommand(QEvent * pEvent);
    208 
     232    /** Performs Video HW Acceleration command. */
     233    virtual void doProcessVHWACommand(QEvent *pEvent);
     234    /** Handles viewport resize-event. */
    209235    virtual void viewportResized(QResizeEvent * /* pEvent */) {}
    210 
     236    /** Handles viewport scroll-event. */
    211237    virtual void viewportScrolled(int /* iX */, int /* iY */) {}
    212238#endif /* VBOX_WITH_VIDEOHWACCEL */
    213 
    214     virtual void setView(UIMachineView * pView);
    215239
    216240    /** Return HiDPI frame-buffer optimization type. */
    217241    HiDPIOptimizationType hiDPIOptimizationType() const { return m_hiDPIOptimizationType; }
    218242    /** Define HiDPI frame-buffer optimization type: */
    219     void setHiDPIOptimizationType(HiDPIOptimizationType optimizationType);
     243    void setHiDPIOptimizationType(HiDPIOptimizationType optimizationType) { m_hiDPIOptimizationType = optimizationType; }
    220244
    221245    /** Return backing scale factor used by HiDPI frame-buffer. */
    222246    double backingScaleFactor() const { return m_dBackingScaleFactor; }
    223247    /** Define backing scale factor used by HiDPI frame-buffer. */
    224     void setBackingScaleFactor(double dBackingScaleFactor);
     248    void setBackingScaleFactor(double dBackingScaleFactor) { m_dBackingScaleFactor = dBackingScaleFactor; }
    225249
    226250protected:
    227251
     252    /** Machine-view this frame-buffer is bounded to. */
    228253    UIMachineView *m_pMachineView;
     254    /** Cached window ID. */
     255    int64_t m_winId;
     256    /** RTCRITSECT object to protect frame-buffer access. */
    229257    mutable RTCRITSECT m_critSect;
     258    /** Frame-buffer width. */
    230259    ulong m_width;
     260    /** Frame-buffer height. */
    231261    ulong m_height;
     262    /** Frame-buffer scaled size. */
    232263    QSize m_scaledSize;
    233     int64_t m_WinId;
    234     bool m_fIsMarkedAsUnused;
    235     bool m_fIsAutoEnabled;
     264    /** Defines whether frame-buffer is <b>unused</b>.
     265      * <b>Unused</b> status determines whether frame-buffer should ignore EMT events or not. */
     266    bool m_fUnused;
     267    /** Defines whether frame-buffer is <b>auto-enabled</b>.
     268      * <b>Auto-enabled</b> status means that guest-screen corresponding to this frame-buffer
     269      * was automatically enabled by the multi-screen layout (auto-mount guest-screen) functionality,
     270      * so have potentially incorrect size-hint posted into guest event queue.
     271      * Machine-view will try to automatically adjust guest-screen size as soon as possible. */
     272    bool m_fAutoEnabled;
    236273
    237274    /** Source bitmap from IDisplay. */
    238275    CDisplaySourceBitmap m_sourceBitmap;
    239     /** Source bitmap from IDisplay acquired but not yet applied. */
     276    /** Source bitmap from IDisplay (acquired but not yet applied). */
    240277    CDisplaySourceBitmap m_pendingSourceBitmap;
    241     /** Reflects whether screen-updates allowed. */
     278    /** Reflects whether screen-updates are allowed. */
    242279    bool m_fIsUpdatesAllowed;
    243280
    244     /* To avoid a seamless flicker,
    245      * which caused by the latency between the
    246      * initial visible-region arriving from EMT thread
    247      * and actual visible-region application on GUI thread
    248      * it was decided to use two visible-region instances:
    249      * 1. 'Sync-one' which being updated synchronously by locking EMT thread,
    250      *               and used for immediate manual clipping of the painting operations.
    251      * 2. 'Async-one' which updated asynchronously by posting async-event from EMT to GUI thread,
    252                       which is used to update viewport parts for visible-region changes,
    253                       because NotifyUpdate doesn't take into account these changes. */
     281    /* To avoid a seamless flicker which caused by the latency between
     282     * the initial visible-region arriving from EMT thread
     283     * and actual visible-region appliance on GUI thread
     284     * it was decided to use two visible-region instances: */
     285    /** Sync visible-region which being updated synchronously by locking EMT thread.
     286      * Used for immediate manual clipping of the painting operations. */
    254287    QRegion m_syncVisibleRegion;
     288    /** Async visible-region which being updated asynchronously by posting async-event from EMT to GUI thread,
     289      * Used to update viewport parts for visible-region changes,
     290      * because NotifyUpdate doesn't take into account these changes. */
    255291    QRegion m_asyncVisibleRegion;
    256292
    257293private:
    258294
    259     /* Helpers: Prepare/cleanup stuff: */
     295    /** Prepare connections routine. */
    260296    void prepareConnections();
     297    /** Cleanup connections routine. */
    261298    void cleanupConnections();
    262299
    263300#ifdef Q_OS_WIN
     301    /** Windows: Holds the reference counter. */
    264302    long m_iRefCnt;
    265303#endif /* Q_OS_WIN */
     
    272310};
    273311
    274 #endif // !___UIFrameBuffer_h___
     312#endif /* !___UIFrameBuffer_h___ */
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.cpp

    r51484 r51487  
    215215    QString strKey = makeExtraDataKeyPerMonitor(GUI_LastGuestSizeHintWasFullscreen);
    216216    machine.SetExtraData(strKey, isFullscreenOrSeamless() ? "true" : "");
    217 }
    218 
    219 void UIMachineView::sltHandleRequestResize(int iPixelFormat, uchar *pVRAM,
    220                                            int iBitsPerPixel, int iBytesPerLine,
    221                                            int iWidth, int iHeight)
    222 {
    223     // TODO: Move to appropriate place!
    224     /* Some situations require frame-buffer resize-events to be ignored at all,
    225      * leaving machine-window, machine-view and frame-buffer sizes preserved: */
    226     if (uisession()->isGuestResizeIgnored())
    227         return;
    228 
    229     /* If machine-window is visible: */
    230     if (uisession()->isScreenVisible(m_uScreenId))
    231     {
    232         // TODO: Move to appropriate place!
    233         /* Adjust 'scale' mode for current machine-view size: */
    234         if (visualStateType() == UIVisualStateType_Scale)
    235             frameBuffer()->setScaledSize(size());
    236 
    237         /* Is there a proposal for frame-buffer resize? */
    238         bool fResizeProposed = (ulong)iWidth != frameBuffer()->width() ||
    239                                (ulong)iHeight != frameBuffer()->height();
    240 
    241         /* Perform frame-buffer mode-change: */
    242         UIResizeEvent resizeEvent(iPixelFormat, pVRAM, iBitsPerPixel, iBytesPerLine, iWidth, iHeight);
    243         frameBuffer()->resizeEvent(&resizeEvent);
    244 
    245         /* Was framebuffer actually resized? */
    246         if (fResizeProposed)
    247         {
    248             /* Scale-mode doesn't need this.. */
    249             if (visualStateType() != UIVisualStateType_Scale)
    250             {
    251                 /* Adjust maximum-size restriction for machine-view: */
    252                 setMaximumSize(sizeHint());
    253 
    254                 /* Disable the resize hint override hack: */
    255                 m_sizeHintOverride = QSize(-1, -1);
    256 
    257                 /* Force machine-window update own layout: */
    258                 QCoreApplication::sendPostedEvents(0, QEvent::LayoutRequest);
    259 
    260                 /* Update machine-view sliders: */
    261                 updateSliders();
    262 
    263                 /* By some reason Win host forgets to update machine-window central-widget
    264                  * after main-layout was updated, let's do it for all the hosts: */
    265                 machineWindow()->centralWidget()->update();
    266 
    267                 /* Normalize machine-window geometry: */
    268                 if (visualStateType() == UIVisualStateType_Normal)
    269                     machineWindow()->normalizeGeometry(true /* adjust position */);
    270             }
    271 
    272 #ifdef Q_WS_MAC
    273             /* Update MacOS X dock icon size: */
    274             machineLogic()->updateDockIconSize(screenId(), iWidth, iHeight);
    275 #endif /* Q_WS_MAC */
    276         }
    277     }
    278 
    279     /* Emit a signal about guest was resized: */
    280     emit resizeHintDone();
    281 
    282     LogRelFlow(("UIMachineView::ResizeHandled: "
    283                 "Screen=%d, Format=%d, "
    284                 "BitsPerPixel=%d, BytesPerLine=%d, "
    285                 "Size=%dx%d.\n",
    286                 (unsigned long)m_uScreenId, iPixelFormat,
    287                 iBitsPerPixel, iBytesPerLine, iWidth, iHeight));
    288217}
    289218
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.h

    r51484 r51487  
    9595    /* Slot to perform guest resize: */
    9696    void sltPerformGuestResize(const QSize &aSize = QSize());
    97 
    98     /* Handler: Frame-buffer RequestResize stuff: */
    99     virtual void sltHandleRequestResize(int iPixelFormat, uchar *pVRAM,
    100                                 int iBitsPerPixel, int iBytesPerLine,
    101                                 int iWidth, int iHeight);
    10297
    10398    /* Handler: Frame-buffer NotifyChange stuff: */
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