VirtualBox

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

Last change on this file since 79365 was 79365, checked in by vboxsync, 5 years ago

Renaming VBoxGlobal to UICommon for bugref:9049 as planned.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use