VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/VBoxFBOverlay.h@ 39816

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

fix DEBUG_misha builds for linux host

  • Property svn:eol-style set to native
File size: 57.5 KB
Line 
1/** @file
2 *
3 * VBox frontends: Qt GUI ("VirtualBox"):
4 * VBoxFrameBuffer Overly classes declarations
5 */
6
7/*
8 * Copyright (C) 2006-2007 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18#ifndef __VBoxFBOverlay_h__
19#define __VBoxFBOverlay_h__
20#if defined (VBOX_GUI_USE_QGL) || defined(VBOX_WITH_VIDEOHWACCEL)
21
22//#define VBOXQGL_PROF_BASE 1
23//#define VBOXQGL_DBG_SURF 1
24
25//#define VBOXVHWADBG_RENDERCHECK
26
27#include "COMDefs.h"
28#include <QGLWidget>
29#include <iprt/assert.h>
30#include <iprt/critsect.h>
31#include <iprt/asm.h>
32#include <iprt/err.h>
33
34#include <VBox/VBoxGL2D.h>
35#include "VBoxFBOverlayCommon.h"
36
37#define VBOXVHWA_ALLOW_PRIMARY_AND_OVERLAY_ONLY 1
38
39#ifdef DEBUG_misha
40# define VBOXVHWA_PROFILE_FPS
41#endif
42
43#ifdef VBOXVHWA_PROFILE_FPS
44# include <iprt/stream.h>
45#endif
46
47#ifdef DEBUG
48class VBoxVHWADbgTimer
49{
50public:
51 VBoxVHWADbgTimer(uint32_t cPeriods);
52 ~VBoxVHWADbgTimer();
53 void frame();
54 uint64_t everagePeriod() {return mPeriodSum / mcPeriods; }
55 double fps() {return ((double)1000000000.0) / everagePeriod(); }
56 uint64_t frames() {return mcFrames; }
57private:
58 uint64_t mPeriodSum;
59 uint64_t *mpaPeriods;
60 uint64_t mPrevTime;
61 uint64_t mcFrames;
62 uint32_t mcPeriods;
63 uint32_t miPeriod;
64};
65
66#endif
67
68class VBoxVHWASettings
69{
70public:
71 VBoxVHWASettings (CSession &session);
72
73 int fourccEnabledCount() const { return mFourccEnabledCount; }
74 const uint32_t * fourccEnabledList() const { return mFourccEnabledList; }
75
76 bool isStretchLinearEnabled() const { return mStretchLinearEnabled; }
77
78 static int calcIntersection (int c1, const uint32_t *a1, int c2, const uint32_t *a2, int cOut, uint32_t *aOut);
79
80 int getIntersection (const VBoxVHWAInfo &aInfo, int cOut, uint32_t *aOut)
81 {
82 return calcIntersection (mFourccEnabledCount, mFourccEnabledList, aInfo.getFourccSupportedCount(), aInfo.getFourccSupportedList(), cOut, aOut);
83 }
84
85 bool isSupported(const VBoxVHWAInfo &aInfo, uint32_t format)
86 {
87 return calcIntersection (mFourccEnabledCount, mFourccEnabledList, 1, &format, 0, NULL)
88 && calcIntersection (aInfo.getFourccSupportedCount(), aInfo.getFourccSupportedList(), 1, &format, 0, NULL);
89 }
90private:
91 uint32_t mFourccEnabledList[VBOXVHWA_NUMFOURCC];
92 int mFourccEnabledCount;
93 bool mStretchLinearEnabled;
94};
95
96class VBoxVHWADirtyRect
97{
98public:
99 VBoxVHWADirtyRect() :
100 mIsClear(true)
101 {}
102
103 VBoxVHWADirtyRect(const QRect & aRect)
104 {
105 if(aRect.isEmpty())
106 {
107 mIsClear = false;
108 mRect = aRect;
109 }
110 else
111 {
112 mIsClear = true;
113 }
114 }
115
116 bool isClear() const { return mIsClear; }
117
118 void add(const QRect & aRect)
119 {
120 if(aRect.isEmpty())
121 return;
122
123 mRect = mIsClear ? aRect : mRect.united(aRect);
124 mIsClear = false;
125 }
126
127 void add(const VBoxVHWADirtyRect & aRect)
128 {
129 if(aRect.isClear())
130 return;
131 add(aRect.rect());
132 }
133
134 void set(const QRect & aRect)
135 {
136 if(aRect.isEmpty())
137 {
138 mIsClear = true;
139 }
140 else
141 {
142 mRect = aRect;
143 mIsClear = false;
144 }
145 }
146
147 void clear() { mIsClear = true; }
148
149 const QRect & rect() const {return mRect;}
150
151 const QRect & toRect()
152 {
153 if(isClear())
154 {
155 mRect.setCoords(0, 0, -1, -1);
156 }
157 return mRect;
158 }
159
160 bool intersects(const QRect & aRect) const {return mIsClear ? false : mRect.intersects(aRect);}
161
162 bool intersects(const VBoxVHWADirtyRect & aRect) const {return mIsClear ? false : aRect.intersects(mRect);}
163
164 QRect united(const QRect & aRect) const {return mIsClear ? aRect : aRect.united(mRect);}
165
166 bool contains(const QRect & aRect) const {return mIsClear ? false : aRect.contains(mRect);}
167
168 void subst(const VBoxVHWADirtyRect & aRect) { if(!mIsClear && aRect.contains(mRect)) clear(); }
169
170private:
171 QRect mRect;
172 bool mIsClear;
173};
174
175class VBoxVHWAColorKey
176{
177public:
178 VBoxVHWAColorKey() :
179 mUpper(0),
180 mLower(0)
181 {}
182
183 VBoxVHWAColorKey(uint32_t aUpper, uint32_t aLower) :
184 mUpper(aUpper),
185 mLower(aLower)
186 {}
187
188 uint32_t upper() const {return mUpper; }
189 uint32_t lower() const {return mLower; }
190
191 bool operator==(const VBoxVHWAColorKey & other) const { return mUpper == other.mUpper && mLower == other.mLower; }
192 bool operator!=(const VBoxVHWAColorKey & other) const { return !(*this == other); }
193private:
194 uint32_t mUpper;
195 uint32_t mLower;
196};
197
198class VBoxVHWAColorComponent
199{
200public:
201 VBoxVHWAColorComponent() :
202 mMask(0),
203 mRange(0),
204 mOffset(32),
205 mcBits(0)
206 {}
207
208 VBoxVHWAColorComponent(uint32_t aMask);
209
210 uint32_t mask() const { return mMask; }
211 uint32_t range() const { return mRange; }
212 uint32_t offset() const { return mOffset; }
213 uint32_t cBits() const { return mcBits; }
214 uint32_t colorVal(uint32_t col) const { return (col & mMask) >> mOffset; }
215 float colorValNorm(uint32_t col) const { return ((float)colorVal(col))/mRange; }
216private:
217 uint32_t mMask;
218 uint32_t mRange;
219 uint32_t mOffset;
220 uint32_t mcBits;
221};
222
223class VBoxVHWAColorFormat
224{
225public:
226
227 VBoxVHWAColorFormat(uint32_t bitsPerPixel, uint32_t r, uint32_t g, uint32_t b);
228 VBoxVHWAColorFormat(uint32_t fourcc);
229 VBoxVHWAColorFormat() :
230 mBitsPerPixel(0) /* needed for isValid() to work */
231 {}
232 GLint internalFormat() const {return mInternalFormat; }
233 GLenum format() const {return mFormat; }
234 GLenum type() const {return mType; }
235 bool isValid() const {return mBitsPerPixel != 0; }
236 uint32_t fourcc() const {return mDataFormat;}
237 uint32_t bitsPerPixel() const { return mBitsPerPixel; }
238 uint32_t bitsPerPixelTex() const { return mBitsPerPixelTex; }
239 void pixel2Normalized(uint32_t pix, float *r, float *g, float *b) const;
240 uint32_t widthCompression() const {return mWidthCompression;}
241 uint32_t heightCompression() const {return mHeightCompression;}
242 const VBoxVHWAColorComponent& r() const {return mR;}
243 const VBoxVHWAColorComponent& g() const {return mG;}
244 const VBoxVHWAColorComponent& b() const {return mB;}
245 const VBoxVHWAColorComponent& a() const {return mA;}
246
247 bool equals (const VBoxVHWAColorFormat & other) const;
248
249 ulong toVBoxPixelFormat() const
250 {
251 if (!mDataFormat)
252 {
253 /* RGB data */
254 switch (mFormat)
255 {
256 case GL_BGRA_EXT:
257 return FramebufferPixelFormat_FOURCC_RGB;
258 }
259 }
260 return FramebufferPixelFormat_Opaque;
261 }
262
263private:
264 void init(uint32_t bitsPerPixel, uint32_t r, uint32_t g, uint32_t b);
265 void init(uint32_t fourcc);
266
267 GLint mInternalFormat;
268 GLenum mFormat;
269 GLenum mType;
270 uint32_t mDataFormat;
271
272 uint32_t mBitsPerPixel;
273 uint32_t mBitsPerPixelTex;
274 uint32_t mWidthCompression;
275 uint32_t mHeightCompression;
276 VBoxVHWAColorComponent mR;
277 VBoxVHWAColorComponent mG;
278 VBoxVHWAColorComponent mB;
279 VBoxVHWAColorComponent mA;
280};
281
282class VBoxVHWATexture
283{
284public:
285 VBoxVHWATexture() :
286 mAddress(NULL),
287 mTexture(0),
288 mBytesPerPixel(0),
289 mBytesPerPixelTex(0),
290 mBytesPerLine(0),
291 mScaleFuncttion(GL_NEAREST)
292{}
293 VBoxVHWATexture(const QRect & aRect, const VBoxVHWAColorFormat &aFormat, uint32_t bytesPerLine, GLint scaleFuncttion);
294 virtual ~VBoxVHWATexture();
295 virtual void init(uchar *pvMem);
296 void setAddress(uchar *pvMem) {mAddress = pvMem;}
297 void update(const QRect * pRect) { doUpdate(mAddress, pRect);}
298 void bind() {glBindTexture(texTarget(), mTexture);}
299
300 virtual void texCoord(int x, int y);
301 virtual void multiTexCoord(GLenum texUnit, int x, int y);
302
303 const QRect & texRect() {return mTexRect;}
304 const QRect & rect() {return mRect;}
305 uchar * address(){ return mAddress; }
306 uint32_t rectSizeTex(const QRect * pRect) {return pRect->width() * pRect->height() * mBytesPerPixelTex;}
307 uchar * pointAddress(int x, int y)
308 {
309 x = toXTex(x);
310 y = toYTex(y);
311 return pointAddressTex(x, y);
312 }
313 uint32_t pointOffsetTex(int x, int y) { return y*mBytesPerLine + x*mBytesPerPixelTex; }
314 uchar * pointAddressTex(int x, int y) { return mAddress + pointOffsetTex(x, y); }
315 int toXTex(int x) {return x/mColorFormat.widthCompression();}
316 int toYTex(int y) {return y/mColorFormat.heightCompression();}
317 ulong memSize(){ return mBytesPerLine * mRect.height(); }
318 uint32_t bytesPerLine() {return mBytesPerLine; }
319#ifdef DEBUG_misha
320 void dbgDump();
321#endif
322
323protected:
324 virtual void doUpdate(uchar * pAddress, const QRect * pRect);
325 virtual void initParams();
326 virtual void load();
327 virtual GLenum texTarget() {return GL_TEXTURE_2D; }
328 GLuint texture() {return mTexture;}
329
330 QRect mTexRect; /* texture size */
331 QRect mRect; /* img size */
332 uchar * mAddress;
333 GLuint mTexture;
334 uint32_t mBytesPerPixel;
335 uint32_t mBytesPerPixelTex;
336 uint32_t mBytesPerLine;
337 VBoxVHWAColorFormat mColorFormat;
338 GLint mScaleFuncttion;
339private:
340 void uninit();
341
342 friend class VBoxVHWAFBO;
343};
344
345class VBoxVHWATextureNP2 : public VBoxVHWATexture
346{
347public:
348 VBoxVHWATextureNP2() : VBoxVHWATexture() {}
349 VBoxVHWATextureNP2(const QRect & aRect, const VBoxVHWAColorFormat &aFormat, uint32_t bytesPerLine, GLint scaleFuncttion) :
350 VBoxVHWATexture(aRect, aFormat, bytesPerLine, scaleFuncttion){
351 mTexRect = QRect(0, 0, aRect.width()/aFormat.widthCompression(), aRect.height()/aFormat.heightCompression());
352 }
353};
354
355class VBoxVHWATextureNP2Rect : public VBoxVHWATextureNP2
356{
357public:
358 VBoxVHWATextureNP2Rect() : VBoxVHWATextureNP2() {}
359 VBoxVHWATextureNP2Rect(const QRect & aRect, const VBoxVHWAColorFormat &aFormat, uint32_t bytesPerLine, GLint scaleFuncttion) :
360 VBoxVHWATextureNP2(aRect, aFormat, bytesPerLine, scaleFuncttion){}
361
362 virtual void texCoord(int x, int y);
363 virtual void multiTexCoord(GLenum texUnit, int x, int y);
364protected:
365 virtual GLenum texTarget();
366};
367
368class VBoxVHWATextureNP2RectPBO : public VBoxVHWATextureNP2Rect
369{
370public:
371 VBoxVHWATextureNP2RectPBO() :
372 VBoxVHWATextureNP2Rect(),
373 mPBO(0)
374 {}
375 VBoxVHWATextureNP2RectPBO(const QRect & aRect, const VBoxVHWAColorFormat &aFormat, uint32_t bytesPerLine, GLint scaleFuncttion) :
376 VBoxVHWATextureNP2Rect(aRect, aFormat, bytesPerLine, scaleFuncttion),
377 mPBO(0)
378 {}
379
380 virtual ~VBoxVHWATextureNP2RectPBO();
381
382 virtual void init(uchar *pvMem);
383protected:
384 virtual void load();
385 virtual void doUpdate(uchar * pAddress, const QRect * pRect);
386 GLuint mPBO;
387};
388
389class VBoxVHWATextureNP2RectPBOMapped : public VBoxVHWATextureNP2RectPBO
390{
391public:
392 VBoxVHWATextureNP2RectPBOMapped() :
393 VBoxVHWATextureNP2RectPBO(),
394 mpMappedAllignedBuffer(NULL),
395 mcbAllignedBufferSize(0),
396 mcbOffset(0)
397 {}
398 VBoxVHWATextureNP2RectPBOMapped(const QRect & aRect, const VBoxVHWAColorFormat &aFormat, uint32_t bytesPerLine, GLint scaleFuncttion) :
399 VBoxVHWATextureNP2RectPBO(aRect, aFormat, bytesPerLine, scaleFuncttion),
400 mpMappedAllignedBuffer(NULL),
401 mcbOffset(0)
402 {
403 mcbAllignedBufferSize = alignSize((size_t)memSize());
404 mcbActualBufferSize = mcbAllignedBufferSize + 0x1fff;
405 }
406
407 uchar* mapAlignedBuffer();
408 void unmapBuffer();
409 size_t alignedBufferSize() { return mcbAllignedBufferSize; }
410
411 static size_t alignSize(size_t size)
412 {
413 size_t alSize = size & ~((size_t)0xfff);
414 return alSize == size ? alSize : alSize + 0x1000;
415 }
416
417 static void* alignBuffer(void* pvMem) { return (void*)(((uintptr_t)pvMem) & ~((uintptr_t)0xfff)); }
418 static size_t calcOffset(void* pvBase, void* pvOffset) { return (size_t)(((uintptr_t)pvBase) - ((uintptr_t)pvOffset)); }
419protected:
420 virtual void load();
421 virtual void doUpdate(uchar * pAddress, const QRect * pRect);
422private:
423 uchar* mpMappedAllignedBuffer;
424 size_t mcbAllignedBufferSize;
425 size_t mcbOffset;
426 size_t mcbActualBufferSize;
427};
428
429#define VBOXVHWAIMG_PBO 0x00000001U
430#define VBOXVHWAIMG_PBOIMG 0x00000002U
431#define VBOXVHWAIMG_FBO 0x00000004U
432#define VBOXVHWAIMG_LINEAR 0x00000008U
433typedef uint32_t VBOXVHWAIMG_TYPE;
434
435class VBoxVHWATextureImage
436{
437public:
438 VBoxVHWATextureImage(const QRect &size, const VBoxVHWAColorFormat &format, class VBoxVHWAGlProgramMngr * aMgr, VBOXVHWAIMG_TYPE flags);
439
440 virtual ~VBoxVHWATextureImage()
441 {
442 for(uint i = 0; i < mcTex; i++)
443 {
444 delete mpTex[i];
445 }
446 }
447
448 virtual void init(uchar *pvMem)
449 {
450 for(uint32_t i = 0; i < mcTex; i++)
451 {
452 mpTex[i]->init(pvMem);
453 pvMem += mpTex[i]->memSize();
454 }
455 }
456
457 virtual void update(const QRect * pRect)
458 {
459 mpTex[0]->update(pRect);
460 if(mColorFormat.fourcc() == FOURCC_YV12)
461 {
462 if(pRect)
463 {
464 QRect rect(pRect->x()/2, pRect->y()/2,
465 pRect->width()/2, pRect->height()/2);
466 mpTex[1]->update(&rect);
467 mpTex[2]->update(&rect);
468 }
469 else
470 {
471 mpTex[1]->update(NULL);
472 mpTex[2]->update(NULL);
473 }
474 }
475 }
476
477 virtual void display(VBoxVHWATextureImage *pDst, const QRect * pDstRect, const QRect * pSrcRect,
478 const VBoxVHWAColorKey * pDstCKey, const VBoxVHWAColorKey * pSrcCKey, bool bNotIntersected);
479
480
481 virtual void display();
482
483 void deleteDisplay();
484
485 int initDisplay(VBoxVHWATextureImage *pDst,
486 const QRect * pDstRect, const QRect * pSrcRect,
487 const VBoxVHWAColorKey * pDstCKey, const VBoxVHWAColorKey * pSrcCKey, bool bNotIntersected);
488
489 bool displayInitialized() { return !!mVisibleDisplay;}
490
491 virtual void setAddress(uchar *pvMem)
492 {
493 for(uint32_t i = 0; i < mcTex; i++)
494 {
495 mpTex[i]->setAddress(pvMem);
496 pvMem += mpTex[i]->memSize();
497 }
498 }
499
500 const QRect &rect()
501 {
502 return mpTex[0]->rect();
503 }
504
505 size_t memSize()
506 {
507 size_t size = 0;
508 for(uint32_t i = 0; i < mcTex; i++)
509 {
510 size+=mpTex[i]->memSize();
511 }
512 return size;
513 }
514
515 uint32_t bytesPerLine() { return mpTex[0]->bytesPerLine(); }
516
517 const VBoxVHWAColorFormat &pixelFormat() { return mColorFormat; }
518
519 uint32_t numComponents() {return mcTex;}
520
521 VBoxVHWATexture* component(uint32_t i) {return mpTex[i]; }
522
523 const VBoxVHWATextureImage *dst() { return mpDst;}
524 const QRect& dstRect() { return mDstRect; }
525 const QRect& srcRect() { return mSrcRect; }
526 const VBoxVHWAColorKey* dstCKey() { return mpDstCKey; }
527 const VBoxVHWAColorKey* srcCKey() { return mpSrcCKey; }
528 bool notIntersectedMode() { return mbNotIntersected; }
529
530 static uint32_t calcBytesPerLine(const VBoxVHWAColorFormat & format, int width);
531 static uint32_t calcMemSize(const VBoxVHWAColorFormat & format, int width, int height);
532
533#ifdef DEBUG_misha
534 void dbgDump();
535#endif
536
537protected:
538 static int setCKey(class VBoxVHWAGlProgramVHWA * pProgram, const VBoxVHWAColorFormat * pFormat, const VBoxVHWAColorKey * pCKey, bool bDst);
539
540 static bool matchCKeys(const VBoxVHWAColorKey * pCKey1, const VBoxVHWAColorKey * pCKey2)
541 {
542 return (pCKey1 == NULL && pCKey2 == NULL)
543 || (*pCKey1 == *pCKey2);
544 }
545
546 void runDisplay(VBoxVHWATextureImage *pDst, const QRect * pDstRect, const QRect * pSrcRect)
547 {
548 bind(pDst);
549
550 draw(pDst, pDstRect, pSrcRect);
551 }
552
553 virtual void draw(VBoxVHWATextureImage *pDst, const QRect * pDstRect, const QRect * pSrcRect);
554
555 virtual uint32_t texCoord(GLenum tex, int x, int y)
556 {
557 uint32_t c = 1;
558 mpTex[0]->multiTexCoord(tex, x, y);
559 if(mColorFormat.fourcc() == FOURCC_YV12)
560 {
561 int x2 = x/2;
562 int y2 = y/2;
563 mpTex[1]->multiTexCoord(tex + 1, x2, y2);
564 ++c;
565 }
566 return c;
567 }
568
569 virtual void bind(VBoxVHWATextureImage * pPrimary);
570
571 virtual uint32_t calcProgramType(VBoxVHWATextureImage *pDst, const VBoxVHWAColorKey * pDstCKey, const VBoxVHWAColorKey * pSrcCKey, bool bNotIntersected);
572
573 virtual class VBoxVHWAGlProgramVHWA * calcProgram(VBoxVHWATextureImage *pDst, const VBoxVHWAColorKey * pDstCKey, const VBoxVHWAColorKey * pSrcCKey, bool bNotIntersected);
574
575 virtual int createDisplay(VBoxVHWATextureImage *pDst, const QRect * pDstRect, const QRect * pSrcRect,
576 const VBoxVHWAColorKey * pDstCKey, const VBoxVHWAColorKey * pSrcCKey, bool bNotIntersected,
577 GLuint *pDisplay, class VBoxVHWAGlProgramVHWA ** ppProgram);
578
579 int createSetDisplay(VBoxVHWATextureImage *pDst, const QRect * pDstRect, const QRect * pSrcRect,
580 const VBoxVHWAColorKey * pDstCKey, const VBoxVHWAColorKey * pSrcCKey, bool bNotIntersected);
581
582 virtual int createDisplayList(VBoxVHWATextureImage *pDst, const QRect * pDstRect, const QRect * pSrcRect,
583 const VBoxVHWAColorKey * pDstCKey, const VBoxVHWAColorKey * pSrcCKey, bool bNotIntersected,
584 GLuint *pDisplay);
585
586 virtual void deleteDisplayList();
587
588 virtual void updateCKeys(VBoxVHWATextureImage * pDst, class VBoxVHWAGlProgramVHWA * pProgram, const VBoxVHWAColorKey * pDstCKey, const VBoxVHWAColorKey * pSrcCKey);
589 virtual void updateSetCKeys(const VBoxVHWAColorKey * pDstCKey, const VBoxVHWAColorKey * pSrcCKey);
590
591 void internalSetDstCKey(const VBoxVHWAColorKey * pDstCKey);
592 void internalSetSrcCKey(const VBoxVHWAColorKey * pSrcCKey);
593
594 VBoxVHWATexture *mpTex[3];
595 uint32_t mcTex;
596 GLuint mVisibleDisplay;
597 class VBoxVHWAGlProgramVHWA * mpProgram;
598 class VBoxVHWAGlProgramMngr * mProgramMngr;
599 VBoxVHWAColorFormat mColorFormat;
600
601 /* display info */
602 VBoxVHWATextureImage *mpDst;
603 QRect mDstRect;
604 QRect mSrcRect;
605 VBoxVHWAColorKey * mpDstCKey;
606 VBoxVHWAColorKey * mpSrcCKey;
607 VBoxVHWAColorKey mDstCKey;
608 VBoxVHWAColorKey mSrcCKey;
609 bool mbNotIntersected;
610};
611
612class VBoxVHWATextureImagePBO : public VBoxVHWATextureImage
613{
614public:
615 VBoxVHWATextureImagePBO(const QRect &size, const VBoxVHWAColorFormat &format, class VBoxVHWAGlProgramMngr * aMgr, VBOXVHWAIMG_TYPE flags) :
616 VBoxVHWATextureImage(size, format, aMgr, flags & (~VBOXVHWAIMG_PBO)),
617 mPBO(0)
618 {
619 }
620
621 virtual ~VBoxVHWATextureImagePBO()
622 {
623 if(mPBO)
624 {
625 VBOXQGL_CHECKERR(
626 vboxglDeleteBuffers(1, &mPBO);
627 );
628 }
629 }
630
631 virtual void init(uchar *pvMem)
632 {
633 VBoxVHWATextureImage::init(pvMem);
634
635 VBOXQGL_CHECKERR(
636 vboxglGenBuffers(1, &mPBO);
637 );
638 mAddress = pvMem;
639
640 VBOXQGL_CHECKERR(
641 vboxglBindBuffer(GL_PIXEL_UNPACK_BUFFER, mPBO);
642 );
643
644 VBOXQGL_CHECKERR(
645 vboxglBufferData(GL_PIXEL_UNPACK_BUFFER, memSize(), NULL, GL_STREAM_DRAW);
646 );
647
648 GLvoid *buf = vboxglMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
649 Assert(buf);
650 if(buf)
651 {
652 memcpy(buf, mAddress, memSize());
653
654 bool unmapped = vboxglUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
655 Assert(unmapped); NOREF(unmapped);
656 }
657
658 vboxglBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
659
660 }
661
662 virtual void update(const QRect * pRect)
663 {
664 VBOXQGL_CHECKERR(
665 vboxglBindBuffer(GL_PIXEL_UNPACK_BUFFER, mPBO);
666 );
667
668 GLvoid *buf;
669
670 VBOXQGL_CHECKERR(
671 buf = vboxglMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
672 );
673 Assert(buf);
674 if(buf)
675 {
676#ifdef VBOXVHWADBG_RENDERCHECK
677 uint32_t * pBuf32 = (uint32_t*)buf;
678 uchar * pBuf8 = (uchar*)buf;
679 for(uint32_t i = 0; i < mcTex; i++)
680 {
681 uint32_t dbgSetVal = 0x40404040 * (i+1);
682 for(uint32_t k = 0; k < mpTex[i]->memSize()/sizeof(pBuf32[0]); k++)
683 {
684 pBuf32[k] = dbgSetVal;
685 }
686
687 pBuf8 += mpTex[i]->memSize();
688 pBuf32 = (uint32_t *)pBuf8;
689 }
690#else
691 memcpy(buf, mAddress, memSize());
692#endif
693
694 bool unmapped;
695 VBOXQGL_CHECKERR(
696 unmapped = vboxglUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
697 );
698
699 Assert(unmapped); NOREF(unmapped);
700
701 VBoxVHWATextureImage::setAddress(0);
702
703 VBoxVHWATextureImage::update(NULL);
704
705 VBoxVHWATextureImage::setAddress(mAddress);
706
707 vboxglBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
708 }
709 else
710 {
711 VBOXQGLLOGREL(("failed to map PBO, trying fallback to non-PBO approach\n"));
712
713 VBoxVHWATextureImage::setAddress(mAddress);
714
715 VBoxVHWATextureImage::update(pRect);
716 }
717 }
718
719 virtual void setAddress(uchar *pvMem)
720 {
721 mAddress = pvMem;
722 }
723private:
724 GLuint mPBO;
725 uchar* mAddress;
726};
727
728class VBoxVHWAHandleTable
729{
730public:
731 VBoxVHWAHandleTable(uint32_t initialSize);
732 ~VBoxVHWAHandleTable();
733 uint32_t put(void * data);
734 bool mapPut(uint32_t h, void * data);
735 void* get(uint32_t h);
736 void* remove(uint32_t h);
737private:
738 void doPut(uint32_t h, void * data);
739 void doRemove(uint32_t h);
740 void** mTable;
741 uint32_t mcSize;
742 uint32_t mcUsage;
743 uint32_t mCursor;
744};
745
746/* data flow:
747 * I. NON-Yinverted surface:
748 * 1.direct memory update (paint, lock/unlock):
749 * mem->tex->fb
750 * 2.blt
751 * srcTex->invFB->tex->fb
752 * |->mem
753 *
754 * II. Yinverted surface:
755 * 1.direct memory update (paint, lock/unlock):
756 * mem->tex->fb
757 * 2.blt
758 * srcTex->fb->tex
759 * |->mem
760 *
761 * III. flip support:
762 * 1. Yinverted<->NON-YInverted conversion :
763 * mem->tex-(rotate model view, force LAZY complete fb update)->invFB->tex
764 * fb-->| |->mem
765 * */
766class VBoxVHWASurfaceBase
767{
768public:
769 VBoxVHWASurfaceBase (class VBoxVHWAImage *pImage,
770 const QSize & aSize,
771 const QRect & aTargRect,
772 const QRect & aSrcRect,
773 const QRect & aVisTargRect,
774 VBoxVHWAColorFormat & aColorFormat,
775 VBoxVHWAColorKey * pSrcBltCKey, VBoxVHWAColorKey * pDstBltCKey,
776 VBoxVHWAColorKey * pSrcOverlayCKey, VBoxVHWAColorKey * pDstOverlayCKey,
777 VBOXVHWAIMG_TYPE aImgFlags);
778
779 virtual ~VBoxVHWASurfaceBase();
780
781 void init (VBoxVHWASurfaceBase * pPrimary, uchar *pvMem);
782
783 void uninit();
784
785 static void globalInit();
786
787 int lock (const QRect * pRect, uint32_t flags);
788
789 int unlock();
790
791 void updatedMem (const QRect * aRect);
792
793 bool performDisplay (VBoxVHWASurfaceBase *pPrimary, bool bForce);
794
795 void setRects (const QRect & aTargRect, const QRect & aSrcRect);
796 void setTargRectPosition (const QPoint & aPoint);
797
798 void updateVisibility (VBoxVHWASurfaceBase *pPrimary, const QRect & aVisibleTargRect, bool bNotIntersected, bool bForce);
799
800 static ulong calcBytesPerPixel (GLenum format, GLenum type);
801
802 static GLsizei makePowerOf2 (GLsizei val);
803
804 bool addressAlocated() const { return mFreeAddress; }
805 uchar * address() { return mAddress; }
806
807 ulong memSize();
808
809 ulong width() const { return mRect.width(); }
810 ulong height() const { return mRect.height(); }
811 const QSize size() const {return mRect.size();}
812
813 uint32_t fourcc() const {return mImage->pixelFormat().fourcc(); }
814
815 ulong bitsPerPixel() const { return mImage->pixelFormat().bitsPerPixel(); }
816 ulong bytesPerLine() const { return mImage->bytesPerLine(); }
817
818 const VBoxVHWAColorKey * dstBltCKey() const { return mpDstBltCKey; }
819 const VBoxVHWAColorKey * srcBltCKey() const { return mpSrcBltCKey; }
820 const VBoxVHWAColorKey * dstOverlayCKey() const { return mpDstOverlayCKey; }
821 const VBoxVHWAColorKey * defaultSrcOverlayCKey() const { return mpDefaultSrcOverlayCKey; }
822 const VBoxVHWAColorKey * defaultDstOverlayCKey() const { return mpDefaultDstOverlayCKey; }
823 const VBoxVHWAColorKey * srcOverlayCKey() const { return mpSrcOverlayCKey; }
824 void resetDefaultSrcOverlayCKey() { mpSrcOverlayCKey = mpDefaultSrcOverlayCKey; }
825 void resetDefaultDstOverlayCKey() { mpDstOverlayCKey = mpDefaultDstOverlayCKey; }
826
827 void setDstBltCKey (const VBoxVHWAColorKey * ckey)
828 {
829 if(ckey)
830 {
831 mDstBltCKey = *ckey;
832 mpDstBltCKey = &mDstBltCKey;
833 }
834 else
835 {
836 mpDstBltCKey = NULL;
837 }
838 }
839
840 void setSrcBltCKey (const VBoxVHWAColorKey * ckey)
841 {
842 if(ckey)
843 {
844 mSrcBltCKey = *ckey;
845 mpSrcBltCKey = &mSrcBltCKey;
846 }
847 else
848 {
849 mpSrcBltCKey = NULL;
850 }
851 }
852
853 void setDefaultDstOverlayCKey (const VBoxVHWAColorKey * ckey)
854 {
855 if(ckey)
856 {
857 mDefaultDstOverlayCKey = *ckey;
858 mpDefaultDstOverlayCKey = &mDefaultDstOverlayCKey;
859 }
860 else
861 {
862 mpDefaultDstOverlayCKey = NULL;
863 }
864 }
865
866 void setDefaultSrcOverlayCKey (const VBoxVHWAColorKey * ckey)
867 {
868 if(ckey)
869 {
870 mDefaultSrcOverlayCKey = *ckey;
871 mpDefaultSrcOverlayCKey = &mDefaultSrcOverlayCKey;
872 }
873 else
874 {
875 mpDefaultSrcOverlayCKey = NULL;
876 }
877 }
878
879 void setOverriddenDstOverlayCKey (const VBoxVHWAColorKey * ckey)
880 {
881 if(ckey)
882 {
883 mOverriddenDstOverlayCKey = *ckey;
884 mpDstOverlayCKey = &mOverriddenDstOverlayCKey;
885 }
886 else
887 {
888 mpDstOverlayCKey = NULL;
889 }
890 }
891
892 void setOverriddenSrcOverlayCKey (const VBoxVHWAColorKey * ckey)
893 {
894 if(ckey)
895 {
896 mOverriddenSrcOverlayCKey = *ckey;
897 mpSrcOverlayCKey = &mOverriddenSrcOverlayCKey;
898 }
899 else
900 {
901 mpSrcOverlayCKey = NULL;
902 }
903 }
904
905 const VBoxVHWAColorKey * getActiveSrcOverlayCKey()
906 {
907 return mpSrcOverlayCKey;
908 }
909
910 const VBoxVHWAColorKey * getActiveDstOverlayCKey (VBoxVHWASurfaceBase * pPrimary)
911 {
912 return mpDstOverlayCKey ? mpDefaultDstOverlayCKey : (pPrimary ? pPrimary->mpDstOverlayCKey : NULL);
913 }
914
915 const VBoxVHWAColorFormat & pixelFormat() const { return mImage->pixelFormat(); }
916
917 void setAddress(uchar * addr);
918
919 const QRect& rect() const {return mRect;}
920 const QRect& srcRect() const {return mSrcRect; }
921 const QRect& targRect() const {return mTargRect; }
922 class VBoxVHWASurfList * getComplexList() {return mComplexList; }
923
924 class VBoxVHWAGlProgramMngr * getGlProgramMngr();
925
926 uint32_t handle() const {return mHGHandle;}
927 void setHandle(uint32_t h) {mHGHandle = h;}
928
929 const VBoxVHWADirtyRect & getDirtyRect() { return mUpdateMem2TexRect; }
930
931 VBoxVHWASurfaceBase * primary() { return mpPrimary; }
932 void setPrimary(VBoxVHWASurfaceBase *apPrimary) { mpPrimary = apPrimary; }
933private:
934 void setRectValues (const QRect & aTargRect, const QRect & aSrcRect);
935 void setVisibleRectValues (const QRect & aVisTargRect);
936
937 void setComplexList (VBoxVHWASurfList *aComplexList) { mComplexList = aComplexList; }
938 void initDisplay();
939
940 bool synchTexMem (const QRect * aRect);
941
942 int performBlt (const QRect * pDstRect, VBoxVHWASurfaceBase * pSrcSurface, const QRect * pSrcRect, const VBoxVHWAColorKey * pDstCKey, const VBoxVHWAColorKey * pSrcCKey, bool blt);
943
944 QRect mRect; /* == Inv FB size */
945
946 QRect mSrcRect;
947 QRect mTargRect; /* == Vis FB size */
948
949 QRect mVisibleTargRect;
950 QRect mVisibleSrcRect;
951
952 class VBoxVHWATextureImage * mImage;
953
954 uchar * mAddress;
955
956 VBoxVHWAColorKey *mpSrcBltCKey;
957 VBoxVHWAColorKey *mpDstBltCKey;
958 VBoxVHWAColorKey *mpSrcOverlayCKey;
959 VBoxVHWAColorKey *mpDstOverlayCKey;
960
961 VBoxVHWAColorKey *mpDefaultDstOverlayCKey;
962 VBoxVHWAColorKey *mpDefaultSrcOverlayCKey;
963
964 VBoxVHWAColorKey mSrcBltCKey;
965 VBoxVHWAColorKey mDstBltCKey;
966 VBoxVHWAColorKey mOverriddenSrcOverlayCKey;
967 VBoxVHWAColorKey mOverriddenDstOverlayCKey;
968 VBoxVHWAColorKey mDefaultDstOverlayCKey;
969 VBoxVHWAColorKey mDefaultSrcOverlayCKey;
970
971 int mLockCount;
972 /* memory buffer not reflected in fm and texture, e.g if memory buffer is replaced or in case of lock/unlock */
973 VBoxVHWADirtyRect mUpdateMem2TexRect;
974
975 bool mFreeAddress;
976 bool mbNotIntersected;
977
978 class VBoxVHWASurfList *mComplexList;
979
980 VBoxVHWASurfaceBase *mpPrimary;
981
982 uint32_t mHGHandle;
983
984 class VBoxVHWAImage *mpImage;
985
986#ifdef DEBUG
987public:
988 uint64_t cFlipsCurr;
989 uint64_t cFlipsTarg;
990#endif
991 friend class VBoxVHWASurfList;
992};
993
994typedef std::list <VBoxVHWASurfaceBase*> SurfList;
995typedef std::list <VBoxVHWASurfList*> OverlayList;
996typedef std::list <struct VBOXVHWACMD *> VHWACommandList;
997
998class VBoxVHWASurfList
999{
1000public:
1001
1002 VBoxVHWASurfList() : mCurrent(NULL) {}
1003 void add(VBoxVHWASurfaceBase *pSurf)
1004 {
1005 VBoxVHWASurfList * pOld = pSurf->getComplexList();
1006 if(pOld)
1007 {
1008 pOld->remove(pSurf);
1009 }
1010 mSurfaces.push_back(pSurf);
1011 pSurf->setComplexList(this);
1012 }
1013
1014 void clear()
1015 {
1016 for (SurfList::iterator it = mSurfaces.begin();
1017 it != mSurfaces.end(); ++ it)
1018 {
1019 (*it)->setComplexList(NULL);
1020 }
1021 mSurfaces.clear();
1022 mCurrent = NULL;
1023 }
1024
1025 size_t size() const {return mSurfaces.size(); }
1026
1027 void remove(VBoxVHWASurfaceBase *pSurf)
1028 {
1029 mSurfaces.remove(pSurf);
1030 pSurf->setComplexList(NULL);
1031 if(mCurrent == pSurf)
1032 mCurrent = NULL;
1033 }
1034
1035 bool empty() { return mSurfaces.empty(); }
1036
1037 void setCurrentVisible(VBoxVHWASurfaceBase *pSurf)
1038 {
1039 mCurrent = pSurf;
1040 }
1041
1042 VBoxVHWASurfaceBase * current() { return mCurrent; }
1043 const SurfList & surfaces() const {return mSurfaces;}
1044
1045private:
1046
1047 SurfList mSurfaces;
1048 VBoxVHWASurfaceBase* mCurrent;
1049};
1050
1051class VBoxVHWADisplay
1052{
1053public:
1054 VBoxVHWADisplay() :
1055 mSurfVGA(NULL),
1056 mbDisplayPrimary(true)
1057// ,
1058// mSurfPrimary(NULL)
1059 {}
1060
1061 VBoxVHWASurfaceBase * setVGA(VBoxVHWASurfaceBase * pVga)
1062 {
1063 VBoxVHWASurfaceBase * old = mSurfVGA;
1064 mSurfVGA = pVga;
1065 mPrimary.clear();
1066 if(pVga)
1067 {
1068 Assert(!pVga->getComplexList());
1069 mPrimary.add(pVga);
1070 mPrimary.setCurrentVisible(pVga);
1071 }
1072 mOverlays.clear();
1073 return old;
1074 }
1075
1076 VBoxVHWASurfaceBase * updateVGA(VBoxVHWASurfaceBase * pVga)
1077 {
1078 VBoxVHWASurfaceBase * old = mSurfVGA;
1079 Assert(old);
1080 mSurfVGA = pVga;
1081 return old;
1082 }
1083
1084 VBoxVHWASurfaceBase * getVGA() const
1085 {
1086 return mSurfVGA;
1087 }
1088
1089 VBoxVHWASurfaceBase * getPrimary()
1090 {
1091 return mPrimary.current();
1092 }
1093
1094 void addOverlay(VBoxVHWASurfList * pSurf)
1095 {
1096 mOverlays.push_back(pSurf);
1097 }
1098
1099 void checkAddOverlay(VBoxVHWASurfList * pSurf)
1100 {
1101 if(!hasOverlay(pSurf))
1102 addOverlay(pSurf);
1103 }
1104
1105 bool hasOverlay(VBoxVHWASurfList * pSurf)
1106 {
1107 for (OverlayList::iterator it = mOverlays.begin();
1108 it != mOverlays.end(); ++ it)
1109 {
1110 if((*it) == pSurf)
1111 {
1112 return true;
1113 }
1114 }
1115 return false;
1116 }
1117
1118 void removeOverlay(VBoxVHWASurfList * pSurf)
1119 {
1120 mOverlays.remove(pSurf);
1121 }
1122
1123 bool performDisplay(bool bForce)
1124 {
1125 VBoxVHWASurfaceBase * pPrimary = mPrimary.current();
1126
1127 if(mbDisplayPrimary)
1128 {
1129#ifdef DEBUG_misha
1130 /* should only display overlay now */
1131 AssertBreakpoint();
1132#endif
1133 bForce |= pPrimary->performDisplay(NULL, bForce);
1134 }
1135
1136 for (OverlayList::const_iterator it = mOverlays.begin();
1137 it != mOverlays.end(); ++ it)
1138 {
1139 VBoxVHWASurfaceBase * pOverlay = (*it)->current();
1140 if(pOverlay)
1141 {
1142 bForce |= pOverlay->performDisplay(pPrimary, bForce);
1143 }
1144 }
1145 return bForce;
1146 }
1147
1148 bool isPrimary(VBoxVHWASurfaceBase * pSurf) { return pSurf->getComplexList() == &mPrimary; }
1149
1150 void setDisplayPrimary(bool bDisplay) { mbDisplayPrimary = bDisplay; }
1151
1152 const OverlayList & overlays() const {return mOverlays;}
1153 const VBoxVHWASurfList & primaries() const { return mPrimary; }
1154
1155private:
1156 VBoxVHWASurfaceBase *mSurfVGA;
1157 VBoxVHWASurfList mPrimary;
1158
1159 OverlayList mOverlays;
1160
1161 bool mbDisplayPrimary;
1162};
1163
1164typedef void (*PFNVBOXQGLFUNC)(void*, void*);
1165
1166typedef enum
1167{
1168 VBOXVHWA_PIPECMD_PAINT = 1,
1169 VBOXVHWA_PIPECMD_VHWA,
1170 VBOXVHWA_PIPECMD_FUNC
1171}VBOXVHWA_PIPECMD_TYPE;
1172
1173typedef struct VBOXVHWAFUNCCALLBACKINFO
1174{
1175 PFNVBOXQGLFUNC pfnCallback;
1176 void * pContext1;
1177 void * pContext2;
1178}VBOXVHWAFUNCCALLBACKINFO;
1179
1180class VBoxVHWACommandElement
1181{
1182public:
1183 VBoxVHWACommandElement() :
1184 bNewEvent(false)
1185 {}
1186
1187 void setVHWACmd(struct VBOXVHWACMD * pCmd)
1188 {
1189 mType = VBOXVHWA_PIPECMD_VHWA;
1190 u.mpCmd = pCmd;
1191 }
1192
1193 void setPaintCmd(const QRect & aRect)
1194 {
1195 mType = VBOXVHWA_PIPECMD_PAINT;
1196 mRect = aRect;
1197 }
1198
1199 void setFunc(const VBOXVHWAFUNCCALLBACKINFO & aOp)
1200 {
1201 mType = VBOXVHWA_PIPECMD_FUNC;
1202 u.mFuncCallback = aOp;
1203 }
1204
1205 void setData(VBOXVHWA_PIPECMD_TYPE aType, void * pvData)
1206 {
1207 switch(aType)
1208 {
1209 case VBOXVHWA_PIPECMD_PAINT:
1210 setPaintCmd(*((QRect*)pvData));
1211 break;
1212 case VBOXVHWA_PIPECMD_VHWA:
1213 setVHWACmd((struct VBOXVHWACMD *)pvData);
1214 break;
1215 case VBOXVHWA_PIPECMD_FUNC:
1216 setFunc(*((VBOXVHWAFUNCCALLBACKINFO *)pvData));
1217 break;
1218 default:
1219 Assert(0);
1220 break;
1221 }
1222 }
1223
1224 void setNewEvent(bool bNew) {bNewEvent = bNew;}
1225 bool isNewEvent() const { return bNewEvent; }
1226
1227 VBOXVHWA_PIPECMD_TYPE type() const {return mType;}
1228 const QRect & rect() const {return mRect;}
1229 struct VBOXVHWACMD * vhwaCmd() const {return u.mpCmd;}
1230 const VBOXVHWAFUNCCALLBACKINFO & func() const {return u.mFuncCallback; }
1231
1232 VBoxVHWACommandElement * mpNext;
1233private:
1234 VBOXVHWA_PIPECMD_TYPE mType;
1235 union
1236 {
1237 struct VBOXVHWACMD * mpCmd;
1238 VBOXVHWAFUNCCALLBACKINFO mFuncCallback;
1239 }u;
1240 QRect mRect;
1241 bool bNewEvent;
1242};
1243
1244class VBoxVHWACommandElementPipe
1245{
1246public:
1247 VBoxVHWACommandElementPipe() :
1248 mpFirst(NULL),
1249 mpLast(NULL)
1250 {}
1251
1252 void put(VBoxVHWACommandElement *pCmd)
1253 {
1254 if (mpLast)
1255 {
1256 Assert(mpFirst);
1257 mpLast->mpNext = pCmd;
1258 mpLast = pCmd;
1259 }
1260 else
1261 {
1262 Assert(!mpFirst);
1263 mpFirst = pCmd;
1264 mpLast = pCmd;
1265 }
1266 pCmd->mpNext= NULL;
1267
1268 }
1269
1270 void setFrom(VBoxVHWACommandElementPipe *pOther)
1271 {
1272 mpFirst = pOther->detachList(&mpLast);
1273 }
1274
1275 void set(VBoxVHWACommandElement *pFirst, VBoxVHWACommandElement *pLast)
1276 {
1277 mpFirst = pFirst;
1278 mpLast = pLast;
1279 if (mpLast)
1280 mpLast->mpNext = NULL;
1281 }
1282
1283 void prepend(VBoxVHWACommandElement *pFirst, VBoxVHWACommandElement *pLast)
1284 {
1285 if (!mpFirst)
1286 set(pFirst, pLast);
1287 else if (pLast)
1288 {
1289 pLast->mpNext = mpFirst;
1290 mpFirst = pFirst;
1291 }
1292 }
1293
1294 void prependFrom(VBoxVHWACommandElementPipe *pOther)
1295 {
1296 VBoxVHWACommandElement *pFirst;
1297 VBoxVHWACommandElement *pLast;
1298 pFirst = pOther->detachList(&pLast);
1299 prepend(pFirst, pLast);
1300 }
1301
1302 void append(VBoxVHWACommandElement *pFirst, VBoxVHWACommandElement *pLast)
1303 {
1304 if (!mpLast)
1305 set(pFirst, pLast);
1306 else if (pLast)
1307 {
1308 mpLast->mpNext = pFirst;
1309 mpLast = pLast;
1310 pLast->mpNext = NULL;
1311 }
1312 }
1313
1314 VBoxVHWACommandElement * detachList(VBoxVHWACommandElement **ppLast)
1315 {
1316 if (mpLast)
1317 {
1318 VBoxVHWACommandElement * pHead = mpFirst;
1319 if (ppLast)
1320 *ppLast = mpLast;
1321 mpFirst = NULL;
1322 mpLast = NULL;
1323 return pHead;
1324 }
1325 if (ppLast)
1326 *ppLast = NULL;
1327 return NULL;
1328 }
1329
1330
1331
1332 const VBoxVHWACommandElement * contentsRo (const VBoxVHWACommandElement **ppLast) const
1333 {
1334 if (ppLast)
1335 *ppLast = mpLast;
1336 return mpFirst;
1337 }
1338
1339 bool isEmpty() const { return !mpLast; }
1340
1341private:
1342 VBoxVHWACommandElement *mpFirst;
1343 VBoxVHWACommandElement *mpLast;
1344};
1345
1346class VBoxVHWACommandElementStack
1347{
1348public:
1349 VBoxVHWACommandElementStack() :
1350 mpFirst(NULL) {}
1351
1352 void push(VBoxVHWACommandElement *pCmd)
1353 {
1354 pCmd->mpNext = mpFirst;
1355 mpFirst = pCmd;
1356 }
1357
1358 void pusha(VBoxVHWACommandElement *pFirst, VBoxVHWACommandElement *pLast)
1359 {
1360 pLast->mpNext = mpFirst;
1361 mpFirst = pFirst;
1362 }
1363
1364 VBoxVHWACommandElement * pop()
1365 {
1366 if(mpFirst)
1367 {
1368 VBoxVHWACommandElement * ret = mpFirst;
1369 mpFirst = ret->mpNext;
1370 return ret;
1371 }
1372 return NULL;
1373 }
1374private:
1375 VBoxVHWACommandElement *mpFirst;
1376};
1377
1378class VBoxVHWARefCounter
1379{
1380#define VBOXVHWA_INIFITE_WAITCOUNT (~0U)
1381public:
1382 VBoxVHWARefCounter() : m_cRefs(0) {}
1383 VBoxVHWARefCounter(uint32_t cRefs) : m_cRefs(cRefs) {}
1384 void inc() { ASMAtomicIncU32(&m_cRefs); }
1385 uint32_t dec()
1386 {
1387 uint32_t cRefs = ASMAtomicDecU32(&m_cRefs);
1388 Assert(cRefs < UINT32_MAX / 2);
1389 return cRefs;
1390 }
1391
1392 uint32_t refs() { return ASMAtomicReadU32(&m_cRefs); }
1393
1394 int wait0(RTMSINTERVAL ms = 1000, uint32_t cWaits = VBOXVHWA_INIFITE_WAITCOUNT)
1395 {
1396 int rc = VINF_SUCCESS;
1397 do
1398 {
1399 if (!refs())
1400 break;
1401 if (!cWaits)
1402 {
1403 rc = VERR_TIMEOUT;
1404 break;
1405 }
1406 if (cWaits != VBOXVHWA_INIFITE_WAITCOUNT)
1407 --cWaits;
1408 rc = RTThreadSleep(ms);
1409 AssertRC(rc);
1410 if (!RT_SUCCESS(rc))
1411 break;
1412 } while(1);
1413 return rc;
1414 }
1415private:
1416 volatile uint32_t m_cRefs;
1417};
1418
1419#define VBOXVHWACMDPIPEC_NEWEVENT 0x00000001
1420#define VBOXVHWACMDPIPEC_COMPLETEEVENT 0x00000002
1421class VBoxVHWACommandElementProcessor
1422{
1423public:
1424 VBoxVHWACommandElementProcessor(QObject *pNotifyObject);
1425 ~VBoxVHWACommandElementProcessor();
1426 void postCmd(VBOXVHWA_PIPECMD_TYPE aType, void * pvData, uint32_t flags);
1427 bool completeCurrentEvent();
1428 class VBoxVHWACommandElement * detachCmdList(class VBoxVHWACommandElement ** ppLast,
1429 class VBoxVHWACommandElement * pFirst2Free, VBoxVHWACommandElement * pLast2Free);
1430 void putBack(class VBoxVHWACommandElement * pFirst2Put, VBoxVHWACommandElement * pLast2Put,
1431 class VBoxVHWACommandElement * pFirst2Free, VBoxVHWACommandElement * pLast2Free);
1432 void reset(class VBoxVHWACommandElement ** ppHead, class VBoxVHWACommandElement ** ppTail);
1433 void setNotifyObject(QObject *pNotifyObject);
1434 int loadExec (struct SSMHANDLE * pSSM, uint32_t u32Version, void *pvVRAM);
1435 void saveExec (struct SSMHANDLE * pSSM, void *pvVRAM);
1436 void disable();
1437 void enable();
1438 void lock();
1439 void unlock();
1440#ifdef DEBUG_misha
1441 void checkConsistence(uint32_t cEvents2Submit = 0, const VBoxVHWACommandElementPipe *pPipe = NULL);
1442#endif
1443private:
1444 RTCRITSECT mCritSect;
1445 VBoxVHWACommandElementPipe m_CmdPipe;
1446 QObject *m_pNotifyObject;
1447 VBoxVHWARefCounter m_NotifyObjectRefs;
1448 bool mbNewEvent;
1449 bool mbProcessingList;
1450 uint32_t mcDisabled;
1451 VBoxVHWACommandElementStack mFreeElements;
1452 VBoxVHWACommandElement mElementsBuffer[2048];
1453};
1454
1455/* added to workaround this ** [VBox|UI] duplication */
1456class VBoxFBSizeInfo
1457{
1458public:
1459 VBoxFBSizeInfo() {}
1460 template<class T> VBoxFBSizeInfo(T * fb) :
1461 mPixelFormat(fb->pixelFormat()), mVRAM(fb->address()), mBitsPerPixel(fb->bitsPerPixel()),
1462 mBytesPerLine(fb->bytesPerLine()), mWidth(fb->width()), mHeight(fb->height()),
1463 mUsesGuestVram(fb->usesGuestVRAM()) {}
1464
1465 VBoxFBSizeInfo(ulong aPixelFormat, uchar *aVRAM,
1466 ulong aBitsPerPixel, ulong aBytesPerLine,
1467 ulong aWidth, ulong aHeight,
1468 bool bUsesGuestVram) :
1469 mPixelFormat (aPixelFormat), mVRAM (aVRAM), mBitsPerPixel (aBitsPerPixel),
1470 mBytesPerLine (aBytesPerLine), mWidth (aWidth), mHeight (aHeight),
1471 mUsesGuestVram(bUsesGuestVram) {}
1472 ulong pixelFormat() const { return mPixelFormat; }
1473 uchar *VRAM() const { return mVRAM; }
1474 ulong bitsPerPixel() const { return mBitsPerPixel; }
1475 ulong bytesPerLine() const { return mBytesPerLine; }
1476 ulong width() const { return mWidth; }
1477 ulong height() const { return mHeight; }
1478 bool usesGuestVram() const {return mUsesGuestVram;}
1479
1480private:
1481 ulong mPixelFormat;
1482 uchar *mVRAM;
1483 ulong mBitsPerPixel;
1484 ulong mBytesPerLine;
1485 ulong mWidth;
1486 ulong mHeight;
1487 bool mUsesGuestVram;
1488};
1489
1490class VBoxVHWAImage
1491{
1492public:
1493 VBoxVHWAImage ();
1494 ~VBoxVHWAImage();
1495
1496 int init(VBoxVHWASettings *aSettings);
1497#ifdef VBOX_WITH_VIDEOHWACCEL
1498 uchar *vboxVRAMAddressFromOffset(uint64_t offset);
1499 uint64_t vboxVRAMOffsetFromAddress(uchar* addr);
1500 uint64_t vboxVRAMOffset(VBoxVHWASurfaceBase * pSurf);
1501
1502 void vhwaSaveExec(struct SSMHANDLE * pSSM);
1503 static void vhwaSaveExecVoid(struct SSMHANDLE * pSSM);
1504 static int vhwaLoadExec(VHWACommandList * pCmdList, struct SSMHANDLE * pSSM, uint32_t u32Version);
1505
1506 int vhwaSurfaceCanCreate(struct VBOXVHWACMD_SURF_CANCREATE *pCmd);
1507 int vhwaSurfaceCreate(struct VBOXVHWACMD_SURF_CREATE *pCmd);
1508#ifdef VBOX_WITH_WDDM
1509 int vhwaSurfaceGetInfo(struct VBOXVHWACMD_SURF_GETINFO *pCmd);
1510#endif
1511 int vhwaSurfaceDestroy(struct VBOXVHWACMD_SURF_DESTROY *pCmd);
1512 int vhwaSurfaceLock(struct VBOXVHWACMD_SURF_LOCK *pCmd);
1513 int vhwaSurfaceUnlock(struct VBOXVHWACMD_SURF_UNLOCK *pCmd);
1514 int vhwaSurfaceBlt(struct VBOXVHWACMD_SURF_BLT *pCmd);
1515 int vhwaSurfaceFlip(struct VBOXVHWACMD_SURF_FLIP *pCmd);
1516 int vhwaSurfaceColorFill(struct VBOXVHWACMD_SURF_COLORFILL *pCmd);
1517 int vhwaSurfaceOverlayUpdate(struct VBOXVHWACMD_SURF_OVERLAY_UPDATE *pCmf);
1518 int vhwaSurfaceOverlaySetPosition(struct VBOXVHWACMD_SURF_OVERLAY_SETPOSITION *pCmd);
1519 int vhwaSurfaceColorkeySet(struct VBOXVHWACMD_SURF_COLORKEY_SET *pCmd);
1520 int vhwaQueryInfo1(struct VBOXVHWACMD_QUERYINFO1 *pCmd);
1521 int vhwaQueryInfo2(struct VBOXVHWACMD_QUERYINFO2 *pCmd);
1522 int vhwaConstruct(struct VBOXVHWACMD_HH_CONSTRUCT *pCmd);
1523
1524 void *vramBase() { return mpvVRAM; }
1525 uint32_t vramSize() { return mcbVRAM; }
1526
1527 bool hasSurfaces() const;
1528 bool hasVisibleOverlays();
1529 QRect overlaysRectUnion();
1530 QRect overlaysRectIntersection();
1531#endif
1532
1533 static const QGLFormat & vboxGLFormat();
1534
1535 int reset(VHWACommandList * pCmdList);
1536
1537 int vboxFbWidth() {return mDisplay.getVGA()->width(); }
1538 int vboxFbHeight() {return mDisplay.getVGA()->height(); }
1539 bool isInitialized() {return mDisplay.getVGA() != NULL; }
1540
1541 void resize(const VBoxFBSizeInfo & size);
1542
1543 class VBoxVHWAGlProgramMngr * vboxVHWAGetGlProgramMngr() { return mpMngr; }
1544
1545 VBoxVHWASurfaceBase * vgaSurface() { return mDisplay.getVGA(); }
1546
1547#ifdef VBOXVHWA_OLD_COORD
1548 static void doSetupMatrix(const QSize & aSize, bool bInverted);
1549#endif
1550
1551 void vboxDoUpdateViewport(const QRect & aRect);
1552 void vboxDoUpdateRect(const QRect * pRect);
1553
1554 const QRect & vboxViewport() const {return mViewport;}
1555
1556#ifdef VBOXVHWA_PROFILE_FPS
1557 void reportNewFrame() { mbNewFrame = true; }
1558#endif
1559
1560 bool performDisplay(bool bForce)
1561 {
1562 bForce = mDisplay.performDisplay(bForce | mRepaintNeeded);
1563
1564#ifdef VBOXVHWA_PROFILE_FPS
1565 if(mbNewFrame)
1566 {
1567 mFPSCounter.frame();
1568 double fps = mFPSCounter.fps();
1569 if(!(mFPSCounter.frames() % 31))
1570 {
1571 RTPrintf("fps: %f\n", fps);
1572 }
1573 mbNewFrame = false;
1574 }
1575#endif
1576 return bForce;
1577 }
1578
1579 static void pushSettingsAndSetupViewport(const QSize &display, const QRect &viewport)
1580 {
1581 glPushAttrib(GL_ALL_ATTRIB_BITS);
1582 glMatrixMode(GL_PROJECTION);
1583 glPushMatrix();
1584 setupMatricies(display, false);
1585 adjustViewport(display, viewport);
1586 }
1587
1588 static void popSettingsAfterSetupViewport()
1589 {
1590 glPopAttrib();
1591 glMatrixMode(GL_PROJECTION);
1592 glPopMatrix();
1593 glMatrixMode(GL_MODELVIEW);
1594 }
1595
1596private:
1597 static void setupMatricies(const QSize &display, bool bInvert);
1598 static void adjustViewport(const QSize &display, const QRect &viewport);
1599
1600
1601#ifdef VBOXQGL_DBG_SURF
1602 void vboxDoTestSurfaces(void *context);
1603#endif
1604#ifdef VBOX_WITH_VIDEOHWACCEL
1605
1606 void vboxCheckUpdateAddress(VBoxVHWASurfaceBase * pSurface, uint64_t offset)
1607 {
1608 if (pSurface->addressAlocated())
1609 {
1610 Assert(!mDisplay.isPrimary(pSurface));
1611 uchar * addr = vboxVRAMAddressFromOffset(offset);
1612 if (addr)
1613 {
1614 pSurface->setAddress(addr);
1615 }
1616 }
1617 }
1618
1619 int vhwaSaveSurface(struct SSMHANDLE * pSSM, VBoxVHWASurfaceBase *pSurf, uint32_t surfCaps);
1620 static int vhwaLoadSurface(VHWACommandList * pCmdList, struct SSMHANDLE * pSSM, uint32_t cBackBuffers, uint32_t u32Version);
1621 int vhwaSaveOverlayData(struct SSMHANDLE * pSSM, VBoxVHWASurfaceBase *pSurf, bool bVisible);
1622 static int vhwaLoadOverlayData(VHWACommandList * pCmdList, struct SSMHANDLE * pSSM, uint32_t u32Version);
1623 static int vhwaLoadVHWAEnable(VHWACommandList * pCmdList);
1624
1625 void vhwaDoSurfaceOverlayUpdate(VBoxVHWASurfaceBase *pDstSurf, VBoxVHWASurfaceBase *pSrcSurf, struct VBOXVHWACMD_SURF_OVERLAY_UPDATE *pCmd);
1626#endif
1627
1628 VBoxVHWADisplay mDisplay;
1629
1630 VBoxVHWASurfaceBase* handle2Surface(uint32_t h)
1631 {
1632 VBoxVHWASurfaceBase* pSurf = (VBoxVHWASurfaceBase*)mSurfHandleTable.get(h);
1633 Assert(pSurf);
1634 return pSurf;
1635 }
1636
1637 VBoxVHWAHandleTable mSurfHandleTable;
1638
1639 bool mRepaintNeeded;
1640
1641 QRect mViewport;
1642
1643 VBoxVHWASurfList *mConstructingList;
1644 int32_t mcRemaining2Contruct;
1645
1646 class VBoxVHWAGlProgramMngr *mpMngr;
1647
1648 VBoxVHWASettings *mSettings;
1649
1650 void *mpvVRAM;
1651 uint32_t mcbVRAM;
1652
1653#ifdef VBOXVHWA_PROFILE_FPS
1654 VBoxVHWADbgTimer mFPSCounter;
1655 bool mbNewFrame;
1656#endif
1657};
1658
1659class VBoxGLWgt : public QGLWidget
1660{
1661public:
1662 VBoxGLWgt(VBoxVHWAImage * pImage,
1663 QWidget* parent, const QGLWidget* shareWidget);
1664
1665protected:
1666 void paintGL()
1667 {
1668 mpImage->performDisplay(true);
1669 }
1670private:
1671 VBoxVHWAImage * mpImage;
1672};
1673
1674class VBoxVHWAFBO
1675{
1676public:
1677 VBoxVHWAFBO() :
1678 mFBO(0)
1679 {}
1680
1681 ~VBoxVHWAFBO()
1682 {
1683 if(mFBO)
1684 {
1685 vboxglDeleteFramebuffers(1, &mFBO);
1686 }
1687 }
1688
1689 void init()
1690 {
1691 VBOXQGL_CHECKERR(
1692 vboxglGenFramebuffers(1, &mFBO);
1693 );
1694 }
1695
1696 void bind()
1697 {
1698 VBOXQGL_CHECKERR(
1699 vboxglBindFramebuffer(GL_FRAMEBUFFER, mFBO);
1700 );
1701 }
1702
1703 void unbind()
1704 {
1705 VBOXQGL_CHECKERR(
1706 vboxglBindFramebuffer(GL_FRAMEBUFFER, 0);
1707 );
1708 }
1709
1710 void attachBound(VBoxVHWATexture *pTex)
1711 {
1712 VBOXQGL_CHECKERR(
1713 vboxglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, pTex->texTarget(), pTex->texture(), 0);
1714 );
1715 }
1716
1717private:
1718 GLuint mFBO;
1719};
1720
1721template <class T>
1722class VBoxVHWATextureImageFBO : public T
1723{
1724public:
1725 VBoxVHWATextureImageFBO(const QRect &size, const VBoxVHWAColorFormat &format, class VBoxVHWAGlProgramMngr * aMgr, VBOXVHWAIMG_TYPE flags) :
1726 T(size, format, aMgr, flags & (~(VBOXVHWAIMG_FBO | VBOXVHWAIMG_LINEAR))),
1727 mFBOTex(size, VBoxVHWAColorFormat(32, 0xff0000, 0xff00, 0xff), aMgr, (flags & (~VBOXVHWAIMG_FBO))),
1728 mpvFBOTexMem(NULL)
1729 {
1730 }
1731
1732 virtual ~VBoxVHWATextureImageFBO()
1733 {
1734 if(mpvFBOTexMem)
1735 free(mpvFBOTexMem);
1736 }
1737
1738 virtual void init(uchar *pvMem)
1739 {
1740 mFBO.init();
1741 mpvFBOTexMem = (uchar*)malloc(mFBOTex.memSize());
1742 mFBOTex.init(mpvFBOTexMem);
1743 T::init(pvMem);
1744 mFBO.bind();
1745 mFBO.attachBound(mFBOTex.component(0));
1746 mFBO.unbind();
1747 }
1748
1749 virtual int createDisplay(VBoxVHWATextureImage *pDst, const QRect * pDstRect, const QRect * pSrcRect,
1750 const VBoxVHWAColorKey * pDstCKey, const VBoxVHWAColorKey * pSrcCKey, bool bNotIntersected,
1751 GLuint *pDisplay, class VBoxVHWAGlProgramVHWA ** ppProgram)
1752 {
1753 T::createDisplay(NULL, &mFBOTex.rect(), &rect(),
1754 NULL, NULL, false,
1755 pDisplay, ppProgram);
1756
1757 return mFBOTex.initDisplay(pDst, pDstRect, pSrcRect,
1758 pDstCKey, pSrcCKey, bNotIntersected);
1759 }
1760
1761 virtual void update(const QRect * pRect)
1762 {
1763 T::update(pRect);
1764
1765 VBoxVHWAImage::pushSettingsAndSetupViewport(rect().size(), rect());
1766 mFBO.bind();
1767 T::display();
1768 mFBO.unbind();
1769 VBoxVHWAImage::popSettingsAfterSetupViewport();
1770 }
1771
1772 virtual void display(VBoxVHWATextureImage *pDst, const QRect * pDstRect, const QRect * pSrcRect,
1773 const VBoxVHWAColorKey * pDstCKey, const VBoxVHWAColorKey * pSrcCKey, bool bNotIntersected)
1774 {
1775 mFBOTex.display(pDst, pDstRect, pSrcRect, pDstCKey, pSrcCKey, bNotIntersected);
1776 }
1777
1778 virtual void display()
1779 {
1780 mFBOTex.display();
1781 }
1782
1783 const QRect &rect() { return T::rect(); }
1784private:
1785 VBoxVHWAFBO mFBO;
1786 VBoxVHWATextureImage mFBOTex;
1787 uchar * mpvFBOTexMem;
1788};
1789
1790class VBoxQGLOverlay
1791{
1792public:
1793 VBoxQGLOverlay(QWidget *pViewport, QObject *pPostEventObject, CSession * aSession, uint32_t id);
1794 ~VBoxQGLOverlay()
1795 {
1796 if (mpShareWgt)
1797 delete mpShareWgt;
1798 }
1799
1800 void updateAttachment(QWidget *pViewport, QObject *pPostEventObject);
1801
1802 int onVHWACommand (struct VBOXVHWACMD * pCommand);
1803
1804 void onVHWACommandEvent (QEvent * pEvent);
1805
1806 /**
1807 * to be called on NotifyUpdate framebuffer call
1808 * @return true if the request was processed & should not be forwarded to the framebuffer
1809 * false - otherwise */
1810 bool onNotifyUpdate (ULONG aX, ULONG aY,
1811 ULONG aW, ULONG aH);
1812
1813 /**
1814 * to be called on RequestResize framebuffer call
1815 * @return true if the request was processed & should not be forwarded to the framebuffer
1816 * false - otherwise */
1817 bool onRequestResize (ULONG aScreenId, ULONG uPixelFormat,
1818 BYTE * pVRAM, ULONG uBitsPerPixel, ULONG uBytesPerLine,
1819 ULONG uWidth, ULONG uHeight,
1820 HRESULT *pResult,
1821 BOOL * pbFinished)
1822 {
1823 Q_UNUSED(aScreenId);
1824 Q_UNUSED(uPixelFormat);
1825 Q_UNUSED(pVRAM);
1826 Q_UNUSED(uBitsPerPixel);
1827 Q_UNUSED(uBytesPerLine);
1828 Q_UNUSED(uWidth);
1829 Q_UNUSED(uHeight);
1830 Q_UNUSED(pbFinished);
1831
1832 if (mCmdPipe.completeCurrentEvent())
1833 return false;
1834
1835 /* TODO: more graceful resize handling */
1836 *pResult = E_FAIL;
1837
1838 return true;
1839 }
1840
1841 void onResizeEventPostprocess (const VBoxFBSizeInfo &re, const QPoint & topLeft);
1842
1843 void onViewportResized (QResizeEvent * /*re*/)
1844 {
1845 vboxDoCheckUpdateViewport();
1846 mGlCurrent = false;
1847 }
1848
1849 void onViewportScrolled (const QPoint & newTopLeft)
1850 {
1851 mContentsTopLeft = newTopLeft;
1852 vboxDoCheckUpdateViewport();
1853 mGlCurrent = false;
1854 }
1855
1856 static bool isAcceleration2DVideoAvailable();
1857
1858 /** additional video memory required for the best 2D support performance
1859 * total amount of VRAM required is thus calculated as requiredVideoMemory + required2DOffscreenVideoMemory */
1860 static quint64 required2DOffscreenVideoMemory();
1861
1862 /* not supposed to be called by clients */
1863 int vhwaLoadExec (struct SSMHANDLE * pSSM, uint32_t u32Version);
1864 void vhwaSaveExec (struct SSMHANDLE * pSSM);
1865private:
1866 int vhwaSurfaceUnlock (struct VBOXVHWACMD_SURF_UNLOCK *pCmd);
1867
1868 void repaintMain();
1869 void repaintOverlay()
1870 {
1871 if(mNeedOverlayRepaint)
1872 {
1873 mNeedOverlayRepaint = false;
1874 performDisplayOverlay();
1875 }
1876 if(mNeedSetVisible)
1877 {
1878 mNeedSetVisible = false;
1879 mpOverlayWgt->setVisible (true);
1880 }
1881 }
1882 void repaint()
1883 {
1884 repaintOverlay();
1885 repaintMain();
1886 }
1887
1888 void makeCurrent()
1889 {
1890 if (!mGlCurrent)
1891 {
1892 mGlCurrent = true;
1893 mpOverlayWgt->makeCurrent();
1894 }
1895 }
1896
1897 void performDisplayOverlay()
1898 {
1899 if (mOverlayVisible)
1900 {
1901 makeCurrent();
1902 if (mOverlayImage.performDisplay(false))
1903 mpOverlayWgt->swapBuffers();
1904 }
1905 }
1906
1907 void vboxSetGlOn (bool on);
1908 bool vboxGetGlOn() { return mGlOn; }
1909 bool vboxSynchGl();
1910 void vboxDoVHWACmdExec(void *cmd);
1911 void vboxShowOverlay (bool show);
1912 void vboxDoCheckUpdateViewport();
1913 void vboxDoVHWACmd (void *cmd);
1914 void addMainDirtyRect (const QRect & aRect);
1915 void vboxCheckUpdateOverlay (const QRect & rect);
1916 VBoxVHWACommandElement * processCmdList (VBoxVHWACommandElement * pCmd, bool bFirst);
1917
1918 int vhwaConstruct (struct VBOXVHWACMD_HH_CONSTRUCT *pCmd);
1919
1920 int reset();
1921
1922 int resetGl();
1923
1924 void initGl();
1925
1926 VBoxGLWgt *mpOverlayWgt;
1927 VBoxVHWAImage mOverlayImage;
1928 QWidget *mpViewport;
1929 bool mGlOn;
1930 bool mOverlayWidgetVisible;
1931 bool mOverlayVisible;
1932 bool mGlCurrent;
1933 bool mProcessingCommands;
1934 bool mNeedOverlayRepaint;
1935 bool mNeedSetVisible;
1936 QRect mOverlayViewport;
1937 VBoxVHWADirtyRect mMainDirtyRect;
1938
1939 VBoxVHWACommandElementProcessor mCmdPipe;
1940
1941 /* this is used in saved state restore to postpone surface restoration
1942 * till the framebuffer size is restored */
1943 VHWACommandList mOnResizeCmdList;
1944
1945 VBoxVHWASettings mSettings;
1946 CSession * mpSession;
1947
1948 VBoxFBSizeInfo mSizeInfo;
1949 VBoxFBSizeInfo mPostponedResize;
1950 QPoint mContentsTopLeft;
1951
1952 QGLWidget *mpShareWgt;
1953
1954 uint32_t m_id;
1955};
1956
1957/* these two additional class V, class R are to workaround the [VBox|UI] duplication,
1958 * @todo: remove them once VBox stuff is removed */
1959template <class T, class V, class R>
1960class VBoxOverlayFrameBuffer : public T
1961{
1962public:
1963 VBoxOverlayFrameBuffer (V *pView, CSession * aSession, uint32_t id)
1964 : T (pView),
1965 mOverlay(pView->viewport(), pView, aSession, id),
1966 mpView (pView)
1967 {
1968 /* sync with framebuffer */
1969 mOverlay.onResizeEventPostprocess (VBoxFBSizeInfo(this), QPoint(mpView->contentsX(), mpView->contentsY()));
1970 }
1971
1972 STDMETHOD(ProcessVHWACommand)(BYTE *pCommand)
1973 {
1974 return mOverlay.onVHWACommand ((struct VBOXVHWACMD*)pCommand);
1975 }
1976
1977 void doProcessVHWACommand (QEvent * pEvent)
1978 {
1979 mOverlay.onVHWACommandEvent (pEvent);
1980 }
1981
1982 STDMETHOD(RequestResize) (ULONG aScreenId, ULONG aPixelFormat,
1983 BYTE *aVRAM, ULONG aBitsPerPixel, ULONG aBytesPerLine,
1984 ULONG aWidth, ULONG aHeight,
1985 BOOL *aFinished)
1986 {
1987 HRESULT result;
1988 if (mOverlay.onRequestResize (aScreenId, aPixelFormat,
1989 aVRAM, aBitsPerPixel, aBytesPerLine,
1990 aWidth, aHeight,
1991 &result,
1992 aFinished))
1993 {
1994 return result;
1995 }
1996 return T::RequestResize (aScreenId, aPixelFormat,
1997 aVRAM, aBitsPerPixel, aBytesPerLine,
1998 aWidth, aHeight,
1999 aFinished);
2000 }
2001
2002 STDMETHOD(NotifyUpdate) (ULONG aX, ULONG aY,
2003 ULONG aW, ULONG aH)
2004 {
2005 if (mOverlay.onNotifyUpdate (aX, aY, aW, aH))
2006 return S_OK;
2007 return T::NotifyUpdate (aX, aY, aW, aH);
2008 }
2009
2010 STDMETHOD(VideoModeSupported) (ULONG uWidth, ULONG uHeight, ULONG uBPP,
2011 BOOL *pbSupported)
2012 {
2013 /* TODO: tmp workaround: the lock should be moved to the calling code??
2014 * otherwise we may end up calling a null View */
2015 /* Todo: can we call VideoModeSupported with the lock held?
2016 * if not we can introduce a ref counting for the mpView usage
2017 * to ensure it stays alive till we need it*/
2018 HRESULT hr = T::Lock();
2019 HRESULT retHr = S_OK;
2020 Assert(hr == S_OK);
2021 if (SUCCEEDED(hr))
2022 {
2023 if (mpView)
2024 retHr = T::VideoModeSupported(uWidth, uHeight, uBPP, pbSupported);
2025 hr = T::Unlock();
2026 Assert(hr == S_OK);
2027 }
2028 return retHr;
2029 }
2030
2031 void resizeEvent (R *re)
2032 {
2033 T::resizeEvent (re);
2034 mOverlay.onResizeEventPostprocess (VBoxFBSizeInfo(this),
2035 QPoint(mpView->contentsX(), mpView->contentsY()));
2036 }
2037
2038 void viewportResized (QResizeEvent * re)
2039 {
2040 mOverlay.onViewportResized (re);
2041 T::viewportResized (re);
2042 }
2043
2044 void viewportScrolled (int dx, int dy)
2045 {
2046 mOverlay.onViewportScrolled (QPoint(mpView->contentsX(), mpView->contentsY()));
2047 T::viewportScrolled (dx, dy);
2048 }
2049
2050 void setView(V * pView)
2051 {
2052 /* lock to ensure we do not collide with the EMT thread passing commands to us */
2053 HRESULT hr = T::Lock();
2054 Assert(hr == S_OK);
2055 if (SUCCEEDED(hr))
2056 {
2057 T::setView(pView);
2058 mpView = pView;
2059 mOverlay.updateAttachment(pView ? pView->viewport() : NULL, pView);
2060 hr = T::Unlock();
2061 Assert(hr == S_OK);
2062 }
2063 }
2064private:
2065 VBoxQGLOverlay mOverlay;
2066 V *mpView;
2067};
2068
2069#endif
2070
2071#endif /* #ifndef __VBoxFBOverlay_h__ */
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use