VirtualBox

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

Last change on this file since 82781 was 82677, checked in by vboxsync, 4 years ago

VBoxFBOverlay: VHWA cleanup, adressed a todo

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

© 2023 Oracle
ContactPrivacy policyTerms of Use