VirtualBox

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

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

FE/Qt: NOREF

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

© 2023 Oracle
ContactPrivacy policyTerms of Use