VirtualBox

Ignore:
Timestamp:
Apr 27, 2018 11:55:52 AM (7 years ago)
Author:
vboxsync
Message:

FE/Qt: bugref:9049: Move common 2D Video Acceleration code from VBoxFBOverlay class to VBox2DHelpers namespace. To be reused by VBoxGlobal library.

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk

    r72043 r72057  
    11351135if defined(VBOX_WITH_VIDEOHWACCEL) || defined(VBOX_GUI_USE_QGL)
    11361136 VirtualBox_SOURCES += \
     1137        src/VBox2DHelpers.cpp \
    11371138        src/VBoxFBOverlay.cpp \
    11381139        src/VBoxGLSupportInfo.cpp
  • trunk/src/VBox/Frontends/VirtualBox/src/VBox2DHelpers.cpp

    r72038 r72057  
    11/* $Id$ */
    22/** @file
    3  * VBox Qt GUI - VBoxFBOverlay implementation.
     3 * VBox Qt GUI - 2D Video Acceleration helpers implementation.
    44 */
    55
    66/*
    7  * Copyright (C) 2009-2017 Oracle Corporation
     7 * Copyright (C) 2009-2018 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    1616 */
    1717
    18 #if defined(VBOX_GUI_USE_QGL) /* entire file */
    1918
     19#if defined(VBOX_GUI_USE_QGL) || defined(VBOX_WITH_VIDEOHWACCEL)
    2020
    21 /*********************************************************************************************************************************
    22 *   Header Files                                                                                                                 *
    23 *********************************************************************************************************************************/
    2421#ifdef VBOX_WITH_PRECOMPILED_HEADERS
    2522# include <precomp.h>
     
    2825# define LOG_GROUP LOG_GROUP_GUI
    2926
     27// WORKAROUND:
     28// QGLWidget drags in Windows.h and stdint.h
     29# ifdef RT_OS_WINDOWS
     30#  include <iprt/win/windows.h>
     31#  include <iprt/stdint.h>
     32# endif
     33
    3034/* Qt includes: */
    31 # ifdef RT_OS_WINDOWS
    32 #  include <iprt/win/windows.h> /* QGLWidget drags in Windows.h; -Wall forces us to use wrapper. */
    33 #  include <iprt/stdint.h>      /* QGLWidget drags in stdint.h; -Wall forces us to use wrapper. */
    34 # endif
    35 # include <QApplication>
    3635# include <QGLWidget>
    37 # include <QFile>
    38 # include <QTextStream>
    3936
    4037/* GUI includes: */
    41 # include "VBoxFBOverlay.h"
    42 # include "UIDesktopWidgetWatchdog.h"
    43 # include "UIExtraDataManager.h"
    44 # include "UIMessageCenter.h"
    45 # include "UIModalWindowManager.h"
    46 # include "UIPopupCenter.h"
    47 # include "VBoxGlobal.h"
    48 
    49 /* COM includes: */
    50 # include "CSession.h"
    51 # include "CConsole.h"
    52 # include "CMachine.h"
    53 # include "CDisplay.h"
     38#include "VBox2DHelpers.h"
    5439
    5540/* Other VBox includes: */
    56 # include <iprt/asm.h>
    57 # include <iprt/semaphore.h>
    58 # include <VBox/AssertGuest.h>
    59 
    6041# include <VBox/VBoxGL2D.h>
    6142
    62 #ifdef VBOX_WS_MAC
    63 # include "VBoxUtils-darwin.h"
    64 #endif /* VBOX_WS_MAC */
    65 
    6643#endif /* !VBOX_WITH_PRECOMPILED_HEADERS */
    67 
    68 /* Other VBox includes: */
    69 #include <iprt/memcache.h>
    70 #include <VBox/err.h>
    71 
    72 #ifdef VBOX_WITH_VIDEOHWACCEL
    73 # include <VBoxVideo.h>
    74 # include <VBox/vmm/ssm.h>
    75 #endif /* VBOX_WITH_VIDEOHWACCEL */
    76 
    77 /* Other includes: */
    78 #include <math.h>
    79 
    80 
    81 /*********************************************************************************************************************************
    82 *   Defined Constants And Macros                                                                                                 *
    83 *********************************************************************************************************************************/
    84 #ifdef VBOXQGL_PROF_BASE
    85 # ifdef VBOXQGL_DBG_SURF
    86 #  define VBOXQGL_PROF_WIDTH 1400
    87 #  define VBOXQGL_PROF_HEIGHT 1050
    88 # else
    89 # define VBOXQGL_PROF_WIDTH 1400
    90 # define VBOXQGL_PROF_HEIGHT 1050
    91 //#define VBOXQGL_PROF_WIDTH 720
    92 //#define VBOXQGL_PROF_HEIGHT 480
    93 # endif
    94 #endif
    95 
    96 #define VBOXQGL_STATE_NAMEBASE "QGLVHWAData"
    97 #define VBOXQGL_STATE_VERSION_PIPESAVED    3
    98 #define VBOXQGL_STATE_VERSION              3
    99 
    100 //#define VBOXQGLOVERLAY_STATE_NAMEBASE "QGLOverlayVHWAData"
    101 //#define VBOXQGLOVERLAY_STATE_VERSION 1
    102 
    103 #ifdef DEBUG_misha
    104 //# define VBOXQGL_STATE_DEBUG
    105 #endif
    106 
    107 #ifdef VBOXQGL_STATE_DEBUG
    108 #define VBOXQGL_STATE_START_MAGIC        0x12345678
    109 #define VBOXQGL_STATE_STOP_MAGIC         0x87654321
    110 
    111 #define VBOXQGL_STATE_SURFSTART_MAGIC    0x9abcdef1
    112 #define VBOXQGL_STATE_SURFSTOP_MAGIC     0x1fedcba9
    113 
    114 #define VBOXQGL_STATE_OVERLAYSTART_MAGIC 0x13579bdf
    115 #define VBOXQGL_STATE_OVERLAYSTOP_MAGIC  0xfdb97531
    116 
    117 #define VBOXQGL_SAVE_START(_pSSM) do{ int rc = SSMR3PutU32(_pSSM, VBOXQGL_STATE_START_MAGIC); AssertRC(rc);}while(0)
    118 #define VBOXQGL_SAVE_STOP(_pSSM) do{ int rc = SSMR3PutU32(_pSSM, VBOXQGL_STATE_STOP_MAGIC); AssertRC(rc);}while(0)
    119 
    120 #define VBOXQGL_SAVE_SURFSTART(_pSSM) do{ int rc = SSMR3PutU32(_pSSM, VBOXQGL_STATE_SURFSTART_MAGIC); AssertRC(rc);}while(0)
    121 #define VBOXQGL_SAVE_SURFSTOP(_pSSM) do{ int rc = SSMR3PutU32(_pSSM, VBOXQGL_STATE_SURFSTOP_MAGIC); AssertRC(rc);}while(0)
    122 
    123 #define VBOXQGL_SAVE_OVERLAYSTART(_pSSM) do{ int rc = SSMR3PutU32(_pSSM, VBOXQGL_STATE_OVERLAYSTART_MAGIC); AssertRC(rc);}while(0)
    124 #define VBOXQGL_SAVE_OVERLAYSTOP(_pSSM) do{ int rc = SSMR3PutU32(_pSSM, VBOXQGL_STATE_OVERLAYSTOP_MAGIC); AssertRC(rc);}while(0)
    125 
    126 #define VBOXQGL_LOAD_CHECK(_pSSM, _v) \
    127     do{ \
    128         uint32_t _u32; \
    129         int rcCheck = SSMR3GetU32(_pSSM, &_u32); AssertRC(rcCheck); \
    130         if (_u32 != (_v)) \
    131         { \
    132             VBOXQGLLOG(("load error: expected magic (0x%x), but was (0x%x)\n", (_v), _u32));\
    133         }\
    134         Assert(_u32 == (_v)); \
    135     }while(0)
    136 
    137 #define VBOXQGL_LOAD_START(_pSSM) VBOXQGL_LOAD_CHECK(_pSSM, VBOXQGL_STATE_START_MAGIC)
    138 #define VBOXQGL_LOAD_STOP(_pSSM) VBOXQGL_LOAD_CHECK(_pSSM, VBOXQGL_STATE_STOP_MAGIC)
    139 
    140 #define VBOXQGL_LOAD_SURFSTART(_pSSM) VBOXQGL_LOAD_CHECK(_pSSM, VBOXQGL_STATE_SURFSTART_MAGIC)
    141 #define VBOXQGL_LOAD_SURFSTOP(_pSSM) VBOXQGL_LOAD_CHECK(_pSSM, VBOXQGL_STATE_SURFSTOP_MAGIC)
    142 
    143 #define VBOXQGL_LOAD_OVERLAYSTART(_pSSM) VBOXQGL_LOAD_CHECK(_pSSM, VBOXQGL_STATE_OVERLAYSTART_MAGIC)
    144 #define VBOXQGL_LOAD_OVERLAYSTOP(_pSSM) VBOXQGL_LOAD_CHECK(_pSSM, VBOXQGL_STATE_OVERLAYSTOP_MAGIC)
    145 
    146 #else
    147 
    148 #define VBOXQGL_SAVE_START(_pSSM) do{}while(0)
    149 #define VBOXQGL_SAVE_STOP(_pSSM) do{}while(0)
    150 
    151 #define VBOXQGL_SAVE_SURFSTART(_pSSM) do{}while(0)
    152 #define VBOXQGL_SAVE_SURFSTOP(_pSSM) do{}while(0)
    153 
    154 #define VBOXQGL_SAVE_OVERLAYSTART(_pSSM) do{}while(0)
    155 #define VBOXQGL_SAVE_OVERLAYSTOP(_pSSM) do{}while(0)
    156 
    157 #define VBOXQGL_LOAD_START(_pSSM) do{}while(0)
    158 #define VBOXQGL_LOAD_STOP(_pSSM) do{}while(0)
    159 
    160 #define VBOXQGL_LOAD_SURFSTART(_pSSM) do{}while(0)
    161 #define VBOXQGL_LOAD_SURFSTOP(_pSSM) do{}while(0)
    162 
    163 #define VBOXQGL_LOAD_OVERLAYSTART(_pSSM) do{}while(0)
    164 #define VBOXQGL_LOAD_OVERLAYSTOP(_pSSM) do{}while(0)
    165 
    166 #endif
    16744
    16845
     
    17047*   Global Variables                                                                                                             *
    17148*********************************************************************************************************************************/
    172 static VBoxVHWAInfo g_VBoxVHWASupportInfo;
    173 static bool g_bVBoxVHWAChecked = false;
    174 static bool g_bVBoxVHWASupported = false;
     49
     50static bool g_fVBoxVHWAChecked = false;
     51static bool g_fVBoxVHWASupported = false;
    17552
    17653
    177 #ifdef DEBUG
     54/*********************************************************************************************************************************
     55*   Namespace VBox2DHelpers implementation.                                                                                      *
     56*********************************************************************************************************************************/
    17857
    179 VBoxVHWADbgTimer::VBoxVHWADbgTimer(uint32_t cPeriods)
    180     : mPeriodSum(0)
    181     , mPrevTime(0)
    182     , mcFrames(0)
    183     , mcPeriods(cPeriods)
    184     , miPeriod(0)
     58bool VBox2DHelpers::isAcceleration2DVideoAvailable()
    18559{
    186     mpaPeriods = new uint64_t[cPeriods];
    187     memset(mpaPeriods, 0, cPeriods * sizeof(mpaPeriods[0]));
     60    if (!g_fVBoxVHWAChecked)
     61    {
     62        g_fVBoxVHWAChecked = true;
     63        g_fVBoxVHWASupported = VBoxVHWAInfo::checkVHWASupport();
     64    }
     65    return g_fVBoxVHWASupported;
    18866}
    18967
    190 VBoxVHWADbgTimer::~VBoxVHWADbgTimer()
    191 {
    192     delete[] mpaPeriods;
    193 }
    194 
    195 void VBoxVHWADbgTimer::frame()
    196 {
    197     uint64_t cur = VBOXGETTIME();
    198     if (mPrevTime)
    199     {
    200         uint64_t curPeriod = cur - mPrevTime;
    201         mPeriodSum += curPeriod - mpaPeriods[miPeriod];
    202         mpaPeriods[miPeriod] = curPeriod;
    203         ++miPeriod;
    204         miPeriod %= mcPeriods;
    205     }
    206     mPrevTime = cur;
    207     ++mcFrames;
    208 }
    209 
    210 #endif /* DEBUG */
    211 
    212 
    213 class VBoxVHWAEntriesCache
    214 {
    215 public:
    216     VBoxVHWAEntriesCache()
    217     {
    218         int rc = RTMemCacheCreate(&mVBoxCmdEntryCache, sizeof (VBoxVHWACommandElement),
    219                                     0, /* size_t cbAlignment */
    220                                     UINT32_MAX, /* uint32_t cMaxObjects */
    221                                     NULL, /* PFNMEMCACHECTOR pfnCtor*/
    222                                     NULL, /* PFNMEMCACHEDTOR pfnDtor*/
    223                                     NULL, /* void *pvUser*/
    224                                     0 /* uint32_t fFlags*/
    225                                     );
    226         AssertRC(rc);
    227     }
    228 
    229     ~VBoxVHWAEntriesCache()
    230     {
    231         RTMemCacheDestroy(mVBoxCmdEntryCache);
    232     }
    233 
    234     VBoxVHWACommandElement * alloc()
    235     {
    236         return (VBoxVHWACommandElement*)RTMemCacheAlloc(mVBoxCmdEntryCache);
    237     }
    238 
    239     void free(VBoxVHWACommandElement * pEl)
    240     {
    241         RTMemCacheFree(mVBoxCmdEntryCache, pEl);
    242     }
    243 
    244 private:
    245     RTMEMCACHE mVBoxCmdEntryCache;
    246 };
    247 
    248 static struct VBOXVHWACMD * vhwaHHCmdCreate(VBOXVHWACMD_TYPE type, size_t size)
    249 {
    250     char *buf = (char *)malloc(VBOXVHWACMD_SIZE_FROMBODYSIZE(size));
    251     memset(buf, 0, size);
    252     VBOXVHWACMD *pCmd = (VBOXVHWACMD *)buf;
    253     pCmd->enmCmd = type;
    254     pCmd->Flags = VBOXVHWACMD_FLAG_HH_CMD;
    255     return pCmd;
    256 }
    257 
    258 static const VBoxVHWAInfo & vboxVHWAGetSupportInfo(const QGLContext *pContext)
    259 {
    260     if (!g_VBoxVHWASupportInfo.isInitialized())
    261     {
    262         if (pContext)
    263         {
    264             g_VBoxVHWASupportInfo.init(pContext);
    265         }
    266         else
    267         {
    268             VBoxGLTmpContext ctx;
    269             const QGLContext *pContext = ctx.makeCurrent();
    270             Assert(pContext);
    271             if (pContext)
    272             {
    273                 g_VBoxVHWASupportInfo.init(pContext);
    274             }
    275         }
    276     }
    277     return g_VBoxVHWASupportInfo;
    278 }
    279 
    280 class VBoxVHWACommandProcessEvent : public QEvent
    281 {
    282 public:
    283     VBoxVHWACommandProcessEvent ()
    284         : QEvent ((QEvent::Type) VHWACommandProcessType),
    285           fProcessed(false)
    286     {
    287 #ifdef DEBUG_misha
    288         g_EventCounter.inc();
    289 #endif
    290     }
    291 
    292     void setProcessed()
    293     {
    294         fProcessed = true;
    295     }
    296 
    297     ~VBoxVHWACommandProcessEvent()
    298     {
    299         if (!fProcessed)
    300         {
    301             AssertMsgFailed(("VHWA command beinf destroyed unproceessed!"));
    302             LogRel(("GUI: VHWA command being destroyed unproceessed!"));
    303         }
    304 #ifdef DEBUG_misha
    305         g_EventCounter.dec();
    306 #endif
    307     }
    308 #ifdef DEBUG_misha
    309     static uint32_t cPending() { return g_EventCounter.refs(); }
    310 #endif
    311 
    312 private:
    313     bool fProcessed;
    314 #ifdef DEBUG_misha
    315     static VBoxVHWARefCounter g_EventCounter;
    316 #endif
    317 };
    318 
    319 #ifdef DEBUG_misha
    320 VBoxVHWARefCounter VBoxVHWACommandProcessEvent::g_EventCounter;
    321 #endif
    322 
    323 VBoxVHWAHandleTable::VBoxVHWAHandleTable(uint32_t initialSize)
    324 {
    325     mTable = new void*[initialSize];
    326     memset(mTable, 0, initialSize*sizeof(void*));
    327     mcSize = initialSize;
    328     mcUsage = 0;
    329     mCursor = 1; /* 0 is treated as invalid */
    330 }
    331 
    332 VBoxVHWAHandleTable::~VBoxVHWAHandleTable()
    333 {
    334     delete[] mTable;
    335 }
    336 
    337 uint32_t VBoxVHWAHandleTable::put(void *data)
    338 {
    339     Assert(data);
    340     if (!data)
    341         return VBOXVHWA_SURFHANDLE_INVALID;
    342 
    343     if (mcUsage == mcSize)
    344     {
    345         /** @todo resize */
    346         AssertFailed();
    347     }
    348 
    349     Assert(mcUsage < mcSize);
    350     if (mcUsage >= mcSize)
    351         return VBOXVHWA_SURFHANDLE_INVALID;
    352 
    353     for (int k = 0; k < 2; ++k)
    354     {
    355         Assert(mCursor != 0);
    356         for (uint32_t i = mCursor; i < mcSize; ++i)
    357         {
    358             if (!mTable[i])
    359             {
    360                 doPut(i, data);
    361                 mCursor = i+1;
    362                 return i;
    363             }
    364         }
    365         mCursor = 1; /* 0 is treated as invalid */
    366     }
    367 
    368     AssertFailed();
    369     return VBOXVHWA_SURFHANDLE_INVALID;
    370 }
    371 
    372 bool VBoxVHWAHandleTable::mapPut(uint32_t h, void * data)
    373 {
    374     if (mcSize <= h)
    375         return false;
    376     if (h == 0)
    377         return false;
    378     if (mTable[h])
    379         return false;
    380 
    381     doPut(h, data);
    382     return true;
    383 }
    384 
    385 void* VBoxVHWAHandleTable::get(uint32_t h)
    386 {
    387     Assert(h < mcSize);
    388     Assert(h > 0);
    389     return mTable[h];
    390 }
    391 
    392 void* VBoxVHWAHandleTable::remove(uint32_t h)
    393 {
    394     Assert(mcUsage);
    395     Assert(h < mcSize);
    396     void* val = mTable[h];
    397     Assert(val);
    398     if (val)
    399     {
    400         doRemove(h);
    401     }
    402     return val;
    403 }
    404 
    405 void VBoxVHWAHandleTable::doPut(uint32_t h, void * data)
    406 {
    407     ++mcUsage;
    408     mTable[h] = data;
    409 }
    410 
    411 void VBoxVHWAHandleTable::doRemove(uint32_t h)
    412 {
    413     mTable[h] = 0;
    414     --mcUsage;
    415 }
    416 
    417 static VBoxVHWATextureImage *vboxVHWAImageCreate(const QRect & aRect, const VBoxVHWAColorFormat & aFormat,
    418                                                  class VBoxVHWAGlProgramMngr * pMgr, VBOXVHWAIMG_TYPE flags)
    419 {
    420     bool bCanLinearNonFBO = false;
    421     if (!aFormat.fourcc())
    422     {
    423         flags &= ~VBOXVHWAIMG_FBO;
    424         bCanLinearNonFBO = true;
    425     }
    426 
    427     const VBoxVHWAInfo & info = vboxVHWAGetSupportInfo(NULL);
    428     if ((flags & VBOXVHWAIMG_PBO) && !info.getGlInfo().isPBOSupported())
    429         flags &= ~VBOXVHWAIMG_PBO;
    430 
    431     if ((flags & VBOXVHWAIMG_PBOIMG) &&
    432             (!info.getGlInfo().isPBOSupported() || !info.getGlInfo().isPBOOffsetSupported()))
    433         flags &= ~VBOXVHWAIMG_PBOIMG;
    434 
    435     if ((flags & VBOXVHWAIMG_FBO) && !info.getGlInfo().isFBOSupported())
    436         flags &= ~VBOXVHWAIMG_FBO;
    437 
    438     /* ensure we don't create a PBO-based texture in case we use a PBO-based image */
    439     if (flags & VBOXVHWAIMG_PBOIMG)
    440         flags &= ~VBOXVHWAIMG_PBO;
    441 
    442     if (flags & VBOXVHWAIMG_FBO)
    443     {
    444         if (flags & VBOXVHWAIMG_PBOIMG)
    445         {
    446             VBOXQGLLOG(("FBO PBO Image\n"));
    447             return new VBoxVHWATextureImageFBO<VBoxVHWATextureImagePBO>(aRect, aFormat, pMgr, flags);
    448         }
    449         VBOXQGLLOG(("FBO Generic Image\n"));
    450         return new VBoxVHWATextureImageFBO<VBoxVHWATextureImage>(aRect, aFormat, pMgr, flags);
    451     }
    452 
    453     if (!bCanLinearNonFBO)
    454     {
    455         VBOXQGLLOG(("Disabling Linear stretching\n"));
    456         flags &= ~VBOXVHWAIMG_LINEAR;
    457     }
    458 
    459     if (flags & VBOXVHWAIMG_PBOIMG)
    460     {
    461         VBOXQGLLOG(("PBO Image\n"));
    462         return new VBoxVHWATextureImagePBO(aRect, aFormat, pMgr, flags);
    463     }
    464 
    465     VBOXQGLLOG(("Generic Image\n"));
    466     return new VBoxVHWATextureImage(aRect, aFormat, pMgr, flags);
    467 }
    468 
    469 static VBoxVHWATexture* vboxVHWATextureCreate(const QGLContext * pContext, const QRect & aRect,
    470                                               const VBoxVHWAColorFormat & aFormat, uint32_t bytesPerLine, VBOXVHWAIMG_TYPE flags)
    471 {
    472     const VBoxVHWAInfo & info = vboxVHWAGetSupportInfo(pContext);
    473     GLint scaleFunc = (flags & VBOXVHWAIMG_LINEAR) ? GL_LINEAR : GL_NEAREST;
    474     if ((flags & VBOXVHWAIMG_PBO) && info.getGlInfo().isPBOSupported())
    475     {
    476         VBOXQGLLOG(("VBoxVHWATextureNP2RectPBO\n"));
    477         return new VBoxVHWATextureNP2RectPBO(aRect, aFormat, bytesPerLine, scaleFunc);
    478     }
    479     else if (info.getGlInfo().isTextureRectangleSupported())
    480     {
    481         VBOXQGLLOG(("VBoxVHWATextureNP2Rect\n"));
    482         return new VBoxVHWATextureNP2Rect(aRect, aFormat, bytesPerLine, scaleFunc);
    483     }
    484     else if (info.getGlInfo().isTextureNP2Supported())
    485     {
    486         VBOXQGLLOG(("VBoxVHWATextureNP2\n"));
    487         return new VBoxVHWATextureNP2(aRect, aFormat, bytesPerLine, scaleFunc);
    488     }
    489     VBOXQGLLOG(("VBoxVHWATexture\n"));
    490     return new VBoxVHWATexture(aRect, aFormat, bytesPerLine, scaleFunc);
    491 }
    492 
    493 class VBoxVHWAGlShaderComponent
    494 {
    495 public:
    496     VBoxVHWAGlShaderComponent(const char *aRcName, GLenum aType)
    497         : mRcName(aRcName)
    498         , mType(aType)
    499         , mInitialized(false)
    500     { NOREF(mType); }
    501 
    502 
    503     int init();
    504 
    505     const char * contents() { return mSource.constData(); }
    506     bool isInitialized() { return mInitialized; }
    507 private:
    508     const char *mRcName;
    509     GLenum mType;
    510     QByteArray mSource;
    511     bool mInitialized;
    512 };
    513 
    514 int VBoxVHWAGlShaderComponent::init()
    515 {
    516     if (isInitialized())
    517         return VINF_ALREADY_INITIALIZED;
    518 
    519     QFile fi(mRcName);
    520     if (!fi.open(QIODevice::ReadOnly))
    521     {
    522         AssertFailed();
    523         return VERR_GENERAL_FAILURE;
    524     }
    525 
    526     QTextStream is(&fi);
    527     QString program = is.readAll();
    528 
    529     mSource = program.toUtf8();
    530 
    531     mInitialized = true;
    532     return VINF_SUCCESS;
    533 }
    534 
    535 class VBoxVHWAGlShader
    536 {
    537 public:
    538     VBoxVHWAGlShader() :
    539         mType(GL_FRAGMENT_SHADER),
    540         mcComponents(0)
    541     {}
    542 
    543     VBoxVHWAGlShader & operator= (const VBoxVHWAGlShader & other)
    544     {
    545         mcComponents = other.mcComponents;
    546         mType = other.mType;
    547         if (mcComponents)
    548         {
    549             maComponents = new VBoxVHWAGlShaderComponent*[mcComponents];
    550             memcpy(maComponents, other.maComponents, mcComponents * sizeof(maComponents[0]));
    551         }
    552         return *this;
    553     }
    554 
    555     VBoxVHWAGlShader(const VBoxVHWAGlShader & other)
    556     {
    557         mcComponents = other.mcComponents;
    558         mType = other.mType;
    559         if (mcComponents)
    560         {
    561             maComponents = new VBoxVHWAGlShaderComponent*[mcComponents];
    562             memcpy(maComponents, other.maComponents, mcComponents * sizeof(maComponents[0]));
    563         }
    564     }
    565 
    566     VBoxVHWAGlShader(GLenum aType, VBoxVHWAGlShaderComponent ** aComponents, int cComponents)
    567         : mType(aType)
    568     {
    569         maComponents = new VBoxVHWAGlShaderComponent*[cComponents];
    570         mcComponents = cComponents;
    571         memcpy(maComponents, aComponents, cComponents * sizeof(maComponents[0]));
    572     }
    573 
    574     ~VBoxVHWAGlShader() {delete[] maComponents;}
    575     int init();
    576     GLenum type() { return mType; }
    577     GLuint shader() { return mShader; }
    578 private:
    579     GLenum mType;
    580     GLuint mShader;
    581     VBoxVHWAGlShaderComponent ** maComponents;
    582     int mcComponents;
    583 };
    584 
    585 int VBoxVHWAGlShader::init()
    586 {
    587     int rc = VERR_GENERAL_FAILURE;
    588     GLint *length;
    589     const char **sources;
    590     length = new GLint[mcComponents];
    591     sources = new const char*[mcComponents];
    592     for (int i = 0; i < mcComponents; i++)
    593     {
    594         length[i] = -1;
    595         rc = maComponents[i]->init();
    596         AssertRC(rc);
    597         if (RT_FAILURE(rc))
    598             break;
    599         sources[i] = maComponents[i]->contents();
    600     }
    601 
    602     if (RT_SUCCESS(rc))
    603     {
    604 #ifdef DEBUG
    605         VBOXQGLLOG(("\ncompiling shaders:\n------------\n"));
    606         for (int i = 0; i < mcComponents; i++)
    607             VBOXQGLLOG(("**********\n%s\n***********\n", sources[i]));
    608         VBOXQGLLOG(("------------\n"));
    609 #endif
    610         mShader = vboxglCreateShader(mType);
    611 
    612         VBOXQGL_CHECKERR(
    613                 vboxglShaderSource(mShader, mcComponents, sources, length);
    614                 );
    615 
    616         VBOXQGL_CHECKERR(
    617                 vboxglCompileShader(mShader);
    618                 );
    619 
    620         GLint compiled;
    621         VBOXQGL_CHECKERR(
    622                 vboxglGetShaderiv(mShader, GL_COMPILE_STATUS, &compiled);
    623                 );
    624 
    625 #ifdef DEBUG
    626         GLchar * pBuf = new GLchar[16300];
    627         vboxglGetShaderInfoLog(mShader, 16300, NULL, pBuf);
    628         VBOXQGLLOG(("\ncompile log:\n-----------\n%s\n---------\n", pBuf));
    629         delete[] pBuf;
    630 #endif
    631 
    632         Assert(compiled);
    633         if (compiled)
    634         {
    635             rc = VINF_SUCCESS;
    636         }
    637         else
    638         {
    639             VBOXQGL_CHECKERR(
    640                     vboxglDeleteShader(mShader);
    641                     );
    642             mShader = 0;
    643         }
    644     }
    645 
    646     delete[] length;
    647     delete[] sources;
    648     return rc;
    649 }
    650 
    651 class VBoxVHWAGlProgram
    652 {
    653 public:
    654     VBoxVHWAGlProgram(VBoxVHWAGlShader ** apShaders, int acShaders);
    655 
    656     virtual ~VBoxVHWAGlProgram();
    657 
    658     virtual int init();
    659     virtual void uninit();
    660     virtual int start();
    661     virtual int stop();
    662     bool isInitialized() { return mProgram; }
    663     GLuint program() {return mProgram;}
    664 private:
    665     GLuint mProgram;
    666     VBoxVHWAGlShader *mShaders;
    667     int mcShaders;
    668 };
    669 
    670 VBoxVHWAGlProgram::VBoxVHWAGlProgram(VBoxVHWAGlShader ** apShaders, int acShaders) :
    671        mProgram(0),
    672        mcShaders(0)
    673 {
    674     Assert(acShaders);
    675     if (acShaders)
    676     {
    677         mShaders = new VBoxVHWAGlShader[acShaders];
    678         for (int i = 0; i < acShaders; i++)
    679         {
    680             mShaders[i] = *apShaders[i];
    681         }
    682         mcShaders = acShaders;
    683     }
    684 }
    685 
    686 VBoxVHWAGlProgram::~VBoxVHWAGlProgram()
    687 {
    688     uninit();
    689 
    690     if (mShaders)
    691     {
    692         delete[] mShaders;
    693     }
    694 }
    695 
    696 int VBoxVHWAGlProgram::init()
    697 {
    698     Assert(!isInitialized());
    699     if (isInitialized())
    700         return VINF_ALREADY_INITIALIZED;
    701 
    702     Assert(mcShaders);
    703     if (!mcShaders)
    704         return VERR_GENERAL_FAILURE;
    705 
    706     int rc = VINF_SUCCESS;
    707     for (int i = 0; i < mcShaders; i++)
    708     {
    709         int rc = mShaders[i].init();
    710         AssertRC(rc);
    711         if (RT_FAILURE(rc))
    712         {
    713             break;
    714         }
    715     }
    716     if (RT_FAILURE(rc))
    717     {
    718         return rc;
    719     }
    720 
    721     mProgram = vboxglCreateProgram();
    722     Assert(mProgram);
    723     if (mProgram)
    724     {
    725         for (int i = 0; i < mcShaders; i++)
    726         {
    727             VBOXQGL_CHECKERR(
    728                     vboxglAttachShader(mProgram, mShaders[i].shader());
    729                     );
    730         }
    731 
    732         VBOXQGL_CHECKERR(
    733                 vboxglLinkProgram(mProgram);
    734                 );
    735 
    736 
    737         GLint linked;
    738         vboxglGetProgramiv(mProgram, GL_LINK_STATUS, &linked);
    739 
    740 #ifdef DEBUG
    741         GLchar * pBuf = new GLchar[16300];
    742         vboxglGetProgramInfoLog(mProgram, 16300, NULL, pBuf);
    743         VBOXQGLLOG(("link log: %s\n", pBuf));
    744         Assert(linked);
    745         delete[] pBuf;
    746 #endif
    747 
    748         if (linked)
    749         {
    750             return VINF_SUCCESS;
    751         }
    752 
    753         VBOXQGL_CHECKERR(
    754                 vboxglDeleteProgram(mProgram);
    755                 );
    756         mProgram = 0;
    757     }
    758     return VERR_GENERAL_FAILURE;
    759 }
    760 
    761 void VBoxVHWAGlProgram::uninit()
    762 {
    763     if (!isInitialized())
    764         return;
    765 
    766     VBOXQGL_CHECKERR(
    767             vboxglDeleteProgram(mProgram);
    768             );
    769     mProgram = 0;
    770 }
    771 
    772 int VBoxVHWAGlProgram::start()
    773 {
    774     VBOXQGL_CHECKERR(
    775             vboxglUseProgram(mProgram);
    776             );
    777     return VINF_SUCCESS;
    778 }
    779 
    780 int VBoxVHWAGlProgram::stop()
    781 {
    782     VBOXQGL_CHECKERR(
    783             vboxglUseProgram(0);
    784             );
    785     return VINF_SUCCESS;
    786 }
    787 
    788 #define VBOXVHWA_PROGRAM_DSTCOLORKEY        0x00000001
    789 #define VBOXVHWA_PROGRAM_SRCCOLORKEY        0x00000002
    790 #define VBOXVHWA_PROGRAM_COLORCONV          0x00000004
    791 #define VBOXVHWA_PROGRAM_COLORKEYNODISCARD  0x00000008
    792 
    793 #define VBOXVHWA_SUPPORTED_PROGRAM ( \
    794         VBOXVHWA_PROGRAM_DSTCOLORKEY \
    795         | VBOXVHWA_PROGRAM_SRCCOLORKEY \
    796         | VBOXVHWA_PROGRAM_COLORCONV \
    797         | VBOXVHWA_PROGRAM_COLORKEYNODISCARD \
    798         )
    799 
    800 class VBoxVHWAGlProgramVHWA : public VBoxVHWAGlProgram
    801 {
    802 public:
    803     VBoxVHWAGlProgramVHWA(uint32_t type, uint32_t fourcc, VBoxVHWAGlShader ** apShaders, int acShaders);
    804 
    805     uint32_t type() const {return mType;}
    806     uint32_t fourcc() const {return mFourcc;}
    807 
    808     int setDstCKeyUpperRange(GLfloat r, GLfloat g, GLfloat b);
    809 
    810     int setDstCKeyLowerRange(GLfloat r, GLfloat g, GLfloat b);
    811 
    812     int setSrcCKeyUpperRange(GLfloat r, GLfloat g, GLfloat b);
    813 
    814     int setSrcCKeyLowerRange(GLfloat r, GLfloat g, GLfloat b);
    815 
    816 
    817     virtual int init();
    818 
    819     bool matches(uint32_t type, uint32_t fourcc)
    820     {
    821         return mType == type && mFourcc == fourcc;
    822     }
    823 
    824     bool equals(const VBoxVHWAGlProgramVHWA & other)
    825     {
    826         return matches(other.mType, other.mFourcc);
    827     }
    828 
    829 private:
    830     uint32_t mType;
    831     uint32_t mFourcc;
    832 
    833     GLfloat mDstUpperR, mDstUpperG, mDstUpperB;
    834     GLint mUniDstUpperColor;
    835 
    836     GLfloat mDstLowerR, mDstLowerG, mDstLowerB;
    837     GLint mUniDstLowerColor;
    838 
    839     GLfloat mSrcUpperR, mSrcUpperG, mSrcUpperB;
    840     GLint mUniSrcUpperColor;
    841 
    842     GLfloat mSrcLowerR, mSrcLowerG, mSrcLowerB;
    843     GLint mUniSrcLowerColor;
    844 
    845     GLint mDstTex;
    846     GLint mUniDstTex;
    847 
    848     GLint mSrcTex;
    849     GLint mUniSrcTex;
    850 
    851     GLint mVTex;
    852     GLint mUniVTex;
    853 
    854     GLint mUTex;
    855     GLint mUniUTex;
    856 };
    857 
    858 VBoxVHWAGlProgramVHWA::VBoxVHWAGlProgramVHWA(uint32_t type, uint32_t fourcc, VBoxVHWAGlShader **apShaders, int acShaders)
    859     : VBoxVHWAGlProgram(apShaders, acShaders)
    860     , mType(type)
    861     , mFourcc(fourcc)
    862     , mDstUpperR(0.0)
    863     , mDstUpperG(0.0)
    864     , mDstUpperB(0.0)
    865     , mUniDstUpperColor(-1)
    866     , mDstLowerR(0.0)
    867     , mDstLowerG(0.0)
    868     , mDstLowerB(0.0)
    869     , mUniDstLowerColor(-1)
    870     , mSrcUpperR(0.0)
    871     , mSrcUpperG(0.0)
    872     , mSrcUpperB(0.0)
    873     , mUniSrcUpperColor(-1)
    874     , mSrcLowerR(0.0)
    875     , mSrcLowerG(0.0)
    876     , mSrcLowerB(0.0)
    877     , mUniSrcLowerColor(-1)
    878     , mDstTex(-1)
    879     , mUniDstTex(-1)
    880     , mSrcTex(-1)
    881     , mUniSrcTex(-1)
    882     , mVTex(-1)
    883     , mUniVTex(-1)
    884     , mUTex(-1)
    885     , mUniUTex(-1)
    886 {}
    887 
    888 int VBoxVHWAGlProgramVHWA::init()
    889 {
    890     int rc = VBoxVHWAGlProgram::init();
    891     if (RT_FAILURE(rc))
    892         return rc;
    893     if (rc == VINF_ALREADY_INITIALIZED)
    894         return rc;
    895 
    896     start();
    897 
    898     rc = VERR_GENERAL_FAILURE;
    899 
    900     do
    901     {
    902         GLint tex = 0;
    903         mUniSrcTex = vboxglGetUniformLocation(program(), "uSrcTex");
    904         Assert(mUniSrcTex != -1);
    905         if (mUniSrcTex == -1)
    906             break;
    907 
    908         VBOXQGL_CHECKERR(
    909                 vboxglUniform1i(mUniSrcTex, tex);
    910                 );
    911         mSrcTex = tex;
    912         ++tex;
    913 
    914         if (type() & VBOXVHWA_PROGRAM_SRCCOLORKEY)
    915         {
    916             mUniSrcLowerColor = vboxglGetUniformLocation(program(), "uSrcClr");
    917             Assert(mUniSrcLowerColor != -1);
    918             if (mUniSrcLowerColor == -1)
    919                 break;
    920 
    921             mSrcLowerR = 0.0; mSrcLowerG = 0.0; mSrcLowerB = 0.0;
    922 
    923             VBOXQGL_CHECKERR(
    924                     vboxglUniform4f(mUniSrcLowerColor, 0.0, 0.0, 0.0, 0.0);
    925                     );
    926         }
    927 
    928         if (type() & VBOXVHWA_PROGRAM_COLORCONV)
    929         {
    930             switch(fourcc())
    931             {
    932                 case FOURCC_YV12:
    933                 {
    934                     mUniVTex = vboxglGetUniformLocation(program(), "uVTex");
    935                     Assert(mUniVTex != -1);
    936                     if (mUniVTex == -1)
    937                         break;
    938 
    939                     VBOXQGL_CHECKERR(
    940                             vboxglUniform1i(mUniVTex, tex);
    941                             );
    942                     mVTex = tex;
    943                     ++tex;
    944 
    945                     mUniUTex = vboxglGetUniformLocation(program(), "uUTex");
    946                     Assert(mUniUTex != -1);
    947                     if (mUniUTex == -1)
    948                         break;
    949                     VBOXQGL_CHECKERR(
    950                             vboxglUniform1i(mUniUTex, tex);
    951                             );
    952                     mUTex = tex;
    953                     ++tex;
    954 
    955                     break;
    956                 }
    957                 case FOURCC_UYVY:
    958                 case FOURCC_YUY2:
    959                 case FOURCC_AYUV:
    960                     break;
    961                 default:
    962                     AssertFailed();
    963                     break;
    964             }
    965         }
    966 
    967         if (type() & VBOXVHWA_PROGRAM_DSTCOLORKEY)
    968         {
    969 
    970             mUniDstTex = vboxglGetUniformLocation(program(), "uDstTex");
    971             Assert(mUniDstTex != -1);
    972             if (mUniDstTex == -1)
    973                 break;
    974             VBOXQGL_CHECKERR(
    975                     vboxglUniform1i(mUniDstTex, tex);
    976                     );
    977             mDstTex = tex;
    978             ++tex;
    979 
    980             mUniDstLowerColor = vboxglGetUniformLocation(program(), "uDstClr");
    981             Assert(mUniDstLowerColor != -1);
    982             if (mUniDstLowerColor == -1)
    983                 break;
    984 
    985             mDstLowerR = 0.0; mDstLowerG = 0.0; mDstLowerB = 0.0;
    986 
    987             VBOXQGL_CHECKERR(
    988                     vboxglUniform4f(mUniDstLowerColor, 0.0, 0.0, 0.0, 0.0);
    989                     );
    990         }
    991 
    992         rc = VINF_SUCCESS;
    993     } while(0);
    994 
    995 
    996     stop();
    997     if (rc == VINF_SUCCESS)
    998         return VINF_SUCCESS;
    999 
    1000     AssertFailed();
    1001     VBoxVHWAGlProgram::uninit();
    1002     return VERR_GENERAL_FAILURE;
    1003 }
    1004 
    1005 int VBoxVHWAGlProgramVHWA::setDstCKeyUpperRange(GLfloat r, GLfloat g, GLfloat b)
    1006 {
    1007     Assert(isInitialized());
    1008     if (!isInitialized())
    1009         return VERR_GENERAL_FAILURE;
    1010     if (mDstUpperR == r && mDstUpperG == g && mDstUpperB == b)
    1011         return VINF_ALREADY_INITIALIZED;
    1012     vboxglUniform4f(mUniDstUpperColor, r, g, b, 0.0);
    1013     mDstUpperR = r;
    1014     mDstUpperG = g;
    1015     mDstUpperB = b;
    1016     return VINF_SUCCESS;
    1017 }
    1018 
    1019 int VBoxVHWAGlProgramVHWA::setDstCKeyLowerRange(GLfloat r, GLfloat g, GLfloat b)
    1020 {
    1021     Assert(isInitialized());
    1022     if (!isInitialized())
    1023         return VERR_GENERAL_FAILURE;
    1024     if (mDstLowerR == r && mDstLowerG == g && mDstLowerB == b)
    1025         return VINF_ALREADY_INITIALIZED;
    1026 
    1027     VBOXQGL_CHECKERR(
    1028             vboxglUniform4f(mUniDstLowerColor, r, g, b, 0.0);
    1029             );
    1030 
    1031     mDstLowerR = r;
    1032     mDstLowerG = g;
    1033     mDstLowerB = b;
    1034     return VINF_SUCCESS;
    1035 }
    1036 
    1037 int VBoxVHWAGlProgramVHWA::setSrcCKeyUpperRange(GLfloat r, GLfloat g, GLfloat b)
    1038 {
    1039     Assert(isInitialized());
    1040     if (!isInitialized())
    1041         return VERR_GENERAL_FAILURE;
    1042     if (mSrcUpperR == r && mSrcUpperG == g && mSrcUpperB == b)
    1043         return VINF_ALREADY_INITIALIZED;
    1044     vboxglUniform4f(mUniSrcUpperColor, r, g, b, 0.0);
    1045     mSrcUpperR = r;
    1046     mSrcUpperG = g;
    1047     mSrcUpperB = b;
    1048     return VINF_SUCCESS;
    1049 }
    1050 
    1051 int VBoxVHWAGlProgramVHWA::setSrcCKeyLowerRange(GLfloat r, GLfloat g, GLfloat b)
    1052 {
    1053     Assert(isInitialized());
    1054     if (!isInitialized())
    1055         return VERR_GENERAL_FAILURE;
    1056     if (mSrcLowerR == r && mSrcLowerG == g && mSrcLowerB == b)
    1057         return VINF_ALREADY_INITIALIZED;
    1058     VBOXQGL_CHECKERR(
    1059             vboxglUniform4f(mUniSrcLowerColor, r, g, b, 0.0);
    1060             );
    1061     mSrcLowerR = r;
    1062     mSrcLowerG = g;
    1063     mSrcLowerB = b;
    1064     return VINF_SUCCESS;
    1065 }
    1066 
    1067 class VBoxVHWAGlProgramMngr
    1068 {
    1069 public:
    1070     VBoxVHWAGlProgramMngr()
    1071         : mShaderCConvApplyAYUV(":/cconvApplyAYUV.c", GL_FRAGMENT_SHADER)
    1072         , mShaderCConvAYUV(":/cconvAYUV.c", GL_FRAGMENT_SHADER)
    1073         , mShaderCConvBGR(":/cconvBGR.c", GL_FRAGMENT_SHADER)
    1074         , mShaderCConvUYVY(":/cconvUYVY.c", GL_FRAGMENT_SHADER)
    1075         , mShaderCConvYUY2(":/cconvYUY2.c", GL_FRAGMENT_SHADER)
    1076         , mShaderCConvYV12(":/cconvYV12.c", GL_FRAGMENT_SHADER)
    1077         , mShaderSplitBGRA(":/splitBGRA.c", GL_FRAGMENT_SHADER)
    1078         , mShaderCKeyDst(":/ckeyDst.c", GL_FRAGMENT_SHADER)
    1079         , mShaderCKeyDst2(":/ckeyDst2.c", GL_FRAGMENT_SHADER)
    1080         , mShaderMainOverlay(":/mainOverlay.c", GL_FRAGMENT_SHADER)
    1081         , mShaderMainOverlayNoCKey(":/mainOverlayNoCKey.c", GL_FRAGMENT_SHADER)
    1082         , mShaderMainOverlayNoDiscard(":/mainOverlayNoDiscard.c", GL_FRAGMENT_SHADER)
    1083         , mShaderMainOverlayNoDiscard2(":/mainOverlayNoDiscard2.c", GL_FRAGMENT_SHADER)
    1084     {}
    1085 
    1086     VBoxVHWAGlProgramVHWA *getProgram(uint32_t type, const VBoxVHWAColorFormat * pFrom, const VBoxVHWAColorFormat * pTo);
    1087 
    1088     void stopCurrentProgram()
    1089     {
    1090         VBOXQGL_CHECKERR(
    1091             vboxglUseProgram(0);
    1092             );
    1093     }
    1094 private:
    1095     VBoxVHWAGlProgramVHWA *searchProgram(uint32_t type, uint32_t fourcc, bool bCreate);
    1096     VBoxVHWAGlProgramVHWA *createProgram(uint32_t type, uint32_t fourcc);
    1097 
    1098     typedef std::list <VBoxVHWAGlProgramVHWA*> ProgramList;
    1099 
    1100     ProgramList mPrograms;
    1101 
    1102     VBoxVHWAGlShaderComponent mShaderCConvApplyAYUV;
    1103 
    1104     VBoxVHWAGlShaderComponent mShaderCConvAYUV;
    1105     VBoxVHWAGlShaderComponent mShaderCConvBGR;
    1106     VBoxVHWAGlShaderComponent mShaderCConvUYVY;
    1107     VBoxVHWAGlShaderComponent mShaderCConvYUY2;
    1108     VBoxVHWAGlShaderComponent mShaderCConvYV12;
    1109     VBoxVHWAGlShaderComponent mShaderSplitBGRA;
    1110 
    1111     /* expected the dst surface texture to be bound to the 1-st tex unit */
    1112     VBoxVHWAGlShaderComponent mShaderCKeyDst;
    1113     /* expected the dst surface texture to be bound to the 2-nd tex unit */
    1114     VBoxVHWAGlShaderComponent mShaderCKeyDst2;
    1115     VBoxVHWAGlShaderComponent mShaderMainOverlay;
    1116     VBoxVHWAGlShaderComponent mShaderMainOverlayNoCKey;
    1117     VBoxVHWAGlShaderComponent mShaderMainOverlayNoDiscard;
    1118     VBoxVHWAGlShaderComponent mShaderMainOverlayNoDiscard2;
    1119 
    1120     friend class VBoxVHWAGlProgramVHWA;
    1121 };
    1122 
    1123 VBoxVHWAGlProgramVHWA *VBoxVHWAGlProgramMngr::createProgram(uint32_t type, uint32_t fourcc)
    1124 {
    1125     VBoxVHWAGlShaderComponent *apShaders[16];
    1126     uint32_t cShaders = 0;
    1127 
    1128     /* workaround for NVIDIA driver bug: ensure we attach the shader before those it is used in */
    1129     /* reserve a slot for the mShaderCConvApplyAYUV,
    1130      * in case it is not used the slot will be occupied by mShaderCConvBGR , which is ok */
    1131     cShaders++;
    1132 
    1133     if (!!(type & VBOXVHWA_PROGRAM_DSTCOLORKEY)
    1134             && !(type & VBOXVHWA_PROGRAM_COLORKEYNODISCARD))
    1135     {
    1136         if (fourcc == FOURCC_YV12)
    1137         {
    1138             apShaders[cShaders++] = &mShaderCKeyDst2;
    1139         }
    1140         else
    1141         {
    1142             apShaders[cShaders++] = &mShaderCKeyDst;
    1143         }
    1144     }
    1145 
    1146     if (type & VBOXVHWA_PROGRAM_SRCCOLORKEY)
    1147     {
    1148         AssertFailed();
    1149         /* disabled for now, not really necessary for video overlaying */
    1150     }
    1151 
    1152     bool bFound = false;
    1153 
    1154 //    if (type & VBOXVHWA_PROGRAM_COLORCONV)
    1155     {
    1156         if (fourcc == FOURCC_UYVY)
    1157         {
    1158             apShaders[cShaders++] = &mShaderCConvUYVY;
    1159             bFound = true;
    1160         }
    1161         else if (fourcc == FOURCC_YUY2)
    1162         {
    1163             apShaders[cShaders++] = &mShaderCConvYUY2;
    1164             bFound = true;
    1165         }
    1166         else if (fourcc == FOURCC_YV12)
    1167         {
    1168             apShaders[cShaders++] = &mShaderCConvYV12;
    1169             bFound = true;
    1170         }
    1171         else if (fourcc == FOURCC_AYUV)
    1172         {
    1173             apShaders[cShaders++] = &mShaderCConvAYUV;
    1174             bFound = true;
    1175         }
    1176     }
    1177 
    1178     if (bFound)
    1179     {
    1180         type |= VBOXVHWA_PROGRAM_COLORCONV;
    1181         apShaders[0] = &mShaderCConvApplyAYUV;
    1182     }
    1183     else
    1184     {
    1185         type &= (~VBOXVHWA_PROGRAM_COLORCONV);
    1186         apShaders[0] = &mShaderCConvBGR;
    1187     }
    1188 
    1189     if (type & VBOXVHWA_PROGRAM_DSTCOLORKEY)
    1190     {
    1191         if (type & VBOXVHWA_PROGRAM_COLORKEYNODISCARD)
    1192         {
    1193             if (fourcc == FOURCC_YV12)
    1194                 apShaders[cShaders++] = &mShaderMainOverlayNoDiscard2;
    1195             else
    1196                 apShaders[cShaders++] = &mShaderMainOverlayNoDiscard;
    1197         }
    1198         else
    1199             apShaders[cShaders++] = &mShaderMainOverlay;
    1200     }
    1201     else
    1202     {
    1203         // ensure we don't have empty functions /* paranoia for for ATI on linux */
    1204         apShaders[cShaders++] = &mShaderMainOverlayNoCKey;
    1205     }
    1206 
    1207     Assert(cShaders <= RT_ELEMENTS(apShaders));
    1208 
    1209     VBoxVHWAGlShader shader(GL_FRAGMENT_SHADER, apShaders, cShaders);
    1210     VBoxVHWAGlShader *pShader = &shader;
    1211 
    1212     VBoxVHWAGlProgramVHWA *pProgram =  new VBoxVHWAGlProgramVHWA(/*this, */type, fourcc, &pShader, 1);
    1213     pProgram->init();
    1214 
    1215     return pProgram;
    1216 }
    1217 
    1218 VBoxVHWAGlProgramVHWA * VBoxVHWAGlProgramMngr::getProgram(uint32_t type, const VBoxVHWAColorFormat * pFrom, const VBoxVHWAColorFormat * pTo)
    1219 {
    1220     Q_UNUSED(pTo);
    1221     uint32_t fourcc = 0;
    1222     type &= VBOXVHWA_SUPPORTED_PROGRAM;
    1223 
    1224     if (pFrom && pFrom->fourcc())
    1225     {
    1226         fourcc = pFrom->fourcc();
    1227         type |= VBOXVHWA_PROGRAM_COLORCONV;
    1228     }
    1229     else
    1230         type &= ~VBOXVHWA_PROGRAM_COLORCONV;
    1231 
    1232     if (   !(type & VBOXVHWA_PROGRAM_DSTCOLORKEY)
    1233         && !(type & VBOXVHWA_PROGRAM_SRCCOLORKEY))
    1234         type &= ~VBOXVHWA_PROGRAM_COLORKEYNODISCARD;
    1235 
    1236     if (type)
    1237         return searchProgram(type, fourcc, true);
    1238     return NULL;
    1239 }
    1240 
    1241 VBoxVHWAGlProgramVHWA * VBoxVHWAGlProgramMngr::searchProgram(uint32_t type, uint32_t fourcc, bool bCreate)
    1242 {
    1243     for (ProgramList::const_iterator it = mPrograms.begin(); it != mPrograms.end(); ++ it)
    1244     {
    1245         if (!(*it)->matches(type, fourcc))
    1246             continue;
    1247         return *it;
    1248     }
    1249     if (bCreate)
    1250     {
    1251         VBoxVHWAGlProgramVHWA *pProgram = createProgram(type, fourcc);
    1252         if (pProgram)
    1253         {
    1254             mPrograms.push_back(pProgram);
    1255             return pProgram;
    1256         }
    1257     }
    1258     return NULL;
    1259 }
    1260 
    1261 void VBoxVHWASurfaceBase::setAddress(uchar * addr)
    1262 {
    1263     Assert(addr);
    1264     if (!addr)
    1265         return;
    1266     if (addr == mAddress)
    1267         return;
    1268 
    1269     if (mFreeAddress)
    1270         free(mAddress);
    1271 
    1272     mAddress = addr;
    1273     mFreeAddress = false;
    1274 
    1275     mImage->setAddress(mAddress);
    1276 
    1277     mUpdateMem2TexRect.set(mRect);
    1278     Assert(!mUpdateMem2TexRect.isClear());
    1279     Assert(mRect.contains(mUpdateMem2TexRect.rect()));
    1280 }
    1281 
    1282 void VBoxVHWASurfaceBase::globalInit()
    1283 {
    1284     VBOXQGLLOG(("globalInit\n"));
    1285 
    1286     glEnable(GL_TEXTURE_RECTANGLE);
    1287     glDisable(GL_DEPTH_TEST);
    1288 
    1289     VBOXQGL_CHECKERR(
    1290             glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    1291             );
    1292     VBOXQGL_CHECKERR(
    1293             glPixelStorei(GL_PACK_ALIGNMENT, 1);
    1294             );
    1295 }
    1296 
    1297 VBoxVHWASurfaceBase::VBoxVHWASurfaceBase(class VBoxVHWAImage *pImage,
    1298                                          const QSize &aSize,
    1299                                          const QRect &aTargRect,
    1300                                          const QRect &aSrcRect,
    1301                                          const QRect &aVisTargRect,
    1302                                          VBoxVHWAColorFormat &aColorFormat,
    1303                                          VBoxVHWAColorKey *pSrcBltCKey,
    1304                                          VBoxVHWAColorKey *pDstBltCKey,
    1305                                          VBoxVHWAColorKey *pSrcOverlayCKey,
    1306                                          VBoxVHWAColorKey *pDstOverlayCKey,
    1307                                          VBOXVHWAIMG_TYPE aImgFlags)
    1308     : mRect(0,0,aSize.width(),aSize.height())
    1309     , mAddress(NULL)
    1310     , mpSrcBltCKey(NULL)
    1311     , mpDstBltCKey(NULL)
    1312     , mpSrcOverlayCKey(NULL)
    1313     , mpDstOverlayCKey(NULL)
    1314     , mpDefaultDstOverlayCKey(NULL)
    1315     , mpDefaultSrcOverlayCKey(NULL)
    1316     , mLockCount(0)
    1317     , mFreeAddress(false)
    1318     , mbNotIntersected(false)
    1319     , mComplexList(NULL)
    1320     , mpPrimary(NULL)
    1321     , mHGHandle(VBOXVHWA_SURFHANDLE_INVALID)
    1322     , mpImage(pImage)
    1323 #ifdef DEBUG
    1324     , cFlipsCurr(0)
    1325     , cFlipsTarg(0)
    1326 #endif
    1327 {
    1328     setDstBltCKey(pDstBltCKey);
    1329     setSrcBltCKey(pSrcBltCKey);
    1330 
    1331     setDefaultDstOverlayCKey(pDstOverlayCKey);
    1332     resetDefaultDstOverlayCKey();
    1333 
    1334     setDefaultSrcOverlayCKey(pSrcOverlayCKey);
    1335     resetDefaultSrcOverlayCKey();
    1336 
    1337     mImage = vboxVHWAImageCreate(QRect(0,0,aSize.width(),aSize.height()), aColorFormat, getGlProgramMngr(), aImgFlags);
    1338 
    1339     setRectValues(aTargRect, aSrcRect);
    1340     setVisibleRectValues(aVisTargRect);
    1341 }
    1342 
    1343 VBoxVHWASurfaceBase::~VBoxVHWASurfaceBase()
    1344 {
    1345     uninit();
    1346 }
    1347 
    1348 GLsizei VBoxVHWASurfaceBase::makePowerOf2(GLsizei val)
    1349 {
    1350     int last = ASMBitLastSetS32(val);
    1351     if (last>1)
    1352     {
    1353         last--;
    1354         if ((1 << last) != val)
    1355         {
    1356             Assert((1 << last) < val);
    1357             val = (1 << (last+1));
    1358         }
    1359     }
    1360     return val;
    1361 }
    1362 
    1363 ulong VBoxVHWASurfaceBase::calcBytesPerPixel(GLenum format, GLenum type)
    1364 {
    1365     /* we now support only common byte-aligned data */
    1366     int numComponents = 0;
    1367     switch(format)
    1368     {
    1369         case GL_COLOR_INDEX:
    1370         case GL_RED:
    1371         case GL_GREEN:
    1372         case GL_BLUE:
    1373         case GL_ALPHA:
    1374         case GL_LUMINANCE:
    1375             numComponents = 1;
    1376             break;
    1377         case GL_RGB:
    1378         case GL_BGR_EXT:
    1379             numComponents = 3;
    1380             break;
    1381         case GL_RGBA:
    1382         case GL_BGRA_EXT:
    1383             numComponents = 4;
    1384             break;
    1385         case GL_LUMINANCE_ALPHA:
    1386             numComponents = 2;
    1387             break;
    1388         default:
    1389             AssertFailed();
    1390             break;
    1391     }
    1392 
    1393     int componentSize = 0;
    1394     switch(type)
    1395     {
    1396         case GL_UNSIGNED_BYTE:
    1397         case GL_BYTE:
    1398             componentSize = 1;
    1399             break;
    1400         //case GL_BITMAP:
    1401         case  GL_UNSIGNED_SHORT:
    1402         case GL_SHORT:
    1403             componentSize = 2;
    1404             break;
    1405         case GL_UNSIGNED_INT:
    1406         case GL_INT:
    1407         case GL_FLOAT:
    1408             componentSize = 4;
    1409             break;
    1410         default:
    1411             AssertFailed();
    1412             break;
    1413     }
    1414     return numComponents * componentSize;
    1415 }
    1416 
    1417 void VBoxVHWASurfaceBase::uninit()
    1418 {
    1419     delete mImage;
    1420 
    1421     if (mAddress && mFreeAddress)
    1422     {
    1423         free(mAddress);
    1424         mAddress = NULL;
    1425     }
    1426 }
    1427 
    1428 ulong VBoxVHWASurfaceBase::memSize()
    1429 {
    1430     return (ulong)mImage->memSize();
    1431 }
    1432 
    1433 void VBoxVHWASurfaceBase::init(VBoxVHWASurfaceBase * pPrimary, uchar *pvMem)
    1434 {
    1435     if (pPrimary)
    1436     {
    1437         VBOXQGL_CHECKERR(
    1438                 vboxglActiveTexture(GL_TEXTURE1);
    1439             );
    1440     }
    1441 
    1442     int size = memSize();
    1443     uchar * address = (uchar *)malloc(size);
    1444 #ifdef DEBUG_misha
    1445     int tex0Size = mImage->component(0)->memSize();
    1446     if (pPrimary)
    1447     {
    1448         memset(address, 0xff, tex0Size);
    1449         Assert(size >= tex0Size);
    1450         if (size > tex0Size)
    1451             memset(address + tex0Size, 0x0, size - tex0Size);
    1452     }
    1453     else
    1454     {
    1455         memset(address, 0x0f, tex0Size);
    1456         Assert(size >= tex0Size);
    1457         if (size > tex0Size)
    1458             memset(address + tex0Size, 0x3f, size - tex0Size);
    1459     }
    1460 #else
    1461     memset(address, 0, size);
    1462 #endif
    1463 
    1464     mImage->init(address);
    1465     mpPrimary = pPrimary;
    1466 
    1467     if (pvMem)
    1468     {
    1469         mAddress = pvMem;
    1470         free(address);
    1471         mFreeAddress = false;
    1472 
    1473     }
    1474     else
    1475     {
    1476         mAddress = address;
    1477         mFreeAddress = true;
    1478     }
    1479 
    1480     mImage->setAddress(mAddress);
    1481 
    1482     initDisplay();
    1483 
    1484     mUpdateMem2TexRect.set(mRect);
    1485     Assert(!mUpdateMem2TexRect.isClear());
    1486     Assert(mRect.contains(mUpdateMem2TexRect.rect()));
    1487 
    1488     if (pPrimary)
    1489     {
    1490         VBOXQGLLOG(("restoring to tex 0"));
    1491         VBOXQGL_CHECKERR(
    1492                 vboxglActiveTexture(GL_TEXTURE0);
    1493             );
    1494     }
    1495 
    1496 }
    1497 
    1498 void VBoxVHWATexture::doUpdate(uchar *pAddress, const QRect *pRect)
    1499 {
    1500     GLenum tt = texTarget();
    1501     if (pRect)
    1502         Assert(mRect.contains(*pRect));
    1503     else
    1504         pRect = &mRect;
    1505 
    1506     Assert(glIsTexture(mTexture));
    1507     VBOXQGL_CHECKERR(
    1508             glBindTexture(tt, mTexture);
    1509             );
    1510 
    1511     int x = pRect->x()/mColorFormat.widthCompression();
    1512     int y = pRect->y()/mColorFormat.heightCompression();
    1513     int width = pRect->width()/mColorFormat.widthCompression();
    1514     int height = pRect->height()/mColorFormat.heightCompression();
    1515 
    1516     uchar *address = pAddress + pointOffsetTex(x, y);
    1517 
    1518     VBOXQGL_CHECKERR(
    1519             glPixelStorei(GL_UNPACK_ROW_LENGTH, mBytesPerLine * 8 /mColorFormat.bitsPerPixelTex());
    1520             );
    1521 
    1522     VBOXQGL_CHECKERR(
    1523             glTexSubImage2D(tt,
    1524                 0,
    1525                 x, y, width, height,
    1526                 mColorFormat.format(),
    1527                 mColorFormat.type(),
    1528                 address);
    1529             );
    1530 
    1531     VBOXQGL_CHECKERR(
    1532             glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
    1533             );
    1534 }
    1535 
    1536 void VBoxVHWATexture::texCoord(int x, int y)
    1537 {
    1538     glTexCoord2f(((float)x)/mTexRect.width()/mColorFormat.widthCompression(),
    1539                  ((float)y)/mTexRect.height()/mColorFormat.heightCompression());
    1540 }
    1541 
    1542 void VBoxVHWATexture::multiTexCoord(GLenum texUnit, int x, int y)
    1543 {
    1544     vboxglMultiTexCoord2f(texUnit, ((float)x)/mTexRect.width()/mColorFormat.widthCompression(),
    1545                           ((float)y)/mTexRect.height()/mColorFormat.heightCompression());
    1546 }
    1547 
    1548 void VBoxVHWATexture::uninit()
    1549 {
    1550     if (mTexture)
    1551         glDeleteTextures(1,&mTexture);
    1552 }
    1553 
    1554 VBoxVHWATexture::VBoxVHWATexture(const QRect & aRect, const VBoxVHWAColorFormat &aFormat,
    1555                                  uint32_t bytesPerLine, GLint scaleFuncttion)
    1556     : mAddress(NULL)
    1557     , mTexture(0)
    1558     , mBytesPerPixel(0)
    1559     , mBytesPerPixelTex(0)
    1560     , mBytesPerLine(0)
    1561     , mScaleFuncttion(scaleFuncttion)
    1562 {
    1563     mColorFormat      = aFormat;
    1564     mRect             = aRect;
    1565     mBytesPerPixel    = mColorFormat.bitsPerPixel() / 8;
    1566     mBytesPerPixelTex = mColorFormat.bitsPerPixelTex() / 8;
    1567     mBytesPerLine     = bytesPerLine ? bytesPerLine : mBytesPerPixel * mRect.width();
    1568     GLsizei wdt       = VBoxVHWASurfaceBase::makePowerOf2(mRect.width() / mColorFormat.widthCompression());
    1569     GLsizei hgt       = VBoxVHWASurfaceBase::makePowerOf2(mRect.height() / mColorFormat.heightCompression());
    1570     mTexRect = QRect(0,0,wdt,hgt);
    1571 }
    1572 
    1573 #ifdef DEBUG_misha
    1574 void VBoxVHWATexture::dbgDump()
    1575 {
    1576 #if 0
    1577     bind();
    1578     GLvoid *pvBuf = malloc(4 * mRect.width() * mRect.height());
    1579     VBOXQGL_CHECKERR(
    1580         glGetTexImage(texTarget(),
    1581             0, /*GLint level*/
    1582             mColorFormat.format(),
    1583             mColorFormat.type(),
    1584             pvBuf);
    1585     );
    1586     VBOXQGLDBGPRINT(("<?dml?><exec cmd=\"!vbvdbg.ms 0x%p 0n%d 0n%d\">texture info</exec>\n",
    1587             pvBuf, mRect.width(), mRect.height()));
    1588     AssertFailed();
    1589 
    1590     free(pvBuf);
    1591 #endif
    1592 }
    1593 #endif
    1594 
    1595 
    1596 void VBoxVHWATexture::initParams()
    1597 {
    1598     GLenum tt = texTarget();
    1599 
    1600     glTexParameteri(tt, GL_TEXTURE_MIN_FILTER, mScaleFuncttion);
    1601     VBOXQGL_ASSERTNOERR();
    1602     glTexParameteri(tt, GL_TEXTURE_MAG_FILTER, mScaleFuncttion);
    1603     VBOXQGL_ASSERTNOERR();
    1604     glTexParameteri(tt, GL_TEXTURE_WRAP_S, GL_CLAMP);
    1605     VBOXQGL_ASSERTNOERR();
    1606 
    1607     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    1608     VBOXQGL_ASSERTNOERR();
    1609     glPixelStorei(GL_PACK_ALIGNMENT, 1);
    1610     VBOXQGL_ASSERTNOERR();
    1611 
    1612     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
    1613     VBOXQGL_ASSERTNOERR();
    1614 }
    1615 
    1616 void VBoxVHWATexture::load()
    1617 {
    1618     VBOXQGL_CHECKERR(
    1619             glPixelStorei(GL_UNPACK_ROW_LENGTH, mTexRect.width());
    1620             );
    1621 
    1622     VBOXQGL_CHECKERR(
    1623         glTexImage2D(texTarget(),
    1624                 0,
    1625                   mColorFormat.internalFormat(),
    1626                   mTexRect.width(),
    1627                   mTexRect.height(),
    1628                   0,
    1629                   mColorFormat.format(),
    1630                   mColorFormat.type(),
    1631                   (GLvoid *)mAddress);
    1632         );
    1633 }
    1634 
    1635 void VBoxVHWATexture::init(uchar *pvMem)
    1636 {
    1637 //    GLsizei wdt = mTexRect.width();
    1638 //    GLsizei hgt = mTexRect.height();
    1639 
    1640     VBOXQGL_CHECKERR(
    1641             glGenTextures(1, &mTexture);
    1642         );
    1643 
    1644     VBOXQGLLOG(("tex: %d", mTexture));
    1645 
    1646     bind();
    1647 
    1648     initParams();
    1649 
    1650     setAddress(pvMem);
    1651 
    1652     load();
    1653 }
    1654 
    1655 VBoxVHWATexture::~VBoxVHWATexture()
    1656 {
    1657     uninit();
    1658 }
    1659 
    1660 void VBoxVHWATextureNP2Rect::texCoord(int x, int y)
    1661 {
    1662     glTexCoord2i(x/mColorFormat.widthCompression(), y/mColorFormat.heightCompression());
    1663 }
    1664 
    1665 void VBoxVHWATextureNP2Rect::multiTexCoord(GLenum texUnit, int x, int y)
    1666 {
    1667     vboxglMultiTexCoord2i(texUnit, x/mColorFormat.widthCompression(), y/mColorFormat.heightCompression());
    1668 }
    1669 
    1670 GLenum VBoxVHWATextureNP2Rect::texTarget()
    1671 {
    1672     return GL_TEXTURE_RECTANGLE;
    1673 }
    1674 
    1675 bool VBoxVHWASurfaceBase::synchTexMem(const QRect * pRect)
    1676 {
    1677     if (pRect)
    1678         Assert(mRect.contains(*pRect));
    1679 
    1680     if (mUpdateMem2TexRect.isClear())
    1681         return false;
    1682 
    1683     if (pRect && !mUpdateMem2TexRect.rect().intersects(*pRect))
    1684         return false;
    1685 
    1686 #ifdef VBOXVHWA_PROFILE_FPS
    1687     mpImage->reportNewFrame();
    1688 #endif
    1689 
    1690     mImage->update(&mUpdateMem2TexRect.rect());
    1691 
    1692     mUpdateMem2TexRect.clear();
    1693     Assert(mUpdateMem2TexRect.isClear());
    1694 
    1695     return true;
    1696 }
    1697 
    1698 void VBoxVHWATextureNP2RectPBO::init(uchar *pvMem)
    1699 {
    1700     VBOXQGL_CHECKERR(
    1701             vboxglGenBuffers(1, &mPBO);
    1702             );
    1703     VBoxVHWATextureNP2Rect::init(pvMem);
    1704 }
    1705 
    1706 void VBoxVHWATextureNP2RectPBO::doUpdate(uchar *pAddress, const QRect *pRect)
    1707 {
    1708     Q_UNUSED(pAddress);
    1709     Q_UNUSED(pRect);
    1710 
    1711     vboxglBindBuffer(GL_PIXEL_UNPACK_BUFFER, mPBO);
    1712 
    1713     GLvoid *buf;
    1714 
    1715     VBOXQGL_CHECKERR(
    1716             buf = vboxglMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
    1717             );
    1718     Assert(buf);
    1719     if (buf)
    1720     {
    1721         memcpy(buf, mAddress, memSize());
    1722 
    1723         bool unmapped;
    1724         VBOXQGL_CHECKERR(
    1725                 unmapped = vboxglUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
    1726                 );
    1727 
    1728         Assert(unmapped); NOREF(unmapped);
    1729 
    1730         VBoxVHWATextureNP2Rect::doUpdate(0, &mRect);
    1731 
    1732         vboxglBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
    1733     }
    1734     else
    1735     {
    1736         VBOXQGLLOGREL(("failed to map PBO, trying fallback to non-PBO approach\n"));
    1737         /* try fallback to non-PBO approach */
    1738         vboxglBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
    1739         VBoxVHWATextureNP2Rect::doUpdate(pAddress, pRect);
    1740     }
    1741 }
    1742 
    1743 VBoxVHWATextureNP2RectPBO::~VBoxVHWATextureNP2RectPBO()
    1744 {
    1745     VBOXQGL_CHECKERR(
    1746             vboxglDeleteBuffers(1, &mPBO);
    1747             );
    1748 }
    1749 
    1750 
    1751 void VBoxVHWATextureNP2RectPBO::load()
    1752 {
    1753     VBoxVHWATextureNP2Rect::load();
    1754 
    1755     VBOXQGL_CHECKERR(
    1756             vboxglBindBuffer(GL_PIXEL_UNPACK_BUFFER, mPBO);
    1757         );
    1758 
    1759     VBOXQGL_CHECKERR(
    1760             vboxglBufferData(GL_PIXEL_UNPACK_BUFFER, memSize(), NULL, GL_STREAM_DRAW);
    1761         );
    1762 
    1763     GLvoid *buf = vboxglMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
    1764     Assert(buf);
    1765     if (buf)
    1766     {
    1767         memcpy(buf, mAddress, memSize());
    1768 
    1769         bool unmapped = vboxglUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
    1770         Assert(unmapped); NOREF(unmapped);
    1771     }
    1772 
    1773     vboxglBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
    1774 }
    1775 
    1776 uchar* VBoxVHWATextureNP2RectPBOMapped::mapAlignedBuffer()
    1777 {
    1778     Assert(!mpMappedAllignedBuffer);
    1779     if (!mpMappedAllignedBuffer)
    1780     {
    1781         VBOXQGL_CHECKERR(
    1782                 vboxglBindBuffer(GL_PIXEL_UNPACK_BUFFER, mPBO);
    1783             );
    1784 
    1785         uchar* buf;
    1786         VBOXQGL_CHECKERR(
    1787                 buf = (uchar*)vboxglMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_READ_WRITE);
    1788         );
    1789 
    1790         Assert(buf);
    1791 
    1792         VBOXQGL_CHECKERR(
    1793                 vboxglBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
    1794             );
    1795 
    1796         mpMappedAllignedBuffer = (uchar*)alignBuffer(buf);
    1797 
    1798         mcbOffset = calcOffset(buf, mpMappedAllignedBuffer);
    1799     }
    1800     return mpMappedAllignedBuffer;
    1801 }
    1802 
    1803 void VBoxVHWATextureNP2RectPBOMapped::unmapBuffer()
    1804 {
    1805     Assert(mpMappedAllignedBuffer);
    1806     if (mpMappedAllignedBuffer)
    1807     {
    1808         VBOXQGL_CHECKERR(
    1809                 vboxglBindBuffer(GL_PIXEL_UNPACK_BUFFER, mPBO);
    1810         );
    1811 
    1812         bool unmapped;
    1813         VBOXQGL_CHECKERR(
    1814                 unmapped = vboxglUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
    1815                 );
    1816 
    1817         Assert(unmapped); NOREF(unmapped);
    1818 
    1819         VBOXQGL_CHECKERR(
    1820                 vboxglBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
    1821         );
    1822 
    1823         mpMappedAllignedBuffer = NULL;
    1824     }
    1825 }
    1826 
    1827 void VBoxVHWATextureNP2RectPBOMapped::load()
    1828 {
    1829     VBoxVHWATextureNP2Rect::load();
    1830 
    1831     VBOXQGL_CHECKERR(
    1832             vboxglBindBuffer(GL_PIXEL_UNPACK_BUFFER, mPBO);
    1833         );
    1834 
    1835     VBOXQGL_CHECKERR(
    1836             vboxglBufferData(GL_PIXEL_UNPACK_BUFFER, mcbActualBufferSize, NULL, GL_STREAM_DRAW);
    1837         );
    1838 
    1839     vboxglBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
    1840 }
    1841 
    1842 void VBoxVHWATextureNP2RectPBOMapped::doUpdate(uchar *pAddress, const QRect *pRect)
    1843 {
    1844     Q_UNUSED(pAddress);
    1845     Q_UNUSED(pRect);
    1846 
    1847     VBOXQGL_CHECKERR(
    1848             vboxglBindBuffer(GL_PIXEL_UNPACK_BUFFER, mPBO);
    1849     );
    1850 
    1851     if (mpMappedAllignedBuffer)
    1852     {
    1853         bool unmapped;
    1854         VBOXQGL_CHECKERR(
    1855                 unmapped = vboxglUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
    1856                 );
    1857 
    1858         Assert(unmapped); NOREF(unmapped);
    1859 
    1860         mpMappedAllignedBuffer = NULL;
    1861     }
    1862 
    1863     VBoxVHWATextureNP2Rect::doUpdate((uchar *)mcbOffset, &mRect);
    1864 
    1865     VBOXQGL_CHECKERR(
    1866             vboxglBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
    1867     );
    1868 }
    1869 
    1870 int VBoxVHWASurfaceBase::lock(const QRect *pRect, uint32_t flags)
    1871 {
    1872     Q_UNUSED(flags);
    1873 
    1874     if (pRect)
    1875         Assert(mRect.contains(*pRect));
    1876 
    1877     Assert(mLockCount >= 0);
    1878     if (pRect && pRect->isEmpty())
    1879         return VERR_GENERAL_FAILURE;
    1880     if (mLockCount < 0)
    1881         return VERR_GENERAL_FAILURE;
    1882 
    1883     VBOXQGLLOG(("lock (0x%x)", this));
    1884     VBOXQGLLOG_QRECT("rect: ", pRect ? pRect : &mRect, "\n");
    1885     VBOXQGLLOG_METHODTIME("time ");
    1886 
    1887     mUpdateMem2TexRect.add(pRect ? *pRect : mRect);
    1888 
    1889     Assert(!mUpdateMem2TexRect.isClear());
    1890     Assert(mRect.contains(mUpdateMem2TexRect.rect()));
    1891     return VINF_SUCCESS;
    1892 }
    1893 
    1894 int VBoxVHWASurfaceBase::unlock()
    1895 {
    1896     VBOXQGLLOG(("unlock (0x%x)\n", this));
    1897     mLockCount = 0;
    1898     return VINF_SUCCESS;
    1899 }
    1900 
    1901 void VBoxVHWASurfaceBase::setRectValues (const QRect &aTargRect, const QRect &aSrcRect)
    1902 {
    1903     mTargRect = aTargRect;
    1904     mSrcRect = aSrcRect;
    1905 }
    1906 
    1907 void VBoxVHWASurfaceBase::setVisibleRectValues (const QRect &aVisTargRect)
    1908 {
    1909     mVisibleTargRect = aVisTargRect.intersected(mTargRect);
    1910     if (mVisibleTargRect.isEmpty() || mTargRect.isEmpty())
    1911         mVisibleSrcRect.setSize(QSize(0, 0));
    1912     else
    1913     {
    1914         float stretchX = float(mSrcRect.width()) / mTargRect.width();
    1915         float stretchY = float(mSrcRect.height()) / mTargRect.height();
    1916         int tx1, tx2, ty1, ty2, vtx1, vtx2, vty1, vty2;
    1917         int sx1, sx2, sy1, sy2;
    1918         mVisibleTargRect.getCoords(&vtx1, &vty1, &vtx2, &vty2);
    1919         mTargRect.getCoords(&tx1, &ty1, &tx2, &ty2);
    1920         mSrcRect.getCoords(&sx1, &sy1, &sx2, &sy2);
    1921         int dx1 = vtx1 - tx1;
    1922         int dy1 = vty1 - ty1;
    1923         int dx2 = vtx2 - tx2;
    1924         int dy2 = vty2 - ty2;
    1925         int vsx1, vsy1, vsx2, vsy2;
    1926         Assert(dx1 >= 0);
    1927         Assert(dy1 >= 0);
    1928         Assert(dx2 <= 0);
    1929         Assert(dy2 <= 0);
    1930         vsx1 = sx1 + int(dx1*stretchX);
    1931         vsy1 = sy1 + int(dy1*stretchY);
    1932         vsx2 = sx2 + int(dx2*stretchX);
    1933         vsy2 = sy2 + int(dy2*stretchY);
    1934         mVisibleSrcRect.setCoords(vsx1, vsy1, vsx2, vsy2);
    1935         Assert(!mVisibleSrcRect.isEmpty());
    1936         Assert(mSrcRect.contains(mVisibleSrcRect));
    1937     }
    1938 }
    1939 
    1940 
    1941 void VBoxVHWASurfaceBase::setRects(const QRect & aTargRect, const QRect & aSrcRect)
    1942 {
    1943     if (mTargRect != aTargRect || mSrcRect != aSrcRect)
    1944         setRectValues(aTargRect, aSrcRect);
    1945 }
    1946 
    1947 void VBoxVHWASurfaceBase::setTargRectPosition(const QPoint & aPoint)
    1948 {
    1949     QRect tRect = targRect();
    1950     tRect.moveTopLeft(aPoint);
    1951     setRects(tRect, srcRect());
    1952 }
    1953 
    1954 void VBoxVHWASurfaceBase::updateVisibility(VBoxVHWASurfaceBase *pPrimary, const QRect & aVisibleTargRect,
    1955                                            bool bNotIntersected, bool bForce)
    1956 {
    1957     if (bForce || aVisibleTargRect.intersected(mTargRect) != mVisibleTargRect)
    1958         setVisibleRectValues(aVisibleTargRect);
    1959 
    1960     mpPrimary = pPrimary;
    1961     mbNotIntersected = bNotIntersected;
    1962 
    1963     initDisplay();
    1964 }
    1965 
    1966 void VBoxVHWASurfaceBase::initDisplay()
    1967 {
    1968     if (mVisibleTargRect.isEmpty() || mVisibleSrcRect.isEmpty())
    1969     {
    1970         Assert(mVisibleTargRect.isEmpty() && mVisibleSrcRect.isEmpty());
    1971         mImage->deleteDisplay();
    1972         return;
    1973     }
    1974 
    1975     int rc = mImage->initDisplay(mpPrimary ? mpPrimary->mImage : NULL, &mVisibleTargRect, &mVisibleSrcRect,
    1976                                  getActiveDstOverlayCKey(mpPrimary), getActiveSrcOverlayCKey(), mbNotIntersected);
    1977     AssertRC(rc);
    1978 }
    1979 
    1980 void VBoxVHWASurfaceBase::updatedMem(const QRect *rec)
    1981 {
    1982     if (rec)
    1983         Assert(mRect.contains(*rec));
    1984     mUpdateMem2TexRect.add(*rec);
    1985 }
    1986 
    1987 bool VBoxVHWASurfaceBase::performDisplay(VBoxVHWASurfaceBase *pPrimary, bool bForce)
    1988 {
    1989     Assert(mImage->displayInitialized());
    1990 
    1991     if (mVisibleTargRect.isEmpty())
    1992     {
    1993         /* nothing to display, i.e. the surface is not visible,
    1994          * in the sense that it's located behind the viewport ranges */
    1995         Assert(mVisibleSrcRect.isEmpty());
    1996         return false;
    1997     }
    1998     Assert(!mVisibleSrcRect.isEmpty());
    1999 
    2000     bForce |= synchTexMem(&mVisibleSrcRect);
    2001 
    2002     const VBoxVHWAColorKey * pDstCKey = getActiveDstOverlayCKey(pPrimary);
    2003     if (pPrimary && pDstCKey)
    2004         bForce |= pPrimary->synchTexMem(&mVisibleTargRect);
    2005 
    2006     if (!bForce)
    2007         return false;
    2008 
    2009     mImage->display();
    2010 
    2011     Assert(bForce);
    2012     return true;
    2013 }
    2014 
    2015 class VBoxVHWAGlProgramMngr * VBoxVHWASurfaceBase::getGlProgramMngr()
    2016 {
    2017     return mpImage->vboxVHWAGetGlProgramMngr();
    2018 }
    2019 
    2020 class VBoxGLContext : public QGLContext
    2021 {
    2022 public:
    2023     VBoxGLContext (const QGLFormat & format )
    2024         : QGLContext(format)
    2025         , mAllowDoneCurrent(true)
    2026     {
    2027     }
    2028 
    2029     void doneCurrent()
    2030     {
    2031         if (!mAllowDoneCurrent)
    2032             return;
    2033         QGLContext::doneCurrent();
    2034     }
    2035 
    2036     bool isDoneCurrentAllowed() { return mAllowDoneCurrent; }
    2037     void allowDoneCurrent(bool bAllow) { mAllowDoneCurrent = bAllow; }
    2038 private:
    2039     bool mAllowDoneCurrent;
    2040 };
    2041 
    2042 
    2043 VBoxGLWgt::VBoxGLWgt(VBoxVHWAImage *pImage, QWidget *parent, const QGLWidget *shareWidget)
    2044     : QGLWidget(new VBoxGLContext(shareWidget->format()), parent, shareWidget)
    2045     , mpImage(pImage)
    2046 {
    2047     /* work-around to disable done current needed to old ATI drivers on Linux */
    2048     VBoxGLContext *pc = (VBoxGLContext *)context();
    2049     pc->allowDoneCurrent (false);
    2050     Assert(isSharing());
    2051 }
    2052 
    2053 
    2054 VBoxVHWAImage::VBoxVHWAImage ()
    2055     : mSurfHandleTable(128) /* 128 should be enough */
    2056     , mRepaintNeeded(false)
    2057 //  ,  mbVGASurfCreated(false)
    2058     , mConstructingList(NULL)
    2059     , mcRemaining2Contruct(0)
    2060     , mSettings(NULL)
    2061 #ifdef VBOXVHWA_PROFILE_FPS
    2062     , mFPSCounter(64)
    2063     , mbNewFrame(false)
    2064 #endif
    2065 {
    2066     mpMngr = new VBoxVHWAGlProgramMngr();
    2067 //        /* No need for background drawing */
    2068 //        setAttribute (Qt::WA_OpaquePaintEvent);
    2069 }
    2070 
    2071 int VBoxVHWAImage::init(VBoxVHWASettings *aSettings)
    2072 {
    2073     mSettings = aSettings;
    2074     return VINF_SUCCESS;
    2075 }
    2076 
    2077 const QGLFormat &VBoxVHWAImage::vboxGLFormat()
    2078 {
    2079     static QGLFormat vboxFormat = QGLFormat();
    2080     vboxFormat.setAlpha(true);
    2081     Assert(vboxFormat.alpha());
    2082     vboxFormat.setSwapInterval(0);
    2083     Assert(vboxFormat.swapInterval() == 0);
    2084     vboxFormat.setAccum(false);
    2085     Assert(!vboxFormat.accum());
    2086     vboxFormat.setDepth(false);
    2087     Assert(!vboxFormat.depth());
    2088 //  vboxFormat.setRedBufferSize(8);
    2089 //  vboxFormat.setGreenBufferSize(8);
    2090 //  vboxFormat.setBlueBufferSize(8);
    2091     return vboxFormat;
    2092 }
    2093 
    2094 
    2095 VBoxVHWAImage::~VBoxVHWAImage()
    2096 {
    2097     delete mpMngr;
    2098 }
    2099 
    2100 #ifdef VBOXVHWA_OLD_COORD
    2101 void VBoxVHWAImage::doSetupMatrix(const QSize &aSize, bool bInverted)
    2102 {
    2103     VBOXQGL_CHECKERR(
    2104             glLoadIdentity();
    2105             );
    2106     if (bInverted)
    2107     {
    2108         VBOXQGL_CHECKERR(
    2109                 glScalef(1.0f / aSize.width(), 1.0f / aSize.height(), 1.0f);
    2110                 );
    2111     }
    2112     else
    2113     {
    2114         /* make display coordinates be scaled to pixel coordinates */
    2115         VBOXQGL_CHECKERR(
    2116                 glTranslatef(0.0f, 1.0f, 0.0f);
    2117                 );
    2118         VBOXQGL_CHECKERR(
    2119                 glScalef(1.0f / aSize.width(), 1.0f / aSize.height(), 1.0f);
    2120                 );
    2121         VBOXQGL_CHECKERR(
    2122                 glRotatef(180.0f, 1.0f, 0.0f, 0.0f);
    2123                 );
    2124     }
    2125 }
    2126 #endif
    2127 
    2128 void VBoxVHWAImage::adjustViewport(const QSize &display, const QRect &viewport)
    2129 {
    2130     glViewport(-viewport.x(),
    2131                viewport.height() + viewport.y() - display.height(),
    2132                display.width(),
    2133                display.height());
    2134 }
    2135 
    2136 void VBoxVHWAImage::setupMatricies(const QSize &display, bool bInverted)
    2137 {
    2138     glMatrixMode(GL_PROJECTION);
    2139     glLoadIdentity();
    2140 
    2141     if (bInverted)
    2142         glOrtho(0., (GLdouble)display.width(), (GLdouble)display.height(), 0., -1., 1.);
    2143     else
    2144         glOrtho(0., (GLdouble)display.width(), 0., (GLdouble)display.height(), -1., 1.);
    2145 
    2146     glMatrixMode(GL_MODELVIEW);
    2147     glLoadIdentity();
    2148 }
    2149 
    2150 int VBoxVHWAImage::reset(VHWACommandList *pCmdList)
    2151 {
    2152     VBOXVHWACMD *pCmd;
    2153     const OverlayList & overlays = mDisplay.overlays();
    2154     for (OverlayList::const_iterator oIt = overlays.begin(); oIt != overlays.end(); ++ oIt)
    2155     {
    2156         VBoxVHWASurfList * pSurfList = *oIt;
    2157         if (pSurfList->current())
    2158         {
    2159             /* 1. hide overlay */
    2160             pCmd = vhwaHHCmdCreate(VBOXVHWACMD_TYPE_SURF_OVERLAY_UPDATE, sizeof(VBOXVHWACMD_SURF_OVERLAY_UPDATE));
    2161             VBOXVHWACMD_SURF_OVERLAY_UPDATE RT_UNTRUSTED_VOLATILE_GUEST *pOUCmd = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_OVERLAY_UPDATE);
    2162             pOUCmd->u.in.hSrcSurf = pSurfList->current()->handle();
    2163             pOUCmd->u.in.flags = VBOXVHWA_OVER_HIDE;
    2164 
    2165             pCmdList->push_back(pCmd);
    2166         }
    2167 
    2168         /* 2. destroy overlay */
    2169         const SurfList & surfaces = pSurfList->surfaces();
    2170         for (SurfList::const_iterator sIt = surfaces.begin(); sIt != surfaces.end(); ++ sIt)
    2171         {
    2172             VBoxVHWASurfaceBase *pCurSurf = (*sIt);
    2173             pCmd = vhwaHHCmdCreate(VBOXVHWACMD_TYPE_SURF_DESTROY, sizeof(VBOXVHWACMD_SURF_DESTROY));
    2174             VBOXVHWACMD_SURF_DESTROY RT_UNTRUSTED_VOLATILE_GUEST *pSDCmd = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_DESTROY);
    2175             pSDCmd->u.in.hSurf = pCurSurf->handle();
    2176 
    2177             pCmdList->push_back(pCmd);
    2178         }
    2179     }
    2180 
    2181     /* 3. destroy primaries */
    2182     const SurfList & surfaces = mDisplay.primaries().surfaces();
    2183     for (SurfList::const_iterator sIt = surfaces.begin(); sIt != surfaces.end(); ++ sIt)
    2184     {
    2185         VBoxVHWASurfaceBase *pCurSurf = (*sIt);
    2186         if (pCurSurf->handle() != VBOXVHWA_SURFHANDLE_INVALID)
    2187         {
    2188             pCmd = vhwaHHCmdCreate(VBOXVHWACMD_TYPE_SURF_DESTROY, sizeof(VBOXVHWACMD_SURF_DESTROY));
    2189             VBOXVHWACMD_SURF_DESTROY RT_UNTRUSTED_VOLATILE_GUEST *pSDCmd = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_DESTROY);
    2190             pSDCmd->u.in.hSurf = pCurSurf->handle();
    2191 
    2192             pCmdList->push_back(pCmd);
    2193         }
    2194     }
    2195 
    2196     return VINF_SUCCESS;
    2197 }
    2198 
    2199 #ifdef VBOX_WITH_VIDEOHWACCEL
    2200 int VBoxVHWAImage::vhwaSurfaceCanCreate(struct VBOXVHWACMD_SURF_CANCREATE RT_UNTRUSTED_VOLATILE_GUEST *pCmd)
    2201 {
    2202     VBOXQGLLOG_ENTER(("\n"));
    2203 
    2204     const VBoxVHWAInfo & info = vboxVHWAGetSupportInfo(NULL);
    2205 
    2206     if (!(pCmd->SurfInfo.flags & VBOXVHWA_SD_CAPS))
    2207     {
    2208         AssertFailed();
    2209         pCmd->u.out.ErrInfo = -1;
    2210         return VINF_SUCCESS;
    2211     }
    2212 #ifdef VBOXVHWA_ALLOW_PRIMARY_AND_OVERLAY_ONLY
    2213     if (pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_OFFSCREENPLAIN)
    2214     {
    2215 #ifdef DEBUGVHWASTRICT
    2216         AssertFailed();
    2217 #endif
    2218         pCmd->u.out.ErrInfo = -1;
    2219         return VINF_SUCCESS;
    2220     }
    2221 #endif
    2222 
    2223     if (pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_PRIMARYSURFACE)
    2224     {
    2225         if (pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_COMPLEX)
    2226         {
    2227 #ifdef DEBUG_misha
    2228             AssertFailed();
    2229 #endif
    2230             pCmd->u.out.ErrInfo = -1;
    2231         }
    2232         else
    2233         {
    2234             pCmd->u.out.ErrInfo = 0;
    2235         }
    2236         return VINF_SUCCESS;
    2237     }
    2238 
    2239 #ifdef VBOXVHWA_ALLOW_PRIMARY_AND_OVERLAY_ONLY
    2240     if ((pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_OVERLAY) == 0)
    2241     {
    2242 #ifdef DEBUGVHWASTRICT
    2243         AssertFailed();
    2244 #endif
    2245         pCmd->u.out.ErrInfo = -1;
    2246         return VINF_SUCCESS;
    2247     }
    2248 #endif
    2249 
    2250     if (pCmd->u.in.bIsDifferentPixelFormat)
    2251     {
    2252         if (!(pCmd->SurfInfo.flags & VBOXVHWA_SD_PIXELFORMAT))
    2253         {
    2254             AssertFailed();
    2255             pCmd->u.out.ErrInfo = -1;
    2256             return VINF_SUCCESS;
    2257         }
    2258 
    2259         if (pCmd->SurfInfo.PixelFormat.flags & VBOXVHWA_PF_RGB)
    2260         {
    2261             if (pCmd->SurfInfo.PixelFormat.c.rgbBitCount != 32
    2262                     && pCmd->SurfInfo.PixelFormat.c.rgbBitCount != 24)
    2263             {
    2264                 AssertFailed();
    2265                 pCmd->u.out.ErrInfo = -1;
    2266                 return VINF_SUCCESS;
    2267             }
    2268         }
    2269         else if (pCmd->SurfInfo.PixelFormat.flags & VBOXVHWA_PF_FOURCC)
    2270         {
    2271             /* detect whether we support this format */
    2272             bool bFound = mSettings->isSupported (info, pCmd->SurfInfo.PixelFormat.fourCC);
    2273 
    2274             if (!bFound)
    2275             {
    2276                 VBOXQGLLOG (("!!unsupported fourcc!!!: %c%c%c%c\n",
    2277                              (pCmd->SurfInfo.PixelFormat.fourCC & 0x000000ff),
    2278                              (pCmd->SurfInfo.PixelFormat.fourCC & 0x0000ff00) >> 8,
    2279                              (pCmd->SurfInfo.PixelFormat.fourCC & 0x00ff0000) >> 16,
    2280                              (pCmd->SurfInfo.PixelFormat.fourCC & 0xff000000) >> 24
    2281                              ));
    2282                 pCmd->u.out.ErrInfo = -1;
    2283                 return VINF_SUCCESS;
    2284             }
    2285         }
    2286         else
    2287         {
    2288             AssertFailed();
    2289             pCmd->u.out.ErrInfo = -1;
    2290             return VINF_SUCCESS;
    2291         }
    2292     }
    2293 
    2294     pCmd->u.out.ErrInfo = 0;
    2295     return VINF_SUCCESS;
    2296 }
    2297 
    2298 int VBoxVHWAImage::vhwaSurfaceCreate(struct VBOXVHWACMD_SURF_CREATE RT_UNTRUSTED_VOLATILE_GUEST *pCmd)
    2299 {
    2300     VBOXQGLLOG_ENTER (("\n"));
    2301 
    2302     uint32_t handle = VBOXVHWA_SURFHANDLE_INVALID;
    2303     if (pCmd->SurfInfo.hSurf != VBOXVHWA_SURFHANDLE_INVALID)
    2304     {
    2305         handle = pCmd->SurfInfo.hSurf;
    2306         if (mSurfHandleTable.get(handle))
    2307         {
    2308             AssertFailed();
    2309             return VERR_GENERAL_FAILURE;
    2310         }
    2311     }
    2312 
    2313     VBoxVHWASurfaceBase *surf = NULL;
    2314     /* in case the Framebuffer is working in "not using VRAM" mode,
    2315      * we need to report the pitch, etc. info of the form guest expects from us*/
    2316     VBoxVHWAColorFormat reportedFormat;
    2317     /* paranoia to ensure the VBoxVHWAColorFormat API works properly */
    2318     Assert(!reportedFormat.isValid());
    2319     bool bNoPBO = false;
    2320     bool bPrimary = false;
    2321 
    2322     VBoxVHWAColorKey *pDstBltCKey = NULL, DstBltCKey;
    2323     VBoxVHWAColorKey *pSrcBltCKey = NULL, SrcBltCKey;
    2324     VBoxVHWAColorKey *pDstOverlayCKey = NULL, DstOverlayCKey;
    2325     VBoxVHWAColorKey *pSrcOverlayCKey = NULL, SrcOverlayCKey;
    2326     if (pCmd->SurfInfo.flags & VBOXVHWA_SD_CKDESTBLT)
    2327     {
    2328         DstBltCKey = VBoxVHWAColorKey(pCmd->SurfInfo.DstBltCK.high, pCmd->SurfInfo.DstBltCK.low);
    2329         pDstBltCKey = &DstBltCKey;
    2330     }
    2331     if (pCmd->SurfInfo.flags & VBOXVHWA_SD_CKSRCBLT)
    2332     {
    2333         SrcBltCKey = VBoxVHWAColorKey(pCmd->SurfInfo.SrcBltCK.high, pCmd->SurfInfo.SrcBltCK.low);
    2334         pSrcBltCKey = &SrcBltCKey;
    2335     }
    2336     if (pCmd->SurfInfo.flags & VBOXVHWA_SD_CKDESTOVERLAY)
    2337     {
    2338         DstOverlayCKey = VBoxVHWAColorKey(pCmd->SurfInfo.DstOverlayCK.high, pCmd->SurfInfo.DstOverlayCK.low);
    2339         pDstOverlayCKey = &DstOverlayCKey;
    2340     }
    2341     if (pCmd->SurfInfo.flags & VBOXVHWA_SD_CKSRCOVERLAY)
    2342     {
    2343         SrcOverlayCKey = VBoxVHWAColorKey(pCmd->SurfInfo.SrcOverlayCK.high, pCmd->SurfInfo.SrcOverlayCK.low);
    2344         pSrcOverlayCKey = &SrcOverlayCKey;
    2345     }
    2346 
    2347     if (pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_PRIMARYSURFACE)
    2348     {
    2349         bNoPBO = true;
    2350         bPrimary = true;
    2351         VBoxVHWASurfaceBase *pVga = vgaSurface();
    2352 #ifdef VBOX_WITH_WDDM
    2353         uchar * addr = vboxVRAMAddressFromOffset(pCmd->SurfInfo.offSurface);
    2354         Assert(addr);
    2355         if (addr)
    2356         {
    2357             pVga->setAddress(addr);
    2358         }
    2359 #endif
    2360 
    2361         Assert((pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_OFFSCREENPLAIN) == 0);
    2362 
    2363         reportedFormat = VBoxVHWAColorFormat(pCmd->SurfInfo.PixelFormat.c.rgbBitCount,
    2364                                              pCmd->SurfInfo.PixelFormat.m1.rgbRBitMask,
    2365                                              pCmd->SurfInfo.PixelFormat.m2.rgbGBitMask,
    2366                                              pCmd->SurfInfo.PixelFormat.m3.rgbBBitMask);
    2367 
    2368         if (pVga->handle() == VBOXVHWA_SURFHANDLE_INVALID
    2369                 && (pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_OFFSCREENPLAIN) == 0)
    2370         {
    2371             Assert(pCmd->SurfInfo.PixelFormat.flags & VBOXVHWA_PF_RGB);
    2372 //            if (pCmd->SurfInfo.PixelFormat.flags & VBOXVHWA_PF_RGB)
    2373             {
    2374                 Assert(pCmd->SurfInfo.width == pVga->width());
    2375                 Assert(pCmd->SurfInfo.height == pVga->height());
    2376 //                if (pCmd->SurfInfo.width == pVga->width()
    2377 //                        && pCmd->SurfInfo.height == pVga->height())
    2378                 {
    2379                     // the assert below is incorrect in case the Framebuffer is working in "not using VRAM" mode
    2380 //                    Assert(pVga->pixelFormat().equals(format));
    2381 //                    if (pVga->pixelFormat().equals(format))
    2382                     {
    2383                         surf = pVga;
    2384 
    2385                         surf->setDstBltCKey(pDstBltCKey);
    2386                         surf->setSrcBltCKey(pSrcBltCKey);
    2387 
    2388                         surf->setDefaultDstOverlayCKey(pDstOverlayCKey);
    2389                         surf->resetDefaultDstOverlayCKey();
    2390 
    2391                         surf->setDefaultSrcOverlayCKey(pSrcOverlayCKey);
    2392                         surf->resetDefaultSrcOverlayCKey();
    2393 //                        mbVGASurfCreated = true;
    2394                     }
    2395                 }
    2396             }
    2397         }
    2398     }
    2399     else if (pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_OFFSCREENPLAIN)
    2400     {
    2401         bNoPBO = true;
    2402     }
    2403 
    2404     if (!surf)
    2405     {
    2406         VBOXVHWAIMG_TYPE fFlags = 0;
    2407         if (!bNoPBO)
    2408         {
    2409             fFlags |= VBOXVHWAIMG_PBO | VBOXVHWAIMG_PBOIMG | VBOXVHWAIMG_LINEAR;
    2410             if (mSettings->isStretchLinearEnabled())
    2411                 fFlags |= VBOXVHWAIMG_FBO;
    2412         }
    2413 
    2414         QSize surfSize(pCmd->SurfInfo.width, pCmd->SurfInfo.height);
    2415         QRect primaryRect = mDisplay.getPrimary()->rect();
    2416         VBoxVHWAColorFormat format;
    2417         if (bPrimary)
    2418             format = mDisplay.getVGA()->pixelFormat();
    2419         else if (pCmd->SurfInfo.PixelFormat.flags & VBOXVHWA_PF_RGB)
    2420             format = VBoxVHWAColorFormat(pCmd->SurfInfo.PixelFormat.c.rgbBitCount,
    2421                                          pCmd->SurfInfo.PixelFormat.m1.rgbRBitMask,
    2422                                          pCmd->SurfInfo.PixelFormat.m2.rgbGBitMask,
    2423                                          pCmd->SurfInfo.PixelFormat.m3.rgbBBitMask);
    2424         else if (pCmd->SurfInfo.PixelFormat.flags & VBOXVHWA_PF_FOURCC)
    2425             format = VBoxVHWAColorFormat(pCmd->SurfInfo.PixelFormat.fourCC);
    2426         else
    2427             AssertFailed();
    2428 
    2429         if (format.isValid())
    2430         {
    2431             surf = new VBoxVHWASurfaceBase(this,
    2432                                            surfSize,
    2433                                            primaryRect,
    2434                                            QRect(0, 0, surfSize.width(), surfSize.height()),
    2435                                            mViewport,
    2436                                            format,
    2437                                            pSrcBltCKey, pDstBltCKey, pSrcOverlayCKey, pDstOverlayCKey,
    2438 #ifdef VBOXVHWA_USE_TEXGROUP
    2439                                            0,
    2440 #endif
    2441                                            fFlags);
    2442         }
    2443         else
    2444         {
    2445             AssertFailed();
    2446             VBOXQGLLOG_EXIT(("pSurf (0x%p)\n",surf));
    2447             return VERR_GENERAL_FAILURE;
    2448         }
    2449 
    2450         uchar *addr = vboxVRAMAddressFromOffset(pCmd->SurfInfo.offSurface);
    2451         surf->init(mDisplay.getPrimary(), addr);
    2452 
    2453         if (pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_OVERLAY)
    2454         {
    2455 #ifdef DEBUG_misha
    2456             Assert(!bNoPBO);
    2457 #endif
    2458 
    2459             if (!mConstructingList)
    2460             {
    2461                 mConstructingList = new VBoxVHWASurfList();
    2462                 mcRemaining2Contruct = pCmd->SurfInfo.cBackBuffers+1;
    2463                 mDisplay.addOverlay(mConstructingList);
    2464             }
    2465 
    2466             mConstructingList->add(surf);
    2467             mcRemaining2Contruct--;
    2468             if (!mcRemaining2Contruct)
    2469                 mConstructingList = NULL;
    2470         }
    2471         else
    2472         {
    2473             VBoxVHWASurfaceBase * pVga = vgaSurface();
    2474             Assert(pVga->handle() != VBOXVHWA_SURFHANDLE_INVALID);
    2475             Assert(pVga != surf); NOREF(pVga);
    2476             mDisplay.getVGA()->getComplexList()->add(surf);
    2477 #ifdef DEBUGVHWASTRICT
    2478             Assert(pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_VISIBLE);
    2479 #endif
    2480             if (bPrimary)
    2481             {
    2482                 Assert(surf->getComplexList() == mDisplay.getVGA()->getComplexList());
    2483                 surf->getComplexList()->setCurrentVisible(surf);
    2484                 mDisplay.updateVGA(surf);
    2485             }
    2486         }
    2487     }
    2488     else
    2489         Assert(pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_PRIMARYSURFACE);
    2490 
    2491     Assert(mDisplay.getVGA() == mDisplay.getPrimary());
    2492 
    2493     /* tell the guest how we think the memory is organized */
    2494     VBOXQGLLOG(("bps: %d\n", surf->bitsPerPixel()));
    2495 
    2496     if (!reportedFormat.isValid())
    2497     {
    2498         pCmd->SurfInfo.pitch = surf->bytesPerLine();
    2499         pCmd->SurfInfo.sizeX = surf->memSize();
    2500         pCmd->SurfInfo.sizeY = 1;
    2501     }
    2502     else
    2503     {
    2504         /* this is the case of Framebuffer not using Guest VRAM */
    2505         /* can happen for primary surface creation only */
    2506         Assert(pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_PRIMARYSURFACE);
    2507         pCmd->SurfInfo.pitch = (reportedFormat.bitsPerPixel() * surf->width() + 7) / 8;
    2508         /* we support only RGB case now, otherwise we would need more complicated mechanism of memsize calculation */
    2509         Assert(!reportedFormat.fourcc());
    2510         pCmd->SurfInfo.sizeX = (reportedFormat.bitsPerPixel() * surf->width() + 7) / 8 * surf->height();
    2511         pCmd->SurfInfo.sizeY = 1;
    2512     }
    2513 
    2514     if (handle != VBOXVHWA_SURFHANDLE_INVALID)
    2515     {
    2516         bool bSuccess = mSurfHandleTable.mapPut(handle, surf);
    2517         Assert(bSuccess);
    2518         if (!bSuccess)
    2519         {
    2520             /** @todo this is very bad, should not be here */
    2521             return VERR_GENERAL_FAILURE;
    2522         }
    2523     }
    2524     else
    2525     {
    2526         /* tell the guest our handle */
    2527         handle = mSurfHandleTable.put(surf);
    2528         pCmd->SurfInfo.hSurf = (VBOXVHWA_SURFHANDLE)handle;
    2529     }
    2530 
    2531     Assert(handle != VBOXVHWA_SURFHANDLE_INVALID);
    2532     Assert(surf->handle() == VBOXVHWA_SURFHANDLE_INVALID);
    2533     surf->setHandle(handle);
    2534     Assert(surf->handle() == handle);
    2535 
    2536     VBOXQGLLOG_EXIT(("pSurf (0x%p)\n",surf));
    2537 
    2538     return VINF_SUCCESS;
    2539 }
    2540 
    2541 #ifdef VBOX_WITH_WDDM
    2542 int VBoxVHWAImage::vhwaSurfaceGetInfo(struct VBOXVHWACMD_SURF_GETINFO RT_UNTRUSTED_VOLATILE_GUEST *pCmd)
    2543 {
    2544     VBoxVHWAColorFormat format;
    2545     Assert(!format.isValid());
    2546     if (pCmd->SurfInfo.PixelFormat.flags & VBOXVHWA_PF_RGB)
    2547         format = VBoxVHWAColorFormat(pCmd->SurfInfo.PixelFormat.c.rgbBitCount,
    2548                                         pCmd->SurfInfo.PixelFormat.m1.rgbRBitMask,
    2549                                         pCmd->SurfInfo.PixelFormat.m2.rgbGBitMask,
    2550                                         pCmd->SurfInfo.PixelFormat.m3.rgbBBitMask);
    2551     else if (pCmd->SurfInfo.PixelFormat.flags & VBOXVHWA_PF_FOURCC)
    2552         format = VBoxVHWAColorFormat(pCmd->SurfInfo.PixelFormat.fourCC);
    2553     else
    2554         AssertFailed();
    2555 
    2556     Assert(format.isValid());
    2557     if (format.isValid())
    2558     {
    2559         pCmd->SurfInfo.pitch = VBoxVHWATextureImage::calcBytesPerLine(format, pCmd->SurfInfo.width);
    2560         pCmd->SurfInfo.sizeX = VBoxVHWATextureImage::calcMemSize(format,
    2561                 pCmd->SurfInfo.width, pCmd->SurfInfo.height);
    2562         pCmd->SurfInfo.sizeY = 1;
    2563         return VINF_SUCCESS;
    2564     }
    2565     return VERR_INVALID_PARAMETER;
    2566 }
    2567 #endif
    2568 
    2569 int VBoxVHWAImage::vhwaSurfaceDestroy(struct VBOXVHWACMD_SURF_DESTROY RT_UNTRUSTED_VOLATILE_GUEST *pCmd)
    2570 {
    2571     VBoxVHWASurfaceBase *pSurf = handle2Surface(pCmd->u.in.hSurf);
    2572     VBoxVHWASurfList *pList = pSurf->getComplexList();
    2573     Assert(pSurf->handle() != VBOXVHWA_SURFHANDLE_INVALID);
    2574 
    2575     VBOXQGLLOG_ENTER(("pSurf (0x%x)\n",pSurf));
    2576     if (pList != mDisplay.getVGA()->getComplexList())
    2577     {
    2578         Assert(pList);
    2579         pList->remove(pSurf);
    2580         if (pList->surfaces().empty())
    2581         {
    2582             mDisplay.removeOverlay(pList);
    2583             if (pList == mConstructingList)
    2584             {
    2585                 mConstructingList = NULL;
    2586                 mcRemaining2Contruct = 0;
    2587             }
    2588             delete pList;
    2589         }
    2590 
    2591         delete(pSurf);
    2592     }
    2593     else
    2594     {
    2595         Assert(pList);
    2596         Assert(pList->size() >= 1);
    2597         if (pList->size() > 1)
    2598         {
    2599             if (pSurf == mDisplay.getVGA())
    2600             {
    2601                 const SurfList & surfaces = pList->surfaces();
    2602 
    2603                 for (SurfList::const_iterator it = surfaces.begin();
    2604                          it != surfaces.end(); ++ it)
    2605                 {
    2606                     VBoxVHWASurfaceBase *pCurSurf = (*it);
    2607                     Assert(pCurSurf);
    2608                     if (pCurSurf != pSurf)
    2609                     {
    2610                         mDisplay.updateVGA(pCurSurf);
    2611                         pList->setCurrentVisible(pCurSurf);
    2612                         break;
    2613                     }
    2614                 }
    2615             }
    2616 
    2617             pList->remove(pSurf);
    2618             delete(pSurf);
    2619         }
    2620         else
    2621         {
    2622             pSurf->setHandle(VBOXVHWA_SURFHANDLE_INVALID);
    2623         }
    2624     }
    2625 
    2626     /* just in case we destroy a visible overlay surface */
    2627     mRepaintNeeded = true;
    2628 
    2629     void * test = mSurfHandleTable.remove(pCmd->u.in.hSurf);
    2630     Assert(test); NOREF(test);
    2631 
    2632     return VINF_SUCCESS;
    2633 }
    2634 
    2635 #define VBOXVHWA_CONSTRUCT_QRECT_FROM_RECTL_RB(a_pr) \
    2636     QRect((a_pr)->left, \
    2637           (a_pr)->top, \
    2638           (a_pr)->right  - (a_pr)->left + 1, \
    2639           (a_pr)->bottom - (a_pr)->top + 1)
    2640 
    2641 #define VBOXVHWA_CONSTRUCT_QRECT_FROM_RECTL_WH(a_pr) \
    2642     QRect((a_pr)->left, \
    2643           (a_pr)->top, \
    2644           (a_pr)->right  - (a_pr)->left, \
    2645           (a_pr)->bottom - (a_pr)->top)
    2646 
    2647 int VBoxVHWAImage::vhwaSurfaceLock(struct VBOXVHWACMD_SURF_LOCK RT_UNTRUSTED_VOLATILE_GUEST *pCmd)
    2648 {
    2649     VBoxVHWASurfaceBase *pSurf = handle2Surface(pCmd->u.in.hSurf);
    2650     VBOXQGLLOG_ENTER(("pSurf (0x%x)\n",pSurf));
    2651     vboxCheckUpdateAddress (pSurf, pCmd->u.in.offSurface);
    2652     if (pCmd->u.in.rectValid)
    2653     {
    2654         QRect r = VBOXVHWA_CONSTRUCT_QRECT_FROM_RECTL_WH(&pCmd->u.in.rect);
    2655         return pSurf->lock(&r, pCmd->u.in.flags);
    2656     }
    2657     return pSurf->lock(NULL, pCmd->u.in.flags);
    2658 }
    2659 
    2660 int VBoxVHWAImage::vhwaSurfaceUnlock(struct VBOXVHWACMD_SURF_UNLOCK RT_UNTRUSTED_VOLATILE_GUEST *pCmd)
    2661 {
    2662     VBoxVHWASurfaceBase *pSurf = handle2Surface(pCmd->u.in.hSurf);
    2663 #ifdef DEBUG_misha
    2664     /* for performance reasons we should receive unlock for visible surfaces only
    2665      * other surfaces receive unlock only once becoming visible, e.g. on DdFlip
    2666      * Ensure this is so*/
    2667     if (pSurf != mDisplay.getPrimary())
    2668     {
    2669         const OverlayList & overlays = mDisplay.overlays();
    2670         bool bFound = false;
    2671 
    2672         if (!mDisplay.isPrimary(pSurf))
    2673         {
    2674             for (OverlayList::const_iterator it = overlays.begin();
    2675                  it != overlays.end(); ++ it)
    2676             {
    2677                 VBoxVHWASurfList * pSurfList = *it;
    2678                 if (pSurfList->current() == pSurf)
    2679                 {
    2680                     bFound = true;
    2681                     break;
    2682                 }
    2683             }
    2684 
    2685             Assert(bFound);
    2686         }
    2687 
    2688 //        Assert(bFound);
    2689     }
    2690 #endif
    2691     VBOXQGLLOG_ENTER(("pSurf (0x%x)\n",pSurf));
    2692     if (pCmd->u.in.xUpdatedMemValid)
    2693     {
    2694         QRect r = VBOXVHWA_CONSTRUCT_QRECT_FROM_RECTL_WH(&pCmd->u.in.xUpdatedMemRect);
    2695         pSurf->updatedMem(&r);
    2696     }
    2697 
    2698     return pSurf->unlock();
    2699 }
    2700 
    2701 int VBoxVHWAImage::vhwaSurfaceBlt(struct VBOXVHWACMD_SURF_BLT RT_UNTRUSTED_VOLATILE_GUEST *pCmd)
    2702 {
    2703     Q_UNUSED(pCmd);
    2704     return VERR_NOT_IMPLEMENTED;
    2705 }
    2706 
    2707 int VBoxVHWAImage::vhwaSurfaceFlip(struct VBOXVHWACMD_SURF_FLIP RT_UNTRUSTED_VOLATILE_GUEST *pCmd)
    2708 {
    2709     VBoxVHWASurfaceBase *pTargSurf = handle2Surface(pCmd->u.in.hTargSurf);
    2710     VBoxVHWASurfaceBase *pCurrSurf = handle2Surface(pCmd->u.in.hCurrSurf);
    2711     VBOXQGLLOG_ENTER(("pTargSurf (0x%x), pCurrSurf (0x%x)\n",pTargSurf,pCurrSurf));
    2712     vboxCheckUpdateAddress (pCurrSurf, pCmd->u.in.offCurrSurface);
    2713     vboxCheckUpdateAddress (pTargSurf, pCmd->u.in.offTargSurface);
    2714 
    2715     if (pCmd->u.in.xUpdatedTargMemValid)
    2716     {
    2717         QRect r = VBOXVHWA_CONSTRUCT_QRECT_FROM_RECTL_WH(&pCmd->u.in.xUpdatedTargMemRect);
    2718         pTargSurf->updatedMem(&r);
    2719     }
    2720     pTargSurf->getComplexList()->setCurrentVisible(pTargSurf);
    2721 
    2722     mRepaintNeeded = true;
    2723 #ifdef DEBUG
    2724     pCurrSurf->cFlipsCurr++;
    2725     pTargSurf->cFlipsTarg++;
    2726 #endif
    2727 
    2728     return VINF_SUCCESS;
    2729 }
    2730 
    2731 int VBoxVHWAImage::vhwaSurfaceColorFill(struct VBOXVHWACMD_SURF_COLORFILL RT_UNTRUSTED_VOLATILE_GUEST *pCmd)
    2732 {
    2733     NOREF(pCmd);
    2734     return VERR_NOT_IMPLEMENTED;
    2735 }
    2736 
    2737 void VBoxVHWAImage::vhwaDoSurfaceOverlayUpdate(VBoxVHWASurfaceBase *pDstSurf, VBoxVHWASurfaceBase *pSrcSurf,
    2738                                                struct VBOXVHWACMD_SURF_OVERLAY_UPDATE RT_UNTRUSTED_VOLATILE_GUEST *pCmd)
    2739 {
    2740     if (pCmd->u.in.flags & VBOXVHWA_OVER_KEYDEST)
    2741     {
    2742         VBOXQGLLOG((", KEYDEST"));
    2743         /* we use src (overlay) surface to maintain overridden dst ckey info
    2744          * to allow multiple overlays have different overridden dst keys for one primary surface */
    2745         /* non-null dstOverlayCKey for overlay would mean the overlay surface contains the overridden
    2746          * dst ckey value in defaultDstOverlayCKey
    2747          * this allows the NULL to be a valid overridden value as well
    2748          *  i.e.
    2749          * 1. indicate the value is NUL overridden, just set NULL*/
    2750         pSrcSurf->setOverriddenDstOverlayCKey(NULL);
    2751     }
    2752     else if (pCmd->u.in.flags & VBOXVHWA_OVER_KEYDESTOVERRIDE)
    2753     {
    2754         VBOXQGLLOG((", KEYDESTOVERRIDE"));
    2755         /* we use src (overlay) surface to maintain overridden dst ckey info
    2756          * to allow multiple overlays have different overridden dst keys for one primary surface */
    2757         /* non-null dstOverlayCKey for overlay would mean the overlay surface contains the overridden
    2758          * dst ckey value in defaultDstOverlayCKey
    2759          * this allows the NULL to be a valid overridden value as well
    2760          *  i.e.
    2761          * 1. indicate the value is overridden (no matter what we write here, bu it should be not NULL)*/
    2762         VBoxVHWAColorKey ckey(pCmd->u.in.desc.DstCK.high, pCmd->u.in.desc.DstCK.low);
    2763         VBOXQGLLOG_CKEY(" ckey: ",&ckey, "\n");
    2764         pSrcSurf->setOverriddenDstOverlayCKey(&ckey);
    2765         /* tell the ckey is enabled */
    2766         pSrcSurf->setDefaultDstOverlayCKey(&ckey);
    2767     }
    2768     else
    2769     {
    2770         VBOXQGLLOG((", no KEYDEST"));
    2771         /* we use src (overlay) surface to maintain overridden dst ckey info
    2772          * to allow multiple overlays have different overridden dst keys for one primary surface */
    2773         /* non-null dstOverlayCKey for overlay would mean the overlay surface contains the overridden
    2774          * dst ckey value in defaultDstOverlayCKey
    2775          * this allows the NULL to be a valid overridden value as well
    2776          * i.e.
    2777          * 1. indicate the value is overridden (no matter what we write here, bu it should be not NULL)*/
    2778         VBoxVHWAColorKey dummyCKey(0, 0);
    2779         pSrcSurf->setOverriddenDstOverlayCKey(&dummyCKey);
    2780         /* tell the ckey is disabled */
    2781         pSrcSurf->setDefaultDstOverlayCKey(NULL);
    2782     }
    2783 
    2784     if (pCmd->u.in.flags & VBOXVHWA_OVER_KEYSRC)
    2785     {
    2786         VBOXQGLLOG((", KEYSRC"));
    2787         pSrcSurf->resetDefaultSrcOverlayCKey();
    2788     }
    2789     else if (pCmd->u.in.flags & VBOXVHWA_OVER_KEYSRCOVERRIDE)
    2790     {
    2791         VBOXQGLLOG((", KEYSRCOVERRIDE"));
    2792         VBoxVHWAColorKey ckey(pCmd->u.in.desc.SrcCK.high, pCmd->u.in.desc.SrcCK.low);
    2793         pSrcSurf->setOverriddenSrcOverlayCKey(&ckey);
    2794     }
    2795     else
    2796     {
    2797         VBOXQGLLOG((", no KEYSRC"));
    2798         pSrcSurf->setOverriddenSrcOverlayCKey(NULL);
    2799     }
    2800     VBOXQGLLOG(("\n"));
    2801     if (pDstSurf)
    2802     {
    2803         QRect dstRect = VBOXVHWA_CONSTRUCT_QRECT_FROM_RECTL_WH(&pCmd->u.in.dstRect);
    2804         QRect srcRect = VBOXVHWA_CONSTRUCT_QRECT_FROM_RECTL_WH(&pCmd->u.in.srcRect);
    2805 
    2806         VBOXQGLLOG(("*******overlay update*******\n"));
    2807         VBOXQGLLOG(("dstSurfSize: w(%d), h(%d)\n", pDstSurf->width(), pDstSurf->height()));
    2808         VBOXQGLLOG(("srcSurfSize: w(%d), h(%d)\n", pSrcSurf->width(), pSrcSurf->height()));
    2809         VBOXQGLLOG_QRECT("dstRect:", &dstRect, "\n");
    2810         VBOXQGLLOG_QRECT("srcRect:", &srcRect, "\n");
    2811 
    2812         pSrcSurf->setPrimary(pDstSurf);
    2813 
    2814         pSrcSurf->setRects(dstRect, srcRect);
    2815     }
    2816 }
    2817 
    2818 int VBoxVHWAImage::vhwaSurfaceOverlayUpdate(struct VBOXVHWACMD_SURF_OVERLAY_UPDATE RT_UNTRUSTED_VOLATILE_GUEST *pCmd)
    2819 {
    2820     VBoxVHWASurfaceBase *pSrcSurf = handle2Surface(pCmd->u.in.hSrcSurf);
    2821     VBoxVHWASurfList *pList = pSrcSurf->getComplexList();
    2822     vboxCheckUpdateAddress (pSrcSurf, pCmd->u.in.offSrcSurface);
    2823     VBOXQGLLOG(("OverlayUpdate: pSrcSurf (0x%x)\n",pSrcSurf));
    2824     VBoxVHWASurfaceBase *pDstSurf = NULL;
    2825 
    2826     if (pCmd->u.in.hDstSurf)
    2827     {
    2828         pDstSurf = handle2Surface(pCmd->u.in.hDstSurf);
    2829         vboxCheckUpdateAddress (pDstSurf, pCmd->u.in.offDstSurface);
    2830         VBOXQGLLOG(("pDstSurf (0x%x)\n",pDstSurf));
    2831 #ifdef DEBUGVHWASTRICT
    2832         Assert(pDstSurf == mDisplay.getVGA());
    2833         Assert(mDisplay.getVGA() == mDisplay.getPrimary());
    2834 #endif
    2835         Assert(pDstSurf->getComplexList() == mDisplay.getVGA()->getComplexList());
    2836 
    2837         if (pCmd->u.in.flags & VBOXVHWA_OVER_SHOW)
    2838         {
    2839             if (pDstSurf != mDisplay.getPrimary())
    2840             {
    2841                 mDisplay.updateVGA(pDstSurf);
    2842                 pDstSurf->getComplexList()->setCurrentVisible(pDstSurf);
    2843             }
    2844         }
    2845     }
    2846 
    2847 #ifdef VBOX_WITH_WDDM
    2848     if (pCmd->u.in.xFlags & VBOXVHWACMD_SURF_OVERLAY_UPDATE_F_SRCMEMRECT)
    2849     {
    2850         QRect r = VBOXVHWA_CONSTRUCT_QRECT_FROM_RECTL_WH(&pCmd->u.in.xUpdatedSrcMemRect);
    2851         pSrcSurf->updatedMem(&r);
    2852     }
    2853     if (pCmd->u.in.xFlags & VBOXVHWACMD_SURF_OVERLAY_UPDATE_F_DSTMEMRECT)
    2854     {
    2855         QRect r = VBOXVHWA_CONSTRUCT_QRECT_FROM_RECTL_WH(&pCmd->u.in.xUpdatedDstMemRect);
    2856         pDstSurf->updatedMem(&r);
    2857     }
    2858 #endif
    2859 
    2860     const SurfList & surfaces = pList->surfaces();
    2861 
    2862     for (SurfList::const_iterator it = surfaces.begin();
    2863              it != surfaces.end(); ++ it)
    2864     {
    2865         VBoxVHWASurfaceBase *pCurSrcSurf = (*it);
    2866         vhwaDoSurfaceOverlayUpdate(pDstSurf, pCurSrcSurf, pCmd);
    2867     }
    2868 
    2869     if (pCmd->u.in.flags & VBOXVHWA_OVER_HIDE)
    2870     {
    2871         VBOXQGLLOG(("hide\n"));
    2872         pList->setCurrentVisible(NULL);
    2873     }
    2874     else if (pCmd->u.in.flags & VBOXVHWA_OVER_SHOW)
    2875     {
    2876         VBOXQGLLOG(("show\n"));
    2877         pList->setCurrentVisible(pSrcSurf);
    2878     }
    2879 
    2880     mRepaintNeeded = true;
    2881 
    2882     return VINF_SUCCESS;
    2883 }
    2884 
    2885 int VBoxVHWAImage::vhwaSurfaceOverlaySetPosition(struct VBOXVHWACMD_SURF_OVERLAY_SETPOSITION RT_UNTRUSTED_VOLATILE_GUEST *pCmd)
    2886 {
    2887     VBoxVHWASurfaceBase *pDstSurf = handle2Surface(pCmd->u.in.hDstSurf);
    2888     VBoxVHWASurfaceBase *pSrcSurf = handle2Surface(pCmd->u.in.hSrcSurf);
    2889 
    2890     VBOXQGLLOG_ENTER(("pDstSurf (0x%x), pSrcSurf (0x%x)\n",pDstSurf,pSrcSurf));
    2891 
    2892     vboxCheckUpdateAddress (pSrcSurf, pCmd->u.in.offSrcSurface);
    2893     vboxCheckUpdateAddress (pDstSurf, pCmd->u.in.offDstSurface);
    2894 
    2895     VBoxVHWASurfList *pList = pSrcSurf->getComplexList();
    2896     const SurfList & surfaces = pList->surfaces();
    2897 
    2898     QPoint pos(pCmd->u.in.xPos, pCmd->u.in.yPos);
    2899 
    2900 #ifdef DEBUGVHWASTRICT
    2901     Assert(pDstSurf == mDisplay.getVGA());
    2902     Assert(mDisplay.getVGA() == mDisplay.getPrimary());
    2903 #endif
    2904     if (pSrcSurf->getComplexList()->current() != NULL)
    2905     {
    2906         Assert(pDstSurf);
    2907         if (pDstSurf != mDisplay.getPrimary())
    2908         {
    2909             mDisplay.updateVGA(pDstSurf);
    2910             pDstSurf->getComplexList()->setCurrentVisible(pDstSurf);
    2911         }
    2912     }
    2913 
    2914     mRepaintNeeded = true;
    2915 
    2916     for (SurfList::const_iterator it = surfaces.begin();
    2917              it != surfaces.end(); ++ it)
    2918     {
    2919         VBoxVHWASurfaceBase *pCurSrcSurf = (*it);
    2920         pCurSrcSurf->setTargRectPosition(pos);
    2921     }
    2922 
    2923     return VINF_SUCCESS;
    2924 }
    2925 
    2926 int VBoxVHWAImage::vhwaSurfaceColorkeySet(struct VBOXVHWACMD_SURF_COLORKEY_SET RT_UNTRUSTED_VOLATILE_GUEST *pCmd)
    2927 {
    2928     VBoxVHWASurfaceBase *pSurf = handle2Surface(pCmd->u.in.hSurf);
    2929     VBOXQGLLOG_ENTER(("pSurf (0x%x)\n", pSurf));
    2930 
    2931     vboxCheckUpdateAddress (pSurf, pCmd->u.in.offSurface);
    2932 
    2933     mRepaintNeeded = true;
    2934 
    2935     if (pCmd->u.in.flags & VBOXVHWA_CKEY_DESTBLT)
    2936     {
    2937         VBoxVHWAColorKey ckey(pCmd->u.in.CKey.high, pCmd->u.in.CKey.low);
    2938         pSurf->setDstBltCKey(&ckey);
    2939     }
    2940     if (pCmd->u.in.flags & VBOXVHWA_CKEY_DESTOVERLAY)
    2941     {
    2942         VBoxVHWAColorKey ckey(pCmd->u.in.CKey.high, pCmd->u.in.CKey.low);
    2943         pSurf->setDefaultDstOverlayCKey(&ckey);
    2944     }
    2945     if (pCmd->u.in.flags & VBOXVHWA_CKEY_SRCBLT)
    2946     {
    2947         VBoxVHWAColorKey ckey(pCmd->u.in.CKey.high, pCmd->u.in.CKey.low);
    2948         pSurf->setSrcBltCKey(&ckey);
    2949 
    2950     }
    2951     if (pCmd->u.in.flags & VBOXVHWA_CKEY_SRCOVERLAY)
    2952     {
    2953         VBoxVHWAColorKey ckey(pCmd->u.in.CKey.high, pCmd->u.in.CKey.low);
    2954         pSurf->setDefaultSrcOverlayCKey(&ckey);
    2955     }
    2956 
    2957     return VINF_SUCCESS;
    2958 }
    2959 
    2960 int VBoxVHWAImage::vhwaQueryInfo1(struct VBOXVHWACMD_QUERYINFO1 RT_UNTRUSTED_VOLATILE_GUEST *pCmd)
    2961 {
    2962     VBOXQGLLOG_ENTER(("\n"));
    2963     bool bEnabled = false;
    2964     const VBoxVHWAInfo & info = vboxVHWAGetSupportInfo(NULL);
    2965     if (info.isVHWASupported())
    2966     {
    2967         Assert(pCmd->u.in.guestVersion.maj == VBOXVHWA_VERSION_MAJ);
    2968         if (pCmd->u.in.guestVersion.maj == VBOXVHWA_VERSION_MAJ)
    2969         {
    2970             Assert(pCmd->u.in.guestVersion.min == VBOXVHWA_VERSION_MIN);
    2971             if (pCmd->u.in.guestVersion.min == VBOXVHWA_VERSION_MIN)
    2972             {
    2973                 Assert(pCmd->u.in.guestVersion.bld == VBOXVHWA_VERSION_BLD);
    2974                 if (pCmd->u.in.guestVersion.bld == VBOXVHWA_VERSION_BLD)
    2975                 {
    2976                     Assert(pCmd->u.in.guestVersion.reserved == VBOXVHWA_VERSION_RSV);
    2977                     if (pCmd->u.in.guestVersion.reserved == VBOXVHWA_VERSION_RSV)
    2978                     {
    2979                         bEnabled = true;
    2980                     }
    2981                 }
    2982             }
    2983         }
    2984     }
    2985 
    2986     memset((void *)pCmd, 0, sizeof(VBOXVHWACMD_QUERYINFO1));
    2987     if (bEnabled)
    2988     {
    2989         pCmd->u.out.cfgFlags = VBOXVHWA_CFG_ENABLED;
    2990 
    2991         pCmd->u.out.caps =
    2992                     /* we do not support blitting for now */
    2993 //                        VBOXVHWA_CAPS_BLT | VBOXVHWA_CAPS_BLTSTRETCH | VBOXVHWA_CAPS_BLTQUEUE
    2994 //                                 | VBOXVHWA_CAPS_BLTCOLORFILL not supported, although adding it is trivial
    2995 //                                 | VBOXVHWA_CAPS_BLTFOURCC set below if shader support is available
    2996                            VBOXVHWA_CAPS_OVERLAY
    2997                          | VBOXVHWA_CAPS_OVERLAYSTRETCH
    2998                          | VBOXVHWA_CAPS_OVERLAYCANTCLIP
    2999                                  // | VBOXVHWA_CAPS_OVERLAYFOURCC set below if shader support is available
    3000                          ;
    3001 
    3002         /** @todo check if we could use DDSCAPS_ALPHA instead of colorkeying */
    3003 
    3004         pCmd->u.out.caps2 = VBOXVHWA_CAPS2_CANRENDERWINDOWED
    3005                                     | VBOXVHWA_CAPS2_WIDESURFACES;
    3006 
    3007         /// @todo setup stretchCaps
    3008         pCmd->u.out.stretchCaps = 0;
    3009 
    3010         pCmd->u.out.numOverlays = 1;
    3011         /** @todo set curOverlays properly */
    3012         pCmd->u.out.curOverlays = 0;
    3013 
    3014         pCmd->u.out.surfaceCaps = VBOXVHWA_SCAPS_PRIMARYSURFACE
    3015 #ifndef VBOXVHWA_ALLOW_PRIMARY_AND_OVERLAY_ONLY
    3016                                 | VBOXVHWA_SCAPS_OFFSCREENPLAIN
    3017 #endif
    3018                                 | VBOXVHWA_SCAPS_FLIP
    3019                                 | VBOXVHWA_SCAPS_LOCALVIDMEM
    3020                                 | VBOXVHWA_SCAPS_OVERLAY
    3021                     //            | VBOXVHWA_SCAPS_BACKBUFFER
    3022                     //            | VBOXVHWA_SCAPS_FRONTBUFFER
    3023                     //            | VBOXVHWA_SCAPS_VIDEOMEMORY
    3024                     //            | VBOXVHWA_SCAPS_COMPLEX
    3025                     //            | VBOXVHWA_SCAPS_VISIBLE
    3026                                 ;
    3027 
    3028         if (info.getGlInfo().isFragmentShaderSupported() && info.getGlInfo().getMultiTexNumSupported() >= 2)
    3029         {
    3030             pCmd->u.out.caps |= VBOXVHWA_CAPS_COLORKEY
    3031                              |  VBOXVHWA_CAPS_COLORKEYHWASSIST;
    3032 
    3033             pCmd->u.out.colorKeyCaps = 0
    3034 //                                   | VBOXVHWA_CKEYCAPS_DESTBLT | VBOXVHWA_CKEYCAPS_DESTBLTCLRSPACE
    3035 //                                   | VBOXVHWA_CKEYCAPS_SRCBLT| VBOXVHWA_CKEYCAPS_SRCBLTCLRSPACE
    3036 //                                   | VBOXVHWA_CKEYCAPS_SRCOVERLAY | VBOXVHWA_CKEYCAPS_SRCOVERLAYONEACTIVE
    3037                                      | VBOXVHWA_CKEYCAPS_DESTOVERLAY
    3038                                      | VBOXVHWA_CKEYCAPS_DESTOVERLAYONEACTIVE;
    3039 
    3040             if (info.getGlInfo().isTextureRectangleSupported())
    3041             {
    3042                 pCmd->u.out.caps |= VBOXVHWA_CAPS_OVERLAYFOURCC
    3043 //                               |  VBOXVHWA_CAPS_BLTFOURCC
    3044                                  ;
    3045 
    3046                 pCmd->u.out.colorKeyCaps |= 0
    3047 //                                       |  VBOXVHWA_CKEYCAPS_SRCOVERLAYYUV
    3048                                          |  VBOXVHWA_CKEYCAPS_DESTOVERLAYYUV;
    3049 
    3050 //              pCmd->u.out.caps2 |= VBOXVHWA_CAPS2_COPYFOURCC;
    3051 
    3052                 pCmd->u.out.numFourCC = mSettings->getIntersection(info, 0, NULL);
    3053             }
    3054         }
    3055     }
    3056 
    3057     return VINF_SUCCESS;
    3058 }
    3059 
    3060 int VBoxVHWAImage::vhwaQueryInfo2(struct VBOXVHWACMD_QUERYINFO2 RT_UNTRUSTED_VOLATILE_GUEST *pCmd)
    3061 {
    3062     VBOXQGLLOG_ENTER(("\n"));
    3063 
    3064     const VBoxVHWAInfo &info = vboxVHWAGetSupportInfo(NULL);
    3065     uint32_t aFourcc[VBOXVHWA_NUMFOURCC];
    3066     int num = mSettings->getIntersection(info, VBOXVHWA_NUMFOURCC, aFourcc);
    3067     Assert(pCmd->numFourCC >= (uint32_t)num);
    3068     if (pCmd->numFourCC < (uint32_t)num)
    3069         return VERR_GENERAL_FAILURE;
    3070 
    3071     pCmd->numFourCC = (uint32_t)num;
    3072     memcpy((void *)&pCmd->FourCC[0], aFourcc, num * sizeof(aFourcc[0]));
    3073     return VINF_SUCCESS;
    3074 }
    3075 
    3076 //static DECLCALLBACK(void) vboxQGLSaveExec(PSSMHANDLE pSSM, void *pvUser)
    3077 //{
    3078 //    VBoxVHWAImage * pw = (VBoxVHWAImage*)pvUser;
    3079 //    pw->vhwaSaveExec(pSSM);
    3080 //}
    3081 //
    3082 //static DECLCALLBACK(int) vboxQGLLoadExec(PSSMHANDLE pSSM, void *pvUser, uint32_t u32Version, uint32_t uPass)
    3083 //{
    3084 //    Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
    3085 //    VBoxVHWAImage * pw = (VBoxVHWAImage*)pvUser;
    3086 //    return VBoxVHWAImage::vhwaLoadExec(&pw->onResizeCmdList(), pSSM, u32Version);
    3087 //}
    3088 
    3089 int VBoxVHWAImage::vhwaSaveSurface(struct SSMHANDLE *pSSM, VBoxVHWASurfaceBase *pSurf, uint32_t surfCaps)
    3090 {
    3091     VBOXQGL_SAVE_SURFSTART(pSSM);
    3092 
    3093     uint64_t u64 = vboxVRAMOffset(pSurf);
    3094     int rc;
    3095     rc = SSMR3PutU32(pSSM, pSurf->handle());
    3096     rc = SSMR3PutU64(pSSM, u64);
    3097     rc = SSMR3PutU32(pSSM, pSurf->width());
    3098     rc = SSMR3PutU32(pSSM, pSurf->height());
    3099     rc = SSMR3PutU32(pSSM, surfCaps);
    3100 
    3101     uint32_t flags = 0;
    3102     const VBoxVHWAColorKey *pDstBltCKey = pSurf->dstBltCKey();
    3103     const VBoxVHWAColorKey *pSrcBltCKey = pSurf->srcBltCKey();
    3104     const VBoxVHWAColorKey *pDstOverlayCKey = pSurf->dstOverlayCKey();
    3105     const VBoxVHWAColorKey *pSrcOverlayCKey = pSurf->srcOverlayCKey();
    3106     if (pDstBltCKey)
    3107         flags |= VBOXVHWA_SD_CKDESTBLT;
    3108     if (pSrcBltCKey)
    3109         flags |= VBOXVHWA_SD_CKSRCBLT;
    3110     if (pDstOverlayCKey)
    3111         flags |= VBOXVHWA_SD_CKDESTOVERLAY;
    3112     if (pSrcOverlayCKey)
    3113         flags |= VBOXVHWA_SD_CKSRCOVERLAY;
    3114     rc = SSMR3PutU32(pSSM, flags);
    3115 
    3116     if (pDstBltCKey)
    3117     {
    3118         rc = SSMR3PutU32(pSSM, pDstBltCKey->lower());
    3119         rc = SSMR3PutU32(pSSM, pDstBltCKey->upper());
    3120     }
    3121     if (pSrcBltCKey)
    3122     {
    3123         rc = SSMR3PutU32(pSSM, pSrcBltCKey->lower());
    3124         rc = SSMR3PutU32(pSSM, pSrcBltCKey->upper());
    3125     }
    3126     if (pDstOverlayCKey)
    3127     {
    3128         rc = SSMR3PutU32(pSSM, pDstOverlayCKey->lower());
    3129         rc = SSMR3PutU32(pSSM, pDstOverlayCKey->upper());
    3130     }
    3131     if (pSrcOverlayCKey)
    3132     {
    3133         rc = SSMR3PutU32(pSSM, pSrcOverlayCKey->lower());
    3134         rc = SSMR3PutU32(pSSM, pSrcOverlayCKey->upper());
    3135     }
    3136     AssertRCReturn(rc, rc);
    3137 
    3138     const VBoxVHWAColorFormat & format = pSurf->pixelFormat();
    3139     flags = 0;
    3140     if (format.fourcc())
    3141     {
    3142         flags |= VBOXVHWA_PF_FOURCC;
    3143         rc = SSMR3PutU32(pSSM, flags);
    3144         rc = SSMR3PutU32(pSSM, format.fourcc());
    3145     }
    3146     else
    3147     {
    3148         flags |= VBOXVHWA_PF_RGB;
    3149         rc = SSMR3PutU32(pSSM, flags);
    3150         rc = SSMR3PutU32(pSSM, format.bitsPerPixel());
    3151         rc = SSMR3PutU32(pSSM, format.r().mask());
    3152         rc = SSMR3PutU32(pSSM, format.g().mask());
    3153         rc = SSMR3PutU32(pSSM, format.b().mask());
    3154         rc = SSMR3PutU32(pSSM, format.a().mask());
    3155     }
    3156     AssertRCReturn(rc, rc);
    3157 
    3158     VBOXQGL_SAVE_SURFSTOP(pSSM);
    3159     return rc;
    3160 }
    3161 
    3162 int VBoxVHWAImage::vhwaLoadSurface(VHWACommandList * pCmdList, struct SSMHANDLE * pSSM, uint32_t cBackBuffers, uint32_t u32Version)
    3163 {
    3164     Q_UNUSED(u32Version);
    3165 
    3166     VBOXQGL_LOAD_SURFSTART(pSSM);
    3167 
    3168     char *buf = (char*)malloc(VBOXVHWACMD_SIZE(VBOXVHWACMD_SURF_CREATE));
    3169     memset(buf, 0, sizeof(VBOXVHWACMD_SIZE(VBOXVHWACMD_SURF_CREATE)));
    3170     VBOXVHWACMD *pCmd = (VBOXVHWACMD *)buf;
    3171     pCmd->enmCmd = VBOXVHWACMD_TYPE_SURF_CREATE;
    3172     pCmd->Flags = VBOXVHWACMD_FLAG_HH_CMD;
    3173 
    3174     VBOXVHWACMD_SURF_CREATE *pCreateSurf = VBOXVHWACMD_BODY_HOST_HEAP(pCmd, VBOXVHWACMD_SURF_CREATE);
    3175     int rc;
    3176     uint32_t u32;
    3177     rc = SSMR3GetU32(pSSM, &u32);         AssertRC(rc);
    3178     pCreateSurf->SurfInfo.hSurf = (VBOXVHWA_SURFHANDLE)u32;
    3179     if (RT_SUCCESS(rc))
    3180     {
    3181         rc = SSMR3GetU64(pSSM, &pCreateSurf->SurfInfo.offSurface);      AssertRC(rc);
    3182         rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.width);           AssertRC(rc);
    3183         rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.height);          AssertRC(rc);
    3184         rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.surfCaps);        AssertRC(rc);
    3185         rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.flags);           AssertRC(rc);
    3186         if (pCreateSurf->SurfInfo.flags & VBOXVHWA_SD_CKDESTBLT)
    3187         {
    3188             rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.DstBltCK.low);    AssertRC(rc);
    3189             rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.DstBltCK.high);   AssertRC(rc);
    3190         }
    3191         if (pCreateSurf->SurfInfo.flags & VBOXVHWA_SD_CKSRCBLT)
    3192         {
    3193             rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.SrcBltCK.low);    AssertRC(rc);
    3194             rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.SrcBltCK.high);   AssertRC(rc);
    3195         }
    3196         if (pCreateSurf->SurfInfo.flags & VBOXVHWA_SD_CKDESTOVERLAY)
    3197         {
    3198             rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.DstOverlayCK.low);  AssertRC(rc);
    3199             rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.DstOverlayCK.high); AssertRC(rc);
    3200         }
    3201         if (pCreateSurf->SurfInfo.flags & VBOXVHWA_SD_CKSRCOVERLAY)
    3202         {
    3203             rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.SrcOverlayCK.low);  AssertRC(rc);
    3204             rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.SrcOverlayCK.high); AssertRC(rc);
    3205         }
    3206 
    3207         rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.PixelFormat.flags);     AssertRC(rc);
    3208         if (pCreateSurf->SurfInfo.PixelFormat.flags & VBOXVHWA_PF_RGB)
    3209         {
    3210             rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.PixelFormat.c.rgbBitCount);   AssertRC(rc);
    3211             rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.PixelFormat.m1.rgbRBitMask);  AssertRC(rc);
    3212             rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.PixelFormat.m2.rgbGBitMask);  AssertRC(rc);
    3213             rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.PixelFormat.m3.rgbBBitMask);  AssertRC(rc);
    3214             rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.PixelFormat.m4.rgbABitMask);  AssertRC(rc);
    3215         }
    3216         else if (pCreateSurf->SurfInfo.PixelFormat.flags & VBOXVHWA_PF_FOURCC)
    3217         {
    3218             rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.PixelFormat.fourCC);
    3219             AssertRC(rc);
    3220         }
    3221         else
    3222         {
    3223             AssertFailed();
    3224         }
    3225         AssertRCReturnStmt(rc, free(buf), rc);
    3226 
    3227         if (cBackBuffers)
    3228         {
    3229             pCreateSurf->SurfInfo.cBackBuffers = cBackBuffers;
    3230             pCreateSurf->SurfInfo.surfCaps |= VBOXVHWA_SCAPS_COMPLEX;
    3231         }
    3232 
    3233         pCmdList->push_back(pCmd);
    3234 //        vboxExecOnResize(&VBoxVHWAImage::vboxDoVHWACmdAndFree, pCmd); AssertRC(rc);
    3235 //        if (RT_SUCCESS(rc))
    3236 //        {
    3237 //            rc = pCmd->rc;
    3238 //            AssertRC(rc);
    3239 //        }
    3240     }
    3241     else
    3242         free(buf);
    3243 
    3244     VBOXQGL_LOAD_SURFSTOP(pSSM);
    3245 
    3246     return rc;
    3247 }
    3248 
    3249 int VBoxVHWAImage::vhwaSaveOverlayData(struct SSMHANDLE * pSSM, VBoxVHWASurfaceBase *pSurf, bool bVisible)
    3250 {
    3251     VBOXQGL_SAVE_OVERLAYSTART(pSSM);
    3252 
    3253     uint32_t flags = 0;
    3254     const VBoxVHWAColorKey * dstCKey = pSurf->dstOverlayCKey();
    3255     const VBoxVHWAColorKey * defaultDstCKey = pSurf->defaultDstOverlayCKey();
    3256     const VBoxVHWAColorKey * srcCKey = pSurf->srcOverlayCKey();;
    3257     const VBoxVHWAColorKey * defaultSrcCKey = pSurf->defaultSrcOverlayCKey();
    3258     bool bSaveDstCKey = false;
    3259     bool bSaveSrcCKey = false;
    3260 
    3261     if (bVisible)
    3262     {
    3263         flags |= VBOXVHWA_OVER_SHOW;
    3264     }
    3265     else
    3266     {
    3267         flags |= VBOXVHWA_OVER_HIDE;
    3268     }
    3269 
    3270     if (!dstCKey)
    3271     {
    3272         flags |= VBOXVHWA_OVER_KEYDEST;
    3273     }
    3274     else if (defaultDstCKey)
    3275     {
    3276         flags |= VBOXVHWA_OVER_KEYDESTOVERRIDE;
    3277         bSaveDstCKey = true;
    3278     }
    3279 
    3280     if (srcCKey == defaultSrcCKey)
    3281     {
    3282         flags |= VBOXVHWA_OVER_KEYSRC;
    3283     }
    3284     else if (srcCKey)
    3285     {
    3286         flags |= VBOXVHWA_OVER_KEYSRCOVERRIDE;
    3287         bSaveSrcCKey = true;
    3288     }
    3289 
    3290     int rc = SSMR3PutU32(pSSM, flags);
    3291 
    3292     rc = SSMR3PutU32(pSSM, mDisplay.getPrimary()->handle());
    3293     rc = SSMR3PutU32(pSSM, pSurf->handle());
    3294 
    3295     if (bSaveDstCKey)
    3296     {
    3297         rc = SSMR3PutU32(pSSM, dstCKey->lower());
    3298         rc = SSMR3PutU32(pSSM, dstCKey->upper());
    3299     }
    3300     if (bSaveSrcCKey)
    3301     {
    3302         rc = SSMR3PutU32(pSSM, srcCKey->lower());
    3303         rc = SSMR3PutU32(pSSM, srcCKey->upper());
    3304     }
    3305 
    3306     int x1, x2, y1, y2;
    3307     pSurf->targRect().getCoords(&x1, &y1, &x2, &y2);
    3308     rc = SSMR3PutS32(pSSM, x1);
    3309     rc = SSMR3PutS32(pSSM, x2+1);
    3310     rc = SSMR3PutS32(pSSM, y1);
    3311     rc = SSMR3PutS32(pSSM, y2+1);
    3312 
    3313     pSurf->srcRect().getCoords(&x1, &y1, &x2, &y2);
    3314     rc = SSMR3PutS32(pSSM, x1);
    3315     rc = SSMR3PutS32(pSSM, x2+1);
    3316     rc = SSMR3PutS32(pSSM, y1);
    3317     rc = SSMR3PutS32(pSSM, y2+1);
    3318     AssertRCReturn(rc, rc);
    3319 
    3320     VBOXQGL_SAVE_OVERLAYSTOP(pSSM);
    3321 
    3322     return rc;
    3323 }
    3324 
    3325 int VBoxVHWAImage::vhwaLoadOverlayData(VHWACommandList *pCmdList, struct SSMHANDLE *pSSM, uint32_t u32Version)
    3326 {
    3327     Q_UNUSED(u32Version);
    3328 
    3329     VBOXQGL_LOAD_OVERLAYSTART(pSSM);
    3330 
    3331     char *buf = new char[VBOXVHWACMD_SIZE(VBOXVHWACMD_SURF_CREATE)];
    3332     memset(buf, 0, VBOXVHWACMD_SIZE(VBOXVHWACMD_SURF_CREATE));
    3333     VBOXVHWACMD * pCmd = (VBOXVHWACMD*)buf;
    3334     pCmd->enmCmd = VBOXVHWACMD_TYPE_SURF_OVERLAY_UPDATE;
    3335     pCmd->Flags = VBOXVHWACMD_FLAG_HH_CMD;
    3336 
    3337     VBOXVHWACMD_SURF_OVERLAY_UPDATE *pUpdateOverlay = VBOXVHWACMD_BODY_HOST_HEAP(pCmd, VBOXVHWACMD_SURF_OVERLAY_UPDATE);
    3338     int rc;
    3339 
    3340     rc = SSMR3GetU32(pSSM, &pUpdateOverlay->u.in.flags); AssertRC(rc);
    3341     uint32_t hSrc, hDst;
    3342     rc = SSMR3GetU32(pSSM, &hDst); AssertRC(rc);
    3343     rc = SSMR3GetU32(pSSM, &hSrc); AssertRC(rc);
    3344     pUpdateOverlay->u.in.hSrcSurf = hSrc;
    3345     pUpdateOverlay->u.in.hDstSurf = hDst;
    3346     {
    3347         pUpdateOverlay->u.in.offDstSurface = VBOXVHWA_OFFSET64_VOID;
    3348         pUpdateOverlay->u.in.offSrcSurface = VBOXVHWA_OFFSET64_VOID;
    3349 
    3350         if (pUpdateOverlay->u.in.flags & VBOXVHWA_OVER_KEYDESTOVERRIDE)
    3351         {
    3352             rc = SSMR3GetU32(pSSM, &pUpdateOverlay->u.in.desc.DstCK.low);  AssertRC(rc);
    3353             rc = SSMR3GetU32(pSSM, &pUpdateOverlay->u.in.desc.DstCK.high); AssertRC(rc);
    3354         }
    3355 
    3356         if (pUpdateOverlay->u.in.flags & VBOXVHWA_OVER_KEYSRCOVERRIDE)
    3357         {
    3358             rc = SSMR3GetU32(pSSM, &pUpdateOverlay->u.in.desc.SrcCK.low);  AssertRC(rc);
    3359             rc = SSMR3GetU32(pSSM, &pUpdateOverlay->u.in.desc.SrcCK.high); AssertRC(rc);
    3360         }
    3361 
    3362         rc = SSMR3GetS32(pSSM, &pUpdateOverlay->u.in.dstRect.left);   AssertRC(rc);
    3363         rc = SSMR3GetS32(pSSM, &pUpdateOverlay->u.in.dstRect.right);  AssertRC(rc);
    3364         rc = SSMR3GetS32(pSSM, &pUpdateOverlay->u.in.dstRect.top);    AssertRC(rc);
    3365         rc = SSMR3GetS32(pSSM, &pUpdateOverlay->u.in.dstRect.bottom); AssertRC(rc);
    3366 
    3367         rc = SSMR3GetS32(pSSM, &pUpdateOverlay->u.in.srcRect.left);   AssertRC(rc);
    3368         rc = SSMR3GetS32(pSSM, &pUpdateOverlay->u.in.srcRect.right);  AssertRC(rc);
    3369         rc = SSMR3GetS32(pSSM, &pUpdateOverlay->u.in.srcRect.top);    AssertRC(rc);
    3370         rc = SSMR3GetS32(pSSM, &pUpdateOverlay->u.in.srcRect.bottom);
    3371         AssertRCReturnStmt(rc, free(buf), rc);
    3372 
    3373         pCmdList->push_back(pCmd);
    3374     }
    3375 
    3376     VBOXQGL_LOAD_OVERLAYSTOP(pSSM);
    3377 
    3378     return rc;
    3379 }
    3380 
    3381 void VBoxVHWAImage::vhwaSaveExecVoid(struct SSMHANDLE *pSSM)
    3382 {
    3383     VBOXQGL_SAVE_START(pSSM);
    3384     SSMR3PutU32(pSSM, 0); /* 0 primaries */
    3385     VBOXQGL_SAVE_STOP(pSSM);
    3386 }
    3387 
    3388 void VBoxVHWAImage::vhwaSaveExec(struct SSMHANDLE *pSSM)
    3389 {
    3390     VBOXQGL_SAVE_START(pSSM);
    3391 
    3392     /* the mechanism of restoring data is based on generating VHWA commands that restore the surfaces state
    3393      * the following commands are generated:
    3394      * I.    CreateSurface
    3395      * II.   UpdateOverlay
    3396      *
    3397      * Data format is the following:
    3398      * I.    u32 - Num primary surfaces - (the current frontbuffer is detected in the stored surf flags which are posted to the generated CreateSurface cmd)
    3399      * II.   for each primary surf
    3400      * II.1    generate & execute CreateSurface cmd (see below on the generation logic)
    3401      * III.  u32 - Num overlays
    3402      * IV.   for each overlay
    3403      * IV.1    u32 - Num surfaces in overlay (the current frontbuffer is detected in the stored surf flags which are posted to the generated CreateSurface cmd)
    3404      * IV.2    for each surface in overlay
    3405      * IV.2.a    generate & execute CreateSurface cmd (see below on the generation logic)
    3406      * IV.2.b    generate & execute UpdateOverlay cmd (see below on the generation logic)
    3407      *
    3408      */
    3409     const SurfList & primaryList = mDisplay.primaries().surfaces();
    3410     uint32_t cPrimary = (uint32_t)primaryList.size();
    3411     if (   cPrimary
    3412         && (   mDisplay.getVGA() == NULL
    3413             || mDisplay.getVGA()->handle() == VBOXVHWA_SURFHANDLE_INVALID))
    3414     {
    3415         cPrimary -= 1;
    3416     }
    3417 
    3418     int rc = SSMR3PutU32(pSSM, cPrimary);
    3419     AssertRCReturnVoid(rc);
    3420     if (cPrimary)
    3421     {
    3422         for (SurfList::const_iterator pr = primaryList.begin(); pr != primaryList.end(); ++ pr)
    3423         {
    3424             VBoxVHWASurfaceBase *pSurf = *pr;
    3425     //        bool bVga = (pSurf == mDisplay.getVGA());
    3426             bool bVisible = (pSurf == mDisplay.getPrimary());
    3427             uint32_t flags = VBOXVHWA_SCAPS_PRIMARYSURFACE;
    3428             if (bVisible)
    3429                 flags |= VBOXVHWA_SCAPS_VISIBLE;
    3430 
    3431             if (pSurf->handle() != VBOXVHWA_SURFHANDLE_INVALID)
    3432             {
    3433                 rc = vhwaSaveSurface(pSSM, *pr, flags);
    3434 #ifdef DEBUG
    3435                 --cPrimary;
    3436                 Assert(cPrimary < UINT32_MAX / 2);
    3437 #endif
    3438             }
    3439             else
    3440             {
    3441                 Assert(pSurf == mDisplay.getVGA());
    3442             }
    3443         }
    3444 
    3445 #ifdef DEBUG
    3446         Assert(!cPrimary);
    3447 #endif
    3448 
    3449         const OverlayList & overlays = mDisplay.overlays();
    3450         rc = SSMR3PutU32(pSSM, (uint32_t)overlays.size());
    3451 
    3452         for (OverlayList::const_iterator it = overlays.begin(); it != overlays.end(); ++ it)
    3453         {
    3454             VBoxVHWASurfList * pSurfList = *it;
    3455             const SurfList & surfaces = pSurfList->surfaces();
    3456             uint32_t cSurfs = (uint32_t)surfaces.size();
    3457             uint32_t flags = VBOXVHWA_SCAPS_OVERLAY;
    3458             if (cSurfs > 1)
    3459                 flags |= VBOXVHWA_SCAPS_COMPLEX;
    3460             rc = SSMR3PutU32(pSSM, cSurfs);
    3461             for (SurfList::const_iterator sit = surfaces.begin(); sit != surfaces.end(); ++ sit)
    3462                 rc = vhwaSaveSurface(pSSM, *sit, flags);
    3463 
    3464             bool bVisible = true;
    3465             VBoxVHWASurfaceBase * pOverlayData = pSurfList->current();
    3466             if (!pOverlayData)
    3467             {
    3468                 pOverlayData = surfaces.front();
    3469                 bVisible = false;
    3470             }
    3471 
    3472             rc = vhwaSaveOverlayData(pSSM, pOverlayData, bVisible);
    3473         }
    3474     }
    3475 
    3476     VBOXQGL_SAVE_STOP(pSSM);
    3477 }
    3478 
    3479 int VBoxVHWAImage::vhwaLoadVHWAEnable(VHWACommandList * pCmdList)
    3480 {
    3481     char *buf = (char *)malloc(sizeof(VBOXVHWACMD));
    3482     Assert(buf);
    3483     if (buf)
    3484     {
    3485         memset(buf, 0, sizeof(VBOXVHWACMD));
    3486         VBOXVHWACMD *pCmd = (VBOXVHWACMD *)buf;
    3487         pCmd->enmCmd = VBOXVHWACMD_TYPE_ENABLE;
    3488         pCmd->Flags = VBOXVHWACMD_FLAG_HH_CMD;
    3489         pCmdList->push_back(pCmd);
    3490         return VINF_SUCCESS;
    3491     }
    3492 
    3493     return VERR_OUT_OF_RESOURCES;
    3494 }
    3495 
    3496 int VBoxVHWAImage::vhwaLoadExec(VHWACommandList *pCmdList, struct SSMHANDLE * pSSM, uint32_t u32Version)
    3497 {
    3498     VBOXQGL_LOAD_START(pSSM);
    3499 
    3500     if (u32Version > VBOXQGL_STATE_VERSION)
    3501         return VERR_VERSION_MISMATCH;
    3502 
    3503     int rc;
    3504     uint32_t u32;
    3505 
    3506     rc = vhwaLoadVHWAEnable(pCmdList); AssertRC(rc);
    3507     if (RT_SUCCESS(rc))
    3508     {
    3509         rc = SSMR3GetU32(pSSM, &u32); AssertRC(rc);
    3510         if (RT_SUCCESS(rc))
    3511         {
    3512             if (u32Version == 1U && u32 == UINT32_MAX) /* work around the v1 bug */
    3513                 u32 = 0;
    3514             if (u32)
    3515             {
    3516                 for (uint32_t i = 0; i < u32; ++i)
    3517                 {
    3518                     rc = vhwaLoadSurface(pCmdList, pSSM, 0, u32Version);
    3519                     AssertRCBreak(rc);
    3520                 }
    3521 
    3522                 if (RT_SUCCESS(rc))
    3523                 {
    3524                     rc = SSMR3GetU32(pSSM, &u32); AssertRC(rc);
    3525                     if (RT_SUCCESS(rc))
    3526                     {
    3527                         for (uint32_t i = 0; i < u32; ++i)
    3528                         {
    3529                             uint32_t cSurfs;
    3530                             rc = SSMR3GetU32(pSSM, &cSurfs); AssertRC(rc);
    3531                             for (uint32_t j = 0; j < cSurfs; ++j)
    3532                             {
    3533                                 rc = vhwaLoadSurface(pCmdList, pSSM, cSurfs - 1, u32Version);
    3534                                 AssertRCBreak(rc);
    3535                             }
    3536 
    3537                             if (RT_SUCCESS(rc))
    3538                             {
    3539                                 rc = vhwaLoadOverlayData(pCmdList, pSSM, u32Version);
    3540                                 AssertRCBreak(rc);
    3541                             }
    3542                             else
    3543                                 break;
    3544                         }
    3545                     }
    3546                 }
    3547             }
    3548 #ifdef VBOXQGL_STATE_DEBUG
    3549             else if (u32Version == 1) /* read the 0 overlay count to ensure the following VBOXQGL_LOAD_STOP succeeds */
    3550             {
    3551                 rc = SSMR3GetU32(pSSM, &u32);
    3552                 AssertRC(rc);
    3553                 Assert(u32 == 0 || RT_FAILURE(rc));
    3554             }
    3555 #endif
    3556         }
    3557     }
    3558 
    3559     VBOXQGL_LOAD_STOP(pSSM);
    3560 
    3561     return rc;
    3562 }
    3563 
    3564 int VBoxVHWAImage::vhwaConstruct(struct VBOXVHWACMD_HH_CONSTRUCT *pCmd)
    3565 {
    3566 //    PVM pVM = (PVM)pCmd->pVM;
    3567 //    uint32_t intsId = 0; /** @todo set the proper id */
    3568 //
    3569 //    char nameFuf[sizeof(VBOXQGL_STATE_NAMEBASE) + 8];
    3570 //
    3571 //    char * pszName = nameFuf;
    3572 //    sprintf(pszName, "%s%d", VBOXQGL_STATE_NAMEBASE, intsId);
    3573 //    int rc = SSMR3RegisterExternal(
    3574 //            pVM,                    /* The VM handle*/
    3575 //            pszName,                /* Data unit name. */
    3576 //            intsId,                 /* The instance identifier of the data unit.
    3577 //                                     * This must together with the name be unique. */
    3578 //            VBOXQGL_STATE_VERSION,   /* Data layout version number. */
    3579 //            128,             /* The approximate amount of data in the unit.
    3580 //                              * Only for progress indicators. */
    3581 //            NULL, NULL, NULL, /* pfnLiveXxx */
    3582 //            NULL,            /* Prepare save callback, optional. */
    3583 //            vboxQGLSaveExec, /* Execute save callback, optional. */
    3584 //            NULL,            /* Done save callback, optional. */
    3585 //            NULL,            /* Prepare load callback, optional. */
    3586 //            vboxQGLLoadExec, /* Execute load callback, optional. */
    3587 //            NULL,            /* Done load callback, optional. */
    3588 //            this             /* User argument. */
    3589 //            );
    3590 //    AssertRC(rc);
    3591     mpvVRAM = pCmd->pvVRAM;
    3592     mcbVRAM = pCmd->cbVRAM;
    3593     return VINF_SUCCESS;
    3594 }
    3595 
    3596 uchar *VBoxVHWAImage::vboxVRAMAddressFromOffset(uint64_t offset)
    3597 {
    3598     /** @todo check vramSize() */
    3599     return (offset != VBOXVHWA_OFFSET64_VOID) ? ((uint8_t *)vramBase()) + offset : NULL;
    3600 }
    3601 
    3602 uint64_t VBoxVHWAImage::vboxVRAMOffsetFromAddress(uchar *addr)
    3603 {
    3604     return uint64_t(addr - ((uchar *)vramBase()));
    3605 }
    3606 
    3607 uint64_t VBoxVHWAImage::vboxVRAMOffset(VBoxVHWASurfaceBase *pSurf)
    3608 {
    3609     return pSurf->addressAlocated() ? VBOXVHWA_OFFSET64_VOID : vboxVRAMOffsetFromAddress(pSurf->address());
    3610 }
    3611 
    3612 #endif
    3613 
    3614 #ifdef VBOXQGL_DBG_SURF
    3615 
    3616 int g_iCur = 0;
    3617 VBoxVHWASurfaceBase *g_apSurf[] = {NULL, NULL, NULL};
    3618 
    3619 void VBoxVHWAImage::vboxDoTestSurfaces(void *context)
    3620 {
    3621     if (g_iCur >= RT_ELEMENTS(g_apSurf))
    3622         g_iCur = 0;
    3623     VBoxVHWASurfaceBase * pSurf1 = g_apSurf[g_iCur];
    3624     if (pSurf1)
    3625         pSurf1->getComplexList()->setCurrentVisible(pSurf1);
    3626 }
    3627 #endif
    3628 
    3629 void VBoxVHWAImage::vboxDoUpdateViewport(const QRect & aRect)
    3630 {
    3631     adjustViewport(mDisplay.getPrimary()->size(), aRect);
    3632     mViewport = aRect;
    3633 
    3634     const SurfList &primaryList = mDisplay.primaries().surfaces();
    3635 
    3636     for (SurfList::const_iterator pr = primaryList.begin(); pr != primaryList.end(); ++pr)
    3637     {
    3638         VBoxVHWASurfaceBase *pSurf = *pr;
    3639         pSurf->updateVisibility(NULL, aRect, false, false);
    3640     }
    3641 
    3642     const OverlayList & overlays = mDisplay.overlays();
    3643     QRect overInter = overlaysRectIntersection();
    3644     overInter = overInter.intersected(aRect);
    3645 
    3646     bool bDisplayPrimary = true;
    3647 
    3648     for (OverlayList::const_iterator it = overlays.begin(); it != overlays.end(); ++it)
    3649     {
    3650         VBoxVHWASurfList *pSurfList = *it;
    3651         const SurfList &surfaces = pSurfList->surfaces();
    3652         if (surfaces.size())
    3653         {
    3654             bool bNotIntersected = !overInter.isEmpty() && surfaces.front()->targRect().contains(overInter);
    3655             Assert(bNotIntersected);
    3656 
    3657             bDisplayPrimary &= !bNotIntersected;
    3658             for (SurfList::const_iterator sit = surfaces.begin();
    3659                  sit != surfaces.end(); ++ sit)
    3660             {
    3661                 VBoxVHWASurfaceBase *pSurf = *sit;
    3662                 pSurf->updateVisibility(mDisplay.getPrimary(), aRect, bNotIntersected, false);
    3663             }
    3664         }
    3665     }
    3666 
    3667     Assert(!bDisplayPrimary);
    3668     mDisplay.setDisplayPrimary(bDisplayPrimary);
    3669 }
    3670 
    3671 bool VBoxVHWAImage::hasSurfaces() const
    3672 {
    3673     if (mDisplay.overlays().size() != 0)
    3674         return true;
    3675     if (mDisplay.primaries().size() > 1)
    3676         return true;
    3677     /* in case gl was never turned on, we have no surfaces at all including VGA */
    3678     if (!mDisplay.getVGA())
    3679         return false;
    3680     return mDisplay.getVGA()->handle() != VBOXVHWA_SURFHANDLE_INVALID;
    3681 }
    3682 
    3683 bool VBoxVHWAImage::hasVisibleOverlays()
    3684 {
    3685     const OverlayList &overlays = mDisplay.overlays();
    3686     for (OverlayList::const_iterator it = overlays.begin(); it != overlays.end(); ++ it)
    3687     {
    3688         VBoxVHWASurfList * pSurfList = *it;
    3689         if (pSurfList->current() != NULL)
    3690             return true;
    3691     }
    3692     return false;
    3693 }
    3694 
    3695 QRect VBoxVHWAImage::overlaysRectUnion()
    3696 {
    3697     const OverlayList &overlays = mDisplay.overlays();
    3698     VBoxVHWADirtyRect un;
    3699     for (OverlayList::const_iterator it = overlays.begin(); it != overlays.end(); ++ it)
    3700     {
    3701         VBoxVHWASurfaceBase *pOverlay = (*it)->current();
    3702         if (pOverlay != NULL)
    3703             un.add(pOverlay->targRect());
    3704     }
    3705     return un.toRect();
    3706 }
    3707 
    3708 QRect VBoxVHWAImage::overlaysRectIntersection()
    3709 {
    3710     const OverlayList &overlays = mDisplay.overlays();
    3711     QRect rect;
    3712     VBoxVHWADirtyRect un;
    3713     for (OverlayList::const_iterator it = overlays.begin(); it != overlays.end(); ++ it)
    3714     {
    3715         VBoxVHWASurfaceBase *pOverlay = (*it)->current();
    3716         if (pOverlay != NULL)
    3717         {
    3718             if (rect.isNull())
    3719                 rect = pOverlay->targRect();
    3720             else
    3721             {
    3722                 rect = rect.intersected(pOverlay->targRect());
    3723                 if (rect.isNull())
    3724                     break;
    3725             }
    3726         }
    3727     }
    3728     return rect;
    3729 }
    3730 
    3731 void VBoxVHWAImage::vboxDoUpdateRect(const QRect *pRect)
    3732 {
    3733     mDisplay.getPrimary()->updatedMem(pRect);
    3734 }
    3735 
    3736 void VBoxVHWAImage::resize(const VBoxFBSizeInfo &size)
    3737 {
    3738     VBOXQGL_CHECKERR(
    3739             vboxglActiveTexture(GL_TEXTURE0);
    3740         );
    3741 
    3742     bool remind = false;
    3743     bool fallback = false;
    3744 
    3745     VBOXQGLLOG(("resizing: fmt=%d, vram=%p, bpp=%d, bpl=%d, width=%d, height=%d\n",
    3746                 size.pixelFormat(), size.VRAM(),
    3747                 size.bitsPerPixel(), size.bytesPerLine(),
    3748                 size.width(), size.height()));
    3749 
    3750     /* clean the old values first */
    3751 
    3752     ulong    bytesPerLine = 0; /* Shut up MSC. */
    3753     uint32_t bitsPerPixel = 0; /* Shut up MSC. */
    3754     uint32_t b =     0xff;
    3755     uint32_t g =   0xff00;
    3756     uint32_t r = 0xff0000;
    3757     bool fUsesGuestVram = false; /* Shut up MSC. */
    3758 
    3759     /* check if we support the pixel format and can use the guest VRAM directly */
    3760     if (size.pixelFormat() == KBitmapFormat_BGR)
    3761     {
    3762 
    3763         bitsPerPixel = size.bitsPerPixel();
    3764         bytesPerLine = size.bytesPerLine();
    3765         ulong bitsPerLine = bytesPerLine * 8;
    3766 
    3767         switch (bitsPerPixel)
    3768         {
    3769             case 32:
    3770                 break;
    3771             case 24:
    3772 #ifdef DEBUG_misha
    3773                 AssertFailed();
    3774 #endif
    3775                 break;
    3776             case 8:
    3777 #ifdef DEBUG_misha
    3778                 AssertFailed();
    3779 #endif
    3780                 g = b = 0;
    3781                 remind = true;
    3782                 break;
    3783             case 1:
    3784 #ifdef DEBUG_misha
    3785                 AssertFailed();
    3786 #endif
    3787                 r = 1;
    3788                 g = b = 0;
    3789                 remind = true;
    3790                 break;
    3791             default:
    3792 #ifdef DEBUG_misha
    3793                 AssertFailed();
    3794 #endif
    3795                 remind = true;
    3796                 fallback = true;
    3797                 break;
    3798         }
    3799 
    3800         if (!fallback)
    3801         {
    3802             /* QImage only supports 32-bit aligned scan lines... */
    3803             Assert ((size.bytesPerLine() & 3) == 0);
    3804             fallback = ((size.bytesPerLine() & 3) != 0);
    3805             Assert(!fallback);
    3806         }
    3807         if (!fallback)
    3808         {
    3809             /* ...and the scan lines ought to be a whole number of pixels. */
    3810             Assert ((bitsPerLine & (size.bitsPerPixel() - 1)) == 0);
    3811             fallback = ((bitsPerLine & (size.bitsPerPixel() - 1)) != 0);
    3812             Assert(!fallback);
    3813         }
    3814         if (!fallback)
    3815         {
    3816             // ulong virtWdt = bitsPerLine / size.bitsPerPixel();
    3817             fUsesGuestVram = true;
    3818         }
    3819     }
    3820     else
    3821     {
    3822         AssertFailed();
    3823         fallback = true;
    3824     }
    3825 
    3826     if (fallback)
    3827     {
    3828         /* we should never come to fallback more now */
    3829         AssertFailed();
    3830         /* we don't support either the pixel format or the color depth,
    3831          * fallback to a self-provided 32bpp RGB buffer */
    3832         bitsPerPixel = 32;
    3833         b = 0xff;
    3834         g = 0xff00;
    3835         r = 0xff0000;
    3836         bytesPerLine = size.width() * bitsPerPixel / 8;
    3837         fUsesGuestVram = false;
    3838     }
    3839 
    3840     ulong bytesPerPixel = bitsPerPixel / 8;
    3841     const QSize scaledSize = size.scaledSize();
    3842     const ulong displayWidth = scaledSize.isValid() ? scaledSize.width() : bytesPerLine / bytesPerPixel;
    3843     const ulong displayHeight = scaledSize.isValid() ? scaledSize.height() : size.height();
    3844 
    3845 #ifdef VBOXQGL_DBG_SURF
    3846     for (int i = 0; i < RT_ELEMENTS(g_apSurf); i++)
    3847     {
    3848         VBoxVHWASurfaceBase * pSurf1 = g_apSurf[i];
    3849         if (pSurf1)
    3850         {
    3851             VBoxVHWASurfList *pConstructingList = pSurf1->getComplexList();
    3852             delete pSurf1;
    3853             if (pConstructingList)
    3854                 delete pConstructingList;
    3855         }
    3856     }
    3857 #endif
    3858 
    3859     VBoxVHWASurfaceBase *pDisplay = mDisplay.setVGA(NULL);
    3860     if (pDisplay)
    3861         delete pDisplay;
    3862 
    3863     VBoxVHWAColorFormat format(bitsPerPixel, r,g,b);
    3864     QSize dispSize(displayWidth, displayHeight);
    3865     QRect dispRect(0, 0, displayWidth, displayHeight);
    3866     pDisplay = new VBoxVHWASurfaceBase(this,
    3867                                        dispSize,
    3868                                        dispRect,
    3869                                        dispRect,
    3870                                        dispRect, /* we do not know viewport at the stage of precise, set as a
    3871                                                     disp rect, it will be updated on repaint */
    3872                                        format,
    3873                                        NULL, NULL, NULL, NULL,
    3874 #ifdef VBOXVHWA_USE_TEXGROUP
    3875                                        0,
    3876 #endif
    3877                                        0 /* VBOXVHWAIMG_TYPE fFlags */);
    3878     pDisplay->init(NULL, fUsesGuestVram ? size.VRAM() : NULL);
    3879     mDisplay.setVGA(pDisplay);
    3880 //    VBOXQGLLOG(("\n\n*******\n\n     viewport size is: (%d):(%d)\n\n*******\n\n", size().width(), size().height()));
    3881     mViewport = QRect(0,0,displayWidth, displayHeight);
    3882     adjustViewport(dispSize, mViewport);
    3883     setupMatricies(dispSize, true);
    3884 
    3885 #ifdef VBOXQGL_DBG_SURF
    3886     {
    3887         uint32_t width = 100;
    3888         uint32_t height = 60;
    3889 
    3890         for (int i = 0; i < RT_ELEMENTS(g_apSurf); i++)
    3891         {
    3892             VBoxVHWAColorFormat tmpFormat(FOURCC_YV12);
    3893             QSize tmpSize(width, height) ;
    3894             VBoxVHWASurfaceBase *pSurf1 = new VBoxVHWASurfaceBase(this, tmpSize,
    3895                                                                   mDisplay.getPrimary()->rect(),
    3896                                                                   QRect(0, 0, width, height),
    3897                                                                   mViewport,
    3898                                                                   tmpFormat,
    3899                                                                   NULL, NULL, NULL, &VBoxVHWAColorKey(0,0),
    3900 #ifdef VBOXVHWA_USE_TEXGROUP
    3901                                                                   0,
    3902 #endif
    3903                                                                   false);
    3904 
    3905             Assert(mDisplay.getVGA());
    3906             pSurf1->init(mDisplay.getVGA(), NULL);
    3907             uchar *addr = pSurf1->address();
    3908             uchar cur = 0;
    3909             for (uint32_t k = 0; k < width*height; k++)
    3910             {
    3911                 addr[k] = cur;
    3912                 cur+=64;
    3913             }
    3914             pSurf1->updatedMem(&QRect(0,0,width, height));
    3915 
    3916             VBoxVHWASurfList *pConstructingList = new VBoxVHWASurfList();
    3917             mDisplay.addOverlay(pConstructingList);
    3918             pConstructingList->add(pSurf1);
    3919             g_apSurf[i] = pSurf1;
    3920 
    3921         }
    3922 
    3923         VBOXVHWACMD_SURF_OVERLAY_UPDATE updateCmd;
    3924         memset(&updateCmd, 0, sizeof(updateCmd));
    3925         updateCmd.u.in.hSrcSurf = (VBOXVHWA_SURFHANDLE)g_apSurf[0];
    3926         updateCmd.u.in.hDstSurf = (VBOXVHWA_SURFHANDLE)pDisplay;
    3927         updateCmd.u.in.flags = VBOXVHWA_OVER_SHOW
    3928                              | VBOXVHWA_OVER_KEYDESTOVERRIDE;
    3929 
    3930         updateCmd.u.in.desc.DstCK.high = 1;
    3931         updateCmd.u.in.desc.DstCK.low = 1;
    3932 
    3933         updateCmd.u.in.dstRect.left = 0;
    3934         updateCmd.u.in.dstRect.right = pDisplay->width();
    3935         updateCmd.u.in.dstRect.top = (pDisplay->height() - height) / 2;
    3936         updateCmd.u.in.dstRect.bottom = updateCmd.u.in.dstRect.top + height;
    3937 
    3938         updateCmd.u.in.srcRect.left = 0;
    3939         updateCmd.u.in.srcRect.right = width;
    3940         updateCmd.u.in.srcRect.top = 0;
    3941         updateCmd.u.in.srcRect.bottom = height;
    3942 
    3943         updateCmd.u.in.offDstSurface = VBOXVHWA_OFFSET64_VOID; /* just a magic to avoid surf mem buffer change  */
    3944         updateCmd.u.in.offSrcSurface = VBOXVHWA_OFFSET64_VOID; /* just a magic to avoid surf mem buffer change  */
    3945 
    3946         vhwaSurfaceOverlayUpdate(&updateCmd);
    3947     }
    3948 #endif
    3949 
    3950 //    if (!mOnResizeCmdList.empty())
    3951 //    {
    3952 //        for (VHWACommandList::const_iterator it = mOnResizeCmdList.begin();
    3953 //             it != mOnResizeCmdList.end(); ++ it)
    3954 //        {
    3955 //            VBOXVHWACMD * pCmd = (*it);
    3956 //            vboxDoVHWACmdExec(pCmd);
    3957 //            free(pCmd);
    3958 //        }
    3959 //        mOnResizeCmdList.clear();
    3960 //    }
    3961 
    3962     if (remind)
    3963         popupCenter().remindAboutWrongColorDepth(windowManager().mainWindowShown(), size.bitsPerPixel(), 32);
    3964     else
    3965         popupCenter().forgetAboutWrongColorDepth(windowManager().mainWindowShown());
    3966 }
    3967 
    3968 VBoxVHWAColorFormat::VBoxVHWAColorFormat (uint32_t bitsPerPixel, uint32_t r, uint32_t g, uint32_t b)
    3969     : mWidthCompression(1)
    3970     , mHeightCompression(1)
    3971 {
    3972     init(bitsPerPixel, r, g, b);
    3973 }
    3974 
    3975 VBoxVHWAColorFormat::VBoxVHWAColorFormat(uint32_t fourcc)
    3976     : mWidthCompression(1)
    3977     , mHeightCompression(1)
    3978 {
    3979     init(fourcc);
    3980 }
    3981 
    3982 void VBoxVHWAColorFormat::init(uint32_t fourcc)
    3983 {
    3984     mDataFormat = fourcc;
    3985     mInternalFormat = GL_RGBA8;//GL_RGB;
    3986     mFormat = GL_BGRA_EXT;//GL_RGBA;
    3987     mType = GL_UNSIGNED_BYTE;
    3988     mR = VBoxVHWAColorComponent(0xff);
    3989     mG = VBoxVHWAColorComponent(0xff);
    3990     mB = VBoxVHWAColorComponent(0xff);
    3991     mA = VBoxVHWAColorComponent(0xff);
    3992     mBitsPerPixelTex = 32;
    3993 
    3994     switch(fourcc)
    3995     {
    3996         case FOURCC_AYUV:
    3997             mBitsPerPixel = 32;
    3998             mWidthCompression = 1;
    3999             break;
    4000         case FOURCC_UYVY:
    4001         case FOURCC_YUY2:
    4002             mBitsPerPixel = 16;
    4003             mWidthCompression = 2;
    4004             break;
    4005         case FOURCC_YV12:
    4006             mBitsPerPixel = 8;
    4007             mWidthCompression = 4;
    4008             break;
    4009         default:
    4010             AssertFailed();
    4011             mBitsPerPixel = 0;
    4012             mBitsPerPixelTex = 0;
    4013             mWidthCompression = 0;
    4014             break;
    4015     }
    4016 }
    4017 
    4018 void VBoxVHWAColorFormat::init(uint32_t bitsPerPixel, uint32_t r, uint32_t g, uint32_t b)
    4019 {
    4020     mBitsPerPixel = bitsPerPixel;
    4021     mBitsPerPixelTex = bitsPerPixel;
    4022     mDataFormat = 0;
    4023     switch (bitsPerPixel)
    4024     {
    4025         case 32:
    4026             mInternalFormat = GL_RGB;//3;//GL_RGB;
    4027             mFormat = GL_BGRA_EXT;//GL_RGBA;
    4028             mType = GL_UNSIGNED_BYTE;
    4029             mR = VBoxVHWAColorComponent(r);
    4030             mG = VBoxVHWAColorComponent(g);
    4031             mB = VBoxVHWAColorComponent(b);
    4032             break;
    4033         case 24:
    4034 #ifdef DEBUG_misha
    4035             AssertFailed();
    4036 #endif
    4037             mInternalFormat = 3;//GL_RGB;
    4038             mFormat = GL_BGR_EXT;
    4039             mType = GL_UNSIGNED_BYTE;
    4040             mR = VBoxVHWAColorComponent(r);
    4041             mG = VBoxVHWAColorComponent(g);
    4042             mB = VBoxVHWAColorComponent(b);
    4043             break;
    4044         case 16:
    4045 #ifdef DEBUG_misha
    4046             AssertFailed();
    4047 #endif
    4048             mInternalFormat = GL_RGB5;
    4049             mFormat = GL_BGR_EXT;
    4050             mType = GL_UNSIGNED_BYTE; /** @todo ??? */
    4051             mR = VBoxVHWAColorComponent(r);
    4052             mG = VBoxVHWAColorComponent(g);
    4053             mB = VBoxVHWAColorComponent(b);
    4054             break;
    4055         case 8:
    4056 #ifdef DEBUG_misha
    4057             AssertFailed();
    4058 #endif
    4059             mInternalFormat = 1;//GL_RGB;
    4060             mFormat = GL_RED;//GL_RGB;
    4061             mType = GL_UNSIGNED_BYTE;
    4062             mR = VBoxVHWAColorComponent(0xff);
    4063             break;
    4064         case 1:
    4065 #ifdef DEBUG_misha
    4066             AssertFailed();
    4067 #endif
    4068             mInternalFormat = 1;
    4069             mFormat = GL_COLOR_INDEX;
    4070             mType = GL_BITMAP;
    4071             mR = VBoxVHWAColorComponent(0x1);
    4072             break;
    4073         default:
    4074 #ifdef DEBUG_misha
    4075             AssertFailed();
    4076 #endif
    4077             mBitsPerPixel = 0;
    4078             mBitsPerPixelTex = 0;
    4079             break;
    4080     }
    4081 }
    4082 
    4083 bool VBoxVHWAColorFormat::equals(const VBoxVHWAColorFormat &other) const
    4084 {
    4085     if (fourcc())
    4086         return fourcc() == other.fourcc();
    4087     if (other.fourcc())
    4088         return false;
    4089 
    4090     return bitsPerPixel() == other.bitsPerPixel();
    4091 }
    4092 
    4093 VBoxVHWAColorComponent::VBoxVHWAColorComponent (uint32_t aMask)
    4094 {
    4095     unsigned f = ASMBitFirstSetU32(aMask);
    4096     if (f)
    4097     {
    4098         mOffset = f - 1;
    4099         f = ASMBitFirstSetU32(~(aMask >> mOffset));
    4100         if (f)
    4101             mcBits = f - 1;
    4102         else
    4103             mcBits = 32 - mOffset;
    4104 
    4105         Assert(mcBits);
    4106         mMask = (((uint32_t)0xffffffff) >> (32 - mcBits)) << mOffset;
    4107         Assert(mMask == aMask);
    4108 
    4109         mRange = (mMask >> mOffset) + 1;
    4110     }
    4111     else
    4112     {
    4113         mMask = 0;
    4114         mRange = 0;
    4115         mOffset = 32;
    4116         mcBits = 0;
    4117     }
    4118 }
    4119 
    4120 void VBoxVHWAColorFormat::pixel2Normalized(uint32_t pix, float *r, float *g, float *b) const
    4121 {
    4122     *r = mR.colorValNorm(pix);
    4123     *g = mG.colorValNorm(pix);
    4124     *b = mB.colorValNorm(pix);
    4125 }
    4126 
    4127 VBoxQGLOverlay::VBoxQGLOverlay()
    4128     : mpOverlayWgt(NULL)
    4129     , mpViewport(NULL)
    4130     , mGlOn(false)
    4131     , mOverlayWidgetVisible(false)
    4132     , mOverlayVisible(false)
    4133     , mGlCurrent(false)
    4134     , mProcessingCommands(false)
    4135     , mNeedOverlayRepaint(false)
    4136     , mNeedSetVisible(false)
    4137     , mCmdPipe()
    4138     , mSettings()
    4139     , mpSession()
    4140     , mpShareWgt(NULL)
    4141     , m_id(0)
    4142 {
    4143     /* postpone the gl widget initialization to avoid conflict with 3D on Mac */
    4144 }
    4145 
    4146 void VBoxQGLOverlay::init(QWidget *pViewport, QObject *pPostEventObject, CSession *aSession, uint32_t id)
    4147 {
    4148     mpViewport = pViewport;
    4149     mpSession = aSession;
    4150     m_id = id;
    4151     mSettings.init(*aSession);
    4152     mCmdPipe.init(pPostEventObject);
    4153 }
    4154 
    4155 class VBoxGLShareWgt : public QGLWidget
    4156 {
    4157 public:
    4158     VBoxGLShareWgt()
    4159         : QGLWidget(new VBoxGLContext(VBoxVHWAImage::vboxGLFormat()))
    4160     {
    4161         /* work-around to disable done current needed to old ATI drivers on Linux */
    4162         VBoxGLContext *pc = (VBoxGLContext *)context();
    4163         pc->allowDoneCurrent(false);
    4164     }
    4165 
    4166 protected:
    4167     void initializeGL()
    4168     {
    4169         vboxVHWAGetSupportInfo(context());
    4170         VBoxVHWASurfaceBase::globalInit();
    4171     }
    4172 };
    4173 void VBoxQGLOverlay::initGl()
    4174 {
    4175     if (mpOverlayWgt)
    4176     {
    4177         Assert(mpShareWgt);
    4178         return;
    4179     }
    4180 
    4181     if (!mpShareWgt)
    4182     {
    4183         mpShareWgt = new VBoxGLShareWgt();
    4184         /* force initializeGL */
    4185         mpShareWgt->updateGL();
    4186     }
    4187 
    4188     mOverlayImage.init(&mSettings);
    4189     mpOverlayWgt = new VBoxGLWgt(&mOverlayImage, mpViewport, mpShareWgt);
    4190 
    4191     mOverlayWidgetVisible = true; /* to ensure it is set hidden with vboxShowOverlay */
    4192     vboxShowOverlay(false);
    4193 
    4194     mpOverlayWgt->setMouseTracking(true);
    4195 }
    4196 
    4197 void VBoxQGLOverlay::updateAttachment(QWidget *pViewport, QObject *pPostEventObject)
    4198 {
    4199     if (mpViewport != pViewport)
    4200     {
    4201         mpViewport = pViewport;
    4202         mpOverlayWgt = NULL;
    4203         mOverlayWidgetVisible = false;
    4204         if (mOverlayImage.hasSurfaces())
    4205         {
    4206 //            Assert(!mOverlayVisible);
    4207             if (pViewport)
    4208             {
    4209                 initGl();
    4210 //            vboxDoCheckUpdateViewport();
    4211             }
    4212 //            Assert(!mOverlayVisible);
    4213         }
    4214         mGlCurrent = false;
    4215     }
    4216     mCmdPipe.setNotifyObject(pPostEventObject);
    4217 }
    4218 
    4219 int VBoxQGLOverlay::reset()
    4220 {
    4221     CDisplay display = mpSession->GetConsole().GetDisplay();
    4222     Assert (!display.isNull());
    4223 
    4224     mCmdPipe.reset(&display);
    4225 
    4226     resetGl();
    4227 
    4228     return VINF_SUCCESS;
    4229 }
    4230 
    4231 static DECLCALLBACK(void) vbvaVHWAHHCommandFreeCmd(void *pvContext)
    4232 {
    4233     free(pvContext);
    4234 }
    4235 
    4236 int VBoxQGLOverlay::resetGl()
    4237 {
    4238     VHWACommandList list;
    4239     int rc = mOverlayImage.reset(&list);
    4240     AssertRC(rc);
    4241     if (RT_SUCCESS(rc))
    4242     {
    4243         for (VHWACommandList::const_iterator sIt = list.begin(); sIt != list.end(); ++ sIt)
    4244         {
    4245             VBOXVHWACMD *pCmd = (*sIt);
    4246             VBOXVHWA_HH_CALLBACK_SET(pCmd, vbvaVHWAHHCommandFreeCmd, pCmd);
    4247             mCmdPipe.postCmd(VBOXVHWA_PIPECMD_VHWA, pCmd, pCmd->enmCmd, false /*fGuestCmd*/);
    4248         }
    4249     }
    4250     return VINF_SUCCESS;
    4251 }
    4252 
    4253 int VBoxQGLOverlay::onVHWACommand(struct VBOXVHWACMD RT_UNTRUSTED_VOLATILE_GUEST *pCmd,
    4254                                   int /*VBOXVHWACMD_TYPE*/ enmCmdInt, bool fGuestCmd)
    4255 {
    4256     VBOXVHWACMD_TYPE const enmCmd = (VBOXVHWACMD_TYPE)enmCmdInt;
    4257     Log(("VHWA Command >>> %#p, %d\n", pCmd, enmCmd));
    4258     switch (enmCmd)
    4259     {
    4260         case VBOXVHWACMD_TYPE_SURF_FLIP:
    4261         case VBOXVHWACMD_TYPE_SURF_OVERLAY_UPDATE:
    4262         case VBOXVHWACMD_TYPE_SURF_OVERLAY_SETPOSITION:
    4263             break;
    4264         case VBOXVHWACMD_TYPE_HH_CONSTRUCT:
    4265         {
    4266             pCmd->Flags &= ~VBOXVHWACMD_FLAG_HG_ASYNCH;
    4267             ASSERT_GUEST_STMT_RETURN(!fGuestCmd, pCmd->rc = VERR_ACCESS_DENIED, VINF_SUCCESS);
    4268             VBOXVHWACMD_HH_CONSTRUCT *pBody = VBOXVHWACMD_BODY_HOST_HEAP(pCmd, VBOXVHWACMD_HH_CONSTRUCT);
    4269             pCmd->rc = vhwaConstruct(pBody);
    4270             Log(("VHWA Command <<< Sync %#p, %d\n", pCmd, enmCmd));
    4271             return VINF_SUCCESS;
    4272         }
    4273 
    4274         case VBOXVHWACMD_TYPE_HH_RESET:
    4275         {
    4276             pCmd->Flags &= ~VBOXVHWACMD_FLAG_HG_ASYNCH;
    4277             ASSERT_GUEST_STMT_RETURN(!fGuestCmd, pCmd->rc = VERR_ACCESS_DENIED, VINF_SUCCESS);
    4278             /* we do not post a reset command to the gui thread since this may lead to a deadlock
    4279              * when reset is initiated by the gui thread*/
    4280             pCmd->rc = reset();
    4281             Log(("VHWA Command <<< Sync %#p, %d\n", pCmd, enmCmd));
    4282             return VINF_SUCCESS;
    4283         }
    4284 
    4285         case VBOXVHWACMD_TYPE_HH_ENABLE:
    4286             pCmd->Flags &= ~VBOXVHWACMD_FLAG_HG_ASYNCH;
    4287             ASSERT_GUEST_STMT_RETURN(!fGuestCmd, pCmd->rc = VERR_ACCESS_DENIED, VINF_SUCCESS);
    4288             pCmd->rc = VINF_SUCCESS;
    4289             Log(("VHWA Command <<< Sync %#p, %d\n", pCmd, enmCmd));
    4290             return VINF_SUCCESS;
    4291 
    4292         case VBOXVHWACMD_TYPE_HH_DISABLE:
    4293             pCmd->Flags &= ~VBOXVHWACMD_FLAG_HG_ASYNCH;
    4294             ASSERT_GUEST_STMT_RETURN(!fGuestCmd, pCmd->rc = VERR_ACCESS_DENIED, VINF_SUCCESS);
    4295             pCmd->rc = VINF_SUCCESS;
    4296             Log(("VHWA Command <<< Sync %#p, %d\n", pCmd, enmCmd));
    4297             return VINF_SUCCESS;
    4298 
    4299         case VBOXVHWACMD_TYPE_HH_SAVESTATE_SAVEBEGIN:
    4300             pCmd->Flags &= ~VBOXVHWACMD_FLAG_HG_ASYNCH;
    4301             ASSERT_GUEST_STMT_RETURN(!fGuestCmd, pCmd->rc = VERR_ACCESS_DENIED, VINF_SUCCESS);
    4302             mCmdPipe.disable();
    4303             pCmd->rc = VINF_SUCCESS;
    4304             Log(("VHWA Command <<< Sync %#p, %d\n", pCmd, enmCmd));
    4305             return VINF_SUCCESS;
    4306 
    4307         case VBOXVHWACMD_TYPE_HH_SAVESTATE_SAVEEND:
    4308             ASSERT_GUEST_STMT_RETURN(!fGuestCmd, pCmd->rc = VERR_ACCESS_DENIED, VINF_SUCCESS);
    4309             pCmd->Flags &= ~VBOXVHWACMD_FLAG_HG_ASYNCH;
    4310             mCmdPipe.enable();
    4311             pCmd->rc = VINF_SUCCESS;
    4312             Log(("VHWA Command <<< Sync %#p, %d\n", pCmd, enmCmd));
    4313             return VINF_SUCCESS;
    4314 
    4315         case VBOXVHWACMD_TYPE_HH_SAVESTATE_SAVEPERFORM:
    4316         {
    4317             pCmd->Flags &= ~VBOXVHWACMD_FLAG_HG_ASYNCH;
    4318             ASSERT_GUEST_STMT_RETURN(!fGuestCmd, pCmd->rc = VERR_ACCESS_DENIED, VINF_SUCCESS);
    4319             VBOXVHWACMD_HH_SAVESTATE_SAVEPERFORM *pSave = VBOXVHWACMD_BODY_HOST_HEAP(pCmd, VBOXVHWACMD_HH_SAVESTATE_SAVEPERFORM);
    4320             PSSMHANDLE pSSM = pSave->pSSM;
    4321             int rc = SSMR3PutU32(pSSM, VBOXQGL_STATE_VERSION); AssertRC(rc);
    4322             if (RT_SUCCESS(rc))
    4323                 vhwaSaveExec(pSSM);
    4324             pCmd->rc = rc;
    4325             Log(("VHWA Command <<< Sync %#p, %d\n", pCmd, enmCmd));
    4326             return VINF_SUCCESS;
    4327         }
    4328         case VBOXVHWACMD_TYPE_HH_SAVESTATE_LOADPERFORM:
    4329         {
    4330             pCmd->Flags &= ~VBOXVHWACMD_FLAG_HG_ASYNCH;
    4331             ASSERT_GUEST_STMT_RETURN(!fGuestCmd, pCmd->rc = VERR_ACCESS_DENIED, VINF_SUCCESS);
    4332             VBOXVHWACMD_HH_SAVESTATE_LOADPERFORM *pLoad = VBOXVHWACMD_BODY_HOST_HEAP(pCmd, VBOXVHWACMD_HH_SAVESTATE_LOADPERFORM);
    4333             PSSMHANDLE pSSM = pLoad->pSSM;
    4334             uint32_t u32Version = 0;
    4335             int rc = SSMR3GetU32(pSSM, &u32Version); Assert(RT_SUCCESS(rc) || rc == VERR_SSM_LOADED_TOO_MUCH);
    4336             if (RT_SUCCESS(rc))
    4337             {
    4338                 rc = vhwaLoadExec(pSSM, u32Version);
    4339                 AssertRC(rc);
    4340             }
    4341             else
    4342             {
    4343                 /* sanity */
    4344                 u32Version = 0;
    4345 
    4346                 if (rc == VERR_SSM_LOADED_TOO_MUCH)
    4347                     rc = VINF_SUCCESS;
    4348             }
    4349             pCmd->rc = rc;
    4350             Log(("VHWA Command <<< Sync %#p, %d\n", pCmd, enmCmd));
    4351             return VINF_SUCCESS;
    4352         }
    4353 
    4354         case VBOXVHWACMD_TYPE_QUERY_INFO1:
    4355         {
    4356 #ifdef RT_STRICT
    4357             VBOXVHWACMD_QUERYINFO1 RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_QUERYINFO1);
    4358 #endif
    4359             Assert(pBody->u.in.guestVersion.maj == VBOXVHWA_VERSION_MAJ);
    4360             Assert(pBody->u.in.guestVersion.min == VBOXVHWA_VERSION_MIN);
    4361             Assert(pBody->u.in.guestVersion.bld == VBOXVHWA_VERSION_BLD);
    4362             Assert(pBody->u.in.guestVersion.reserved == VBOXVHWA_VERSION_RSV);
    4363             /* do NOT break!! make it proceed asynchronously */
    4364         }
    4365 
    4366         default:
    4367             break;
    4368     }
    4369 
    4370     Log(("VHWA Command --- Going Async %#p, %d\n", pCmd, enmCmd));
    4371     /* indicate that we process and complete the command asynchronously */
    4372     pCmd->Flags |= VBOXVHWACMD_FLAG_HG_ASYNCH;
    4373 
    4374     mCmdPipe.postCmd(VBOXVHWA_PIPECMD_VHWA, (void *)pCmd, enmCmd, fGuestCmd);
    4375     return VINF_CALLBACK_RETURN;
    4376 
    4377 }
    4378 
    4379 void VBoxQGLOverlay::onVHWACommandEvent(QEvent *pEvent)
    4380 {
    4381     VBoxVHWACommandProcessEvent *pVhwaEvent = (VBoxVHWACommandProcessEvent *)pEvent;
    4382     /* sanity actually */
    4383     pVhwaEvent->setProcessed();
    4384 
    4385     Assert(!mProcessingCommands);
    4386     mProcessingCommands = true;
    4387     Assert(!mGlCurrent);
    4388     mGlCurrent = false; /* just a fall-back */
    4389     VBoxVHWACommandElement *pCmd = mCmdPipe.getCmd();
    4390     if (pCmd)
    4391     {
    4392         processCmd(pCmd);
    4393         mCmdPipe.doneCmd();
    4394     }
    4395 
    4396     mProcessingCommands = false;
    4397     repaint();
    4398     mGlCurrent = false;
    4399 }
    4400 
    4401 bool VBoxQGLOverlay::onNotifyUpdate(ULONG uX, ULONG uY, ULONG uW, ULONG uH)
    4402 {
    4403     /* Prepare corresponding viewport part: */
    4404     QRect rect(uX, uY, uW, uH);
    4405 
    4406     /* Take the scaling into account: */
    4407     const double dScaleFactor = mSizeInfo.scaleFactor();
    4408     const QSize scaledSize = mSizeInfo.scaledSize();
    4409     if (scaledSize.isValid())
    4410     {
    4411         /* Calculate corresponding scale-factors: */
    4412         const double xScaleFactor = mSizeInfo.visualState() == UIVisualStateType_Scale
    4413                                   ? (double)scaledSize.width()  / mSizeInfo.width()  : dScaleFactor;
    4414         const double yScaleFactor = mSizeInfo.visualState() == UIVisualStateType_Scale
    4415                                   ? (double)scaledSize.height() / mSizeInfo.height() : dScaleFactor;
    4416         /* Adjust corresponding viewport part: */
    4417         rect.moveTo((int)floor((double)rect.x() * xScaleFactor) - 1,
    4418                     (int)floor((double)rect.y() * yScaleFactor) - 1);
    4419         rect.setSize(QSize((int)ceil((double)rect.width()  * xScaleFactor) + 2,
    4420                            (int)ceil((double)rect.height() * yScaleFactor) + 2));
    4421     }
    4422 
    4423     /* Take the device-pixel-ratio into account: */
    4424     if (mSizeInfo.useUnscaledHiDPIOutput())
    4425     {
    4426         const double dDevicePixelRatio = gpDesktop->devicePixelRatio(mpViewport->window());
    4427         if (dDevicePixelRatio > 1.0)
    4428         {
    4429             rect.moveTo((int)floor((double)rect.x() / dDevicePixelRatio) - 1,
    4430                         (int)floor((double)rect.y() / dDevicePixelRatio) - 1);
    4431             rect.setSize(QSize((int)ceil((double)rect.width()  / dDevicePixelRatio) + 2,
    4432                                (int)ceil((double)rect.height() / dDevicePixelRatio) + 2));
    4433         }
    4434     }
    4435 
    4436     /* we do not to miss notify updates, because we have to update bg textures for it,
    4437      * so no not check for m_fUnused here,
    4438      * mOverlay will store the required info for us */
    4439     mCmdPipe.postCmd(VBOXVHWA_PIPECMD_PAINT, &rect, -1, false);
    4440 
    4441     return true;
    4442 }
    4443 
    4444 void VBoxQGLOverlay::onResizeEventPostprocess(const VBoxFBSizeInfo &re, const QPoint &topLeft)
    4445 {
    4446     mSizeInfo = re;
    4447     mContentsTopLeft = topLeft;
    4448 
    4449     if (mGlOn)
    4450     {
    4451         Assert(mOverlayImage.hasSurfaces());
    4452         Assert(!mGlCurrent);
    4453         Assert(!mNeedOverlayRepaint);
    4454         mGlCurrent = false;
    4455         makeCurrent();
    4456         /* need to ensure we're in sync */
    4457         mNeedOverlayRepaint = vboxSynchGl();
    4458 
    4459         if (!mOverlayImage.hasSurfaces())
    4460             vboxSetGlOn(false);
    4461     }
    4462     else
    4463         Assert(!mOverlayImage.hasSurfaces());
    4464 
    4465     if (!mOnResizeCmdList.empty())
    4466     {
    4467         for (VHWACommandList::const_iterator it = mOnResizeCmdList.begin(); it != mOnResizeCmdList.end(); ++ it)
    4468         {
    4469             VBOXVHWACMD *pCmd = (*it);
    4470             vboxDoVHWACmdExec(pCmd, pCmd->enmCmd, false);
    4471             free(pCmd);
    4472         }
    4473         mOnResizeCmdList.clear();
    4474     }
    4475 
    4476     repaintOverlay();
    4477     mGlCurrent = false;
    4478 }
    4479 
    4480 void VBoxQGLOverlay::repaintMain()
    4481 {
    4482     if (mMainDirtyRect.isClear())
    4483         return;
    4484 
    4485     const QRect &rect = mMainDirtyRect.rect();
    4486     if (mOverlayWidgetVisible)
    4487         if (mOverlayViewport.contains(rect))
    4488             return;
    4489 
    4490     mpViewport->repaint(rect.x() - mContentsTopLeft.x(),
    4491                         rect.y() - mContentsTopLeft.y(),
    4492                         rect.width(),
    4493                         rect.height());
    4494 
    4495     mMainDirtyRect.clear();
    4496 }
    4497 
    4498 void VBoxQGLOverlay::vboxDoVHWACmd(void RT_UNTRUSTED_VOLATILE_GUEST *pvCmd, int /*VBOXVHWACMD_TYPE*/ enmCmd, bool fGuestCmd)
    4499 {
    4500     vboxDoVHWACmdExec(pvCmd, enmCmd, fGuestCmd);
    4501 
    4502     CDisplay display = mpSession->GetConsole().GetDisplay();
    4503     Assert(!display.isNull());
    4504 
    4505     Log(("VHWA Command <<< Async %#p, %d\n", pvCmd, enmCmd));
    4506 
    4507     display.CompleteVHWACommand((BYTE *)pvCmd);
    4508 }
    4509 
    4510 bool VBoxQGLOverlay::vboxSynchGl()
    4511 {
    4512     VBoxVHWASurfaceBase *pVGA = mOverlayImage.vgaSurface();
    4513     if (   pVGA
    4514         && mSizeInfo.pixelFormat()  == pVGA->pixelFormat().toVBoxPixelFormat()
    4515         && mSizeInfo.VRAM()         == pVGA->address()
    4516         && mSizeInfo.bitsPerPixel() == pVGA->bitsPerPixel()
    4517         && mSizeInfo.bytesPerLine() == pVGA->bytesPerLine()
    4518         && mSizeInfo.width()        == pVGA->width()
    4519         && mSizeInfo.height()       == pVGA->height()
    4520        )
    4521     {
    4522         return false;
    4523     }
    4524     /* create and issue a resize event to the gl widget to ensure we have all gl data initialized
    4525      * and synchronized with the framebuffer */
    4526     mOverlayImage.resize(mSizeInfo);
    4527     return true;
    4528 }
    4529 
    4530 void VBoxQGLOverlay::vboxSetGlOn(bool on)
    4531 {
    4532     if (on == mGlOn)
    4533         return;
    4534 
    4535     mGlOn = on;
    4536 
    4537     if (on)
    4538     {
    4539         /* need to ensure we have gl functions initialized */
    4540         mpOverlayWgt->makeCurrent();
    4541         vboxVHWAGetSupportInfo(mpOverlayWgt->context());
    4542 
    4543         VBOXQGLLOGREL(("Switching Gl mode on\n"));
    4544         Assert(!mpOverlayWgt->isVisible());
    4545         /* just to ensure */
    4546         vboxShowOverlay(false);
    4547         mOverlayVisible = false;
    4548         vboxSynchGl();
    4549     }
    4550     else
    4551     {
    4552         VBOXQGLLOGREL(("Switching Gl mode off\n"));
    4553         mOverlayVisible = false;
    4554         vboxShowOverlay(false);
    4555         /* for now just set the flag w/o destroying anything */
    4556     }
    4557 }
    4558 
    4559 void VBoxQGLOverlay::vboxDoCheckUpdateViewport()
    4560 {
    4561     if (!mOverlayVisible)
    4562     {
    4563         vboxShowOverlay(false);
    4564         return;
    4565     }
    4566 
    4567     int cX = mContentsTopLeft.x();
    4568     int cY = mContentsTopLeft.y();
    4569     QRect fbVp(cX, cY, mpViewport->width(), mpViewport->height());
    4570     QRect overVp = fbVp.intersected(mOverlayViewport);
    4571 
    4572     if (overVp.isEmpty())
    4573         vboxShowOverlay(false);
    4574     else
    4575     {
    4576         if (overVp != mOverlayImage.vboxViewport())
    4577         {
    4578             makeCurrent();
    4579             mOverlayImage.vboxDoUpdateViewport(overVp);
    4580             mNeedOverlayRepaint = true;
    4581         }
    4582 
    4583         QRect rect(overVp.x() - cX, overVp.y() - cY, overVp.width(), overVp.height());
    4584 
    4585         vboxCheckUpdateOverlay(rect);
    4586 
    4587         vboxShowOverlay(true);
    4588 
    4589         /* workaround for linux ATI issue: need to update gl viewport after widget becomes visible */
    4590         mOverlayImage.vboxDoUpdateViewport(overVp);
    4591     }
    4592 }
    4593 
    4594 void VBoxQGLOverlay::vboxShowOverlay(bool show)
    4595 {
    4596     if (mOverlayWidgetVisible != show)
    4597     {
    4598         mpOverlayWgt->setVisible(show);
    4599         mOverlayWidgetVisible = show;
    4600         mGlCurrent = false;
    4601         if (!show)
    4602             mMainDirtyRect.add(mOverlayImage.vboxViewport());
    4603     }
    4604 }
    4605 
    4606 void VBoxQGLOverlay::vboxCheckUpdateOverlay(const QRect &rect)
    4607 {
    4608     QRect overRect(mpOverlayWgt->pos(), mpOverlayWgt->size());
    4609     if (overRect.x() != rect.x() || overRect.y() != rect.y())
    4610     {
    4611 #if defined(RT_OS_WINDOWS)
    4612         mpOverlayWgt->setVisible(false);
    4613         mNeedSetVisible = true;
    4614 #endif
    4615         VBOXQGLLOG_QRECT("moving wgt to " , &rect, "\n");
    4616         mpOverlayWgt->move(rect.x(), rect.y());
    4617         mGlCurrent = false;
    4618     }
    4619 
    4620     if (overRect.width() != rect.width() || overRect.height() != rect.height())
    4621     {
    4622 #if defined(RT_OS_WINDOWS)
    4623         mpOverlayWgt->setVisible(false);
    4624         mNeedSetVisible = true;
    4625 #endif
    4626         VBOXQGLLOG(("resizing wgt to w(%d) ,h(%d)\n" , rect.width(), rect.height()));
    4627         mpOverlayWgt->resize(rect.width(), rect.height());
    4628         mGlCurrent = false;
    4629     }
    4630 }
    4631 
    4632 void VBoxQGLOverlay::addMainDirtyRect(const QRect &aRect)
    4633 {
    4634     mMainDirtyRect.add(aRect);
    4635     if (mGlOn)
    4636     {
    4637         mOverlayImage.vboxDoUpdateRect(&aRect);
    4638         mNeedOverlayRepaint = true;
    4639     }
    4640 }
    4641 
    4642 int VBoxQGLOverlay::vhwaSurfaceUnlock(struct VBOXVHWACMD_SURF_UNLOCK RT_UNTRUSTED_VOLATILE_GUEST *pCmd)
    4643 {
    4644     int rc = mOverlayImage.vhwaSurfaceUnlock(pCmd);
    4645     VBoxVHWASurfaceBase *pVGA = mOverlayImage.vgaSurface();
    4646     const VBoxVHWADirtyRect &rect = pVGA->getDirtyRect();
    4647     mNeedOverlayRepaint = true;
    4648     if (!rect.isClear())
    4649         mMainDirtyRect.add(rect);
    4650     return rc;
    4651 }
    4652 
    4653 void VBoxQGLOverlay::vboxDoVHWACmdExec(void RT_UNTRUSTED_VOLATILE_GUEST *pvCmd, int /*VBOXVHWACMD_TYPE*/ enmCmdInt, bool fGuestCmd)
    4654 {
    4655     struct VBOXVHWACMD RT_UNTRUSTED_VOLATILE_GUEST *pCmd = (struct VBOXVHWACMD RT_UNTRUSTED_VOLATILE_GUEST *)pvCmd;
    4656     VBOXVHWACMD_TYPE enmCmd = (VBOXVHWACMD_TYPE)enmCmdInt;
    4657 
    4658     switch (enmCmd)
    4659     {
    4660         case VBOXVHWACMD_TYPE_SURF_CANCREATE:
    4661         {
    4662             VBOXVHWACMD_SURF_CANCREATE RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_CANCREATE);
    4663             Assert(!mGlOn == !mOverlayImage.hasSurfaces());
    4664             initGl();
    4665             makeCurrent();
    4666             pCmd->rc = mOverlayImage.vhwaSurfaceCanCreate(pBody);
    4667             Assert(!mGlOn == !mOverlayImage.hasSurfaces());
    4668             break;
    4669         }
    4670 
    4671         case VBOXVHWACMD_TYPE_SURF_CREATE:
    4672         {
    4673             VBOXVHWACMD_SURF_CREATE RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_CREATE);
    4674             Assert(!mGlOn == !mOverlayImage.hasSurfaces());
    4675             initGl();
    4676             makeCurrent();
    4677             vboxSetGlOn(true);
    4678             pCmd->rc = mOverlayImage.vhwaSurfaceCreate(pBody);
    4679             if (!mOverlayImage.hasSurfaces())
    4680             {
    4681                 vboxSetGlOn(false);
    4682             }
    4683             else
    4684             {
    4685                 mOverlayVisible = mOverlayImage.hasVisibleOverlays();
    4686                 if (mOverlayVisible)
    4687                 {
    4688                     mOverlayViewport = mOverlayImage.overlaysRectUnion();
    4689                 }
    4690                 vboxDoCheckUpdateViewport();
    4691                 mNeedOverlayRepaint = true;
    4692             }
    4693 
    4694             Assert(!mGlOn == !mOverlayImage.hasSurfaces());
    4695             break;
    4696         }
    4697 
    4698         case VBOXVHWACMD_TYPE_SURF_DESTROY:
    4699         {
    4700             VBOXVHWACMD_SURF_DESTROY RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_DESTROY);
    4701             Assert(!mGlOn == !mOverlayImage.hasSurfaces());
    4702             initGl();
    4703             makeCurrent();
    4704             pCmd->rc = mOverlayImage.vhwaSurfaceDestroy(pBody);
    4705             if (!mOverlayImage.hasSurfaces())
    4706             {
    4707                 vboxSetGlOn(false);
    4708             }
    4709             else
    4710             {
    4711                 mOverlayVisible = mOverlayImage.hasVisibleOverlays();
    4712                 if (mOverlayVisible)
    4713                 {
    4714                     mOverlayViewport = mOverlayImage.overlaysRectUnion();
    4715                 }
    4716                 vboxDoCheckUpdateViewport();
    4717                 mNeedOverlayRepaint = true;
    4718             }
    4719             Assert(!mGlOn == !mOverlayImage.hasSurfaces());
    4720             break;
    4721         }
    4722 
    4723         case VBOXVHWACMD_TYPE_SURF_LOCK:
    4724         {
    4725             VBOXVHWACMD_SURF_LOCK RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_LOCK);
    4726             Assert(!mGlOn == !mOverlayImage.hasSurfaces());
    4727             initGl();
    4728             makeCurrent();
    4729             pCmd->rc = mOverlayImage.vhwaSurfaceLock(pBody);
    4730             Assert(!mGlOn == !mOverlayImage.hasSurfaces());
    4731             break;
    4732         }
    4733 
    4734         case VBOXVHWACMD_TYPE_SURF_UNLOCK:
    4735         {
    4736             VBOXVHWACMD_SURF_UNLOCK RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_UNLOCK);
    4737             Assert(!mGlOn == !mOverlayImage.hasSurfaces());
    4738             initGl();
    4739             makeCurrent();
    4740             pCmd->rc = vhwaSurfaceUnlock(pBody);
    4741             Assert(!mGlOn == !mOverlayImage.hasSurfaces());
    4742             /* mNeedOverlayRepaint is set inside the vhwaSurfaceUnlock */
    4743             break;
    4744         }
    4745 
    4746         case VBOXVHWACMD_TYPE_SURF_BLT:
    4747         {
    4748             VBOXVHWACMD_SURF_BLT RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_BLT);
    4749             Assert(!mGlOn == !mOverlayImage.hasSurfaces());
    4750             initGl();
    4751             makeCurrent();
    4752             pCmd->rc = mOverlayImage.vhwaSurfaceBlt(pBody);
    4753             mNeedOverlayRepaint = true;
    4754             Assert(!mGlOn == !mOverlayImage.hasSurfaces());
    4755             break;
    4756         }
    4757 
    4758         case VBOXVHWACMD_TYPE_SURF_FLIP:
    4759         {
    4760             VBOXVHWACMD_SURF_FLIP RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_FLIP);
    4761             Assert(!mGlOn == !mOverlayImage.hasSurfaces());
    4762             initGl();
    4763             makeCurrent();
    4764             pCmd->rc = mOverlayImage.vhwaSurfaceFlip(pBody);
    4765             mNeedOverlayRepaint = true;
    4766             Assert(!mGlOn == !mOverlayImage.hasSurfaces());
    4767             break;
    4768         }
    4769 
    4770         case VBOXVHWACMD_TYPE_SURF_OVERLAY_UPDATE:
    4771         {
    4772             VBOXVHWACMD_SURF_OVERLAY_UPDATE RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_OVERLAY_UPDATE);
    4773             Assert(!mGlOn == !mOverlayImage.hasSurfaces());
    4774             initGl();
    4775             makeCurrent();
    4776             pCmd->rc = mOverlayImage.vhwaSurfaceOverlayUpdate(pBody);
    4777             mOverlayVisible = mOverlayImage.hasVisibleOverlays();
    4778             if (mOverlayVisible)
    4779             {
    4780                 mOverlayViewport = mOverlayImage.overlaysRectUnion();
    4781             }
    4782             vboxDoCheckUpdateViewport();
    4783             mNeedOverlayRepaint = true;
    4784             Assert(!mGlOn == !mOverlayImage.hasSurfaces());
    4785             break;
    4786         }
    4787 
    4788         case VBOXVHWACMD_TYPE_SURF_OVERLAY_SETPOSITION:
    4789         {
    4790             VBOXVHWACMD_SURF_OVERLAY_SETPOSITION RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_OVERLAY_SETPOSITION);
    4791             Assert(!mGlOn == !mOverlayImage.hasSurfaces());
    4792             initGl();
    4793             makeCurrent();
    4794             pCmd->rc = mOverlayImage.vhwaSurfaceOverlaySetPosition(pBody);
    4795             mOverlayVisible = mOverlayImage.hasVisibleOverlays();
    4796             if (mOverlayVisible)
    4797             {
    4798                 mOverlayViewport = mOverlayImage.overlaysRectUnion();
    4799             }
    4800             vboxDoCheckUpdateViewport();
    4801             mNeedOverlayRepaint = true;
    4802             Assert(!mGlOn == !mOverlayImage.hasSurfaces());
    4803             break;
    4804         }
    4805 
    4806 #ifdef VBOX_WITH_WDDM
    4807         case VBOXVHWACMD_TYPE_SURF_COLORFILL:
    4808         {
    4809             VBOXVHWACMD_SURF_COLORFILL RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_COLORFILL);
    4810             Assert(!mGlOn == !mOverlayImage.hasSurfaces());
    4811             initGl();
    4812             makeCurrent();
    4813             pCmd->rc = mOverlayImage.vhwaSurfaceColorFill(pBody);
    4814             mNeedOverlayRepaint = true;
    4815             Assert(!mGlOn == !mOverlayImage.hasSurfaces());
    4816             break;
    4817         }
    4818 #endif
    4819         case VBOXVHWACMD_TYPE_SURF_COLORKEY_SET:
    4820         {
    4821             VBOXVHWACMD_SURF_COLORKEY_SET RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_COLORKEY_SET);
    4822             Assert(!mGlOn == !mOverlayImage.hasSurfaces());
    4823             initGl();
    4824             makeCurrent();
    4825             pCmd->rc = mOverlayImage.vhwaSurfaceColorkeySet(pBody);
    4826             /* this is here to ensure we have color key changes picked up */
    4827             vboxDoCheckUpdateViewport();
    4828             mNeedOverlayRepaint = true;
    4829             Assert(!mGlOn == !mOverlayImage.hasSurfaces());
    4830             break;
    4831         }
    4832 
    4833         case VBOXVHWACMD_TYPE_QUERY_INFO1:
    4834         {
    4835             VBOXVHWACMD_QUERYINFO1 RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_QUERYINFO1);
    4836             Assert(!mGlOn == !mOverlayImage.hasSurfaces());
    4837             initGl();
    4838             makeCurrent();
    4839             pCmd->rc = mOverlayImage.vhwaQueryInfo1(pBody);
    4840             Assert(!mGlOn == !mOverlayImage.hasSurfaces());
    4841             break;
    4842         }
    4843 
    4844         case VBOXVHWACMD_TYPE_QUERY_INFO2:
    4845         {
    4846             VBOXVHWACMD_QUERYINFO2 RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_QUERYINFO2);
    4847             Assert(!mGlOn == !mOverlayImage.hasSurfaces());
    4848             initGl();
    4849             makeCurrent();
    4850             pCmd->rc = mOverlayImage.vhwaQueryInfo2(pBody);
    4851             Assert(!mGlOn == !mOverlayImage.hasSurfaces());
    4852             break;
    4853         }
    4854 
    4855         case VBOXVHWACMD_TYPE_ENABLE:
    4856             Assert(!mGlOn == !mOverlayImage.hasSurfaces());
    4857             initGl();
    4858             Assert(!mGlOn == !mOverlayImage.hasSurfaces());
    4859             pCmd->rc = VINF_SUCCESS;
    4860             break;
    4861 
    4862         case VBOXVHWACMD_TYPE_DISABLE:
    4863             pCmd->rc = VINF_SUCCESS;
    4864             break;
    4865 
    4866         case VBOXVHWACMD_TYPE_HH_CONSTRUCT:
    4867         {
    4868             ASSERT_GUEST_STMT_RETURN_VOID(!fGuestCmd, pCmd->rc = VERR_ACCESS_DENIED);
    4869             VBOXVHWACMD_HH_CONSTRUCT *pBody = VBOXVHWACMD_BODY_HOST_HEAP(pCmd, VBOXVHWACMD_HH_CONSTRUCT);
    4870             Assert(!mGlOn == !mOverlayImage.hasSurfaces());
    4871             pCmd->rc = vhwaConstruct(pBody);
    4872             Assert(!mGlOn == !mOverlayImage.hasSurfaces());
    4873             break;
    4874         }
    4875 
    4876 #ifdef VBOX_WITH_WDDM
    4877         case VBOXVHWACMD_TYPE_SURF_GETINFO:
    4878         {
    4879             VBOXVHWACMD_SURF_GETINFO RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_GETINFO);
    4880             Assert(!mGlOn == !mOverlayImage.hasSurfaces());
    4881             pCmd->rc = mOverlayImage.vhwaSurfaceGetInfo(pBody);
    4882             Assert(!mGlOn == !mOverlayImage.hasSurfaces());
    4883             break;
    4884         }
    4885 #endif
    4886 
    4887         default:
    4888             AssertFailed();
    4889             pCmd->rc = VERR_NOT_IMPLEMENTED;
    4890             break;
    4891     }
    4892 }
    4893 
    4894 #if 0
    4895 static DECLCALLBACK(void) vboxQGLOverlaySaveExec(PSSMHANDLE pSSM, void *pvUser)
    4896 {
    4897     VBoxQGLOverlay * fb = (VBoxQGLOverlay*)pvUser;
    4898     fb->vhwaSaveExec(pSSM);
    4899 }
    4900 #endif
    4901 
    4902 static DECLCALLBACK(int) vboxQGLOverlayLoadExec(PSSMHANDLE pSSM, void *pvUser, uint32_t u32Version, uint32_t uPass)
    4903 {
    4904     Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
    4905     VBoxQGLOverlay *fb = (VBoxQGLOverlay *)pvUser;
    4906     return fb->vhwaLoadExec(pSSM, u32Version);
    4907 }
    4908 
    4909 int VBoxQGLOverlay::vhwaLoadExec(struct SSMHANDLE *pSSM, uint32_t u32Version)
    4910 {
    4911     int rc = VBoxVHWAImage::vhwaLoadExec(&mOnResizeCmdList, pSSM, u32Version);
    4912     AssertRC(rc);
    4913     if (RT_SUCCESS(rc))
    4914     {
    4915         if (u32Version >= VBOXQGL_STATE_VERSION_PIPESAVED)
    4916         {
    4917             rc = mCmdPipe.loadExec(pSSM, u32Version, mOverlayImage.vramBase());
    4918             AssertRC(rc);
    4919         }
    4920     }
    4921     return rc;
    4922 }
    4923 
    4924 void VBoxQGLOverlay::vhwaSaveExec(struct SSMHANDLE *pSSM)
    4925 {
    4926     mOverlayImage.vhwaSaveExec(pSSM);
    4927     mCmdPipe.saveExec(pSSM, mOverlayImage.vramBase());
    4928 }
    4929 
    4930 int VBoxQGLOverlay::vhwaConstruct(struct VBOXVHWACMD_HH_CONSTRUCT *pCmd)
    4931 {
    4932     PUVM pUVM = VMR3GetUVM((PVM)pCmd->pVM);
    4933     uint32_t intsId = m_id;
    4934 
    4935     char nameFuf[sizeof(VBOXQGL_STATE_NAMEBASE) + 8];
    4936 
    4937     char * pszName = nameFuf;
    4938     sprintf(pszName, "%s%d", VBOXQGL_STATE_NAMEBASE, intsId);
    4939     int rc = SSMR3RegisterExternal(pUVM,                    /* The VM handle*/
    4940                                    pszName,                 /* Data unit name. */
    4941                                    intsId,                  /* The instance identifier of the data unit.
    4942                                                              * This must together with the name be unique. */
    4943                                    VBOXQGL_STATE_VERSION,   /* Data layout version number. */
    4944                                    128,                     /* The approximate amount of data in the unit.
    4945                                                              * Only for progress indicators. */
    4946                                    NULL, NULL, NULL,        /* pfnLiveXxx */
    4947                                    NULL,                    /* Prepare save callback, optional. */
    4948                                    NULL, //vboxQGLOverlaySaveExec, /* Execute save callback, optional. */
    4949                                    NULL,                    /* Done save callback, optional. */
    4950                                    NULL,                    /* Prepare load callback, optional. */
    4951                                    vboxQGLOverlayLoadExec,  /* Execute load callback, optional. */
    4952                                    NULL,                    /* Done load callback, optional. */
    4953                                    this                     /* User argument. */
    4954                                    );
    4955     AssertRC(rc);
    4956     if (RT_SUCCESS(rc))
    4957     {
    4958         rc = mOverlayImage.vhwaConstruct(pCmd);
    4959         AssertRC(rc);
    4960     }
    4961     return rc;
    4962 }
    4963 
    4964 /* static */
    4965 bool VBoxQGLOverlay::isAcceleration2DVideoAvailable()
    4966 {
    4967 #ifndef DEBUG_misha
    4968     if (!g_bVBoxVHWAChecked)
    4969 #endif
    4970     {
    4971         g_bVBoxVHWAChecked = true;
    4972         g_bVBoxVHWASupported = VBoxVHWAInfo::checkVHWASupport();
    4973     }
    4974     return g_bVBoxVHWASupported;
    4975 }
    4976 
    4977 /** additional video memory required for the best 2D support performance
    4978  *  total amount of VRAM required is thus calculated as requiredVideoMemory + required2DOffscreenVideoMemory  */
    4979 /* static */
    4980 quint64 VBoxQGLOverlay::required2DOffscreenVideoMemory()
     68quint64 VBox2DHelpers::required2DOffscreenVideoMemory()
    498169{
    498270    /* HDTV == 1920x1080 ~ 2M
     
    498775}
    498876
    4989 void VBoxQGLOverlay::processCmd(VBoxVHWACommandElement * pCmd)
    4990 {
    4991     switch(pCmd->type())
    4992     {
    4993         case VBOXVHWA_PIPECMD_PAINT:
    4994             addMainDirtyRect(pCmd->rect());
    4995             break;
    4996 
    4997 #ifdef VBOX_WITH_VIDEOHWACCEL
    4998         case VBOXVHWA_PIPECMD_VHWA:
    4999             vboxDoVHWACmd(pCmd->vhwaCmdPtr(), pCmd->vhwaCmdType(), pCmd->vhwaIsGuestCmd());
    5000             break;
    5001 
    5002         case VBOXVHWA_PIPECMD_FUNC:
    5003         {
    5004             const VBOXVHWAFUNCCALLBACKINFO & info = pCmd->func();
    5005             info.pfnCallback(info.pContext1, info.pContext2);
    5006             break;
    5007         }
    5008 #endif
    5009         default:
    5010             AssertFailed();
    5011     }
    5012 }
    5013 
    5014 VBoxVHWACommandElementProcessor::VBoxVHWACommandElementProcessor()
    5015     : m_pNotifyObject(NULL)
    5016     , mpCurCmd(NULL)
    5017     , mbResetting(false)
    5018     , mcDisabled(0)
    5019 {
    5020     int rc = RTCritSectInit(&mCritSect);
    5021     AssertRC(rc);
    5022 
    5023     RTListInit(&mCommandList);
    5024 
    5025     m_pCmdEntryCache = new VBoxVHWAEntriesCache;
    5026 }
    5027 
    5028 void VBoxVHWACommandElementProcessor::init(QObject *pNotifyObject)
    5029 {
    5030     m_pNotifyObject = pNotifyObject;
    5031 }
    5032 
    5033 VBoxVHWACommandElementProcessor::~VBoxVHWACommandElementProcessor()
    5034 {
    5035     Assert(!m_NotifyObjectRefs.refs());
    5036     RTListIsEmpty(&mCommandList);
    5037 
    5038     RTCritSectDelete(&mCritSect);
    5039 
    5040     delete m_pCmdEntryCache;
    5041 }
    5042 
    5043 void VBoxVHWACommandElementProcessor::postCmd(VBOXVHWA_PIPECMD_TYPE aType, void *pvData,
    5044                                               int /*VBOXVHWACMD_TYPE*/ enmCmd, bool fGuestCmd)
    5045 {
    5046     QObject *pNotifyObject = NULL;
    5047 
    5048     Log(("VHWA post %d %#p\n", aType, pvData));
    5049 
    5050     /* 1. lock*/
    5051     RTCritSectEnter(&mCritSect);
    5052 
    5053     VBoxVHWACommandElement *pCmd = m_pCmdEntryCache->alloc();
    5054     if (!pCmd)
    5055     {
    5056         VBOXQGLLOG(("!!!no more free elements!!!\n"));
    5057 #ifdef VBOXQGL_PROF_BASE
    5058         RTCritSectLeave(&mCritSect);
    5059         return;
    5060 #else
    5061     /// @todo
    5062 #endif
    5063     }
    5064     pCmd->setData(aType, pvData, enmCmd, fGuestCmd);
    5065 
    5066     /* 2. if can add to current*/
    5067     if (m_pNotifyObject)
    5068     {
    5069         m_NotifyObjectRefs.inc(); /* ensure the parent does not get destroyed while we are using it */
    5070         pNotifyObject = m_pNotifyObject;
    5071     }
    5072 
    5073     RTListAppend(&mCommandList, &pCmd->ListNode);
    5074 
    5075     RTCritSectLeave(&mCritSect);
    5076 
    5077     if (pNotifyObject)
    5078     {
    5079         VBoxVHWACommandProcessEvent *pCurrentEvent = new VBoxVHWACommandProcessEvent();
    5080         QApplication::postEvent(pNotifyObject, pCurrentEvent);
    5081         m_NotifyObjectRefs.dec();
    5082     }
    5083 }
    5084 
    5085 void VBoxVHWACommandElementProcessor::setNotifyObject(QObject *pNotifyObject)
    5086 {
    5087     int cEventsNeeded = 0;
    5088     RTCritSectEnter(&mCritSect);
    5089     if (m_pNotifyObject == pNotifyObject)
    5090     {
    5091         RTCritSectLeave(&mCritSect);
    5092         return;
    5093     }
    5094 
    5095     if (m_pNotifyObject)
    5096     {
    5097         m_pNotifyObject = NULL;
    5098         RTCritSectLeave(&mCritSect);
    5099 
    5100         m_NotifyObjectRefs.wait0();
    5101 
    5102         RTCritSectEnter(&mCritSect);
    5103     }
    5104     else
    5105     {
    5106         /* NULL can not be references */
    5107         Assert(!m_NotifyObjectRefs.refs());
    5108     }
    5109 
    5110     if (pNotifyObject)
    5111     {
    5112         m_pNotifyObject = pNotifyObject;
    5113 
    5114         VBoxVHWACommandElement *pCur;
    5115         RTListForEachCpp(&mCommandList, pCur, VBoxVHWACommandElement, ListNode)
    5116         {
    5117             ++cEventsNeeded;
    5118         }
    5119 
    5120         if (cEventsNeeded)
    5121             m_NotifyObjectRefs.inc();
    5122     }
    5123     else
    5124     {
    5125         /* should be zeroed already */
    5126         Assert(!m_pNotifyObject);
    5127     }
    5128 
    5129     RTCritSectLeave(&mCritSect);
    5130 
    5131     if (cEventsNeeded)
    5132     {
    5133         /* cEventsNeeded can only be != 0 if pNotifyObject is valid */
    5134         Assert(pNotifyObject);
    5135         for (int i = 0; i < cEventsNeeded; ++i)
    5136         {
    5137             VBoxVHWACommandProcessEvent *pCurrentEvent = new VBoxVHWACommandProcessEvent();
    5138             QApplication::postEvent(pNotifyObject, pCurrentEvent);
    5139         }
    5140         m_NotifyObjectRefs.dec();
    5141     }
    5142 }
    5143 
    5144 void VBoxVHWACommandElementProcessor::doneCmd()
    5145 {
    5146     VBoxVHWACommandElement *pEl;
    5147     RTCritSectEnter(&mCritSect);
    5148     pEl = mpCurCmd;
    5149     Assert(mpCurCmd);
    5150     mpCurCmd = NULL;
    5151     RTCritSectLeave(&mCritSect);
    5152 
    5153     if (pEl)
    5154         m_pCmdEntryCache->free(pEl);
    5155 }
    5156 
    5157 VBoxVHWACommandElement *VBoxVHWACommandElementProcessor::getCmd()
    5158 {
    5159     VBoxVHWACommandElement *pEl = NULL;
    5160     RTCritSectEnter(&mCritSect);
    5161 
    5162     Assert(!mpCurCmd);
    5163 
    5164     if (mbResetting)
    5165     {
    5166         RTCritSectLeave(&mCritSect);
    5167         return NULL;
    5168     }
    5169 
    5170     if (mcDisabled)
    5171     {
    5172         QObject *pNotifyObject = NULL;
    5173 
    5174         if (!RTListIsEmpty(&mCommandList))
    5175         {
    5176             Assert(m_pNotifyObject);
    5177             if (m_pNotifyObject)
    5178             {
    5179                 m_NotifyObjectRefs.inc(); /* ensure the parent does not get destroyed while we are using it */
    5180                 pNotifyObject = m_pNotifyObject;
    5181             }
    5182         }
    5183 
    5184         RTCritSectLeave(&mCritSect);
    5185 
    5186         if (pNotifyObject)
    5187         {
    5188             VBoxVHWACommandProcessEvent *pCurrentEvent = new VBoxVHWACommandProcessEvent();
    5189             QApplication::postEvent(pNotifyObject, pCurrentEvent);
    5190             m_NotifyObjectRefs.dec();
    5191         }
    5192         return NULL;
    5193     }
    5194 
    5195     pEl = RTListGetFirstCpp(&mCommandList, VBoxVHWACommandElement, ListNode);
    5196     if (pEl)
    5197     {
    5198         RTListNodeRemove(&pEl->ListNode);
    5199         mpCurCmd = pEl;
    5200     }
    5201 
    5202     RTCritSectLeave(&mCritSect);
    5203 
    5204     return pEl;
    5205 }
    5206 
    5207 /* it is currently assumed no one sends any new commands while reset is in progress */
    5208 void VBoxVHWACommandElementProcessor::reset(CDisplay *pDisplay)
    5209 {
    5210     RTCritSectEnter(&mCritSect);
    5211 
    5212     mbResetting = true;
    5213 
    5214     if (mpCurCmd)
    5215     {
    5216         for (;;)
    5217         {
    5218             RTCritSectLeave(&mCritSect);
    5219             RTThreadSleep(2); /* 2 ms */
    5220             RTCritSectEnter(&mCritSect);
    5221             /* it is assumed no one sends any new commands while reset is in progress */
    5222             if (!mpCurCmd)
    5223             {
    5224                 break;
    5225             }
    5226         }
    5227     }
    5228 
    5229     RTCritSectLeave(&mCritSect);
    5230 
    5231     VBoxVHWACommandElement *pCur, *pNext;
    5232     RTListForEachSafeCpp(&mCommandList, pCur, pNext, VBoxVHWACommandElement, ListNode)
    5233     {
    5234         switch (pCur->type())
    5235         {
    5236 #ifdef VBOX_WITH_VIDEOHWACCEL
    5237             case VBOXVHWA_PIPECMD_VHWA:
    5238                 {
    5239                     struct VBOXVHWACMD RT_UNTRUSTED_VOLATILE_GUEST *pCmd = pCur->vhwaCmdPtr();
    5240                     pCmd->rc = VERR_INVALID_STATE;
    5241                     Log(("VHWA Command <<< Async RESET %#p, %d\n", pCmd, pCmd->enmCmd));
    5242                     pDisplay->CompleteVHWACommand((BYTE *)pCmd);
    5243                 }
    5244                 break;
    5245 
    5246             case VBOXVHWA_PIPECMD_FUNC:
    5247                 /* should not happen, don't handle this for now */
    5248                 AssertFailed();
    5249                 break;
    5250 #endif
    5251             case VBOXVHWA_PIPECMD_PAINT:
    5252                 break;
    5253 
    5254             default:
    5255                 /* should not happen, don't handle this for now */
    5256                 AssertFailed();
    5257                 break;
    5258         }
    5259 
    5260         RTListNodeRemove(&pCur->ListNode);
    5261         m_pCmdEntryCache->free(pCur);
    5262     }
    5263 
    5264     RTCritSectEnter(&mCritSect);
    5265 
    5266     mbResetting = false;
    5267 
    5268     RTCritSectLeave(&mCritSect);
    5269 }
    5270 
    5271 #define VBOXVHWACOMMANDELEMENTLISTBEGIN_MAGIC UINT32_C(0x89abcdef)
    5272 #define VBOXVHWACOMMANDELEMENTLISTEND_MAGIC   UINT32_C(0xfedcba98)
    5273 
    5274 int VBoxVHWACommandElementProcessor::loadExec(struct SSMHANDLE *pSSM, uint32_t u32Version, void *pvVRAM)
    5275 {
    5276     uint32_t u32;
    5277 
    5278     Q_UNUSED(u32Version);
    5279 
    5280     int rc = SSMR3GetU32(pSSM, &u32);
    5281     AssertRCReturn(rc, rc);
    5282     AssertReturn(u32 == VBOXVHWACOMMANDELEMENTLISTBEGIN_MAGIC, VERR_INVALID_MAGIC);
    5283 
    5284     SSMR3GetU32(pSSM, &u32);
    5285     bool b;
    5286     rc = SSMR3GetBool(pSSM, &b);
    5287     AssertRCReturn(rc, rc);
    5288 
    5289 //    m_NotifyObjectRefs = VBoxVHWARefCounter(u32);
    5290     bool fContinue = true;
    5291     do
    5292     {
    5293         rc = SSMR3GetU32(pSSM, &u32);
    5294         AssertRCReturn(rc, rc);
    5295 
    5296         bool fNewEvent;
    5297         switch (u32)
    5298         {
    5299             case VBOXVHWA_PIPECMD_PAINT:
    5300             {
    5301                 int x,y,w,h;
    5302                 rc = SSMR3GetS32(pSSM, &x);
    5303                 rc = SSMR3GetS32(pSSM, &y);
    5304                 rc = SSMR3GetS32(pSSM, &w);
    5305                 rc = SSMR3GetS32(pSSM, &h);
    5306                 rc = SSMR3GetBool(pSSM, &fNewEvent);
    5307                 AssertRCReturn(rc, rc);
    5308 
    5309                 QRect r = QRect(x, y, w, h);
    5310                 postCmd(VBOXVHWA_PIPECMD_PAINT, &r, -1, false);
    5311                 break;
    5312             }
    5313 
    5314             case VBOXVHWA_PIPECMD_VHWA:
    5315             {
    5316                 uint32_t offCmd;
    5317                 rc = SSMR3GetU32(pSSM, &offCmd);
    5318                 rc = SSMR3GetBool(pSSM, &fNewEvent);
    5319                 AssertRCReturn(rc, rc);
    5320 
    5321                 VBOXVHWACMD *pCmd = (VBOXVHWACMD *)(((uint8_t *)pvVRAM) + offCmd);
    5322                 postCmd(VBOXVHWA_PIPECMD_VHWA, pCmd, pCmd->enmCmd, true);
    5323                 break;
    5324             }
    5325 
    5326             case VBOXVHWACOMMANDELEMENTLISTEND_MAGIC:
    5327                 fContinue = false;
    5328                 break;
    5329 
    5330             default:
    5331                 AssertLogRelMsgFailed(("u32=%#x\n", u32));
    5332                 break;
    5333         }
    5334 
    5335     } while (fContinue && RT_SUCCESS(rc));
    5336 
    5337     return rc;
    5338 }
    5339 
    5340 void VBoxVHWACommandElementProcessor::saveExec(struct SSMHANDLE *pSSM, void *pvVRAM)
    5341 {
    5342     int rc;
    5343 
    5344     rc = SSMR3PutU32(pSSM, VBOXVHWACOMMANDELEMENTLISTBEGIN_MAGIC);
    5345     rc = SSMR3PutU32(pSSM, m_NotifyObjectRefs.refs());
    5346     rc = SSMR3PutBool(pSSM, true);
    5347     AssertRC(rc);
    5348 
    5349     VBoxVHWACommandElement *pCur;
    5350     RTListForEachCpp(&mCommandList, pCur, VBoxVHWACommandElement, ListNode)
    5351     {
    5352 
    5353         switch (pCur->type())
    5354         {
    5355             case VBOXVHWA_PIPECMD_PAINT:
    5356                 rc = SSMR3PutU32(pSSM, pCur->type());
    5357                 rc = SSMR3PutS32(pSSM, pCur->rect().x());
    5358                 rc = SSMR3PutS32(pSSM, pCur->rect().y());
    5359                 rc = SSMR3PutS32(pSSM, pCur->rect().width());
    5360                 rc = SSMR3PutS32(pSSM, pCur->rect().height());
    5361                 rc = SSMR3PutBool(pSSM, true);
    5362                 AssertRC(rc);
    5363                 break;
    5364 
    5365             case VBOXVHWA_PIPECMD_VHWA:
    5366                 if (pCur->vhwaIsGuestCmd())
    5367                 {
    5368                     rc = SSMR3PutU32(pSSM, pCur->type());
    5369                     rc = SSMR3PutU32(pSSM, (uint32_t)(uintptr_t)pCur->vhwaCmdPtr() - (uintptr_t)pvVRAM);
    5370                     rc = SSMR3PutBool(pSSM, true);
    5371                     AssertRC(rc);
    5372                 }
    5373                 break;
    5374 
    5375             default:
    5376                 AssertFailed();
    5377                 break;
    5378         }
    5379     }
    5380 
    5381     rc = SSMR3PutU32(pSSM, VBOXVHWACOMMANDELEMENTLISTEND_MAGIC);
    5382     AssertRC(rc);
    5383 }
    5384 
    5385 void VBoxVHWACommandElementProcessor::lock()
    5386 {
    5387     RTCritSectEnter(&mCritSect);
    5388 
    5389     if (mpCurCmd)
    5390     {
    5391         for (;;)
    5392         {
    5393             RTCritSectLeave(&mCritSect);
    5394             RTThreadSleep(2); /* 2 ms */
    5395             RTCritSectEnter(&mCritSect);
    5396             /* it is assumed no one sends any new commands while reset is in progress */
    5397             if (!mpCurCmd)
    5398             {
    5399                 break;
    5400             }
    5401         }
    5402     }
    5403 
    5404     Assert(!mpCurCmd);
    5405 }
    5406 
    5407 void VBoxVHWACommandElementProcessor::unlock()
    5408 {
    5409     RTCritSectLeave(&mCritSect);
    5410 }
    5411 
    5412 void VBoxVHWACommandElementProcessor::disable()
    5413 {
    5414     lock();
    5415     ++mcDisabled;
    5416     unlock();
    5417 }
    5418 
    5419 void VBoxVHWACommandElementProcessor::enable()
    5420 {
    5421     lock();
    5422     --mcDisabled;
    5423     unlock();
    5424 }
    5425 
    5426 /* static */
    5427 uint32_t VBoxVHWATextureImage::calcBytesPerLine(const VBoxVHWAColorFormat &format, int width)
    5428 {
    5429     uint32_t pitch = (format.bitsPerPixel() * width + 7) / 8;
    5430     switch (format.fourcc())
    5431     {
    5432         case FOURCC_YV12:
    5433             /* make sure the color components pitch is multiple of 8
    5434              * where 8 is 2 (for color component width is Y width / 2) * 4 for 4byte texture format */
    5435             pitch = (pitch + 7) & ~7;
    5436             break;
    5437 
    5438         default:
    5439             pitch = (pitch + 3) & ~3;
    5440             break;
    5441     }
    5442     return pitch;
    5443 }
    5444 
    5445 /* static */
    5446 uint32_t VBoxVHWATextureImage::calcMemSize(const VBoxVHWAColorFormat &format, int width, int height)
    5447 {
    5448     uint32_t pitch = calcBytesPerLine(format, width);
    5449     switch (format.fourcc())
    5450     {
    5451         case FOURCC_YV12:
    5452             /* we have 3 separate planes here
    5453              * Y - pitch x height
    5454              * U - pitch / 2 x height / 2
    5455              * V - pitch / 2 x height / 2
    5456              * */
    5457             return 3 * pitch * height / 2;
    5458 
    5459         default:
    5460             return pitch * height;
    5461     }
    5462 }
    5463 
    5464 VBoxVHWATextureImage::VBoxVHWATextureImage(const QRect &size, const VBoxVHWAColorFormat &format,
    5465                                            class VBoxVHWAGlProgramMngr * aMgr, VBOXVHWAIMG_TYPE flags)
    5466     : mVisibleDisplay(0)
    5467     , mpProgram(0)
    5468     , mProgramMngr(aMgr)
    5469     , mpDst(NULL)
    5470     , mpDstCKey(NULL)
    5471     , mpSrcCKey(NULL)
    5472     , mbNotIntersected(false)
    5473 {
    5474     uint32_t pitch = calcBytesPerLine(format, size.width());
    5475 
    5476     mpTex[0] = vboxVHWATextureCreate(NULL, size, format, pitch, flags);
    5477     mColorFormat = format;
    5478     if (mColorFormat.fourcc() == FOURCC_YV12)
    5479     {
    5480         QRect rect(size.x() / 2,size.y() / 2,size.width() / 2,size.height() / 2);
    5481         mpTex[1] = vboxVHWATextureCreate(NULL, rect, format, pitch / 2, flags);
    5482         mpTex[2] = vboxVHWATextureCreate(NULL, rect, format, pitch / 2, flags);
    5483         mcTex = 3;
    5484     }
    5485     else
    5486         mcTex = 1;
    5487 }
    5488 
    5489 void VBoxVHWATextureImage::deleteDisplayList()
    5490 {
    5491     if (mVisibleDisplay)
    5492     {
    5493         glDeleteLists(mVisibleDisplay, 1);
    5494         mVisibleDisplay = 0;
    5495     }
    5496 }
    5497 
    5498 void VBoxVHWATextureImage::deleteDisplay()
    5499 {
    5500     deleteDisplayList();
    5501     mpProgram = NULL;
    5502 }
    5503 
    5504 void VBoxVHWATextureImage::draw(VBoxVHWATextureImage *pDst, const QRect *pDstRect, const QRect *pSrcRect)
    5505 {
    5506     int tx1, ty1, tx2, ty2;
    5507     pSrcRect->getCoords(&tx1, &ty1, &tx2, &ty2);
    5508 
    5509     int bx1, by1, bx2, by2;
    5510     pDstRect->getCoords(&bx1, &by1, &bx2, &by2);
    5511 
    5512     tx2++; ty2++;bx2++; by2++;
    5513 
    5514     glBegin(GL_QUADS);
    5515     uint32_t c = texCoord(GL_TEXTURE0, tx1, ty1);
    5516     if (pDst)
    5517         pDst->texCoord(GL_TEXTURE0 + c, bx1, by1);
    5518     glVertex2i(bx1, by1);
    5519 
    5520     texCoord(GL_TEXTURE0, tx1, ty2);
    5521     if (pDst)
    5522         pDst->texCoord(GL_TEXTURE0 + c, bx1, by2);
    5523     glVertex2i(bx1, by2);
    5524 
    5525     texCoord(GL_TEXTURE0, tx2, ty2);
    5526     if (pDst)
    5527         pDst->texCoord(GL_TEXTURE0 + c, bx2, by2);
    5528     glVertex2i(bx2, by2);
    5529 
    5530     texCoord(GL_TEXTURE0, tx2, ty1);
    5531     if (pDst)
    5532         pDst->texCoord(GL_TEXTURE0 + c, bx2, by1);
    5533     glVertex2i(bx2, by1);
    5534 
    5535     glEnd();
    5536 }
    5537 
    5538 void VBoxVHWATextureImage::internalSetDstCKey(const VBoxVHWAColorKey * pDstCKey)
    5539 {
    5540     if (pDstCKey)
    5541     {
    5542         mDstCKey = *pDstCKey;
    5543         mpDstCKey = &mDstCKey;
    5544     }
    5545     else
    5546     {
    5547         mpDstCKey = NULL;
    5548     }
    5549 }
    5550 
    5551 void VBoxVHWATextureImage::internalSetSrcCKey(const VBoxVHWAColorKey * pSrcCKey)
    5552 {
    5553     if (pSrcCKey)
    5554     {
    5555         mSrcCKey = *pSrcCKey;
    5556         mpSrcCKey = &mSrcCKey;
    5557     }
    5558     else
    5559     {
    5560         mpSrcCKey = NULL;
    5561     }
    5562 }
    5563 
    5564 int VBoxVHWATextureImage::initDisplay(VBoxVHWATextureImage *pDst,
    5565                                       const QRect *pDstRect, const QRect *pSrcRect,
    5566                                       const VBoxVHWAColorKey *pDstCKey, const VBoxVHWAColorKey *pSrcCKey, bool bNotIntersected)
    5567 {
    5568     if (  !mVisibleDisplay
    5569         || mpDst != pDst
    5570         || *pDstRect != mDstRect
    5571         || *pSrcRect != mSrcRect
    5572         || !!(pDstCKey) != !!(mpDstCKey)
    5573         || !!(pSrcCKey) != !!(mpSrcCKey)
    5574         || mbNotIntersected != bNotIntersected
    5575         || mpProgram != calcProgram(pDst, pDstCKey, pSrcCKey, bNotIntersected))
    5576         return createSetDisplay(pDst, pDstRect, pSrcRect, pDstCKey, pSrcCKey, bNotIntersected);
    5577     if (   (pDstCKey && mpDstCKey && *pDstCKey != *mpDstCKey)
    5578         || (pSrcCKey && mpSrcCKey && *pSrcCKey != *mpSrcCKey))
    5579     {
    5580         Assert(mpProgram);
    5581         updateSetCKeys(pDstCKey, pSrcCKey);
    5582         return VINF_SUCCESS;
    5583     }
    5584     return VINF_SUCCESS;
    5585 }
    5586 
    5587 void VBoxVHWATextureImage::bind(VBoxVHWATextureImage * pPrimary)
    5588 {
    5589     for (uint32_t i = 1; i < mcTex; i++)
    5590     {
    5591         vboxglActiveTexture(GL_TEXTURE0 + i);
    5592         mpTex[i]->bind();
    5593     }
    5594     if (pPrimary)
    5595         for (uint32_t i = 0; i < pPrimary->mcTex; i++)
    5596         {
    5597             vboxglActiveTexture(GL_TEXTURE0 + i + mcTex);
    5598             pPrimary->mpTex[i]->bind();
    5599         }
    5600 
    5601     vboxglActiveTexture(GL_TEXTURE0);
    5602     mpTex[0]->bind();
    5603 }
    5604 
    5605 uint32_t VBoxVHWATextureImage::calcProgramType(VBoxVHWATextureImage *pDst, const VBoxVHWAColorKey *pDstCKey,
    5606                                                const VBoxVHWAColorKey *pSrcCKey, bool bNotIntersected)
    5607 {
    5608     uint32_t type = 0;
    5609 
    5610     if (pDstCKey != NULL)
    5611         type |= VBOXVHWA_PROGRAM_DSTCOLORKEY;
    5612     if (pSrcCKey)
    5613         type |= VBOXVHWA_PROGRAM_SRCCOLORKEY;
    5614     if ((pDstCKey || pSrcCKey) && bNotIntersected)
    5615         type |= VBOXVHWA_PROGRAM_COLORKEYNODISCARD;
    5616 
    5617     NOREF(pDst);
    5618     return type;
    5619 }
    5620 
    5621 class VBoxVHWAGlProgramVHWA *VBoxVHWATextureImage::calcProgram(VBoxVHWATextureImage *pDst, const VBoxVHWAColorKey *pDstCKey,
    5622                                                                const VBoxVHWAColorKey *pSrcCKey, bool bNotIntersected)
    5623 {
    5624     uint32_t type = calcProgramType(pDst, pDstCKey, pSrcCKey, bNotIntersected);
    5625 
    5626     return mProgramMngr->getProgram(type, &pixelFormat(), pDst ? &pDst->pixelFormat() : NULL);
    5627 }
    5628 
    5629 int VBoxVHWATextureImage::createSetDisplay(VBoxVHWATextureImage *pDst, const QRect *pDstRect, const QRect *pSrcRect,
    5630                                            const VBoxVHWAColorKey *pDstCKey, const VBoxVHWAColorKey * pSrcCKey,
    5631                                            bool bNotIntersected)
    5632 {
    5633     deleteDisplay();
    5634     int rc = createDisplay(pDst, pDstRect, pSrcRect, pDstCKey, pSrcCKey, bNotIntersected, &mVisibleDisplay, &mpProgram);
    5635     if (RT_FAILURE(rc))
    5636     {
    5637         mVisibleDisplay = 0;
    5638         mpProgram = NULL;
    5639     }
    5640 
    5641     mpDst = pDst;
    5642 
    5643     mDstRect = *pDstRect;
    5644     mSrcRect = *pSrcRect;
    5645 
    5646     internalSetDstCKey(pDstCKey);
    5647     internalSetSrcCKey(pSrcCKey);
    5648 
    5649     mbNotIntersected = bNotIntersected;
    5650 
    5651     return rc;
    5652 }
    5653 
    5654 
    5655 int VBoxVHWATextureImage::createDisplayList(VBoxVHWATextureImage *pDst, const QRect *pDstRect, const QRect *pSrcRect,
    5656                                             const VBoxVHWAColorKey *pDstCKey, const VBoxVHWAColorKey *pSrcCKey,
    5657                                             bool bNotIntersected, GLuint *pDisplay)
    5658 {
    5659     Q_UNUSED(pDstCKey);
    5660     Q_UNUSED(pSrcCKey);
    5661     Q_UNUSED(bNotIntersected);
    5662 
    5663     glGetError(); /* clear the err flag */
    5664     GLuint display = glGenLists(1);
    5665     GLenum err = glGetError();
    5666     if (err == GL_NO_ERROR)
    5667     {
    5668         Assert(display);
    5669         if (!display)
    5670         {
    5671             /* well, it seems it should not return 0 on success according to the spec,
    5672              * but just in case, pick another one */
    5673             display = glGenLists(1);
    5674             err = glGetError();
    5675             if (err == GL_NO_ERROR)
    5676             {
    5677                 Assert(display);
    5678             }
    5679             else
    5680             {
    5681                 /* we are failed */
    5682                 Assert(!display);
    5683                 display = 0;
    5684             }
    5685         }
    5686 
    5687         if (display)
    5688         {
    5689             glNewList(display, GL_COMPILE);
    5690 
    5691             runDisplay(pDst, pDstRect, pSrcRect);
    5692 
    5693             glEndList();
    5694             VBOXQGL_ASSERTNOERR();
    5695             *pDisplay = display;
    5696             return VINF_SUCCESS;
    5697         }
    5698     }
    5699     else
    5700     {
    5701         VBOXQGLLOG(("gl error ocured (0x%x)\n", err));
    5702         Assert(err == GL_NO_ERROR);
    5703     }
    5704     return VERR_GENERAL_FAILURE;
    5705 }
    5706 
    5707 void VBoxVHWATextureImage::updateCKeys(VBoxVHWATextureImage *pDst, class VBoxVHWAGlProgramVHWA *pProgram,
    5708                                        const VBoxVHWAColorKey *pDstCKey, const VBoxVHWAColorKey *pSrcCKey)
    5709 {
    5710     if (pProgram)
    5711     {
    5712         pProgram->start();
    5713         if (pSrcCKey)
    5714             VBoxVHWATextureImage::setCKey(pProgram, &pixelFormat(), pSrcCKey, false);
    5715         if (pDstCKey)
    5716             VBoxVHWATextureImage::setCKey(pProgram, &pDst->pixelFormat(), pDstCKey, true);
    5717         pProgram->stop();
    5718     }
    5719 }
    5720 
    5721 void VBoxVHWATextureImage::updateSetCKeys(const VBoxVHWAColorKey *pDstCKey, const VBoxVHWAColorKey *pSrcCKey)
    5722 {
    5723     updateCKeys(mpDst, mpProgram, pDstCKey, pSrcCKey);
    5724     internalSetDstCKey(pDstCKey);
    5725     internalSetSrcCKey(pSrcCKey);
    5726 }
    5727 
    5728 int VBoxVHWATextureImage::createDisplay(VBoxVHWATextureImage *pDst, const QRect *pDstRect, const QRect *pSrcRect,
    5729                                         const VBoxVHWAColorKey *pDstCKey, const VBoxVHWAColorKey *pSrcCKey, bool bNotIntersected,
    5730                                         GLuint *pDisplay, class VBoxVHWAGlProgramVHWA **ppProgram)
    5731 {
    5732     VBoxVHWAGlProgramVHWA *pProgram = NULL;
    5733     if (!pDst)
    5734     {
    5735         /* sanity */
    5736         Assert(pDstCKey == NULL);
    5737         pDstCKey = NULL;
    5738     }
    5739 
    5740     Assert(!pSrcCKey);
    5741     if (pSrcCKey)
    5742         pSrcCKey = NULL; /* fallback */
    5743 
    5744     pProgram = calcProgram(pDst, pDstCKey, pSrcCKey, bNotIntersected);
    5745 
    5746     updateCKeys(pDst, pProgram, pDstCKey, pSrcCKey);
    5747 
    5748     GLuint displ;
    5749     int rc = createDisplayList(pDst, pDstRect, pSrcRect, pDstCKey, pSrcCKey, bNotIntersected, &displ);
    5750     if (RT_SUCCESS(rc))
    5751     {
    5752         *pDisplay = displ;
    5753         *ppProgram = pProgram;
    5754     }
    5755 
    5756     return rc;
    5757 }
    5758 
    5759 void VBoxVHWATextureImage::display(VBoxVHWATextureImage *pDst, const QRect *pDstRect, const QRect *pSrcRect,
    5760                                    const VBoxVHWAColorKey *pDstCKey, const VBoxVHWAColorKey *pSrcCKey, bool bNotIntersected)
    5761 {
    5762     VBoxVHWAGlProgramVHWA *pProgram = calcProgram(pDst, pDstCKey, pSrcCKey, bNotIntersected);
    5763     if (pProgram)
    5764         pProgram->start();
    5765 
    5766     runDisplay(pDst, pDstRect, pSrcRect);
    5767 
    5768     if (pProgram)
    5769         pProgram->stop();
    5770 }
    5771 
    5772 void VBoxVHWATextureImage::display()
    5773 {
    5774 #ifdef DEBUG_misha
    5775     if (mpDst)
    5776         dbgDump();
    5777 
    5778     static bool bDisplayOn = true;
    5779 #endif
    5780     Assert(mVisibleDisplay);
    5781     if (   mVisibleDisplay
    5782 #ifdef DEBUG_misha
    5783         && bDisplayOn
    5784 #endif
    5785         )
    5786     {
    5787         if (mpProgram)
    5788             mpProgram->start();
    5789 
    5790         VBOXQGL_CHECKERR(
    5791                 glCallList(mVisibleDisplay);
    5792                 );
    5793 
    5794         if (mpProgram)
    5795             mpProgram->stop();
    5796     }
    5797     else
    5798     {
    5799         display(mpDst, &mDstRect, &mSrcRect,
    5800                 mpDstCKey, mpSrcCKey, mbNotIntersected);
    5801     }
    5802 }
    5803 
    5804 #ifdef DEBUG_misha
    5805 void VBoxVHWATextureImage::dbgDump()
    5806 {
    5807     for (uint32_t i = 0; i < mcTex; ++i)
    5808         mpTex[i]->dbgDump();
    5809 }
    5810 #endif
    5811 
    5812 int VBoxVHWATextureImage::setCKey(VBoxVHWAGlProgramVHWA *pProgram, const VBoxVHWAColorFormat *pFormat,
    5813                                   const VBoxVHWAColorKey *pCKey, bool bDst)
    5814 {
    5815     float r,g,b;
    5816     pFormat->pixel2Normalized(pCKey->lower(), &r, &g, &b);
    5817     int rcL = bDst ? pProgram->setDstCKeyLowerRange(r, g, b) : pProgram->setSrcCKeyLowerRange(r, g, b);
    5818     Assert(RT_SUCCESS(rcL));
    5819 
    5820     return RT_SUCCESS(rcL) /*&& RT_SUCCESS(rcU)*/ ? VINF_SUCCESS: VERR_GENERAL_FAILURE;
    5821 }
    5822 
    5823 VBoxVHWASettings::VBoxVHWASettings ()
    5824 {
    5825 }
    5826 
    5827 void VBoxVHWASettings::init(CSession &session)
    5828 {
    5829     const QString strMachineID = session.GetMachine().GetId();
    5830 
    5831     mStretchLinearEnabled = gEDataManager->useLinearStretch(strMachineID);
    5832 
    5833     uint32_t aFourccs[VBOXVHWA_NUMFOURCC];
    5834     int num = 0;
    5835     if (gEDataManager->usePixelFormatAYUV(strMachineID))
    5836         aFourccs[num++] = FOURCC_AYUV;
    5837     if (gEDataManager->usePixelFormatUYVY(strMachineID))
    5838         aFourccs[num++] = FOURCC_UYVY;
    5839     if (gEDataManager->usePixelFormatYUY2(strMachineID))
    5840         aFourccs[num++] = FOURCC_YUY2;
    5841     if (gEDataManager->usePixelFormatYV12(strMachineID))
    5842         aFourccs[num++] = FOURCC_YV12;
    5843 
    5844     mFourccEnabledCount = num;
    5845     memcpy(mFourccEnabledList, aFourccs, num* sizeof (aFourccs[0]));
    5846 }
    5847 
    5848 int VBoxVHWASettings::calcIntersection(int c1, const uint32_t *a1, int c2, const uint32_t *a2, int cOut, uint32_t *aOut)
    5849 {
    5850     /* fourcc arrays are not big, so linear search is enough,
    5851      * also no need to check for duplicates */
    5852     int cMatch = 0;
    5853     for (int i = 0; i < c1; ++i)
    5854     {
    5855         uint32_t cur1 = a1[i];
    5856         for (int j = 0; j < c2; ++j)
    5857         {
    5858             uint32_t cur2 = a2[j];
    5859             if (cur1 == cur2)
    5860             {
    5861                 if (cOut > cMatch && aOut)
    5862                     aOut[cMatch] = cur1;
    5863                 ++cMatch;
    5864                 break;
    5865             }
    5866         }
    5867     }
    5868 
    5869     return cMatch;
    5870 }
    5871 
    5872 #endif /* VBOX_GUI_USE_QGL */
    5873 
     77#endif /* VBOX_GUI_USE_QGL || VBOX_WITH_VIDEOHWACCEL */
  • trunk/src/VBox/Frontends/VirtualBox/src/VBox2DHelpers.h

    r72038 r72057  
    11/* $Id$ */
    22/** @file
    3  * VBox Qt GUI - VBoxFrameBuffer Overly classes declarations.
     3 * VBox Qt GUI - 2D Video Acceleration helpers declarations.
    44 */
    55
    66/*
    7  * Copyright (C) 2006-2017 Oracle Corporation
     7 * Copyright (C) 2006-2018 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    1515 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
    1616 */
    17 #ifndef __VBoxFBOverlay_h__
    18 #define __VBoxFBOverlay_h__
     17
     18#ifndef ___VBox2DHelpers_h___
     19#define ___VBox2DHelpers_h___
    1920
    2021#if defined(VBOX_GUI_USE_QGL) || defined(VBOX_WITH_VIDEOHWACCEL)
    2122
    22 /* Defines: */
    23 //#define VBOXQGL_PROF_BASE 1
    24 //#define VBOXQGL_DBG_SURF 1
    25 //#define VBOXVHWADBG_RENDERCHECK
    26 #define VBOXVHWA_ALLOW_PRIMARY_AND_OVERLAY_ONLY 1
     23/* Qt includes: */
     24#include <QtGlobal>
    2725
    28 /* Qt includes: */
    29 #ifdef RT_OS_WINDOWS
    30 # include <iprt/win/windows.h> /* QGLWidget drags in Windows.h; -Wall forces us to use wrapper. */
    31 # include <iprt/stdint.h>      /* QGLWidget drags in stdint.h; -Wall forces us to use wrapper. */
    32 #endif
    33 #include <QGLWidget>
     26/** 2D Video Acceleration Helpers */
     27namespace VBox2DHelpers
     28{
     29    /** Returns whether 2D Video Acceleration is available. */
     30    bool isAcceleration2DVideoAvailable();
    3431
    35 /* GUI includes: */
    36 #include "UIDefs.h"
    37 #include "VBoxFBOverlayCommon.h"
    38 #include "runtime/UIFrameBuffer.h"
    39 #include "runtime/UIMachineView.h"
    40 
    41 /* COM includes: */
    42 #include "COMEnums.h"
    43 
    44 #include "CDisplay.h"
    45 
    46 /* Other VBox includes: */
    47 #include <iprt/assert.h>
    48 #include <iprt/critsect.h>
    49 #include <iprt/asm.h>
    50 #include <iprt/err.h>
    51 #include <iprt/list.h>
    52 #include <VBox/VBoxGL2D.h>
    53 #ifdef VBOXVHWA_PROFILE_FPS
    54 # include <iprt/stream.h>
    55 #endif /* VBOXVHWA_PROFILE_FPS */
    56 
    57 #ifndef S_FALSE
    58 # define S_FALSE ((HRESULT)1L)
    59 #endif
    60 
    61 #ifdef DEBUG_misha
    62 # define VBOXVHWA_PROFILE_FPS
    63 #endif /* DEBUG_misha */
    64 
    65 /* Forward declarations: */
    66 class CSession;
    67 
    68 #ifdef DEBUG
    69 class VBoxVHWADbgTimer
    70 {
    71 public:
    72     VBoxVHWADbgTimer(uint32_t cPeriods);
    73     ~VBoxVHWADbgTimer();
    74     void frame();
    75     uint64_t everagePeriod() {return mPeriodSum / mcPeriods; }
    76     double fps() {return ((double)1000000000.0) / everagePeriod(); }
    77     uint64_t frames() {return mcFrames; }
    78 private:
    79     uint64_t mPeriodSum;
    80     uint64_t *mpaPeriods;
    81     uint64_t mPrevTime;
    82     uint64_t mcFrames;
    83     uint32_t mcPeriods;
    84     uint32_t miPeriod;
     32    /** Returns 2D offscreen video memory required for 2D Video Acceleration. */
     33    quint64 required2DOffscreenVideoMemory();
    8534};
    8635
    87 #endif /* DEBUG */
     36#endif /* VBOX_GUI_USE_QGL || VBOX_WITH_VIDEOHWACCEL */
    8837
    89 class VBoxVHWASettings
    90 {
    91 public:
    92     VBoxVHWASettings ();
    93     void init(CSession &session);
    94 
    95     int fourccEnabledCount() const { return mFourccEnabledCount; }
    96     const uint32_t * fourccEnabledList() const { return mFourccEnabledList; }
    97 
    98     bool isStretchLinearEnabled() const { return mStretchLinearEnabled; }
    99 
    100     static int calcIntersection (int c1, const uint32_t *a1, int c2, const uint32_t *a2, int cOut, uint32_t *aOut);
    101 
    102     int getIntersection (const VBoxVHWAInfo &aInfo, int cOut, uint32_t *aOut)
    103     {
    104         return calcIntersection (mFourccEnabledCount, mFourccEnabledList, aInfo.getFourccSupportedCount(), aInfo.getFourccSupportedList(), cOut, aOut);
    105     }
    106 
    107     bool isSupported(const VBoxVHWAInfo &aInfo, uint32_t format)
    108     {
    109         return calcIntersection (mFourccEnabledCount, mFourccEnabledList, 1, &format, 0, NULL)
    110                 && calcIntersection (aInfo.getFourccSupportedCount(), aInfo.getFourccSupportedList(), 1, &format, 0, NULL);
    111     }
    112 private:
    113     uint32_t mFourccEnabledList[VBOXVHWA_NUMFOURCC];
    114     int mFourccEnabledCount;
    115     bool mStretchLinearEnabled;
    116 };
    117 
    118 class VBoxVHWADirtyRect
    119 {
    120 public:
    121     VBoxVHWADirtyRect() :
    122         mIsClear(true)
    123     {}
    124 
    125     VBoxVHWADirtyRect(const QRect & aRect)
    126     {
    127         if(aRect.isEmpty())
    128         {
    129             mIsClear = false;
    130             mRect = aRect;
    131         }
    132         else
    133         {
    134             mIsClear = true;
    135         }
    136     }
    137 
    138     bool isClear() const { return mIsClear; }
    139 
    140     void add(const QRect & aRect)
    141     {
    142         if(aRect.isEmpty())
    143             return;
    144 
    145         mRect = mIsClear ? aRect : mRect.united(aRect);
    146         mIsClear = false;
    147     }
    148 
    149     void add(const VBoxVHWADirtyRect & aRect)
    150     {
    151         if(aRect.isClear())
    152             return;
    153         add(aRect.rect());
    154     }
    155 
    156     void set(const QRect & aRect)
    157     {
    158         if(aRect.isEmpty())
    159         {
    160             mIsClear = true;
    161         }
    162         else
    163         {
    164             mRect = aRect;
    165             mIsClear = false;
    166         }
    167     }
    168 
    169     void clear() { mIsClear = true; }
    170 
    171     const QRect & rect() const {return mRect;}
    172 
    173     const QRect & toRect()
    174     {
    175         if(isClear())
    176         {
    177             mRect.setCoords(0, 0, -1, -1);
    178         }
    179         return mRect;
    180     }
    181 
    182     bool intersects(const QRect & aRect) const {return mIsClear ? false : mRect.intersects(aRect);}
    183 
    184     bool intersects(const VBoxVHWADirtyRect & aRect) const {return mIsClear ? false : aRect.intersects(mRect);}
    185 
    186     QRect united(const QRect & aRect) const {return mIsClear ? aRect : aRect.united(mRect);}
    187 
    188     bool contains(const QRect & aRect) const {return mIsClear ? false : aRect.contains(mRect);}
    189 
    190     void subst(const VBoxVHWADirtyRect & aRect) { if(!mIsClear && aRect.contains(mRect)) clear(); }
    191 
    192 private:
    193     QRect mRect;
    194     bool mIsClear;
    195 };
    196 
    197 class VBoxVHWAColorKey
    198 {
    199 public:
    200     VBoxVHWAColorKey() :
    201         mUpper(0),
    202         mLower(0)
    203     {}
    204 
    205     VBoxVHWAColorKey(uint32_t aUpper, uint32_t aLower) :
    206         mUpper(aUpper),
    207         mLower(aLower)
    208     {}
    209 
    210     uint32_t upper() const {return mUpper; }
    211     uint32_t lower() const {return mLower; }
    212 
    213     bool operator==(const VBoxVHWAColorKey & other) const { return mUpper == other.mUpper && mLower == other.mLower; }
    214     bool operator!=(const VBoxVHWAColorKey & other) const { return !(*this == other); }
    215 private:
    216     uint32_t mUpper;
    217     uint32_t mLower;
    218 };
    219 
    220 class VBoxVHWAColorComponent
    221 {
    222 public:
    223     VBoxVHWAColorComponent() :
    224         mMask(0),
    225         mRange(0),
    226         mOffset(32),
    227         mcBits(0)
    228     {}
    229 
    230     VBoxVHWAColorComponent(uint32_t aMask);
    231 
    232     uint32_t mask() const { return mMask; }
    233     uint32_t range() const { return mRange; }
    234     uint32_t offset() const { return mOffset; }
    235     uint32_t cBits() const { return mcBits; }
    236     uint32_t colorVal(uint32_t col) const { return (col & mMask) >> mOffset; }
    237     float colorValNorm(uint32_t col) const { return ((float)colorVal(col))/mRange; }
    238 private:
    239     uint32_t mMask;
    240     uint32_t mRange;
    241     uint32_t mOffset;
    242     uint32_t mcBits;
    243 };
    244 
    245 class VBoxVHWAColorFormat
    246 {
    247 public:
    248 
    249     VBoxVHWAColorFormat(uint32_t bitsPerPixel, uint32_t r, uint32_t g, uint32_t b);
    250     VBoxVHWAColorFormat(uint32_t fourcc);
    251     VBoxVHWAColorFormat() :
    252         mBitsPerPixel(0) /* needed for isValid() to work */
    253     {}
    254     GLint internalFormat() const {return mInternalFormat; }
    255     GLenum format() const {return mFormat; }
    256     GLenum type() const {return mType; }
    257     bool isValid() const {return mBitsPerPixel != 0; }
    258     uint32_t fourcc() const {return mDataFormat;}
    259     uint32_t bitsPerPixel() const { return mBitsPerPixel; }
    260     uint32_t bitsPerPixelTex() const { return mBitsPerPixelTex; }
    261     void pixel2Normalized(uint32_t pix, float *r, float *g, float *b) const;
    262     uint32_t widthCompression() const {return mWidthCompression;}
    263     uint32_t heightCompression() const {return mHeightCompression;}
    264     const VBoxVHWAColorComponent& r() const {return mR;}
    265     const VBoxVHWAColorComponent& g() const {return mG;}
    266     const VBoxVHWAColorComponent& b() const {return mB;}
    267     const VBoxVHWAColorComponent& a() const {return mA;}
    268 
    269     bool equals (const VBoxVHWAColorFormat & other) const;
    270 
    271     ulong toVBoxPixelFormat() const
    272     {
    273         if (!mDataFormat)
    274         {
    275             /* RGB data */
    276             switch (mFormat)
    277             {
    278                 case GL_BGRA_EXT:
    279                     return KBitmapFormat_BGR;
    280             }
    281         }
    282         return KBitmapFormat_Opaque;
    283     }
    284 
    285 private:
    286     void init(uint32_t bitsPerPixel, uint32_t r, uint32_t g, uint32_t b);
    287     void init(uint32_t fourcc);
    288 
    289     GLint mInternalFormat;
    290     GLenum mFormat;
    291     GLenum mType;
    292     uint32_t mDataFormat;
    293 
    294     uint32_t mBitsPerPixel;
    295     uint32_t mBitsPerPixelTex;
    296     uint32_t mWidthCompression;
    297     uint32_t mHeightCompression;
    298     VBoxVHWAColorComponent mR;
    299     VBoxVHWAColorComponent mG;
    300     VBoxVHWAColorComponent mB;
    301     VBoxVHWAColorComponent mA;
    302 };
    303 
    304 class VBoxVHWATexture
    305 {
    306 public:
    307     VBoxVHWATexture() :
    308             mAddress(NULL),
    309             mTexture(0),
    310             mBytesPerPixel(0),
    311             mBytesPerPixelTex(0),
    312             mBytesPerLine(0),
    313             mScaleFuncttion(GL_NEAREST)
    314 {}
    315     VBoxVHWATexture(const QRect & aRect, const VBoxVHWAColorFormat &aFormat, uint32_t bytesPerLine, GLint scaleFuncttion);
    316     virtual ~VBoxVHWATexture();
    317     virtual void init(uchar *pvMem);
    318     void setAddress(uchar *pvMem) {mAddress = pvMem;}
    319     void update(const QRect * pRect) { doUpdate(mAddress, pRect);}
    320     void bind() {glBindTexture(texTarget(), mTexture);}
    321 
    322     virtual void texCoord(int x, int y);
    323     virtual void multiTexCoord(GLenum texUnit, int x, int y);
    324 
    325     const QRect & texRect() {return mTexRect;}
    326     const QRect & rect() {return mRect;}
    327     uchar * address(){ return mAddress; }
    328     uint32_t rectSizeTex(const QRect * pRect) {return pRect->width() * pRect->height() * mBytesPerPixelTex;}
    329     uchar * pointAddress(int x, int y)
    330     {
    331         x = toXTex(x);
    332         y = toYTex(y);
    333         return pointAddressTex(x, y);
    334     }
    335     uint32_t pointOffsetTex(int x, int y) { return y*mBytesPerLine + x*mBytesPerPixelTex; }
    336     uchar * pointAddressTex(int x, int y) { return mAddress + pointOffsetTex(x, y); }
    337     int toXTex(int x) {return x/mColorFormat.widthCompression();}
    338     int toYTex(int y) {return y/mColorFormat.heightCompression();}
    339     ulong memSize(){ return mBytesPerLine * mRect.height(); }
    340     uint32_t bytesPerLine() {return mBytesPerLine; }
    341 #ifdef DEBUG_misha
    342     void dbgDump();
    343 #endif
    344 
    345 protected:
    346     virtual void doUpdate(uchar * pAddress, const QRect * pRect);
    347     virtual void initParams();
    348     virtual void load();
    349     virtual GLenum texTarget() {return GL_TEXTURE_2D; }
    350     GLuint texture() {return mTexture;}
    351 
    352     QRect mTexRect; /* texture size */
    353     QRect mRect; /* img size */
    354     uchar * mAddress;
    355     GLuint mTexture;
    356     uint32_t mBytesPerPixel;
    357     uint32_t mBytesPerPixelTex;
    358     uint32_t mBytesPerLine;
    359     VBoxVHWAColorFormat mColorFormat;
    360     GLint mScaleFuncttion;
    361 private:
    362     void uninit();
    363 
    364     friend class VBoxVHWAFBO;
    365 };
    366 
    367 class VBoxVHWATextureNP2 : public VBoxVHWATexture
    368 {
    369 public:
    370     VBoxVHWATextureNP2() : VBoxVHWATexture() {}
    371     VBoxVHWATextureNP2(const QRect & aRect, const VBoxVHWAColorFormat &aFormat, uint32_t bytesPerLine, GLint scaleFuncttion) :
    372         VBoxVHWATexture(aRect, aFormat, bytesPerLine, scaleFuncttion){
    373         mTexRect = QRect(0, 0, aRect.width()/aFormat.widthCompression(), aRect.height()/aFormat.heightCompression());
    374     }
    375 };
    376 
    377 class VBoxVHWATextureNP2Rect : public VBoxVHWATextureNP2
    378 {
    379 public:
    380     VBoxVHWATextureNP2Rect() : VBoxVHWATextureNP2() {}
    381     VBoxVHWATextureNP2Rect(const QRect & aRect, const VBoxVHWAColorFormat &aFormat, uint32_t bytesPerLine, GLint scaleFuncttion) :
    382         VBoxVHWATextureNP2(aRect, aFormat, bytesPerLine, scaleFuncttion){}
    383 
    384     virtual void texCoord(int x, int y);
    385     virtual void multiTexCoord(GLenum texUnit, int x, int y);
    386 protected:
    387     virtual GLenum texTarget();
    388 };
    389 
    390 class VBoxVHWATextureNP2RectPBO : public VBoxVHWATextureNP2Rect
    391 {
    392 public:
    393     VBoxVHWATextureNP2RectPBO() :
    394         VBoxVHWATextureNP2Rect(),
    395         mPBO(0)
    396     {}
    397     VBoxVHWATextureNP2RectPBO(const QRect & aRect, const VBoxVHWAColorFormat &aFormat, uint32_t bytesPerLine, GLint scaleFuncttion) :
    398         VBoxVHWATextureNP2Rect(aRect, aFormat, bytesPerLine, scaleFuncttion),
    399         mPBO(0)
    400     {}
    401 
    402     virtual ~VBoxVHWATextureNP2RectPBO();
    403 
    404     virtual void init(uchar *pvMem);
    405 protected:
    406     virtual void load();
    407     virtual void doUpdate(uchar * pAddress, const QRect * pRect);
    408     GLuint mPBO;
    409 };
    410 
    411 class VBoxVHWATextureNP2RectPBOMapped : public VBoxVHWATextureNP2RectPBO
    412 {
    413 public:
    414     VBoxVHWATextureNP2RectPBOMapped() :
    415         VBoxVHWATextureNP2RectPBO(),
    416         mpMappedAllignedBuffer(NULL),
    417         mcbAllignedBufferSize(0),
    418         mcbOffset(0)
    419     {}
    420     VBoxVHWATextureNP2RectPBOMapped(const QRect & aRect, const VBoxVHWAColorFormat &aFormat, uint32_t bytesPerLine, GLint scaleFuncttion) :
    421             VBoxVHWATextureNP2RectPBO(aRect, aFormat, bytesPerLine, scaleFuncttion),
    422             mpMappedAllignedBuffer(NULL),
    423             mcbOffset(0)
    424     {
    425         mcbAllignedBufferSize = alignSize((size_t)memSize());
    426         mcbActualBufferSize = mcbAllignedBufferSize + 0x1fff;
    427     }
    428 
    429     uchar* mapAlignedBuffer();
    430     void   unmapBuffer();
    431     size_t alignedBufferSize() { return mcbAllignedBufferSize; }
    432 
    433     static size_t alignSize(size_t size)
    434     {
    435         size_t alSize = size & ~((size_t)0xfff);
    436         return alSize == size ? alSize : alSize + 0x1000;
    437     }
    438 
    439     static void* alignBuffer(void* pvMem) { return (void*)(((uintptr_t)pvMem) & ~((uintptr_t)0xfff)); }
    440     static size_t calcOffset(void* pvBase, void* pvOffset) { return (size_t)(((uintptr_t)pvBase) - ((uintptr_t)pvOffset)); }
    441 protected:
    442     virtual void load();
    443     virtual void doUpdate(uchar * pAddress, const QRect * pRect);
    444 private:
    445     uchar* mpMappedAllignedBuffer;
    446     size_t mcbAllignedBufferSize;
    447     size_t mcbOffset;
    448     size_t mcbActualBufferSize;
    449 };
    450 
    451 #define VBOXVHWAIMG_PBO    0x00000001U
    452 #define VBOXVHWAIMG_PBOIMG 0x00000002U
    453 #define VBOXVHWAIMG_FBO    0x00000004U
    454 #define VBOXVHWAIMG_LINEAR 0x00000008U
    455 typedef uint32_t VBOXVHWAIMG_TYPE;
    456 
    457 class VBoxVHWATextureImage
    458 {
    459 public:
    460     VBoxVHWATextureImage(const QRect &size, const VBoxVHWAColorFormat &format, class VBoxVHWAGlProgramMngr * aMgr, VBOXVHWAIMG_TYPE flags);
    461 
    462     virtual ~VBoxVHWATextureImage()
    463     {
    464         for(uint i = 0; i < mcTex; i++)
    465         {
    466             delete mpTex[i];
    467         }
    468     }
    469 
    470     virtual void init(uchar *pvMem)
    471     {
    472         for(uint32_t i = 0; i < mcTex; i++)
    473         {
    474             mpTex[i]->init(pvMem);
    475             pvMem += mpTex[i]->memSize();
    476         }
    477     }
    478 
    479     virtual void update(const QRect * pRect)
    480     {
    481         mpTex[0]->update(pRect);
    482         if(mColorFormat.fourcc() == FOURCC_YV12)
    483         {
    484             if(pRect)
    485             {
    486                 QRect rect(pRect->x()/2, pRect->y()/2,
    487                         pRect->width()/2, pRect->height()/2);
    488                 mpTex[1]->update(&rect);
    489                 mpTex[2]->update(&rect);
    490             }
    491             else
    492             {
    493                 mpTex[1]->update(NULL);
    494                 mpTex[2]->update(NULL);
    495             }
    496         }
    497     }
    498 
    499     virtual void display(VBoxVHWATextureImage *pDst, const QRect * pDstRect, const QRect * pSrcRect,
    500             const VBoxVHWAColorKey * pDstCKey, const VBoxVHWAColorKey * pSrcCKey, bool bNotIntersected);
    501 
    502 
    503     virtual void display();
    504 
    505     void deleteDisplay();
    506 
    507     int initDisplay(VBoxVHWATextureImage *pDst,
    508             const QRect * pDstRect, const QRect * pSrcRect,
    509             const VBoxVHWAColorKey * pDstCKey, const VBoxVHWAColorKey * pSrcCKey, bool bNotIntersected);
    510 
    511     bool displayInitialized() { return !!mVisibleDisplay;}
    512 
    513     virtual void setAddress(uchar *pvMem)
    514     {
    515         for(uint32_t i = 0; i < mcTex; i++)
    516         {
    517             mpTex[i]->setAddress(pvMem);
    518             pvMem += mpTex[i]->memSize();
    519         }
    520     }
    521 
    522     const QRect &rect()
    523     {
    524         return mpTex[0]->rect();
    525     }
    526 
    527     size_t memSize()
    528     {
    529         size_t size = 0;
    530         for(uint32_t i = 0; i < mcTex; i++)
    531         {
    532             size+=mpTex[i]->memSize();
    533         }
    534         return size;
    535     }
    536 
    537     uint32_t bytesPerLine() { return mpTex[0]->bytesPerLine(); }
    538 
    539     const VBoxVHWAColorFormat &pixelFormat() { return mColorFormat; }
    540 
    541     uint32_t numComponents() {return mcTex;}
    542 
    543     VBoxVHWATexture* component(uint32_t i) {return mpTex[i]; }
    544 
    545     const VBoxVHWATextureImage *dst() { return mpDst;}
    546     const QRect& dstRect() { return mDstRect; }
    547     const QRect& srcRect() { return mSrcRect; }
    548     const VBoxVHWAColorKey* dstCKey() { return mpDstCKey; }
    549     const VBoxVHWAColorKey* srcCKey() { return mpSrcCKey; }
    550     bool notIntersectedMode() { return mbNotIntersected; }
    551 
    552     static uint32_t calcBytesPerLine(const VBoxVHWAColorFormat & format, int width);
    553     static uint32_t calcMemSize(const VBoxVHWAColorFormat & format, int width, int height);
    554 
    555 #ifdef DEBUG_misha
    556     void dbgDump();
    557 #endif
    558 
    559 protected:
    560     static int setCKey(class VBoxVHWAGlProgramVHWA * pProgram, const VBoxVHWAColorFormat * pFormat, const VBoxVHWAColorKey * pCKey, bool bDst);
    561 
    562     static bool matchCKeys(const VBoxVHWAColorKey * pCKey1, const VBoxVHWAColorKey * pCKey2)
    563     {
    564         return (pCKey1 == NULL && pCKey2 == NULL)
    565                 || (*pCKey1 == *pCKey2);
    566     }
    567 
    568     void runDisplay(VBoxVHWATextureImage *pDst, const QRect * pDstRect, const QRect * pSrcRect)
    569     {
    570         bind(pDst);
    571 
    572         draw(pDst, pDstRect, pSrcRect);
    573     }
    574 
    575     virtual void draw(VBoxVHWATextureImage *pDst, const QRect * pDstRect, const QRect * pSrcRect);
    576 
    577     virtual uint32_t texCoord(GLenum tex, int x, int y)
    578     {
    579         uint32_t c = 1;
    580         mpTex[0]->multiTexCoord(tex, x, y);
    581         if(mColorFormat.fourcc() == FOURCC_YV12)
    582         {
    583             int x2 = x/2;
    584             int y2 = y/2;
    585             mpTex[1]->multiTexCoord(tex + 1, x2, y2);
    586             ++c;
    587         }
    588         return c;
    589     }
    590 
    591     virtual void bind(VBoxVHWATextureImage * pPrimary);
    592 
    593     virtual uint32_t calcProgramType(VBoxVHWATextureImage *pDst, const VBoxVHWAColorKey * pDstCKey, const VBoxVHWAColorKey * pSrcCKey, bool bNotIntersected);
    594 
    595     virtual class VBoxVHWAGlProgramVHWA * calcProgram(VBoxVHWATextureImage *pDst, const VBoxVHWAColorKey * pDstCKey, const VBoxVHWAColorKey * pSrcCKey, bool bNotIntersected);
    596 
    597     virtual int createDisplay(VBoxVHWATextureImage *pDst, const QRect * pDstRect, const QRect * pSrcRect,
    598             const VBoxVHWAColorKey * pDstCKey, const VBoxVHWAColorKey * pSrcCKey, bool bNotIntersected,
    599             GLuint *pDisplay, class VBoxVHWAGlProgramVHWA ** ppProgram);
    600 
    601     int createSetDisplay(VBoxVHWATextureImage *pDst, const QRect * pDstRect, const QRect * pSrcRect,
    602             const VBoxVHWAColorKey * pDstCKey, const VBoxVHWAColorKey * pSrcCKey, bool bNotIntersected);
    603 
    604     virtual int createDisplayList(VBoxVHWATextureImage *pDst, const QRect * pDstRect, const QRect * pSrcRect,
    605             const VBoxVHWAColorKey * pDstCKey, const VBoxVHWAColorKey * pSrcCKey, bool bNotIntersected,
    606             GLuint *pDisplay);
    607 
    608     virtual void deleteDisplayList();
    609 
    610     virtual void updateCKeys(VBoxVHWATextureImage * pDst, class VBoxVHWAGlProgramVHWA * pProgram, const VBoxVHWAColorKey * pDstCKey, const VBoxVHWAColorKey * pSrcCKey);
    611     virtual void updateSetCKeys(const VBoxVHWAColorKey * pDstCKey, const VBoxVHWAColorKey * pSrcCKey);
    612 
    613     void internalSetDstCKey(const VBoxVHWAColorKey * pDstCKey);
    614     void internalSetSrcCKey(const VBoxVHWAColorKey * pSrcCKey);
    615 
    616     VBoxVHWATexture *mpTex[3];
    617     uint32_t mcTex;
    618     GLuint mVisibleDisplay;
    619     class VBoxVHWAGlProgramVHWA * mpProgram;
    620     class VBoxVHWAGlProgramMngr * mProgramMngr;
    621     VBoxVHWAColorFormat mColorFormat;
    622 
    623     /* display info */
    624     VBoxVHWATextureImage *mpDst;
    625     QRect mDstRect;
    626     QRect mSrcRect;
    627     VBoxVHWAColorKey * mpDstCKey;
    628     VBoxVHWAColorKey * mpSrcCKey;
    629     VBoxVHWAColorKey mDstCKey;
    630     VBoxVHWAColorKey mSrcCKey;
    631     bool mbNotIntersected;
    632 };
    633 
    634 class VBoxVHWATextureImagePBO : public VBoxVHWATextureImage
    635 {
    636 public:
    637     VBoxVHWATextureImagePBO(const QRect &size, const VBoxVHWAColorFormat &format, class VBoxVHWAGlProgramMngr * aMgr, VBOXVHWAIMG_TYPE flags) :
    638             VBoxVHWATextureImage(size, format, aMgr, flags & (~VBOXVHWAIMG_PBO)),
    639             mPBO(0)
    640     {
    641     }
    642 
    643     virtual ~VBoxVHWATextureImagePBO()
    644     {
    645         if(mPBO)
    646         {
    647             VBOXQGL_CHECKERR(
    648                     vboxglDeleteBuffers(1, &mPBO);
    649                     );
    650         }
    651     }
    652 
    653     virtual void init(uchar *pvMem)
    654     {
    655         VBoxVHWATextureImage::init(pvMem);
    656 
    657         VBOXQGL_CHECKERR(
    658                 vboxglGenBuffers(1, &mPBO);
    659                 );
    660         mAddress = pvMem;
    661 
    662         VBOXQGL_CHECKERR(
    663                 vboxglBindBuffer(GL_PIXEL_UNPACK_BUFFER, mPBO);
    664             );
    665 
    666         VBOXQGL_CHECKERR(
    667                 vboxglBufferData(GL_PIXEL_UNPACK_BUFFER, memSize(), NULL, GL_STREAM_DRAW);
    668             );
    669 
    670         GLvoid *buf = vboxglMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
    671         Assert(buf);
    672         if(buf)
    673         {
    674             memcpy(buf, mAddress, memSize());
    675 
    676             bool unmapped = vboxglUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
    677             Assert(unmapped); NOREF(unmapped);
    678         }
    679 
    680         vboxglBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
    681 
    682     }
    683 
    684     virtual void update(const QRect * pRect)
    685     {
    686         VBOXQGL_CHECKERR(
    687                 vboxglBindBuffer(GL_PIXEL_UNPACK_BUFFER, mPBO);
    688         );
    689 
    690         GLvoid *buf;
    691 
    692         VBOXQGL_CHECKERR(
    693                 buf = vboxglMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
    694                 );
    695         Assert(buf);
    696         if(buf)
    697         {
    698 #ifdef VBOXVHWADBG_RENDERCHECK
    699             uint32_t * pBuf32 = (uint32_t*)buf;
    700             uchar * pBuf8 = (uchar*)buf;
    701             for(uint32_t i = 0; i < mcTex; i++)
    702             {
    703                 uint32_t dbgSetVal = 0x40404040 * (i+1);
    704                 for(uint32_t k = 0; k < mpTex[i]->memSize()/sizeof(pBuf32[0]); k++)
    705                 {
    706                     pBuf32[k] = dbgSetVal;
    707                 }
    708 
    709                 pBuf8 += mpTex[i]->memSize();
    710                 pBuf32 = (uint32_t *)pBuf8;
    711             }
    712 #else
    713             memcpy(buf, mAddress, memSize());
    714 #endif
    715 
    716             bool unmapped;
    717             VBOXQGL_CHECKERR(
    718                     unmapped = vboxglUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
    719                     );
    720 
    721             Assert(unmapped); NOREF(unmapped);
    722 
    723             VBoxVHWATextureImage::setAddress(0);
    724 
    725             VBoxVHWATextureImage::update(NULL);
    726 
    727             VBoxVHWATextureImage::setAddress(mAddress);
    728 
    729             vboxglBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
    730         }
    731         else
    732         {
    733             VBOXQGLLOGREL(("failed to map PBO, trying fallback to non-PBO approach\n"));
    734 
    735             VBoxVHWATextureImage::setAddress(mAddress);
    736 
    737             VBoxVHWATextureImage::update(pRect);
    738         }
    739     }
    740 
    741     virtual void setAddress(uchar *pvMem)
    742     {
    743         mAddress = pvMem;
    744     }
    745 private:
    746     GLuint mPBO;
    747     uchar* mAddress;
    748 };
    749 
    750 class VBoxVHWAHandleTable
    751 {
    752 public:
    753     VBoxVHWAHandleTable(uint32_t initialSize);
    754     ~VBoxVHWAHandleTable();
    755     uint32_t put(void * data);
    756     bool mapPut(uint32_t h, void * data);
    757     void* get(uint32_t h);
    758     void* remove(uint32_t h);
    759 private:
    760     void doPut(uint32_t h, void * data);
    761     void doRemove(uint32_t h);
    762     void** mTable;
    763     uint32_t mcSize;
    764     uint32_t mcUsage;
    765     uint32_t mCursor;
    766 };
    767 
    768 /* data flow:
    769  * I. NON-Yinverted surface:
    770  * 1.direct memory update (paint, lock/unlock):
    771  *  mem->tex->fb
    772  * 2.blt
    773  *  srcTex->invFB->tex->fb
    774  *              |->mem
    775  *
    776  * II. Yinverted surface:
    777  * 1.direct memory update (paint, lock/unlock):
    778  *  mem->tex->fb
    779  * 2.blt
    780  *  srcTex->fb->tex
    781  *           |->mem
    782  *
    783  * III. flip support:
    784  * 1. Yinverted<->NON-YInverted conversion :
    785  *  mem->tex-(rotate model view, force LAZY complete fb update)->invFB->tex
    786  *  fb-->|                                                           |->mem
    787  * */
    788 class VBoxVHWASurfaceBase
    789 {
    790 public:
    791     VBoxVHWASurfaceBase (class VBoxVHWAImage *pImage,
    792             const QSize & aSize,
    793             const QRect & aTargRect,
    794             const QRect & aSrcRect,
    795             const QRect & aVisTargRect,
    796             VBoxVHWAColorFormat & aColorFormat,
    797             VBoxVHWAColorKey * pSrcBltCKey, VBoxVHWAColorKey * pDstBltCKey,
    798             VBoxVHWAColorKey * pSrcOverlayCKey, VBoxVHWAColorKey * pDstOverlayCKey,
    799             VBOXVHWAIMG_TYPE aImgFlags);
    800 
    801     virtual ~VBoxVHWASurfaceBase();
    802 
    803     void init (VBoxVHWASurfaceBase * pPrimary, uchar *pvMem);
    804 
    805     void uninit();
    806 
    807     static void globalInit();
    808 
    809     int lock (const QRect * pRect, uint32_t flags);
    810 
    811     int unlock();
    812 
    813     void updatedMem (const QRect * aRect);
    814 
    815     bool performDisplay (VBoxVHWASurfaceBase *pPrimary, bool bForce);
    816 
    817     void setRects (const QRect & aTargRect, const QRect & aSrcRect);
    818     void setTargRectPosition (const QPoint & aPoint);
    819 
    820     void updateVisibility (VBoxVHWASurfaceBase *pPrimary, const QRect & aVisibleTargRect, bool bNotIntersected, bool bForce);
    821 
    822     static ulong calcBytesPerPixel (GLenum format, GLenum type);
    823 
    824     static GLsizei makePowerOf2 (GLsizei val);
    825 
    826     bool    addressAlocated() const { return mFreeAddress; }
    827     uchar * address() { return mAddress; }
    828 
    829     ulong   memSize();
    830 
    831     ulong width() const { return mRect.width();  }
    832     ulong height() const { return mRect.height(); }
    833     const QSize size() const {return mRect.size();}
    834 
    835     uint32_t fourcc() const {return mImage->pixelFormat().fourcc(); }
    836 
    837     ulong  bitsPerPixel() const { return mImage->pixelFormat().bitsPerPixel(); }
    838     ulong  bytesPerLine() const { return mImage->bytesPerLine(); }
    839 
    840     const VBoxVHWAColorKey * dstBltCKey() const { return mpDstBltCKey; }
    841     const VBoxVHWAColorKey * srcBltCKey() const { return mpSrcBltCKey; }
    842     const VBoxVHWAColorKey * dstOverlayCKey() const { return mpDstOverlayCKey; }
    843     const VBoxVHWAColorKey * defaultSrcOverlayCKey() const { return mpDefaultSrcOverlayCKey; }
    844     const VBoxVHWAColorKey * defaultDstOverlayCKey() const { return mpDefaultDstOverlayCKey; }
    845     const VBoxVHWAColorKey * srcOverlayCKey() const { return mpSrcOverlayCKey; }
    846     void resetDefaultSrcOverlayCKey() { mpSrcOverlayCKey = mpDefaultSrcOverlayCKey; }
    847     void resetDefaultDstOverlayCKey() { mpDstOverlayCKey = mpDefaultDstOverlayCKey; }
    848 
    849     void setDstBltCKey (const VBoxVHWAColorKey * ckey)
    850     {
    851         if(ckey)
    852         {
    853             mDstBltCKey = *ckey;
    854             mpDstBltCKey = &mDstBltCKey;
    855         }
    856         else
    857         {
    858             mpDstBltCKey = NULL;
    859         }
    860     }
    861 
    862     void setSrcBltCKey (const VBoxVHWAColorKey * ckey)
    863     {
    864         if(ckey)
    865         {
    866             mSrcBltCKey = *ckey;
    867             mpSrcBltCKey = &mSrcBltCKey;
    868         }
    869         else
    870         {
    871             mpSrcBltCKey = NULL;
    872         }
    873     }
    874 
    875     void setDefaultDstOverlayCKey (const VBoxVHWAColorKey * ckey)
    876     {
    877         if(ckey)
    878         {
    879             mDefaultDstOverlayCKey = *ckey;
    880             mpDefaultDstOverlayCKey = &mDefaultDstOverlayCKey;
    881         }
    882         else
    883         {
    884             mpDefaultDstOverlayCKey = NULL;
    885         }
    886     }
    887 
    888     void setDefaultSrcOverlayCKey (const VBoxVHWAColorKey * ckey)
    889     {
    890         if(ckey)
    891         {
    892             mDefaultSrcOverlayCKey = *ckey;
    893             mpDefaultSrcOverlayCKey = &mDefaultSrcOverlayCKey;
    894         }
    895         else
    896         {
    897             mpDefaultSrcOverlayCKey = NULL;
    898         }
    899     }
    900 
    901     void setOverriddenDstOverlayCKey (const VBoxVHWAColorKey * ckey)
    902     {
    903         if(ckey)
    904         {
    905             mOverriddenDstOverlayCKey = *ckey;
    906             mpDstOverlayCKey = &mOverriddenDstOverlayCKey;
    907         }
    908         else
    909         {
    910             mpDstOverlayCKey = NULL;
    911         }
    912     }
    913 
    914     void setOverriddenSrcOverlayCKey (const VBoxVHWAColorKey * ckey)
    915     {
    916         if(ckey)
    917         {
    918             mOverriddenSrcOverlayCKey = *ckey;
    919             mpSrcOverlayCKey = &mOverriddenSrcOverlayCKey;
    920         }
    921         else
    922         {
    923             mpSrcOverlayCKey = NULL;
    924         }
    925     }
    926 
    927     const VBoxVHWAColorKey * getActiveSrcOverlayCKey()
    928     {
    929         return mpSrcOverlayCKey;
    930     }
    931 
    932     const VBoxVHWAColorKey * getActiveDstOverlayCKey (VBoxVHWASurfaceBase * pPrimary)
    933     {
    934         return mpDstOverlayCKey ? mpDefaultDstOverlayCKey : (pPrimary ? pPrimary->mpDstOverlayCKey : NULL);
    935     }
    936 
    937     const VBoxVHWAColorFormat & pixelFormat() const { return mImage->pixelFormat(); }
    938 
    939     void setAddress(uchar * addr);
    940 
    941     const QRect& rect() const {return mRect;}
    942     const QRect& srcRect() const {return mSrcRect; }
    943     const QRect& targRect() const {return mTargRect; }
    944     class VBoxVHWASurfList * getComplexList() {return mComplexList; }
    945 
    946     class VBoxVHWAGlProgramMngr * getGlProgramMngr();
    947 
    948     uint32_t handle() const {return mHGHandle;}
    949     void setHandle(uint32_t h) {mHGHandle = h;}
    950 
    951     const VBoxVHWADirtyRect & getDirtyRect() { return mUpdateMem2TexRect; }
    952 
    953     VBoxVHWASurfaceBase * primary() { return mpPrimary; }
    954     void setPrimary(VBoxVHWASurfaceBase *apPrimary) { mpPrimary = apPrimary; }
    955 private:
    956     void setRectValues (const QRect & aTargRect, const QRect & aSrcRect);
    957     void setVisibleRectValues (const QRect & aVisTargRect);
    958 
    959     void setComplexList (VBoxVHWASurfList *aComplexList) { mComplexList = aComplexList; }
    960     void initDisplay();
    961 
    962     bool synchTexMem (const QRect * aRect);
    963 
    964     int performBlt (const QRect * pDstRect, VBoxVHWASurfaceBase * pSrcSurface, const QRect * pSrcRect, const VBoxVHWAColorKey * pDstCKey, const VBoxVHWAColorKey * pSrcCKey, bool blt);
    965 
    966     QRect mRect; /* == Inv FB size */
    967 
    968     QRect mSrcRect;
    969     QRect mTargRect; /* == Vis FB size */
    970 
    971     QRect mVisibleTargRect;
    972     QRect mVisibleSrcRect;
    973 
    974     class VBoxVHWATextureImage * mImage;
    975 
    976     uchar * mAddress;
    977 
    978     VBoxVHWAColorKey *mpSrcBltCKey;
    979     VBoxVHWAColorKey *mpDstBltCKey;
    980     VBoxVHWAColorKey *mpSrcOverlayCKey;
    981     VBoxVHWAColorKey *mpDstOverlayCKey;
    982 
    983     VBoxVHWAColorKey *mpDefaultDstOverlayCKey;
    984     VBoxVHWAColorKey *mpDefaultSrcOverlayCKey;
    985 
    986     VBoxVHWAColorKey mSrcBltCKey;
    987     VBoxVHWAColorKey mDstBltCKey;
    988     VBoxVHWAColorKey mOverriddenSrcOverlayCKey;
    989     VBoxVHWAColorKey mOverriddenDstOverlayCKey;
    990     VBoxVHWAColorKey mDefaultDstOverlayCKey;
    991     VBoxVHWAColorKey mDefaultSrcOverlayCKey;
    992 
    993     int mLockCount;
    994     /* memory buffer not reflected in fm and texture, e.g if memory buffer is replaced or in case of lock/unlock  */
    995     VBoxVHWADirtyRect mUpdateMem2TexRect;
    996 
    997     bool mFreeAddress;
    998     bool mbNotIntersected;
    999 
    1000     class VBoxVHWASurfList *mComplexList;
    1001 
    1002     VBoxVHWASurfaceBase *mpPrimary;
    1003 
    1004     uint32_t mHGHandle;
    1005 
    1006     class VBoxVHWAImage *mpImage;
    1007 
    1008 #ifdef DEBUG
    1009 public:
    1010     uint64_t cFlipsCurr;
    1011     uint64_t cFlipsTarg;
    1012 #endif
    1013     friend class VBoxVHWASurfList;
    1014 };
    1015 
    1016 typedef std::list <VBoxVHWASurfaceBase*> SurfList;
    1017 typedef std::list <VBoxVHWASurfList*> OverlayList;
    1018 typedef std::list <struct VBOXVHWACMD *> VHWACommandList;
    1019 
    1020 class VBoxVHWASurfList
    1021 {
    1022 public:
    1023 
    1024     VBoxVHWASurfList() : mCurrent(NULL) {}
    1025 
    1026     void moveTo(VBoxVHWASurfList *pDst)
    1027     {
    1028         for (SurfList::iterator it = mSurfaces.begin();
    1029              it != mSurfaces.end(); it = mSurfaces.begin())
    1030         {
    1031             pDst->add((*it));
    1032         }
    1033 
    1034         Assert(empty());
    1035     }
    1036 
    1037     void add(VBoxVHWASurfaceBase *pSurf)
    1038     {
    1039         VBoxVHWASurfList * pOld = pSurf->getComplexList();
    1040         if(pOld)
    1041         {
    1042             pOld->remove(pSurf);
    1043         }
    1044         mSurfaces.push_back(pSurf);
    1045         pSurf->setComplexList(this);
    1046     }
    1047 /*
    1048     void clear()
    1049     {
    1050         for (SurfList::iterator it = mSurfaces.begin();
    1051              it != mSurfaces.end(); ++ it)
    1052         {
    1053             (*it)->setComplexList(NULL);
    1054         }
    1055         mSurfaces.clear();
    1056         mCurrent = NULL;
    1057     }
    1058 */
    1059     size_t size() const {return mSurfaces.size(); }
    1060 
    1061     void remove(VBoxVHWASurfaceBase *pSurf)
    1062     {
    1063         mSurfaces.remove(pSurf);
    1064         pSurf->setComplexList(NULL);
    1065         if(mCurrent == pSurf)
    1066             mCurrent = NULL;
    1067     }
    1068 
    1069     bool empty() { return mSurfaces.empty(); }
    1070 
    1071     void setCurrentVisible(VBoxVHWASurfaceBase *pSurf)
    1072     {
    1073         mCurrent = pSurf;
    1074     }
    1075 
    1076     VBoxVHWASurfaceBase * current() { return mCurrent; }
    1077     const SurfList & surfaces() const {return mSurfaces;}
    1078 
    1079 private:
    1080 
    1081     SurfList mSurfaces;
    1082     VBoxVHWASurfaceBase* mCurrent;
    1083 };
    1084 
    1085 class VBoxVHWADisplay
    1086 {
    1087 public:
    1088     VBoxVHWADisplay() :
    1089         mSurfVGA(NULL),
    1090         mbDisplayPrimary(true)
    1091 //        ,
    1092 //        mSurfPrimary(NULL)
    1093     {}
    1094 
    1095     VBoxVHWASurfaceBase * setVGA(VBoxVHWASurfaceBase * pVga)
    1096     {
    1097         VBoxVHWASurfaceBase * old = mSurfVGA;
    1098         mSurfVGA = pVga;
    1099         if (!mPrimary.empty())
    1100         {
    1101             VBoxVHWASurfList *pNewList = new VBoxVHWASurfList();
    1102             mPrimary.moveTo(pNewList);
    1103             Assert(mPrimary.empty());
    1104         }
    1105         if(pVga)
    1106         {
    1107             Assert(!pVga->getComplexList());
    1108             mPrimary.add(pVga);
    1109             mPrimary.setCurrentVisible(pVga);
    1110         }
    1111         mOverlays.clear();
    1112         return old;
    1113     }
    1114 
    1115     VBoxVHWASurfaceBase * updateVGA(VBoxVHWASurfaceBase * pVga)
    1116     {
    1117         VBoxVHWASurfaceBase * old = mSurfVGA;
    1118         Assert(old);
    1119         mSurfVGA = pVga;
    1120         return old;
    1121     }
    1122 
    1123     VBoxVHWASurfaceBase * getVGA() const
    1124     {
    1125         return mSurfVGA;
    1126     }
    1127 
    1128     VBoxVHWASurfaceBase * getPrimary()
    1129     {
    1130         return mPrimary.current();
    1131     }
    1132 
    1133     void addOverlay(VBoxVHWASurfList * pSurf)
    1134     {
    1135         mOverlays.push_back(pSurf);
    1136     }
    1137 
    1138     void checkAddOverlay(VBoxVHWASurfList * pSurf)
    1139     {
    1140         if(!hasOverlay(pSurf))
    1141             addOverlay(pSurf);
    1142     }
    1143 
    1144     bool hasOverlay(VBoxVHWASurfList * pSurf)
    1145     {
    1146         for (OverlayList::iterator it = mOverlays.begin();
    1147              it != mOverlays.end(); ++ it)
    1148         {
    1149             if((*it) == pSurf)
    1150             {
    1151                 return true;
    1152             }
    1153         }
    1154         return false;
    1155     }
    1156 
    1157     void removeOverlay(VBoxVHWASurfList * pSurf)
    1158     {
    1159         mOverlays.remove(pSurf);
    1160     }
    1161 
    1162     bool performDisplay(bool bForce)
    1163     {
    1164         VBoxVHWASurfaceBase * pPrimary = mPrimary.current();
    1165 
    1166         if(mbDisplayPrimary)
    1167         {
    1168 #ifdef DEBUG_misha
    1169             /* should only display overlay now */
    1170             AssertBreakpoint();
    1171 #endif
    1172             bForce |= pPrimary->performDisplay(NULL, bForce);
    1173         }
    1174 
    1175         for (OverlayList::const_iterator it = mOverlays.begin();
    1176              it != mOverlays.end(); ++ it)
    1177         {
    1178             VBoxVHWASurfaceBase * pOverlay = (*it)->current();
    1179             if(pOverlay)
    1180             {
    1181                 bForce |= pOverlay->performDisplay(pPrimary, bForce);
    1182             }
    1183         }
    1184         return bForce;
    1185     }
    1186 
    1187     bool isPrimary(VBoxVHWASurfaceBase * pSurf) { return pSurf->getComplexList() == &mPrimary; }
    1188 
    1189     void setDisplayPrimary(bool bDisplay) { mbDisplayPrimary = bDisplay; }
    1190 
    1191     const OverlayList & overlays() const {return mOverlays;}
    1192     const VBoxVHWASurfList & primaries() const { return mPrimary; }
    1193 
    1194 private:
    1195     VBoxVHWASurfaceBase *mSurfVGA;
    1196     VBoxVHWASurfList mPrimary;
    1197 
    1198     OverlayList mOverlays;
    1199 
    1200     bool mbDisplayPrimary;
    1201 };
    1202 
    1203 typedef void (*PFNVBOXQGLFUNC)(void*, void*);
    1204 
    1205 typedef enum
    1206 {
    1207     VBOXVHWA_PIPECMD_PAINT = 1,
    1208     VBOXVHWA_PIPECMD_VHWA,
    1209     VBOXVHWA_PIPECMD_FUNC
    1210 }VBOXVHWA_PIPECMD_TYPE;
    1211 
    1212 typedef struct VBOXVHWAFUNCCALLBACKINFO
    1213 {
    1214     PFNVBOXQGLFUNC pfnCallback;
    1215     void * pContext1;
    1216     void * pContext2;
    1217 }VBOXVHWAFUNCCALLBACKINFO;
    1218 
    1219 class VBoxVHWACommandElement
    1220 {
    1221 public:
    1222     void setVHWACmd(struct VBOXVHWACMD RT_UNTRUSTED_VOLATILE_GUEST *pCmd, int enmCmd, bool fGuestCmd)
    1223     {
    1224         mType = VBOXVHWA_PIPECMD_VHWA;
    1225         u.s.mpCmd = pCmd;
    1226         u.s.menmCmd = enmCmd;
    1227         u.s.mfGuestCmd = fGuestCmd;
    1228     }
    1229 
    1230     void setPaintCmd(const QRect & aRect)
    1231     {
    1232         mType = VBOXVHWA_PIPECMD_PAINT;
    1233         mRect = aRect;
    1234     }
    1235 
    1236     void setFunc(const VBOXVHWAFUNCCALLBACKINFO & aOp)
    1237     {
    1238         mType = VBOXVHWA_PIPECMD_FUNC;
    1239         u.mFuncCallback = aOp;
    1240     }
    1241 
    1242     void setData(VBOXVHWA_PIPECMD_TYPE aType, void *pvData, int /*VBOXVHWACMD_TYPE*/ enmCmd, bool fGuestCmd = false)
    1243     {
    1244         switch (aType)
    1245         {
    1246         case VBOXVHWA_PIPECMD_PAINT:
    1247             setPaintCmd(*((QRect *)pvData));
    1248             break;
    1249         case VBOXVHWA_PIPECMD_VHWA:
    1250             setVHWACmd((struct VBOXVHWACMD *)pvData, enmCmd, fGuestCmd);
    1251             break;
    1252         case VBOXVHWA_PIPECMD_FUNC:
    1253             setFunc(*((VBOXVHWAFUNCCALLBACKINFO *)pvData));
    1254             break;
    1255         default:
    1256             AssertFailed();
    1257             mType = (VBOXVHWA_PIPECMD_TYPE)0;
    1258             break;
    1259         }
    1260     }
    1261 
    1262     VBOXVHWA_PIPECMD_TYPE type() const {return mType;}
    1263     const QRect & rect() const {return mRect;}
    1264     struct VBOXVHWACMD RT_UNTRUSTED_VOLATILE_GUEST *vhwaCmdPtr() const      { return u.s.mpCmd; }
    1265     int /*VBOXVHWACMD_TYPE*/                        vhwaCmdType() const     { return u.s.menmCmd; }
    1266     bool                                            vhwaIsGuestCmd() const  { return u.s.mfGuestCmd; }
    1267     const VBOXVHWAFUNCCALLBACKINFO & func() const {return u.mFuncCallback; }
    1268 
    1269     RTLISTNODE ListNode;
    1270 private:
    1271     VBOXVHWA_PIPECMD_TYPE mType;
    1272     union
    1273     {
    1274         struct
    1275         {
    1276             struct VBOXVHWACMD RT_UNTRUSTED_VOLATILE_GUEST *mpCmd;
    1277             int /*VBOXVHWACMD_TYPE*/                        menmCmd;
    1278             bool                                            mfGuestCmd;
    1279         } s;
    1280         VBOXVHWAFUNCCALLBACKINFO mFuncCallback;
    1281     } u;
    1282     QRect                 mRect;
    1283 };
    1284 
    1285 class VBoxVHWARefCounter
    1286 {
    1287 #define VBOXVHWA_INIFITE_WAITCOUNT (~0U)
    1288 public:
    1289     VBoxVHWARefCounter() : m_cRefs(0) {}
    1290     VBoxVHWARefCounter(uint32_t cRefs) : m_cRefs(cRefs) {}
    1291     void inc() { ASMAtomicIncU32(&m_cRefs); }
    1292     uint32_t dec()
    1293     {
    1294         uint32_t cRefs = ASMAtomicDecU32(&m_cRefs);
    1295         Assert(cRefs < UINT32_MAX / 2);
    1296         return cRefs;
    1297     }
    1298 
    1299     uint32_t refs() { return ASMAtomicReadU32(&m_cRefs); }
    1300 
    1301     int wait0(RTMSINTERVAL ms = 1000, uint32_t cWaits = VBOXVHWA_INIFITE_WAITCOUNT)
    1302     {
    1303         int rc = VINF_SUCCESS;
    1304         do
    1305         {
    1306             if (!refs())
    1307                 break;
    1308             if (!cWaits)
    1309             {
    1310                 rc = VERR_TIMEOUT;
    1311                 break;
    1312             }
    1313             if (cWaits != VBOXVHWA_INIFITE_WAITCOUNT)
    1314                 --cWaits;
    1315             rc = RTThreadSleep(ms);
    1316             AssertRC(rc);
    1317             if (!RT_SUCCESS(rc))
    1318                 break;
    1319         } while(1);
    1320         return rc;
    1321     }
    1322 private:
    1323     volatile uint32_t m_cRefs;
    1324 };
    1325 
    1326 class VBoxVHWAEntriesCache;
    1327 class VBoxVHWACommandElementProcessor
    1328 {
    1329 public:
    1330     VBoxVHWACommandElementProcessor();
    1331     void init(QObject *pNotifyObject);
    1332     ~VBoxVHWACommandElementProcessor();
    1333     void postCmd(VBOXVHWA_PIPECMD_TYPE aType, void *pvData, int /*VBOXVHWACMD_TYPE*/ enmCmdInt, bool fGuestCmd);
    1334     VBoxVHWACommandElement *getCmd();
    1335     void doneCmd();
    1336     void reset(CDisplay *pDisplay);
    1337     void setNotifyObject(QObject *pNotifyObject);
    1338     int loadExec (struct SSMHANDLE * pSSM, uint32_t u32Version, void *pvVRAM);
    1339     void saveExec (struct SSMHANDLE * pSSM, void *pvVRAM);
    1340     void disable();
    1341     void enable();
    1342     void lock();
    1343     void unlock();
    1344 private:
    1345     RTCRITSECT mCritSect;
    1346     RTLISTNODE mCommandList;
    1347     QObject *m_pNotifyObject;
    1348     VBoxVHWARefCounter m_NotifyObjectRefs;
    1349     VBoxVHWACommandElement *mpCurCmd;
    1350     bool mbResetting;
    1351     uint32_t mcDisabled;
    1352     VBoxVHWAEntriesCache *m_pCmdEntryCache;
    1353 };
    1354 
    1355 /* added to workaround this ** [VBox|UI] duplication */
    1356 class VBoxFBSizeInfo
    1357 {
    1358 public:
    1359 
    1360     VBoxFBSizeInfo() {}
    1361     template<class T> VBoxFBSizeInfo(T *pFb) :
    1362         m_visualState(pFb->visualState()),
    1363         mPixelFormat(pFb->pixelFormat()), mVRAM(pFb->address()), mBitsPerPixel(pFb->bitsPerPixel()),
    1364         mBytesPerLine(pFb->bytesPerLine()), mWidth(pFb->width()), mHeight(pFb->height()),
    1365         m_dScaleFactor(pFb->scaleFactor()), m_scaledSize(pFb->scaledSize()), m_fUseUnscaledHiDPIOutput(pFb->useUnscaledHiDPIOutput()),
    1366         mUsesGuestVram(true) {}
    1367 
    1368     VBoxFBSizeInfo(UIVisualStateType visualState,
    1369                    ulong aPixelFormat, uchar *aVRAM,
    1370                    ulong aBitsPerPixel, ulong aBytesPerLine,
    1371                    ulong aWidth, ulong aHeight,
    1372                    double dScaleFactor, const QSize &scaledSize, bool fUseUnscaledHiDPIOutput,
    1373                    bool bUsesGuestVram) :
    1374         m_visualState(visualState),
    1375         mPixelFormat(aPixelFormat), mVRAM(aVRAM), mBitsPerPixel(aBitsPerPixel),
    1376         mBytesPerLine(aBytesPerLine), mWidth(aWidth), mHeight(aHeight),
    1377         m_dScaleFactor(dScaleFactor), m_scaledSize(scaledSize), m_fUseUnscaledHiDPIOutput(fUseUnscaledHiDPIOutput),
    1378         mUsesGuestVram(bUsesGuestVram) {}
    1379 
    1380     UIVisualStateType visualState() const { return m_visualState; }
    1381     ulong pixelFormat() const { return mPixelFormat; }
    1382     uchar *VRAM() const { return mVRAM; }
    1383     ulong bitsPerPixel() const { return mBitsPerPixel; }
    1384     ulong bytesPerLine() const { return mBytesPerLine; }
    1385     ulong width() const { return mWidth; }
    1386     ulong height() const { return mHeight; }
    1387     double scaleFactor() const { return m_dScaleFactor; }
    1388     QSize scaledSize() const { return m_scaledSize; }
    1389     bool useUnscaledHiDPIOutput() const { return m_fUseUnscaledHiDPIOutput; }
    1390     bool usesGuestVram() const {return mUsesGuestVram;}
    1391 
    1392 private:
    1393 
    1394     UIVisualStateType m_visualState;
    1395     ulong mPixelFormat;
    1396     uchar *mVRAM;
    1397     ulong mBitsPerPixel;
    1398     ulong mBytesPerLine;
    1399     ulong mWidth;
    1400     ulong mHeight;
    1401     double m_dScaleFactor;
    1402     QSize m_scaledSize;
    1403     bool m_fUseUnscaledHiDPIOutput;
    1404     bool mUsesGuestVram;
    1405 };
    1406 
    1407 class VBoxVHWAImage
    1408 {
    1409 public:
    1410     VBoxVHWAImage ();
    1411     ~VBoxVHWAImage();
    1412 
    1413     int init(VBoxVHWASettings *aSettings);
    1414 #ifdef VBOX_WITH_VIDEOHWACCEL
    1415     uchar *vboxVRAMAddressFromOffset(uint64_t offset);
    1416     uint64_t vboxVRAMOffsetFromAddress(uchar* addr);
    1417     uint64_t vboxVRAMOffset(VBoxVHWASurfaceBase * pSurf);
    1418 
    1419     void vhwaSaveExec(struct SSMHANDLE * pSSM);
    1420     static void vhwaSaveExecVoid(struct SSMHANDLE * pSSM);
    1421     static int vhwaLoadExec(VHWACommandList * pCmdList, struct SSMHANDLE * pSSM, uint32_t u32Version);
    1422 
    1423     int vhwaSurfaceCanCreate(struct VBOXVHWACMD_SURF_CANCREATE RT_UNTRUSTED_VOLATILE_GUEST *pCmd);
    1424     int vhwaSurfaceCreate(struct VBOXVHWACMD_SURF_CREATE RT_UNTRUSTED_VOLATILE_GUEST *pCmd);
    1425 #ifdef VBOX_WITH_WDDM
    1426     int vhwaSurfaceGetInfo(struct VBOXVHWACMD_SURF_GETINFO RT_UNTRUSTED_VOLATILE_GUEST *pCmd);
    1427 #endif
    1428     int vhwaSurfaceDestroy(struct VBOXVHWACMD_SURF_DESTROY RT_UNTRUSTED_VOLATILE_GUEST *pCmd);
    1429     int vhwaSurfaceLock(struct VBOXVHWACMD_SURF_LOCK RT_UNTRUSTED_VOLATILE_GUEST *pCmd);
    1430     int vhwaSurfaceUnlock(struct VBOXVHWACMD_SURF_UNLOCK RT_UNTRUSTED_VOLATILE_GUEST *pCmd);
    1431     int vhwaSurfaceBlt(struct VBOXVHWACMD_SURF_BLT RT_UNTRUSTED_VOLATILE_GUEST *pCmd);
    1432     int vhwaSurfaceFlip(struct VBOXVHWACMD_SURF_FLIP RT_UNTRUSTED_VOLATILE_GUEST *pCmd);
    1433     int vhwaSurfaceColorFill(struct VBOXVHWACMD_SURF_COLORFILL RT_UNTRUSTED_VOLATILE_GUEST *pCmd);
    1434     int vhwaSurfaceOverlayUpdate(struct VBOXVHWACMD_SURF_OVERLAY_UPDATE RT_UNTRUSTED_VOLATILE_GUEST *pCmf);
    1435     int vhwaSurfaceOverlaySetPosition(struct VBOXVHWACMD_SURF_OVERLAY_SETPOSITION RT_UNTRUSTED_VOLATILE_GUEST *pCmd);
    1436     int vhwaSurfaceColorkeySet(struct VBOXVHWACMD_SURF_COLORKEY_SET RT_UNTRUSTED_VOLATILE_GUEST *pCmd);
    1437     int vhwaQueryInfo1(struct VBOXVHWACMD_QUERYINFO1 RT_UNTRUSTED_VOLATILE_GUEST *pCmd);
    1438     int vhwaQueryInfo2(struct VBOXVHWACMD_QUERYINFO2 RT_UNTRUSTED_VOLATILE_GUEST *pCmd);
    1439     int vhwaConstruct(struct VBOXVHWACMD_HH_CONSTRUCT *pCmd);
    1440 
    1441     void *vramBase() { return mpvVRAM; }
    1442     uint32_t vramSize() { return mcbVRAM; }
    1443 
    1444     bool hasSurfaces() const;
    1445     bool hasVisibleOverlays();
    1446     QRect overlaysRectUnion();
    1447     QRect overlaysRectIntersection();
    1448 #endif
    1449 
    1450     static const QGLFormat & vboxGLFormat();
    1451 
    1452     int reset(VHWACommandList * pCmdList);
    1453 
    1454     int vboxFbWidth() {return mDisplay.getVGA()->width(); }
    1455     int vboxFbHeight() {return mDisplay.getVGA()->height(); }
    1456     bool isInitialized() {return mDisplay.getVGA() != NULL; }
    1457 
    1458     void resize(const VBoxFBSizeInfo & size);
    1459 
    1460     class VBoxVHWAGlProgramMngr * vboxVHWAGetGlProgramMngr() { return mpMngr; }
    1461 
    1462     VBoxVHWASurfaceBase * vgaSurface() { return mDisplay.getVGA(); }
    1463 
    1464 #ifdef VBOXVHWA_OLD_COORD
    1465     static void doSetupMatrix(const QSize & aSize, bool bInverted);
    1466 #endif
    1467 
    1468     void vboxDoUpdateViewport(const QRect & aRect);
    1469     void vboxDoUpdateRect(const QRect * pRect);
    1470 
    1471     const QRect & vboxViewport() const {return mViewport;}
    1472 
    1473 #ifdef VBOXVHWA_PROFILE_FPS
    1474     void reportNewFrame() { mbNewFrame = true; }
    1475 #endif
    1476 
    1477     bool performDisplay(bool bForce)
    1478     {
    1479         bForce = mDisplay.performDisplay(bForce | mRepaintNeeded);
    1480 
    1481 #ifdef VBOXVHWA_PROFILE_FPS
    1482         if(mbNewFrame)
    1483         {
    1484             mFPSCounter.frame();
    1485             double fps = mFPSCounter.fps();
    1486             if(!(mFPSCounter.frames() % 31))
    1487             {
    1488                 LogRel(("fps: %f\n", fps));
    1489             }
    1490             mbNewFrame = false;
    1491         }
    1492 #endif
    1493         return bForce;
    1494     }
    1495 
    1496     static void pushSettingsAndSetupViewport(const QSize &display, const QRect &viewport)
    1497     {
    1498         glPushAttrib(GL_ALL_ATTRIB_BITS);
    1499         glMatrixMode(GL_PROJECTION);
    1500         glPushMatrix();
    1501         setupMatricies(display, false);
    1502         adjustViewport(display, viewport);
    1503     }
    1504 
    1505     static void popSettingsAfterSetupViewport()
    1506     {
    1507         glPopAttrib();
    1508         glMatrixMode(GL_PROJECTION);
    1509         glPopMatrix();
    1510         glMatrixMode(GL_MODELVIEW);
    1511     }
    1512 
    1513 private:
    1514     static void setupMatricies(const QSize &display, bool bInvert);
    1515     static void adjustViewport(const QSize &display, const QRect &viewport);
    1516 
    1517 
    1518 #ifdef VBOXQGL_DBG_SURF
    1519     void vboxDoTestSurfaces(void *context);
    1520 #endif
    1521 #ifdef VBOX_WITH_VIDEOHWACCEL
    1522 
    1523     void vboxCheckUpdateAddress(VBoxVHWASurfaceBase * pSurface, uint64_t offset)
    1524     {
    1525         if (pSurface->addressAlocated())
    1526         {
    1527             Assert(!mDisplay.isPrimary(pSurface));
    1528             uchar * addr = vboxVRAMAddressFromOffset(offset);
    1529             if (addr)
    1530             {
    1531                 pSurface->setAddress(addr);
    1532             }
    1533         }
    1534     }
    1535 
    1536     int vhwaSaveSurface(struct SSMHANDLE * pSSM, VBoxVHWASurfaceBase *pSurf, uint32_t surfCaps);
    1537     static int vhwaLoadSurface(VHWACommandList * pCmdList, struct SSMHANDLE * pSSM, uint32_t cBackBuffers, uint32_t u32Version);
    1538     int vhwaSaveOverlayData(struct SSMHANDLE * pSSM, VBoxVHWASurfaceBase *pSurf, bool bVisible);
    1539     static int vhwaLoadOverlayData(VHWACommandList * pCmdList, struct SSMHANDLE * pSSM, uint32_t u32Version);
    1540     static int vhwaLoadVHWAEnable(VHWACommandList * pCmdList);
    1541 
    1542     void vhwaDoSurfaceOverlayUpdate(VBoxVHWASurfaceBase *pDstSurf, VBoxVHWASurfaceBase *pSrcSurf,
    1543                                     struct VBOXVHWACMD_SURF_OVERLAY_UPDATE RT_UNTRUSTED_VOLATILE_GUEST *pCmd);
    1544 #endif
    1545 
    1546     VBoxVHWADisplay mDisplay;
    1547 
    1548     VBoxVHWASurfaceBase* handle2Surface(uint32_t h)
    1549     {
    1550         VBoxVHWASurfaceBase* pSurf = (VBoxVHWASurfaceBase*)mSurfHandleTable.get(h);
    1551         Assert(pSurf);
    1552         return pSurf;
    1553     }
    1554 
    1555     VBoxVHWAHandleTable mSurfHandleTable;
    1556 
    1557     bool mRepaintNeeded;
    1558 
    1559     QRect mViewport;
    1560 
    1561     VBoxVHWASurfList *mConstructingList;
    1562     int32_t mcRemaining2Contruct;
    1563 
    1564     class VBoxVHWAGlProgramMngr *mpMngr;
    1565 
    1566     VBoxVHWASettings *mSettings;
    1567 
    1568     void    *mpvVRAM;
    1569     uint32_t mcbVRAM;
    1570 
    1571 #ifdef VBOXVHWA_PROFILE_FPS
    1572     VBoxVHWADbgTimer mFPSCounter;
    1573     bool mbNewFrame;
    1574 #endif
    1575 };
    1576 
    1577 class VBoxGLWgt : public QGLWidget
    1578 {
    1579 public:
    1580     VBoxGLWgt(VBoxVHWAImage * pImage,
    1581             QWidget* parent, const QGLWidget* shareWidget);
    1582 
    1583 protected:
    1584     void paintGL()
    1585     {
    1586         mpImage->performDisplay(true);
    1587     }
    1588 private:
    1589     VBoxVHWAImage * mpImage;
    1590 };
    1591 
    1592 class VBoxVHWAFBO
    1593 {
    1594 public:
    1595     VBoxVHWAFBO() :
    1596             mFBO(0)
    1597     {}
    1598 
    1599     ~VBoxVHWAFBO()
    1600     {
    1601         if(mFBO)
    1602         {
    1603             vboxglDeleteFramebuffers(1, &mFBO);
    1604         }
    1605     }
    1606 
    1607     void init()
    1608     {
    1609         VBOXQGL_CHECKERR(
    1610                 vboxglGenFramebuffers(1, &mFBO);
    1611         );
    1612     }
    1613 
    1614     void bind()
    1615     {
    1616         VBOXQGL_CHECKERR(
    1617             vboxglBindFramebuffer(GL_FRAMEBUFFER, mFBO);
    1618         );
    1619     }
    1620 
    1621     void unbind()
    1622     {
    1623         VBOXQGL_CHECKERR(
    1624             vboxglBindFramebuffer(GL_FRAMEBUFFER, 0);
    1625         );
    1626     }
    1627 
    1628     void attachBound(VBoxVHWATexture *pTex)
    1629     {
    1630         VBOXQGL_CHECKERR(
    1631                 vboxglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, pTex->texTarget(), pTex->texture(), 0);
    1632         );
    1633     }
    1634 
    1635 private:
    1636     GLuint mFBO;
    1637 };
    1638 
    1639 template <class T>
    1640 class VBoxVHWATextureImageFBO : public T
    1641 {
    1642 public:
    1643     VBoxVHWATextureImageFBO(const QRect &size, const VBoxVHWAColorFormat &format, class VBoxVHWAGlProgramMngr * aMgr, VBOXVHWAIMG_TYPE flags) :
    1644             T(size, format, aMgr, flags & (~(VBOXVHWAIMG_FBO | VBOXVHWAIMG_LINEAR))),
    1645             mFBOTex(size, VBoxVHWAColorFormat(32, 0xff0000, 0xff00, 0xff), aMgr, (flags & (~VBOXVHWAIMG_FBO))),
    1646             mpvFBOTexMem(NULL)
    1647     {
    1648     }
    1649 
    1650     virtual ~VBoxVHWATextureImageFBO()
    1651     {
    1652         if(mpvFBOTexMem)
    1653             free(mpvFBOTexMem);
    1654     }
    1655 
    1656     virtual void init(uchar *pvMem)
    1657     {
    1658         mFBO.init();
    1659         mpvFBOTexMem = (uchar*)malloc(mFBOTex.memSize());
    1660         mFBOTex.init(mpvFBOTexMem);
    1661         T::init(pvMem);
    1662         mFBO.bind();
    1663         mFBO.attachBound(mFBOTex.component(0));
    1664         mFBO.unbind();
    1665     }
    1666 
    1667     virtual int createDisplay(VBoxVHWATextureImage *pDst, const QRect * pDstRect, const QRect * pSrcRect,
    1668             const VBoxVHWAColorKey * pDstCKey, const VBoxVHWAColorKey * pSrcCKey, bool bNotIntersected,
    1669             GLuint *pDisplay, class VBoxVHWAGlProgramVHWA ** ppProgram)
    1670     {
    1671         T::createDisplay(NULL, &mFBOTex.rect(), &rect(),
    1672                 NULL, NULL, false,
    1673                 pDisplay, ppProgram);
    1674 
    1675         return mFBOTex.initDisplay(pDst, pDstRect, pSrcRect,
    1676                 pDstCKey, pSrcCKey, bNotIntersected);
    1677     }
    1678 
    1679     virtual void update(const QRect * pRect)
    1680     {
    1681         T::update(pRect);
    1682 
    1683         VBoxVHWAImage::pushSettingsAndSetupViewport(rect().size(), rect());
    1684         mFBO.bind();
    1685         T::display();
    1686         mFBO.unbind();
    1687         VBoxVHWAImage::popSettingsAfterSetupViewport();
    1688     }
    1689 
    1690     virtual void display(VBoxVHWATextureImage *pDst, const QRect * pDstRect, const QRect * pSrcRect,
    1691             const VBoxVHWAColorKey * pDstCKey, const VBoxVHWAColorKey * pSrcCKey, bool bNotIntersected)
    1692     {
    1693         mFBOTex.display(pDst, pDstRect, pSrcRect, pDstCKey, pSrcCKey, bNotIntersected);
    1694     }
    1695 
    1696     virtual void display()
    1697     {
    1698         mFBOTex.display();
    1699     }
    1700 
    1701     const QRect &rect() { return T::rect(); }
    1702 private:
    1703     VBoxVHWAFBO mFBO;
    1704     VBoxVHWATextureImage mFBOTex;
    1705     uchar * mpvFBOTexMem;
    1706 };
    1707 
    1708 class VBoxQGLOverlay
    1709 {
    1710 public:
    1711     VBoxQGLOverlay();
    1712     void init(QWidget *pViewport, QObject *pPostEventObject, CSession * aSession, uint32_t id);
    1713     ~VBoxQGLOverlay()
    1714     {
    1715         if (mpShareWgt)
    1716             delete mpShareWgt;
    1717     }
    1718 
    1719     void updateAttachment(QWidget *pViewport, QObject *pPostEventObject);
    1720 
    1721     int onVHWACommand(struct VBOXVHWACMD RT_UNTRUSTED_VOLATILE_GUEST *pCommand,
    1722                       int /*VBOXVHWACMD_TYPE*/ enmCmdInt, bool fGuestCmd);
    1723 
    1724     void onVHWACommandEvent (QEvent * pEvent);
    1725 
    1726     /**
    1727      * to be called on NotifyUpdate framebuffer call
    1728      * @return true if the request was processed & should not be forwarded to the framebuffer
    1729      * false - otherwise */
    1730     bool onNotifyUpdate (ULONG aX, ULONG aY,
    1731                              ULONG aW, ULONG aH);
    1732 
    1733     void onNotifyUpdateIgnore (ULONG aX, ULONG aY,
    1734                              ULONG aW, ULONG aH)
    1735     {
    1736         Q_UNUSED(aX);
    1737         Q_UNUSED(aY);
    1738         Q_UNUSED(aW);
    1739         Q_UNUSED(aH);
    1740         /* @todo: we actually should not miss notify updates, since we need to update the texture on it */
    1741     }
    1742 
    1743     void onResizeEventPostprocess (const VBoxFBSizeInfo &re, const QPoint & topLeft);
    1744 
    1745     void onViewportResized (QResizeEvent * /*re*/)
    1746     {
    1747         vboxDoCheckUpdateViewport();
    1748         mGlCurrent = false;
    1749     }
    1750 
    1751     void onViewportScrolled (const QPoint & newTopLeft)
    1752     {
    1753         mContentsTopLeft = newTopLeft;
    1754         vboxDoCheckUpdateViewport();
    1755         mGlCurrent = false;
    1756     }
    1757 
    1758     static bool isAcceleration2DVideoAvailable();
    1759 
    1760     /** additional video memory required for the best 2D support performance
    1761      *  total amount of VRAM required is thus calculated as requiredVideoMemory + required2DOffscreenVideoMemory  */
    1762     static quint64 required2DOffscreenVideoMemory();
    1763 
    1764     /* not supposed to be called by clients */
    1765     int vhwaLoadExec (struct SSMHANDLE * pSSM, uint32_t u32Version);
    1766     void vhwaSaveExec (struct SSMHANDLE * pSSM);
    1767 private:
    1768     int vhwaSurfaceUnlock (struct VBOXVHWACMD_SURF_UNLOCK RT_UNTRUSTED_VOLATILE_GUEST *pCmd);
    1769 
    1770     void repaintMain();
    1771     void repaintOverlay()
    1772     {
    1773         if(mNeedOverlayRepaint)
    1774         {
    1775             mNeedOverlayRepaint = false;
    1776             performDisplayOverlay();
    1777         }
    1778         if(mNeedSetVisible)
    1779         {
    1780             mNeedSetVisible = false;
    1781             mpOverlayWgt->setVisible (true);
    1782         }
    1783     }
    1784     void repaint()
    1785     {
    1786         repaintOverlay();
    1787         repaintMain();
    1788     }
    1789 
    1790     void makeCurrent()
    1791     {
    1792         if (!mGlCurrent)
    1793         {
    1794             mGlCurrent = true;
    1795             mpOverlayWgt->makeCurrent();
    1796         }
    1797     }
    1798 
    1799     void performDisplayOverlay()
    1800     {
    1801         if (mOverlayVisible)
    1802         {
    1803             makeCurrent();
    1804             if (mOverlayImage.performDisplay(false))
    1805                 mpOverlayWgt->swapBuffers();
    1806         }
    1807     }
    1808 
    1809     void vboxSetGlOn (bool on);
    1810     bool vboxGetGlOn() { return mGlOn; }
    1811     bool vboxSynchGl();
    1812     void vboxDoVHWACmdExec(void RT_UNTRUSTED_VOLATILE_GUEST *pvCmd, int /*VBOXVHWACMD_TYPE*/ enmCmdInt, bool fGuestCmd);
    1813     void vboxShowOverlay (bool show);
    1814     void vboxDoCheckUpdateViewport();
    1815     void vboxDoVHWACmd(void RT_UNTRUSTED_VOLATILE_GUEST *pvCmd, int /*VBOXVHWACMD_TYPE*/ enmCmd, bool fGuestCmd);
    1816     void addMainDirtyRect (const QRect & aRect);
    1817     void vboxCheckUpdateOverlay (const QRect & rect);
    1818     void processCmd (VBoxVHWACommandElement * pCmd);
    1819 
    1820     int vhwaConstruct (struct VBOXVHWACMD_HH_CONSTRUCT *pCmd);
    1821 
    1822     int reset();
    1823 
    1824     int resetGl();
    1825 
    1826     void initGl();
    1827 
    1828     VBoxGLWgt *mpOverlayWgt;
    1829     VBoxVHWAImage mOverlayImage;
    1830     QWidget *mpViewport;
    1831     bool mGlOn;
    1832     bool mOverlayWidgetVisible;
    1833     bool mOverlayVisible;
    1834     bool mGlCurrent;
    1835     bool mProcessingCommands;
    1836     bool mNeedOverlayRepaint;
    1837     bool mNeedSetVisible;
    1838     QRect mOverlayViewport;
    1839     VBoxVHWADirtyRect mMainDirtyRect;
    1840 
    1841     VBoxVHWACommandElementProcessor mCmdPipe;
    1842 
    1843     /* this is used in saved state restore to postpone surface restoration
    1844      * till the framebuffer size is restored */
    1845     VHWACommandList mOnResizeCmdList;
    1846 
    1847     VBoxVHWASettings mSettings;
    1848     CSession * mpSession;
    1849 
    1850     VBoxFBSizeInfo mSizeInfo;
    1851     VBoxFBSizeInfo mPostponedResize;
    1852     QPoint mContentsTopLeft;
    1853 
    1854     QGLWidget *mpShareWgt;
    1855 
    1856     uint32_t m_id;
    1857 };
    1858 
    1859 #endif /* defined(VBOX_GUI_USE_QGL) || defined(VBOX_WITH_VIDEOHWACCEL) */
    1860 
    1861 #endif /* #ifndef __VBoxFBOverlay_h__ */
     38#endif /* !___VBox2DHelpers_h___ */
  • trunk/src/VBox/Frontends/VirtualBox/src/VBoxFBOverlay.cpp

    r71666 r72057  
    171171*********************************************************************************************************************************/
    172172static VBoxVHWAInfo g_VBoxVHWASupportInfo;
    173 static bool g_bVBoxVHWAChecked = false;
    174 static bool g_bVBoxVHWASupported = false;
    175173
    176174
     
    49624960}
    49634961
    4964 /* static */
    4965 bool VBoxQGLOverlay::isAcceleration2DVideoAvailable()
    4966 {
    4967 #ifndef DEBUG_misha
    4968     if (!g_bVBoxVHWAChecked)
    4969 #endif
    4970     {
    4971         g_bVBoxVHWAChecked = true;
    4972         g_bVBoxVHWASupported = VBoxVHWAInfo::checkVHWASupport();
    4973     }
    4974     return g_bVBoxVHWASupported;
    4975 }
    4976 
    4977 /** additional video memory required for the best 2D support performance
    4978  *  total amount of VRAM required is thus calculated as requiredVideoMemory + required2DOffscreenVideoMemory  */
    4979 /* static */
    4980 quint64 VBoxQGLOverlay::required2DOffscreenVideoMemory()
    4981 {
    4982     /* HDTV == 1920x1080 ~ 2M
    4983      * for the 4:2:2 formats each pixel is 2Bytes
    4984      * so each frame may be 4MiB
    4985      * so for triple-buffering we would need 12 MiB */
    4986     return _1M * 12;
    4987 }
    4988 
    49894962void VBoxQGLOverlay::processCmd(VBoxVHWACommandElement * pCmd)
    49904963{
  • trunk/src/VBox/Frontends/VirtualBox/src/VBoxFBOverlay.h

    r71651 r72057  
    17561756    }
    17571757
    1758     static bool isAcceleration2DVideoAvailable();
    1759 
    1760     /** additional video memory required for the best 2D support performance
    1761      *  total amount of VRAM required is thus calculated as requiredVideoMemory + required2DOffscreenVideoMemory  */
    1762     static quint64 required2DOffscreenVideoMemory();
    1763 
    17641758    /* not supposed to be called by clients */
    17651759    int vhwaLoadExec (struct SSMHANDLE * pSSM, uint32_t u32Version);
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineWindow.cpp

    r71375 r72057  
    4444# include "UIMouseHandler.h"
    4545# include "UIVMCloseDialog.h"
    46 # include "VBoxFBOverlay.h"
     46# include "VBox2DHelpers.h"
    4747
    4848/* COM includes: */
     
    504504#ifdef VBOX_WITH_VIDEOHWACCEL
    505505    /* Need to force the QGL framebuffer in case 2D Video Acceleration is supported & enabled: */
    506     bool bAccelerate2DVideo = machine().GetAccelerate2DVideoEnabled() && VBoxQGLOverlay::isAcceleration2DVideoAvailable();
     506    bool bAccelerate2DVideo = machine().GetAccelerate2DVideoEnabled() && VBox2DHelpers::isAcceleration2DVideoAvailable();
    507507#endif /* VBOX_WITH_VIDEOHWACCEL */
    508508
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UISession.cpp

    r71615 r72057  
    4747# include "UISettingsDialogSpecific.h"
    4848# ifdef VBOX_WITH_VIDEOHWACCEL
    49 #  include "VBoxFBOverlay.h"
     49#  include "VBox2DHelpers.h"
    5050# endif /* VBOX_WITH_VIDEOHWACCEL */
    5151# ifdef VBOX_WS_MAC
     
    248248    /* Log whether 2D video acceleration is enabled: */
    249249    LogRel(("GUI: 2D video acceleration is %s\n",
    250            machine().GetAccelerate2DVideoEnabled() && VBoxQGLOverlay::isAcceleration2DVideoAvailable()
     250           machine().GetAccelerate2DVideoEnabled() && VBox2DHelpers::isAcceleration2DVideoAvailable()
    251251           ? "enabled" : "disabled"));
    252252#endif /* VBOX_WITH_VIDEOHWACCEL */
  • trunk/src/VBox/Frontends/VirtualBox/src/settings/machine/UIMachineSettingsDisplay.cpp

    r71368 r72057  
    2828# include "UIErrorString.h"
    2929# include "VBoxGlobal.h"
    30 # include "VBoxFBOverlay.h"
     30# include "VBox2DHelpers.h"
    3131
    3232/* COM includes: */
     
    521521            else if (m_pCheckbox2DVideo->isChecked() && m_f2DVideoAccelerationSupported)
    522522            {
    523                 uNeedBytes += VBoxQGLOverlay::required2DOffscreenVideoMemory();
     523                uNeedBytes += VBox2DHelpers::required2DOffscreenVideoMemory();
    524524                if ((quint64)m_pEditorVideoMemorySize->value() * _1M < uNeedBytes)
    525525                {
     
    695695    m_pCheckbox3D->setEnabled(isMachineOffline());
    696696#ifdef VBOX_WITH_VIDEOHWACCEL
    697     m_pCheckbox2DVideo->setEnabled(isMachineOffline() && VBoxQGLOverlay::isAcceleration2DVideoAvailable());
     697    m_pCheckbox2DVideo->setEnabled(isMachineOffline() && VBox2DHelpers::isAcceleration2DVideoAvailable());
    698698#else /* !VBOX_WITH_VIDEOHWACCEL */
    699699    m_pCheckbox2DVideo->hide();
     
    12071207    if (m_pCheckbox2DVideo->isChecked() && m_f2DVideoAccelerationSupported)
    12081208    {
    1209         uNeedMBytes += VBoxQGLOverlay::required2DOffscreenVideoMemory() / _1M;
     1209        uNeedMBytes += VBox2DHelpers::required2DOffscreenVideoMemory() / _1M;
    12101210    }
    12111211#endif
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette