Changeset 72057 in vbox for trunk/src/VBox/Frontends/VirtualBox
- Timestamp:
- Apr 27, 2018 11:55:52 AM (7 years ago)
- Location:
- trunk/src/VBox/Frontends/VirtualBox
- Files:
-
- 6 edited
- 2 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk
r72043 r72057 1135 1135 if defined(VBOX_WITH_VIDEOHWACCEL) || defined(VBOX_GUI_USE_QGL) 1136 1136 VirtualBox_SOURCES += \ 1137 src/VBox2DHelpers.cpp \ 1137 1138 src/VBoxFBOverlay.cpp \ 1138 1139 src/VBoxGLSupportInfo.cpp -
trunk/src/VBox/Frontends/VirtualBox/src/VBox2DHelpers.cpp
r72038 r72057 1 1 /* $Id$ */ 2 2 /** @file 3 * VBox Qt GUI - VBoxFBOverlayimplementation.3 * VBox Qt GUI - 2D Video Acceleration helpers implementation. 4 4 */ 5 5 6 6 /* 7 * Copyright (C) 2009-201 7Oracle Corporation7 * Copyright (C) 2009-2018 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 16 16 */ 17 17 18 #if defined(VBOX_GUI_USE_QGL) /* entire file */19 18 19 #if defined(VBOX_GUI_USE_QGL) || defined(VBOX_WITH_VIDEOHWACCEL) 20 20 21 /*********************************************************************************************************************************22 * Header Files *23 *********************************************************************************************************************************/24 21 #ifdef VBOX_WITH_PRECOMPILED_HEADERS 25 22 # include <precomp.h> … … 28 25 # define LOG_GROUP LOG_GROUP_GUI 29 26 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 30 34 /* Qt includes: */ 31 # ifdef RT_OS_WINDOWS32 # 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 # endif35 # include <QApplication>36 35 # include <QGLWidget> 37 # include <QFile>38 # include <QTextStream>39 36 40 37 /* 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" 54 39 55 40 /* Other VBox includes: */ 56 # include <iprt/asm.h>57 # include <iprt/semaphore.h>58 # include <VBox/AssertGuest.h>59 60 41 # include <VBox/VBoxGL2D.h> 61 42 62 #ifdef VBOX_WS_MAC63 # include "VBoxUtils-darwin.h"64 #endif /* VBOX_WS_MAC */65 66 43 #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_VIDEOHWACCEL73 # 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_BASE85 # ifdef VBOXQGL_DBG_SURF86 # define VBOXQGL_PROF_WIDTH 140087 # define VBOXQGL_PROF_HEIGHT 105088 # else89 # define VBOXQGL_PROF_WIDTH 140090 # define VBOXQGL_PROF_HEIGHT 105091 //#define VBOXQGL_PROF_WIDTH 72092 //#define VBOXQGL_PROF_HEIGHT 48093 # endif94 #endif95 96 #define VBOXQGL_STATE_NAMEBASE "QGLVHWAData"97 #define VBOXQGL_STATE_VERSION_PIPESAVED 398 #define VBOXQGL_STATE_VERSION 399 100 //#define VBOXQGLOVERLAY_STATE_NAMEBASE "QGLOverlayVHWAData"101 //#define VBOXQGLOVERLAY_STATE_VERSION 1102 103 #ifdef DEBUG_misha104 //# define VBOXQGL_STATE_DEBUG105 #endif106 107 #ifdef VBOXQGL_STATE_DEBUG108 #define VBOXQGL_STATE_START_MAGIC 0x12345678109 #define VBOXQGL_STATE_STOP_MAGIC 0x87654321110 111 #define VBOXQGL_STATE_SURFSTART_MAGIC 0x9abcdef1112 #define VBOXQGL_STATE_SURFSTOP_MAGIC 0x1fedcba9113 114 #define VBOXQGL_STATE_OVERLAYSTART_MAGIC 0x13579bdf115 #define VBOXQGL_STATE_OVERLAYSTOP_MAGIC 0xfdb97531116 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 #else147 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 #endif167 44 168 45 … … 170 47 * Global Variables * 171 48 *********************************************************************************************************************************/ 172 static VBoxVHWAInfo g_VBoxVHWASupportInfo; 173 static bool g_ bVBoxVHWAChecked = false;174 static bool g_ bVBoxVHWASupported = false;49 50 static bool g_fVBoxVHWAChecked = false; 51 static bool g_fVBoxVHWASupported = false; 175 52 176 53 177 #ifdef DEBUG 54 /********************************************************************************************************************************* 55 * Namespace VBox2DHelpers implementation. * 56 *********************************************************************************************************************************/ 178 57 179 VBoxVHWADbgTimer::VBoxVHWADbgTimer(uint32_t cPeriods) 180 : mPeriodSum(0) 181 , mPrevTime(0) 182 , mcFrames(0) 183 , mcPeriods(cPeriods) 184 , miPeriod(0) 58 bool VBox2DHelpers::isAcceleration2DVideoAvailable() 185 59 { 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; 188 66 } 189 67 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() 68 quint64 VBox2DHelpers::required2DOffscreenVideoMemory() 4981 69 { 4982 70 /* HDTV == 1920x1080 ~ 2M … … 4987 75 } 4988 76 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 1 1 /* $Id$ */ 2 2 /** @file 3 * VBox Qt GUI - VBoxFrameBuffer Overly classes declarations.3 * VBox Qt GUI - 2D Video Acceleration helpers declarations. 4 4 */ 5 5 6 6 /* 7 * Copyright (C) 2006-201 7Oracle Corporation7 * Copyright (C) 2006-2018 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 15 15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. 16 16 */ 17 #ifndef __VBoxFBOverlay_h__ 18 #define __VBoxFBOverlay_h__ 17 18 #ifndef ___VBox2DHelpers_h___ 19 #define ___VBox2DHelpers_h___ 19 20 20 21 #if defined(VBOX_GUI_USE_QGL) || defined(VBOX_WITH_VIDEOHWACCEL) 21 22 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> 27 25 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 */ 27 namespace VBox2DHelpers 28 { 29 /** Returns whether 2D Video Acceleration is available. */ 30 bool isAcceleration2DVideoAvailable(); 34 31 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(); 85 34 }; 86 35 87 #endif /* DEBUG*/36 #endif /* VBOX_GUI_USE_QGL || VBOX_WITH_VIDEOHWACCEL */ 88 37 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 171 171 *********************************************************************************************************************************/ 172 172 static VBoxVHWAInfo g_VBoxVHWASupportInfo; 173 static bool g_bVBoxVHWAChecked = false;174 static bool g_bVBoxVHWASupported = false;175 173 176 174 … … 4962 4960 } 4963 4961 4964 /* static */4965 bool VBoxQGLOverlay::isAcceleration2DVideoAvailable()4966 {4967 #ifndef DEBUG_misha4968 if (!g_bVBoxVHWAChecked)4969 #endif4970 {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 performance4978 * total amount of VRAM required is thus calculated as requiredVideoMemory + required2DOffscreenVideoMemory */4979 /* static */4980 quint64 VBoxQGLOverlay::required2DOffscreenVideoMemory()4981 {4982 /* HDTV == 1920x1080 ~ 2M4983 * for the 4:2:2 formats each pixel is 2Bytes4984 * so each frame may be 4MiB4985 * so for triple-buffering we would need 12 MiB */4986 return _1M * 12;4987 }4988 4989 4962 void VBoxQGLOverlay::processCmd(VBoxVHWACommandElement * pCmd) 4990 4963 { -
trunk/src/VBox/Frontends/VirtualBox/src/VBoxFBOverlay.h
r71651 r72057 1756 1756 } 1757 1757 1758 static bool isAcceleration2DVideoAvailable();1759 1760 /** additional video memory required for the best 2D support performance1761 * total amount of VRAM required is thus calculated as requiredVideoMemory + required2DOffscreenVideoMemory */1762 static quint64 required2DOffscreenVideoMemory();1763 1764 1758 /* not supposed to be called by clients */ 1765 1759 int vhwaLoadExec (struct SSMHANDLE * pSSM, uint32_t u32Version); -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineWindow.cpp
r71375 r72057 44 44 # include "UIMouseHandler.h" 45 45 # include "UIVMCloseDialog.h" 46 # include "VBox FBOverlay.h"46 # include "VBox2DHelpers.h" 47 47 48 48 /* COM includes: */ … … 504 504 #ifdef VBOX_WITH_VIDEOHWACCEL 505 505 /* Need to force the QGL framebuffer in case 2D Video Acceleration is supported & enabled: */ 506 bool bAccelerate2DVideo = machine().GetAccelerate2DVideoEnabled() && VBox QGLOverlay::isAcceleration2DVideoAvailable();506 bool bAccelerate2DVideo = machine().GetAccelerate2DVideoEnabled() && VBox2DHelpers::isAcceleration2DVideoAvailable(); 507 507 #endif /* VBOX_WITH_VIDEOHWACCEL */ 508 508 -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UISession.cpp
r71615 r72057 47 47 # include "UISettingsDialogSpecific.h" 48 48 # ifdef VBOX_WITH_VIDEOHWACCEL 49 # include "VBox FBOverlay.h"49 # include "VBox2DHelpers.h" 50 50 # endif /* VBOX_WITH_VIDEOHWACCEL */ 51 51 # ifdef VBOX_WS_MAC … … 248 248 /* Log whether 2D video acceleration is enabled: */ 249 249 LogRel(("GUI: 2D video acceleration is %s\n", 250 machine().GetAccelerate2DVideoEnabled() && VBox QGLOverlay::isAcceleration2DVideoAvailable()250 machine().GetAccelerate2DVideoEnabled() && VBox2DHelpers::isAcceleration2DVideoAvailable() 251 251 ? "enabled" : "disabled")); 252 252 #endif /* VBOX_WITH_VIDEOHWACCEL */ -
trunk/src/VBox/Frontends/VirtualBox/src/settings/machine/UIMachineSettingsDisplay.cpp
r71368 r72057 28 28 # include "UIErrorString.h" 29 29 # include "VBoxGlobal.h" 30 # include "VBox FBOverlay.h"30 # include "VBox2DHelpers.h" 31 31 32 32 /* COM includes: */ … … 521 521 else if (m_pCheckbox2DVideo->isChecked() && m_f2DVideoAccelerationSupported) 522 522 { 523 uNeedBytes += VBox QGLOverlay::required2DOffscreenVideoMemory();523 uNeedBytes += VBox2DHelpers::required2DOffscreenVideoMemory(); 524 524 if ((quint64)m_pEditorVideoMemorySize->value() * _1M < uNeedBytes) 525 525 { … … 695 695 m_pCheckbox3D->setEnabled(isMachineOffline()); 696 696 #ifdef VBOX_WITH_VIDEOHWACCEL 697 m_pCheckbox2DVideo->setEnabled(isMachineOffline() && VBox QGLOverlay::isAcceleration2DVideoAvailable());697 m_pCheckbox2DVideo->setEnabled(isMachineOffline() && VBox2DHelpers::isAcceleration2DVideoAvailable()); 698 698 #else /* !VBOX_WITH_VIDEOHWACCEL */ 699 699 m_pCheckbox2DVideo->hide(); … … 1207 1207 if (m_pCheckbox2DVideo->isChecked() && m_f2DVideoAccelerationSupported) 1208 1208 { 1209 uNeedMBytes += VBox QGLOverlay::required2DOffscreenVideoMemory() / _1M;1209 uNeedMBytes += VBox2DHelpers::required2DOffscreenVideoMemory() / _1M; 1210 1210 } 1211 1211 #endif
Note:
See TracChangeset
for help on using the changeset viewer.