VirtualBox

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

Last change on this file since 35740 was 35500, checked in by vboxsync, 13 years ago

FE/Qt: NOREF

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

© 2023 Oracle
ContactPrivacy policyTerms of Use