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
Line 
1/* $Id: VBoxFBOverlay.cpp 82677 2020-01-08 17:08:09Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - VBoxFBOverlay implementation.
4 */
5
6/*
7 * Copyright (C) 2009-2019 Oracle Corporation
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
18#if defined(VBOX_GUI_USE_QGL) /* entire file */
19
20
21/*********************************************************************************************************************************
22* Header Files *
23*********************************************************************************************************************************/
24#define LOG_GROUP LOG_GROUP_GUI
25
26/* Qt includes: */
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>
35
36/* GUI includes: */
37#include "VBoxFBOverlay.h"
38#include "UIDesktopWidgetWatchdog.h"
39#include "UIExtraDataManager.h"
40#include "UIMessageCenter.h"
41#include "UIModalWindowManager.h"
42#include "UIPopupCenter.h"
43#include "UICommon.h"
44
45/* COM includes: */
46#include "CSession.h"
47#include "CConsole.h"
48#include "CMachine.h"
49#include "CDisplay.h"
50
51/* Other VBox includes: */
52#include <iprt/asm.h>
53#include <iprt/semaphore.h>
54#include <VBox/AssertGuest.h>
55
56#include <VBox/VBoxGL2D.h>
57
58#ifdef VBOX_WS_MAC
59#include "VBoxUtils-darwin.h"
60#endif
61
62/* Other VBox includes: */
63#include <iprt/memcache.h>
64#include <VBox/err.h>
65
66#ifdef VBOX_WITH_VIDEOHWACCEL
67# include <VBoxVideo.h>
68# include <VBox/vmm/ssm.h>
69#endif
70
71/* Other includes: */
72#include <math.h>
73
74
75/*********************************************************************************************************************************
76* Defined Constants And Macros *
77*********************************************************************************************************************************/
78/* 128 should be enough */
79#define VBOXVHWA_MAX_SURFACES 128
80#define VBOXVHWA_MAX_WIDTH 4096
81#define VBOXVHWA_MAX_HEIGHT 4096
82
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"
96#define VBOXQGL_STATE_VERSION_PIPESAVED 3
97#define VBOXQGL_STATE_VERSION 3
98
99//#define VBOXQGLOVERLAY_STATE_NAMEBASE "QGLOverlayVHWAData"
100//#define VBOXQGLOVERLAY_STATE_VERSION 1
101
102#ifdef DEBUG_misha
103//# define VBOXQGL_STATE_DEBUG
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; \
128 int rcCheck = SSMR3GetU32(_pSSM, &_u32); AssertRC(rcCheck); \
129 if (_u32 != (_v)) \
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
167
168/*********************************************************************************************************************************
169* Global Variables *
170*********************************************************************************************************************************/
171static VBoxVHWAInfo g_VBoxVHWASupportInfo;
172
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
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
245static struct VBOXVHWACMD * vhwaHHCmdCreate(VBOXVHWACMD_TYPE type, size_t size)
246{
247 char *buf = (char *)malloc(VBOXVHWACMD_SIZE_FROMBODYSIZE(size));
248 memset(buf, 0, size);
249 VBOXVHWACMD *pCmd = (VBOXVHWACMD *)buf;
250 pCmd->enmCmd = type;
251 pCmd->Flags = VBOXVHWACMD_FLAG_HH_CMD;
252 return pCmd;
253}
254
255static const VBoxVHWAInfo & vboxVHWAGetSupportInfo(const QGLContext *pContext)
256{
257 if (!g_VBoxVHWASupportInfo.isInitialized())
258 {
259 if (pContext)
260 {
261 g_VBoxVHWASupportInfo.init(pContext);
262 }
263 else
264 {
265 VBoxGLTmpContext ctx;
266 const QGLContext *pContext = ctx.makeCurrent();
267 Assert(pContext);
268 if (pContext)
269 {
270 g_VBoxVHWASupportInfo.init(pContext);
271 }
272 }
273 }
274 return g_VBoxVHWASupportInfo;
275}
276
277class VBoxVHWACommandProcessEvent : public QEvent
278{
279public:
280 VBoxVHWACommandProcessEvent ()
281 : QEvent ((QEvent::Type) VHWACommandProcessType),
282 fProcessed(false)
283 {
284#ifdef DEBUG_misha
285 g_EventCounter.inc();
286#endif
287 }
288
289 void setProcessed()
290 {
291 fProcessed = true;
292 }
293
294 ~VBoxVHWACommandProcessEvent()
295 {
296 if (!fProcessed)
297 {
298 AssertMsgFailed(("VHWA command beinf destroyed unproceessed!"));
299 LogRel(("GUI: VHWA command being destroyed unproceessed!"));
300 }
301#ifdef DEBUG_misha
302 g_EventCounter.dec();
303#endif
304 }
305#ifdef DEBUG_misha
306 static uint32_t cPending() { return g_EventCounter.refs(); }
307#endif
308
309private:
310 bool fProcessed;
311#ifdef DEBUG_misha
312 static VBoxVHWARefCounter g_EventCounter;
313#endif
314};
315
316#ifdef DEBUG_misha
317VBoxVHWARefCounter VBoxVHWACommandProcessEvent::g_EventCounter;
318#endif
319
320VBoxVHWAHandleTable::VBoxVHWAHandleTable(uint32_t maxSize)
321 :
322 mcSize(maxSize),
323 mcUsage(0),
324 mCursor(1) /* 0 is treated as invalid */
325{
326 mTable = (void **)RTMemAllocZ(sizeof(void *) * maxSize);
327}
328
329VBoxVHWAHandleTable::~VBoxVHWAHandleTable()
330{
331 RTMemFree(mTable);
332}
333
334uint32_t VBoxVHWAHandleTable::put(void *data)
335{
336 AssertPtrReturn(data, VBOXVHWA_SURFHANDLE_INVALID);
337 AssertReturn(mcUsage < mcSize, VBOXVHWA_SURFHANDLE_INVALID);
338
339 for (int k = 0; k < 2; ++k)
340 {
341 Assert(mCursor != 0);
342 for (uint32_t i = mCursor; i < mcSize; ++i)
343 {
344 if (!mTable[i])
345 {
346 doPut(i, data);
347 mCursor = i+1;
348 return i;
349 }
350 }
351 mCursor = 1; /* 0 is treated as invalid */
352 }
353
354 AssertFailed();
355 return VBOXVHWA_SURFHANDLE_INVALID;
356}
357
358bool VBoxVHWAHandleTable::mapPut(uint32_t h, void *data)
359{
360 AssertReturn(h > 0 && h < mcSize, false);
361 RT_UNTRUSTED_VALIDATED_FENCE();
362 if (mTable[h])
363 return false;
364 doPut(h, data);
365 return true;
366}
367
368void * VBoxVHWAHandleTable::get(uint32_t h)
369{
370 AssertReturn(h > 0 && h < mcSize, NULL);
371 RT_UNTRUSTED_VALIDATED_FENCE();
372 return mTable[h];
373}
374
375void * VBoxVHWAHandleTable::remove(uint32_t h)
376{
377 Assert(mcUsage);
378 AssertReturn(h > 0 && h < mcSize, NULL);
379 RT_UNTRUSTED_VALIDATED_FENCE();
380 void *val = mTable[h];
381 Assert(val);
382 if (val)
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
401static VBoxVHWATextureImage *vboxVHWAImageCreate(const QRect & aRect, const VBoxVHWAColorFormat & aFormat,
402 class VBoxVHWAGlProgramMngr * pMgr, VBOXVHWAIMG_TYPE flags)
403{
404 bool bCanLinearNonFBO = false;
405 if (!aFormat.fourcc())
406 {
407 flags &= ~VBOXVHWAIMG_FBO;
408 bCanLinearNonFBO = true;
409 }
410
411 const VBoxVHWAInfo & info = vboxVHWAGetSupportInfo(NULL);
412 if ((flags & VBOXVHWAIMG_PBO) && !info.getGlInfo().isPBOSupported())
413 flags &= ~VBOXVHWAIMG_PBO;
414
415 if ((flags & VBOXVHWAIMG_PBOIMG) &&
416 (!info.getGlInfo().isPBOSupported() || !info.getGlInfo().isPBOOffsetSupported()))
417 flags &= ~VBOXVHWAIMG_PBOIMG;
418
419 if ((flags & VBOXVHWAIMG_FBO) && !info.getGlInfo().isFBOSupported())
420 flags &= ~VBOXVHWAIMG_FBO;
421
422 /* ensure we don't create a PBO-based texture in case we use a PBO-based image */
423 if (flags & VBOXVHWAIMG_PBOIMG)
424 flags &= ~VBOXVHWAIMG_PBO;
425
426 if (flags & VBOXVHWAIMG_FBO)
427 {
428 if (flags & VBOXVHWAIMG_PBOIMG)
429 {
430 VBOXQGLLOG(("FBO PBO Image\n"));
431 return new VBoxVHWATextureImageFBO<VBoxVHWATextureImagePBO>(aRect, aFormat, pMgr, flags);
432 }
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
443 if (flags & VBOXVHWAIMG_PBOIMG)
444 {
445 VBOXQGLLOG(("PBO Image\n"));
446 return new VBoxVHWATextureImagePBO(aRect, aFormat, pMgr, flags);
447 }
448
449 VBOXQGLLOG(("Generic Image\n"));
450 return new VBoxVHWATextureImage(aRect, aFormat, pMgr, flags);
451}
452
453static VBoxVHWATexture* vboxVHWATextureCreate(const QGLContext * pContext, const QRect & aRect,
454 const VBoxVHWAColorFormat & aFormat, uint32_t bytesPerLine, VBOXVHWAIMG_TYPE flags)
455{
456 const VBoxVHWAInfo & info = vboxVHWAGetSupportInfo(pContext);
457 GLint scaleFunc = (flags & VBOXVHWAIMG_LINEAR) ? GL_LINEAR : GL_NEAREST;
458 if ((flags & VBOXVHWAIMG_PBO) && info.getGlInfo().isPBOSupported())
459 {
460 VBOXQGLLOG(("VBoxVHWATextureNP2RectPBO\n"));
461 return new VBoxVHWATextureNP2RectPBO(aRect, aFormat, bytesPerLine, scaleFunc);
462 }
463 else if (info.getGlInfo().isTextureRectangleSupported())
464 {
465 VBOXQGLLOG(("VBoxVHWATextureNP2Rect\n"));
466 return new VBoxVHWATextureNP2Rect(aRect, aFormat, bytesPerLine, scaleFunc);
467 }
468 else if (info.getGlInfo().isTextureNP2Supported())
469 {
470 VBOXQGLLOG(("VBoxVHWATextureNP2\n"));
471 return new VBoxVHWATextureNP2(aRect, aFormat, bytesPerLine, scaleFunc);
472 }
473 VBOXQGLLOG(("VBoxVHWATexture\n"));
474 return new VBoxVHWATexture(aRect, aFormat, bytesPerLine, scaleFunc);
475}
476
477class VBoxVHWAGlShaderComponent
478{
479public:
480 VBoxVHWAGlShaderComponent(const char *aRcName, GLenum aType)
481 : mRcName(aRcName)
482 , mType(aType)
483 , mInitialized(false)
484 { NOREF(mType); }
485
486
487 int init();
488
489 const char * contents() { return mSource.constData(); }
490 bool isInitialized() { return mInitialized; }
491private:
492 const char *mRcName;
493 GLenum mType;
494 QByteArray mSource;
495 bool mInitialized;
496};
497
498int VBoxVHWAGlShaderComponent::init()
499{
500 if (isInitialized())
501 return VINF_ALREADY_INITIALIZED;
502
503 QFile fi(mRcName);
504 if (!fi.open(QIODevice::ReadOnly))
505 {
506 AssertFailed();
507 return VERR_GENERAL_FAILURE;
508 }
509
510 QTextStream is(&fi);
511 QString program = is.readAll();
512
513 mSource = program.toUtf8();
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;
531 if (mcComponents)
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;
543 if (mcComponents)
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{
571 int rc = VERR_GENERAL_FAILURE;
572 GLint *length;
573 const char **sources;
574 length = new GLint[mcComponents];
575 sources = new const char*[mcComponents];
576 for (int i = 0; i < mcComponents; i++)
577 {
578 length[i] = -1;
579 rc = maComponents[i]->init();
580 AssertRC(rc);
581 if (RT_FAILURE(rc))
582 break;
583 sources[i] = maComponents[i]->contents();
584 }
585
586 if (RT_SUCCESS(rc))
587 {
588#ifdef DEBUG
589 VBOXQGLLOG(("\ncompiling shaders:\n------------\n"));
590 for (int i = 0; i < mcComponents; i++)
591 VBOXQGLLOG(("**********\n%s\n***********\n", sources[i]));
592 VBOXQGLLOG(("------------\n"));
593#endif
594 mShader = vboxglCreateShader(mType);
595
596 VBOXQGL_CHECKERR(
597 vboxglShaderSource(mShader, mcComponents, sources, length);
598 );
599
600 VBOXQGL_CHECKERR(
601 vboxglCompileShader(mShader);
602 );
603
604 GLint compiled;
605 VBOXQGL_CHECKERR(
606 vboxglGetShaderiv(mShader, GL_COMPILE_STATUS, &compiled);
607 );
608
609#ifdef DEBUG
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;
614#endif
615
616 Assert(compiled);
617 if (compiled)
618 {
619 rc = VINF_SUCCESS;
620 }
621 else
622 {
623 VBOXQGL_CHECKERR(
624 vboxglDeleteShader(mShader);
625 );
626 mShader = 0;
627 }
628 }
629
630 delete[] length;
631 delete[] sources;
632 return rc;
633}
634
635class VBoxVHWAGlProgram
636{
637public:
638 VBoxVHWAGlProgram(VBoxVHWAGlShader ** apShaders, int acShaders);
639
640 virtual ~VBoxVHWAGlProgram();
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;
650 VBoxVHWAGlShader *mShaders;
651 int mcShaders;
652};
653
654VBoxVHWAGlProgram::VBoxVHWAGlProgram(VBoxVHWAGlShader ** apShaders, int acShaders) :
655 mProgram(0),
656 mcShaders(0)
657{
658 Assert(acShaders);
659 if (acShaders)
660 {
661 mShaders = new VBoxVHWAGlShader[acShaders];
662 for (int i = 0; i < acShaders; i++)
663 {
664 mShaders[i] = *apShaders[i];
665 }
666 mcShaders = acShaders;
667 }
668}
669
670VBoxVHWAGlProgram::~VBoxVHWAGlProgram()
671{
672 uninit();
673
674 if (mShaders)
675 {
676 delete[] mShaders;
677 }
678}
679
680int VBoxVHWAGlProgram::init()
681{
682 Assert(!isInitialized());
683 if (isInitialized())
684 return VINF_ALREADY_INITIALIZED;
685
686 Assert(mcShaders);
687 if (!mcShaders)
688 return VERR_GENERAL_FAILURE;
689
690 int rc = VINF_SUCCESS;
691 for (int i = 0; i < mcShaders; i++)
692 {
693 int rc = mShaders[i].init();
694 AssertRC(rc);
695 if (RT_FAILURE(rc))
696 {
697 break;
698 }
699 }
700 if (RT_FAILURE(rc))
701 {
702 return rc;
703 }
704
705 mProgram = vboxglCreateProgram();
706 Assert(mProgram);
707 if (mProgram)
708 {
709 for (int i = 0; i < mcShaders; i++)
710 {
711 VBOXQGL_CHECKERR(
712 vboxglAttachShader(mProgram, mShaders[i].shader());
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);
729 delete[] pBuf;
730#endif
731
732 if (linked)
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{
747 if (!isInitialized())
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
772#define VBOXVHWA_PROGRAM_DSTCOLORKEY 0x00000001
773#define VBOXVHWA_PROGRAM_SRCCOLORKEY 0x00000002
774#define VBOXVHWA_PROGRAM_COLORCONV 0x00000004
775#define VBOXVHWA_PROGRAM_COLORKEYNODISCARD 0x00000008
776
777#define VBOXVHWA_SUPPORTED_PROGRAM ( \
778 VBOXVHWA_PROGRAM_DSTCOLORKEY \
779 | VBOXVHWA_PROGRAM_SRCCOLORKEY \
780 | VBOXVHWA_PROGRAM_COLORCONV \
781 | VBOXVHWA_PROGRAM_COLORKEYNODISCARD \
782 )
783
784class VBoxVHWAGlProgramVHWA : public VBoxVHWAGlProgram
785{
786public:
787 VBoxVHWAGlProgramVHWA(uint32_t type, uint32_t fourcc, VBoxVHWAGlShader ** apShaders, int acShaders);
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
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)
870{}
871
872int VBoxVHWAGlProgramVHWA::init()
873{
874 int rc = VBoxVHWAGlProgram::init();
875 if (RT_FAILURE(rc))
876 return rc;
877 if (rc == VINF_ALREADY_INITIALIZED)
878 return rc;
879
880 start();
881
882 rc = VERR_GENERAL_FAILURE;
883
884 do
885 {
886 GLint tex = 0;
887 mUniSrcTex = vboxglGetUniformLocation(program(), "uSrcTex");
888 Assert(mUniSrcTex != -1);
889 if (mUniSrcTex == -1)
890 break;
891
892 VBOXQGL_CHECKERR(
893 vboxglUniform1i(mUniSrcTex, tex);
894 );
895 mSrcTex = tex;
896 ++tex;
897
898 if (type() & VBOXVHWA_PROGRAM_SRCCOLORKEY)
899 {
900 mUniSrcLowerColor = vboxglGetUniformLocation(program(), "uSrcClr");
901 Assert(mUniSrcLowerColor != -1);
902 if (mUniSrcLowerColor == -1)
903 break;
904
905 mSrcLowerR = 0.0; mSrcLowerG = 0.0; mSrcLowerB = 0.0;
906
907 VBOXQGL_CHECKERR(
908 vboxglUniform4f(mUniSrcLowerColor, 0.0, 0.0, 0.0, 0.0);
909 );
910 }
911
912 if (type() & VBOXVHWA_PROGRAM_COLORCONV)
913 {
914 switch(fourcc())
915 {
916 case FOURCC_YV12:
917 {
918 mUniVTex = vboxglGetUniformLocation(program(), "uVTex");
919 Assert(mUniVTex != -1);
920 if (mUniVTex == -1)
921 break;
922
923 VBOXQGL_CHECKERR(
924 vboxglUniform1i(mUniVTex, tex);
925 );
926 mVTex = tex;
927 ++tex;
928
929 mUniUTex = vboxglGetUniformLocation(program(), "uUTex");
930 Assert(mUniUTex != -1);
931 if (mUniUTex == -1)
932 break;
933 VBOXQGL_CHECKERR(
934 vboxglUniform1i(mUniUTex, tex);
935 );
936 mUTex = tex;
937 ++tex;
938
939 break;
940 }
941 case FOURCC_UYVY:
942 case FOURCC_YUY2:
943 case FOURCC_AYUV:
944 break;
945 default:
946 AssertFailed();
947 break;
948 }
949 }
950
951 if (type() & VBOXVHWA_PROGRAM_DSTCOLORKEY)
952 {
953
954 mUniDstTex = vboxglGetUniformLocation(program(), "uDstTex");
955 Assert(mUniDstTex != -1);
956 if (mUniDstTex == -1)
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);
966 if (mUniDstLowerColor == -1)
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
976 rc = VINF_SUCCESS;
977 } while(0);
978
979
980 stop();
981 if (rc == VINF_SUCCESS)
982 return VINF_SUCCESS;
983
984 AssertFailed();
985 VBoxVHWAGlProgram::uninit();
986 return VERR_GENERAL_FAILURE;
987}
988
989int VBoxVHWAGlProgramVHWA::setDstCKeyUpperRange(GLfloat r, GLfloat g, GLfloat b)
990{
991 Assert(isInitialized());
992 if (!isInitialized())
993 return VERR_GENERAL_FAILURE;
994 if (mDstUpperR == r && mDstUpperG == g && mDstUpperB == b)
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());
1006 if (!isInitialized())
1007 return VERR_GENERAL_FAILURE;
1008 if (mDstLowerR == r && mDstLowerG == g && mDstLowerB == b)
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());
1024 if (!isInitialized())
1025 return VERR_GENERAL_FAILURE;
1026 if (mSrcUpperR == r && mSrcUpperG == g && mSrcUpperB == b)
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());
1038 if (!isInitialized())
1039 return VERR_GENERAL_FAILURE;
1040 if (mSrcLowerR == r && mSrcLowerG == g && mSrcLowerB == b)
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:
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)
1068 {}
1069
1070 VBoxVHWAGlProgramVHWA *getProgram(uint32_t type, const VBoxVHWAColorFormat * pFrom, const VBoxVHWAColorFormat * pTo);
1071
1072 void stopCurrentProgram()
1073 {
1074 VBOXQGL_CHECKERR(
1075 vboxglUseProgram(0);
1076 );
1077 }
1078private:
1079 VBoxVHWAGlProgramVHWA *searchProgram(uint32_t type, uint32_t fourcc, bool bCreate);
1080 VBoxVHWAGlProgramVHWA *createProgram(uint32_t type, uint32_t fourcc);
1081
1082 typedef std::list <VBoxVHWAGlProgramVHWA*> ProgramList;
1083
1084 ProgramList mPrograms;
1085
1086 VBoxVHWAGlShaderComponent mShaderCConvApplyAYUV;
1087
1088 VBoxVHWAGlShaderComponent mShaderCConvAYUV;
1089 VBoxVHWAGlShaderComponent mShaderCConvBGR;
1090 VBoxVHWAGlShaderComponent mShaderCConvUYVY;
1091 VBoxVHWAGlShaderComponent mShaderCConvYUY2;
1092 VBoxVHWAGlShaderComponent mShaderCConvYV12;
1093 VBoxVHWAGlShaderComponent mShaderSplitBGRA;
1094
1095 /* expected the dst surface texture to be bound to the 1-st tex unit */
1096 VBoxVHWAGlShaderComponent mShaderCKeyDst;
1097 /* expected the dst surface texture to be bound to the 2-nd tex unit */
1098 VBoxVHWAGlShaderComponent mShaderCKeyDst2;
1099 VBoxVHWAGlShaderComponent mShaderMainOverlay;
1100 VBoxVHWAGlShaderComponent mShaderMainOverlayNoCKey;
1101 VBoxVHWAGlShaderComponent mShaderMainOverlayNoDiscard;
1102 VBoxVHWAGlShaderComponent mShaderMainOverlayNoDiscard2;
1103
1104 friend class VBoxVHWAGlProgramVHWA;
1105};
1106
1107VBoxVHWAGlProgramVHWA *VBoxVHWAGlProgramMngr::createProgram(uint32_t type, uint32_t fourcc)
1108{
1109 VBoxVHWAGlShaderComponent *apShaders[16];
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
1117 if (!!(type & VBOXVHWA_PROGRAM_DSTCOLORKEY)
1118 && !(type & VBOXVHWA_PROGRAM_COLORKEYNODISCARD))
1119 {
1120 if (fourcc == FOURCC_YV12)
1121 {
1122 apShaders[cShaders++] = &mShaderCKeyDst2;
1123 }
1124 else
1125 {
1126 apShaders[cShaders++] = &mShaderCKeyDst;
1127 }
1128 }
1129
1130 if (type & VBOXVHWA_PROGRAM_SRCCOLORKEY)
1131 {
1132 AssertFailed();
1133 /* disabled for now, not really necessary for video overlaying */
1134 }
1135
1136 bool bFound = false;
1137
1138// if (type & VBOXVHWA_PROGRAM_COLORCONV)
1139 {
1140 if (fourcc == FOURCC_UYVY)
1141 {
1142 apShaders[cShaders++] = &mShaderCConvUYVY;
1143 bFound = true;
1144 }
1145 else if (fourcc == FOURCC_YUY2)
1146 {
1147 apShaders[cShaders++] = &mShaderCConvYUY2;
1148 bFound = true;
1149 }
1150 else if (fourcc == FOURCC_YV12)
1151 {
1152 apShaders[cShaders++] = &mShaderCConvYV12;
1153 bFound = true;
1154 }
1155 else if (fourcc == FOURCC_AYUV)
1156 {
1157 apShaders[cShaders++] = &mShaderCConvAYUV;
1158 bFound = true;
1159 }
1160 }
1161
1162 if (bFound)
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
1173 if (type & VBOXVHWA_PROGRAM_DSTCOLORKEY)
1174 {
1175 if (type & VBOXVHWA_PROGRAM_COLORKEYNODISCARD)
1176 {
1177 if (fourcc == FOURCC_YV12)
1178 apShaders[cShaders++] = &mShaderMainOverlayNoDiscard2;
1179 else
1180 apShaders[cShaders++] = &mShaderMainOverlayNoDiscard;
1181 }
1182 else
1183 apShaders[cShaders++] = &mShaderMainOverlay;
1184 }
1185 else
1186 {
1187 // ensure we don't have empty functions /* paranoia for for ATI on linux */
1188 apShaders[cShaders++] = &mShaderMainOverlayNoCKey;
1189 }
1190
1191 Assert(cShaders <= RT_ELEMENTS(apShaders));
1192
1193 VBoxVHWAGlShader shader(GL_FRAGMENT_SHADER, apShaders, cShaders);
1194 VBoxVHWAGlShader *pShader = &shader;
1195
1196 VBoxVHWAGlProgramVHWA *pProgram = new VBoxVHWAGlProgramVHWA(/*this, */type, fourcc, &pShader, 1);
1197 pProgram->init();
1198
1199 return pProgram;
1200}
1201
1202VBoxVHWAGlProgramVHWA * VBoxVHWAGlProgramMngr::getProgram(uint32_t type, const VBoxVHWAColorFormat * pFrom, const VBoxVHWAColorFormat * pTo)
1203{
1204 Q_UNUSED(pTo);
1205 uint32_t fourcc = 0;
1206 type &= VBOXVHWA_SUPPORTED_PROGRAM;
1207
1208 if (pFrom && pFrom->fourcc())
1209 {
1210 fourcc = pFrom->fourcc();
1211 type |= VBOXVHWA_PROGRAM_COLORCONV;
1212 }
1213 else
1214 type &= ~VBOXVHWA_PROGRAM_COLORCONV;
1215
1216 if ( !(type & VBOXVHWA_PROGRAM_DSTCOLORKEY)
1217 && !(type & VBOXVHWA_PROGRAM_SRCCOLORKEY))
1218 type &= ~VBOXVHWA_PROGRAM_COLORKEYNODISCARD;
1219
1220 if (type)
1221 return searchProgram(type, fourcc, true);
1222 return NULL;
1223}
1224
1225VBoxVHWAGlProgramVHWA * VBoxVHWAGlProgramMngr::searchProgram(uint32_t type, uint32_t fourcc, bool bCreate)
1226{
1227 for (ProgramList::const_iterator it = mPrograms.begin(); it != mPrograms.end(); ++ it)
1228 {
1229 if (!(*it)->matches(type, fourcc))
1230 continue;
1231 return *it;
1232 }
1233 if (bCreate)
1234 {
1235 VBoxVHWAGlProgramVHWA *pProgram = createProgram(type, fourcc);
1236 if (pProgram)
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);
1248 if (!addr)
1249 return;
1250 if (addr == mAddress)
1251 return;
1252
1253 if (mFreeAddress)
1254 free(mAddress);
1255
1256 mAddress = addr;
1257 mFreeAddress = false;
1258
1259 mImage->setAddress(mAddress);
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);
1271 glDisable(GL_DEPTH_TEST);
1272
1273 VBOXQGL_CHECKERR(
1274 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1275 );
1276 VBOXQGL_CHECKERR(
1277 glPixelStorei(GL_PACK_ALIGNMENT, 1);
1278 );
1279}
1280
1281VBoxVHWASurfaceBase::VBoxVHWASurfaceBase(class VBoxVHWAImage *pImage,
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)
1307#ifdef DEBUG
1308 , cFlipsCurr(0)
1309 , cFlipsTarg(0)
1310#endif
1311{
1312 setDstBltCKey(pDstBltCKey);
1313 setSrcBltCKey(pSrcBltCKey);
1314
1315 setDefaultDstOverlayCKey(pDstOverlayCKey);
1316 resetDefaultDstOverlayCKey();
1317
1318 setDefaultSrcOverlayCKey(pSrcOverlayCKey);
1319 resetDefaultSrcOverlayCKey();
1320
1321 mImage = vboxVHWAImageCreate(QRect(0,0,aSize.width(),aSize.height()), aColorFormat, getGlProgramMngr(), aImgFlags);
1322
1323 setRectValues(aTargRect, aSrcRect);
1324 setVisibleRectValues(aVisTargRect);
1325}
1326
1327VBoxVHWASurfaceBase::~VBoxVHWASurfaceBase()
1328{
1329 uninit();
1330}
1331
1332GLsizei VBoxVHWASurfaceBase::makePowerOf2(GLsizei val)
1333{
1334 int last = ASMBitLastSetS32(val);
1335 if (last>1)
1336 {
1337 last--;
1338 if ((1 << last) != val)
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 {
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;
1375 }
1376
1377 int componentSize = 0;
1378 switch(type)
1379 {
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;
1397 }
1398 return numComponents * componentSize;
1399}
1400
1401void VBoxVHWASurfaceBase::uninit()
1402{
1403 delete mImage;
1404
1405 if (mAddress && mFreeAddress)
1406 {
1407 free(mAddress);
1408 mAddress = NULL;
1409 }
1410}
1411
1412ulong VBoxVHWASurfaceBase::memSize()
1413{
1414 return (ulong)mImage->memSize();
1415}
1416
1417void VBoxVHWASurfaceBase::init(VBoxVHWASurfaceBase * pPrimary, uchar *pvMem)
1418{
1419 if (pPrimary)
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
1429 int tex0Size = mImage->component(0)->memSize();
1430 if (pPrimary)
1431 {
1432 memset(address, 0xff, tex0Size);
1433 Assert(size >= tex0Size);
1434 if (size > tex0Size)
1435 memset(address + tex0Size, 0x0, size - tex0Size);
1436 }
1437 else
1438 {
1439 memset(address, 0x0f, tex0Size);
1440 Assert(size >= tex0Size);
1441 if (size > tex0Size)
1442 memset(address + tex0Size, 0x3f, size - tex0Size);
1443 }
1444#else
1445 memset(address, 0, size);
1446#endif
1447
1448 mImage->init(address);
1449 mpPrimary = pPrimary;
1450
1451 if (pvMem)
1452 {
1453 mAddress = pvMem;
1454 free(address);
1455 mFreeAddress = false;
1456
1457 }
1458 else
1459 {
1460 mAddress = address;
1461 mFreeAddress = true;
1462 }
1463
1464 mImage->setAddress(mAddress);
1465
1466 initDisplay();
1467
1468 mUpdateMem2TexRect.set(mRect);
1469 Assert(!mUpdateMem2TexRect.isClear());
1470 Assert(mRect.contains(mUpdateMem2TexRect.rect()));
1471
1472 if (pPrimary)
1473 {
1474 VBOXQGLLOG(("restoring to tex 0"));
1475 VBOXQGL_CHECKERR(
1476 vboxglActiveTexture(GL_TEXTURE0);
1477 );
1478 }
1479
1480}
1481
1482void VBoxVHWATexture::doUpdate(uchar *pAddress, const QRect *pRect)
1483{
1484 GLenum tt = texTarget();
1485 QRect rect = mRect;
1486 if (pRect)
1487 rect = rect.intersected(*pRect);
1488 AssertReturnVoid(!rect.isEmpty());
1489
1490 Assert(glIsTexture(mTexture));
1491 VBOXQGL_CHECKERR(
1492 glBindTexture(tt, mTexture);
1493 );
1494
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();
1499
1500 uchar *address = pAddress + pointOffsetTex(x, y);
1501
1502 VBOXQGL_CHECKERR(
1503 glPixelStorei(GL_UNPACK_ROW_LENGTH, mBytesPerLine * 8 /mColorFormat.bitsPerPixelTex());
1504 );
1505
1506 VBOXQGL_CHECKERR(
1507 glTexSubImage2D(tt,
1508 0,
1509 x, y, width, height,
1510 mColorFormat.format(),
1511 mColorFormat.type(),
1512 address);
1513 );
1514
1515 VBOXQGL_CHECKERR(
1516 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
1517 );
1518}
1519
1520void VBoxVHWATexture::texCoord(int x, int y)
1521{
1522 glTexCoord2f(((float)x)/mTexRect.width()/mColorFormat.widthCompression(),
1523 ((float)y)/mTexRect.height()/mColorFormat.heightCompression());
1524}
1525
1526void VBoxVHWATexture::multiTexCoord(GLenum texUnit, int x, int y)
1527{
1528 vboxglMultiTexCoord2f(texUnit, ((float)x)/mTexRect.width()/mColorFormat.widthCompression(),
1529 ((float)y)/mTexRect.height()/mColorFormat.heightCompression());
1530}
1531
1532void VBoxVHWATexture::uninit()
1533{
1534 if (mTexture)
1535 glDeleteTextures(1,&mTexture);
1536}
1537
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)
1546{
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());
1554 mTexRect = QRect(0,0,wdt,hgt);
1555}
1556
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()));
1572 AssertFailed();
1573
1574 free(pvBuf);
1575#endif
1576}
1577#endif
1578
1579
1580void VBoxVHWATexture::initParams()
1581{
1582 GLenum tt = texTarget();
1583
1584 glTexParameteri(tt, GL_TEXTURE_MIN_FILTER, mScaleFuncttion);
1585 VBOXQGL_ASSERTNOERR();
1586 glTexParameteri(tt, GL_TEXTURE_MAG_FILTER, mScaleFuncttion);
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{
1646 glTexCoord2i(x/mColorFormat.widthCompression(), y/mColorFormat.heightCompression());
1647}
1648
1649void VBoxVHWATextureNP2Rect::multiTexCoord(GLenum texUnit, int x, int y)
1650{
1651 vboxglMultiTexCoord2i(texUnit, x/mColorFormat.widthCompression(), y/mColorFormat.heightCompression());
1652}
1653
1654GLenum VBoxVHWATextureNP2Rect::texTarget()
1655{
1656 return GL_TEXTURE_RECTANGLE;
1657}
1658
1659bool VBoxVHWASurfaceBase::synchTexMem(const QRect * pRect)
1660{
1661 if (pRect)
1662 AssertReturn(mRect.contains(*pRect), false);
1663
1664 if (mUpdateMem2TexRect.isClear())
1665 return false;
1666
1667 if (pRect && !mUpdateMem2TexRect.rect().intersects(*pRect))
1668 return false;
1669
1670#ifdef VBOXVHWA_PROFILE_FPS
1671 mpImage->reportNewFrame();
1672#endif
1673
1674 mImage->update(&mUpdateMem2TexRect.rect());
1675
1676 mUpdateMem2TexRect.clear();
1677 Assert(mUpdateMem2TexRect.isClear());
1678
1679 return true;
1680}
1681
1682void VBoxVHWATextureNP2RectPBO::init(uchar *pvMem)
1683{
1684 VBOXQGL_CHECKERR(
1685 vboxglGenBuffers(1, &mPBO);
1686 );
1687 VBoxVHWATextureNP2Rect::init(pvMem);
1688}
1689
1690void VBoxVHWATextureNP2RectPBO::doUpdate(uchar *pAddress, const QRect *pRect)
1691{
1692 Q_UNUSED(pAddress);
1693 Q_UNUSED(pRect);
1694
1695 vboxglBindBuffer(GL_PIXEL_UNPACK_BUFFER, mPBO);
1696
1697 GLvoid *buf;
1698
1699 VBOXQGL_CHECKERR(
1700 buf = vboxglMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
1701 );
1702 Assert(buf);
1703 if (buf)
1704 {
1705 memcpy(buf, mAddress, memSize());
1706
1707 bool unmapped;
1708 VBOXQGL_CHECKERR(
1709 unmapped = vboxglUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
1710 );
1711
1712 Assert(unmapped); NOREF(unmapped);
1713
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 }
1725}
1726
1727VBoxVHWATextureNP2RectPBO::~VBoxVHWATextureNP2RectPBO()
1728{
1729 VBOXQGL_CHECKERR(
1730 vboxglDeleteBuffers(1, &mPBO);
1731 );
1732}
1733
1734
1735void VBoxVHWATextureNP2RectPBO::load()
1736{
1737 VBoxVHWATextureNP2Rect::load();
1738
1739 VBOXQGL_CHECKERR(
1740 vboxglBindBuffer(GL_PIXEL_UNPACK_BUFFER, mPBO);
1741 );
1742
1743 VBOXQGL_CHECKERR(
1744 vboxglBufferData(GL_PIXEL_UNPACK_BUFFER, memSize(), NULL, GL_STREAM_DRAW);
1745 );
1746
1747 GLvoid *buf = vboxglMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
1748 Assert(buf);
1749 if (buf)
1750 {
1751 memcpy(buf, mAddress, memSize());
1752
1753 bool unmapped = vboxglUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
1754 Assert(unmapped); NOREF(unmapped);
1755 }
1756
1757 vboxglBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
1758}
1759
1760uchar* VBoxVHWATextureNP2RectPBOMapped::mapAlignedBuffer()
1761{
1762 Assert(!mpMappedAllignedBuffer);
1763 if (!mpMappedAllignedBuffer)
1764 {
1765 VBOXQGL_CHECKERR(
1766 vboxglBindBuffer(GL_PIXEL_UNPACK_BUFFER, mPBO);
1767 );
1768
1769 uchar* buf;
1770 VBOXQGL_CHECKERR(
1771 buf = (uchar*)vboxglMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_READ_WRITE);
1772 );
1773
1774 Assert(buf);
1775
1776 VBOXQGL_CHECKERR(
1777 vboxglBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
1778 );
1779
1780 mpMappedAllignedBuffer = (uchar*)alignBuffer(buf);
1781
1782 mcbOffset = calcOffset(buf, mpMappedAllignedBuffer);
1783 }
1784 return mpMappedAllignedBuffer;
1785}
1786
1787void VBoxVHWATextureNP2RectPBOMapped::unmapBuffer()
1788{
1789 Assert(mpMappedAllignedBuffer);
1790 if (mpMappedAllignedBuffer)
1791 {
1792 VBOXQGL_CHECKERR(
1793 vboxglBindBuffer(GL_PIXEL_UNPACK_BUFFER, mPBO);
1794 );
1795
1796 bool unmapped;
1797 VBOXQGL_CHECKERR(
1798 unmapped = vboxglUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
1799 );
1800
1801 Assert(unmapped); NOREF(unmapped);
1802
1803 VBOXQGL_CHECKERR(
1804 vboxglBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
1805 );
1806
1807 mpMappedAllignedBuffer = NULL;
1808 }
1809}
1810
1811void VBoxVHWATextureNP2RectPBOMapped::load()
1812{
1813 VBoxVHWATextureNP2Rect::load();
1814
1815 VBOXQGL_CHECKERR(
1816 vboxglBindBuffer(GL_PIXEL_UNPACK_BUFFER, mPBO);
1817 );
1818
1819 VBOXQGL_CHECKERR(
1820 vboxglBufferData(GL_PIXEL_UNPACK_BUFFER, mcbActualBufferSize, NULL, GL_STREAM_DRAW);
1821 );
1822
1823 vboxglBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
1824}
1825
1826void VBoxVHWATextureNP2RectPBOMapped::doUpdate(uchar *pAddress, const QRect *pRect)
1827{
1828 Q_UNUSED(pAddress);
1829 Q_UNUSED(pRect);
1830
1831 VBOXQGL_CHECKERR(
1832 vboxglBindBuffer(GL_PIXEL_UNPACK_BUFFER, mPBO);
1833 );
1834
1835 if (mpMappedAllignedBuffer)
1836 {
1837 bool unmapped;
1838 VBOXQGL_CHECKERR(
1839 unmapped = vboxglUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
1840 );
1841
1842 Assert(unmapped); NOREF(unmapped);
1843
1844 mpMappedAllignedBuffer = NULL;
1845 }
1846
1847 VBoxVHWATextureNP2Rect::doUpdate((uchar *)mcbOffset, &mRect);
1848
1849 VBOXQGL_CHECKERR(
1850 vboxglBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
1851 );
1852}
1853
1854int VBoxVHWASurfaceBase::lock(const QRect *pRect, uint32_t flags)
1855{
1856 Q_UNUSED(flags);
1857
1858 if (pRect)
1859 AssertReturn(mRect.contains(*pRect), VERR_GENERAL_FAILURE);
1860
1861 Assert(mLockCount >= 0);
1862 if (pRect && pRect->isEmpty())
1863 return VERR_GENERAL_FAILURE;
1864 if (mLockCount < 0)
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
1871 mUpdateMem2TexRect.add(pRect ? mRect.intersected(*pRect) : mRect);
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
1885void VBoxVHWASurfaceBase::setRectValues (const QRect &aTargRect, const QRect &aSrcRect)
1886{
1887 mTargRect = aTargRect;
1888 mSrcRect = mRect.intersected(aSrcRect);
1889}
1890
1891void VBoxVHWASurfaceBase::setVisibleRectValues (const QRect &aVisTargRect)
1892{
1893 mVisibleTargRect = aVisTargRect.intersected(mTargRect);
1894 if (mVisibleTargRect.isEmpty() || mTargRect.isEmpty())
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
1924
1925void VBoxVHWASurfaceBase::setRects(const QRect & aTargRect, const QRect & aSrcRect)
1926{
1927 if (mTargRect != aTargRect || mSrcRect != aSrcRect)
1928 setRectValues(aTargRect, aSrcRect);
1929}
1930
1931void VBoxVHWASurfaceBase::setTargRectPosition(const QPoint & aPoint)
1932{
1933 QRect tRect = targRect();
1934 tRect.moveTopLeft(aPoint);
1935 setRects(tRect, srcRect());
1936}
1937
1938void VBoxVHWASurfaceBase::updateVisibility(VBoxVHWASurfaceBase *pPrimary, const QRect & aVisibleTargRect,
1939 bool bNotIntersected, bool bForce)
1940{
1941 if (bForce || aVisibleTargRect.intersected(mTargRect) != mVisibleTargRect)
1942 setVisibleRectValues(aVisibleTargRect);
1943
1944 mpPrimary = pPrimary;
1945 mbNotIntersected = bNotIntersected;
1946
1947 initDisplay();
1948}
1949
1950void VBoxVHWASurfaceBase::initDisplay()
1951{
1952 if (mVisibleTargRect.isEmpty() || mVisibleSrcRect.isEmpty())
1953 {
1954 Assert(mVisibleTargRect.isEmpty() && mVisibleSrcRect.isEmpty());
1955 mImage->deleteDisplay();
1956 return;
1957 }
1958
1959 int rc = mImage->initDisplay(mpPrimary ? mpPrimary->mImage : NULL, &mVisibleTargRect, &mVisibleSrcRect,
1960 getActiveDstOverlayCKey(mpPrimary), getActiveSrcOverlayCKey(), mbNotIntersected);
1961 AssertRC(rc);
1962}
1963
1964void VBoxVHWASurfaceBase::updatedMem(const QRect *rec)
1965{
1966 AssertReturnVoid(mRect.contains(*rec));
1967 mUpdateMem2TexRect.add(*rec);
1968}
1969
1970bool VBoxVHWASurfaceBase::performDisplay(VBoxVHWASurfaceBase *pPrimary, bool bForce)
1971{
1972 Assert(mImage->displayInitialized());
1973
1974 if (mVisibleTargRect.isEmpty())
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());
1979 return false;
1980 }
1981 Assert(!mVisibleSrcRect.isEmpty());
1982
1983 bForce |= synchTexMem(&mVisibleSrcRect);
1984
1985 const VBoxVHWAColorKey * pDstCKey = getActiveDstOverlayCKey(pPrimary);
1986 if (pPrimary && pDstCKey)
1987 bForce |= pPrimary->synchTexMem(&mVisibleTargRect);
1988
1989 if (!bForce)
1990 return false;
1991
1992 mImage->display();
1993
1994 Assert(bForce);
1995 return true;
1996}
1997
1998class VBoxVHWAGlProgramMngr * VBoxVHWASurfaceBase::getGlProgramMngr()
1999{
2000 return mpImage->vboxVHWAGetGlProgramMngr();
2001}
2002
2003class VBoxGLContext : public QGLContext
2004{
2005public:
2006 VBoxGLContext (const QGLFormat & format )
2007 : QGLContext(format)
2008 , mAllowDoneCurrent(true)
2009 {
2010 }
2011
2012 void doneCurrent()
2013 {
2014 if (!mAllowDoneCurrent)
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
2025
2026VBoxGLWgt::VBoxGLWgt(VBoxVHWAImage *pImage, QWidget *parent, const QGLWidget *shareWidget)
2027 : QGLWidget(new VBoxGLContext(shareWidget->format()), parent, shareWidget)
2028 , mpImage(pImage)
2029{
2030 /* work-around to disable done current needed to old ATI drivers on Linux */
2031 VBoxGLContext *pc = (VBoxGLContext *)context();
2032 pc->allowDoneCurrent (false);
2033 Assert(isSharing());
2034}
2035
2036VBoxVHWAImage::VBoxVHWAImage ()
2037 : mSurfHandleTable(VBOXVHWA_MAX_SURFACES)
2038 , mRepaintNeeded(false)
2039// , mbVGASurfCreated(false)
2040 , mConstructingList(NULL)
2041 , mcRemaining2Contruct(0)
2042 , mSettings(NULL)
2043#ifdef VBOXVHWA_PROFILE_FPS
2044 , mFPSCounter(64)
2045 , mbNewFrame(false)
2046#endif
2047{
2048 mpMngr = new VBoxVHWAGlProgramMngr();
2049// /* No need for background drawing */
2050// setAttribute (Qt::WA_OpaquePaintEvent);
2051}
2052
2053int VBoxVHWAImage::init(VBoxVHWASettings *aSettings)
2054{
2055 mSettings = aSettings;
2056 return VINF_SUCCESS;
2057}
2058
2059const QGLFormat &VBoxVHWAImage::vboxGLFormat()
2060{
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());
2070// vboxFormat.setRedBufferSize(8);
2071// vboxFormat.setGreenBufferSize(8);
2072// vboxFormat.setBlueBufferSize(8);
2073 return vboxFormat;
2074}
2075
2076
2077VBoxVHWAImage::~VBoxVHWAImage()
2078{
2079 delete mpMngr;
2080}
2081
2082#ifdef VBOXVHWA_OLD_COORD
2083void VBoxVHWAImage::doSetupMatrix(const QSize &aSize, bool bInverted)
2084{
2085 VBOXQGL_CHECKERR(
2086 glLoadIdentity();
2087 );
2088 if (bInverted)
2089 {
2090 VBOXQGL_CHECKERR(
2091 glScalef(1.0f / aSize.width(), 1.0f / aSize.height(), 1.0f);
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(
2101 glScalef(1.0f / aSize.width(), 1.0f / aSize.height(), 1.0f);
2102 );
2103 VBOXQGL_CHECKERR(
2104 glRotatef(180.0f, 1.0f, 0.0f, 0.0f);
2105 );
2106 }
2107}
2108#endif
2109
2110void VBoxVHWAImage::adjustViewport(const QSize &display, const QRect &viewport)
2111{
2112 glViewport(-viewport.x(),
2113 viewport.height() + viewport.y() - display.height(),
2114 display.width(),
2115 display.height());
2116}
2117
2118void VBoxVHWAImage::setupMatricies(const QSize &display, bool bInverted)
2119{
2120 glMatrixMode(GL_PROJECTION);
2121 glLoadIdentity();
2122
2123 if (bInverted)
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
2128 glMatrixMode(GL_MODELVIEW);
2129 glLoadIdentity();
2130}
2131
2132int VBoxVHWAImage::reset(VHWACommandList *pCmdList)
2133{
2134 VBOXVHWACMD *pCmd;
2135 const OverlayList & overlays = mDisplay.overlays();
2136 for (OverlayList::const_iterator oIt = overlays.begin(); oIt != overlays.end(); ++ oIt)
2137 {
2138 VBoxVHWASurfList * pSurfList = *oIt;
2139 if (pSurfList->current())
2140 {
2141 /* 1. hide overlay */
2142 pCmd = vhwaHHCmdCreate(VBOXVHWACMD_TYPE_SURF_OVERLAY_UPDATE, sizeof(VBOXVHWACMD_SURF_OVERLAY_UPDATE));
2143 VBOXVHWACMD_SURF_OVERLAY_UPDATE RT_UNTRUSTED_VOLATILE_GUEST *pOUCmd = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_OVERLAY_UPDATE);
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();
2152 for (SurfList::const_iterator sIt = surfaces.begin(); sIt != surfaces.end(); ++ sIt)
2153 {
2154 VBoxVHWASurfaceBase *pCurSurf = (*sIt);
2155 pCmd = vhwaHHCmdCreate(VBOXVHWACMD_TYPE_SURF_DESTROY, sizeof(VBOXVHWACMD_SURF_DESTROY));
2156 VBOXVHWACMD_SURF_DESTROY RT_UNTRUSTED_VOLATILE_GUEST *pSDCmd = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_DESTROY);
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();
2165 for (SurfList::const_iterator sIt = surfaces.begin(); sIt != surfaces.end(); ++ sIt)
2166 {
2167 VBoxVHWASurfaceBase *pCurSurf = (*sIt);
2168 if (pCurSurf->handle() != VBOXVHWA_SURFHANDLE_INVALID)
2169 {
2170 pCmd = vhwaHHCmdCreate(VBOXVHWACMD_TYPE_SURF_DESTROY, sizeof(VBOXVHWACMD_SURF_DESTROY));
2171 VBOXVHWACMD_SURF_DESTROY RT_UNTRUSTED_VOLATILE_GUEST *pSDCmd = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_DESTROY);
2172 pSDCmd->u.in.hSurf = pCurSurf->handle();
2173
2174 pCmdList->push_back(pCmd);
2175 }
2176 }
2177
2178 return VINF_SUCCESS;
2179}
2180
2181#ifdef VBOX_WITH_VIDEOHWACCEL
2182int VBoxVHWAImage::vhwaSurfaceCanCreate(struct VBOXVHWACMD_SURF_CANCREATE RT_UNTRUSTED_VOLATILE_GUEST *pCmd)
2183{
2184 VBOXQGLLOG_ENTER(("\n"));
2185
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
2193 const VBoxVHWAInfo & info = vboxVHWAGetSupportInfo(NULL);
2194
2195 if (!(pCmd->SurfInfo.flags & VBOXVHWA_SD_CAPS))
2196 {
2197 AssertFailed();
2198 pCmd->u.out.ErrInfo = -1;
2199 return VINF_SUCCESS;
2200 }
2201#ifdef VBOXVHWA_ALLOW_PRIMARY_AND_OVERLAY_ONLY
2202 if (pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_OFFSCREENPLAIN)
2203 {
2204#ifdef DEBUGVHWASTRICT
2205 AssertFailed();
2206#endif
2207 pCmd->u.out.ErrInfo = -1;
2208 return VINF_SUCCESS;
2209 }
2210#endif
2211
2212 if (pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_PRIMARYSURFACE)
2213 {
2214 if (pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_COMPLEX)
2215 {
2216#ifdef DEBUG_misha
2217 AssertFailed();
2218#endif
2219 pCmd->u.out.ErrInfo = -1;
2220 }
2221 else
2222 {
2223 pCmd->u.out.ErrInfo = 0;
2224 }
2225 return VINF_SUCCESS;
2226 }
2227
2228#ifdef VBOXVHWA_ALLOW_PRIMARY_AND_OVERLAY_ONLY
2229 if ((pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_OVERLAY) == 0)
2230 {
2231#ifdef DEBUGVHWASTRICT
2232 AssertFailed();
2233#endif
2234 pCmd->u.out.ErrInfo = -1;
2235 return VINF_SUCCESS;
2236 }
2237#endif
2238
2239 if (pCmd->u.in.bIsDifferentPixelFormat)
2240 {
2241 if (!(pCmd->SurfInfo.flags & VBOXVHWA_SD_PIXELFORMAT))
2242 {
2243 AssertFailed();
2244 pCmd->u.out.ErrInfo = -1;
2245 return VINF_SUCCESS;
2246 }
2247
2248 if (pCmd->SurfInfo.PixelFormat.flags & VBOXVHWA_PF_RGB)
2249 {
2250 if (pCmd->SurfInfo.PixelFormat.c.rgbBitCount != 32
2251 && pCmd->SurfInfo.PixelFormat.c.rgbBitCount != 24)
2252 {
2253 AssertFailed();
2254 pCmd->u.out.ErrInfo = -1;
2255 return VINF_SUCCESS;
2256 }
2257 }
2258 else if (pCmd->SurfInfo.PixelFormat.flags & VBOXVHWA_PF_FOURCC)
2259 {
2260 /* detect whether we support this format */
2261 bool bFound = mSettings->isSupported (info, pCmd->SurfInfo.PixelFormat.fourCC);
2262
2263 if (!bFound)
2264 {
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 ));
2271 pCmd->u.out.ErrInfo = -1;
2272 return VINF_SUCCESS;
2273 }
2274 }
2275 else
2276 {
2277 AssertFailed();
2278 pCmd->u.out.ErrInfo = -1;
2279 return VINF_SUCCESS;
2280 }
2281 }
2282
2283 pCmd->u.out.ErrInfo = 0;
2284 return VINF_SUCCESS;
2285}
2286
2287int VBoxVHWAImage::vhwaSurfaceCreate(struct VBOXVHWACMD_SURF_CREATE RT_UNTRUSTED_VOLATILE_GUEST *pCmd)
2288{
2289 VBOXQGLLOG_ENTER (("\n"));
2290
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)
2295 {
2296 if (mSurfHandleTable.get(handle))
2297 {
2298 AssertFailed();
2299 return VERR_GENERAL_FAILURE;
2300 }
2301 }
2302
2303 VBoxVHWASurfaceBase *surf = NULL;
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;
2307 /* paranoia to ensure the VBoxVHWAColorFormat API works properly */
2308 Assert(!reportedFormat.isValid());
2309 bool bNoPBO = false;
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;
2316 if (pCmd->SurfInfo.flags & VBOXVHWA_SD_CKDESTBLT)
2317 {
2318 DstBltCKey = VBoxVHWAColorKey(pCmd->SurfInfo.DstBltCK.high, pCmd->SurfInfo.DstBltCK.low);
2319 pDstBltCKey = &DstBltCKey;
2320 }
2321 if (pCmd->SurfInfo.flags & VBOXVHWA_SD_CKSRCBLT)
2322 {
2323 SrcBltCKey = VBoxVHWAColorKey(pCmd->SurfInfo.SrcBltCK.high, pCmd->SurfInfo.SrcBltCK.low);
2324 pSrcBltCKey = &SrcBltCKey;
2325 }
2326 if (pCmd->SurfInfo.flags & VBOXVHWA_SD_CKDESTOVERLAY)
2327 {
2328 DstOverlayCKey = VBoxVHWAColorKey(pCmd->SurfInfo.DstOverlayCK.high, pCmd->SurfInfo.DstOverlayCK.low);
2329 pDstOverlayCKey = &DstOverlayCKey;
2330 }
2331 if (pCmd->SurfInfo.flags & VBOXVHWA_SD_CKSRCOVERLAY)
2332 {
2333 SrcOverlayCKey = VBoxVHWAColorKey(pCmd->SurfInfo.SrcOverlayCK.high, pCmd->SurfInfo.SrcOverlayCK.low);
2334 pSrcOverlayCKey = &SrcOverlayCKey;
2335 }
2336
2337 if (pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_PRIMARYSURFACE)
2338 {
2339 bNoPBO = true;
2340 bPrimary = true;
2341 VBoxVHWASurfaceBase *pVga = vgaSurface();
2342#ifdef VBOX_WITH_WDDM
2343 uchar *addr = vboxVRAMAddressFromOffset(pCmd->SurfInfo.offSurface);
2344 AssertPtrReturn(addr, VERR_GENERAL_FAILURE);
2345 RT_UNTRUSTED_VALIDATED_FENCE();
2346 pVga->setAddress(addr);
2347#endif
2348
2349 Assert((pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_OFFSCREENPLAIN) == 0);
2350
2351 reportedFormat = VBoxVHWAColorFormat(pCmd->SurfInfo.PixelFormat.c.rgbBitCount,
2352 pCmd->SurfInfo.PixelFormat.m1.rgbRBitMask,
2353 pCmd->SurfInfo.PixelFormat.m2.rgbGBitMask,
2354 pCmd->SurfInfo.PixelFormat.m3.rgbBBitMask);
2355
2356 if (pVga->handle() == VBOXVHWA_SURFHANDLE_INVALID
2357 && (pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_OFFSCREENPLAIN) == 0)
2358 {
2359 Assert(pCmd->SurfInfo.PixelFormat.flags & VBOXVHWA_PF_RGB);
2360// if (pCmd->SurfInfo.PixelFormat.flags & VBOXVHWA_PF_RGB)
2361 {
2362 Assert(pCmd->SurfInfo.width == pVga->width());
2363 Assert(pCmd->SurfInfo.height == pVga->height());
2364// if (pCmd->SurfInfo.width == pVga->width()
2365// && pCmd->SurfInfo.height == pVga->height())
2366 {
2367 // the assert below is incorrect in case the Framebuffer is working in "not using VRAM" mode
2368// Assert(pVga->pixelFormat().equals(format));
2369// if (pVga->pixelFormat().equals(format))
2370 {
2371 surf = pVga;
2372
2373 surf->setDstBltCKey(pDstBltCKey);
2374 surf->setSrcBltCKey(pSrcBltCKey);
2375
2376 surf->setDefaultDstOverlayCKey(pDstOverlayCKey);
2377 surf->resetDefaultDstOverlayCKey();
2378
2379 surf->setDefaultSrcOverlayCKey(pSrcOverlayCKey);
2380 surf->resetDefaultSrcOverlayCKey();
2381// mbVGASurfCreated = true;
2382 }
2383 }
2384 }
2385 }
2386 }
2387 else if (pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_OFFSCREENPLAIN)
2388 {
2389 bNoPBO = true;
2390 }
2391
2392 if (!surf)
2393 {
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
2399 VBOXVHWAIMG_TYPE fFlags = 0;
2400 if (!bNoPBO)
2401 {
2402 fFlags |= VBOXVHWAIMG_PBO | VBOXVHWAIMG_PBOIMG | VBOXVHWAIMG_LINEAR;
2403 if (mSettings->isStretchLinearEnabled())
2404 fFlags |= VBOXVHWAIMG_FBO;
2405 }
2406
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,
2414 pCmd->SurfInfo.PixelFormat.m1.rgbRBitMask,
2415 pCmd->SurfInfo.PixelFormat.m2.rgbGBitMask,
2416 pCmd->SurfInfo.PixelFormat.m3.rgbBBitMask);
2417 else if (pCmd->SurfInfo.PixelFormat.flags & VBOXVHWA_PF_FOURCC)
2418 format = VBoxVHWAColorFormat(pCmd->SurfInfo.PixelFormat.fourCC);
2419 else
2420 AssertFailed();
2421
2422 if (format.isValid())
2423 {
2424 surf = new VBoxVHWASurfaceBase(this,
2425 surfSize,
2426 primaryRect,
2427 QRect(0, 0, surfSize.width(), surfSize.height()),
2428 mViewport,
2429 format,
2430 pSrcBltCKey, pDstBltCKey, pSrcOverlayCKey, pDstOverlayCKey,
2431#ifdef VBOXVHWA_USE_TEXGROUP
2432 0,
2433#endif
2434 fFlags);
2435 }
2436 else
2437 {
2438 AssertFailed();
2439 VBOXQGLLOG_EXIT(("pSurf (0x%p)\n",surf));
2440 return VERR_GENERAL_FAILURE;
2441 }
2442
2443 uchar *addr = vboxVRAMAddressFromOffset(pCmd->SurfInfo.offSurface);
2444 AssertReturn(addr || pCmd->SurfInfo.offSurface == VBOXVHWA_OFFSET64_VOID, VERR_GENERAL_FAILURE);
2445 surf->init(mDisplay.getPrimary(), addr);
2446
2447 if (pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_OVERLAY)
2448 {
2449#ifdef DEBUG_misha
2450 Assert(!bNoPBO);
2451#endif
2452
2453 if (!mConstructingList)
2454 {
2455 mConstructingList = new VBoxVHWASurfList();
2456 mcRemaining2Contruct = pCmd->SurfInfo.cBackBuffers+1;
2457 mDisplay.addOverlay(mConstructingList);
2458 }
2459
2460 mConstructingList->add(surf);
2461 mcRemaining2Contruct--;
2462 if (!mcRemaining2Contruct)
2463 mConstructingList = NULL;
2464 }
2465 else
2466 {
2467 VBoxVHWASurfaceBase * pVga = vgaSurface();
2468 Assert(pVga->handle() != VBOXVHWA_SURFHANDLE_INVALID);
2469 Assert(pVga != surf); NOREF(pVga);
2470 mDisplay.getVGA()->getComplexList()->add(surf);
2471#ifdef DEBUGVHWASTRICT
2472 Assert(pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_VISIBLE);
2473#endif
2474 if (bPrimary)
2475 {
2476 Assert(surf->getComplexList() == mDisplay.getVGA()->getComplexList());
2477 surf->getComplexList()->setCurrentVisible(surf);
2478 mDisplay.updateVGA(surf);
2479 }
2480 }
2481 }
2482 else
2483 Assert(pCmd->SurfInfo.surfCaps & VBOXVHWA_SCAPS_PRIMARYSURFACE);
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
2490 if (!reportedFormat.isValid())
2491 {
2492 pCmd->SurfInfo.pitch = surf->bytesPerLine();
2493 pCmd->SurfInfo.sizeX = surf->memSize();
2494 pCmd->SurfInfo.sizeY = 1;
2495 }
2496 else
2497 {
2498 /* this is the case of Framebuffer not using Guest VRAM */
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 }
2507
2508 if (handle != VBOXVHWA_SURFHANDLE_INVALID)
2509 {
2510 bool bSuccess = mSurfHandleTable.mapPut(handle, surf);
2511 Assert(bSuccess);
2512 if (!bSuccess)
2513 {
2514 /** @todo this is very bad, should not be here */
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
2530 VBOXQGLLOG_EXIT(("pSurf (0x%p)\n",surf));
2531
2532 return VINF_SUCCESS;
2533}
2534
2535#ifdef VBOX_WITH_WDDM
2536int VBoxVHWAImage::vhwaSurfaceGetInfo(struct VBOXVHWACMD_SURF_GETINFO RT_UNTRUSTED_VOLATILE_GUEST *pCmd)
2537{
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();
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
2551 AssertFailed();
2552
2553 Assert(format.isValid());
2554 if (format.isValid())
2555 {
2556 pCmd->SurfInfo.pitch = VBoxVHWATextureImage::calcBytesPerLine(format, pCmd->SurfInfo.width);
2557 pCmd->SurfInfo.sizeX = VBoxVHWATextureImage::calcMemSize(format,
2558 pCmd->SurfInfo.width, pCmd->SurfInfo.height);
2559 pCmd->SurfInfo.sizeY = 1;
2560 return VINF_SUCCESS;
2561 }
2562 return VERR_INVALID_PARAMETER;
2563}
2564#endif
2565
2566int VBoxVHWAImage::vhwaSurfaceDestroy(struct VBOXVHWACMD_SURF_DESTROY RT_UNTRUSTED_VOLATILE_GUEST *pCmd)
2567{
2568 VBoxVHWASurfaceBase *pSurf = handle2Surface(pCmd->u.in.hSurf);
2569 AssertReturn(pSurf, VERR_INVALID_PARAMETER);
2570 VBoxVHWASurfList *pList = pSurf->getComplexList();
2571 Assert(pSurf->handle() != VBOXVHWA_SURFHANDLE_INVALID);
2572
2573 VBOXQGLLOG_ENTER(("pSurf (0x%x)\n",pSurf));
2574 if (pList != mDisplay.getVGA()->getComplexList())
2575 {
2576 Assert(pList);
2577 if (pList)
2578 {
2579 pList->remove(pSurf);
2580 if (pList->surfaces().empty())
2581 {
2582 mDisplay.removeOverlay(pList);
2583 if (pList == mConstructingList)
2584 {
2585 mConstructingList = NULL;
2586 mcRemaining2Contruct = 0;
2587 }
2588 delete pList;
2589 }
2590 }
2591
2592 delete(pSurf);
2593 }
2594 else
2595 {
2596 Assert(pList && pList->size() >= 1);
2597 if (pList && pList->size() > 1)
2598 {
2599 if (pSurf == mDisplay.getVGA())
2600 {
2601 const SurfList & surfaces = pList->surfaces();
2602
2603 for (SurfList::const_iterator it = surfaces.begin();
2604 it != surfaces.end(); ++ it)
2605 {
2606 VBoxVHWASurfaceBase *pCurSurf = (*it);
2607 Assert(pCurSurf);
2608 if (pCurSurf != pSurf)
2609 {
2610 mDisplay.updateVGA(pCurSurf);
2611 pList->setCurrentVisible(pCurSurf);
2612 break;
2613 }
2614 }
2615 }
2616
2617 pList->remove(pSurf);
2618 delete(pSurf);
2619 }
2620 else
2621 {
2622 pSurf->setHandle(VBOXVHWA_SURFHANDLE_INVALID);
2623 }
2624 }
2625
2626 /* just in case we destroy a visible overlay surface */
2627 mRepaintNeeded = true;
2628
2629 void * test = mSurfHandleTable.remove(pCmd->u.in.hSurf);
2630 Assert(test); NOREF(test);
2631
2632 return VINF_SUCCESS;
2633}
2634
2635#define VBOXVHWA_CONSTRUCT_QRECT_FROM_RECTL_RB(a_pr) \
2636 QRect((a_pr)->left, \
2637 (a_pr)->top, \
2638 (a_pr)->right - (a_pr)->left + 1, \
2639 (a_pr)->bottom - (a_pr)->top + 1)
2640
2641#define VBOXVHWA_CONSTRUCT_QRECT_FROM_RECTL_WH(a_pr) \
2642 QRect((a_pr)->left, \
2643 (a_pr)->top, \
2644 (a_pr)->right - (a_pr)->left, \
2645 (a_pr)->bottom - (a_pr)->top)
2646
2647int VBoxVHWAImage::vhwaSurfaceLock(struct VBOXVHWACMD_SURF_LOCK RT_UNTRUSTED_VOLATILE_GUEST *pCmd)
2648{
2649 VBoxVHWASurfaceBase *pSurf = handle2Surface(pCmd->u.in.hSurf);
2650 AssertReturn(pSurf, VERR_INVALID_PARAMETER);
2651 VBOXQGLLOG_ENTER(("pSurf (0x%x)\n",pSurf));
2652
2653 vboxCheckUpdateAddress (pSurf, pCmd->u.in.offSurface);
2654 if (pCmd->u.in.rectValid)
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
2662int VBoxVHWAImage::vhwaSurfaceUnlock(struct VBOXVHWACMD_SURF_UNLOCK RT_UNTRUSTED_VOLATILE_GUEST *pCmd)
2663{
2664 VBoxVHWASurfaceBase *pSurf = handle2Surface(pCmd->u.in.hSurf);
2665 AssertReturn(pSurf, VERR_INVALID_PARAMETER);
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*/
2670 if (pSurf != mDisplay.getPrimary())
2671 {
2672 const OverlayList & overlays = mDisplay.overlays();
2673 bool bFound = false;
2674
2675 if (!mDisplay.isPrimary(pSurf))
2676 {
2677 for (OverlayList::const_iterator it = overlays.begin();
2678 it != overlays.end(); ++ it)
2679 {
2680 VBoxVHWASurfList * pSurfList = *it;
2681 if (pSurfList->current() == pSurf)
2682 {
2683 bFound = true;
2684 break;
2685 }
2686 }
2687
2688 Assert(bFound);
2689 }
2690
2691// Assert(bFound);
2692 }
2693#endif
2694 VBOXQGLLOG_ENTER(("pSurf (0x%x)\n",pSurf));
2695 if (pCmd->u.in.xUpdatedMemValid)
2696 {
2697 QRect r = VBOXVHWA_CONSTRUCT_QRECT_FROM_RECTL_WH(&pCmd->u.in.xUpdatedMemRect);
2698 pSurf->updatedMem(&r);
2699 }
2700
2701 return pSurf->unlock();
2702}
2703
2704int VBoxVHWAImage::vhwaSurfaceBlt(struct VBOXVHWACMD_SURF_BLT RT_UNTRUSTED_VOLATILE_GUEST *pCmd)
2705{
2706 Q_UNUSED(pCmd);
2707 return VERR_NOT_IMPLEMENTED;
2708}
2709
2710int VBoxVHWAImage::vhwaSurfaceFlip(struct VBOXVHWACMD_SURF_FLIP RT_UNTRUSTED_VOLATILE_GUEST *pCmd)
2711{
2712 VBoxVHWASurfaceBase *pTargSurf = handle2Surface(pCmd->u.in.hTargSurf);
2713 AssertReturn(pTargSurf, VERR_INVALID_PARAMETER);
2714 VBoxVHWASurfaceBase *pCurrSurf = handle2Surface(pCmd->u.in.hCurrSurf);
2715 AssertReturn(pCurrSurf, VERR_INVALID_PARAMETER);
2716 VBOXQGLLOG_ENTER(("pTargSurf (0x%x), pCurrSurf (0x%x)\n", pTargSurf, pCurrSurf));
2717 vboxCheckUpdateAddress (pCurrSurf, pCmd->u.in.offCurrSurface);
2718 vboxCheckUpdateAddress (pTargSurf, pCmd->u.in.offTargSurface);
2719
2720 if (pCmd->u.in.xUpdatedTargMemValid)
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
2727 mRepaintNeeded = true;
2728#ifdef DEBUG
2729 pCurrSurf->cFlipsCurr++;
2730 pTargSurf->cFlipsTarg++;
2731#endif
2732
2733 return VINF_SUCCESS;
2734}
2735
2736int VBoxVHWAImage::vhwaSurfaceColorFill(struct VBOXVHWACMD_SURF_COLORFILL RT_UNTRUSTED_VOLATILE_GUEST *pCmd)
2737{
2738 NOREF(pCmd);
2739 return VERR_NOT_IMPLEMENTED;
2740}
2741
2742void VBoxVHWAImage::vhwaDoSurfaceOverlayUpdate(VBoxVHWASurfaceBase *pDstSurf, VBoxVHWASurfaceBase *pSrcSurf,
2743 struct VBOXVHWACMD_SURF_OVERLAY_UPDATE RT_UNTRUSTED_VOLATILE_GUEST *pCmd)
2744{
2745 if (pCmd->u.in.flags & VBOXVHWA_OVER_KEYDEST)
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 }
2757 else if (pCmd->u.in.flags & VBOXVHWA_OVER_KEYDESTOVERRIDE)
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
2789 if (pCmd->u.in.flags & VBOXVHWA_OVER_KEYSRC)
2790 {
2791 VBOXQGLLOG((", KEYSRC"));
2792 pSrcSurf->resetDefaultSrcOverlayCKey();
2793 }
2794 else if (pCmd->u.in.flags & VBOXVHWA_OVER_KEYSRCOVERRIDE)
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"));
2806 if (pDstSurf)
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
2817 pSrcSurf->setPrimary(pDstSurf);
2818
2819 pSrcSurf->setRects(dstRect, srcRect);
2820 }
2821}
2822
2823int VBoxVHWAImage::vhwaSurfaceOverlayUpdate(struct VBOXVHWACMD_SURF_OVERLAY_UPDATE RT_UNTRUSTED_VOLATILE_GUEST *pCmd)
2824{
2825 VBoxVHWASurfaceBase *pSrcSurf = handle2Surface(pCmd->u.in.hSrcSurf);
2826 AssertReturn(pSrcSurf, VERR_INVALID_PARAMETER);
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
2832 if (pCmd->u.in.hDstSurf)
2833 {
2834 pDstSurf = handle2Surface(pCmd->u.in.hDstSurf);
2835 AssertReturn(pDstSurf, VERR_INVALID_PARAMETER);
2836 vboxCheckUpdateAddress (pDstSurf, pCmd->u.in.offDstSurface);
2837 VBOXQGLLOG(("pDstSurf (0x%x)\n",pDstSurf));
2838#ifdef DEBUGVHWASTRICT
2839 Assert(pDstSurf == mDisplay.getVGA());
2840 Assert(mDisplay.getVGA() == mDisplay.getPrimary());
2841#endif
2842 Assert(pDstSurf->getComplexList() == mDisplay.getVGA()->getComplexList());
2843
2844 if (pCmd->u.in.flags & VBOXVHWA_OVER_SHOW)
2845 {
2846 if (pDstSurf != mDisplay.getPrimary())
2847 {
2848 mDisplay.updateVGA(pDstSurf);
2849 pDstSurf->getComplexList()->setCurrentVisible(pDstSurf);
2850 }
2851 }
2852 }
2853
2854#ifdef VBOX_WITH_WDDM
2855 if (pCmd->u.in.xFlags & VBOXVHWACMD_SURF_OVERLAY_UPDATE_F_SRCMEMRECT)
2856 {
2857 QRect r = VBOXVHWA_CONSTRUCT_QRECT_FROM_RECTL_WH(&pCmd->u.in.xUpdatedSrcMemRect);
2858 pSrcSurf->updatedMem(&r);
2859 }
2860 if (pCmd->u.in.xFlags & VBOXVHWACMD_SURF_OVERLAY_UPDATE_F_DSTMEMRECT)
2861 {
2862 AssertReturn(pDstSurf, VERR_INVALID_PARAMETER);
2863 QRect r = VBOXVHWA_CONSTRUCT_QRECT_FROM_RECTL_WH(&pCmd->u.in.xUpdatedDstMemRect);
2864 pDstSurf->updatedMem(&r);
2865 }
2866#endif
2867
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
2877 if (pCmd->u.in.flags & VBOXVHWA_OVER_HIDE)
2878 {
2879 VBOXQGLLOG(("hide\n"));
2880 pList->setCurrentVisible(NULL);
2881 }
2882 else if (pCmd->u.in.flags & VBOXVHWA_OVER_SHOW)
2883 {
2884 VBOXQGLLOG(("show\n"));
2885 pList->setCurrentVisible(pSrcSurf);
2886 }
2887
2888 mRepaintNeeded = true;
2889
2890 return VINF_SUCCESS;
2891}
2892
2893int VBoxVHWAImage::vhwaSurfaceOverlaySetPosition(struct VBOXVHWACMD_SURF_OVERLAY_SETPOSITION RT_UNTRUSTED_VOLATILE_GUEST *pCmd)
2894{
2895 VBoxVHWASurfaceBase *pDstSurf = handle2Surface(pCmd->u.in.hDstSurf);
2896 AssertReturn(pDstSurf, VERR_INVALID_PARAMETER);
2897 VBoxVHWASurfaceBase *pSrcSurf = handle2Surface(pCmd->u.in.hSrcSurf);
2898 AssertReturn(pSrcSurf, VERR_INVALID_PARAMETER);
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
2910#ifdef DEBUGVHWASTRICT
2911 Assert(pDstSurf == mDisplay.getVGA());
2912 Assert(mDisplay.getVGA() == mDisplay.getPrimary());
2913#endif
2914 if (pSrcSurf->getComplexList()->current() != NULL)
2915 {
2916 if (pDstSurf != mDisplay.getPrimary())
2917 {
2918 mDisplay.updateVGA(pDstSurf);
2919 pDstSurf->getComplexList()->setCurrentVisible(pDstSurf);
2920 }
2921 }
2922
2923 mRepaintNeeded = true;
2924
2925 for (SurfList::const_iterator it = surfaces.begin();
2926 it != surfaces.end(); ++ it)
2927 {
2928 VBoxVHWASurfaceBase *pCurSrcSurf = (*it);
2929 pCurSrcSurf->setTargRectPosition(pos);
2930 }
2931
2932 return VINF_SUCCESS;
2933}
2934
2935int VBoxVHWAImage::vhwaSurfaceColorkeySet(struct VBOXVHWACMD_SURF_COLORKEY_SET RT_UNTRUSTED_VOLATILE_GUEST *pCmd)
2936{
2937 VBoxVHWASurfaceBase *pSurf = handle2Surface(pCmd->u.in.hSurf);
2938 AssertReturn(pSurf, VERR_INVALID_PARAMETER);
2939 VBOXQGLLOG_ENTER(("pSurf (0x%x)\n", pSurf));
2940
2941 vboxCheckUpdateAddress (pSurf, pCmd->u.in.offSurface);
2942
2943 mRepaintNeeded = true;
2944
2945 if (pCmd->u.in.flags & VBOXVHWA_CKEY_DESTBLT)
2946 {
2947 VBoxVHWAColorKey ckey(pCmd->u.in.CKey.high, pCmd->u.in.CKey.low);
2948 pSurf->setDstBltCKey(&ckey);
2949 }
2950 if (pCmd->u.in.flags & VBOXVHWA_CKEY_DESTOVERLAY)
2951 {
2952 VBoxVHWAColorKey ckey(pCmd->u.in.CKey.high, pCmd->u.in.CKey.low);
2953 pSurf->setDefaultDstOverlayCKey(&ckey);
2954 }
2955 if (pCmd->u.in.flags & VBOXVHWA_CKEY_SRCBLT)
2956 {
2957 VBoxVHWAColorKey ckey(pCmd->u.in.CKey.high, pCmd->u.in.CKey.low);
2958 pSurf->setSrcBltCKey(&ckey);
2959
2960 }
2961 if (pCmd->u.in.flags & VBOXVHWA_CKEY_SRCOVERLAY)
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
2970int VBoxVHWAImage::vhwaQueryInfo1(struct VBOXVHWACMD_QUERYINFO1 RT_UNTRUSTED_VOLATILE_GUEST *pCmd)
2971{
2972 VBOXQGLLOG_ENTER(("\n"));
2973 bool bEnabled = false;
2974 const VBoxVHWAInfo & info = vboxVHWAGetSupportInfo(NULL);
2975 if (info.isVHWASupported())
2976 {
2977 Assert(pCmd->u.in.guestVersion.maj == VBOXVHWA_VERSION_MAJ);
2978 if (pCmd->u.in.guestVersion.maj == VBOXVHWA_VERSION_MAJ)
2979 {
2980 Assert(pCmd->u.in.guestVersion.min == VBOXVHWA_VERSION_MIN);
2981 if (pCmd->u.in.guestVersion.min == VBOXVHWA_VERSION_MIN)
2982 {
2983 Assert(pCmd->u.in.guestVersion.bld == VBOXVHWA_VERSION_BLD);
2984 if (pCmd->u.in.guestVersion.bld == VBOXVHWA_VERSION_BLD)
2985 {
2986 Assert(pCmd->u.in.guestVersion.reserved == VBOXVHWA_VERSION_RSV);
2987 if (pCmd->u.in.guestVersion.reserved == VBOXVHWA_VERSION_RSV)
2988 {
2989 bEnabled = true;
2990 }
2991 }
2992 }
2993 }
2994 }
2995
2996 memset((void *)pCmd, 0, sizeof(VBOXVHWACMD_QUERYINFO1));
2997 if (bEnabled)
2998 {
2999 pCmd->u.out.cfgFlags = VBOXVHWA_CFG_ENABLED;
3000
3001 pCmd->u.out.caps =
3002 /* we do not support blitting for now */
3003// VBOXVHWA_CAPS_BLT | VBOXVHWA_CAPS_BLTSTRETCH | VBOXVHWA_CAPS_BLTQUEUE
3004// | VBOXVHWA_CAPS_BLTCOLORFILL not supported, although adding it is trivial
3005// | VBOXVHWA_CAPS_BLTFOURCC set below if shader support is available
3006 VBOXVHWA_CAPS_OVERLAY
3007 | VBOXVHWA_CAPS_OVERLAYSTRETCH
3008 | VBOXVHWA_CAPS_OVERLAYCANTCLIP
3009 // | VBOXVHWA_CAPS_OVERLAYFOURCC set below if shader support is available
3010 ;
3011
3012 /** @todo check if we could use DDSCAPS_ALPHA instead of colorkeying */
3013
3014 pCmd->u.out.caps2 = VBOXVHWA_CAPS2_CANRENDERWINDOWED
3015 | VBOXVHWA_CAPS2_WIDESURFACES;
3016
3017 /// @todo setup stretchCaps
3018 pCmd->u.out.stretchCaps = 0;
3019
3020 pCmd->u.out.numOverlays = 1;
3021 /** @todo set curOverlays properly */
3022 pCmd->u.out.curOverlays = 0;
3023
3024 pCmd->u.out.surfaceCaps = VBOXVHWA_SCAPS_PRIMARYSURFACE
3025#ifndef VBOXVHWA_ALLOW_PRIMARY_AND_OVERLAY_ONLY
3026 | VBOXVHWA_SCAPS_OFFSCREENPLAIN
3027#endif
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 ;
3037
3038 if (info.getGlInfo().isFragmentShaderSupported() && info.getGlInfo().getMultiTexNumSupported() >= 2)
3039 {
3040 pCmd->u.out.caps |= VBOXVHWA_CAPS_COLORKEY
3041 | VBOXVHWA_CAPS_COLORKEYHWASSIST;
3042
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;
3049
3050 if (info.getGlInfo().isTextureRectangleSupported())
3051 {
3052 pCmd->u.out.caps |= VBOXVHWA_CAPS_OVERLAYFOURCC
3053// | VBOXVHWA_CAPS_BLTFOURCC
3054 ;
3055
3056 pCmd->u.out.colorKeyCaps |= 0
3057// | VBOXVHWA_CKEYCAPS_SRCOVERLAYYUV
3058 | VBOXVHWA_CKEYCAPS_DESTOVERLAYYUV;
3059
3060// pCmd->u.out.caps2 |= VBOXVHWA_CAPS2_COPYFOURCC;
3061
3062 pCmd->u.out.numFourCC = mSettings->getIntersection(info, 0, NULL);
3063 }
3064 }
3065 }
3066
3067 return VINF_SUCCESS;
3068}
3069
3070int VBoxVHWAImage::vhwaQueryInfo2(struct VBOXVHWACMD_QUERYINFO2 RT_UNTRUSTED_VOLATILE_GUEST *pCmd)
3071{
3072 VBOXQGLLOG_ENTER(("\n"));
3073
3074 const VBoxVHWAInfo &info = vboxVHWAGetSupportInfo(NULL);
3075 uint32_t aFourcc[VBOXVHWA_NUMFOURCC];
3076 int num = mSettings->getIntersection(info, VBOXVHWA_NUMFOURCC, aFourcc);
3077 Assert(pCmd->numFourCC >= (uint32_t)num);
3078 if (pCmd->numFourCC < (uint32_t)num)
3079 return VERR_GENERAL_FAILURE;
3080
3081 pCmd->numFourCC = (uint32_t)num;
3082 memcpy((void *)&pCmd->FourCC[0], aFourcc, num * sizeof(aFourcc[0]));
3083 return VINF_SUCCESS;
3084}
3085
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//}
3098
3099int VBoxVHWAImage::vhwaSaveSurface(struct SSMHANDLE *pSSM, VBoxVHWASurfaceBase *pSurf, uint32_t surfCaps)
3100{
3101 VBOXQGL_SAVE_SURFSTART(pSSM);
3102
3103 uint64_t u64 = vboxVRAMOffset(pSurf);
3104 int rc;
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
3111 uint32_t flags = 0;
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)
3117 flags |= VBOXVHWA_SD_CKDESTBLT;
3118 if (pSrcBltCKey)
3119 flags |= VBOXVHWA_SD_CKSRCBLT;
3120 if (pDstOverlayCKey)
3121 flags |= VBOXVHWA_SD_CKDESTOVERLAY;
3122 if (pSrcOverlayCKey)
3123 flags |= VBOXVHWA_SD_CKSRCOVERLAY;
3124 rc = SSMR3PutU32(pSSM, flags);
3125
3126 if (pDstBltCKey)
3127 {
3128 rc = SSMR3PutU32(pSSM, pDstBltCKey->lower());
3129 rc = SSMR3PutU32(pSSM, pDstBltCKey->upper());
3130 }
3131 if (pSrcBltCKey)
3132 {
3133 rc = SSMR3PutU32(pSSM, pSrcBltCKey->lower());
3134 rc = SSMR3PutU32(pSSM, pSrcBltCKey->upper());
3135 }
3136 if (pDstOverlayCKey)
3137 {
3138 rc = SSMR3PutU32(pSSM, pDstOverlayCKey->lower());
3139 rc = SSMR3PutU32(pSSM, pDstOverlayCKey->upper());
3140 }
3141 if (pSrcOverlayCKey)
3142 {
3143 rc = SSMR3PutU32(pSSM, pSrcOverlayCKey->lower());
3144 rc = SSMR3PutU32(pSSM, pSrcOverlayCKey->upper());
3145 }
3146 AssertRCReturn(rc, rc);
3147
3148 const VBoxVHWAColorFormat & format = pSurf->pixelFormat();
3149 flags = 0;
3150 if (format.fourcc())
3151 {
3152 flags |= VBOXVHWA_PF_FOURCC;
3153 rc = SSMR3PutU32(pSSM, flags);
3154 rc = SSMR3PutU32(pSSM, format.fourcc());
3155 }
3156 else
3157 {
3158 flags |= VBOXVHWA_PF_RGB;
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());
3165 }
3166 AssertRCReturn(rc, rc);
3167
3168 VBOXQGL_SAVE_SURFSTOP(pSSM);
3169 return rc;
3170}
3171
3172int VBoxVHWAImage::vhwaLoadSurface(VHWACommandList * pCmdList, struct SSMHANDLE * pSSM, uint32_t cBackBuffers, uint32_t u32Version)
3173{
3174 Q_UNUSED(u32Version);
3175
3176 VBOXQGL_LOAD_SURFSTART(pSSM);
3177
3178 char *buf = (char*)malloc(VBOXVHWACMD_SIZE(VBOXVHWACMD_SURF_CREATE));
3179 memset(buf, 0, sizeof(VBOXVHWACMD_SIZE(VBOXVHWACMD_SURF_CREATE)));
3180 VBOXVHWACMD *pCmd = (VBOXVHWACMD *)buf;
3181 pCmd->enmCmd = VBOXVHWACMD_TYPE_SURF_CREATE;
3182 pCmd->Flags = VBOXVHWACMD_FLAG_HH_CMD;
3183
3184 VBOXVHWACMD_SURF_CREATE *pCreateSurf = VBOXVHWACMD_BODY_HOST_HEAP(pCmd, VBOXVHWACMD_SURF_CREATE);
3185 int rc;
3186 uint32_t u32;
3187 rc = SSMR3GetU32(pSSM, &u32); AssertRC(rc);
3188 pCreateSurf->SurfInfo.hSurf = (VBOXVHWA_SURFHANDLE)u32;
3189 if (RT_SUCCESS(rc))
3190 {
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)
3197 {
3198 rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.DstBltCK.low); AssertRC(rc);
3199 rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.DstBltCK.high); AssertRC(rc);
3200 }
3201 if (pCreateSurf->SurfInfo.flags & VBOXVHWA_SD_CKSRCBLT)
3202 {
3203 rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.SrcBltCK.low); AssertRC(rc);
3204 rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.SrcBltCK.high); AssertRC(rc);
3205 }
3206 if (pCreateSurf->SurfInfo.flags & VBOXVHWA_SD_CKDESTOVERLAY)
3207 {
3208 rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.DstOverlayCK.low); AssertRC(rc);
3209 rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.DstOverlayCK.high); AssertRC(rc);
3210 }
3211 if (pCreateSurf->SurfInfo.flags & VBOXVHWA_SD_CKSRCOVERLAY)
3212 {
3213 rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.SrcOverlayCK.low); AssertRC(rc);
3214 rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.SrcOverlayCK.high); AssertRC(rc);
3215 }
3216
3217 rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.PixelFormat.flags); AssertRC(rc);
3218 if (pCreateSurf->SurfInfo.PixelFormat.flags & VBOXVHWA_PF_RGB)
3219 {
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);
3225 }
3226 else if (pCreateSurf->SurfInfo.PixelFormat.flags & VBOXVHWA_PF_FOURCC)
3227 {
3228 rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.PixelFormat.fourCC);
3229 AssertRC(rc);
3230 }
3231 else
3232 {
3233 AssertFailed();
3234 }
3235 AssertRCReturnStmt(rc, free(buf), rc);
3236
3237 if (cBackBuffers)
3238 {
3239 pCreateSurf->SurfInfo.cBackBuffers = cBackBuffers;
3240 pCreateSurf->SurfInfo.surfCaps |= VBOXVHWA_SCAPS_COMPLEX;
3241 }
3242
3243 pCmdList->push_back(pCmd);
3244// vboxExecOnResize(&VBoxVHWAImage::vboxDoVHWACmdAndFree, pCmd); AssertRC(rc);
3245// if (RT_SUCCESS(rc))
3246// {
3247// rc = pCmd->rc;
3248// AssertRC(rc);
3249// }
3250 }
3251 else
3252 free(buf);
3253
3254 VBOXQGL_LOAD_SURFSTOP(pSSM);
3255
3256 return rc;
3257}
3258
3259int VBoxVHWAImage::vhwaSaveOverlayData(struct SSMHANDLE * pSSM, VBoxVHWASurfaceBase *pSurf, bool bVisible)
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
3271 if (bVisible)
3272 {
3273 flags |= VBOXVHWA_OVER_SHOW;
3274 }
3275 else
3276 {
3277 flags |= VBOXVHWA_OVER_HIDE;
3278 }
3279
3280 if (!dstCKey)
3281 {
3282 flags |= VBOXVHWA_OVER_KEYDEST;
3283 }
3284 else if (defaultDstCKey)
3285 {
3286 flags |= VBOXVHWA_OVER_KEYDESTOVERRIDE;
3287 bSaveDstCKey = true;
3288 }
3289
3290 if (srcCKey == defaultSrcCKey)
3291 {
3292 flags |= VBOXVHWA_OVER_KEYSRC;
3293 }
3294 else if (srcCKey)
3295 {
3296 flags |= VBOXVHWA_OVER_KEYSRCOVERRIDE;
3297 bSaveSrcCKey = true;
3298 }
3299
3300 int rc = SSMR3PutU32(pSSM, flags);
3301
3302 rc = SSMR3PutU32(pSSM, mDisplay.getPrimary()->handle());
3303 rc = SSMR3PutU32(pSSM, pSurf->handle());
3304
3305 if (bSaveDstCKey)
3306 {
3307 rc = SSMR3PutU32(pSSM, dstCKey->lower());
3308 rc = SSMR3PutU32(pSSM, dstCKey->upper());
3309 }
3310 if (bSaveSrcCKey)
3311 {
3312 rc = SSMR3PutU32(pSSM, srcCKey->lower());
3313 rc = SSMR3PutU32(pSSM, srcCKey->upper());
3314 }
3315
3316 int x1, x2, y1, y2;
3317 pSurf->targRect().getCoords(&x1, &y1, &x2, &y2);
3318 rc = SSMR3PutS32(pSSM, x1);
3319 rc = SSMR3PutS32(pSSM, x2+1);
3320 rc = SSMR3PutS32(pSSM, y1);
3321 rc = SSMR3PutS32(pSSM, y2+1);
3322
3323 pSurf->srcRect().getCoords(&x1, &y1, &x2, &y2);
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);
3329
3330 VBOXQGL_SAVE_OVERLAYSTOP(pSSM);
3331
3332 return rc;
3333}
3334
3335int VBoxVHWAImage::vhwaLoadOverlayData(VHWACommandList *pCmdList, struct SSMHANDLE *pSSM, uint32_t u32Version)
3336{
3337 Q_UNUSED(u32Version);
3338
3339 VBOXQGL_LOAD_OVERLAYSTART(pSSM);
3340
3341 char *buf = new char[VBOXVHWACMD_SIZE(VBOXVHWACMD_SURF_CREATE)];
3342 memset(buf, 0, VBOXVHWACMD_SIZE(VBOXVHWACMD_SURF_CREATE));
3343 VBOXVHWACMD * pCmd = (VBOXVHWACMD*)buf;
3344 pCmd->enmCmd = VBOXVHWACMD_TYPE_SURF_OVERLAY_UPDATE;
3345 pCmd->Flags = VBOXVHWACMD_FLAG_HH_CMD;
3346
3347 VBOXVHWACMD_SURF_OVERLAY_UPDATE *pUpdateOverlay = VBOXVHWACMD_BODY_HOST_HEAP(pCmd, VBOXVHWACMD_SURF_OVERLAY_UPDATE);
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
3360 if (pUpdateOverlay->u.in.flags & VBOXVHWA_OVER_KEYDESTOVERRIDE)
3361 {
3362 rc = SSMR3GetU32(pSSM, &pUpdateOverlay->u.in.desc.DstCK.low); AssertRC(rc);
3363 rc = SSMR3GetU32(pSSM, &pUpdateOverlay->u.in.desc.DstCK.high); AssertRC(rc);
3364 }
3365
3366 if (pUpdateOverlay->u.in.flags & VBOXVHWA_OVER_KEYSRCOVERRIDE)
3367 {
3368 rc = SSMR3GetU32(pSSM, &pUpdateOverlay->u.in.desc.SrcCK.low); AssertRC(rc);
3369 rc = SSMR3GetU32(pSSM, &pUpdateOverlay->u.in.desc.SrcCK.high); AssertRC(rc);
3370 }
3371
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);
3375 rc = SSMR3GetS32(pSSM, &pUpdateOverlay->u.in.dstRect.bottom); AssertRC(rc);
3376
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);
3382
3383 pCmdList->push_back(pCmd);
3384 }
3385
3386 VBOXQGL_LOAD_OVERLAYSTOP(pSSM);
3387
3388 return rc;
3389}
3390
3391void VBoxVHWAImage::vhwaSaveExecVoid(struct SSMHANDLE *pSSM)
3392{
3393 VBOXQGL_SAVE_START(pSSM);
3394 SSMR3PutU32(pSSM, 0); /* 0 primaries */
3395 VBOXQGL_SAVE_STOP(pSSM);
3396}
3397
3398void VBoxVHWAImage::vhwaSaveExec(struct SSMHANDLE *pSSM)
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();
3421 if ( cPrimary
3422 && ( mDisplay.getVGA() == NULL
3423 || mDisplay.getVGA()->handle() == VBOXVHWA_SURFHANDLE_INVALID))
3424 {
3425 cPrimary -= 1;
3426 }
3427
3428 int rc = SSMR3PutU32(pSSM, cPrimary);
3429 AssertRCReturnVoid(rc);
3430 if (cPrimary)
3431 {
3432 for (SurfList::const_iterator pr = primaryList.begin(); pr != primaryList.end(); ++ pr)
3433 {
3434 VBoxVHWASurfaceBase *pSurf = *pr;
3435 // bool bVga = (pSurf == mDisplay.getVGA());
3436 bool bVisible = (pSurf == mDisplay.getPrimary());
3437 uint32_t flags = VBOXVHWA_SCAPS_PRIMARYSURFACE;
3438 if (bVisible)
3439 flags |= VBOXVHWA_SCAPS_VISIBLE;
3440
3441 if (pSurf->handle() != VBOXVHWA_SURFHANDLE_INVALID)
3442 {
3443 rc = vhwaSaveSurface(pSSM, *pr, flags);
3444#ifdef DEBUG
3445 --cPrimary;
3446 Assert(cPrimary < UINT32_MAX / 2);
3447#endif
3448 }
3449 else
3450 {
3451 Assert(pSurf == mDisplay.getVGA());
3452 }
3453 }
3454
3455#ifdef DEBUG
3456 Assert(!cPrimary);
3457#endif
3458
3459 const OverlayList & overlays = mDisplay.overlays();
3460 rc = SSMR3PutU32(pSSM, (uint32_t)overlays.size());
3461
3462 for (OverlayList::const_iterator it = overlays.begin(); it != overlays.end(); ++ it)
3463 {
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;
3468 if (cSurfs > 1)
3469 flags |= VBOXVHWA_SCAPS_COMPLEX;
3470 rc = SSMR3PutU32(pSSM, cSurfs);
3471 for (SurfList::const_iterator sit = surfaces.begin(); sit != surfaces.end(); ++ sit)
3472 rc = vhwaSaveSurface(pSSM, *sit, flags);
3473
3474 bool bVisible = true;
3475 VBoxVHWASurfaceBase * pOverlayData = pSurfList->current();
3476 if (!pOverlayData)
3477 {
3478 pOverlayData = surfaces.front();
3479 bVisible = false;
3480 }
3481
3482 rc = vhwaSaveOverlayData(pSSM, pOverlayData, bVisible);
3483 }
3484 }
3485
3486 VBOXQGL_SAVE_STOP(pSSM);
3487}
3488
3489int VBoxVHWAImage::vhwaLoadVHWAEnable(VHWACommandList * pCmdList)
3490{
3491 char *buf = (char *)malloc(sizeof(VBOXVHWACMD));
3492 Assert(buf);
3493 if (buf)
3494 {
3495 memset(buf, 0, sizeof(VBOXVHWACMD));
3496 VBOXVHWACMD *pCmd = (VBOXVHWACMD *)buf;
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
3506int VBoxVHWAImage::vhwaLoadExec(VHWACommandList *pCmdList, struct SSMHANDLE * pSSM, uint32_t u32Version)
3507{
3508 VBOXQGL_LOAD_START(pSSM);
3509
3510 if (u32Version > VBOXQGL_STATE_VERSION)
3511 return VERR_VERSION_MISMATCH;
3512
3513 int rc;
3514 uint32_t u32;
3515
3516 rc = vhwaLoadVHWAEnable(pCmdList); AssertRC(rc);
3517 if (RT_SUCCESS(rc))
3518 {
3519 rc = SSMR3GetU32(pSSM, &u32); AssertRC(rc);
3520 if (RT_SUCCESS(rc))
3521 {
3522 if (u32Version == 1U && u32 == UINT32_MAX) /* work around the v1 bug */
3523 u32 = 0;
3524 if (u32)
3525 {
3526 for (uint32_t i = 0; i < u32; ++i)
3527 {
3528 rc = vhwaLoadSurface(pCmdList, pSSM, 0, u32Version);
3529 AssertRCBreak(rc);
3530 }
3531
3532 if (RT_SUCCESS(rc))
3533 {
3534 rc = SSMR3GetU32(pSSM, &u32); AssertRC(rc);
3535 if (RT_SUCCESS(rc))
3536 {
3537 for (uint32_t i = 0; i < u32; ++i)
3538 {
3539 uint32_t cSurfs;
3540 rc = SSMR3GetU32(pSSM, &cSurfs); AssertRC(rc);
3541 for (uint32_t j = 0; j < cSurfs; ++j)
3542 {
3543 rc = vhwaLoadSurface(pCmdList, pSSM, cSurfs - 1, u32Version);
3544 AssertRCBreak(rc);
3545 }
3546
3547 if (RT_SUCCESS(rc))
3548 {
3549 rc = vhwaLoadOverlayData(pCmdList, pSSM, u32Version);
3550 AssertRCBreak(rc);
3551 }
3552 else
3553 break;
3554 }
3555 }
3556 }
3557 }
3558#ifdef VBOXQGL_STATE_DEBUG
3559 else if (u32Version == 1) /* read the 0 overlay count to ensure the following VBOXQGL_LOAD_STOP succeeds */
3560 {
3561 rc = SSMR3GetU32(pSSM, &u32);
3562 AssertRC(rc);
3563 Assert(u32 == 0 || RT_FAILURE(rc));
3564 }
3565#endif
3566 }
3567 }
3568
3569 VBOXQGL_LOAD_STOP(pSSM);
3570
3571 return rc;
3572}
3573
3574int VBoxVHWAImage::vhwaConstruct(struct VBOXVHWACMD_HH_CONSTRUCT *pCmd)
3575{
3576// PVM pVM = (PVM)pCmd->pVM;
3577// uint32_t intsId = 0; /** @todo set the proper id */
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;
3604}
3605
3606uchar *VBoxVHWAImage::vboxVRAMAddressFromOffset(uint64_t offset)
3607{
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;
3613}
3614
3615uint64_t VBoxVHWAImage::vboxVRAMOffsetFromAddress(uchar *addr)
3616{
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;
3621}
3622
3623uint64_t VBoxVHWAImage::vboxVRAMOffset(VBoxVHWASurfaceBase *pSurf)
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;
3633VBoxVHWASurfaceBase *g_apSurf[] = {NULL, NULL, NULL};
3634
3635void VBoxVHWAImage::vboxDoTestSurfaces(void *context)
3636{
3637 if (g_iCur >= RT_ELEMENTS(g_apSurf))
3638 g_iCur = 0;
3639 VBoxVHWASurfaceBase * pSurf1 = g_apSurf[g_iCur];
3640 if (pSurf1)
3641 pSurf1->getComplexList()->setCurrentVisible(pSurf1);
3642}
3643#endif
3644
3645void VBoxVHWAImage::vboxDoUpdateViewport(const QRect & aRect)
3646{
3647 adjustViewport(mDisplay.getPrimary()->size(), aRect);
3648 mViewport = aRect;
3649
3650 const SurfList &primaryList = mDisplay.primaries().surfaces();
3651
3652 for (SurfList::const_iterator pr = primaryList.begin(); pr != primaryList.end(); ++pr)
3653 {
3654 VBoxVHWASurfaceBase *pSurf = *pr;
3655 pSurf->updateVisibility(NULL, aRect, false, false);
3656 }
3657
3658 const OverlayList & overlays = mDisplay.overlays();
3659 QRect overInter = overlaysRectIntersection();
3660 overInter = overInter.intersected(aRect);
3661
3662 bool bDisplayPrimary = true;
3663
3664 for (OverlayList::const_iterator it = overlays.begin(); it != overlays.end(); ++it)
3665 {
3666 VBoxVHWASurfList *pSurfList = *it;
3667 const SurfList &surfaces = pSurfList->surfaces();
3668 if (surfaces.size())
3669 {
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 }
3680 }
3681 }
3682
3683 Assert(!bDisplayPrimary);
3684 mDisplay.setDisplayPrimary(bDisplayPrimary);
3685}
3686
3687bool VBoxVHWAImage::hasSurfaces() const
3688{
3689 if (mDisplay.overlays().size() != 0)
3690 return true;
3691 if (mDisplay.primaries().size() > 1)
3692 return true;
3693 /* in case gl was never turned on, we have no surfaces at all including VGA */
3694 if (!mDisplay.getVGA())
3695 return false;
3696 return mDisplay.getVGA()->handle() != VBOXVHWA_SURFHANDLE_INVALID;
3697}
3698
3699bool VBoxVHWAImage::hasVisibleOverlays()
3700{
3701 const OverlayList &overlays = mDisplay.overlays();
3702 for (OverlayList::const_iterator it = overlays.begin(); it != overlays.end(); ++ it)
3703 {
3704 VBoxVHWASurfList * pSurfList = *it;
3705 if (pSurfList->current() != NULL)
3706 return true;
3707 }
3708 return false;
3709}
3710
3711QRect VBoxVHWAImage::overlaysRectUnion()
3712{
3713 const OverlayList &overlays = mDisplay.overlays();
3714 VBoxVHWADirtyRect un;
3715 for (OverlayList::const_iterator it = overlays.begin(); it != overlays.end(); ++ it)
3716 {
3717 VBoxVHWASurfaceBase *pOverlay = (*it)->current();
3718 if (pOverlay != NULL)
3719 un.add(pOverlay->targRect());
3720 }
3721 return un.toRect();
3722}
3723
3724QRect VBoxVHWAImage::overlaysRectIntersection()
3725{
3726 const OverlayList &overlays = mDisplay.overlays();
3727 QRect rect;
3728 VBoxVHWADirtyRect un;
3729 for (OverlayList::const_iterator it = overlays.begin(); it != overlays.end(); ++ it)
3730 {
3731 VBoxVHWASurfaceBase *pOverlay = (*it)->current();
3732 if (pOverlay != NULL)
3733 {
3734 if (rect.isNull())
3735 rect = pOverlay->targRect();
3736 else
3737 {
3738 rect = rect.intersected(pOverlay->targRect());
3739 if (rect.isNull())
3740 break;
3741 }
3742 }
3743 }
3744 return rect;
3745}
3746
3747void VBoxVHWAImage::vboxDoUpdateRect(const QRect *pRect)
3748{
3749 mDisplay.getPrimary()->updatedMem(pRect);
3750}
3751
3752void VBoxVHWAImage::resize(const VBoxFBSizeInfo &size)
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",
3762 size.pixelFormat(), size.VRAM(),
3763 size.bitsPerPixel(), size.bytesPerLine(),
3764 size.width(), size.height()));
3765
3766 /* clean the old values first */
3767
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. */
3774
3775 /* check if we support the pixel format and can use the guest VRAM directly */
3776 if (size.pixelFormat() == KBitmapFormat_BGR)
3777 {
3778
3779 bitsPerPixel = size.bitsPerPixel();
3780 bytesPerLine = size.bytesPerLine();
3781 ulong bitsPerLine = bytesPerLine * 8;
3782
3783 switch (bitsPerPixel)
3784 {
3785 case 32:
3786 break;
3787 case 24:
3788#ifdef DEBUG_misha
3789 AssertFailed();
3790#endif
3791 break;
3792 case 8:
3793#ifdef DEBUG_misha
3794 AssertFailed();
3795#endif
3796 g = b = 0;
3797 remind = true;
3798 break;
3799 case 1:
3800#ifdef DEBUG_misha
3801 AssertFailed();
3802#endif
3803 r = 1;
3804 g = b = 0;
3805 remind = true;
3806 break;
3807 default:
3808#ifdef DEBUG_misha
3809 AssertFailed();
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... */
3819 Assert ((size.bytesPerLine() & 3) == 0);
3820 fallback = ((size.bytesPerLine() & 3) != 0);
3821 Assert(!fallback);
3822 }
3823 if (!fallback)
3824 {
3825 /* ...and the scan lines ought to be a whole number of pixels. */
3826 Assert ((bitsPerLine & (size.bitsPerPixel() - 1)) == 0);
3827 fallback = ((bitsPerLine & (size.bitsPerPixel() - 1)) != 0);
3828 Assert(!fallback);
3829 }
3830 if (!fallback)
3831 {
3832 // ulong virtWdt = bitsPerLine / size.bitsPerPixel();
3833 fUsesGuestVram = true;
3834 }
3835 }
3836 else
3837 {
3838 AssertFailed();
3839 fallback = true;
3840 }
3841
3842 if (fallback)
3843 {
3844 /* we should never come to fallback more now */
3845 AssertFailed();
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;
3852 bytesPerLine = size.width() * bitsPerPixel / 8;
3853 fUsesGuestVram = false;
3854 }
3855
3856 ulong bytesPerPixel = bitsPerPixel / 8;
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();
3860
3861#ifdef VBOXQGL_DBG_SURF
3862 for (int i = 0; i < RT_ELEMENTS(g_apSurf); i++)
3863 {
3864 VBoxVHWASurfaceBase * pSurf1 = g_apSurf[i];
3865 if (pSurf1)
3866 {
3867 VBoxVHWASurfList *pConstructingList = pSurf1->getComplexList();
3868 delete pSurf1;
3869 if (pConstructingList)
3870 delete pConstructingList;
3871 }
3872 }
3873#endif
3874
3875 VBoxVHWASurfaceBase *pDisplay = mDisplay.setVGA(NULL);
3876 if (pDisplay)
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,
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,
3890#ifdef VBOXVHWA_USE_TEXGROUP
3891 0,
3892#endif
3893 0 /* VBOXVHWAIMG_TYPE fFlags */);
3894 pDisplay->init(NULL, fUsesGuestVram ? size.VRAM() : NULL);
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);
3899 setupMatricies(dispSize, true);
3900
3901#ifdef VBOXQGL_DBG_SURF
3902 {
3903 uint32_t width = 100;
3904 uint32_t height = 60;
3905
3906 for (int i = 0; i < RT_ELEMENTS(g_apSurf); i++)
3907 {
3908 VBoxVHWAColorFormat tmpFormat(FOURCC_YV12);
3909 QSize tmpSize(width, height) ;
3910 VBoxVHWASurfaceBase *pSurf1 = new VBoxVHWASurfaceBase(this, tmpSize,
3911 mDisplay.getPrimary()->rect(),
3912 QRect(0, 0, width, height),
3913 mViewport,
3914 tmpFormat,
3915 NULL, NULL, NULL, &VBoxVHWAColorKey(0,0),
3916#ifdef VBOXVHWA_USE_TEXGROUP
3917 0,
3918#endif
3919 false);
3920
3921 Assert(mDisplay.getVGA());
3922 pSurf1->init(mDisplay.getVGA(), NULL);
3923 uchar *addr = pSurf1->address();
3924 uchar cur = 0;
3925 for (uint32_t k = 0; k < width*height; k++)
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;
3943 updateCmd.u.in.flags = VBOXVHWA_OVER_SHOW
3944 | VBOXVHWA_OVER_KEYDESTOVERRIDE;
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();
3951 updateCmd.u.in.dstRect.top = (pDisplay->height() - height) / 2;
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
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 */
3961
3962 vhwaSurfaceOverlayUpdate(&updateCmd);
3963 }
3964#endif
3965
3966// if (!mOnResizeCmdList.empty())
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// }
3977
3978 if (remind)
3979 popupCenter().remindAboutWrongColorDepth(windowManager().mainWindowShown(), size.bitsPerPixel(), 32);
3980 else
3981 popupCenter().forgetAboutWrongColorDepth(windowManager().mainWindowShown());
3982}
3983
3984VBoxVHWAColorFormat::VBoxVHWAColorFormat (uint32_t bitsPerPixel, uint32_t r, uint32_t g, uint32_t b)
3985 : mWidthCompression(1)
3986 , mHeightCompression(1)
3987{
3988 init(bitsPerPixel, r, g, b);
3989}
3990
3991VBoxVHWAColorFormat::VBoxVHWAColorFormat(uint32_t fourcc)
3992 : mWidthCompression(1)
3993 , mHeightCompression(1)
3994{
3995 init(fourcc);
3996}
3997
3998void VBoxVHWAColorFormat::init(uint32_t fourcc)
3999{
4000 mDataFormat = fourcc;
4001 mInternalFormat = GL_RGBA8;//GL_RGB;
4002 mFormat = GL_BGRA_EXT;//GL_RGBA;
4003 mType = GL_UNSIGNED_BYTE;
4004 mR = VBoxVHWAColorComponent(0xff);
4005 mG = VBoxVHWAColorComponent(0xff);
4006 mB = VBoxVHWAColorComponent(0xff);
4007 mA = VBoxVHWAColorComponent(0xff);
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:
4026 AssertFailed();
4027 mBitsPerPixel = 0;
4028 mBitsPerPixelTex = 0;
4029 mWidthCompression = 0;
4030 break;
4031 }
4032}
4033
4034void VBoxVHWAColorFormat::init(uint32_t bitsPerPixel, uint32_t r, uint32_t g, uint32_t b)
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;
4045 mR = VBoxVHWAColorComponent(r);
4046 mG = VBoxVHWAColorComponent(g);
4047 mB = VBoxVHWAColorComponent(b);
4048 break;
4049 case 24:
4050#ifdef DEBUG_misha
4051 AssertFailed();
4052#endif
4053 mInternalFormat = 3;//GL_RGB;
4054 mFormat = GL_BGR_EXT;
4055 mType = GL_UNSIGNED_BYTE;
4056 mR = VBoxVHWAColorComponent(r);
4057 mG = VBoxVHWAColorComponent(g);
4058 mB = VBoxVHWAColorComponent(b);
4059 break;
4060 case 16:
4061#ifdef DEBUG_misha
4062 AssertFailed();
4063#endif
4064 mInternalFormat = GL_RGB5;
4065 mFormat = GL_BGR_EXT;
4066 mType = GL_UNSIGNED_BYTE; /** @todo ??? */
4067 mR = VBoxVHWAColorComponent(r);
4068 mG = VBoxVHWAColorComponent(g);
4069 mB = VBoxVHWAColorComponent(b);
4070 break;
4071 case 8:
4072#ifdef DEBUG_misha
4073 AssertFailed();
4074#endif
4075 mInternalFormat = 1;//GL_RGB;
4076 mFormat = GL_RED;//GL_RGB;
4077 mType = GL_UNSIGNED_BYTE;
4078 mR = VBoxVHWAColorComponent(0xff);
4079 break;
4080 case 1:
4081#ifdef DEBUG_misha
4082 AssertFailed();
4083#endif
4084 mInternalFormat = 1;
4085 mFormat = GL_COLOR_INDEX;
4086 mType = GL_BITMAP;
4087 mR = VBoxVHWAColorComponent(0x1);
4088 break;
4089 default:
4090#ifdef DEBUG_misha
4091 AssertFailed();
4092#endif
4093 mBitsPerPixel = 0;
4094 mBitsPerPixelTex = 0;
4095 break;
4096 }
4097}
4098
4099bool VBoxVHWAColorFormat::equals(const VBoxVHWAColorFormat &other) const
4100{
4101 if (fourcc())
4102 return fourcc() == other.fourcc();
4103 if (other.fourcc())
4104 return false;
4105
4106 return bitsPerPixel() == other.bitsPerPixel();
4107}
4108
4109VBoxVHWAColorComponent::VBoxVHWAColorComponent (uint32_t aMask)
4110{
4111 unsigned f = ASMBitFirstSetU32(aMask);
4112 if (f)
4113 {
4114 mOffset = f - 1;
4115 f = ASMBitFirstSetU32(~(aMask >> mOffset));
4116 if (f)
4117 mcBits = f - 1;
4118 else
4119 mcBits = 32 - mOffset;
4120
4121 Assert(mcBits);
4122 mMask = (((uint32_t)0xffffffff) >> (32 - mcBits)) << mOffset;
4123 Assert(mMask == aMask);
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
4136void VBoxVHWAColorFormat::pixel2Normalized(uint32_t pix, float *r, float *g, float *b) const
4137{
4138 *r = mR.colorValNorm(pix);
4139 *g = mG.colorValNorm(pix);
4140 *b = mB.colorValNorm(pix);
4141}
4142
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)
4158{
4159 /* postpone the gl widget initialization to avoid conflict with 3D on Mac */
4160}
4161
4162void VBoxQGLOverlay::init(QWidget *pViewport, QObject *pPostEventObject, CSession *aSession, uint32_t id)
4163{
4164 mpViewport = pViewport;
4165 mpSession = aSession;
4166 m_id = id;
4167 mSettings.init(*aSession);
4168 mCmdPipe.init(pPostEventObject);
4169}
4170
4171class VBoxGLShareWgt : public QGLWidget
4172{
4173public:
4174 VBoxGLShareWgt()
4175 : QGLWidget(new VBoxGLContext(VBoxVHWAImage::vboxGLFormat()))
4176 {
4177 /* work-around to disable done current needed to old ATI drivers on Linux */
4178 VBoxGLContext *pc = (VBoxGLContext *)context();
4179 pc->allowDoneCurrent(false);
4180 }
4181
4182protected:
4183 void initializeGL()
4184 {
4185 vboxVHWAGetSupportInfo(context());
4186 VBoxVHWASurfaceBase::globalInit();
4187 }
4188};
4189void VBoxQGLOverlay::initGl()
4190{
4191 if (mpOverlayWgt)
4192 {
4193 Assert(mpShareWgt);
4194 return;
4195 }
4196
4197 if (!mpShareWgt)
4198 {
4199 mpShareWgt = new VBoxGLShareWgt();
4200 /* force initializeGL */
4201 mpShareWgt->updateGL();
4202 }
4203
4204 mOverlayImage.init(&mSettings);
4205 mpOverlayWgt = new VBoxGLWgt(&mOverlayImage, mpViewport, mpShareWgt);
4206
4207 mOverlayWidgetVisible = true; /* to ensure it is set hidden with vboxShowOverlay */
4208 vboxShowOverlay(false);
4209
4210 mpOverlayWgt->setMouseTracking(true);
4211}
4212
4213void VBoxQGLOverlay::updateAttachment(QWidget *pViewport, QObject *pPostEventObject)
4214{
4215 if (mpViewport != pViewport)
4216 {
4217 mpViewport = pViewport;
4218 mpOverlayWgt = NULL;
4219 mOverlayWidgetVisible = false;
4220 if (mOverlayImage.hasSurfaces())
4221 {
4222// Assert(!mOverlayVisible);
4223 if (pViewport)
4224 {
4225 initGl();
4226// vboxDoCheckUpdateViewport();
4227 }
4228// Assert(!mOverlayVisible);
4229 }
4230 mGlCurrent = false;
4231 }
4232 mCmdPipe.setNotifyObject(pPostEventObject);
4233}
4234
4235int VBoxQGLOverlay::reset()
4236{
4237 CDisplay display = mpSession->GetConsole().GetDisplay();
4238 Assert (!display.isNull());
4239
4240 mCmdPipe.reset(&display);
4241
4242 resetGl();
4243
4244 return VINF_SUCCESS;
4245}
4246
4247static DECLCALLBACK(void) vbvaVHWAHHCommandFreeCmd(void *pvContext)
4248{
4249 free(pvContext);
4250}
4251
4252int VBoxQGLOverlay::resetGl()
4253{
4254 VHWACommandList list;
4255 int rc = mOverlayImage.reset(&list);
4256 AssertRC(rc);
4257 if (RT_SUCCESS(rc))
4258 {
4259 for (VHWACommandList::const_iterator sIt = list.begin(); sIt != list.end(); ++ sIt)
4260 {
4261 VBOXVHWACMD *pCmd = (*sIt);
4262 VBOXVHWA_HH_CALLBACK_SET(pCmd, vbvaVHWAHHCommandFreeCmd, pCmd);
4263 mCmdPipe.postCmd(VBOXVHWA_PIPECMD_VHWA, pCmd, pCmd->enmCmd, false /*fGuestCmd*/);
4264 }
4265 }
4266 return VINF_SUCCESS;
4267}
4268
4269int VBoxQGLOverlay::onVHWACommand(struct VBOXVHWACMD RT_UNTRUSTED_VOLATILE_GUEST *pCmd,
4270 int /*VBOXVHWACMD_TYPE*/ enmCmdInt, bool fGuestCmd)
4271{
4272 VBOXVHWACMD_TYPE const enmCmd = (VBOXVHWACMD_TYPE)enmCmdInt;
4273 Log(("VHWA Command >>> %#p, %d\n", pCmd, enmCmd));
4274 switch (enmCmd)
4275 {
4276 case VBOXVHWACMD_TYPE_SURF_FLIP:
4277 case VBOXVHWACMD_TYPE_SURF_OVERLAY_UPDATE:
4278 case VBOXVHWACMD_TYPE_SURF_OVERLAY_SETPOSITION:
4279 break;
4280 case VBOXVHWACMD_TYPE_HH_CONSTRUCT:
4281 {
4282 pCmd->Flags &= ~VBOXVHWACMD_FLAG_HG_ASYNCH;
4283 ASSERT_GUEST_STMT_RETURN(!fGuestCmd, pCmd->rc = VERR_ACCESS_DENIED, VINF_SUCCESS);
4284 VBOXVHWACMD_HH_CONSTRUCT *pBody = VBOXVHWACMD_BODY_HOST_HEAP(pCmd, VBOXVHWACMD_HH_CONSTRUCT);
4285 pCmd->rc = vhwaConstruct(pBody);
4286 Log(("VHWA Command <<< Sync %#p, %d\n", pCmd, enmCmd));
4287 return VINF_SUCCESS;
4288 }
4289
4290 case VBOXVHWACMD_TYPE_HH_RESET:
4291 {
4292 pCmd->Flags &= ~VBOXVHWACMD_FLAG_HG_ASYNCH;
4293 ASSERT_GUEST_STMT_RETURN(!fGuestCmd, pCmd->rc = VERR_ACCESS_DENIED, VINF_SUCCESS);
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();
4297 Log(("VHWA Command <<< Sync %#p, %d\n", pCmd, enmCmd));
4298 return VINF_SUCCESS;
4299 }
4300
4301 case VBOXVHWACMD_TYPE_HH_ENABLE:
4302 pCmd->Flags &= ~VBOXVHWACMD_FLAG_HG_ASYNCH;
4303 ASSERT_GUEST_STMT_RETURN(!fGuestCmd, pCmd->rc = VERR_ACCESS_DENIED, VINF_SUCCESS);
4304 pCmd->rc = VINF_SUCCESS;
4305 Log(("VHWA Command <<< Sync %#p, %d\n", pCmd, enmCmd));
4306 return VINF_SUCCESS;
4307
4308 case VBOXVHWACMD_TYPE_HH_DISABLE:
4309 pCmd->Flags &= ~VBOXVHWACMD_FLAG_HG_ASYNCH;
4310 ASSERT_GUEST_STMT_RETURN(!fGuestCmd, pCmd->rc = VERR_ACCESS_DENIED, VINF_SUCCESS);
4311 pCmd->rc = VINF_SUCCESS;
4312 Log(("VHWA Command <<< Sync %#p, %d\n", pCmd, enmCmd));
4313 return VINF_SUCCESS;
4314
4315 case VBOXVHWACMD_TYPE_HH_SAVESTATE_SAVEBEGIN:
4316 pCmd->Flags &= ~VBOXVHWACMD_FLAG_HG_ASYNCH;
4317 ASSERT_GUEST_STMT_RETURN(!fGuestCmd, pCmd->rc = VERR_ACCESS_DENIED, VINF_SUCCESS);
4318 mCmdPipe.disable();
4319 pCmd->rc = VINF_SUCCESS;
4320 Log(("VHWA Command <<< Sync %#p, %d\n", pCmd, enmCmd));
4321 return VINF_SUCCESS;
4322
4323 case VBOXVHWACMD_TYPE_HH_SAVESTATE_SAVEEND:
4324 ASSERT_GUEST_STMT_RETURN(!fGuestCmd, pCmd->rc = VERR_ACCESS_DENIED, VINF_SUCCESS);
4325 pCmd->Flags &= ~VBOXVHWACMD_FLAG_HG_ASYNCH;
4326 mCmdPipe.enable();
4327 pCmd->rc = VINF_SUCCESS;
4328 Log(("VHWA Command <<< Sync %#p, %d\n", pCmd, enmCmd));
4329 return VINF_SUCCESS;
4330
4331 case VBOXVHWACMD_TYPE_HH_SAVESTATE_SAVEPERFORM:
4332 {
4333 pCmd->Flags &= ~VBOXVHWACMD_FLAG_HG_ASYNCH;
4334 ASSERT_GUEST_STMT_RETURN(!fGuestCmd, pCmd->rc = VERR_ACCESS_DENIED, VINF_SUCCESS);
4335 VBOXVHWACMD_HH_SAVESTATE_SAVEPERFORM *pSave = VBOXVHWACMD_BODY_HOST_HEAP(pCmd, VBOXVHWACMD_HH_SAVESTATE_SAVEPERFORM);
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;
4341 Log(("VHWA Command <<< Sync %#p, %d\n", pCmd, enmCmd));
4342 return VINF_SUCCESS;
4343 }
4344 case VBOXVHWACMD_TYPE_HH_SAVESTATE_LOADPERFORM:
4345 {
4346 pCmd->Flags &= ~VBOXVHWACMD_FLAG_HG_ASYNCH;
4347 ASSERT_GUEST_STMT_RETURN(!fGuestCmd, pCmd->rc = VERR_ACCESS_DENIED, VINF_SUCCESS);
4348 VBOXVHWACMD_HH_SAVESTATE_LOADPERFORM *pLoad = VBOXVHWACMD_BODY_HOST_HEAP(pCmd, VBOXVHWACMD_HH_SAVESTATE_LOADPERFORM);
4349 PSSMHANDLE pSSM = pLoad->pSSM;
4350 uint32_t u32Version = 0;
4351 int rc = SSMR3GetU32(pSSM, &u32Version); Assert(RT_SUCCESS(rc) || rc == VERR_SSM_LOADED_TOO_MUCH);
4352 if (RT_SUCCESS(rc))
4353 {
4354 rc = vhwaLoadExec(pSSM, u32Version);
4355 AssertRC(rc);
4356 }
4357 else
4358 {
4359 /* sanity */
4360 u32Version = 0;
4361
4362 if (rc == VERR_SSM_LOADED_TOO_MUCH)
4363 rc = VINF_SUCCESS;
4364 }
4365 pCmd->rc = rc;
4366 Log(("VHWA Command <<< Sync %#p, %d\n", pCmd, enmCmd));
4367 return VINF_SUCCESS;
4368 }
4369
4370 case VBOXVHWACMD_TYPE_QUERY_INFO1:
4371 {
4372#ifdef RT_STRICT
4373 VBOXVHWACMD_QUERYINFO1 RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_QUERYINFO1);
4374#endif
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 }
4381
4382 default:
4383 break;
4384 }
4385
4386 Log(("VHWA Command --- Going Async %#p, %d\n", pCmd, enmCmd));
4387 /* indicate that we process and complete the command asynchronously */
4388 pCmd->Flags |= VBOXVHWACMD_FLAG_HG_ASYNCH;
4389
4390 mCmdPipe.postCmd(VBOXVHWA_PIPECMD_VHWA, (void *)pCmd, enmCmd, fGuestCmd);
4391 return VINF_CALLBACK_RETURN;
4392
4393}
4394
4395void VBoxQGLOverlay::onVHWACommandEvent(QEvent *pEvent)
4396{
4397 VBoxVHWACommandProcessEvent *pVhwaEvent = (VBoxVHWACommandProcessEvent *)pEvent;
4398 /* sanity actually */
4399 pVhwaEvent->setProcessed();
4400
4401 Assert(!mProcessingCommands);
4402 mProcessingCommands = true;
4403 Assert(!mGlCurrent);
4404 mGlCurrent = false; /* just a fall-back */
4405 VBoxVHWACommandElement *pCmd = mCmdPipe.getCmd();
4406 if (pCmd)
4407 {
4408 processCmd(pCmd);
4409 mCmdPipe.doneCmd();
4410 }
4411
4412 mProcessingCommands = false;
4413 repaint();
4414 mGlCurrent = false;
4415}
4416
4417bool VBoxQGLOverlay::onNotifyUpdate(ULONG uX, ULONG uY, ULONG uW, ULONG uH)
4418{
4419 /* Prepare corresponding viewport part: */
4420 QRect rect(uX, uY, uW, uH);
4421
4422 /* Take the scaling into account: */
4423 const double dScaleFactor = mSizeInfo.scaleFactor();
4424 const QSize scaledSize = mSizeInfo.scaledSize();
4425 if (scaledSize.isValid())
4426 {
4427 /* Calculate corresponding scale-factors: */
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;
4432 /* Adjust corresponding viewport part: */
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));
4437 }
4438
4439 /* Take the device-pixel-ratio into account: */
4440 if (mSizeInfo.useUnscaledHiDPIOutput())
4441 {
4442 const double dDevicePixelRatio = gpDesktop->devicePixelRatio(mpViewport->window());
4443 if (dDevicePixelRatio > 1.0)
4444 {
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));
4449 }
4450 }
4451
4452 /* we do not to miss notify updates, because we have to update bg textures for it,
4453 * so no not check for m_fUnused here,
4454 * mOverlay will store the required info for us */
4455 mCmdPipe.postCmd(VBOXVHWA_PIPECMD_PAINT, &rect, -1, false);
4456
4457 return true;
4458}
4459
4460void VBoxQGLOverlay::onResizeEventPostprocess(const VBoxFBSizeInfo &re, const QPoint &topLeft)
4461{
4462 mSizeInfo = re;
4463 mContentsTopLeft = topLeft;
4464
4465 if (mGlOn)
4466 {
4467 Assert(mOverlayImage.hasSurfaces());
4468 Assert(!mGlCurrent);
4469 Assert(!mNeedOverlayRepaint);
4470 mGlCurrent = false;
4471 makeCurrent();
4472 /* need to ensure we're in sync */
4473 mNeedOverlayRepaint = vboxSynchGl();
4474
4475 if (!mOverlayImage.hasSurfaces())
4476 vboxSetGlOn(false);
4477 }
4478 else
4479 Assert(!mOverlayImage.hasSurfaces());
4480
4481 if (!mOnResizeCmdList.empty())
4482 {
4483 for (VHWACommandList::const_iterator it = mOnResizeCmdList.begin(); it != mOnResizeCmdList.end(); ++ it)
4484 {
4485 VBOXVHWACMD *pCmd = (*it);
4486 vboxDoVHWACmdExec(pCmd, pCmd->enmCmd, false);
4487 free(pCmd);
4488 }
4489 mOnResizeCmdList.clear();
4490 }
4491
4492 repaintOverlay();
4493 mGlCurrent = false;
4494}
4495
4496void VBoxQGLOverlay::repaintMain()
4497{
4498 if (mMainDirtyRect.isClear())
4499 return;
4500
4501 const QRect &rect = mMainDirtyRect.rect();
4502 if (mOverlayWidgetVisible)
4503 if (mOverlayViewport.contains(rect))
4504 return;
4505
4506 mpViewport->repaint(rect.x() - mContentsTopLeft.x(),
4507 rect.y() - mContentsTopLeft.y(),
4508 rect.width(),
4509 rect.height());
4510
4511 mMainDirtyRect.clear();
4512}
4513
4514void VBoxQGLOverlay::vboxDoVHWACmd(void RT_UNTRUSTED_VOLATILE_GUEST *pvCmd, int /*VBOXVHWACMD_TYPE*/ enmCmd, bool fGuestCmd)
4515{
4516 vboxDoVHWACmdExec(pvCmd, enmCmd, fGuestCmd);
4517
4518 CDisplay display = mpSession->GetConsole().GetDisplay();
4519 Assert(!display.isNull());
4520
4521 Log(("VHWA Command <<< Async %#p, %d\n", pvCmd, enmCmd));
4522
4523 display.CompleteVHWACommand((BYTE *)pvCmd);
4524}
4525
4526bool VBoxQGLOverlay::vboxSynchGl()
4527{
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 )
4537 {
4538 return false;
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 */
4542 mOverlayImage.resize(mSizeInfo);
4543 return true;
4544}
4545
4546void VBoxQGLOverlay::vboxSetGlOn(bool on)
4547{
4548 if (on == mGlOn)
4549 return;
4550
4551 mGlOn = on;
4552
4553 if (on)
4554 {
4555 /* need to ensure we have gl functions initialized */
4556 mpOverlayWgt->makeCurrent();
4557 vboxVHWAGetSupportInfo(mpOverlayWgt->context());
4558
4559 VBOXQGLLOGREL(("Switching Gl mode on\n"));
4560 Assert(!mpOverlayWgt->isVisible());
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{
4577 if (!mOverlayVisible)
4578 {
4579 vboxShowOverlay(false);
4580 return;
4581 }
4582
4583 int cX = mContentsTopLeft.x();
4584 int cY = mContentsTopLeft.y();
4585 QRect fbVp(cX, cY, mpViewport->width(), mpViewport->height());
4586 QRect overVp = fbVp.intersected(mOverlayViewport);
4587
4588 if (overVp.isEmpty())
4589 vboxShowOverlay(false);
4590 else
4591 {
4592 if (overVp != mOverlayImage.vboxViewport())
4593 {
4594 makeCurrent();
4595 mOverlayImage.vboxDoUpdateViewport(overVp);
4596 mNeedOverlayRepaint = true;
4597 }
4598
4599 QRect rect(overVp.x() - cX, overVp.y() - cY, overVp.width(), overVp.height());
4600
4601 vboxCheckUpdateOverlay(rect);
4602
4603 vboxShowOverlay(true);
4604
4605 /* workaround for linux ATI issue: need to update gl viewport after widget becomes visible */
4606 mOverlayImage.vboxDoUpdateViewport(overVp);
4607 }
4608}
4609
4610void VBoxQGLOverlay::vboxShowOverlay(bool show)
4611{
4612 if (mOverlayWidgetVisible != show)
4613 {
4614 mpOverlayWgt->setVisible(show);
4615 mOverlayWidgetVisible = show;
4616 mGlCurrent = false;
4617 if (!show)
4618 mMainDirtyRect.add(mOverlayImage.vboxViewport());
4619 }
4620}
4621
4622void VBoxQGLOverlay::vboxCheckUpdateOverlay(const QRect &rect)
4623{
4624 QRect overRect(mpOverlayWgt->pos(), mpOverlayWgt->size());
4625 if (overRect.x() != rect.x() || overRect.y() != rect.y())
4626 {
4627#if defined(RT_OS_WINDOWS)
4628 mpOverlayWgt->setVisible(false);
4629 mNeedSetVisible = true;
4630#endif
4631 VBOXQGLLOG_QRECT("moving wgt to " , &rect, "\n");
4632 mpOverlayWgt->move(rect.x(), rect.y());
4633 mGlCurrent = false;
4634 }
4635
4636 if (overRect.width() != rect.width() || overRect.height() != rect.height())
4637 {
4638#if defined(RT_OS_WINDOWS)
4639 mpOverlayWgt->setVisible(false);
4640 mNeedSetVisible = true;
4641#endif
4642 VBOXQGLLOG(("resizing wgt to w(%d) ,h(%d)\n" , rect.width(), rect.height()));
4643 mpOverlayWgt->resize(rect.width(), rect.height());
4644 mGlCurrent = false;
4645 }
4646}
4647
4648void VBoxQGLOverlay::addMainDirtyRect(const QRect &aRect)
4649{
4650 mMainDirtyRect.add(aRect);
4651 if (mGlOn)
4652 {
4653 mOverlayImage.vboxDoUpdateRect(&aRect);
4654 mNeedOverlayRepaint = true;
4655 }
4656}
4657
4658int VBoxQGLOverlay::vhwaSurfaceUnlock(struct VBOXVHWACMD_SURF_UNLOCK RT_UNTRUSTED_VOLATILE_GUEST *pCmd)
4659{
4660 int rc = mOverlayImage.vhwaSurfaceUnlock(pCmd);
4661 VBoxVHWASurfaceBase *pVGA = mOverlayImage.vgaSurface();
4662 const VBoxVHWADirtyRect &rect = pVGA->getDirtyRect();
4663 mNeedOverlayRepaint = true;
4664 if (!rect.isClear())
4665 mMainDirtyRect.add(rect);
4666 return rc;
4667}
4668
4669void VBoxQGLOverlay::vboxDoVHWACmdExec(void RT_UNTRUSTED_VOLATILE_GUEST *pvCmd, int /*VBOXVHWACMD_TYPE*/ enmCmdInt, bool fGuestCmd)
4670{
4671 struct VBOXVHWACMD RT_UNTRUSTED_VOLATILE_GUEST *pCmd = (struct VBOXVHWACMD RT_UNTRUSTED_VOLATILE_GUEST *)pvCmd;
4672 VBOXVHWACMD_TYPE enmCmd = (VBOXVHWACMD_TYPE)enmCmdInt;
4673
4674 switch (enmCmd)
4675 {
4676 case VBOXVHWACMD_TYPE_SURF_CANCREATE:
4677 {
4678 VBOXVHWACMD_SURF_CANCREATE RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_CANCREATE);
4679 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4680 initGl();
4681 makeCurrent();
4682 pCmd->rc = mOverlayImage.vhwaSurfaceCanCreate(pBody);
4683 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4684 break;
4685 }
4686
4687 case VBOXVHWACMD_TYPE_SURF_CREATE:
4688 {
4689 VBOXVHWACMD_SURF_CREATE RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_CREATE);
4690 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4691 initGl();
4692 makeCurrent();
4693 vboxSetGlOn(true);
4694 pCmd->rc = mOverlayImage.vhwaSurfaceCreate(pBody);
4695 if (!mOverlayImage.hasSurfaces())
4696 {
4697 vboxSetGlOn(false);
4698 }
4699 else
4700 {
4701 mOverlayVisible = mOverlayImage.hasVisibleOverlays();
4702 if (mOverlayVisible)
4703 {
4704 mOverlayViewport = mOverlayImage.overlaysRectUnion();
4705 }
4706 vboxDoCheckUpdateViewport();
4707 mNeedOverlayRepaint = true;
4708 }
4709
4710 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4711 break;
4712 }
4713
4714 case VBOXVHWACMD_TYPE_SURF_DESTROY:
4715 {
4716 VBOXVHWACMD_SURF_DESTROY RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_DESTROY);
4717 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4718 initGl();
4719 makeCurrent();
4720 pCmd->rc = mOverlayImage.vhwaSurfaceDestroy(pBody);
4721 if (!mOverlayImage.hasSurfaces())
4722 {
4723 vboxSetGlOn(false);
4724 }
4725 else
4726 {
4727 mOverlayVisible = mOverlayImage.hasVisibleOverlays();
4728 if (mOverlayVisible)
4729 {
4730 mOverlayViewport = mOverlayImage.overlaysRectUnion();
4731 }
4732 vboxDoCheckUpdateViewport();
4733 mNeedOverlayRepaint = true;
4734 }
4735 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4736 break;
4737 }
4738
4739 case VBOXVHWACMD_TYPE_SURF_LOCK:
4740 {
4741 VBOXVHWACMD_SURF_LOCK RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_LOCK);
4742 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4743 initGl();
4744 makeCurrent();
4745 pCmd->rc = mOverlayImage.vhwaSurfaceLock(pBody);
4746 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4747 break;
4748 }
4749
4750 case VBOXVHWACMD_TYPE_SURF_UNLOCK:
4751 {
4752 VBOXVHWACMD_SURF_UNLOCK RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_UNLOCK);
4753 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4754 initGl();
4755 makeCurrent();
4756 pCmd->rc = vhwaSurfaceUnlock(pBody);
4757 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4758 /* mNeedOverlayRepaint is set inside the vhwaSurfaceUnlock */
4759 break;
4760 }
4761
4762 case VBOXVHWACMD_TYPE_SURF_BLT:
4763 {
4764 VBOXVHWACMD_SURF_BLT RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_BLT);
4765 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4766 initGl();
4767 makeCurrent();
4768 pCmd->rc = mOverlayImage.vhwaSurfaceBlt(pBody);
4769 mNeedOverlayRepaint = true;
4770 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4771 break;
4772 }
4773
4774 case VBOXVHWACMD_TYPE_SURF_FLIP:
4775 {
4776 VBOXVHWACMD_SURF_FLIP RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_FLIP);
4777 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4778 initGl();
4779 makeCurrent();
4780 pCmd->rc = mOverlayImage.vhwaSurfaceFlip(pBody);
4781 mNeedOverlayRepaint = true;
4782 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4783 break;
4784 }
4785
4786 case VBOXVHWACMD_TYPE_SURF_OVERLAY_UPDATE:
4787 {
4788 VBOXVHWACMD_SURF_OVERLAY_UPDATE RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_OVERLAY_UPDATE);
4789 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4790 initGl();
4791 makeCurrent();
4792 pCmd->rc = mOverlayImage.vhwaSurfaceOverlayUpdate(pBody);
4793 mOverlayVisible = mOverlayImage.hasVisibleOverlays();
4794 if (mOverlayVisible)
4795 {
4796 mOverlayViewport = mOverlayImage.overlaysRectUnion();
4797 }
4798 vboxDoCheckUpdateViewport();
4799 mNeedOverlayRepaint = true;
4800 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4801 break;
4802 }
4803
4804 case VBOXVHWACMD_TYPE_SURF_OVERLAY_SETPOSITION:
4805 {
4806 VBOXVHWACMD_SURF_OVERLAY_SETPOSITION RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_OVERLAY_SETPOSITION);
4807 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4808 initGl();
4809 makeCurrent();
4810 pCmd->rc = mOverlayImage.vhwaSurfaceOverlaySetPosition(pBody);
4811 mOverlayVisible = mOverlayImage.hasVisibleOverlays();
4812 if (mOverlayVisible)
4813 {
4814 mOverlayViewport = mOverlayImage.overlaysRectUnion();
4815 }
4816 vboxDoCheckUpdateViewport();
4817 mNeedOverlayRepaint = true;
4818 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4819 break;
4820 }
4821
4822#ifdef VBOX_WITH_WDDM
4823 case VBOXVHWACMD_TYPE_SURF_COLORFILL:
4824 {
4825 VBOXVHWACMD_SURF_COLORFILL RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_COLORFILL);
4826 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4827 initGl();
4828 makeCurrent();
4829 pCmd->rc = mOverlayImage.vhwaSurfaceColorFill(pBody);
4830 mNeedOverlayRepaint = true;
4831 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4832 break;
4833 }
4834#endif
4835 case VBOXVHWACMD_TYPE_SURF_COLORKEY_SET:
4836 {
4837 VBOXVHWACMD_SURF_COLORKEY_SET RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_COLORKEY_SET);
4838 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4839 initGl();
4840 makeCurrent();
4841 pCmd->rc = mOverlayImage.vhwaSurfaceColorkeySet(pBody);
4842 /* this is here to ensure we have color key changes picked up */
4843 vboxDoCheckUpdateViewport();
4844 mNeedOverlayRepaint = true;
4845 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4846 break;
4847 }
4848
4849 case VBOXVHWACMD_TYPE_QUERY_INFO1:
4850 {
4851 VBOXVHWACMD_QUERYINFO1 RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_QUERYINFO1);
4852 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4853 initGl();
4854 makeCurrent();
4855 pCmd->rc = mOverlayImage.vhwaQueryInfo1(pBody);
4856 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4857 break;
4858 }
4859
4860 case VBOXVHWACMD_TYPE_QUERY_INFO2:
4861 {
4862 VBOXVHWACMD_QUERYINFO2 RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_QUERYINFO2);
4863 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4864 initGl();
4865 makeCurrent();
4866 pCmd->rc = mOverlayImage.vhwaQueryInfo2(pBody);
4867 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4868 break;
4869 }
4870
4871 case VBOXVHWACMD_TYPE_ENABLE:
4872 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4873 initGl();
4874 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4875 pCmd->rc = VINF_SUCCESS;
4876 break;
4877
4878 case VBOXVHWACMD_TYPE_DISABLE:
4879 pCmd->rc = VINF_SUCCESS;
4880 break;
4881
4882 case VBOXVHWACMD_TYPE_HH_CONSTRUCT:
4883 {
4884 ASSERT_GUEST_STMT_RETURN_VOID(!fGuestCmd, pCmd->rc = VERR_ACCESS_DENIED);
4885 VBOXVHWACMD_HH_CONSTRUCT *pBody = VBOXVHWACMD_BODY_HOST_HEAP(pCmd, VBOXVHWACMD_HH_CONSTRUCT);
4886 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4887 pCmd->rc = vhwaConstruct(pBody);
4888 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4889 break;
4890 }
4891
4892#ifdef VBOX_WITH_WDDM
4893 case VBOXVHWACMD_TYPE_SURF_GETINFO:
4894 {
4895 VBOXVHWACMD_SURF_GETINFO RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_GETINFO);
4896 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4897 pCmd->rc = mOverlayImage.vhwaSurfaceGetInfo(pBody);
4898 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4899 break;
4900 }
4901#endif
4902
4903 default:
4904 AssertFailed();
4905 pCmd->rc = VERR_NOT_IMPLEMENTED;
4906 break;
4907 }
4908}
4909
4910#if 0
4911static DECLCALLBACK(void) vboxQGLOverlaySaveExec(PSSMHANDLE pSSM, void *pvUser)
4912{
4913 VBoxQGLOverlay * fb = (VBoxQGLOverlay*)pvUser;
4914 fb->vhwaSaveExec(pSSM);
4915}
4916#endif
4917
4918static DECLCALLBACK(int) vboxQGLOverlayLoadExec(PSSMHANDLE pSSM, void *pvUser, uint32_t u32Version, uint32_t uPass)
4919{
4920 Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
4921 VBoxQGLOverlay *fb = (VBoxQGLOverlay *)pvUser;
4922 return fb->vhwaLoadExec(pSSM, u32Version);
4923}
4924
4925int VBoxQGLOverlay::vhwaLoadExec(struct SSMHANDLE *pSSM, uint32_t u32Version)
4926{
4927 int rc = VBoxVHWAImage::vhwaLoadExec(&mOnResizeCmdList, pSSM, u32Version);
4928 AssertRC(rc);
4929 if (RT_SUCCESS(rc))
4930 {
4931 if (u32Version >= VBOXQGL_STATE_VERSION_PIPESAVED)
4932 {
4933 rc = mCmdPipe.loadExec(pSSM, u32Version, mOverlayImage.vramBase());
4934 AssertRC(rc);
4935 }
4936 }
4937 return rc;
4938}
4939
4940void VBoxQGLOverlay::vhwaSaveExec(struct SSMHANDLE *pSSM)
4941{
4942 mOverlayImage.vhwaSaveExec(pSSM);
4943 mCmdPipe.saveExec(pSSM, mOverlayImage.vramBase());
4944}
4945
4946int VBoxQGLOverlay::vhwaConstruct(struct VBOXVHWACMD_HH_CONSTRUCT *pCmd)
4947{
4948 PUVM pUVM = VMR3GetUVM((PVM)pCmd->pVM);
4949 uint32_t intsId = m_id;
4950
4951 char nameFuf[sizeof(VBOXQGL_STATE_NAMEBASE) + 8];
4952
4953 char * pszName = nameFuf;
4954 sprintf(pszName, "%s%d", VBOXQGL_STATE_NAMEBASE, intsId);
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 );
4971 AssertRC(rc);
4972 if (RT_SUCCESS(rc))
4973 {
4974 rc = mOverlayImage.vhwaConstruct(pCmd);
4975 AssertRC(rc);
4976 }
4977 return rc;
4978}
4979
4980void VBoxQGLOverlay::processCmd(VBoxVHWACommandElement * pCmd)
4981{
4982 switch(pCmd->type())
4983 {
4984 case VBOXVHWA_PIPECMD_PAINT:
4985 addMainDirtyRect(pCmd->rect());
4986 break;
4987
4988#ifdef VBOX_WITH_VIDEOHWACCEL
4989 case VBOXVHWA_PIPECMD_VHWA:
4990 vboxDoVHWACmd(pCmd->vhwaCmdPtr(), pCmd->vhwaCmdType(), pCmd->vhwaIsGuestCmd());
4991 break;
4992
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:
5001 AssertFailed();
5002 }
5003}
5004
5005VBoxVHWACommandElementProcessor::VBoxVHWACommandElementProcessor()
5006 : m_pNotifyObject(NULL)
5007 , mpCurCmd(NULL)
5008 , mbResetting(false)
5009 , mcDisabled(0)
5010{
5011 int rc = RTCritSectInit(&mCritSect);
5012 AssertRC(rc);
5013
5014 RTListInit(&mCommandList);
5015
5016 m_pCmdEntryCache = new VBoxVHWAEntriesCache;
5017}
5018
5019void VBoxVHWACommandElementProcessor::init(QObject *pNotifyObject)
5020{
5021 m_pNotifyObject = pNotifyObject;
5022}
5023
5024VBoxVHWACommandElementProcessor::~VBoxVHWACommandElementProcessor()
5025{
5026 Assert(!m_NotifyObjectRefs.refs());
5027 RTListIsEmpty(&mCommandList);
5028
5029 RTCritSectDelete(&mCritSect);
5030
5031 delete m_pCmdEntryCache;
5032}
5033
5034void VBoxVHWACommandElementProcessor::postCmd(VBOXVHWA_PIPECMD_TYPE aType, void *pvData,
5035 int /*VBOXVHWACMD_TYPE*/ enmCmd, bool fGuestCmd)
5036{
5037 QObject *pNotifyObject = NULL;
5038
5039 Log(("VHWA post %d %#p\n", aType, pvData));
5040
5041 /* 1. lock*/
5042 RTCritSectEnter(&mCritSect);
5043
5044 VBoxVHWACommandElement *pCmd = m_pCmdEntryCache->alloc();
5045 if (!pCmd)
5046 {
5047 VBOXQGLLOG(("!!!no more free elements!!!\n"));
5048#ifdef VBOXQGL_PROF_BASE
5049 RTCritSectLeave(&mCritSect);
5050 return;
5051#else
5052 /// @todo
5053#endif
5054 }
5055 pCmd->setData(aType, pvData, enmCmd, fGuestCmd);
5056
5057 /* 2. if can add to current*/
5058 if (m_pNotifyObject)
5059 {
5060 m_NotifyObjectRefs.inc(); /* ensure the parent does not get destroyed while we are using it */
5061 pNotifyObject = m_pNotifyObject;
5062 }
5063
5064 RTListAppend(&mCommandList, &pCmd->ListNode);
5065
5066 RTCritSectLeave(&mCritSect);
5067
5068 if (pNotifyObject)
5069 {
5070 VBoxVHWACommandProcessEvent *pCurrentEvent = new VBoxVHWACommandProcessEvent();
5071 QApplication::postEvent(pNotifyObject, pCurrentEvent);
5072 m_NotifyObjectRefs.dec();
5073 }
5074}
5075
5076void VBoxVHWACommandElementProcessor::setNotifyObject(QObject *pNotifyObject)
5077{
5078 int cEventsNeeded = 0;
5079 RTCritSectEnter(&mCritSect);
5080 if (m_pNotifyObject == pNotifyObject)
5081 {
5082 RTCritSectLeave(&mCritSect);
5083 return;
5084 }
5085
5086 if (m_pNotifyObject)
5087 {
5088 m_pNotifyObject = NULL;
5089 RTCritSectLeave(&mCritSect);
5090
5091 m_NotifyObjectRefs.wait0();
5092
5093 RTCritSectEnter(&mCritSect);
5094 }
5095 else
5096 {
5097 /* NULL can not be references */
5098 Assert(!m_NotifyObjectRefs.refs());
5099 }
5100
5101 if (pNotifyObject)
5102 {
5103 m_pNotifyObject = pNotifyObject;
5104
5105 VBoxVHWACommandElement *pCur;
5106 RTListForEachCpp(&mCommandList, pCur, VBoxVHWACommandElement, ListNode)
5107 {
5108 ++cEventsNeeded;
5109 }
5110
5111 if (cEventsNeeded)
5112 m_NotifyObjectRefs.inc();
5113 }
5114 else
5115 {
5116 /* should be zeroed already */
5117 Assert(!m_pNotifyObject);
5118 }
5119
5120 RTCritSectLeave(&mCritSect);
5121
5122 if (cEventsNeeded)
5123 {
5124 /* cEventsNeeded can only be != 0 if pNotifyObject is valid */
5125 Assert(pNotifyObject);
5126 for (int i = 0; i < cEventsNeeded; ++i)
5127 {
5128 VBoxVHWACommandProcessEvent *pCurrentEvent = new VBoxVHWACommandProcessEvent();
5129 QApplication::postEvent(pNotifyObject, pCurrentEvent);
5130 }
5131 m_NotifyObjectRefs.dec();
5132 }
5133}
5134
5135void VBoxVHWACommandElementProcessor::doneCmd()
5136{
5137 VBoxVHWACommandElement *pEl;
5138 RTCritSectEnter(&mCritSect);
5139 pEl = mpCurCmd;
5140 Assert(mpCurCmd);
5141 mpCurCmd = NULL;
5142 RTCritSectLeave(&mCritSect);
5143
5144 if (pEl)
5145 m_pCmdEntryCache->free(pEl);
5146}
5147
5148VBoxVHWACommandElement *VBoxVHWACommandElementProcessor::getCmd()
5149{
5150 VBoxVHWACommandElement *pEl = NULL;
5151 RTCritSectEnter(&mCritSect);
5152
5153 Assert(!mpCurCmd);
5154
5155 if (mbResetting)
5156 {
5157 RTCritSectLeave(&mCritSect);
5158 return NULL;
5159 }
5160
5161 if (mcDisabled)
5162 {
5163 QObject *pNotifyObject = NULL;
5164
5165 if (!RTListIsEmpty(&mCommandList))
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 }
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;
5184 }
5185
5186 pEl = RTListGetFirstCpp(&mCommandList, VBoxVHWACommandElement, ListNode);
5187 if (pEl)
5188 {
5189 RTListNodeRemove(&pEl->ListNode);
5190 mpCurCmd = pEl;
5191 }
5192
5193 RTCritSectLeave(&mCritSect);
5194
5195 return pEl;
5196}
5197
5198/* it is currently assumed no one sends any new commands while reset is in progress */
5199void VBoxVHWACommandElementProcessor::reset(CDisplay *pDisplay)
5200{
5201 RTCritSectEnter(&mCritSect);
5202
5203 mbResetting = true;
5204
5205 if (mpCurCmd)
5206 {
5207 for (;;)
5208 {
5209 RTCritSectLeave(&mCritSect);
5210 RTThreadSleep(2); /* 2 ms */
5211 RTCritSectEnter(&mCritSect);
5212 /* it is assumed no one sends any new commands while reset is in progress */
5213 if (!mpCurCmd)
5214 {
5215 break;
5216 }
5217 }
5218 }
5219
5220 RTCritSectLeave(&mCritSect);
5221
5222 VBoxVHWACommandElement *pCur, *pNext;
5223 RTListForEachSafeCpp(&mCommandList, pCur, pNext, VBoxVHWACommandElement, ListNode)
5224 {
5225 switch (pCur->type())
5226 {
5227#ifdef VBOX_WITH_VIDEOHWACCEL
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;
5241#endif
5242 case VBOXVHWA_PIPECMD_PAINT:
5243 break;
5244
5245 default:
5246 /* should not happen, don't handle this for now */
5247 AssertFailed();
5248 break;
5249 }
5250
5251 RTListNodeRemove(&pCur->ListNode);
5252 m_pCmdEntryCache->free(pCur);
5253 }
5254
5255 RTCritSectEnter(&mCritSect);
5256
5257 mbResetting = false;
5258
5259 RTCritSectLeave(&mCritSect);
5260}
5261
5262#define VBOXVHWACOMMANDELEMENTLISTBEGIN_MAGIC UINT32_C(0x89abcdef)
5263#define VBOXVHWACOMMANDELEMENTLISTEND_MAGIC UINT32_C(0xfedcba98)
5264
5265int VBoxVHWACommandElementProcessor::loadExec(struct SSMHANDLE *pSSM, uint32_t u32Version, void *pvVRAM)
5266{
5267 uint32_t u32;
5268
5269 Q_UNUSED(u32Version);
5270
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
5283 {
5284 rc = SSMR3GetU32(pSSM, &u32);
5285 AssertRCReturn(rc, rc);
5286
5287 bool fNewEvent;
5288 switch (u32)
5289 {
5290 case VBOXVHWA_PIPECMD_PAINT:
5291 {
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);
5299
5300 QRect r = QRect(x, y, w, h);
5301 postCmd(VBOXVHWA_PIPECMD_PAINT, &r, -1, false);
5302 break;
5303 }
5304
5305 case VBOXVHWA_PIPECMD_VHWA:
5306 {
5307 uint32_t offCmd;
5308 rc = SSMR3GetU32(pSSM, &offCmd);
5309 rc = SSMR3GetBool(pSSM, &fNewEvent);
5310 AssertRCReturn(rc, rc);
5311
5312 VBOXVHWACMD *pCmd = (VBOXVHWACMD *)(((uint8_t *)pvVRAM) + offCmd);
5313 postCmd(VBOXVHWA_PIPECMD_VHWA, pCmd, pCmd->enmCmd, true);
5314 break;
5315 }
5316
5317 case VBOXVHWACOMMANDELEMENTLISTEND_MAGIC:
5318 fContinue = false;
5319 break;
5320
5321 default:
5322 AssertLogRelMsgFailed(("u32=%#x\n", u32));
5323 break;
5324 }
5325
5326 } while (fContinue && RT_SUCCESS(rc));
5327
5328 return rc;
5329}
5330
5331void VBoxVHWACommandElementProcessor::saveExec(struct SSMHANDLE *pSSM, void *pvVRAM)
5332{
5333 int rc;
5334
5335 rc = SSMR3PutU32(pSSM, VBOXVHWACOMMANDELEMENTLISTBEGIN_MAGIC);
5336 rc = SSMR3PutU32(pSSM, m_NotifyObjectRefs.refs());
5337 rc = SSMR3PutBool(pSSM, true);
5338 AssertRC(rc);
5339
5340 VBoxVHWACommandElement *pCur;
5341 RTListForEachCpp(&mCommandList, pCur, VBoxVHWACommandElement, ListNode)
5342 {
5343
5344 switch (pCur->type())
5345 {
5346 case VBOXVHWA_PIPECMD_PAINT:
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);
5354 break;
5355
5356 case VBOXVHWA_PIPECMD_VHWA:
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 }
5364 break;
5365
5366 default:
5367 AssertFailed();
5368 break;
5369 }
5370 }
5371
5372 rc = SSMR3PutU32(pSSM, VBOXVHWACOMMANDELEMENTLISTEND_MAGIC);
5373 AssertRC(rc);
5374}
5375
5376void VBoxVHWACommandElementProcessor::lock()
5377{
5378 RTCritSectEnter(&mCritSect);
5379
5380 if (mpCurCmd)
5381 {
5382 for (;;)
5383 {
5384 RTCritSectLeave(&mCritSect);
5385 RTThreadSleep(2); /* 2 ms */
5386 RTCritSectEnter(&mCritSect);
5387 /* it is assumed no one sends any new commands while reset is in progress */
5388 if (!mpCurCmd)
5389 {
5390 break;
5391 }
5392 }
5393 }
5394
5395 Assert(!mpCurCmd);
5396}
5397
5398void VBoxVHWACommandElementProcessor::unlock()
5399{
5400 RTCritSectLeave(&mCritSect);
5401}
5402
5403void VBoxVHWACommandElementProcessor::disable()
5404{
5405 lock();
5406 ++mcDisabled;
5407 unlock();
5408}
5409
5410void VBoxVHWACommandElementProcessor::enable()
5411{
5412 lock();
5413 --mcDisabled;
5414 unlock();
5415}
5416
5417/* static */
5418uint32_t VBoxVHWATextureImage::calcBytesPerLine(const VBoxVHWAColorFormat &format, int width)
5419{
5420 uint32_t pitch = (format.bitsPerPixel() * width + 7) / 8;
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;
5428
5429 default:
5430 pitch = (pitch + 3) & ~3;
5431 break;
5432 }
5433 return pitch;
5434}
5435
5436/* static */
5437uint32_t VBoxVHWATextureImage::calcMemSize(const VBoxVHWAColorFormat &format, int width, int height)
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
5445 * U - pitch / 2 x height / 2
5446 * V - pitch / 2 x height / 2
5447 * */
5448 return 3 * pitch * height / 2;
5449
5450 default:
5451 return pitch * height;
5452 }
5453}
5454
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)
5464{
5465 uint32_t pitch = calcBytesPerLine(format, size.width());
5466
5467 mpTex[0] = vboxVHWATextureCreate(NULL, size, format, pitch, flags);
5468 mColorFormat = format;
5469 if (mColorFormat.fourcc() == FOURCC_YV12)
5470 {
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);
5474 mcTex = 3;
5475 }
5476 else
5477 mcTex = 1;
5478}
5479
5480void VBoxVHWATextureImage::deleteDisplayList()
5481{
5482 if (mVisibleDisplay)
5483 {
5484 glDeleteLists(mVisibleDisplay, 1);
5485 mVisibleDisplay = 0;
5486 }
5487}
5488
5489void VBoxVHWATextureImage::deleteDisplay()
5490{
5491 deleteDisplayList();
5492 mpProgram = NULL;
5493}
5494
5495void VBoxVHWATextureImage::draw(VBoxVHWATextureImage *pDst, const QRect *pDstRect, const QRect *pSrcRect)
5496{
5497 int tx1, ty1, tx2, ty2;
5498 pSrcRect->getCoords(&tx1, &ty1, &tx2, &ty2);
5499
5500 int bx1, by1, bx2, by2;
5501 pDstRect->getCoords(&bx1, &by1, &bx2, &by2);
5502
5503 tx2++; ty2++;bx2++; by2++;
5504
5505 glBegin(GL_QUADS);
5506 uint32_t c = texCoord(GL_TEXTURE0, tx1, ty1);
5507 if (pDst)
5508 pDst->texCoord(GL_TEXTURE0 + c, bx1, by1);
5509 glVertex2i(bx1, by1);
5510
5511 texCoord(GL_TEXTURE0, tx1, ty2);
5512 if (pDst)
5513 pDst->texCoord(GL_TEXTURE0 + c, bx1, by2);
5514 glVertex2i(bx1, by2);
5515
5516 texCoord(GL_TEXTURE0, tx2, ty2);
5517 if (pDst)
5518 pDst->texCoord(GL_TEXTURE0 + c, bx2, by2);
5519 glVertex2i(bx2, by2);
5520
5521 texCoord(GL_TEXTURE0, tx2, ty1);
5522 if (pDst)
5523 pDst->texCoord(GL_TEXTURE0 + c, bx2, by1);
5524 glVertex2i(bx2, by1);
5525
5526 glEnd();
5527}
5528
5529void VBoxVHWATextureImage::internalSetDstCKey(const VBoxVHWAColorKey * pDstCKey)
5530{
5531 if (pDstCKey)
5532 {
5533 mDstCKey = *pDstCKey;
5534 mpDstCKey = &mDstCKey;
5535 }
5536 else
5537 {
5538 mpDstCKey = NULL;
5539 }
5540}
5541
5542void VBoxVHWATextureImage::internalSetSrcCKey(const VBoxVHWAColorKey * pSrcCKey)
5543{
5544 if (pSrcCKey)
5545 {
5546 mSrcCKey = *pSrcCKey;
5547 mpSrcCKey = &mSrcCKey;
5548 }
5549 else
5550 {
5551 mpSrcCKey = NULL;
5552 }
5553}
5554
5555int VBoxVHWATextureImage::initDisplay(VBoxVHWATextureImage *pDst,
5556 const QRect *pDstRect, const QRect *pSrcRect,
5557 const VBoxVHWAColorKey *pDstCKey, const VBoxVHWAColorKey *pSrcCKey, bool bNotIntersected)
5558{
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))
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{
5580 for (uint32_t i = 1; i < mcTex; i++)
5581 {
5582 vboxglActiveTexture(GL_TEXTURE0 + i);
5583 mpTex[i]->bind();
5584 }
5585 if (pPrimary)
5586 for (uint32_t i = 0; i < pPrimary->mcTex; i++)
5587 {
5588 vboxglActiveTexture(GL_TEXTURE0 + i + mcTex);
5589 pPrimary->mpTex[i]->bind();
5590 }
5591
5592 vboxglActiveTexture(GL_TEXTURE0);
5593 mpTex[0]->bind();
5594}
5595
5596uint32_t VBoxVHWATextureImage::calcProgramType(VBoxVHWATextureImage *pDst, const VBoxVHWAColorKey *pDstCKey,
5597 const VBoxVHWAColorKey *pSrcCKey, bool bNotIntersected)
5598{
5599 uint32_t type = 0;
5600
5601 if (pDstCKey != NULL)
5602 type |= VBOXVHWA_PROGRAM_DSTCOLORKEY;
5603 if (pSrcCKey)
5604 type |= VBOXVHWA_PROGRAM_SRCCOLORKEY;
5605 if ((pDstCKey || pSrcCKey) && bNotIntersected)
5606 type |= VBOXVHWA_PROGRAM_COLORKEYNODISCARD;
5607
5608 NOREF(pDst);
5609 return type;
5610}
5611
5612class VBoxVHWAGlProgramVHWA *VBoxVHWATextureImage::calcProgram(VBoxVHWATextureImage *pDst, const VBoxVHWAColorKey *pDstCKey,
5613 const VBoxVHWAColorKey *pSrcCKey, bool bNotIntersected)
5614{
5615 uint32_t type = calcProgramType(pDst, pDstCKey, pSrcCKey, bNotIntersected);
5616
5617 return mProgramMngr->getProgram(type, &pixelFormat(), pDst ? &pDst->pixelFormat() : NULL);
5618}
5619
5620int VBoxVHWATextureImage::createSetDisplay(VBoxVHWATextureImage *pDst, const QRect *pDstRect, const QRect *pSrcRect,
5621 const VBoxVHWAColorKey *pDstCKey, const VBoxVHWAColorKey * pSrcCKey,
5622 bool bNotIntersected)
5623{
5624 deleteDisplay();
5625 int rc = createDisplay(pDst, pDstRect, pSrcRect, pDstCKey, pSrcCKey, bNotIntersected, &mVisibleDisplay, &mpProgram);
5626 if (RT_FAILURE(rc))
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
5646int VBoxVHWATextureImage::createDisplayList(VBoxVHWATextureImage *pDst, const QRect *pDstRect, const QRect *pSrcRect,
5647 const VBoxVHWAColorKey *pDstCKey, const VBoxVHWAColorKey *pSrcCKey,
5648 bool bNotIntersected, GLuint *pDisplay)
5649{
5650 Q_UNUSED(pDstCKey);
5651 Q_UNUSED(pSrcCKey);
5652 Q_UNUSED(bNotIntersected);
5653
5654 glGetError(); /* clear the err flag */
5655 GLuint display = glGenLists(1);
5656 GLenum err = glGetError();
5657 if (err == GL_NO_ERROR)
5658 {
5659 Assert(display);
5660 if (!display)
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();
5666 if (err == GL_NO_ERROR)
5667 {
5668 Assert(display);
5669 }
5670 else
5671 {
5672 /* we are failed */
5673 Assert(!display);
5674 display = 0;
5675 }
5676 }
5677
5678 if (display)
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
5698void VBoxVHWATextureImage::updateCKeys(VBoxVHWATextureImage *pDst, class VBoxVHWAGlProgramVHWA *pProgram,
5699 const VBoxVHWAColorKey *pDstCKey, const VBoxVHWAColorKey *pSrcCKey)
5700{
5701 if (pProgram)
5702 {
5703 pProgram->start();
5704 if (pSrcCKey)
5705 VBoxVHWATextureImage::setCKey(pProgram, &pixelFormat(), pSrcCKey, false);
5706 if (pDstCKey)
5707 VBoxVHWATextureImage::setCKey(pProgram, &pDst->pixelFormat(), pDstCKey, true);
5708 pProgram->stop();
5709 }
5710}
5711
5712void VBoxVHWATextureImage::updateSetCKeys(const VBoxVHWAColorKey *pDstCKey, const VBoxVHWAColorKey *pSrcCKey)
5713{
5714 updateCKeys(mpDst, mpProgram, pDstCKey, pSrcCKey);
5715 internalSetDstCKey(pDstCKey);
5716 internalSetSrcCKey(pSrcCKey);
5717}
5718
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)
5722{
5723 VBoxVHWAGlProgramVHWA *pProgram = NULL;
5724 if (!pDst)
5725 {
5726 /* sanity */
5727 Assert(pDstCKey == NULL);
5728 pDstCKey = NULL;
5729 }
5730
5731 Assert(!pSrcCKey);
5732 if (pSrcCKey)
5733 pSrcCKey = NULL; /* fallback */
5734
5735 pProgram = calcProgram(pDst, pDstCKey, pSrcCKey, bNotIntersected);
5736
5737 updateCKeys(pDst, pProgram, pDstCKey, pSrcCKey);
5738
5739 GLuint displ;
5740 int rc = createDisplayList(pDst, pDstRect, pSrcRect, pDstCKey, pSrcCKey, bNotIntersected, &displ);
5741 if (RT_SUCCESS(rc))
5742 {
5743 *pDisplay = displ;
5744 *ppProgram = pProgram;
5745 }
5746
5747 return rc;
5748}
5749
5750void VBoxVHWATextureImage::display(VBoxVHWATextureImage *pDst, const QRect *pDstRect, const QRect *pSrcRect,
5751 const VBoxVHWAColorKey *pDstCKey, const VBoxVHWAColorKey *pSrcCKey, bool bNotIntersected)
5752{
5753 VBoxVHWAGlProgramVHWA *pProgram = calcProgram(pDst, pDstCKey, pSrcCKey, bNotIntersected);
5754 if (pProgram)
5755 pProgram->start();
5756
5757 runDisplay(pDst, pDstRect, pSrcRect);
5758
5759 if (pProgram)
5760 pProgram->stop();
5761}
5762
5763void VBoxVHWATextureImage::display()
5764{
5765#ifdef DEBUG_misha
5766 if (mpDst)
5767 dbgDump();
5768
5769 static bool bDisplayOn = true;
5770#endif
5771 Assert(mVisibleDisplay);
5772 if ( mVisibleDisplay
5773#ifdef DEBUG_misha
5774 && bDisplayOn
5775#endif
5776 )
5777 {
5778 if (mpProgram)
5779 mpProgram->start();
5780
5781 VBOXQGL_CHECKERR(
5782 glCallList(mVisibleDisplay);
5783 );
5784
5785 if (mpProgram)
5786 mpProgram->stop();
5787 }
5788 else
5789 {
5790 display(mpDst, &mDstRect, &mSrcRect,
5791 mpDstCKey, mpSrcCKey, mbNotIntersected);
5792 }
5793}
5794
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
5803int VBoxVHWATextureImage::setCKey(VBoxVHWAGlProgramVHWA *pProgram, const VBoxVHWAColorFormat *pFormat,
5804 const VBoxVHWAColorKey *pCKey, bool bDst)
5805{
5806 float r,g,b;
5807 pFormat->pixel2Normalized(pCKey->lower(), &r, &g, &b);
5808 int rcL = bDst ? pProgram->setDstCKeyLowerRange(r, g, b) : pProgram->setSrcCKeyLowerRange(r, g, b);
5809 Assert(RT_SUCCESS(rcL));
5810
5811 return RT_SUCCESS(rcL) /*&& RT_SUCCESS(rcU)*/ ? VINF_SUCCESS: VERR_GENERAL_FAILURE;
5812}
5813
5814VBoxVHWASettings::VBoxVHWASettings ()
5815{
5816}
5817
5818void VBoxVHWASettings::init(CSession &session)
5819{
5820 const QUuid uMachineID = session.GetMachine().GetId();
5821
5822 mStretchLinearEnabled = gEDataManager->useLinearStretch(uMachineID);
5823
5824 uint32_t aFourccs[VBOXVHWA_NUMFOURCC];
5825 int num = 0;
5826 if (gEDataManager->usePixelFormatAYUV(uMachineID))
5827 aFourccs[num++] = FOURCC_AYUV;
5828 if (gEDataManager->usePixelFormatUYVY(uMachineID))
5829 aFourccs[num++] = FOURCC_UYVY;
5830 if (gEDataManager->usePixelFormatYUY2(uMachineID))
5831 aFourccs[num++] = FOURCC_YUY2;
5832 if (gEDataManager->usePixelFormatYV12(uMachineID))
5833 aFourccs[num++] = FOURCC_YV12;
5834
5835 mFourccEnabledCount = num;
5836 memcpy(mFourccEnabledList, aFourccs, num* sizeof (aFourccs[0]));
5837}
5838
5839int VBoxVHWASettings::calcIntersection(int c1, const uint32_t *a1, int c2, const uint32_t *a2, int cOut, uint32_t *aOut)
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];
5850 if (cur1 == cur2)
5851 {
5852 if (cOut > cMatch && aOut)
5853 aOut[cMatch] = cur1;
5854 ++cMatch;
5855 break;
5856 }
5857 }
5858 }
5859
5860 return cMatch;
5861}
5862
5863#endif /* VBOX_GUI_USE_QGL */
5864
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use