VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/VBoxFBOverlay.cpp@ 82781

Last change on this file since 82781 was 82677, checked in by vboxsync, 4 years ago

VBoxFBOverlay: VHWA cleanup, adressed a todo

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

© 2023 Oracle
ContactPrivacy policyTerms of Use