VirtualBox

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

Last change on this file since 43138 was 41689, checked in by vboxsync, 12 years ago

FE/Qt: VBoxDefs renamed to UIDefs and reworked into namespace. Corresponding files which were using VBoxDefs updated.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use