VirtualBox

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

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

Check if surface handle is valid, bugref:9570

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 175.2 KB
Line 
1/* $Id: VBoxFBOverlay.cpp 81210 2019-10-10 11:21:37Z 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 AssertReturn(pSurf, VERR_INVALID_PARAMETER);
2565 VBoxVHWASurfList *pList = pSurf->getComplexList();
2566 Assert(pSurf->handle() != VBOXVHWA_SURFHANDLE_INVALID);
2567
2568 VBOXQGLLOG_ENTER(("pSurf (0x%x)\n",pSurf));
2569 if (pList != mDisplay.getVGA()->getComplexList())
2570 {
2571 Assert(pList);
2572 pList->remove(pSurf);
2573 if (pList->surfaces().empty())
2574 {
2575 mDisplay.removeOverlay(pList);
2576 if (pList == mConstructingList)
2577 {
2578 mConstructingList = NULL;
2579 mcRemaining2Contruct = 0;
2580 }
2581 delete pList;
2582 }
2583
2584 delete(pSurf);
2585 }
2586 else
2587 {
2588 Assert(pList);
2589 Assert(pList->size() >= 1);
2590 if (pList->size() > 1)
2591 {
2592 if (pSurf == mDisplay.getVGA())
2593 {
2594 const SurfList & surfaces = pList->surfaces();
2595
2596 for (SurfList::const_iterator it = surfaces.begin();
2597 it != surfaces.end(); ++ it)
2598 {
2599 VBoxVHWASurfaceBase *pCurSurf = (*it);
2600 Assert(pCurSurf);
2601 if (pCurSurf != pSurf)
2602 {
2603 mDisplay.updateVGA(pCurSurf);
2604 pList->setCurrentVisible(pCurSurf);
2605 break;
2606 }
2607 }
2608 }
2609
2610 pList->remove(pSurf);
2611 delete(pSurf);
2612 }
2613 else
2614 {
2615 pSurf->setHandle(VBOXVHWA_SURFHANDLE_INVALID);
2616 }
2617 }
2618
2619 /* just in case we destroy a visible overlay surface */
2620 mRepaintNeeded = true;
2621
2622 void * test = mSurfHandleTable.remove(pCmd->u.in.hSurf);
2623 Assert(test); NOREF(test);
2624
2625 return VINF_SUCCESS;
2626}
2627
2628#define VBOXVHWA_CONSTRUCT_QRECT_FROM_RECTL_RB(a_pr) \
2629 QRect((a_pr)->left, \
2630 (a_pr)->top, \
2631 (a_pr)->right - (a_pr)->left + 1, \
2632 (a_pr)->bottom - (a_pr)->top + 1)
2633
2634#define VBOXVHWA_CONSTRUCT_QRECT_FROM_RECTL_WH(a_pr) \
2635 QRect((a_pr)->left, \
2636 (a_pr)->top, \
2637 (a_pr)->right - (a_pr)->left, \
2638 (a_pr)->bottom - (a_pr)->top)
2639
2640int VBoxVHWAImage::vhwaSurfaceLock(struct VBOXVHWACMD_SURF_LOCK RT_UNTRUSTED_VOLATILE_GUEST *pCmd)
2641{
2642 VBoxVHWASurfaceBase *pSurf = handle2Surface(pCmd->u.in.hSurf);
2643 AssertReturn(pSurf, VERR_INVALID_PARAMETER);
2644 VBOXQGLLOG_ENTER(("pSurf (0x%x)\n",pSurf));
2645
2646 vboxCheckUpdateAddress (pSurf, pCmd->u.in.offSurface);
2647 if (pCmd->u.in.rectValid)
2648 {
2649 QRect r = VBOXVHWA_CONSTRUCT_QRECT_FROM_RECTL_WH(&pCmd->u.in.rect);
2650 return pSurf->lock(&r, pCmd->u.in.flags);
2651 }
2652 return pSurf->lock(NULL, pCmd->u.in.flags);
2653}
2654
2655int VBoxVHWAImage::vhwaSurfaceUnlock(struct VBOXVHWACMD_SURF_UNLOCK RT_UNTRUSTED_VOLATILE_GUEST *pCmd)
2656{
2657 VBoxVHWASurfaceBase *pSurf = handle2Surface(pCmd->u.in.hSurf);
2658 AssertReturn(pSurf, VERR_INVALID_PARAMETER);
2659#ifdef DEBUG_misha
2660 /* for performance reasons we should receive unlock for visible surfaces only
2661 * other surfaces receive unlock only once becoming visible, e.g. on DdFlip
2662 * Ensure this is so*/
2663 if (pSurf != mDisplay.getPrimary())
2664 {
2665 const OverlayList & overlays = mDisplay.overlays();
2666 bool bFound = false;
2667
2668 if (!mDisplay.isPrimary(pSurf))
2669 {
2670 for (OverlayList::const_iterator it = overlays.begin();
2671 it != overlays.end(); ++ it)
2672 {
2673 VBoxVHWASurfList * pSurfList = *it;
2674 if (pSurfList->current() == pSurf)
2675 {
2676 bFound = true;
2677 break;
2678 }
2679 }
2680
2681 Assert(bFound);
2682 }
2683
2684// Assert(bFound);
2685 }
2686#endif
2687 VBOXQGLLOG_ENTER(("pSurf (0x%x)\n",pSurf));
2688 if (pCmd->u.in.xUpdatedMemValid)
2689 {
2690 QRect r = VBOXVHWA_CONSTRUCT_QRECT_FROM_RECTL_WH(&pCmd->u.in.xUpdatedMemRect);
2691 pSurf->updatedMem(&r);
2692 }
2693
2694 return pSurf->unlock();
2695}
2696
2697int VBoxVHWAImage::vhwaSurfaceBlt(struct VBOXVHWACMD_SURF_BLT RT_UNTRUSTED_VOLATILE_GUEST *pCmd)
2698{
2699 Q_UNUSED(pCmd);
2700 return VERR_NOT_IMPLEMENTED;
2701}
2702
2703int VBoxVHWAImage::vhwaSurfaceFlip(struct VBOXVHWACMD_SURF_FLIP RT_UNTRUSTED_VOLATILE_GUEST *pCmd)
2704{
2705 VBoxVHWASurfaceBase *pTargSurf = handle2Surface(pCmd->u.in.hTargSurf);
2706 AssertReturn(pTargSurf, VERR_INVALID_PARAMETER);
2707 VBoxVHWASurfaceBase *pCurrSurf = handle2Surface(pCmd->u.in.hCurrSurf);
2708 AssertReturn(pCurrSurf, VERR_INVALID_PARAMETER);
2709 VBOXQGLLOG_ENTER(("pTargSurf (0x%x), pCurrSurf (0x%x)\n", pTargSurf, pCurrSurf));
2710 vboxCheckUpdateAddress (pCurrSurf, pCmd->u.in.offCurrSurface);
2711 vboxCheckUpdateAddress (pTargSurf, pCmd->u.in.offTargSurface);
2712
2713 if (pCmd->u.in.xUpdatedTargMemValid)
2714 {
2715 QRect r = VBOXVHWA_CONSTRUCT_QRECT_FROM_RECTL_WH(&pCmd->u.in.xUpdatedTargMemRect);
2716 pTargSurf->updatedMem(&r);
2717 }
2718 pTargSurf->getComplexList()->setCurrentVisible(pTargSurf);
2719
2720 mRepaintNeeded = true;
2721#ifdef DEBUG
2722 pCurrSurf->cFlipsCurr++;
2723 pTargSurf->cFlipsTarg++;
2724#endif
2725
2726 return VINF_SUCCESS;
2727}
2728
2729int VBoxVHWAImage::vhwaSurfaceColorFill(struct VBOXVHWACMD_SURF_COLORFILL RT_UNTRUSTED_VOLATILE_GUEST *pCmd)
2730{
2731 NOREF(pCmd);
2732 return VERR_NOT_IMPLEMENTED;
2733}
2734
2735void VBoxVHWAImage::vhwaDoSurfaceOverlayUpdate(VBoxVHWASurfaceBase *pDstSurf, VBoxVHWASurfaceBase *pSrcSurf,
2736 struct VBOXVHWACMD_SURF_OVERLAY_UPDATE RT_UNTRUSTED_VOLATILE_GUEST *pCmd)
2737{
2738 if (pCmd->u.in.flags & VBOXVHWA_OVER_KEYDEST)
2739 {
2740 VBOXQGLLOG((", KEYDEST"));
2741 /* we use src (overlay) surface to maintain overridden dst ckey info
2742 * to allow multiple overlays have different overridden dst keys for one primary surface */
2743 /* non-null dstOverlayCKey for overlay would mean the overlay surface contains the overridden
2744 * dst ckey value in defaultDstOverlayCKey
2745 * this allows the NULL to be a valid overridden value as well
2746 * i.e.
2747 * 1. indicate the value is NUL overridden, just set NULL*/
2748 pSrcSurf->setOverriddenDstOverlayCKey(NULL);
2749 }
2750 else if (pCmd->u.in.flags & VBOXVHWA_OVER_KEYDESTOVERRIDE)
2751 {
2752 VBOXQGLLOG((", KEYDESTOVERRIDE"));
2753 /* we use src (overlay) surface to maintain overridden dst ckey info
2754 * to allow multiple overlays have different overridden dst keys for one primary surface */
2755 /* non-null dstOverlayCKey for overlay would mean the overlay surface contains the overridden
2756 * dst ckey value in defaultDstOverlayCKey
2757 * this allows the NULL to be a valid overridden value as well
2758 * i.e.
2759 * 1. indicate the value is overridden (no matter what we write here, bu it should be not NULL)*/
2760 VBoxVHWAColorKey ckey(pCmd->u.in.desc.DstCK.high, pCmd->u.in.desc.DstCK.low);
2761 VBOXQGLLOG_CKEY(" ckey: ",&ckey, "\n");
2762 pSrcSurf->setOverriddenDstOverlayCKey(&ckey);
2763 /* tell the ckey is enabled */
2764 pSrcSurf->setDefaultDstOverlayCKey(&ckey);
2765 }
2766 else
2767 {
2768 VBOXQGLLOG((", no KEYDEST"));
2769 /* we use src (overlay) surface to maintain overridden dst ckey info
2770 * to allow multiple overlays have different overridden dst keys for one primary surface */
2771 /* non-null dstOverlayCKey for overlay would mean the overlay surface contains the overridden
2772 * dst ckey value in defaultDstOverlayCKey
2773 * this allows the NULL to be a valid overridden value as well
2774 * i.e.
2775 * 1. indicate the value is overridden (no matter what we write here, bu it should be not NULL)*/
2776 VBoxVHWAColorKey dummyCKey(0, 0);
2777 pSrcSurf->setOverriddenDstOverlayCKey(&dummyCKey);
2778 /* tell the ckey is disabled */
2779 pSrcSurf->setDefaultDstOverlayCKey(NULL);
2780 }
2781
2782 if (pCmd->u.in.flags & VBOXVHWA_OVER_KEYSRC)
2783 {
2784 VBOXQGLLOG((", KEYSRC"));
2785 pSrcSurf->resetDefaultSrcOverlayCKey();
2786 }
2787 else if (pCmd->u.in.flags & VBOXVHWA_OVER_KEYSRCOVERRIDE)
2788 {
2789 VBOXQGLLOG((", KEYSRCOVERRIDE"));
2790 VBoxVHWAColorKey ckey(pCmd->u.in.desc.SrcCK.high, pCmd->u.in.desc.SrcCK.low);
2791 pSrcSurf->setOverriddenSrcOverlayCKey(&ckey);
2792 }
2793 else
2794 {
2795 VBOXQGLLOG((", no KEYSRC"));
2796 pSrcSurf->setOverriddenSrcOverlayCKey(NULL);
2797 }
2798 VBOXQGLLOG(("\n"));
2799 if (pDstSurf)
2800 {
2801 QRect dstRect = VBOXVHWA_CONSTRUCT_QRECT_FROM_RECTL_WH(&pCmd->u.in.dstRect);
2802 QRect srcRect = VBOXVHWA_CONSTRUCT_QRECT_FROM_RECTL_WH(&pCmd->u.in.srcRect);
2803
2804 VBOXQGLLOG(("*******overlay update*******\n"));
2805 VBOXQGLLOG(("dstSurfSize: w(%d), h(%d)\n", pDstSurf->width(), pDstSurf->height()));
2806 VBOXQGLLOG(("srcSurfSize: w(%d), h(%d)\n", pSrcSurf->width(), pSrcSurf->height()));
2807 VBOXQGLLOG_QRECT("dstRect:", &dstRect, "\n");
2808 VBOXQGLLOG_QRECT("srcRect:", &srcRect, "\n");
2809
2810 pSrcSurf->setPrimary(pDstSurf);
2811
2812 pSrcSurf->setRects(dstRect, srcRect);
2813 }
2814}
2815
2816int VBoxVHWAImage::vhwaSurfaceOverlayUpdate(struct VBOXVHWACMD_SURF_OVERLAY_UPDATE RT_UNTRUSTED_VOLATILE_GUEST *pCmd)
2817{
2818 VBoxVHWASurfaceBase *pSrcSurf = handle2Surface(pCmd->u.in.hSrcSurf);
2819 AssertReturn(pSrcSurf, VERR_INVALID_PARAMETER);
2820 VBoxVHWASurfList *pList = pSrcSurf->getComplexList();
2821 vboxCheckUpdateAddress (pSrcSurf, pCmd->u.in.offSrcSurface);
2822 VBOXQGLLOG(("OverlayUpdate: pSrcSurf (0x%x)\n",pSrcSurf));
2823 VBoxVHWASurfaceBase *pDstSurf = NULL;
2824
2825 if (pCmd->u.in.hDstSurf)
2826 {
2827 pDstSurf = handle2Surface(pCmd->u.in.hDstSurf);
2828 AssertReturn(pDstSurf, VERR_INVALID_PARAMETER);
2829 vboxCheckUpdateAddress (pDstSurf, pCmd->u.in.offDstSurface);
2830 VBOXQGLLOG(("pDstSurf (0x%x)\n",pDstSurf));
2831#ifdef DEBUGVHWASTRICT
2832 Assert(pDstSurf == mDisplay.getVGA());
2833 Assert(mDisplay.getVGA() == mDisplay.getPrimary());
2834#endif
2835 Assert(pDstSurf->getComplexList() == mDisplay.getVGA()->getComplexList());
2836
2837 if (pCmd->u.in.flags & VBOXVHWA_OVER_SHOW)
2838 {
2839 if (pDstSurf != mDisplay.getPrimary())
2840 {
2841 mDisplay.updateVGA(pDstSurf);
2842 pDstSurf->getComplexList()->setCurrentVisible(pDstSurf);
2843 }
2844 }
2845 }
2846
2847#ifdef VBOX_WITH_WDDM
2848 if (pCmd->u.in.xFlags & VBOXVHWACMD_SURF_OVERLAY_UPDATE_F_SRCMEMRECT)
2849 {
2850 QRect r = VBOXVHWA_CONSTRUCT_QRECT_FROM_RECTL_WH(&pCmd->u.in.xUpdatedSrcMemRect);
2851 pSrcSurf->updatedMem(&r);
2852 }
2853 if (pCmd->u.in.xFlags & VBOXVHWACMD_SURF_OVERLAY_UPDATE_F_DSTMEMRECT)
2854 {
2855 AssertReturn(pDstSurf, VERR_INVALID_PARAMETER);
2856 QRect r = VBOXVHWA_CONSTRUCT_QRECT_FROM_RECTL_WH(&pCmd->u.in.xUpdatedDstMemRect);
2857 pDstSurf->updatedMem(&r);
2858 }
2859#endif
2860
2861 const SurfList & surfaces = pList->surfaces();
2862
2863 for (SurfList::const_iterator it = surfaces.begin();
2864 it != surfaces.end(); ++ it)
2865 {
2866 VBoxVHWASurfaceBase *pCurSrcSurf = (*it);
2867 vhwaDoSurfaceOverlayUpdate(pDstSurf, pCurSrcSurf, pCmd);
2868 }
2869
2870 if (pCmd->u.in.flags & VBOXVHWA_OVER_HIDE)
2871 {
2872 VBOXQGLLOG(("hide\n"));
2873 pList->setCurrentVisible(NULL);
2874 }
2875 else if (pCmd->u.in.flags & VBOXVHWA_OVER_SHOW)
2876 {
2877 VBOXQGLLOG(("show\n"));
2878 pList->setCurrentVisible(pSrcSurf);
2879 }
2880
2881 mRepaintNeeded = true;
2882
2883 return VINF_SUCCESS;
2884}
2885
2886int VBoxVHWAImage::vhwaSurfaceOverlaySetPosition(struct VBOXVHWACMD_SURF_OVERLAY_SETPOSITION RT_UNTRUSTED_VOLATILE_GUEST *pCmd)
2887{
2888 VBoxVHWASurfaceBase *pDstSurf = handle2Surface(pCmd->u.in.hDstSurf);
2889 AssertReturn(pDstSurf, VERR_INVALID_PARAMETER);
2890 VBoxVHWASurfaceBase *pSrcSurf = handle2Surface(pCmd->u.in.hSrcSurf);
2891 AssertReturn(pSrcSurf, VERR_INVALID_PARAMETER);
2892
2893 VBOXQGLLOG_ENTER(("pDstSurf (0x%x), pSrcSurf (0x%x)\n",pDstSurf,pSrcSurf));
2894
2895 vboxCheckUpdateAddress (pSrcSurf, pCmd->u.in.offSrcSurface);
2896 vboxCheckUpdateAddress (pDstSurf, pCmd->u.in.offDstSurface);
2897
2898 VBoxVHWASurfList *pList = pSrcSurf->getComplexList();
2899 const SurfList & surfaces = pList->surfaces();
2900
2901 QPoint pos(pCmd->u.in.xPos, pCmd->u.in.yPos);
2902
2903#ifdef DEBUGVHWASTRICT
2904 Assert(pDstSurf == mDisplay.getVGA());
2905 Assert(mDisplay.getVGA() == mDisplay.getPrimary());
2906#endif
2907 if (pSrcSurf->getComplexList()->current() != NULL)
2908 {
2909 Assert(pDstSurf);
2910 if (pDstSurf != mDisplay.getPrimary())
2911 {
2912 mDisplay.updateVGA(pDstSurf);
2913 pDstSurf->getComplexList()->setCurrentVisible(pDstSurf);
2914 }
2915 }
2916
2917 mRepaintNeeded = true;
2918
2919 for (SurfList::const_iterator it = surfaces.begin();
2920 it != surfaces.end(); ++ it)
2921 {
2922 VBoxVHWASurfaceBase *pCurSrcSurf = (*it);
2923 pCurSrcSurf->setTargRectPosition(pos);
2924 }
2925
2926 return VINF_SUCCESS;
2927}
2928
2929int VBoxVHWAImage::vhwaSurfaceColorkeySet(struct VBOXVHWACMD_SURF_COLORKEY_SET RT_UNTRUSTED_VOLATILE_GUEST *pCmd)
2930{
2931 VBoxVHWASurfaceBase *pSurf = handle2Surface(pCmd->u.in.hSurf);
2932 AssertReturn(pSurf, VERR_INVALID_PARAMETER);
2933 VBOXQGLLOG_ENTER(("pSurf (0x%x)\n", pSurf));
2934
2935 vboxCheckUpdateAddress (pSurf, pCmd->u.in.offSurface);
2936
2937 mRepaintNeeded = true;
2938
2939 if (pCmd->u.in.flags & VBOXVHWA_CKEY_DESTBLT)
2940 {
2941 VBoxVHWAColorKey ckey(pCmd->u.in.CKey.high, pCmd->u.in.CKey.low);
2942 pSurf->setDstBltCKey(&ckey);
2943 }
2944 if (pCmd->u.in.flags & VBOXVHWA_CKEY_DESTOVERLAY)
2945 {
2946 VBoxVHWAColorKey ckey(pCmd->u.in.CKey.high, pCmd->u.in.CKey.low);
2947 pSurf->setDefaultDstOverlayCKey(&ckey);
2948 }
2949 if (pCmd->u.in.flags & VBOXVHWA_CKEY_SRCBLT)
2950 {
2951 VBoxVHWAColorKey ckey(pCmd->u.in.CKey.high, pCmd->u.in.CKey.low);
2952 pSurf->setSrcBltCKey(&ckey);
2953
2954 }
2955 if (pCmd->u.in.flags & VBOXVHWA_CKEY_SRCOVERLAY)
2956 {
2957 VBoxVHWAColorKey ckey(pCmd->u.in.CKey.high, pCmd->u.in.CKey.low);
2958 pSurf->setDefaultSrcOverlayCKey(&ckey);
2959 }
2960
2961 return VINF_SUCCESS;
2962}
2963
2964int VBoxVHWAImage::vhwaQueryInfo1(struct VBOXVHWACMD_QUERYINFO1 RT_UNTRUSTED_VOLATILE_GUEST *pCmd)
2965{
2966 VBOXQGLLOG_ENTER(("\n"));
2967 bool bEnabled = false;
2968 const VBoxVHWAInfo & info = vboxVHWAGetSupportInfo(NULL);
2969 if (info.isVHWASupported())
2970 {
2971 Assert(pCmd->u.in.guestVersion.maj == VBOXVHWA_VERSION_MAJ);
2972 if (pCmd->u.in.guestVersion.maj == VBOXVHWA_VERSION_MAJ)
2973 {
2974 Assert(pCmd->u.in.guestVersion.min == VBOXVHWA_VERSION_MIN);
2975 if (pCmd->u.in.guestVersion.min == VBOXVHWA_VERSION_MIN)
2976 {
2977 Assert(pCmd->u.in.guestVersion.bld == VBOXVHWA_VERSION_BLD);
2978 if (pCmd->u.in.guestVersion.bld == VBOXVHWA_VERSION_BLD)
2979 {
2980 Assert(pCmd->u.in.guestVersion.reserved == VBOXVHWA_VERSION_RSV);
2981 if (pCmd->u.in.guestVersion.reserved == VBOXVHWA_VERSION_RSV)
2982 {
2983 bEnabled = true;
2984 }
2985 }
2986 }
2987 }
2988 }
2989
2990 memset((void *)pCmd, 0, sizeof(VBOXVHWACMD_QUERYINFO1));
2991 if (bEnabled)
2992 {
2993 pCmd->u.out.cfgFlags = VBOXVHWA_CFG_ENABLED;
2994
2995 pCmd->u.out.caps =
2996 /* we do not support blitting for now */
2997// VBOXVHWA_CAPS_BLT | VBOXVHWA_CAPS_BLTSTRETCH | VBOXVHWA_CAPS_BLTQUEUE
2998// | VBOXVHWA_CAPS_BLTCOLORFILL not supported, although adding it is trivial
2999// | VBOXVHWA_CAPS_BLTFOURCC set below if shader support is available
3000 VBOXVHWA_CAPS_OVERLAY
3001 | VBOXVHWA_CAPS_OVERLAYSTRETCH
3002 | VBOXVHWA_CAPS_OVERLAYCANTCLIP
3003 // | VBOXVHWA_CAPS_OVERLAYFOURCC set below if shader support is available
3004 ;
3005
3006 /** @todo check if we could use DDSCAPS_ALPHA instead of colorkeying */
3007
3008 pCmd->u.out.caps2 = VBOXVHWA_CAPS2_CANRENDERWINDOWED
3009 | VBOXVHWA_CAPS2_WIDESURFACES;
3010
3011 /// @todo setup stretchCaps
3012 pCmd->u.out.stretchCaps = 0;
3013
3014 pCmd->u.out.numOverlays = 1;
3015 /** @todo set curOverlays properly */
3016 pCmd->u.out.curOverlays = 0;
3017
3018 pCmd->u.out.surfaceCaps = VBOXVHWA_SCAPS_PRIMARYSURFACE
3019#ifndef VBOXVHWA_ALLOW_PRIMARY_AND_OVERLAY_ONLY
3020 | VBOXVHWA_SCAPS_OFFSCREENPLAIN
3021#endif
3022 | VBOXVHWA_SCAPS_FLIP
3023 | VBOXVHWA_SCAPS_LOCALVIDMEM
3024 | VBOXVHWA_SCAPS_OVERLAY
3025 // | VBOXVHWA_SCAPS_BACKBUFFER
3026 // | VBOXVHWA_SCAPS_FRONTBUFFER
3027 // | VBOXVHWA_SCAPS_VIDEOMEMORY
3028 // | VBOXVHWA_SCAPS_COMPLEX
3029 // | VBOXVHWA_SCAPS_VISIBLE
3030 ;
3031
3032 if (info.getGlInfo().isFragmentShaderSupported() && info.getGlInfo().getMultiTexNumSupported() >= 2)
3033 {
3034 pCmd->u.out.caps |= VBOXVHWA_CAPS_COLORKEY
3035 | VBOXVHWA_CAPS_COLORKEYHWASSIST;
3036
3037 pCmd->u.out.colorKeyCaps = 0
3038// | VBOXVHWA_CKEYCAPS_DESTBLT | VBOXVHWA_CKEYCAPS_DESTBLTCLRSPACE
3039// | VBOXVHWA_CKEYCAPS_SRCBLT| VBOXVHWA_CKEYCAPS_SRCBLTCLRSPACE
3040// | VBOXVHWA_CKEYCAPS_SRCOVERLAY | VBOXVHWA_CKEYCAPS_SRCOVERLAYONEACTIVE
3041 | VBOXVHWA_CKEYCAPS_DESTOVERLAY
3042 | VBOXVHWA_CKEYCAPS_DESTOVERLAYONEACTIVE;
3043
3044 if (info.getGlInfo().isTextureRectangleSupported())
3045 {
3046 pCmd->u.out.caps |= VBOXVHWA_CAPS_OVERLAYFOURCC
3047// | VBOXVHWA_CAPS_BLTFOURCC
3048 ;
3049
3050 pCmd->u.out.colorKeyCaps |= 0
3051// | VBOXVHWA_CKEYCAPS_SRCOVERLAYYUV
3052 | VBOXVHWA_CKEYCAPS_DESTOVERLAYYUV;
3053
3054// pCmd->u.out.caps2 |= VBOXVHWA_CAPS2_COPYFOURCC;
3055
3056 pCmd->u.out.numFourCC = mSettings->getIntersection(info, 0, NULL);
3057 }
3058 }
3059 }
3060
3061 return VINF_SUCCESS;
3062}
3063
3064int VBoxVHWAImage::vhwaQueryInfo2(struct VBOXVHWACMD_QUERYINFO2 RT_UNTRUSTED_VOLATILE_GUEST *pCmd)
3065{
3066 VBOXQGLLOG_ENTER(("\n"));
3067
3068 const VBoxVHWAInfo &info = vboxVHWAGetSupportInfo(NULL);
3069 uint32_t aFourcc[VBOXVHWA_NUMFOURCC];
3070 int num = mSettings->getIntersection(info, VBOXVHWA_NUMFOURCC, aFourcc);
3071 Assert(pCmd->numFourCC >= (uint32_t)num);
3072 if (pCmd->numFourCC < (uint32_t)num)
3073 return VERR_GENERAL_FAILURE;
3074
3075 pCmd->numFourCC = (uint32_t)num;
3076 memcpy((void *)&pCmd->FourCC[0], aFourcc, num * sizeof(aFourcc[0]));
3077 return VINF_SUCCESS;
3078}
3079
3080//static DECLCALLBACK(void) vboxQGLSaveExec(PSSMHANDLE pSSM, void *pvUser)
3081//{
3082// VBoxVHWAImage * pw = (VBoxVHWAImage*)pvUser;
3083// pw->vhwaSaveExec(pSSM);
3084//}
3085//
3086//static DECLCALLBACK(int) vboxQGLLoadExec(PSSMHANDLE pSSM, void *pvUser, uint32_t u32Version, uint32_t uPass)
3087//{
3088// Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
3089// VBoxVHWAImage * pw = (VBoxVHWAImage*)pvUser;
3090// return VBoxVHWAImage::vhwaLoadExec(&pw->onResizeCmdList(), pSSM, u32Version);
3091//}
3092
3093int VBoxVHWAImage::vhwaSaveSurface(struct SSMHANDLE *pSSM, VBoxVHWASurfaceBase *pSurf, uint32_t surfCaps)
3094{
3095 VBOXQGL_SAVE_SURFSTART(pSSM);
3096
3097 uint64_t u64 = vboxVRAMOffset(pSurf);
3098 int rc;
3099 rc = SSMR3PutU32(pSSM, pSurf->handle());
3100 rc = SSMR3PutU64(pSSM, u64);
3101 rc = SSMR3PutU32(pSSM, pSurf->width());
3102 rc = SSMR3PutU32(pSSM, pSurf->height());
3103 rc = SSMR3PutU32(pSSM, surfCaps);
3104
3105 uint32_t flags = 0;
3106 const VBoxVHWAColorKey *pDstBltCKey = pSurf->dstBltCKey();
3107 const VBoxVHWAColorKey *pSrcBltCKey = pSurf->srcBltCKey();
3108 const VBoxVHWAColorKey *pDstOverlayCKey = pSurf->dstOverlayCKey();
3109 const VBoxVHWAColorKey *pSrcOverlayCKey = pSurf->srcOverlayCKey();
3110 if (pDstBltCKey)
3111 flags |= VBOXVHWA_SD_CKDESTBLT;
3112 if (pSrcBltCKey)
3113 flags |= VBOXVHWA_SD_CKSRCBLT;
3114 if (pDstOverlayCKey)
3115 flags |= VBOXVHWA_SD_CKDESTOVERLAY;
3116 if (pSrcOverlayCKey)
3117 flags |= VBOXVHWA_SD_CKSRCOVERLAY;
3118 rc = SSMR3PutU32(pSSM, flags);
3119
3120 if (pDstBltCKey)
3121 {
3122 rc = SSMR3PutU32(pSSM, pDstBltCKey->lower());
3123 rc = SSMR3PutU32(pSSM, pDstBltCKey->upper());
3124 }
3125 if (pSrcBltCKey)
3126 {
3127 rc = SSMR3PutU32(pSSM, pSrcBltCKey->lower());
3128 rc = SSMR3PutU32(pSSM, pSrcBltCKey->upper());
3129 }
3130 if (pDstOverlayCKey)
3131 {
3132 rc = SSMR3PutU32(pSSM, pDstOverlayCKey->lower());
3133 rc = SSMR3PutU32(pSSM, pDstOverlayCKey->upper());
3134 }
3135 if (pSrcOverlayCKey)
3136 {
3137 rc = SSMR3PutU32(pSSM, pSrcOverlayCKey->lower());
3138 rc = SSMR3PutU32(pSSM, pSrcOverlayCKey->upper());
3139 }
3140 AssertRCReturn(rc, rc);
3141
3142 const VBoxVHWAColorFormat & format = pSurf->pixelFormat();
3143 flags = 0;
3144 if (format.fourcc())
3145 {
3146 flags |= VBOXVHWA_PF_FOURCC;
3147 rc = SSMR3PutU32(pSSM, flags);
3148 rc = SSMR3PutU32(pSSM, format.fourcc());
3149 }
3150 else
3151 {
3152 flags |= VBOXVHWA_PF_RGB;
3153 rc = SSMR3PutU32(pSSM, flags);
3154 rc = SSMR3PutU32(pSSM, format.bitsPerPixel());
3155 rc = SSMR3PutU32(pSSM, format.r().mask());
3156 rc = SSMR3PutU32(pSSM, format.g().mask());
3157 rc = SSMR3PutU32(pSSM, format.b().mask());
3158 rc = SSMR3PutU32(pSSM, format.a().mask());
3159 }
3160 AssertRCReturn(rc, rc);
3161
3162 VBOXQGL_SAVE_SURFSTOP(pSSM);
3163 return rc;
3164}
3165
3166int VBoxVHWAImage::vhwaLoadSurface(VHWACommandList * pCmdList, struct SSMHANDLE * pSSM, uint32_t cBackBuffers, uint32_t u32Version)
3167{
3168 Q_UNUSED(u32Version);
3169
3170 VBOXQGL_LOAD_SURFSTART(pSSM);
3171
3172 char *buf = (char*)malloc(VBOXVHWACMD_SIZE(VBOXVHWACMD_SURF_CREATE));
3173 memset(buf, 0, sizeof(VBOXVHWACMD_SIZE(VBOXVHWACMD_SURF_CREATE)));
3174 VBOXVHWACMD *pCmd = (VBOXVHWACMD *)buf;
3175 pCmd->enmCmd = VBOXVHWACMD_TYPE_SURF_CREATE;
3176 pCmd->Flags = VBOXVHWACMD_FLAG_HH_CMD;
3177
3178 VBOXVHWACMD_SURF_CREATE *pCreateSurf = VBOXVHWACMD_BODY_HOST_HEAP(pCmd, VBOXVHWACMD_SURF_CREATE);
3179 int rc;
3180 uint32_t u32;
3181 rc = SSMR3GetU32(pSSM, &u32); AssertRC(rc);
3182 pCreateSurf->SurfInfo.hSurf = (VBOXVHWA_SURFHANDLE)u32;
3183 if (RT_SUCCESS(rc))
3184 {
3185 rc = SSMR3GetU64(pSSM, &pCreateSurf->SurfInfo.offSurface); AssertRC(rc);
3186 rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.width); AssertRC(rc);
3187 rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.height); AssertRC(rc);
3188 rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.surfCaps); AssertRC(rc);
3189 rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.flags); AssertRC(rc);
3190 if (pCreateSurf->SurfInfo.flags & VBOXVHWA_SD_CKDESTBLT)
3191 {
3192 rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.DstBltCK.low); AssertRC(rc);
3193 rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.DstBltCK.high); AssertRC(rc);
3194 }
3195 if (pCreateSurf->SurfInfo.flags & VBOXVHWA_SD_CKSRCBLT)
3196 {
3197 rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.SrcBltCK.low); AssertRC(rc);
3198 rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.SrcBltCK.high); AssertRC(rc);
3199 }
3200 if (pCreateSurf->SurfInfo.flags & VBOXVHWA_SD_CKDESTOVERLAY)
3201 {
3202 rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.DstOverlayCK.low); AssertRC(rc);
3203 rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.DstOverlayCK.high); AssertRC(rc);
3204 }
3205 if (pCreateSurf->SurfInfo.flags & VBOXVHWA_SD_CKSRCOVERLAY)
3206 {
3207 rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.SrcOverlayCK.low); AssertRC(rc);
3208 rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.SrcOverlayCK.high); AssertRC(rc);
3209 }
3210
3211 rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.PixelFormat.flags); AssertRC(rc);
3212 if (pCreateSurf->SurfInfo.PixelFormat.flags & VBOXVHWA_PF_RGB)
3213 {
3214 rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.PixelFormat.c.rgbBitCount); AssertRC(rc);
3215 rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.PixelFormat.m1.rgbRBitMask); AssertRC(rc);
3216 rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.PixelFormat.m2.rgbGBitMask); AssertRC(rc);
3217 rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.PixelFormat.m3.rgbBBitMask); AssertRC(rc);
3218 rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.PixelFormat.m4.rgbABitMask); AssertRC(rc);
3219 }
3220 else if (pCreateSurf->SurfInfo.PixelFormat.flags & VBOXVHWA_PF_FOURCC)
3221 {
3222 rc = SSMR3GetU32(pSSM, &pCreateSurf->SurfInfo.PixelFormat.fourCC);
3223 AssertRC(rc);
3224 }
3225 else
3226 {
3227 AssertFailed();
3228 }
3229 AssertRCReturnStmt(rc, free(buf), rc);
3230
3231 if (cBackBuffers)
3232 {
3233 pCreateSurf->SurfInfo.cBackBuffers = cBackBuffers;
3234 pCreateSurf->SurfInfo.surfCaps |= VBOXVHWA_SCAPS_COMPLEX;
3235 }
3236
3237 pCmdList->push_back(pCmd);
3238// vboxExecOnResize(&VBoxVHWAImage::vboxDoVHWACmdAndFree, pCmd); AssertRC(rc);
3239// if (RT_SUCCESS(rc))
3240// {
3241// rc = pCmd->rc;
3242// AssertRC(rc);
3243// }
3244 }
3245 else
3246 free(buf);
3247
3248 VBOXQGL_LOAD_SURFSTOP(pSSM);
3249
3250 return rc;
3251}
3252
3253int VBoxVHWAImage::vhwaSaveOverlayData(struct SSMHANDLE * pSSM, VBoxVHWASurfaceBase *pSurf, bool bVisible)
3254{
3255 VBOXQGL_SAVE_OVERLAYSTART(pSSM);
3256
3257 uint32_t flags = 0;
3258 const VBoxVHWAColorKey * dstCKey = pSurf->dstOverlayCKey();
3259 const VBoxVHWAColorKey * defaultDstCKey = pSurf->defaultDstOverlayCKey();
3260 const VBoxVHWAColorKey * srcCKey = pSurf->srcOverlayCKey();;
3261 const VBoxVHWAColorKey * defaultSrcCKey = pSurf->defaultSrcOverlayCKey();
3262 bool bSaveDstCKey = false;
3263 bool bSaveSrcCKey = false;
3264
3265 if (bVisible)
3266 {
3267 flags |= VBOXVHWA_OVER_SHOW;
3268 }
3269 else
3270 {
3271 flags |= VBOXVHWA_OVER_HIDE;
3272 }
3273
3274 if (!dstCKey)
3275 {
3276 flags |= VBOXVHWA_OVER_KEYDEST;
3277 }
3278 else if (defaultDstCKey)
3279 {
3280 flags |= VBOXVHWA_OVER_KEYDESTOVERRIDE;
3281 bSaveDstCKey = true;
3282 }
3283
3284 if (srcCKey == defaultSrcCKey)
3285 {
3286 flags |= VBOXVHWA_OVER_KEYSRC;
3287 }
3288 else if (srcCKey)
3289 {
3290 flags |= VBOXVHWA_OVER_KEYSRCOVERRIDE;
3291 bSaveSrcCKey = true;
3292 }
3293
3294 int rc = SSMR3PutU32(pSSM, flags);
3295
3296 rc = SSMR3PutU32(pSSM, mDisplay.getPrimary()->handle());
3297 rc = SSMR3PutU32(pSSM, pSurf->handle());
3298
3299 if (bSaveDstCKey)
3300 {
3301 rc = SSMR3PutU32(pSSM, dstCKey->lower());
3302 rc = SSMR3PutU32(pSSM, dstCKey->upper());
3303 }
3304 if (bSaveSrcCKey)
3305 {
3306 rc = SSMR3PutU32(pSSM, srcCKey->lower());
3307 rc = SSMR3PutU32(pSSM, srcCKey->upper());
3308 }
3309
3310 int x1, x2, y1, y2;
3311 pSurf->targRect().getCoords(&x1, &y1, &x2, &y2);
3312 rc = SSMR3PutS32(pSSM, x1);
3313 rc = SSMR3PutS32(pSSM, x2+1);
3314 rc = SSMR3PutS32(pSSM, y1);
3315 rc = SSMR3PutS32(pSSM, y2+1);
3316
3317 pSurf->srcRect().getCoords(&x1, &y1, &x2, &y2);
3318 rc = SSMR3PutS32(pSSM, x1);
3319 rc = SSMR3PutS32(pSSM, x2+1);
3320 rc = SSMR3PutS32(pSSM, y1);
3321 rc = SSMR3PutS32(pSSM, y2+1);
3322 AssertRCReturn(rc, rc);
3323
3324 VBOXQGL_SAVE_OVERLAYSTOP(pSSM);
3325
3326 return rc;
3327}
3328
3329int VBoxVHWAImage::vhwaLoadOverlayData(VHWACommandList *pCmdList, struct SSMHANDLE *pSSM, uint32_t u32Version)
3330{
3331 Q_UNUSED(u32Version);
3332
3333 VBOXQGL_LOAD_OVERLAYSTART(pSSM);
3334
3335 char *buf = new char[VBOXVHWACMD_SIZE(VBOXVHWACMD_SURF_CREATE)];
3336 memset(buf, 0, VBOXVHWACMD_SIZE(VBOXVHWACMD_SURF_CREATE));
3337 VBOXVHWACMD * pCmd = (VBOXVHWACMD*)buf;
3338 pCmd->enmCmd = VBOXVHWACMD_TYPE_SURF_OVERLAY_UPDATE;
3339 pCmd->Flags = VBOXVHWACMD_FLAG_HH_CMD;
3340
3341 VBOXVHWACMD_SURF_OVERLAY_UPDATE *pUpdateOverlay = VBOXVHWACMD_BODY_HOST_HEAP(pCmd, VBOXVHWACMD_SURF_OVERLAY_UPDATE);
3342 int rc;
3343
3344 rc = SSMR3GetU32(pSSM, &pUpdateOverlay->u.in.flags); AssertRC(rc);
3345 uint32_t hSrc, hDst;
3346 rc = SSMR3GetU32(pSSM, &hDst); AssertRC(rc);
3347 rc = SSMR3GetU32(pSSM, &hSrc); AssertRC(rc);
3348 pUpdateOverlay->u.in.hSrcSurf = hSrc;
3349 pUpdateOverlay->u.in.hDstSurf = hDst;
3350 {
3351 pUpdateOverlay->u.in.offDstSurface = VBOXVHWA_OFFSET64_VOID;
3352 pUpdateOverlay->u.in.offSrcSurface = VBOXVHWA_OFFSET64_VOID;
3353
3354 if (pUpdateOverlay->u.in.flags & VBOXVHWA_OVER_KEYDESTOVERRIDE)
3355 {
3356 rc = SSMR3GetU32(pSSM, &pUpdateOverlay->u.in.desc.DstCK.low); AssertRC(rc);
3357 rc = SSMR3GetU32(pSSM, &pUpdateOverlay->u.in.desc.DstCK.high); AssertRC(rc);
3358 }
3359
3360 if (pUpdateOverlay->u.in.flags & VBOXVHWA_OVER_KEYSRCOVERRIDE)
3361 {
3362 rc = SSMR3GetU32(pSSM, &pUpdateOverlay->u.in.desc.SrcCK.low); AssertRC(rc);
3363 rc = SSMR3GetU32(pSSM, &pUpdateOverlay->u.in.desc.SrcCK.high); AssertRC(rc);
3364 }
3365
3366 rc = SSMR3GetS32(pSSM, &pUpdateOverlay->u.in.dstRect.left); AssertRC(rc);
3367 rc = SSMR3GetS32(pSSM, &pUpdateOverlay->u.in.dstRect.right); AssertRC(rc);
3368 rc = SSMR3GetS32(pSSM, &pUpdateOverlay->u.in.dstRect.top); AssertRC(rc);
3369 rc = SSMR3GetS32(pSSM, &pUpdateOverlay->u.in.dstRect.bottom); AssertRC(rc);
3370
3371 rc = SSMR3GetS32(pSSM, &pUpdateOverlay->u.in.srcRect.left); AssertRC(rc);
3372 rc = SSMR3GetS32(pSSM, &pUpdateOverlay->u.in.srcRect.right); AssertRC(rc);
3373 rc = SSMR3GetS32(pSSM, &pUpdateOverlay->u.in.srcRect.top); AssertRC(rc);
3374 rc = SSMR3GetS32(pSSM, &pUpdateOverlay->u.in.srcRect.bottom);
3375 AssertRCReturnStmt(rc, free(buf), rc);
3376
3377 pCmdList->push_back(pCmd);
3378 }
3379
3380 VBOXQGL_LOAD_OVERLAYSTOP(pSSM);
3381
3382 return rc;
3383}
3384
3385void VBoxVHWAImage::vhwaSaveExecVoid(struct SSMHANDLE *pSSM)
3386{
3387 VBOXQGL_SAVE_START(pSSM);
3388 SSMR3PutU32(pSSM, 0); /* 0 primaries */
3389 VBOXQGL_SAVE_STOP(pSSM);
3390}
3391
3392void VBoxVHWAImage::vhwaSaveExec(struct SSMHANDLE *pSSM)
3393{
3394 VBOXQGL_SAVE_START(pSSM);
3395
3396 /* the mechanism of restoring data is based on generating VHWA commands that restore the surfaces state
3397 * the following commands are generated:
3398 * I. CreateSurface
3399 * II. UpdateOverlay
3400 *
3401 * Data format is the following:
3402 * I. u32 - Num primary surfaces - (the current frontbuffer is detected in the stored surf flags which are posted to the generated CreateSurface cmd)
3403 * II. for each primary surf
3404 * II.1 generate & execute CreateSurface cmd (see below on the generation logic)
3405 * III. u32 - Num overlays
3406 * IV. for each overlay
3407 * 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)
3408 * IV.2 for each surface in overlay
3409 * IV.2.a generate & execute CreateSurface cmd (see below on the generation logic)
3410 * IV.2.b generate & execute UpdateOverlay cmd (see below on the generation logic)
3411 *
3412 */
3413 const SurfList & primaryList = mDisplay.primaries().surfaces();
3414 uint32_t cPrimary = (uint32_t)primaryList.size();
3415 if ( cPrimary
3416 && ( mDisplay.getVGA() == NULL
3417 || mDisplay.getVGA()->handle() == VBOXVHWA_SURFHANDLE_INVALID))
3418 {
3419 cPrimary -= 1;
3420 }
3421
3422 int rc = SSMR3PutU32(pSSM, cPrimary);
3423 AssertRCReturnVoid(rc);
3424 if (cPrimary)
3425 {
3426 for (SurfList::const_iterator pr = primaryList.begin(); pr != primaryList.end(); ++ pr)
3427 {
3428 VBoxVHWASurfaceBase *pSurf = *pr;
3429 // bool bVga = (pSurf == mDisplay.getVGA());
3430 bool bVisible = (pSurf == mDisplay.getPrimary());
3431 uint32_t flags = VBOXVHWA_SCAPS_PRIMARYSURFACE;
3432 if (bVisible)
3433 flags |= VBOXVHWA_SCAPS_VISIBLE;
3434
3435 if (pSurf->handle() != VBOXVHWA_SURFHANDLE_INVALID)
3436 {
3437 rc = vhwaSaveSurface(pSSM, *pr, flags);
3438#ifdef DEBUG
3439 --cPrimary;
3440 Assert(cPrimary < UINT32_MAX / 2);
3441#endif
3442 }
3443 else
3444 {
3445 Assert(pSurf == mDisplay.getVGA());
3446 }
3447 }
3448
3449#ifdef DEBUG
3450 Assert(!cPrimary);
3451#endif
3452
3453 const OverlayList & overlays = mDisplay.overlays();
3454 rc = SSMR3PutU32(pSSM, (uint32_t)overlays.size());
3455
3456 for (OverlayList::const_iterator it = overlays.begin(); it != overlays.end(); ++ it)
3457 {
3458 VBoxVHWASurfList * pSurfList = *it;
3459 const SurfList & surfaces = pSurfList->surfaces();
3460 uint32_t cSurfs = (uint32_t)surfaces.size();
3461 uint32_t flags = VBOXVHWA_SCAPS_OVERLAY;
3462 if (cSurfs > 1)
3463 flags |= VBOXVHWA_SCAPS_COMPLEX;
3464 rc = SSMR3PutU32(pSSM, cSurfs);
3465 for (SurfList::const_iterator sit = surfaces.begin(); sit != surfaces.end(); ++ sit)
3466 rc = vhwaSaveSurface(pSSM, *sit, flags);
3467
3468 bool bVisible = true;
3469 VBoxVHWASurfaceBase * pOverlayData = pSurfList->current();
3470 if (!pOverlayData)
3471 {
3472 pOverlayData = surfaces.front();
3473 bVisible = false;
3474 }
3475
3476 rc = vhwaSaveOverlayData(pSSM, pOverlayData, bVisible);
3477 }
3478 }
3479
3480 VBOXQGL_SAVE_STOP(pSSM);
3481}
3482
3483int VBoxVHWAImage::vhwaLoadVHWAEnable(VHWACommandList * pCmdList)
3484{
3485 char *buf = (char *)malloc(sizeof(VBOXVHWACMD));
3486 Assert(buf);
3487 if (buf)
3488 {
3489 memset(buf, 0, sizeof(VBOXVHWACMD));
3490 VBOXVHWACMD *pCmd = (VBOXVHWACMD *)buf;
3491 pCmd->enmCmd = VBOXVHWACMD_TYPE_ENABLE;
3492 pCmd->Flags = VBOXVHWACMD_FLAG_HH_CMD;
3493 pCmdList->push_back(pCmd);
3494 return VINF_SUCCESS;
3495 }
3496
3497 return VERR_OUT_OF_RESOURCES;
3498}
3499
3500int VBoxVHWAImage::vhwaLoadExec(VHWACommandList *pCmdList, struct SSMHANDLE * pSSM, uint32_t u32Version)
3501{
3502 VBOXQGL_LOAD_START(pSSM);
3503
3504 if (u32Version > VBOXQGL_STATE_VERSION)
3505 return VERR_VERSION_MISMATCH;
3506
3507 int rc;
3508 uint32_t u32;
3509
3510 rc = vhwaLoadVHWAEnable(pCmdList); AssertRC(rc);
3511 if (RT_SUCCESS(rc))
3512 {
3513 rc = SSMR3GetU32(pSSM, &u32); AssertRC(rc);
3514 if (RT_SUCCESS(rc))
3515 {
3516 if (u32Version == 1U && u32 == UINT32_MAX) /* work around the v1 bug */
3517 u32 = 0;
3518 if (u32)
3519 {
3520 for (uint32_t i = 0; i < u32; ++i)
3521 {
3522 rc = vhwaLoadSurface(pCmdList, pSSM, 0, u32Version);
3523 AssertRCBreak(rc);
3524 }
3525
3526 if (RT_SUCCESS(rc))
3527 {
3528 rc = SSMR3GetU32(pSSM, &u32); AssertRC(rc);
3529 if (RT_SUCCESS(rc))
3530 {
3531 for (uint32_t i = 0; i < u32; ++i)
3532 {
3533 uint32_t cSurfs;
3534 rc = SSMR3GetU32(pSSM, &cSurfs); AssertRC(rc);
3535 for (uint32_t j = 0; j < cSurfs; ++j)
3536 {
3537 rc = vhwaLoadSurface(pCmdList, pSSM, cSurfs - 1, u32Version);
3538 AssertRCBreak(rc);
3539 }
3540
3541 if (RT_SUCCESS(rc))
3542 {
3543 rc = vhwaLoadOverlayData(pCmdList, pSSM, u32Version);
3544 AssertRCBreak(rc);
3545 }
3546 else
3547 break;
3548 }
3549 }
3550 }
3551 }
3552#ifdef VBOXQGL_STATE_DEBUG
3553 else if (u32Version == 1) /* read the 0 overlay count to ensure the following VBOXQGL_LOAD_STOP succeeds */
3554 {
3555 rc = SSMR3GetU32(pSSM, &u32);
3556 AssertRC(rc);
3557 Assert(u32 == 0 || RT_FAILURE(rc));
3558 }
3559#endif
3560 }
3561 }
3562
3563 VBOXQGL_LOAD_STOP(pSSM);
3564
3565 return rc;
3566}
3567
3568int VBoxVHWAImage::vhwaConstruct(struct VBOXVHWACMD_HH_CONSTRUCT *pCmd)
3569{
3570// PVM pVM = (PVM)pCmd->pVM;
3571// uint32_t intsId = 0; /** @todo set the proper id */
3572//
3573// char nameFuf[sizeof(VBOXQGL_STATE_NAMEBASE) + 8];
3574//
3575// char * pszName = nameFuf;
3576// sprintf(pszName, "%s%d", VBOXQGL_STATE_NAMEBASE, intsId);
3577// int rc = SSMR3RegisterExternal(
3578// pVM, /* The VM handle*/
3579// pszName, /* Data unit name. */
3580// intsId, /* The instance identifier of the data unit.
3581// * This must together with the name be unique. */
3582// VBOXQGL_STATE_VERSION, /* Data layout version number. */
3583// 128, /* The approximate amount of data in the unit.
3584// * Only for progress indicators. */
3585// NULL, NULL, NULL, /* pfnLiveXxx */
3586// NULL, /* Prepare save callback, optional. */
3587// vboxQGLSaveExec, /* Execute save callback, optional. */
3588// NULL, /* Done save callback, optional. */
3589// NULL, /* Prepare load callback, optional. */
3590// vboxQGLLoadExec, /* Execute load callback, optional. */
3591// NULL, /* Done load callback, optional. */
3592// this /* User argument. */
3593// );
3594// AssertRC(rc);
3595 mpvVRAM = pCmd->pvVRAM;
3596 mcbVRAM = pCmd->cbVRAM;
3597 return VINF_SUCCESS;
3598}
3599
3600uchar *VBoxVHWAImage::vboxVRAMAddressFromOffset(uint64_t offset)
3601{
3602 /** @todo check vramSize() */
3603 return (offset != VBOXVHWA_OFFSET64_VOID) ? ((uint8_t *)vramBase()) + offset : NULL;
3604}
3605
3606uint64_t VBoxVHWAImage::vboxVRAMOffsetFromAddress(uchar *addr)
3607{
3608 return uint64_t(addr - ((uchar *)vramBase()));
3609}
3610
3611uint64_t VBoxVHWAImage::vboxVRAMOffset(VBoxVHWASurfaceBase *pSurf)
3612{
3613 return pSurf->addressAlocated() ? VBOXVHWA_OFFSET64_VOID : vboxVRAMOffsetFromAddress(pSurf->address());
3614}
3615
3616#endif
3617
3618#ifdef VBOXQGL_DBG_SURF
3619
3620int g_iCur = 0;
3621VBoxVHWASurfaceBase *g_apSurf[] = {NULL, NULL, NULL};
3622
3623void VBoxVHWAImage::vboxDoTestSurfaces(void *context)
3624{
3625 if (g_iCur >= RT_ELEMENTS(g_apSurf))
3626 g_iCur = 0;
3627 VBoxVHWASurfaceBase * pSurf1 = g_apSurf[g_iCur];
3628 if (pSurf1)
3629 pSurf1->getComplexList()->setCurrentVisible(pSurf1);
3630}
3631#endif
3632
3633void VBoxVHWAImage::vboxDoUpdateViewport(const QRect & aRect)
3634{
3635 adjustViewport(mDisplay.getPrimary()->size(), aRect);
3636 mViewport = aRect;
3637
3638 const SurfList &primaryList = mDisplay.primaries().surfaces();
3639
3640 for (SurfList::const_iterator pr = primaryList.begin(); pr != primaryList.end(); ++pr)
3641 {
3642 VBoxVHWASurfaceBase *pSurf = *pr;
3643 pSurf->updateVisibility(NULL, aRect, false, false);
3644 }
3645
3646 const OverlayList & overlays = mDisplay.overlays();
3647 QRect overInter = overlaysRectIntersection();
3648 overInter = overInter.intersected(aRect);
3649
3650 bool bDisplayPrimary = true;
3651
3652 for (OverlayList::const_iterator it = overlays.begin(); it != overlays.end(); ++it)
3653 {
3654 VBoxVHWASurfList *pSurfList = *it;
3655 const SurfList &surfaces = pSurfList->surfaces();
3656 if (surfaces.size())
3657 {
3658 bool bNotIntersected = !overInter.isEmpty() && surfaces.front()->targRect().contains(overInter);
3659 Assert(bNotIntersected);
3660
3661 bDisplayPrimary &= !bNotIntersected;
3662 for (SurfList::const_iterator sit = surfaces.begin();
3663 sit != surfaces.end(); ++ sit)
3664 {
3665 VBoxVHWASurfaceBase *pSurf = *sit;
3666 pSurf->updateVisibility(mDisplay.getPrimary(), aRect, bNotIntersected, false);
3667 }
3668 }
3669 }
3670
3671 Assert(!bDisplayPrimary);
3672 mDisplay.setDisplayPrimary(bDisplayPrimary);
3673}
3674
3675bool VBoxVHWAImage::hasSurfaces() const
3676{
3677 if (mDisplay.overlays().size() != 0)
3678 return true;
3679 if (mDisplay.primaries().size() > 1)
3680 return true;
3681 /* in case gl was never turned on, we have no surfaces at all including VGA */
3682 if (!mDisplay.getVGA())
3683 return false;
3684 return mDisplay.getVGA()->handle() != VBOXVHWA_SURFHANDLE_INVALID;
3685}
3686
3687bool VBoxVHWAImage::hasVisibleOverlays()
3688{
3689 const OverlayList &overlays = mDisplay.overlays();
3690 for (OverlayList::const_iterator it = overlays.begin(); it != overlays.end(); ++ it)
3691 {
3692 VBoxVHWASurfList * pSurfList = *it;
3693 if (pSurfList->current() != NULL)
3694 return true;
3695 }
3696 return false;
3697}
3698
3699QRect VBoxVHWAImage::overlaysRectUnion()
3700{
3701 const OverlayList &overlays = mDisplay.overlays();
3702 VBoxVHWADirtyRect un;
3703 for (OverlayList::const_iterator it = overlays.begin(); it != overlays.end(); ++ it)
3704 {
3705 VBoxVHWASurfaceBase *pOverlay = (*it)->current();
3706 if (pOverlay != NULL)
3707 un.add(pOverlay->targRect());
3708 }
3709 return un.toRect();
3710}
3711
3712QRect VBoxVHWAImage::overlaysRectIntersection()
3713{
3714 const OverlayList &overlays = mDisplay.overlays();
3715 QRect rect;
3716 VBoxVHWADirtyRect un;
3717 for (OverlayList::const_iterator it = overlays.begin(); it != overlays.end(); ++ it)
3718 {
3719 VBoxVHWASurfaceBase *pOverlay = (*it)->current();
3720 if (pOverlay != NULL)
3721 {
3722 if (rect.isNull())
3723 rect = pOverlay->targRect();
3724 else
3725 {
3726 rect = rect.intersected(pOverlay->targRect());
3727 if (rect.isNull())
3728 break;
3729 }
3730 }
3731 }
3732 return rect;
3733}
3734
3735void VBoxVHWAImage::vboxDoUpdateRect(const QRect *pRect)
3736{
3737 mDisplay.getPrimary()->updatedMem(pRect);
3738}
3739
3740void VBoxVHWAImage::resize(const VBoxFBSizeInfo &size)
3741{
3742 VBOXQGL_CHECKERR(
3743 vboxglActiveTexture(GL_TEXTURE0);
3744 );
3745
3746 bool remind = false;
3747 bool fallback = false;
3748
3749 VBOXQGLLOG(("resizing: fmt=%d, vram=%p, bpp=%d, bpl=%d, width=%d, height=%d\n",
3750 size.pixelFormat(), size.VRAM(),
3751 size.bitsPerPixel(), size.bytesPerLine(),
3752 size.width(), size.height()));
3753
3754 /* clean the old values first */
3755
3756 ulong bytesPerLine = 0; /* Shut up MSC. */
3757 uint32_t bitsPerPixel = 0; /* Shut up MSC. */
3758 uint32_t b = 0xff;
3759 uint32_t g = 0xff00;
3760 uint32_t r = 0xff0000;
3761 bool fUsesGuestVram = false; /* Shut up MSC. */
3762
3763 /* check if we support the pixel format and can use the guest VRAM directly */
3764 if (size.pixelFormat() == KBitmapFormat_BGR)
3765 {
3766
3767 bitsPerPixel = size.bitsPerPixel();
3768 bytesPerLine = size.bytesPerLine();
3769 ulong bitsPerLine = bytesPerLine * 8;
3770
3771 switch (bitsPerPixel)
3772 {
3773 case 32:
3774 break;
3775 case 24:
3776#ifdef DEBUG_misha
3777 AssertFailed();
3778#endif
3779 break;
3780 case 8:
3781#ifdef DEBUG_misha
3782 AssertFailed();
3783#endif
3784 g = b = 0;
3785 remind = true;
3786 break;
3787 case 1:
3788#ifdef DEBUG_misha
3789 AssertFailed();
3790#endif
3791 r = 1;
3792 g = b = 0;
3793 remind = true;
3794 break;
3795 default:
3796#ifdef DEBUG_misha
3797 AssertFailed();
3798#endif
3799 remind = true;
3800 fallback = true;
3801 break;
3802 }
3803
3804 if (!fallback)
3805 {
3806 /* QImage only supports 32-bit aligned scan lines... */
3807 Assert ((size.bytesPerLine() & 3) == 0);
3808 fallback = ((size.bytesPerLine() & 3) != 0);
3809 Assert(!fallback);
3810 }
3811 if (!fallback)
3812 {
3813 /* ...and the scan lines ought to be a whole number of pixels. */
3814 Assert ((bitsPerLine & (size.bitsPerPixel() - 1)) == 0);
3815 fallback = ((bitsPerLine & (size.bitsPerPixel() - 1)) != 0);
3816 Assert(!fallback);
3817 }
3818 if (!fallback)
3819 {
3820 // ulong virtWdt = bitsPerLine / size.bitsPerPixel();
3821 fUsesGuestVram = true;
3822 }
3823 }
3824 else
3825 {
3826 AssertFailed();
3827 fallback = true;
3828 }
3829
3830 if (fallback)
3831 {
3832 /* we should never come to fallback more now */
3833 AssertFailed();
3834 /* we don't support either the pixel format or the color depth,
3835 * fallback to a self-provided 32bpp RGB buffer */
3836 bitsPerPixel = 32;
3837 b = 0xff;
3838 g = 0xff00;
3839 r = 0xff0000;
3840 bytesPerLine = size.width() * bitsPerPixel / 8;
3841 fUsesGuestVram = false;
3842 }
3843
3844 ulong bytesPerPixel = bitsPerPixel / 8;
3845 const QSize scaledSize = size.scaledSize();
3846 const ulong displayWidth = scaledSize.isValid() ? scaledSize.width() : bytesPerLine / bytesPerPixel;
3847 const ulong displayHeight = scaledSize.isValid() ? scaledSize.height() : size.height();
3848
3849#ifdef VBOXQGL_DBG_SURF
3850 for (int i = 0; i < RT_ELEMENTS(g_apSurf); i++)
3851 {
3852 VBoxVHWASurfaceBase * pSurf1 = g_apSurf[i];
3853 if (pSurf1)
3854 {
3855 VBoxVHWASurfList *pConstructingList = pSurf1->getComplexList();
3856 delete pSurf1;
3857 if (pConstructingList)
3858 delete pConstructingList;
3859 }
3860 }
3861#endif
3862
3863 VBoxVHWASurfaceBase *pDisplay = mDisplay.setVGA(NULL);
3864 if (pDisplay)
3865 delete pDisplay;
3866
3867 VBoxVHWAColorFormat format(bitsPerPixel, r,g,b);
3868 QSize dispSize(displayWidth, displayHeight);
3869 QRect dispRect(0, 0, displayWidth, displayHeight);
3870 pDisplay = new VBoxVHWASurfaceBase(this,
3871 dispSize,
3872 dispRect,
3873 dispRect,
3874 dispRect, /* we do not know viewport at the stage of precise, set as a
3875 disp rect, it will be updated on repaint */
3876 format,
3877 NULL, NULL, NULL, NULL,
3878#ifdef VBOXVHWA_USE_TEXGROUP
3879 0,
3880#endif
3881 0 /* VBOXVHWAIMG_TYPE fFlags */);
3882 pDisplay->init(NULL, fUsesGuestVram ? size.VRAM() : NULL);
3883 mDisplay.setVGA(pDisplay);
3884// VBOXQGLLOG(("\n\n*******\n\n viewport size is: (%d):(%d)\n\n*******\n\n", size().width(), size().height()));
3885 mViewport = QRect(0,0,displayWidth, displayHeight);
3886 adjustViewport(dispSize, mViewport);
3887 setupMatricies(dispSize, true);
3888
3889#ifdef VBOXQGL_DBG_SURF
3890 {
3891 uint32_t width = 100;
3892 uint32_t height = 60;
3893
3894 for (int i = 0; i < RT_ELEMENTS(g_apSurf); i++)
3895 {
3896 VBoxVHWAColorFormat tmpFormat(FOURCC_YV12);
3897 QSize tmpSize(width, height) ;
3898 VBoxVHWASurfaceBase *pSurf1 = new VBoxVHWASurfaceBase(this, tmpSize,
3899 mDisplay.getPrimary()->rect(),
3900 QRect(0, 0, width, height),
3901 mViewport,
3902 tmpFormat,
3903 NULL, NULL, NULL, &VBoxVHWAColorKey(0,0),
3904#ifdef VBOXVHWA_USE_TEXGROUP
3905 0,
3906#endif
3907 false);
3908
3909 Assert(mDisplay.getVGA());
3910 pSurf1->init(mDisplay.getVGA(), NULL);
3911 uchar *addr = pSurf1->address();
3912 uchar cur = 0;
3913 for (uint32_t k = 0; k < width*height; k++)
3914 {
3915 addr[k] = cur;
3916 cur+=64;
3917 }
3918 pSurf1->updatedMem(&QRect(0,0,width, height));
3919
3920 VBoxVHWASurfList *pConstructingList = new VBoxVHWASurfList();
3921 mDisplay.addOverlay(pConstructingList);
3922 pConstructingList->add(pSurf1);
3923 g_apSurf[i] = pSurf1;
3924
3925 }
3926
3927 VBOXVHWACMD_SURF_OVERLAY_UPDATE updateCmd;
3928 memset(&updateCmd, 0, sizeof(updateCmd));
3929 updateCmd.u.in.hSrcSurf = (VBOXVHWA_SURFHANDLE)g_apSurf[0];
3930 updateCmd.u.in.hDstSurf = (VBOXVHWA_SURFHANDLE)pDisplay;
3931 updateCmd.u.in.flags = VBOXVHWA_OVER_SHOW
3932 | VBOXVHWA_OVER_KEYDESTOVERRIDE;
3933
3934 updateCmd.u.in.desc.DstCK.high = 1;
3935 updateCmd.u.in.desc.DstCK.low = 1;
3936
3937 updateCmd.u.in.dstRect.left = 0;
3938 updateCmd.u.in.dstRect.right = pDisplay->width();
3939 updateCmd.u.in.dstRect.top = (pDisplay->height() - height) / 2;
3940 updateCmd.u.in.dstRect.bottom = updateCmd.u.in.dstRect.top + height;
3941
3942 updateCmd.u.in.srcRect.left = 0;
3943 updateCmd.u.in.srcRect.right = width;
3944 updateCmd.u.in.srcRect.top = 0;
3945 updateCmd.u.in.srcRect.bottom = height;
3946
3947 updateCmd.u.in.offDstSurface = VBOXVHWA_OFFSET64_VOID; /* just a magic to avoid surf mem buffer change */
3948 updateCmd.u.in.offSrcSurface = VBOXVHWA_OFFSET64_VOID; /* just a magic to avoid surf mem buffer change */
3949
3950 vhwaSurfaceOverlayUpdate(&updateCmd);
3951 }
3952#endif
3953
3954// if (!mOnResizeCmdList.empty())
3955// {
3956// for (VHWACommandList::const_iterator it = mOnResizeCmdList.begin();
3957// it != mOnResizeCmdList.end(); ++ it)
3958// {
3959// VBOXVHWACMD * pCmd = (*it);
3960// vboxDoVHWACmdExec(pCmd);
3961// free(pCmd);
3962// }
3963// mOnResizeCmdList.clear();
3964// }
3965
3966 if (remind)
3967 popupCenter().remindAboutWrongColorDepth(windowManager().mainWindowShown(), size.bitsPerPixel(), 32);
3968 else
3969 popupCenter().forgetAboutWrongColorDepth(windowManager().mainWindowShown());
3970}
3971
3972VBoxVHWAColorFormat::VBoxVHWAColorFormat (uint32_t bitsPerPixel, uint32_t r, uint32_t g, uint32_t b)
3973 : mWidthCompression(1)
3974 , mHeightCompression(1)
3975{
3976 init(bitsPerPixel, r, g, b);
3977}
3978
3979VBoxVHWAColorFormat::VBoxVHWAColorFormat(uint32_t fourcc)
3980 : mWidthCompression(1)
3981 , mHeightCompression(1)
3982{
3983 init(fourcc);
3984}
3985
3986void VBoxVHWAColorFormat::init(uint32_t fourcc)
3987{
3988 mDataFormat = fourcc;
3989 mInternalFormat = GL_RGBA8;//GL_RGB;
3990 mFormat = GL_BGRA_EXT;//GL_RGBA;
3991 mType = GL_UNSIGNED_BYTE;
3992 mR = VBoxVHWAColorComponent(0xff);
3993 mG = VBoxVHWAColorComponent(0xff);
3994 mB = VBoxVHWAColorComponent(0xff);
3995 mA = VBoxVHWAColorComponent(0xff);
3996 mBitsPerPixelTex = 32;
3997
3998 switch(fourcc)
3999 {
4000 case FOURCC_AYUV:
4001 mBitsPerPixel = 32;
4002 mWidthCompression = 1;
4003 break;
4004 case FOURCC_UYVY:
4005 case FOURCC_YUY2:
4006 mBitsPerPixel = 16;
4007 mWidthCompression = 2;
4008 break;
4009 case FOURCC_YV12:
4010 mBitsPerPixel = 8;
4011 mWidthCompression = 4;
4012 break;
4013 default:
4014 AssertFailed();
4015 mBitsPerPixel = 0;
4016 mBitsPerPixelTex = 0;
4017 mWidthCompression = 0;
4018 break;
4019 }
4020}
4021
4022void VBoxVHWAColorFormat::init(uint32_t bitsPerPixel, uint32_t r, uint32_t g, uint32_t b)
4023{
4024 mBitsPerPixel = bitsPerPixel;
4025 mBitsPerPixelTex = bitsPerPixel;
4026 mDataFormat = 0;
4027 switch (bitsPerPixel)
4028 {
4029 case 32:
4030 mInternalFormat = GL_RGB;//3;//GL_RGB;
4031 mFormat = GL_BGRA_EXT;//GL_RGBA;
4032 mType = GL_UNSIGNED_BYTE;
4033 mR = VBoxVHWAColorComponent(r);
4034 mG = VBoxVHWAColorComponent(g);
4035 mB = VBoxVHWAColorComponent(b);
4036 break;
4037 case 24:
4038#ifdef DEBUG_misha
4039 AssertFailed();
4040#endif
4041 mInternalFormat = 3;//GL_RGB;
4042 mFormat = GL_BGR_EXT;
4043 mType = GL_UNSIGNED_BYTE;
4044 mR = VBoxVHWAColorComponent(r);
4045 mG = VBoxVHWAColorComponent(g);
4046 mB = VBoxVHWAColorComponent(b);
4047 break;
4048 case 16:
4049#ifdef DEBUG_misha
4050 AssertFailed();
4051#endif
4052 mInternalFormat = GL_RGB5;
4053 mFormat = GL_BGR_EXT;
4054 mType = GL_UNSIGNED_BYTE; /** @todo ??? */
4055 mR = VBoxVHWAColorComponent(r);
4056 mG = VBoxVHWAColorComponent(g);
4057 mB = VBoxVHWAColorComponent(b);
4058 break;
4059 case 8:
4060#ifdef DEBUG_misha
4061 AssertFailed();
4062#endif
4063 mInternalFormat = 1;//GL_RGB;
4064 mFormat = GL_RED;//GL_RGB;
4065 mType = GL_UNSIGNED_BYTE;
4066 mR = VBoxVHWAColorComponent(0xff);
4067 break;
4068 case 1:
4069#ifdef DEBUG_misha
4070 AssertFailed();
4071#endif
4072 mInternalFormat = 1;
4073 mFormat = GL_COLOR_INDEX;
4074 mType = GL_BITMAP;
4075 mR = VBoxVHWAColorComponent(0x1);
4076 break;
4077 default:
4078#ifdef DEBUG_misha
4079 AssertFailed();
4080#endif
4081 mBitsPerPixel = 0;
4082 mBitsPerPixelTex = 0;
4083 break;
4084 }
4085}
4086
4087bool VBoxVHWAColorFormat::equals(const VBoxVHWAColorFormat &other) const
4088{
4089 if (fourcc())
4090 return fourcc() == other.fourcc();
4091 if (other.fourcc())
4092 return false;
4093
4094 return bitsPerPixel() == other.bitsPerPixel();
4095}
4096
4097VBoxVHWAColorComponent::VBoxVHWAColorComponent (uint32_t aMask)
4098{
4099 unsigned f = ASMBitFirstSetU32(aMask);
4100 if (f)
4101 {
4102 mOffset = f - 1;
4103 f = ASMBitFirstSetU32(~(aMask >> mOffset));
4104 if (f)
4105 mcBits = f - 1;
4106 else
4107 mcBits = 32 - mOffset;
4108
4109 Assert(mcBits);
4110 mMask = (((uint32_t)0xffffffff) >> (32 - mcBits)) << mOffset;
4111 Assert(mMask == aMask);
4112
4113 mRange = (mMask >> mOffset) + 1;
4114 }
4115 else
4116 {
4117 mMask = 0;
4118 mRange = 0;
4119 mOffset = 32;
4120 mcBits = 0;
4121 }
4122}
4123
4124void VBoxVHWAColorFormat::pixel2Normalized(uint32_t pix, float *r, float *g, float *b) const
4125{
4126 *r = mR.colorValNorm(pix);
4127 *g = mG.colorValNorm(pix);
4128 *b = mB.colorValNorm(pix);
4129}
4130
4131VBoxQGLOverlay::VBoxQGLOverlay()
4132 : mpOverlayWgt(NULL)
4133 , mpViewport(NULL)
4134 , mGlOn(false)
4135 , mOverlayWidgetVisible(false)
4136 , mOverlayVisible(false)
4137 , mGlCurrent(false)
4138 , mProcessingCommands(false)
4139 , mNeedOverlayRepaint(false)
4140 , mNeedSetVisible(false)
4141 , mCmdPipe()
4142 , mSettings()
4143 , mpSession()
4144 , mpShareWgt(NULL)
4145 , m_id(0)
4146{
4147 /* postpone the gl widget initialization to avoid conflict with 3D on Mac */
4148}
4149
4150void VBoxQGLOverlay::init(QWidget *pViewport, QObject *pPostEventObject, CSession *aSession, uint32_t id)
4151{
4152 mpViewport = pViewport;
4153 mpSession = aSession;
4154 m_id = id;
4155 mSettings.init(*aSession);
4156 mCmdPipe.init(pPostEventObject);
4157}
4158
4159class VBoxGLShareWgt : public QGLWidget
4160{
4161public:
4162 VBoxGLShareWgt()
4163 : QGLWidget(new VBoxGLContext(VBoxVHWAImage::vboxGLFormat()))
4164 {
4165 /* work-around to disable done current needed to old ATI drivers on Linux */
4166 VBoxGLContext *pc = (VBoxGLContext *)context();
4167 pc->allowDoneCurrent(false);
4168 }
4169
4170protected:
4171 void initializeGL()
4172 {
4173 vboxVHWAGetSupportInfo(context());
4174 VBoxVHWASurfaceBase::globalInit();
4175 }
4176};
4177void VBoxQGLOverlay::initGl()
4178{
4179 if (mpOverlayWgt)
4180 {
4181 Assert(mpShareWgt);
4182 return;
4183 }
4184
4185 if (!mpShareWgt)
4186 {
4187 mpShareWgt = new VBoxGLShareWgt();
4188 /* force initializeGL */
4189 mpShareWgt->updateGL();
4190 }
4191
4192 mOverlayImage.init(&mSettings);
4193 mpOverlayWgt = new VBoxGLWgt(&mOverlayImage, mpViewport, mpShareWgt);
4194
4195 mOverlayWidgetVisible = true; /* to ensure it is set hidden with vboxShowOverlay */
4196 vboxShowOverlay(false);
4197
4198 mpOverlayWgt->setMouseTracking(true);
4199}
4200
4201void VBoxQGLOverlay::updateAttachment(QWidget *pViewport, QObject *pPostEventObject)
4202{
4203 if (mpViewport != pViewport)
4204 {
4205 mpViewport = pViewport;
4206 mpOverlayWgt = NULL;
4207 mOverlayWidgetVisible = false;
4208 if (mOverlayImage.hasSurfaces())
4209 {
4210// Assert(!mOverlayVisible);
4211 if (pViewport)
4212 {
4213 initGl();
4214// vboxDoCheckUpdateViewport();
4215 }
4216// Assert(!mOverlayVisible);
4217 }
4218 mGlCurrent = false;
4219 }
4220 mCmdPipe.setNotifyObject(pPostEventObject);
4221}
4222
4223int VBoxQGLOverlay::reset()
4224{
4225 CDisplay display = mpSession->GetConsole().GetDisplay();
4226 Assert (!display.isNull());
4227
4228 mCmdPipe.reset(&display);
4229
4230 resetGl();
4231
4232 return VINF_SUCCESS;
4233}
4234
4235static DECLCALLBACK(void) vbvaVHWAHHCommandFreeCmd(void *pvContext)
4236{
4237 free(pvContext);
4238}
4239
4240int VBoxQGLOverlay::resetGl()
4241{
4242 VHWACommandList list;
4243 int rc = mOverlayImage.reset(&list);
4244 AssertRC(rc);
4245 if (RT_SUCCESS(rc))
4246 {
4247 for (VHWACommandList::const_iterator sIt = list.begin(); sIt != list.end(); ++ sIt)
4248 {
4249 VBOXVHWACMD *pCmd = (*sIt);
4250 VBOXVHWA_HH_CALLBACK_SET(pCmd, vbvaVHWAHHCommandFreeCmd, pCmd);
4251 mCmdPipe.postCmd(VBOXVHWA_PIPECMD_VHWA, pCmd, pCmd->enmCmd, false /*fGuestCmd*/);
4252 }
4253 }
4254 return VINF_SUCCESS;
4255}
4256
4257int VBoxQGLOverlay::onVHWACommand(struct VBOXVHWACMD RT_UNTRUSTED_VOLATILE_GUEST *pCmd,
4258 int /*VBOXVHWACMD_TYPE*/ enmCmdInt, bool fGuestCmd)
4259{
4260 VBOXVHWACMD_TYPE const enmCmd = (VBOXVHWACMD_TYPE)enmCmdInt;
4261 Log(("VHWA Command >>> %#p, %d\n", pCmd, enmCmd));
4262 switch (enmCmd)
4263 {
4264 case VBOXVHWACMD_TYPE_SURF_FLIP:
4265 case VBOXVHWACMD_TYPE_SURF_OVERLAY_UPDATE:
4266 case VBOXVHWACMD_TYPE_SURF_OVERLAY_SETPOSITION:
4267 break;
4268 case VBOXVHWACMD_TYPE_HH_CONSTRUCT:
4269 {
4270 pCmd->Flags &= ~VBOXVHWACMD_FLAG_HG_ASYNCH;
4271 ASSERT_GUEST_STMT_RETURN(!fGuestCmd, pCmd->rc = VERR_ACCESS_DENIED, VINF_SUCCESS);
4272 VBOXVHWACMD_HH_CONSTRUCT *pBody = VBOXVHWACMD_BODY_HOST_HEAP(pCmd, VBOXVHWACMD_HH_CONSTRUCT);
4273 pCmd->rc = vhwaConstruct(pBody);
4274 Log(("VHWA Command <<< Sync %#p, %d\n", pCmd, enmCmd));
4275 return VINF_SUCCESS;
4276 }
4277
4278 case VBOXVHWACMD_TYPE_HH_RESET:
4279 {
4280 pCmd->Flags &= ~VBOXVHWACMD_FLAG_HG_ASYNCH;
4281 ASSERT_GUEST_STMT_RETURN(!fGuestCmd, pCmd->rc = VERR_ACCESS_DENIED, VINF_SUCCESS);
4282 /* we do not post a reset command to the gui thread since this may lead to a deadlock
4283 * when reset is initiated by the gui thread*/
4284 pCmd->rc = reset();
4285 Log(("VHWA Command <<< Sync %#p, %d\n", pCmd, enmCmd));
4286 return VINF_SUCCESS;
4287 }
4288
4289 case VBOXVHWACMD_TYPE_HH_ENABLE:
4290 pCmd->Flags &= ~VBOXVHWACMD_FLAG_HG_ASYNCH;
4291 ASSERT_GUEST_STMT_RETURN(!fGuestCmd, pCmd->rc = VERR_ACCESS_DENIED, VINF_SUCCESS);
4292 pCmd->rc = VINF_SUCCESS;
4293 Log(("VHWA Command <<< Sync %#p, %d\n", pCmd, enmCmd));
4294 return VINF_SUCCESS;
4295
4296 case VBOXVHWACMD_TYPE_HH_DISABLE:
4297 pCmd->Flags &= ~VBOXVHWACMD_FLAG_HG_ASYNCH;
4298 ASSERT_GUEST_STMT_RETURN(!fGuestCmd, pCmd->rc = VERR_ACCESS_DENIED, VINF_SUCCESS);
4299 pCmd->rc = VINF_SUCCESS;
4300 Log(("VHWA Command <<< Sync %#p, %d\n", pCmd, enmCmd));
4301 return VINF_SUCCESS;
4302
4303 case VBOXVHWACMD_TYPE_HH_SAVESTATE_SAVEBEGIN:
4304 pCmd->Flags &= ~VBOXVHWACMD_FLAG_HG_ASYNCH;
4305 ASSERT_GUEST_STMT_RETURN(!fGuestCmd, pCmd->rc = VERR_ACCESS_DENIED, VINF_SUCCESS);
4306 mCmdPipe.disable();
4307 pCmd->rc = VINF_SUCCESS;
4308 Log(("VHWA Command <<< Sync %#p, %d\n", pCmd, enmCmd));
4309 return VINF_SUCCESS;
4310
4311 case VBOXVHWACMD_TYPE_HH_SAVESTATE_SAVEEND:
4312 ASSERT_GUEST_STMT_RETURN(!fGuestCmd, pCmd->rc = VERR_ACCESS_DENIED, VINF_SUCCESS);
4313 pCmd->Flags &= ~VBOXVHWACMD_FLAG_HG_ASYNCH;
4314 mCmdPipe.enable();
4315 pCmd->rc = VINF_SUCCESS;
4316 Log(("VHWA Command <<< Sync %#p, %d\n", pCmd, enmCmd));
4317 return VINF_SUCCESS;
4318
4319 case VBOXVHWACMD_TYPE_HH_SAVESTATE_SAVEPERFORM:
4320 {
4321 pCmd->Flags &= ~VBOXVHWACMD_FLAG_HG_ASYNCH;
4322 ASSERT_GUEST_STMT_RETURN(!fGuestCmd, pCmd->rc = VERR_ACCESS_DENIED, VINF_SUCCESS);
4323 VBOXVHWACMD_HH_SAVESTATE_SAVEPERFORM *pSave = VBOXVHWACMD_BODY_HOST_HEAP(pCmd, VBOXVHWACMD_HH_SAVESTATE_SAVEPERFORM);
4324 PSSMHANDLE pSSM = pSave->pSSM;
4325 int rc = SSMR3PutU32(pSSM, VBOXQGL_STATE_VERSION); AssertRC(rc);
4326 if (RT_SUCCESS(rc))
4327 vhwaSaveExec(pSSM);
4328 pCmd->rc = rc;
4329 Log(("VHWA Command <<< Sync %#p, %d\n", pCmd, enmCmd));
4330 return VINF_SUCCESS;
4331 }
4332 case VBOXVHWACMD_TYPE_HH_SAVESTATE_LOADPERFORM:
4333 {
4334 pCmd->Flags &= ~VBOXVHWACMD_FLAG_HG_ASYNCH;
4335 ASSERT_GUEST_STMT_RETURN(!fGuestCmd, pCmd->rc = VERR_ACCESS_DENIED, VINF_SUCCESS);
4336 VBOXVHWACMD_HH_SAVESTATE_LOADPERFORM *pLoad = VBOXVHWACMD_BODY_HOST_HEAP(pCmd, VBOXVHWACMD_HH_SAVESTATE_LOADPERFORM);
4337 PSSMHANDLE pSSM = pLoad->pSSM;
4338 uint32_t u32Version = 0;
4339 int rc = SSMR3GetU32(pSSM, &u32Version); Assert(RT_SUCCESS(rc) || rc == VERR_SSM_LOADED_TOO_MUCH);
4340 if (RT_SUCCESS(rc))
4341 {
4342 rc = vhwaLoadExec(pSSM, u32Version);
4343 AssertRC(rc);
4344 }
4345 else
4346 {
4347 /* sanity */
4348 u32Version = 0;
4349
4350 if (rc == VERR_SSM_LOADED_TOO_MUCH)
4351 rc = VINF_SUCCESS;
4352 }
4353 pCmd->rc = rc;
4354 Log(("VHWA Command <<< Sync %#p, %d\n", pCmd, enmCmd));
4355 return VINF_SUCCESS;
4356 }
4357
4358 case VBOXVHWACMD_TYPE_QUERY_INFO1:
4359 {
4360#ifdef RT_STRICT
4361 VBOXVHWACMD_QUERYINFO1 RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_QUERYINFO1);
4362#endif
4363 Assert(pBody->u.in.guestVersion.maj == VBOXVHWA_VERSION_MAJ);
4364 Assert(pBody->u.in.guestVersion.min == VBOXVHWA_VERSION_MIN);
4365 Assert(pBody->u.in.guestVersion.bld == VBOXVHWA_VERSION_BLD);
4366 Assert(pBody->u.in.guestVersion.reserved == VBOXVHWA_VERSION_RSV);
4367 /* do NOT break!! make it proceed asynchronously */
4368 }
4369
4370 default:
4371 break;
4372 }
4373
4374 Log(("VHWA Command --- Going Async %#p, %d\n", pCmd, enmCmd));
4375 /* indicate that we process and complete the command asynchronously */
4376 pCmd->Flags |= VBOXVHWACMD_FLAG_HG_ASYNCH;
4377
4378 mCmdPipe.postCmd(VBOXVHWA_PIPECMD_VHWA, (void *)pCmd, enmCmd, fGuestCmd);
4379 return VINF_CALLBACK_RETURN;
4380
4381}
4382
4383void VBoxQGLOverlay::onVHWACommandEvent(QEvent *pEvent)
4384{
4385 VBoxVHWACommandProcessEvent *pVhwaEvent = (VBoxVHWACommandProcessEvent *)pEvent;
4386 /* sanity actually */
4387 pVhwaEvent->setProcessed();
4388
4389 Assert(!mProcessingCommands);
4390 mProcessingCommands = true;
4391 Assert(!mGlCurrent);
4392 mGlCurrent = false; /* just a fall-back */
4393 VBoxVHWACommandElement *pCmd = mCmdPipe.getCmd();
4394 if (pCmd)
4395 {
4396 processCmd(pCmd);
4397 mCmdPipe.doneCmd();
4398 }
4399
4400 mProcessingCommands = false;
4401 repaint();
4402 mGlCurrent = false;
4403}
4404
4405bool VBoxQGLOverlay::onNotifyUpdate(ULONG uX, ULONG uY, ULONG uW, ULONG uH)
4406{
4407 /* Prepare corresponding viewport part: */
4408 QRect rect(uX, uY, uW, uH);
4409
4410 /* Take the scaling into account: */
4411 const double dScaleFactor = mSizeInfo.scaleFactor();
4412 const QSize scaledSize = mSizeInfo.scaledSize();
4413 if (scaledSize.isValid())
4414 {
4415 /* Calculate corresponding scale-factors: */
4416 const double xScaleFactor = mSizeInfo.visualState() == UIVisualStateType_Scale
4417 ? (double)scaledSize.width() / mSizeInfo.width() : dScaleFactor;
4418 const double yScaleFactor = mSizeInfo.visualState() == UIVisualStateType_Scale
4419 ? (double)scaledSize.height() / mSizeInfo.height() : dScaleFactor;
4420 /* Adjust corresponding viewport part: */
4421 rect.moveTo((int)floor((double)rect.x() * xScaleFactor) - 1,
4422 (int)floor((double)rect.y() * yScaleFactor) - 1);
4423 rect.setSize(QSize((int)ceil((double)rect.width() * xScaleFactor) + 2,
4424 (int)ceil((double)rect.height() * yScaleFactor) + 2));
4425 }
4426
4427 /* Take the device-pixel-ratio into account: */
4428 if (mSizeInfo.useUnscaledHiDPIOutput())
4429 {
4430 const double dDevicePixelRatio = gpDesktop->devicePixelRatio(mpViewport->window());
4431 if (dDevicePixelRatio > 1.0)
4432 {
4433 rect.moveTo((int)floor((double)rect.x() / dDevicePixelRatio) - 1,
4434 (int)floor((double)rect.y() / dDevicePixelRatio) - 1);
4435 rect.setSize(QSize((int)ceil((double)rect.width() / dDevicePixelRatio) + 2,
4436 (int)ceil((double)rect.height() / dDevicePixelRatio) + 2));
4437 }
4438 }
4439
4440 /* we do not to miss notify updates, because we have to update bg textures for it,
4441 * so no not check for m_fUnused here,
4442 * mOverlay will store the required info for us */
4443 mCmdPipe.postCmd(VBOXVHWA_PIPECMD_PAINT, &rect, -1, false);
4444
4445 return true;
4446}
4447
4448void VBoxQGLOverlay::onResizeEventPostprocess(const VBoxFBSizeInfo &re, const QPoint &topLeft)
4449{
4450 mSizeInfo = re;
4451 mContentsTopLeft = topLeft;
4452
4453 if (mGlOn)
4454 {
4455 Assert(mOverlayImage.hasSurfaces());
4456 Assert(!mGlCurrent);
4457 Assert(!mNeedOverlayRepaint);
4458 mGlCurrent = false;
4459 makeCurrent();
4460 /* need to ensure we're in sync */
4461 mNeedOverlayRepaint = vboxSynchGl();
4462
4463 if (!mOverlayImage.hasSurfaces())
4464 vboxSetGlOn(false);
4465 }
4466 else
4467 Assert(!mOverlayImage.hasSurfaces());
4468
4469 if (!mOnResizeCmdList.empty())
4470 {
4471 for (VHWACommandList::const_iterator it = mOnResizeCmdList.begin(); it != mOnResizeCmdList.end(); ++ it)
4472 {
4473 VBOXVHWACMD *pCmd = (*it);
4474 vboxDoVHWACmdExec(pCmd, pCmd->enmCmd, false);
4475 free(pCmd);
4476 }
4477 mOnResizeCmdList.clear();
4478 }
4479
4480 repaintOverlay();
4481 mGlCurrent = false;
4482}
4483
4484void VBoxQGLOverlay::repaintMain()
4485{
4486 if (mMainDirtyRect.isClear())
4487 return;
4488
4489 const QRect &rect = mMainDirtyRect.rect();
4490 if (mOverlayWidgetVisible)
4491 if (mOverlayViewport.contains(rect))
4492 return;
4493
4494 mpViewport->repaint(rect.x() - mContentsTopLeft.x(),
4495 rect.y() - mContentsTopLeft.y(),
4496 rect.width(),
4497 rect.height());
4498
4499 mMainDirtyRect.clear();
4500}
4501
4502void VBoxQGLOverlay::vboxDoVHWACmd(void RT_UNTRUSTED_VOLATILE_GUEST *pvCmd, int /*VBOXVHWACMD_TYPE*/ enmCmd, bool fGuestCmd)
4503{
4504 vboxDoVHWACmdExec(pvCmd, enmCmd, fGuestCmd);
4505
4506 CDisplay display = mpSession->GetConsole().GetDisplay();
4507 Assert(!display.isNull());
4508
4509 Log(("VHWA Command <<< Async %#p, %d\n", pvCmd, enmCmd));
4510
4511 display.CompleteVHWACommand((BYTE *)pvCmd);
4512}
4513
4514bool VBoxQGLOverlay::vboxSynchGl()
4515{
4516 VBoxVHWASurfaceBase *pVGA = mOverlayImage.vgaSurface();
4517 if ( pVGA
4518 && mSizeInfo.pixelFormat() == pVGA->pixelFormat().toVBoxPixelFormat()
4519 && mSizeInfo.VRAM() == pVGA->address()
4520 && mSizeInfo.bitsPerPixel() == pVGA->bitsPerPixel()
4521 && mSizeInfo.bytesPerLine() == pVGA->bytesPerLine()
4522 && mSizeInfo.width() == pVGA->width()
4523 && mSizeInfo.height() == pVGA->height()
4524 )
4525 {
4526 return false;
4527 }
4528 /* create and issue a resize event to the gl widget to ensure we have all gl data initialized
4529 * and synchronized with the framebuffer */
4530 mOverlayImage.resize(mSizeInfo);
4531 return true;
4532}
4533
4534void VBoxQGLOverlay::vboxSetGlOn(bool on)
4535{
4536 if (on == mGlOn)
4537 return;
4538
4539 mGlOn = on;
4540
4541 if (on)
4542 {
4543 /* need to ensure we have gl functions initialized */
4544 mpOverlayWgt->makeCurrent();
4545 vboxVHWAGetSupportInfo(mpOverlayWgt->context());
4546
4547 VBOXQGLLOGREL(("Switching Gl mode on\n"));
4548 Assert(!mpOverlayWgt->isVisible());
4549 /* just to ensure */
4550 vboxShowOverlay(false);
4551 mOverlayVisible = false;
4552 vboxSynchGl();
4553 }
4554 else
4555 {
4556 VBOXQGLLOGREL(("Switching Gl mode off\n"));
4557 mOverlayVisible = false;
4558 vboxShowOverlay(false);
4559 /* for now just set the flag w/o destroying anything */
4560 }
4561}
4562
4563void VBoxQGLOverlay::vboxDoCheckUpdateViewport()
4564{
4565 if (!mOverlayVisible)
4566 {
4567 vboxShowOverlay(false);
4568 return;
4569 }
4570
4571 int cX = mContentsTopLeft.x();
4572 int cY = mContentsTopLeft.y();
4573 QRect fbVp(cX, cY, mpViewport->width(), mpViewport->height());
4574 QRect overVp = fbVp.intersected(mOverlayViewport);
4575
4576 if (overVp.isEmpty())
4577 vboxShowOverlay(false);
4578 else
4579 {
4580 if (overVp != mOverlayImage.vboxViewport())
4581 {
4582 makeCurrent();
4583 mOverlayImage.vboxDoUpdateViewport(overVp);
4584 mNeedOverlayRepaint = true;
4585 }
4586
4587 QRect rect(overVp.x() - cX, overVp.y() - cY, overVp.width(), overVp.height());
4588
4589 vboxCheckUpdateOverlay(rect);
4590
4591 vboxShowOverlay(true);
4592
4593 /* workaround for linux ATI issue: need to update gl viewport after widget becomes visible */
4594 mOverlayImage.vboxDoUpdateViewport(overVp);
4595 }
4596}
4597
4598void VBoxQGLOverlay::vboxShowOverlay(bool show)
4599{
4600 if (mOverlayWidgetVisible != show)
4601 {
4602 mpOverlayWgt->setVisible(show);
4603 mOverlayWidgetVisible = show;
4604 mGlCurrent = false;
4605 if (!show)
4606 mMainDirtyRect.add(mOverlayImage.vboxViewport());
4607 }
4608}
4609
4610void VBoxQGLOverlay::vboxCheckUpdateOverlay(const QRect &rect)
4611{
4612 QRect overRect(mpOverlayWgt->pos(), mpOverlayWgt->size());
4613 if (overRect.x() != rect.x() || overRect.y() != rect.y())
4614 {
4615#if defined(RT_OS_WINDOWS)
4616 mpOverlayWgt->setVisible(false);
4617 mNeedSetVisible = true;
4618#endif
4619 VBOXQGLLOG_QRECT("moving wgt to " , &rect, "\n");
4620 mpOverlayWgt->move(rect.x(), rect.y());
4621 mGlCurrent = false;
4622 }
4623
4624 if (overRect.width() != rect.width() || overRect.height() != rect.height())
4625 {
4626#if defined(RT_OS_WINDOWS)
4627 mpOverlayWgt->setVisible(false);
4628 mNeedSetVisible = true;
4629#endif
4630 VBOXQGLLOG(("resizing wgt to w(%d) ,h(%d)\n" , rect.width(), rect.height()));
4631 mpOverlayWgt->resize(rect.width(), rect.height());
4632 mGlCurrent = false;
4633 }
4634}
4635
4636void VBoxQGLOverlay::addMainDirtyRect(const QRect &aRect)
4637{
4638 mMainDirtyRect.add(aRect);
4639 if (mGlOn)
4640 {
4641 mOverlayImage.vboxDoUpdateRect(&aRect);
4642 mNeedOverlayRepaint = true;
4643 }
4644}
4645
4646int VBoxQGLOverlay::vhwaSurfaceUnlock(struct VBOXVHWACMD_SURF_UNLOCK RT_UNTRUSTED_VOLATILE_GUEST *pCmd)
4647{
4648 int rc = mOverlayImage.vhwaSurfaceUnlock(pCmd);
4649 VBoxVHWASurfaceBase *pVGA = mOverlayImage.vgaSurface();
4650 const VBoxVHWADirtyRect &rect = pVGA->getDirtyRect();
4651 mNeedOverlayRepaint = true;
4652 if (!rect.isClear())
4653 mMainDirtyRect.add(rect);
4654 return rc;
4655}
4656
4657void VBoxQGLOverlay::vboxDoVHWACmdExec(void RT_UNTRUSTED_VOLATILE_GUEST *pvCmd, int /*VBOXVHWACMD_TYPE*/ enmCmdInt, bool fGuestCmd)
4658{
4659 struct VBOXVHWACMD RT_UNTRUSTED_VOLATILE_GUEST *pCmd = (struct VBOXVHWACMD RT_UNTRUSTED_VOLATILE_GUEST *)pvCmd;
4660 VBOXVHWACMD_TYPE enmCmd = (VBOXVHWACMD_TYPE)enmCmdInt;
4661
4662 switch (enmCmd)
4663 {
4664 case VBOXVHWACMD_TYPE_SURF_CANCREATE:
4665 {
4666 VBOXVHWACMD_SURF_CANCREATE RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_CANCREATE);
4667 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4668 initGl();
4669 makeCurrent();
4670 pCmd->rc = mOverlayImage.vhwaSurfaceCanCreate(pBody);
4671 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4672 break;
4673 }
4674
4675 case VBOXVHWACMD_TYPE_SURF_CREATE:
4676 {
4677 VBOXVHWACMD_SURF_CREATE RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_CREATE);
4678 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4679 initGl();
4680 makeCurrent();
4681 vboxSetGlOn(true);
4682 pCmd->rc = mOverlayImage.vhwaSurfaceCreate(pBody);
4683 if (!mOverlayImage.hasSurfaces())
4684 {
4685 vboxSetGlOn(false);
4686 }
4687 else
4688 {
4689 mOverlayVisible = mOverlayImage.hasVisibleOverlays();
4690 if (mOverlayVisible)
4691 {
4692 mOverlayViewport = mOverlayImage.overlaysRectUnion();
4693 }
4694 vboxDoCheckUpdateViewport();
4695 mNeedOverlayRepaint = true;
4696 }
4697
4698 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4699 break;
4700 }
4701
4702 case VBOXVHWACMD_TYPE_SURF_DESTROY:
4703 {
4704 VBOXVHWACMD_SURF_DESTROY RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_DESTROY);
4705 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4706 initGl();
4707 makeCurrent();
4708 pCmd->rc = mOverlayImage.vhwaSurfaceDestroy(pBody);
4709 if (!mOverlayImage.hasSurfaces())
4710 {
4711 vboxSetGlOn(false);
4712 }
4713 else
4714 {
4715 mOverlayVisible = mOverlayImage.hasVisibleOverlays();
4716 if (mOverlayVisible)
4717 {
4718 mOverlayViewport = mOverlayImage.overlaysRectUnion();
4719 }
4720 vboxDoCheckUpdateViewport();
4721 mNeedOverlayRepaint = true;
4722 }
4723 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4724 break;
4725 }
4726
4727 case VBOXVHWACMD_TYPE_SURF_LOCK:
4728 {
4729 VBOXVHWACMD_SURF_LOCK RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_LOCK);
4730 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4731 initGl();
4732 makeCurrent();
4733 pCmd->rc = mOverlayImage.vhwaSurfaceLock(pBody);
4734 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4735 break;
4736 }
4737
4738 case VBOXVHWACMD_TYPE_SURF_UNLOCK:
4739 {
4740 VBOXVHWACMD_SURF_UNLOCK RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_UNLOCK);
4741 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4742 initGl();
4743 makeCurrent();
4744 pCmd->rc = vhwaSurfaceUnlock(pBody);
4745 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4746 /* mNeedOverlayRepaint is set inside the vhwaSurfaceUnlock */
4747 break;
4748 }
4749
4750 case VBOXVHWACMD_TYPE_SURF_BLT:
4751 {
4752 VBOXVHWACMD_SURF_BLT RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_BLT);
4753 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4754 initGl();
4755 makeCurrent();
4756 pCmd->rc = mOverlayImage.vhwaSurfaceBlt(pBody);
4757 mNeedOverlayRepaint = true;
4758 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4759 break;
4760 }
4761
4762 case VBOXVHWACMD_TYPE_SURF_FLIP:
4763 {
4764 VBOXVHWACMD_SURF_FLIP RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_FLIP);
4765 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4766 initGl();
4767 makeCurrent();
4768 pCmd->rc = mOverlayImage.vhwaSurfaceFlip(pBody);
4769 mNeedOverlayRepaint = true;
4770 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4771 break;
4772 }
4773
4774 case VBOXVHWACMD_TYPE_SURF_OVERLAY_UPDATE:
4775 {
4776 VBOXVHWACMD_SURF_OVERLAY_UPDATE RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_OVERLAY_UPDATE);
4777 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4778 initGl();
4779 makeCurrent();
4780 pCmd->rc = mOverlayImage.vhwaSurfaceOverlayUpdate(pBody);
4781 mOverlayVisible = mOverlayImage.hasVisibleOverlays();
4782 if (mOverlayVisible)
4783 {
4784 mOverlayViewport = mOverlayImage.overlaysRectUnion();
4785 }
4786 vboxDoCheckUpdateViewport();
4787 mNeedOverlayRepaint = true;
4788 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4789 break;
4790 }
4791
4792 case VBOXVHWACMD_TYPE_SURF_OVERLAY_SETPOSITION:
4793 {
4794 VBOXVHWACMD_SURF_OVERLAY_SETPOSITION RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_OVERLAY_SETPOSITION);
4795 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4796 initGl();
4797 makeCurrent();
4798 pCmd->rc = mOverlayImage.vhwaSurfaceOverlaySetPosition(pBody);
4799 mOverlayVisible = mOverlayImage.hasVisibleOverlays();
4800 if (mOverlayVisible)
4801 {
4802 mOverlayViewport = mOverlayImage.overlaysRectUnion();
4803 }
4804 vboxDoCheckUpdateViewport();
4805 mNeedOverlayRepaint = true;
4806 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4807 break;
4808 }
4809
4810#ifdef VBOX_WITH_WDDM
4811 case VBOXVHWACMD_TYPE_SURF_COLORFILL:
4812 {
4813 VBOXVHWACMD_SURF_COLORFILL RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_COLORFILL);
4814 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4815 initGl();
4816 makeCurrent();
4817 pCmd->rc = mOverlayImage.vhwaSurfaceColorFill(pBody);
4818 mNeedOverlayRepaint = true;
4819 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4820 break;
4821 }
4822#endif
4823 case VBOXVHWACMD_TYPE_SURF_COLORKEY_SET:
4824 {
4825 VBOXVHWACMD_SURF_COLORKEY_SET RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_COLORKEY_SET);
4826 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4827 initGl();
4828 makeCurrent();
4829 pCmd->rc = mOverlayImage.vhwaSurfaceColorkeySet(pBody);
4830 /* this is here to ensure we have color key changes picked up */
4831 vboxDoCheckUpdateViewport();
4832 mNeedOverlayRepaint = true;
4833 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4834 break;
4835 }
4836
4837 case VBOXVHWACMD_TYPE_QUERY_INFO1:
4838 {
4839 VBOXVHWACMD_QUERYINFO1 RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_QUERYINFO1);
4840 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4841 initGl();
4842 makeCurrent();
4843 pCmd->rc = mOverlayImage.vhwaQueryInfo1(pBody);
4844 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4845 break;
4846 }
4847
4848 case VBOXVHWACMD_TYPE_QUERY_INFO2:
4849 {
4850 VBOXVHWACMD_QUERYINFO2 RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_QUERYINFO2);
4851 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4852 initGl();
4853 makeCurrent();
4854 pCmd->rc = mOverlayImage.vhwaQueryInfo2(pBody);
4855 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4856 break;
4857 }
4858
4859 case VBOXVHWACMD_TYPE_ENABLE:
4860 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4861 initGl();
4862 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4863 pCmd->rc = VINF_SUCCESS;
4864 break;
4865
4866 case VBOXVHWACMD_TYPE_DISABLE:
4867 pCmd->rc = VINF_SUCCESS;
4868 break;
4869
4870 case VBOXVHWACMD_TYPE_HH_CONSTRUCT:
4871 {
4872 ASSERT_GUEST_STMT_RETURN_VOID(!fGuestCmd, pCmd->rc = VERR_ACCESS_DENIED);
4873 VBOXVHWACMD_HH_CONSTRUCT *pBody = VBOXVHWACMD_BODY_HOST_HEAP(pCmd, VBOXVHWACMD_HH_CONSTRUCT);
4874 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4875 pCmd->rc = vhwaConstruct(pBody);
4876 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4877 break;
4878 }
4879
4880#ifdef VBOX_WITH_WDDM
4881 case VBOXVHWACMD_TYPE_SURF_GETINFO:
4882 {
4883 VBOXVHWACMD_SURF_GETINFO RT_UNTRUSTED_VOLATILE_GUEST *pBody = VBOXVHWACMD_BODY(pCmd, VBOXVHWACMD_SURF_GETINFO);
4884 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4885 pCmd->rc = mOverlayImage.vhwaSurfaceGetInfo(pBody);
4886 Assert(!mGlOn == !mOverlayImage.hasSurfaces());
4887 break;
4888 }
4889#endif
4890
4891 default:
4892 AssertFailed();
4893 pCmd->rc = VERR_NOT_IMPLEMENTED;
4894 break;
4895 }
4896}
4897
4898#if 0
4899static DECLCALLBACK(void) vboxQGLOverlaySaveExec(PSSMHANDLE pSSM, void *pvUser)
4900{
4901 VBoxQGLOverlay * fb = (VBoxQGLOverlay*)pvUser;
4902 fb->vhwaSaveExec(pSSM);
4903}
4904#endif
4905
4906static DECLCALLBACK(int) vboxQGLOverlayLoadExec(PSSMHANDLE pSSM, void *pvUser, uint32_t u32Version, uint32_t uPass)
4907{
4908 Assert(uPass == SSM_PASS_FINAL); NOREF(uPass);
4909 VBoxQGLOverlay *fb = (VBoxQGLOverlay *)pvUser;
4910 return fb->vhwaLoadExec(pSSM, u32Version);
4911}
4912
4913int VBoxQGLOverlay::vhwaLoadExec(struct SSMHANDLE *pSSM, uint32_t u32Version)
4914{
4915 int rc = VBoxVHWAImage::vhwaLoadExec(&mOnResizeCmdList, pSSM, u32Version);
4916 AssertRC(rc);
4917 if (RT_SUCCESS(rc))
4918 {
4919 if (u32Version >= VBOXQGL_STATE_VERSION_PIPESAVED)
4920 {
4921 rc = mCmdPipe.loadExec(pSSM, u32Version, mOverlayImage.vramBase());
4922 AssertRC(rc);
4923 }
4924 }
4925 return rc;
4926}
4927
4928void VBoxQGLOverlay::vhwaSaveExec(struct SSMHANDLE *pSSM)
4929{
4930 mOverlayImage.vhwaSaveExec(pSSM);
4931 mCmdPipe.saveExec(pSSM, mOverlayImage.vramBase());
4932}
4933
4934int VBoxQGLOverlay::vhwaConstruct(struct VBOXVHWACMD_HH_CONSTRUCT *pCmd)
4935{
4936 PUVM pUVM = VMR3GetUVM((PVM)pCmd->pVM);
4937 uint32_t intsId = m_id;
4938
4939 char nameFuf[sizeof(VBOXQGL_STATE_NAMEBASE) + 8];
4940
4941 char * pszName = nameFuf;
4942 sprintf(pszName, "%s%d", VBOXQGL_STATE_NAMEBASE, intsId);
4943 int rc = SSMR3RegisterExternal(pUVM, /* The VM handle*/
4944 pszName, /* Data unit name. */
4945 intsId, /* The instance identifier of the data unit.
4946 * This must together with the name be unique. */
4947 VBOXQGL_STATE_VERSION, /* Data layout version number. */
4948 128, /* The approximate amount of data in the unit.
4949 * Only for progress indicators. */
4950 NULL, NULL, NULL, /* pfnLiveXxx */
4951 NULL, /* Prepare save callback, optional. */
4952 NULL, //vboxQGLOverlaySaveExec, /* Execute save callback, optional. */
4953 NULL, /* Done save callback, optional. */
4954 NULL, /* Prepare load callback, optional. */
4955 vboxQGLOverlayLoadExec, /* Execute load callback, optional. */
4956 NULL, /* Done load callback, optional. */
4957 this /* User argument. */
4958 );
4959 AssertRC(rc);
4960 if (RT_SUCCESS(rc))
4961 {
4962 rc = mOverlayImage.vhwaConstruct(pCmd);
4963 AssertRC(rc);
4964 }
4965 return rc;
4966}
4967
4968void VBoxQGLOverlay::processCmd(VBoxVHWACommandElement * pCmd)
4969{
4970 switch(pCmd->type())
4971 {
4972 case VBOXVHWA_PIPECMD_PAINT:
4973 addMainDirtyRect(pCmd->rect());
4974 break;
4975
4976#ifdef VBOX_WITH_VIDEOHWACCEL
4977 case VBOXVHWA_PIPECMD_VHWA:
4978 vboxDoVHWACmd(pCmd->vhwaCmdPtr(), pCmd->vhwaCmdType(), pCmd->vhwaIsGuestCmd());
4979 break;
4980
4981 case VBOXVHWA_PIPECMD_FUNC:
4982 {
4983 const VBOXVHWAFUNCCALLBACKINFO & info = pCmd->func();
4984 info.pfnCallback(info.pContext1, info.pContext2);
4985 break;
4986 }
4987#endif
4988 default:
4989 AssertFailed();
4990 }
4991}
4992
4993VBoxVHWACommandElementProcessor::VBoxVHWACommandElementProcessor()
4994 : m_pNotifyObject(NULL)
4995 , mpCurCmd(NULL)
4996 , mbResetting(false)
4997 , mcDisabled(0)
4998{
4999 int rc = RTCritSectInit(&mCritSect);
5000 AssertRC(rc);
5001
5002 RTListInit(&mCommandList);
5003
5004 m_pCmdEntryCache = new VBoxVHWAEntriesCache;
5005}
5006
5007void VBoxVHWACommandElementProcessor::init(QObject *pNotifyObject)
5008{
5009 m_pNotifyObject = pNotifyObject;
5010}
5011
5012VBoxVHWACommandElementProcessor::~VBoxVHWACommandElementProcessor()
5013{
5014 Assert(!m_NotifyObjectRefs.refs());
5015 RTListIsEmpty(&mCommandList);
5016
5017 RTCritSectDelete(&mCritSect);
5018
5019 delete m_pCmdEntryCache;
5020}
5021
5022void VBoxVHWACommandElementProcessor::postCmd(VBOXVHWA_PIPECMD_TYPE aType, void *pvData,
5023 int /*VBOXVHWACMD_TYPE*/ enmCmd, bool fGuestCmd)
5024{
5025 QObject *pNotifyObject = NULL;
5026
5027 Log(("VHWA post %d %#p\n", aType, pvData));
5028
5029 /* 1. lock*/
5030 RTCritSectEnter(&mCritSect);
5031
5032 VBoxVHWACommandElement *pCmd = m_pCmdEntryCache->alloc();
5033 if (!pCmd)
5034 {
5035 VBOXQGLLOG(("!!!no more free elements!!!\n"));
5036#ifdef VBOXQGL_PROF_BASE
5037 RTCritSectLeave(&mCritSect);
5038 return;
5039#else
5040 /// @todo
5041#endif
5042 }
5043 pCmd->setData(aType, pvData, enmCmd, fGuestCmd);
5044
5045 /* 2. if can add to current*/
5046 if (m_pNotifyObject)
5047 {
5048 m_NotifyObjectRefs.inc(); /* ensure the parent does not get destroyed while we are using it */
5049 pNotifyObject = m_pNotifyObject;
5050 }
5051
5052 RTListAppend(&mCommandList, &pCmd->ListNode);
5053
5054 RTCritSectLeave(&mCritSect);
5055
5056 if (pNotifyObject)
5057 {
5058 VBoxVHWACommandProcessEvent *pCurrentEvent = new VBoxVHWACommandProcessEvent();
5059 QApplication::postEvent(pNotifyObject, pCurrentEvent);
5060 m_NotifyObjectRefs.dec();
5061 }
5062}
5063
5064void VBoxVHWACommandElementProcessor::setNotifyObject(QObject *pNotifyObject)
5065{
5066 int cEventsNeeded = 0;
5067 RTCritSectEnter(&mCritSect);
5068 if (m_pNotifyObject == pNotifyObject)
5069 {
5070 RTCritSectLeave(&mCritSect);
5071 return;
5072 }
5073
5074 if (m_pNotifyObject)
5075 {
5076 m_pNotifyObject = NULL;
5077 RTCritSectLeave(&mCritSect);
5078
5079 m_NotifyObjectRefs.wait0();
5080
5081 RTCritSectEnter(&mCritSect);
5082 }
5083 else
5084 {
5085 /* NULL can not be references */
5086 Assert(!m_NotifyObjectRefs.refs());
5087 }
5088
5089 if (pNotifyObject)
5090 {
5091 m_pNotifyObject = pNotifyObject;
5092
5093 VBoxVHWACommandElement *pCur;
5094 RTListForEachCpp(&mCommandList, pCur, VBoxVHWACommandElement, ListNode)
5095 {
5096 ++cEventsNeeded;
5097 }
5098
5099 if (cEventsNeeded)
5100 m_NotifyObjectRefs.inc();
5101 }
5102 else
5103 {
5104 /* should be zeroed already */
5105 Assert(!m_pNotifyObject);
5106 }
5107
5108 RTCritSectLeave(&mCritSect);
5109
5110 if (cEventsNeeded)
5111 {
5112 /* cEventsNeeded can only be != 0 if pNotifyObject is valid */
5113 Assert(pNotifyObject);
5114 for (int i = 0; i < cEventsNeeded; ++i)
5115 {
5116 VBoxVHWACommandProcessEvent *pCurrentEvent = new VBoxVHWACommandProcessEvent();
5117 QApplication::postEvent(pNotifyObject, pCurrentEvent);
5118 }
5119 m_NotifyObjectRefs.dec();
5120 }
5121}
5122
5123void VBoxVHWACommandElementProcessor::doneCmd()
5124{
5125 VBoxVHWACommandElement *pEl;
5126 RTCritSectEnter(&mCritSect);
5127 pEl = mpCurCmd;
5128 Assert(mpCurCmd);
5129 mpCurCmd = NULL;
5130 RTCritSectLeave(&mCritSect);
5131
5132 if (pEl)
5133 m_pCmdEntryCache->free(pEl);
5134}
5135
5136VBoxVHWACommandElement *VBoxVHWACommandElementProcessor::getCmd()
5137{
5138 VBoxVHWACommandElement *pEl = NULL;
5139 RTCritSectEnter(&mCritSect);
5140
5141 Assert(!mpCurCmd);
5142
5143 if (mbResetting)
5144 {
5145 RTCritSectLeave(&mCritSect);
5146 return NULL;
5147 }
5148
5149 if (mcDisabled)
5150 {
5151 QObject *pNotifyObject = NULL;
5152
5153 if (!RTListIsEmpty(&mCommandList))
5154 {
5155 Assert(m_pNotifyObject);
5156 if (m_pNotifyObject)
5157 {
5158 m_NotifyObjectRefs.inc(); /* ensure the parent does not get destroyed while we are using it */
5159 pNotifyObject = m_pNotifyObject;
5160 }
5161 }
5162
5163 RTCritSectLeave(&mCritSect);
5164
5165 if (pNotifyObject)
5166 {
5167 VBoxVHWACommandProcessEvent *pCurrentEvent = new VBoxVHWACommandProcessEvent();
5168 QApplication::postEvent(pNotifyObject, pCurrentEvent);
5169 m_NotifyObjectRefs.dec();
5170 }
5171 return NULL;
5172 }
5173
5174 pEl = RTListGetFirstCpp(&mCommandList, VBoxVHWACommandElement, ListNode);
5175 if (pEl)
5176 {
5177 RTListNodeRemove(&pEl->ListNode);
5178 mpCurCmd = pEl;
5179 }
5180
5181 RTCritSectLeave(&mCritSect);
5182
5183 return pEl;
5184}
5185
5186/* it is currently assumed no one sends any new commands while reset is in progress */
5187void VBoxVHWACommandElementProcessor::reset(CDisplay *pDisplay)
5188{
5189 RTCritSectEnter(&mCritSect);
5190
5191 mbResetting = true;
5192
5193 if (mpCurCmd)
5194 {
5195 for (;;)
5196 {
5197 RTCritSectLeave(&mCritSect);
5198 RTThreadSleep(2); /* 2 ms */
5199 RTCritSectEnter(&mCritSect);
5200 /* it is assumed no one sends any new commands while reset is in progress */
5201 if (!mpCurCmd)
5202 {
5203 break;
5204 }
5205 }
5206 }
5207
5208 RTCritSectLeave(&mCritSect);
5209
5210 VBoxVHWACommandElement *pCur, *pNext;
5211 RTListForEachSafeCpp(&mCommandList, pCur, pNext, VBoxVHWACommandElement, ListNode)
5212 {
5213 switch (pCur->type())
5214 {
5215#ifdef VBOX_WITH_VIDEOHWACCEL
5216 case VBOXVHWA_PIPECMD_VHWA:
5217 {
5218 struct VBOXVHWACMD RT_UNTRUSTED_VOLATILE_GUEST *pCmd = pCur->vhwaCmdPtr();
5219 pCmd->rc = VERR_INVALID_STATE;
5220 Log(("VHWA Command <<< Async RESET %#p, %d\n", pCmd, pCmd->enmCmd));
5221 pDisplay->CompleteVHWACommand((BYTE *)pCmd);
5222 }
5223 break;
5224
5225 case VBOXVHWA_PIPECMD_FUNC:
5226 /* should not happen, don't handle this for now */
5227 AssertFailed();
5228 break;
5229#endif
5230 case VBOXVHWA_PIPECMD_PAINT:
5231 break;
5232
5233 default:
5234 /* should not happen, don't handle this for now */
5235 AssertFailed();
5236 break;
5237 }
5238
5239 RTListNodeRemove(&pCur->ListNode);
5240 m_pCmdEntryCache->free(pCur);
5241 }
5242
5243 RTCritSectEnter(&mCritSect);
5244
5245 mbResetting = false;
5246
5247 RTCritSectLeave(&mCritSect);
5248}
5249
5250#define VBOXVHWACOMMANDELEMENTLISTBEGIN_MAGIC UINT32_C(0x89abcdef)
5251#define VBOXVHWACOMMANDELEMENTLISTEND_MAGIC UINT32_C(0xfedcba98)
5252
5253int VBoxVHWACommandElementProcessor::loadExec(struct SSMHANDLE *pSSM, uint32_t u32Version, void *pvVRAM)
5254{
5255 uint32_t u32;
5256
5257 Q_UNUSED(u32Version);
5258
5259 int rc = SSMR3GetU32(pSSM, &u32);
5260 AssertRCReturn(rc, rc);
5261 AssertReturn(u32 == VBOXVHWACOMMANDELEMENTLISTBEGIN_MAGIC, VERR_INVALID_MAGIC);
5262
5263 SSMR3GetU32(pSSM, &u32);
5264 bool b;
5265 rc = SSMR3GetBool(pSSM, &b);
5266 AssertRCReturn(rc, rc);
5267
5268// m_NotifyObjectRefs = VBoxVHWARefCounter(u32);
5269 bool fContinue = true;
5270 do
5271 {
5272 rc = SSMR3GetU32(pSSM, &u32);
5273 AssertRCReturn(rc, rc);
5274
5275 bool fNewEvent;
5276 switch (u32)
5277 {
5278 case VBOXVHWA_PIPECMD_PAINT:
5279 {
5280 int x,y,w,h;
5281 rc = SSMR3GetS32(pSSM, &x);
5282 rc = SSMR3GetS32(pSSM, &y);
5283 rc = SSMR3GetS32(pSSM, &w);
5284 rc = SSMR3GetS32(pSSM, &h);
5285 rc = SSMR3GetBool(pSSM, &fNewEvent);
5286 AssertRCReturn(rc, rc);
5287
5288 QRect r = QRect(x, y, w, h);
5289 postCmd(VBOXVHWA_PIPECMD_PAINT, &r, -1, false);
5290 break;
5291 }
5292
5293 case VBOXVHWA_PIPECMD_VHWA:
5294 {
5295 uint32_t offCmd;
5296 rc = SSMR3GetU32(pSSM, &offCmd);
5297 rc = SSMR3GetBool(pSSM, &fNewEvent);
5298 AssertRCReturn(rc, rc);
5299
5300 VBOXVHWACMD *pCmd = (VBOXVHWACMD *)(((uint8_t *)pvVRAM) + offCmd);
5301 postCmd(VBOXVHWA_PIPECMD_VHWA, pCmd, pCmd->enmCmd, true);
5302 break;
5303 }
5304
5305 case VBOXVHWACOMMANDELEMENTLISTEND_MAGIC:
5306 fContinue = false;
5307 break;
5308
5309 default:
5310 AssertLogRelMsgFailed(("u32=%#x\n", u32));
5311 break;
5312 }
5313
5314 } while (fContinue && RT_SUCCESS(rc));
5315
5316 return rc;
5317}
5318
5319void VBoxVHWACommandElementProcessor::saveExec(struct SSMHANDLE *pSSM, void *pvVRAM)
5320{
5321 int rc;
5322
5323 rc = SSMR3PutU32(pSSM, VBOXVHWACOMMANDELEMENTLISTBEGIN_MAGIC);
5324 rc = SSMR3PutU32(pSSM, m_NotifyObjectRefs.refs());
5325 rc = SSMR3PutBool(pSSM, true);
5326 AssertRC(rc);
5327
5328 VBoxVHWACommandElement *pCur;
5329 RTListForEachCpp(&mCommandList, pCur, VBoxVHWACommandElement, ListNode)
5330 {
5331
5332 switch (pCur->type())
5333 {
5334 case VBOXVHWA_PIPECMD_PAINT:
5335 rc = SSMR3PutU32(pSSM, pCur->type());
5336 rc = SSMR3PutS32(pSSM, pCur->rect().x());
5337 rc = SSMR3PutS32(pSSM, pCur->rect().y());
5338 rc = SSMR3PutS32(pSSM, pCur->rect().width());
5339 rc = SSMR3PutS32(pSSM, pCur->rect().height());
5340 rc = SSMR3PutBool(pSSM, true);
5341 AssertRC(rc);
5342 break;
5343
5344 case VBOXVHWA_PIPECMD_VHWA:
5345 if (pCur->vhwaIsGuestCmd())
5346 {
5347 rc = SSMR3PutU32(pSSM, pCur->type());
5348 rc = SSMR3PutU32(pSSM, (uint32_t)(uintptr_t)pCur->vhwaCmdPtr() - (uintptr_t)pvVRAM);
5349 rc = SSMR3PutBool(pSSM, true);
5350 AssertRC(rc);
5351 }
5352 break;
5353
5354 default:
5355 AssertFailed();
5356 break;
5357 }
5358 }
5359
5360 rc = SSMR3PutU32(pSSM, VBOXVHWACOMMANDELEMENTLISTEND_MAGIC);
5361 AssertRC(rc);
5362}
5363
5364void VBoxVHWACommandElementProcessor::lock()
5365{
5366 RTCritSectEnter(&mCritSect);
5367
5368 if (mpCurCmd)
5369 {
5370 for (;;)
5371 {
5372 RTCritSectLeave(&mCritSect);
5373 RTThreadSleep(2); /* 2 ms */
5374 RTCritSectEnter(&mCritSect);
5375 /* it is assumed no one sends any new commands while reset is in progress */
5376 if (!mpCurCmd)
5377 {
5378 break;
5379 }
5380 }
5381 }
5382
5383 Assert(!mpCurCmd);
5384}
5385
5386void VBoxVHWACommandElementProcessor::unlock()
5387{
5388 RTCritSectLeave(&mCritSect);
5389}
5390
5391void VBoxVHWACommandElementProcessor::disable()
5392{
5393 lock();
5394 ++mcDisabled;
5395 unlock();
5396}
5397
5398void VBoxVHWACommandElementProcessor::enable()
5399{
5400 lock();
5401 --mcDisabled;
5402 unlock();
5403}
5404
5405/* static */
5406uint32_t VBoxVHWATextureImage::calcBytesPerLine(const VBoxVHWAColorFormat &format, int width)
5407{
5408 uint32_t pitch = (format.bitsPerPixel() * width + 7) / 8;
5409 switch (format.fourcc())
5410 {
5411 case FOURCC_YV12:
5412 /* make sure the color components pitch is multiple of 8
5413 * where 8 is 2 (for color component width is Y width / 2) * 4 for 4byte texture format */
5414 pitch = (pitch + 7) & ~7;
5415 break;
5416
5417 default:
5418 pitch = (pitch + 3) & ~3;
5419 break;
5420 }
5421 return pitch;
5422}
5423
5424/* static */
5425uint32_t VBoxVHWATextureImage::calcMemSize(const VBoxVHWAColorFormat &format, int width, int height)
5426{
5427 uint32_t pitch = calcBytesPerLine(format, width);
5428 switch (format.fourcc())
5429 {
5430 case FOURCC_YV12:
5431 /* we have 3 separate planes here
5432 * Y - pitch x height
5433 * U - pitch / 2 x height / 2
5434 * V - pitch / 2 x height / 2
5435 * */
5436 return 3 * pitch * height / 2;
5437
5438 default:
5439 return pitch * height;
5440 }
5441}
5442
5443VBoxVHWATextureImage::VBoxVHWATextureImage(const QRect &size, const VBoxVHWAColorFormat &format,
5444 class VBoxVHWAGlProgramMngr * aMgr, VBOXVHWAIMG_TYPE flags)
5445 : mVisibleDisplay(0)
5446 , mpProgram(0)
5447 , mProgramMngr(aMgr)
5448 , mpDst(NULL)
5449 , mpDstCKey(NULL)
5450 , mpSrcCKey(NULL)
5451 , mbNotIntersected(false)
5452{
5453 uint32_t pitch = calcBytesPerLine(format, size.width());
5454
5455 mpTex[0] = vboxVHWATextureCreate(NULL, size, format, pitch, flags);
5456 mColorFormat = format;
5457 if (mColorFormat.fourcc() == FOURCC_YV12)
5458 {
5459 QRect rect(size.x() / 2,size.y() / 2,size.width() / 2,size.height() / 2);
5460 mpTex[1] = vboxVHWATextureCreate(NULL, rect, format, pitch / 2, flags);
5461 mpTex[2] = vboxVHWATextureCreate(NULL, rect, format, pitch / 2, flags);
5462 mcTex = 3;
5463 }
5464 else
5465 mcTex = 1;
5466}
5467
5468void VBoxVHWATextureImage::deleteDisplayList()
5469{
5470 if (mVisibleDisplay)
5471 {
5472 glDeleteLists(mVisibleDisplay, 1);
5473 mVisibleDisplay = 0;
5474 }
5475}
5476
5477void VBoxVHWATextureImage::deleteDisplay()
5478{
5479 deleteDisplayList();
5480 mpProgram = NULL;
5481}
5482
5483void VBoxVHWATextureImage::draw(VBoxVHWATextureImage *pDst, const QRect *pDstRect, const QRect *pSrcRect)
5484{
5485 int tx1, ty1, tx2, ty2;
5486 pSrcRect->getCoords(&tx1, &ty1, &tx2, &ty2);
5487
5488 int bx1, by1, bx2, by2;
5489 pDstRect->getCoords(&bx1, &by1, &bx2, &by2);
5490
5491 tx2++; ty2++;bx2++; by2++;
5492
5493 glBegin(GL_QUADS);
5494 uint32_t c = texCoord(GL_TEXTURE0, tx1, ty1);
5495 if (pDst)
5496 pDst->texCoord(GL_TEXTURE0 + c, bx1, by1);
5497 glVertex2i(bx1, by1);
5498
5499 texCoord(GL_TEXTURE0, tx1, ty2);
5500 if (pDst)
5501 pDst->texCoord(GL_TEXTURE0 + c, bx1, by2);
5502 glVertex2i(bx1, by2);
5503
5504 texCoord(GL_TEXTURE0, tx2, ty2);
5505 if (pDst)
5506 pDst->texCoord(GL_TEXTURE0 + c, bx2, by2);
5507 glVertex2i(bx2, by2);
5508
5509 texCoord(GL_TEXTURE0, tx2, ty1);
5510 if (pDst)
5511 pDst->texCoord(GL_TEXTURE0 + c, bx2, by1);
5512 glVertex2i(bx2, by1);
5513
5514 glEnd();
5515}
5516
5517void VBoxVHWATextureImage::internalSetDstCKey(const VBoxVHWAColorKey * pDstCKey)
5518{
5519 if (pDstCKey)
5520 {
5521 mDstCKey = *pDstCKey;
5522 mpDstCKey = &mDstCKey;
5523 }
5524 else
5525 {
5526 mpDstCKey = NULL;
5527 }
5528}
5529
5530void VBoxVHWATextureImage::internalSetSrcCKey(const VBoxVHWAColorKey * pSrcCKey)
5531{
5532 if (pSrcCKey)
5533 {
5534 mSrcCKey = *pSrcCKey;
5535 mpSrcCKey = &mSrcCKey;
5536 }
5537 else
5538 {
5539 mpSrcCKey = NULL;
5540 }
5541}
5542
5543int VBoxVHWATextureImage::initDisplay(VBoxVHWATextureImage *pDst,
5544 const QRect *pDstRect, const QRect *pSrcRect,
5545 const VBoxVHWAColorKey *pDstCKey, const VBoxVHWAColorKey *pSrcCKey, bool bNotIntersected)
5546{
5547 if ( !mVisibleDisplay
5548 || mpDst != pDst
5549 || *pDstRect != mDstRect
5550 || *pSrcRect != mSrcRect
5551 || !!(pDstCKey) != !!(mpDstCKey)
5552 || !!(pSrcCKey) != !!(mpSrcCKey)
5553 || mbNotIntersected != bNotIntersected
5554 || mpProgram != calcProgram(pDst, pDstCKey, pSrcCKey, bNotIntersected))
5555 return createSetDisplay(pDst, pDstRect, pSrcRect, pDstCKey, pSrcCKey, bNotIntersected);
5556 if ( (pDstCKey && mpDstCKey && *pDstCKey != *mpDstCKey)
5557 || (pSrcCKey && mpSrcCKey && *pSrcCKey != *mpSrcCKey))
5558 {
5559 Assert(mpProgram);
5560 updateSetCKeys(pDstCKey, pSrcCKey);
5561 return VINF_SUCCESS;
5562 }
5563 return VINF_SUCCESS;
5564}
5565
5566void VBoxVHWATextureImage::bind(VBoxVHWATextureImage * pPrimary)
5567{
5568 for (uint32_t i = 1; i < mcTex; i++)
5569 {
5570 vboxglActiveTexture(GL_TEXTURE0 + i);
5571 mpTex[i]->bind();
5572 }
5573 if (pPrimary)
5574 for (uint32_t i = 0; i < pPrimary->mcTex; i++)
5575 {
5576 vboxglActiveTexture(GL_TEXTURE0 + i + mcTex);
5577 pPrimary->mpTex[i]->bind();
5578 }
5579
5580 vboxglActiveTexture(GL_TEXTURE0);
5581 mpTex[0]->bind();
5582}
5583
5584uint32_t VBoxVHWATextureImage::calcProgramType(VBoxVHWATextureImage *pDst, const VBoxVHWAColorKey *pDstCKey,
5585 const VBoxVHWAColorKey *pSrcCKey, bool bNotIntersected)
5586{
5587 uint32_t type = 0;
5588
5589 if (pDstCKey != NULL)
5590 type |= VBOXVHWA_PROGRAM_DSTCOLORKEY;
5591 if (pSrcCKey)
5592 type |= VBOXVHWA_PROGRAM_SRCCOLORKEY;
5593 if ((pDstCKey || pSrcCKey) && bNotIntersected)
5594 type |= VBOXVHWA_PROGRAM_COLORKEYNODISCARD;
5595
5596 NOREF(pDst);
5597 return type;
5598}
5599
5600class VBoxVHWAGlProgramVHWA *VBoxVHWATextureImage::calcProgram(VBoxVHWATextureImage *pDst, const VBoxVHWAColorKey *pDstCKey,
5601 const VBoxVHWAColorKey *pSrcCKey, bool bNotIntersected)
5602{
5603 uint32_t type = calcProgramType(pDst, pDstCKey, pSrcCKey, bNotIntersected);
5604
5605 return mProgramMngr->getProgram(type, &pixelFormat(), pDst ? &pDst->pixelFormat() : NULL);
5606}
5607
5608int VBoxVHWATextureImage::createSetDisplay(VBoxVHWATextureImage *pDst, const QRect *pDstRect, const QRect *pSrcRect,
5609 const VBoxVHWAColorKey *pDstCKey, const VBoxVHWAColorKey * pSrcCKey,
5610 bool bNotIntersected)
5611{
5612 deleteDisplay();
5613 int rc = createDisplay(pDst, pDstRect, pSrcRect, pDstCKey, pSrcCKey, bNotIntersected, &mVisibleDisplay, &mpProgram);
5614 if (RT_FAILURE(rc))
5615 {
5616 mVisibleDisplay = 0;
5617 mpProgram = NULL;
5618 }
5619
5620 mpDst = pDst;
5621
5622 mDstRect = *pDstRect;
5623 mSrcRect = *pSrcRect;
5624
5625 internalSetDstCKey(pDstCKey);
5626 internalSetSrcCKey(pSrcCKey);
5627
5628 mbNotIntersected = bNotIntersected;
5629
5630 return rc;
5631}
5632
5633
5634int VBoxVHWATextureImage::createDisplayList(VBoxVHWATextureImage *pDst, const QRect *pDstRect, const QRect *pSrcRect,
5635 const VBoxVHWAColorKey *pDstCKey, const VBoxVHWAColorKey *pSrcCKey,
5636 bool bNotIntersected, GLuint *pDisplay)
5637{
5638 Q_UNUSED(pDstCKey);
5639 Q_UNUSED(pSrcCKey);
5640 Q_UNUSED(bNotIntersected);
5641
5642 glGetError(); /* clear the err flag */
5643 GLuint display = glGenLists(1);
5644 GLenum err = glGetError();
5645 if (err == GL_NO_ERROR)
5646 {
5647 Assert(display);
5648 if (!display)
5649 {
5650 /* well, it seems it should not return 0 on success according to the spec,
5651 * but just in case, pick another one */
5652 display = glGenLists(1);
5653 err = glGetError();
5654 if (err == GL_NO_ERROR)
5655 {
5656 Assert(display);
5657 }
5658 else
5659 {
5660 /* we are failed */
5661 Assert(!display);
5662 display = 0;
5663 }
5664 }
5665
5666 if (display)
5667 {
5668 glNewList(display, GL_COMPILE);
5669
5670 runDisplay(pDst, pDstRect, pSrcRect);
5671
5672 glEndList();
5673 VBOXQGL_ASSERTNOERR();
5674 *pDisplay = display;
5675 return VINF_SUCCESS;
5676 }
5677 }
5678 else
5679 {
5680 VBOXQGLLOG(("gl error ocured (0x%x)\n", err));
5681 Assert(err == GL_NO_ERROR);
5682 }
5683 return VERR_GENERAL_FAILURE;
5684}
5685
5686void VBoxVHWATextureImage::updateCKeys(VBoxVHWATextureImage *pDst, class VBoxVHWAGlProgramVHWA *pProgram,
5687 const VBoxVHWAColorKey *pDstCKey, const VBoxVHWAColorKey *pSrcCKey)
5688{
5689 if (pProgram)
5690 {
5691 pProgram->start();
5692 if (pSrcCKey)
5693 VBoxVHWATextureImage::setCKey(pProgram, &pixelFormat(), pSrcCKey, false);
5694 if (pDstCKey)
5695 VBoxVHWATextureImage::setCKey(pProgram, &pDst->pixelFormat(), pDstCKey, true);
5696 pProgram->stop();
5697 }
5698}
5699
5700void VBoxVHWATextureImage::updateSetCKeys(const VBoxVHWAColorKey *pDstCKey, const VBoxVHWAColorKey *pSrcCKey)
5701{
5702 updateCKeys(mpDst, mpProgram, pDstCKey, pSrcCKey);
5703 internalSetDstCKey(pDstCKey);
5704 internalSetSrcCKey(pSrcCKey);
5705}
5706
5707int VBoxVHWATextureImage::createDisplay(VBoxVHWATextureImage *pDst, const QRect *pDstRect, const QRect *pSrcRect,
5708 const VBoxVHWAColorKey *pDstCKey, const VBoxVHWAColorKey *pSrcCKey, bool bNotIntersected,
5709 GLuint *pDisplay, class VBoxVHWAGlProgramVHWA **ppProgram)
5710{
5711 VBoxVHWAGlProgramVHWA *pProgram = NULL;
5712 if (!pDst)
5713 {
5714 /* sanity */
5715 Assert(pDstCKey == NULL);
5716 pDstCKey = NULL;
5717 }
5718
5719 Assert(!pSrcCKey);
5720 if (pSrcCKey)
5721 pSrcCKey = NULL; /* fallback */
5722
5723 pProgram = calcProgram(pDst, pDstCKey, pSrcCKey, bNotIntersected);
5724
5725 updateCKeys(pDst, pProgram, pDstCKey, pSrcCKey);
5726
5727 GLuint displ;
5728 int rc = createDisplayList(pDst, pDstRect, pSrcRect, pDstCKey, pSrcCKey, bNotIntersected, &displ);
5729 if (RT_SUCCESS(rc))
5730 {
5731 *pDisplay = displ;
5732 *ppProgram = pProgram;
5733 }
5734
5735 return rc;
5736}
5737
5738void VBoxVHWATextureImage::display(VBoxVHWATextureImage *pDst, const QRect *pDstRect, const QRect *pSrcRect,
5739 const VBoxVHWAColorKey *pDstCKey, const VBoxVHWAColorKey *pSrcCKey, bool bNotIntersected)
5740{
5741 VBoxVHWAGlProgramVHWA *pProgram = calcProgram(pDst, pDstCKey, pSrcCKey, bNotIntersected);
5742 if (pProgram)
5743 pProgram->start();
5744
5745 runDisplay(pDst, pDstRect, pSrcRect);
5746
5747 if (pProgram)
5748 pProgram->stop();
5749}
5750
5751void VBoxVHWATextureImage::display()
5752{
5753#ifdef DEBUG_misha
5754 if (mpDst)
5755 dbgDump();
5756
5757 static bool bDisplayOn = true;
5758#endif
5759 Assert(mVisibleDisplay);
5760 if ( mVisibleDisplay
5761#ifdef DEBUG_misha
5762 && bDisplayOn
5763#endif
5764 )
5765 {
5766 if (mpProgram)
5767 mpProgram->start();
5768
5769 VBOXQGL_CHECKERR(
5770 glCallList(mVisibleDisplay);
5771 );
5772
5773 if (mpProgram)
5774 mpProgram->stop();
5775 }
5776 else
5777 {
5778 display(mpDst, &mDstRect, &mSrcRect,
5779 mpDstCKey, mpSrcCKey, mbNotIntersected);
5780 }
5781}
5782
5783#ifdef DEBUG_misha
5784void VBoxVHWATextureImage::dbgDump()
5785{
5786 for (uint32_t i = 0; i < mcTex; ++i)
5787 mpTex[i]->dbgDump();
5788}
5789#endif
5790
5791int VBoxVHWATextureImage::setCKey(VBoxVHWAGlProgramVHWA *pProgram, const VBoxVHWAColorFormat *pFormat,
5792 const VBoxVHWAColorKey *pCKey, bool bDst)
5793{
5794 float r,g,b;
5795 pFormat->pixel2Normalized(pCKey->lower(), &r, &g, &b);
5796 int rcL = bDst ? pProgram->setDstCKeyLowerRange(r, g, b) : pProgram->setSrcCKeyLowerRange(r, g, b);
5797 Assert(RT_SUCCESS(rcL));
5798
5799 return RT_SUCCESS(rcL) /*&& RT_SUCCESS(rcU)*/ ? VINF_SUCCESS: VERR_GENERAL_FAILURE;
5800}
5801
5802VBoxVHWASettings::VBoxVHWASettings ()
5803{
5804}
5805
5806void VBoxVHWASettings::init(CSession &session)
5807{
5808 const QUuid uMachineID = session.GetMachine().GetId();
5809
5810 mStretchLinearEnabled = gEDataManager->useLinearStretch(uMachineID);
5811
5812 uint32_t aFourccs[VBOXVHWA_NUMFOURCC];
5813 int num = 0;
5814 if (gEDataManager->usePixelFormatAYUV(uMachineID))
5815 aFourccs[num++] = FOURCC_AYUV;
5816 if (gEDataManager->usePixelFormatUYVY(uMachineID))
5817 aFourccs[num++] = FOURCC_UYVY;
5818 if (gEDataManager->usePixelFormatYUY2(uMachineID))
5819 aFourccs[num++] = FOURCC_YUY2;
5820 if (gEDataManager->usePixelFormatYV12(uMachineID))
5821 aFourccs[num++] = FOURCC_YV12;
5822
5823 mFourccEnabledCount = num;
5824 memcpy(mFourccEnabledList, aFourccs, num* sizeof (aFourccs[0]));
5825}
5826
5827int VBoxVHWASettings::calcIntersection(int c1, const uint32_t *a1, int c2, const uint32_t *a2, int cOut, uint32_t *aOut)
5828{
5829 /* fourcc arrays are not big, so linear search is enough,
5830 * also no need to check for duplicates */
5831 int cMatch = 0;
5832 for (int i = 0; i < c1; ++i)
5833 {
5834 uint32_t cur1 = a1[i];
5835 for (int j = 0; j < c2; ++j)
5836 {
5837 uint32_t cur2 = a2[j];
5838 if (cur1 == cur2)
5839 {
5840 if (cOut > cMatch && aOut)
5841 aOut[cMatch] = cur1;
5842 ++cMatch;
5843 break;
5844 }
5845 }
5846 }
5847
5848 return cMatch;
5849}
5850
5851#endif /* VBOX_GUI_USE_QGL */
5852
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use