VirtualBox

Ignore:
Timestamp:
Nov 21, 2014 1:52:39 PM (10 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
96997
Message:

FE/Qt: 6278: Support for scaled video-output: Initial implementation, no UI settings for now.

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

Legend:

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

    r53249 r53372  
    136136const char* UIExtraDataDefs::GUI_GuruMeditationHandler = "GUI/GuruMeditationHandler";
    137137const char* UIExtraDataDefs::GUI_HidLedsSync = "GUI/HidLedsSync";
     138const char* UIExtraDataDefs::GUI_ScaleFactor = "GUI/ScaleFactor";
    138139
    139140/* Virtual Machine: Information dialog: */
  • trunk/src/VBox/Frontends/VirtualBox/src/extradata/UIExtraDataDefs.h

    r53249 r53372  
    237237        /** Holds whether machine should perform HID LEDs synchronization. */
    238238        extern const char* GUI_HidLedsSync;
     239        /** Holds the scale-factor. */
     240        extern const char* GUI_ScaleFactor;
    239241    /** @} */
    240242
  • trunk/src/VBox/Frontends/VirtualBox/src/extradata/UIExtraDataManager.cpp

    r53320 r53372  
    17921792           << GUI_GuruMeditationHandler
    17931793           << GUI_HidLedsSync
     1794           << GUI_ScaleFactor
    17941795           << GUI_InformationWindowGeometry
    17951796           << GUI_DefaultCloseAction << GUI_RestrictedCloseActions
     
    32553256    /* 'True' unless feature restricted: */
    32563257    return !isFeatureRestricted(GUI_HidLedsSync, strID);
     3258}
     3259
     3260double UIExtraDataManager::scaleFactor(const QString &strID)
     3261{
     3262    /* Get corresponding extra-data value: */
     3263    const QString strValue = extraDataString(GUI_ScaleFactor, strID);
     3264
     3265    /* Try to convert loaded data to double: */
     3266    bool fOk = false;
     3267    double dValue = strValue.toDouble(&fOk);
     3268
     3269    /* Invent the default value: */
     3270    if (!fOk || !dValue)
     3271        dValue = 1;
     3272
     3273    /* Return value: */
     3274    return dValue;
    32573275}
    32583276
  • trunk/src/VBox/Frontends/VirtualBox/src/extradata/UIExtraDataManager.h

    r53320 r53372  
    450450        /** Returns whether machine should perform HID LEDs synchronization. */
    451451        bool hidLedsSyncState(const QString &strID);
     452
     453        /** Returns scale-factor. */
     454        double scaleFactor(const QString &strID);
    452455    /** @} */
    453456
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIFrameBuffer.cpp

    r53236 r53372  
    2828# include "UIMachineView.h"
    2929# include "UIPopupCenter.h"
     30# include "UIExtraDataManager.h"
    3031# include "VBoxGlobal.h"
    3132# ifdef VBOX_WITH_MASKED_SEAMLESS
     
    6162    , m_fUnused(false)
    6263    , m_fAutoEnabled(false)
     64    , m_dScaleFactor(gEDataManager->scaleFactor(vboxGlobal().managedVMUuid()))
    6365    , m_hiDPIOptimizationType(HiDPIOptimizationType_None)
    6466    , m_dBackingScaleFactor(1.0)
     
    469471        rect.setRight(rects->xRight - 1);
    470472        rect.setBottom(rects->yBottom - 1);
     473        /* Tune according scale-factor: */
     474        // TODO: Take rounding into account..
     475        rect.moveTo(rect.topLeft() * m_dScaleFactor);
     476        rect.setSize(rect.size() * m_dScaleFactor);
    471477        /* Append region: */
    472478        region += rect;
     
    719725            paintSeamless(pEvent);
    720726            break;
    721         case UIVisualStateType_Scale:
    722             paintScaled(pEvent);
    723             break;
    724727        default:
    725728            paintDefault(pEvent);
     
    791794void UIFrameBuffer::paintDefault(QPaintEvent *pEvent)
    792795{
     796    /* Scaled image is NULL by default: */
     797    QImage scaledImage;
     798    /* But if scaled-factor is set and current image is NOT null: */
     799    if (m_scaledSize.isValid() && !m_image.isNull())
     800    {
     801        /* We are doing a deep copy of the image to make sure it will not be
     802         * detached during scale process, otherwise we can get a frozen frame-buffer. */
     803        scaledImage = m_image.copy();
     804        /* And scaling the image to predefined scaled-factor: */
     805        scaledImage = scaledImage.scaled(m_scaledSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
     806    }
     807    /* Finally we are choosing image to paint from: */
     808    const QImage &sourceImage = scaledImage.isNull() ? m_image : scaledImage;
     809
    793810    /* Get rectangle to paint: */
    794     QRect paintRect = pEvent->rect().intersected(m_image.rect()).intersected(m_pMachineView->viewport()->geometry());
     811    QRect paintRect = pEvent->rect().intersected(sourceImage.rect()).intersected(m_pMachineView->viewport()->geometry());
    795812    if (paintRect.isEmpty())
    796813        return;
     
    800817
    801818    /* Draw image rectangle: */
    802     drawImageRect(painter, m_image, paintRect,
     819    drawImageRect(painter, sourceImage, paintRect,
    803820                  m_pMachineView->contentsX(), m_pMachineView->contentsY(),
    804821                  hiDPIOptimizationType(), backingScaleFactor());
     
    807824void UIFrameBuffer::paintSeamless(QPaintEvent *pEvent)
    808825{
     826    /* Scaled image is NULL by default: */
     827    QImage scaledImage;
     828    /* But if scaled-factor is set and current image is NOT null: */
     829    if (m_scaledSize.isValid() && !m_image.isNull())
     830    {
     831        /* We are doing a deep copy of the image to make sure it will not be
     832         * detached during scale process, otherwise we can get a frozen frame-buffer. */
     833        scaledImage = m_image.copy();
     834        /* And scaling the image to predefined scaled-factor: */
     835        scaledImage = scaledImage.scaled(m_scaledSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
     836    }
     837    /* Finally we are choosing image to paint from: */
     838    const QImage &sourceImage = scaledImage.isNull() ? m_image : scaledImage;
     839
    809840    /* Get rectangle to paint: */
    810     QRect paintRect = pEvent->rect().intersected(m_image.rect()).intersected(m_pMachineView->viewport()->geometry());
     841    QRect paintRect = pEvent->rect().intersected(sourceImage.rect()).intersected(m_pMachineView->viewport()->geometry());
    811842    if (paintRect.isEmpty())
    812843        return;
     
    851882
    852883            /* Draw image rectangle: */
    853             drawImageRect(painter, m_image, rect,
     884            drawImageRect(painter, sourceImage, rect,
    854885                          m_pMachineView->contentsX(), m_pMachineView->contentsY(),
    855886                          hiDPIOptimizationType(), backingScaleFactor());
    856887        }
    857888    }
    858 }
    859 
    860 void UIFrameBuffer::paintScaled(QPaintEvent *pEvent)
    861 {
    862     /* Scaled image is NULL by default: */
    863     QImage scaledImage;
    864     /* But if scaled-factor is set and current image is NOT null: */
    865     if (m_scaledSize.isValid() && !m_image.isNull())
    866     {
    867         /* We are doing a deep copy of the image to make sure it will not be
    868          * detached during scale process, otherwise we can get a frozen frame-buffer. */
    869         scaledImage = m_image.copy();
    870         /* And scaling the image to predefined scaled-factor: */
    871         scaledImage = scaledImage.scaled(m_scaledSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
    872     }
    873     /* Finally we are choosing image to paint from: */
    874     QImage &sourceImage = scaledImage.isNull() ? m_image : scaledImage;
    875 
    876     /* Get rectangle to paint: */
    877     QRect paintRect = pEvent->rect().intersected(sourceImage.rect()).intersected(m_pMachineView->viewport()->geometry());
    878     if (paintRect.isEmpty())
    879         return;
    880 
    881     /* Create painter: */
    882     QPainter painter(m_pMachineView->viewport());
    883 
    884     /* Draw image rectangle: */
    885     drawImageRect(painter, sourceImage, paintRect,
    886                   m_pMachineView->contentsX(), m_pMachineView->contentsY(),
    887                   hiDPIOptimizationType(), backingScaleFactor());
    888889}
    889890
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIFrameBuffer.h

    r52902 r53372  
    234234    /** Paint routine for seamless mode. */
    235235    void paintSeamless(QPaintEvent *pEvent);
    236     /** Paint routine for scaled mode. */
    237     void paintScaled(QPaintEvent *pEvent);
    238236
    239237    /** Draws corresponding @a rect of passed @a image with @a painter. */
     
    277275    mutable RTCRITSECT m_critSect;
    278276
    279     /** @name Scaled mode related variables.
     277    /** @name Scale-factor related variables.
    280278     * @{ */
    281     /** Holds frame-buffer scaled size. */
     279    /** Holds the scale-factor used by the scaled-size. */
     280    const double m_dScaleFactor;
     281    /** Holds the frame-buffer's scaled-size. */
    282282    QSize m_scaledSize;
    283283    /** @} */
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.cpp

    r53365 r53372  
    185185    AssertMsg(newSize.isValid(), ("Size should be valid!\n"));
    186186
     187    /* Take the scale-factor into account: */
     188    const double dScaleFactor = gEDataManager->scaleFactor(vboxGlobal().managedVMUuid());
     189    newSize /= dScaleFactor;
     190
    187191    /* Expand current limitations: */
    188192    setMaxGuestSize(newSize);
     
    224228            frameBuffer()->setScaledSize(size());
    225229        }
     230        /* Adjust other modes to current NotifyChange event size: */
     231        else
     232        {
     233            /* Assign new frame-buffer logical-size taking the scale-factor into account: */
     234            const double dScaleFactor = gEDataManager->scaleFactor(vboxGlobal().managedVMUuid());
     235            frameBuffer()->setScaledSize(dScaleFactor == 1 ? QSize() : QSize(iWidth * dScaleFactor, iHeight * dScaleFactor));
     236        }
    226237
    227238        /* Perform frame-buffer mode-change: */
     
    271282void UIMachineView::sltHandleNotifyUpdate(int iX, int iY, int iWidth, int iHeight)
    272283{
    273     /* Update corresponding viewport part: */
    274     viewport()->update(iX - contentsX(), iY - contentsY(), iWidth, iHeight);
     284    /* Take the scale-factor into account: */
     285    const double dScaleFactor = gEDataManager->scaleFactor(vboxGlobal().managedVMUuid());
     286    if (dScaleFactor == 1)
     287    {
     288        /* Just update corresponding viewport part: */
     289        viewport()->update(iX - contentsX(), iY - contentsY(), iWidth, iHeight);
     290    }
     291    else
     292    {
     293        /* Calculate corresponding viewport part: */
     294        QRect rect(iX * dScaleFactor - 1 - contentsX(),
     295                   iY * dScaleFactor - 1 - contentsY(),
     296                   iWidth  * dScaleFactor + 2 * dScaleFactor + 1,
     297                   iHeight * dScaleFactor + 2 * dScaleFactor + 1);
     298        /* Limit the resulting part by the viewport rectangle: */
     299        rect &= viewport()->rect();
     300        /* Update corresponding viewport part: */
     301        viewport()->update(rect);
     302    }
    275303}
    276304
     
    392420void UIMachineView::prepareFrameBuffer()
    393421{
     422    /* Take scale-factor into account: */
     423    const double dScaleFactor = gEDataManager->scaleFactor(vboxGlobal().managedVMUuid());
     424
    394425    /* Prepare frame-buffer: */
    395426    UIFrameBuffer *pFrameBuffer = uisession()->frameBuffer(screenId());
     
    422453# endif /* !VBOX_WITH_VIDEOHWACCEL */
    423454        m_pFrameBuffer->setHiDPIOptimizationType(uisession()->hiDPIOptimizationType());
    424 
     455        m_pFrameBuffer->setScaledSize(dScaleFactor == 1 ? QSize() :
     456                                      QSize(m_pFrameBuffer->width() * dScaleFactor,
     457                                            m_pFrameBuffer->height() * dScaleFactor));
    425458        uisession()->setFrameBuffer(screenId(), m_pFrameBuffer);
    426459    }
     
    463496    /* If we have a valid size, resize the framebuffer. */
    464497    if (size.width() > 0 && size.height() > 0)
     498    {
    465499        frameBuffer()->resizeEvent(size.width(), size.height());
     500        frameBuffer()->setScaledSize(dScaleFactor == 1 ? QSize() :
     501                                     QSize(frameBuffer()->width() * dScaleFactor,
     502                                           frameBuffer()->height() * dScaleFactor));
     503    }
    466504}
    467505
     
    609647    QSize size(m_pFrameBuffer->width(), m_pFrameBuffer->height());
    610648
     649    /* Take the scale-factor into account: */
     650    const double dScaleFactor = gEDataManager->scaleFactor(vboxGlobal().managedVMUuid());
     651    size *= dScaleFactor;
     652
    611653#ifdef VBOX_WITH_DEBUGGER_GUI
    612654    // TODO: Fix all DEBUGGER stuff!
     
    689731        size = QSize(800, 600);
    690732
     733    /* Take the scale-factor into account: */
     734    const double dScaleFactor = gEDataManager->scaleFactor(vboxGlobal().managedVMUuid());
     735    size *= dScaleFactor;
     736
    691737    /* Return size: */
    692738    return size;
     
    704750void UIMachineView::resetPausePixmap()
    705751{
    706     /* Reset pixmap: */
     752    /* Reset pixmap(s): */
    707753    m_pausePixmap = QPixmap();
     754    m_pausePixmapScaled = QPixmap();
    708755}
    709756
     
    737784    /* Finally copy the screen-shot to pause-pixmap: */
    738785    m_pausePixmap = QPixmap::fromImage(screenShot);
     786
     787    /* Update scaled pause pixmap: */
     788    updateScaledPausePixmap();
    739789}
    740790
     
    763813    /* Finally copy the screen-shot to pause-pixmap: */
    764814    m_pausePixmap = QPixmap::fromImage(screenShot);
     815
     816    /* Update scaled pause pixmap: */
     817    updateScaledPausePixmap();
     818}
     819
     820void UIMachineView::updateScaledPausePixmap()
     821{
     822    /* Make sure pause pixmap is not null: */
     823    if (pausePixmap().isNull())
     824        return;
     825
     826    /* Make sure scaled-size is not null: */
     827    const QSize scaledSize = frameBuffer()->scaledSize();
     828    if (!scaledSize.isValid())
     829        return;
     830
     831    /* Update pause pixmap finally: */
     832    m_pausePixmapScaled = pausePixmap().scaled(scaledSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
    765833}
    766834
     
    10011069        QRect rect = pPaintEvent->rect().intersect(viewport()->rect());
    10021070        QPainter painter(viewport());
    1003         painter.drawPixmap(rect, pausePixmap(), QRect(rect.x() + contentsX(), rect.y() + contentsY(),
    1004                                                       rect.width(), rect.height()));
     1071        /* Take the scale-factor into account: */
     1072        const double dScaleFactor = gEDataManager->scaleFactor(vboxGlobal().managedVMUuid());
     1073        if (dScaleFactor == 1)
     1074            painter.drawPixmap(rect, pausePixmap(), QRect(rect.x() + contentsX(), rect.y() + contentsY(),
     1075                                                          rect.width(), rect.height()));
     1076        else
     1077            painter.drawPixmap(rect, pausePixmapScaled(), QRect(rect.x() + contentsX(), rect.y() + contentsY(),
     1078                                                                rect.width(), rect.height()));
    10051079#ifdef Q_WS_MAC
    10061080        /* Update the dock icon: */
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.h

    r53363 r53372  
    194194    /** Returns the pause-pixmap: */
    195195    const QPixmap& pausePixmap() const { return m_pausePixmap; }
     196    /** Returns the scaled pause-pixmap: */
     197    const QPixmap& pausePixmapScaled() const { return m_pausePixmapScaled; }
    196198    /** Resets the pause-pixmap. */
    197     virtual void resetPausePixmap();
     199    void resetPausePixmap();
    198200    /** Acquires live pause-pixmap. */
    199     virtual void takePausePixmapLive();
     201    void takePausePixmapLive();
    200202    /** Acquires snapshot pause-pixmap. */
    201     virtual void takePausePixmapSnapshot();
     203    void takePausePixmapSnapshot();
     204    /** Updates the scaled pause-pixmap. */
     205    void updateScaledPausePixmap();
    202206
    203207    /** The available area on the current screen for application windows. */
     
    275279    /** Holds the pause-pixmap. */
    276280    QPixmap m_pausePixmap;
     281    /** Holds the scaled pause-pixmap. */
     282    QPixmap m_pausePixmapScaled;
    277283
    278284    /* Friend classes: */
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/scale/UIMachineViewScale.cpp

    r53363 r53372  
    5353#endif
    5454                    )
    55     , m_pPauseImage(0)
    5655{
    5756    /* Resend the last resize hint if necessary: */
     
    7170}
    7271
    73 void UIMachineViewScale::takePausePixmapLive()
    74 {
    75     /* Take a screen snapshot. Note that TakeScreenShot() always needs a 32bpp image: */
    76     QImage shot = QImage(m_pFrameBuffer->width(), m_pFrameBuffer->height(), QImage::Format_RGB32);
    77     /* If TakeScreenShot fails or returns no image, just show a black image. */
    78     shot.fill(0);
    79     display().TakeScreenShot(screenId(), shot.bits(), shot.width(), shot.height(), KBitmapFormat_BGR0);
    80     m_pPauseImage = new QImage(shot);
    81     scalePauseShot();
    82 }
    83 
    84 void UIMachineViewScale::takePausePixmapSnapshot()
    85 {
    86     ULONG width = 0, height = 0;
    87     QVector<BYTE> screenData = machine().ReadSavedScreenshotPNGToArray(0, width, height);
    88     if (screenData.size() != 0)
    89     {
    90         ULONG guestOriginX = 0, guestOriginY = 0, guestWidth = 0, guestHeight = 0;
    91         BOOL fEnabled = true;
    92         machine().QuerySavedGuestScreenInfo(m_uScreenId, guestOriginX, guestOriginY, guestWidth, guestHeight, fEnabled);
    93         QImage shot = QImage::fromData(screenData.data(), screenData.size(), "PNG").scaled(guestWidth > 0 ? QSize(guestWidth, guestHeight) : guestSizeHint());
    94         m_pPauseImage = new QImage(shot);
    95         scalePauseShot();
    96     }
    97 }
    98 
    99 void UIMachineViewScale::resetPausePixmap()
    100 {
    101     /* Call the base class */
    102     UIMachineView::resetPausePixmap();
    103 
    104     if (m_pPauseImage)
    105     {
    106         delete m_pPauseImage;
    107         m_pPauseImage = 0;
    108     }
    109 }
    110 
    111 void UIMachineViewScale::scalePauseShot()
    112 {
    113     if (m_pPauseImage)
    114     {
    115         QSize scaledSize = frameBuffer()->scaledSize();
    116         if (scaledSize.isValid())
    117         {
    118             QImage tmpImg = m_pPauseImage->scaled(scaledSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
    119             dimImage(tmpImg);
    120             m_pausePixmap = QPixmap::fromImage(tmpImg);
    121         }
    122     }
    123 }
    124 
    12572void UIMachineViewScale::sltPerformGuestScale()
    12673{
     
    12976    frameBuffer()->setScaledSize(viewport()->size());
    13077
    131     /* Scale the pause image if necessary */
    132     scalePauseShot();
     78    /* Scale the pause-pixmap: */
     79    updateScaledPausePixmap();
    13380
    13481    /* Update viewport: */
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/scale/UIMachineViewScale.h

    r53363 r53372  
    3737    virtual ~UIMachineViewScale();
    3838
    39     virtual void takePausePixmapLive();
    40     virtual void takePausePixmapSnapshot();
    41     virtual void resetPausePixmap();
    42     void scalePauseShot();
    43 
    4439private slots:
    4540
     
    7065    void updateSliders();
    7166
    72     /* Private members: */
    73     QImage *m_pPauseImage;
    74 
    7567    /* Friend classes: */
    7668    friend class UIMachineView;
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