VirtualBox

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

Last change on this file since 74942 was 74878, checked in by vboxsync, 6 years ago

FE/Qt: bugref:9261: Changed COMWrapper to generate QUuid for GUID instead of QString

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

© 2023 Oracle
ContactPrivacy policyTerms of Use