VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/include/VBoxFrameBuffer.h@ 21304

Last change on this file since 21304 was 21304, checked in by vboxsync, 15 years ago

video hw accel: more flip & overlay support impl for QGLFrameBuffer

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 31.1 KB
Line 
1/** @file
2 *
3 * VBox frontends: Qt GUI ("VirtualBox"):
4 * VBoxFrameBuffer class and subclasses declarations
5 */
6
7/*
8 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
19 * Clara, CA 95054 USA or visit http://www.sun.com if you need
20 * additional information or have any questions.
21 */
22
23#ifndef ___VBoxFrameBuffer_h___
24#define ___VBoxFrameBuffer_h___
25
26#include "COMDefs.h"
27#include <iprt/critsect.h>
28
29/* Qt includes */
30#include <QImage>
31#include <QPixmap>
32#include <QMutex>
33#include <QPaintEvent>
34#include <QMoveEvent>
35#if defined (VBOX_GUI_USE_QGL)
36#include <QGLWidget>
37#endif
38
39#if defined (VBOX_GUI_USE_SDL)
40#include <SDL.h>
41#include <signal.h>
42#endif
43
44#if defined (Q_WS_WIN) && defined (VBOX_GUI_USE_DDRAW)
45// VBox/cdefs.h defines these:
46#undef LOWORD
47#undef HIWORD
48#undef LOBYTE
49#undef HIBYTE
50#include <ddraw.h>
51#endif
52
53class VBoxConsoleView;
54
55/////////////////////////////////////////////////////////////////////////////
56
57/**
58 * Frame buffer resize event.
59 */
60class VBoxResizeEvent : public QEvent
61{
62public:
63
64 VBoxResizeEvent (ulong aPixelFormat, uchar *aVRAM,
65 ulong aBitsPerPixel, ulong aBytesPerLine,
66 ulong aWidth, ulong aHeight) :
67 QEvent ((QEvent::Type) VBoxDefs::ResizeEventType),
68 mPixelFormat (aPixelFormat), mVRAM (aVRAM), mBitsPerPixel (aBitsPerPixel),
69 mBytesPerLine (aBytesPerLine), mWidth (aWidth), mHeight (aHeight) {}
70 ulong pixelFormat() { return mPixelFormat; }
71 uchar *VRAM() { return mVRAM; }
72 ulong bitsPerPixel() { return mBitsPerPixel; }
73 ulong bytesPerLine() { return mBytesPerLine; }
74 ulong width() { return mWidth; }
75 ulong height() { return mHeight; }
76
77private:
78
79 ulong mPixelFormat;
80 uchar *mVRAM;
81 ulong mBitsPerPixel;
82 ulong mBytesPerLine;
83 ulong mWidth;
84 ulong mHeight;
85};
86
87/**
88 * Frame buffer repaint event.
89 */
90class VBoxRepaintEvent : public QEvent
91{
92public:
93 VBoxRepaintEvent (int x, int y, int w, int h) :
94 QEvent ((QEvent::Type) VBoxDefs::RepaintEventType),
95 ex (x), ey (y), ew (w), eh (h)
96 {}
97 int x() { return ex; }
98 int y() { return ey; }
99 int width() { return ew; }
100 int height() { return eh; }
101private:
102 int ex, ey, ew, eh;
103};
104
105/**
106 * Frame buffer set region event.
107 */
108class VBoxSetRegionEvent : public QEvent
109{
110public:
111 VBoxSetRegionEvent (const QRegion &aReg)
112 : QEvent ((QEvent::Type) VBoxDefs::SetRegionEventType)
113 , mReg (aReg) {}
114 QRegion region() { return mReg; }
115private:
116 QRegion mReg;
117};
118
119#ifdef VBOX_WITH_VIDEOHWACCEL
120class VBoxVHWACommandProcessEvent : public QEvent
121{
122public:
123 VBoxVHWACommandProcessEvent (struct _VBOXVHWACMD * pCmd)
124 : QEvent ((QEvent::Type) VBoxDefs::VHWACommandProcessType)
125 , mpCmd (pCmd) {}
126 struct _VBOXVHWACMD * command() { return mpCmd; }
127private:
128 struct _VBOXVHWACMD * mpCmd;
129};
130
131#endif
132
133/////////////////////////////////////////////////////////////////////////////
134
135/**
136 * Common IFramebuffer implementation for all methods used by GUI to maintain
137 * the VM display video memory.
138 *
139 * Note that although this class can be called from multiple threads
140 * (in particular, the GUI thread and EMT) it doesn't protect access to every
141 * data field using its mutex lock. This is because all synchronization between
142 * the GUI and the EMT thread is supposed to be done using the
143 * IFramebuffer::NotifyUpdate() and IFramebuffer::RequestResize() methods
144 * (in particular, the \a aFinished parameter of these methods is responsible
145 * for the synchronization). These methods are always called on EMT and
146 * therefore always follow one another but never in parallel.
147 *
148 * Using this object's mutex lock (exposed also in IFramebuffer::Lock() and
149 * IFramebuffer::Unlock() implementations) usually makes sense only if some
150 * third-party thread (i.e. other than GUI or EMT) needs to make sure that
151 * *no* VM display update or resize event can occur while it is accessing
152 * IFramebuffer properties or the underlying display memory storage area.
153 *
154 * See IFramebuffer documentation for more info.
155 */
156
157class VBoxFrameBuffer : VBOX_SCRIPTABLE_IMPL(IFramebuffer)
158{
159public:
160
161 VBoxFrameBuffer (VBoxConsoleView *aView);
162 virtual ~VBoxFrameBuffer();
163
164 NS_DECL_ISUPPORTS
165
166#if defined (Q_OS_WIN32)
167
168 STDMETHOD_(ULONG, AddRef)()
169 {
170 return ::InterlockedIncrement (&refcnt);
171 }
172
173 STDMETHOD_(ULONG, Release)()
174 {
175 long cnt = ::InterlockedDecrement (&refcnt);
176 if (cnt == 0)
177 delete this;
178 return cnt;
179 }
180
181 STDMETHOD(QueryInterface) (REFIID riid , void **ppObj)
182 {
183 if (riid == IID_IUnknown) {
184 *ppObj = this;
185 AddRef();
186 return S_OK;
187 }
188 if (riid == IID_IFramebuffer) {
189 *ppObj = this;
190 AddRef();
191 return S_OK;
192 }
193 *ppObj = NULL;
194 return E_NOINTERFACE;
195 }
196
197#endif
198
199 // IFramebuffer COM methods
200 STDMETHOD(COMGETTER(Address)) (BYTE **aAddress);
201 STDMETHOD(COMGETTER(Width)) (ULONG *aWidth);
202 STDMETHOD(COMGETTER(Height)) (ULONG *aHeight);
203 STDMETHOD(COMGETTER(BitsPerPixel)) (ULONG *aBitsPerPixel);
204 STDMETHOD(COMGETTER(BytesPerLine)) (ULONG *aBytesPerLine);
205 STDMETHOD(COMGETTER(PixelFormat)) (ULONG *aPixelFormat);
206 STDMETHOD(COMGETTER(UsesGuestVRAM)) (BOOL *aUsesGuestVRAM);
207 STDMETHOD(COMGETTER(HeightReduction)) (ULONG *aHeightReduction);
208 STDMETHOD(COMGETTER(Overlay)) (IFramebufferOverlay **aOverlay);
209 STDMETHOD(COMGETTER(WinId)) (ULONG64 *winId);
210
211 STDMETHOD(Lock)();
212 STDMETHOD(Unlock)();
213
214 STDMETHOD(RequestResize) (ULONG aScreenId, ULONG aPixelFormat,
215 BYTE *aVRAM, ULONG aBitsPerPixel, ULONG aBytesPerLine,
216 ULONG aWidth, ULONG aHeight,
217 BOOL *aFinished);
218
219 STDMETHOD(VideoModeSupported) (ULONG aWidth, ULONG aHeight, ULONG aBPP,
220 BOOL *aSupported);
221
222 STDMETHOD(GetVisibleRegion)(BYTE *aRectangles, ULONG aCount, ULONG *aCountCopied);
223 STDMETHOD(SetVisibleRegion)(BYTE *aRectangles, ULONG aCount);
224
225 STDMETHOD(ProcessVHWACommand)(BYTE *pCommand);
226
227 ulong width() { return mWdt; }
228 ulong height() { return mHgt; }
229
230 virtual ulong pixelFormat()
231 {
232 return FramebufferPixelFormat_FOURCC_RGB;
233 }
234
235 virtual bool usesGuestVRAM()
236 {
237 return false;
238 }
239
240 void lock() { RTCritSectEnter(&mCritSect); }
241 void unlock() { RTCritSectLeave(&mCritSect); }
242
243 virtual uchar *address() = 0;
244 virtual ulong bitsPerPixel() = 0;
245 virtual ulong bytesPerLine() = 0;
246
247 /**
248 * Called on the GUI thread (from VBoxConsoleView) when some part of the
249 * VM display viewport needs to be repainted on the host screen.
250 */
251 virtual void paintEvent (QPaintEvent *pe) = 0;
252
253 /**
254 * Called on the GUI thread (from VBoxConsoleView) after it gets a
255 * VBoxResizeEvent posted from the RequestResize() method implementation.
256 */
257 virtual void resizeEvent (VBoxResizeEvent *re)
258 {
259 mWdt = re->width();
260 mHgt = re->height();
261 }
262
263 /**
264 * Called on the GUI thread (from VBoxConsoleView) when the VM console
265 * window is moved.
266 */
267 virtual void moveEvent (QMoveEvent * /*me*/ ) {}
268
269#ifdef VBOX_WITH_VIDEOHWACCEL
270 /* this method is called from the GUI thread
271 * to perform the actual Video HW Acceleration command processing */
272 virtual void doProcessVHWACommand(struct _VBOXVHWACMD * pCommand);
273#endif
274
275protected:
276
277 VBoxConsoleView *mView;
278 RTCRITSECT mCritSect;
279 int mWdt;
280 int mHgt;
281 uint64_t mWinId;
282
283#if defined (Q_OS_WIN32)
284private:
285 long refcnt;
286#endif
287};
288
289/////////////////////////////////////////////////////////////////////////////
290
291#if defined (VBOX_GUI_USE_QIMAGE)
292
293class VBoxQImageFrameBuffer : public VBoxFrameBuffer
294{
295public:
296
297 VBoxQImageFrameBuffer (VBoxConsoleView *aView);
298
299 STDMETHOD(NotifyUpdate) (ULONG aX, ULONG aY,
300 ULONG aW, ULONG aH);
301
302 ulong pixelFormat() { return mPixelFormat; }
303 bool usesGuestVRAM() { return mUsesGuestVRAM; }
304
305 uchar *address() { return mImg.bits(); }
306 ulong bitsPerPixel() { return mImg.depth(); }
307 ulong bytesPerLine() { return mImg.bytesPerLine(); }
308
309 void paintEvent (QPaintEvent *pe);
310 void resizeEvent (VBoxResizeEvent *re);
311
312private:
313
314 QPixmap mPM;
315 QImage mImg;
316 ulong mPixelFormat;
317 bool mUsesGuestVRAM;
318};
319
320#endif
321
322/////////////////////////////////////////////////////////////////////////////
323
324#if defined (VBOX_GUI_USE_QGL)
325class VBoxVHWADirtyRect
326{
327public:
328 VBoxVHWADirtyRect() :
329 mIsClear(true)
330 {}
331
332 VBoxVHWADirtyRect(const QRect & aRect)
333 {
334 if(aRect.isEmpty())
335 {
336 mIsClear = false;
337 mRect = aRect;
338 }
339 else
340 {
341 mIsClear = true;
342 }
343 }
344
345 bool isClear() const { return mIsClear; }
346
347 void add(const QRect & aRect)
348 {
349 if(aRect.isEmpty())
350 return;
351
352 mRect = mIsClear ? aRect : mRect.united(aRect);
353 mIsClear = false;
354 }
355
356 void add(const VBoxVHWADirtyRect & aRect)
357 {
358 if(aRect.isClear())
359 return;
360 add(aRect.rect());
361 }
362
363 void set(const QRect & aRect)
364 {
365 if(aRect.isEmpty())
366 {
367 mIsClear = true;
368 }
369 else
370 {
371 mRect = aRect;
372 mIsClear = false;
373 }
374 }
375
376 void clear() { mIsClear = true; }
377
378 const QRect & rect() const {return mRect;}
379
380 bool intersects(const QRect & aRect) const {return mIsClear ? false : mRect.intersects(aRect);}
381
382 bool intersects(const VBoxVHWADirtyRect & aRect) const {return mIsClear ? false : aRect.intersects(mRect);}
383
384 QRect united(const QRect & aRect) const {return mIsClear ? aRect : aRect.united(mRect);}
385
386 bool contains(const QRect & aRect) const {return mIsClear ? false : aRect.contains(mRect);}
387
388 void subst(const VBoxVHWADirtyRect & aRect) { if(!mIsClear && aRect.contains(mRect)) clear(); }
389
390private:
391 QRect mRect;
392 bool mIsClear;
393};
394
395class VBoxVHWAColorKey
396{
397public:
398 VBoxVHWAColorKey() :
399 mUpper(0),
400 mLower(0)
401 {}
402
403 VBoxVHWAColorKey(uint32_t aUpper, uint32_t aLower) :
404 mUpper(aUpper),
405 mLower(aLower)
406 {}
407
408 uint32_t upper() const {return mUpper; }
409 uint32_t lower() const {return mLower; }
410private:
411 uint32_t mUpper;
412 uint32_t mLower;
413};
414
415class VBoxVHWAColorComponent
416{
417public:
418 VBoxVHWAColorComponent() :
419 mMask(0),
420 mRange(0),
421 mOffset(32),
422 mcBits(0)
423 {}
424
425 VBoxVHWAColorComponent(uint32_t aMask);
426
427 uint32_t mask() const { return mMask; }
428 uint32_t range() const { return mRange; }
429 uint32_t offset() const { return mOffset; }
430 uint32_t cBits() const { return mcBits; }
431 uint32_t colorVal(uint32_t col) const { return (col & mMask) >> mOffset; }
432 float colorValNorm(uint32_t col) const { return ((float)colorVal(col))/mRange; }
433private:
434 uint32_t mMask;
435 uint32_t mRange;
436 uint32_t mOffset;
437 uint32_t mcBits;
438};
439
440class VBoxVHWAColorFormat
441{
442public:
443
444// VBoxVHWAColorFormat(GLint aInternalFormat, GLenum aFormat, GLenum aType, uint32_t aDataFormat);
445 VBoxVHWAColorFormat(uint32_t bitsPerPixel, uint32_t r, uint32_t g, uint32_t b);
446
447 GLint internalFormat() const {return mInternalFormat; }
448 GLenum format() const {return mFormat; }
449 GLenum type() const {return mType; }
450 bool isValid() const {return mBitsPerPixel != 0; }
451 uint32_t dataFormat() const {return mDataFormat;}
452 uint32_t bitsPerPixel() const { return mBitsPerPixel; }
453 void pixel2Normalized(uint32_t pix, float *r, float *g, float *b) const;
454// uint32_t r(uint32_t pix);
455// uint32_t g(uint32_t pix);
456// uint32_t b(uint32_t pix);
457
458private:
459 void VBoxVHWAColorFormat::init(uint32_t bitsPerPixel, uint32_t r, uint32_t g, uint32_t b);
460
461 GLint mInternalFormat;
462 GLenum mFormat;
463 GLenum mType;
464 uint32_t mDataFormat;
465
466 uint32_t mBitsPerPixel;
467
468 VBoxVHWAColorComponent mR;
469 VBoxVHWAColorComponent mG;
470 VBoxVHWAColorComponent mB;
471};
472
473/* data flow:
474 * I. NON-Yinverted surface:
475 * 1.direct memory update (paint, lock/unlock):
476 * mem->tex->fb
477 * 2.blt
478 * srcTex->invFB->tex->fb
479 * |->mem
480 *
481 * II. Yinverted surface:
482 * 1.direct memory update (paint, lock/unlock):
483 * mem->tex->fb
484 * 2.blt
485 * srcTex->fb->tex
486 * |->mem
487 *
488 * III. flip support:
489 * 1. Yinverted<->NON-YInverted conversion :
490 * mem->tex-(rotate model view, force LAZY complete fb update)->invFB->tex
491 * fb-->| |->mem
492 * */
493class VBoxVHWASurfaceBase
494{
495public:
496 VBoxVHWASurfaceBase(class VBoxVHWAGlContextState *aState, bool aIsYInverted, GLsizei aWidth, GLsizei aHeight,
497 VBoxVHWAColorFormat & aColorFormat,
498 VBoxVHWAColorKey * pSrcBltCKey, VBoxVHWAColorKey * pDstBltCKey,
499 VBoxVHWAColorKey * pSrcOverlayCKey, VBoxVHWAColorKey * pDstOverlayCKey);
500
501 virtual ~VBoxVHWASurfaceBase();
502
503 virtual void init(uchar *pvMem);
504
505 virtual void uninit();
506
507 static void globalInit();
508
509 int blt(const QRect * aDstRect, VBoxVHWASurfaceBase * aSrtSurface, const QRect * aSrcRect, const VBoxVHWAColorKey * pDstCKeyOverride, const VBoxVHWAColorKey * pSrcCKeyOverride);
510
511 virtual int lock(const QRect * pRect, uint32_t flags);
512
513 virtual int unlock();
514
515 void updatedMem(const QRect * aRect);
516
517 void performDisplay();
518
519 static ulong calcBytesPerPixel(GLenum format, GLenum type);
520
521 static GLsizei makePowerOf2(GLsizei val);
522
523 bool addressAlocated() const { return mFreeAddress; }
524 uchar * address(){ return mAddress; }
525 uchar * pointAddress(int x, int y) { return mAddress + y*mBytesPerLine + x*mBytesPerPixel; }
526 ulong memSize(){ return mBytesPerLine * mRect.height(); }
527
528 ulong width() { return mRect.width(); }
529 ulong height() { return mRect.height(); }
530
531 GLenum format() {return mColorFormat.format(); }
532 GLint internalFormat() { return mColorFormat.internalFormat(); }
533 GLenum type() { return mColorFormat.type(); }
534 uint32_t dataFormat() {return mColorFormat.dataFormat(); }
535
536 ulong bytesPerPixel() { return mBytesPerPixel; }
537 ulong bitsPerPixel() { return mColorFormat.bitsPerPixel(); }
538 ulong bytesPerLine() { return mBytesPerLine; }
539
540 const VBoxVHWAColorKey * dstBltCKey() { return mDstBltCKeyValid ? &mDstBltCKey : NULL; }
541 const VBoxVHWAColorKey * srcBltCKey() { return mSrcBltCKeyValid ? &mSrcBltCKey : NULL; }
542 const VBoxVHWAColorKey * dstOverlayCKey() { return mDstOverlayCKeyValid ? &mDstOverlayCKey : NULL; }
543 const VBoxVHWAColorKey * srcOverlayCKey() { return mSrcOverlayCKeyValid ? &mSrcOverlayCKey : NULL; }
544 const VBoxVHWAColorFormat & colorFormat() {return mColorFormat; }
545
546 /* clients should treat the returned texture as read-only */
547 GLuint textureSynched(const QRect * aRect) { synchTex(aRect); return mTexture; }
548
549 void setAddress(uchar * addr);
550
551 const QRect& rect() {return mRect;}
552
553// /* surface currently being displayed in a flip chain */
554// virtual bool isPrimary() = 0;
555// /* surface representing the main framebuffer. */
556// virtual bool isMainFramebuffer() = 0;
557 virtual void makeCurrent() = 0;
558 virtual void makeYInvertedCurrent() = 0;
559
560 bool isYInverted() {return mIsYInverted; }
561
562 int invert();
563
564 bool isFrontBuffer() {return !mIsYInverted; }
565
566 bool isOverlay() { return mIsOverlay; }
567
568#ifdef VBOX_WITH_VIDEOHWACCEL
569 virtual class VBoxVHWAGlProgramMngr * getGlProgramMngr() = 0;
570 static int setCKey(class VBoxVHWAGlProgramVHWA * pProgram, const VBoxVHWAColorFormat * pFormat, const VBoxVHWAColorKey * pCKey);
571#endif
572private:
573 void initDisplay();
574 void deleteDisplay();
575 void synchTex(const QRect * aRect);
576 void synchTexMem(const QRect * aRect);
577 void synchTexFB(const QRect * aRect);
578 void synchMem(const QRect * aRect);
579 void synchFB(const QRect * aRect);
580 void synch(const QRect * aRect);
581
582 void doTex2FB(const QRect * aRect);
583
584 void doSetupModelView(bool bInverted);
585
586 QRect mRect;
587
588 GLuint mDisplay;
589 bool mDisplayInitialized;
590
591 uchar * mAddress;
592 GLuint mTexture;
593
594 VBoxVHWAColorFormat mColorFormat;
595 VBoxVHWAColorKey mSrcBltCKey;
596 VBoxVHWAColorKey mDstBltCKey;
597 VBoxVHWAColorKey mSrcOverlayCKey;
598 VBoxVHWAColorKey mDstOverlayCKey;
599 bool mSrcBltCKeyValid;
600 bool mDstBltCKeyValid;
601 bool mSrcOverlayCKeyValid;
602 bool mDstOverlayCKeyValid;
603 GLenum mFormat;
604 GLint mInternalFormat;
605 GLenum mType;
606// ulong mDisplayWidth;
607// ulong mDisplayHeight;
608 ulong mBytesPerPixel;
609 ulong mBytesPerLine;
610
611 int mLockCount;
612 /* memory buffer not reflected in fm and texture, e.g if memory buffer is replaced or in case of lock/unlock */
613 VBoxVHWADirtyRect mUpdateMem2TexRect;
614 /* memory buffer not reflected in fm and texture, e.g if memory buffer is replaced or in case of lock/unlock */
615 VBoxVHWADirtyRect mUpdateTex2FBRect;
616 /*in case of blit we blit from another surface's texture, so our current texture gets durty */
617 VBoxVHWADirtyRect mUpdateFB2TexRect;
618 /*in case of blit the memory buffer does not get updated until we need it, e.g. for paint or lock operations */
619 VBoxVHWADirtyRect mUpdateFB2MemRect;
620
621 /* flag for lazy invert post-processing */
622 bool mInverted;
623
624 bool mFreeAddress;
625
626 bool mIsYInverted;
627
628 bool mIsOverlay;
629
630protected:
631 virtual void init(uchar *pvMem, bool bInverted);
632
633 class VBoxVHWAGlContextState *mState;
634
635};
636
637class VBoxVHWADisplay
638{
639public:
640 VBoxVHWADisplay() :
641 mSurfVGA(NULL),
642 mSurfPrimary(NULL)
643 {}
644
645 VBoxVHWASurfaceBase * setVGA(VBoxVHWASurfaceBase * pVga)
646 {
647 VBoxVHWASurfaceBase * old = mSurfVGA;
648 mSurfVGA = pVga;
649 mSurfPrimary = pVga;
650 mOverlays.clear();
651 return old;
652 }
653
654 VBoxVHWASurfaceBase * getVGA()
655 {
656 return mSurfVGA;
657 }
658
659 void setPrimary(VBoxVHWASurfaceBase * pSurf)
660 {
661 mSurfPrimary = pSurf;
662 }
663
664 void addOverlay(VBoxVHWASurfaceBase * pSurf)
665 {
666 mOverlays.push_back(pSurf);
667 }
668
669 void removeOverlay(VBoxVHWASurfaceBase * pSurf)
670 {
671 mOverlays.remove(pSurf);
672 }
673
674 void flip(VBoxVHWASurfaceBase * pTarg, VBoxVHWASurfaceBase * pCurr)
675 {
676 pCurr->invert();
677 pTarg->invert();
678 if(pTarg->isOverlay())
679 {
680 for (OverlayList::iterator it = mOverlays.begin();
681 it != mOverlays.end(); ++ it)
682 {
683 if((*it) == pCurr)
684 {
685 (*it) = pTarg;
686 }
687 }
688 }
689 else
690 {
691 mSurfPrimary = pTarg;
692 }
693 }
694
695 void performDisplay()
696 {
697 mSurfPrimary->performDisplay();
698
699 for (OverlayList::const_iterator it = mOverlays.begin();
700 it != mOverlays.end(); ++ it)
701 {
702 (*it)->performDisplay();
703 }
704 }
705
706private:
707 VBoxVHWASurfaceBase *mSurfVGA;
708 VBoxVHWASurfaceBase *mSurfPrimary;
709
710 typedef std::list <VBoxVHWASurfaceBase*> OverlayList;
711
712 OverlayList mOverlays;
713};
714
715
716
717class VBoxVHWAGlContextState
718{
719public:
720 VBoxVHWAGlContextState() : mContext(NULL), mInverted(false) {}
721
722 void assertCurrent(class VBoxVHWASurfaceBase *aContext, bool bInverted)
723 {
724 mContext = aContext;
725 if(aContext && aContext->isYInverted())
726 {
727 mInverted = true;
728 }
729 else
730 {
731 mInverted = bInverted;
732 }
733 }
734
735 void makeYInvertedCurrent(class VBoxVHWASurfaceBase *aContext)
736 {
737 if(mContext != aContext)
738 {
739// aContext->makeCurrent();
740 aContext->makeYInvertedCurrent();
741 assertCurrent(aContext, true);
742 }
743 else
744 {
745 if(!aContext->isYInverted() && !mInverted)
746 {
747// aContext->makeCurrent();
748 aContext->makeYInvertedCurrent();
749 mInverted = true;
750 }
751 }
752 }
753
754 void makeCurrent(class VBoxVHWASurfaceBase *aContext)
755 {
756 if(mContext != aContext)
757 {
758 aContext->makeCurrent();
759 assertCurrent(aContext, false);
760 }
761 else
762 {
763 if(!aContext->isYInverted() && mInverted)
764 {
765 aContext->makeCurrent();
766 mInverted = false;
767 }
768 }
769 }
770
771 class VBoxVHWASurfaceBase * getCurrent() {return mContext; }
772 bool isCurrentYInverted() {return mInverted; }
773
774private:
775
776 class VBoxVHWASurfaceBase *mContext;
777 bool mInverted;
778};
779
780class VBoxVHWASurfaceQGL : public VBoxVHWASurfaceBase
781{
782public:
783 VBoxVHWASurfaceQGL(class VBoxVHWAGlContextState *aState, GLsizei aWidth, GLsizei aHeight,
784 VBoxVHWAColorFormat & aColorFormat,
785 VBoxVHWAColorKey * pSrcBltCKey, VBoxVHWAColorKey * pDstBltCKey,
786 VBoxVHWAColorKey * pSrcOverlayCKey, VBoxVHWAColorKey * pDstOverlayCKey,
787 class VBoxGLWidget *pWidget,
788 bool bInvisibleBuffer) :
789 VBoxVHWASurfaceBase(aState, bInvisibleBuffer, aWidth, aHeight,
790 aColorFormat,
791 pSrcBltCKey, pDstBltCKey, pSrcOverlayCKey, pDstOverlayCKey),
792 mWidget(pWidget),
793 mBuffer(NULL)
794 {}
795
796 ~VBoxVHWASurfaceQGL();
797
798 void makeCurrent();
799 void makeYInvertedCurrent();
800
801 void init(uchar *pvMem);
802
803 void uninit();
804
805// int unlock()
806// {
807// int rc = VBoxVHWASurfaceBase::unlock();
808// if(!mBuffer)
809// performDisplay();
810// return rc;
811// }
812#ifdef VBOX_WITH_VIDEOHWACCEL
813 class VBoxVHWAGlProgramMngr * getGlProgramMngr();
814#endif
815private:
816 class VBoxGLWidget *mWidget;
817 class QGLPixelBuffer *mBuffer;
818protected:
819 virtual void init(uchar *pvMem, bool bInverted);
820};
821
822class VBoxGLWidget : public QGLWidget
823{
824public:
825 VBoxGLWidget (QWidget *aParent);
826 ~VBoxGLWidget();
827
828 ulong vboxPixelFormat() { return mPixelFormat; }
829 bool vboxUsesGuestVRAM() { return mUsesGuestVRAM; }
830
831 uchar *vboxAddress() { return mDisplay.getVGA() ? mDisplay.getVGA()->address() : NULL; }
832 uchar *vboxVRAMAddressFromOffset(uint64_t offset);
833 ulong vboxBitsPerPixel() { return mDisplay.getVGA()->bitsPerPixel(); }
834 ulong vboxBytesPerLine() { return mDisplay.getVGA() ? mDisplay.getVGA()->bytesPerLine() : NULL; }
835
836typedef void (VBoxGLWidget::*PFNVBOXQGLOP)(void* );
837//typedef FNVBOXQGLOP *PFNVBOXQGLOP;
838
839 void vboxPaintEvent (QPaintEvent *pe) {vboxPerformGLOp(&VBoxGLWidget::vboxDoPaint, pe);}
840 void vboxResizeEvent (VBoxResizeEvent *re) {vboxPerformGLOp(&VBoxGLWidget::vboxDoResize, re);}
841#ifdef DEBUG_misha
842 void vboxTestSurfaces () {vboxPerformGLOp(&VBoxGLWidget::vboxDoTestSurfaces, NULL);}
843#endif
844#ifdef VBOX_WITH_VIDEOHWACCEL
845 void vboxVHWACmd (struct _VBOXVHWACMD * pCmd) {vboxPerformGLOp(&VBoxGLWidget::vboxDoVHWACmd, pCmd);}
846 class VBoxVHWAGlProgramMngr * vboxVHWAGetGlProgramMngr();
847#endif
848
849 VBoxVHWASurfaceBase * vboxGetVGASurface() { return mDisplay.getVGA(); }
850protected:
851// void resizeGL (int height, int width);
852
853 void paintGL()
854 {
855 Assert(mState.getCurrent() == NULL);
856 /* we are called with QGLWidget context */
857 mState.assertCurrent(mDisplay.getVGA(), false);
858 (this->*mpfnOp)(mOpContext);
859 /* restore the context */
860 mState.makeCurrent(mDisplay.getVGA());
861 /* clear*/
862 mState.assertCurrent(NULL, false);
863 }
864
865 void initializeGL();
866
867private:
868// void vboxDoInitDisplay();
869// void vboxDoDeleteDisplay();
870// void vboxDoPerformDisplay() { Assert(mDisplayInitialized); glCallList(mDisplay); }
871 void vboxDoResize(void *re);
872 void vboxDoPaint(void *rec);
873#ifdef DEBUG_misha
874 void vboxDoTestSurfaces(void *context);
875#endif
876#ifdef VBOX_WITH_VIDEOHWACCEL
877 void vboxDoVHWACmd(void *cmd);
878 void vboxCheckUpdateAddress (VBoxVHWASurfaceBase * pSurface, uint64_t offset)
879 {
880 if (pSurface->addressAlocated())
881 {
882 uchar * addr = vboxVRAMAddressFromOffset(offset);
883 if(addr)
884 {
885 pSurface->setAddress(addr);
886 }
887 }
888 }
889 int vhwaSurfaceCanCreate(struct _VBOXVHWACMD_SURF_CANCREATE *pCmd);
890 int vhwaSurfaceCreate(struct _VBOXVHWACMD_SURF_CREATE *pCmd);
891 int vhwaSurfaceDestroy(struct _VBOXVHWACMD_SURF_DESTROY *pCmd);
892 int vhwaSurfaceLock(struct _VBOXVHWACMD_SURF_LOCK *pCmd);
893 int vhwaSurfaceUnlock(struct _VBOXVHWACMD_SURF_UNLOCK *pCmd);
894 int vhwaSurfaceBlt(struct _VBOXVHWACMD_SURF_BLT *pCmd);
895 int vhwaSurfaceFlip(struct _VBOXVHWACMD_SURF_FLIP *pCmd);
896 int vhwaQueryInfo1(struct _VBOXVHWACMD_QUERYINFO1 *pCmd);
897 int vhwaQueryInfo2(struct _VBOXVHWACMD_QUERYINFO2 *pCmd);
898#endif
899
900// VBoxVHWASurfaceQGL * pDisplay;
901 VBoxVHWADisplay mDisplay;
902
903
904 /* we need to do all opengl stuff in the paintGL context,
905 * submit the operation to be performed */
906 void vboxPerformGLOp(PFNVBOXQGLOP pfn, void* pContext) {mpfnOp = pfn; mOpContext = pContext; updateGL();}
907
908 PFNVBOXQGLOP mpfnOp;
909 void *mOpContext;
910
911// ulong mBitsPerPixel;
912 ulong mPixelFormat;
913 bool mUsesGuestVRAM;
914
915 VBoxVHWAGlContextState mState;
916
917#ifdef VBOX_WITH_VIDEOHWACCEL
918 class VBoxVHWAGlProgramMngr *mpMngr;
919#endif
920};
921
922
923class VBoxQGLFrameBuffer : public VBoxFrameBuffer
924{
925public:
926
927 VBoxQGLFrameBuffer (VBoxConsoleView *aView);
928
929 STDMETHOD(NotifyUpdate) (ULONG aX, ULONG aY,
930 ULONG aW, ULONG aH);
931
932#ifdef VBOX_WITH_VIDEOHWACCEL
933 STDMETHOD(ProcessVHWACommand)(BYTE *pCommand);
934#endif
935
936 ulong pixelFormat() { return vboxWidget()->vboxPixelFormat(); }
937 bool usesGuestVRAM() { return vboxWidget()->vboxUsesGuestVRAM(); }
938
939 uchar *address() { return vboxWidget()->vboxAddress(); }
940 ulong bitsPerPixel() { return vboxWidget()->vboxBitsPerPixel(); }
941 ulong bytesPerLine() { return vboxWidget()->vboxBytesPerLine(); }
942
943 void paintEvent (QPaintEvent *pe);
944 void resizeEvent (VBoxResizeEvent *re);
945#ifdef VBOX_WITH_VIDEOHWACCEL
946 void doProcessVHWACommand(struct _VBOXVHWACMD * pCommand);
947#endif
948
949private:
950// void vboxMakeCurrent();
951 VBoxGLWidget * vboxWidget();
952};
953
954
955#endif
956
957/////////////////////////////////////////////////////////////////////////////
958
959#if defined (VBOX_GUI_USE_SDL)
960
961class VBoxSDLFrameBuffer : public VBoxFrameBuffer
962{
963public:
964
965 VBoxSDLFrameBuffer (VBoxConsoleView *aView);
966 virtual ~VBoxSDLFrameBuffer();
967
968 STDMETHOD(NotifyUpdate) (ULONG aX, ULONG aY,
969 ULONG aW, ULONG aH);
970
971 uchar *address()
972 {
973 SDL_Surface *surf = mSurfVRAM ? mSurfVRAM : mScreen;
974 return surf ? (uchar *) (uintptr_t) surf->pixels : 0;
975 }
976
977 ulong bitsPerPixel()
978 {
979 SDL_Surface *surf = mSurfVRAM ? mSurfVRAM : mScreen;
980 return surf ? surf->format->BitsPerPixel : 0;
981 }
982
983 ulong bytesPerLine()
984 {
985 SDL_Surface *surf = mSurfVRAM ? mSurfVRAM : mScreen;
986 return surf ? surf->pitch : 0;
987 }
988
989 ulong pixelFormat()
990 {
991 return mPixelFormat;
992 }
993
994 bool usesGuestVRAM()
995 {
996 return mSurfVRAM != NULL;
997 }
998
999 void paintEvent (QPaintEvent *pe);
1000 void resizeEvent (VBoxResizeEvent *re);
1001
1002private:
1003
1004 SDL_Surface *mScreen;
1005 SDL_Surface *mSurfVRAM;
1006
1007 ulong mPixelFormat;
1008};
1009
1010#endif
1011
1012/////////////////////////////////////////////////////////////////////////////
1013
1014#if defined (VBOX_GUI_USE_DDRAW)
1015
1016class VBoxDDRAWFrameBuffer : public VBoxFrameBuffer
1017{
1018public:
1019
1020 VBoxDDRAWFrameBuffer (VBoxConsoleView *aView);
1021 virtual ~VBoxDDRAWFrameBuffer();
1022
1023 STDMETHOD(NotifyUpdate) (ULONG aX, ULONG aY,
1024 ULONG aW, ULONG aH);
1025
1026 uchar *address() { return (uchar *) mSurfaceDesc.lpSurface; }
1027 ulong bitsPerPixel() { return mSurfaceDesc.ddpfPixelFormat.dwRGBBitCount; }
1028 ulong bytesPerLine() { return (ulong) mSurfaceDesc.lPitch; }
1029
1030 ulong pixelFormat() { return mPixelFormat; };
1031
1032 bool usesGuestVRAM() { return mUsesGuestVRAM; }
1033
1034 void paintEvent (QPaintEvent *pe);
1035 void resizeEvent (VBoxResizeEvent *re);
1036 void moveEvent (QMoveEvent *me);
1037
1038private:
1039
1040 void releaseObjects();
1041
1042 bool createSurface (ULONG aPixelFormat, uchar *pvVRAM,
1043 ULONG aBitsPerPixel, ULONG aBytesPerLine,
1044 ULONG aWidth, ULONG aHeight);
1045 void deleteSurface();
1046 void drawRect (ULONG x, ULONG y, ULONG w, ULONG h);
1047 void getWindowPosition (void);
1048
1049 LPDIRECTDRAW7 mDDRAW;
1050 LPDIRECTDRAWCLIPPER mClipper;
1051 LPDIRECTDRAWSURFACE7 mSurface;
1052 DDSURFACEDESC2 mSurfaceDesc;
1053 LPDIRECTDRAWSURFACE7 mPrimarySurface;
1054
1055 ulong mPixelFormat;
1056
1057 bool mUsesGuestVRAM;
1058
1059 int mWndX;
1060 int mWndY;
1061
1062 bool mSynchronousUpdates;
1063};
1064
1065#endif
1066
1067/////////////////////////////////////////////////////////////////////////////
1068
1069#if defined (Q_WS_MAC) && defined (VBOX_GUI_USE_QUARTZ2D)
1070
1071#include <Carbon/Carbon.h>
1072
1073class VBoxQuartz2DFrameBuffer : public VBoxFrameBuffer
1074{
1075public:
1076
1077 VBoxQuartz2DFrameBuffer (VBoxConsoleView *aView);
1078 virtual ~VBoxQuartz2DFrameBuffer ();
1079
1080 STDMETHOD (NotifyUpdate) (ULONG aX, ULONG aY,
1081 ULONG aW, ULONG aH);
1082 STDMETHOD (SetVisibleRegion) (BYTE *aRectangles, ULONG aCount);
1083
1084 uchar *address() { return mDataAddress; }
1085 ulong bitsPerPixel() { return CGImageGetBitsPerPixel (mImage); }
1086 ulong bytesPerLine() { return CGImageGetBytesPerRow (mImage); }
1087 ulong pixelFormat() { return mPixelFormat; };
1088 bool usesGuestVRAM() { return mBitmapData == NULL; }
1089
1090 const CGImageRef imageRef() const { return mImage; }
1091
1092 void paintEvent (QPaintEvent *pe);
1093 void resizeEvent (VBoxResizeEvent *re);
1094
1095private:
1096
1097 void clean();
1098
1099 uchar *mDataAddress;
1100 void *mBitmapData;
1101 ulong mPixelFormat;
1102 CGImageRef mImage;
1103 typedef struct
1104 {
1105 /** The size of this structure expressed in rcts entries. */
1106 ULONG allocated;
1107 /** The number of entries in the rcts array. */
1108 ULONG used;
1109 /** Variable sized array of the rectangle that makes up the region. */
1110 CGRect rcts[1];
1111 } RegionRects;
1112 /** The current valid region, all access is by atomic cmpxchg or atomic xchg.
1113 *
1114 * The protocol for updating and using this has to take into account that
1115 * the producer (SetVisibleRegion) and consumer (paintEvent) are running
1116 * on different threads. Therefore the producer will create a new RegionRects
1117 * structure before atomically replace the existing one. While the consumer
1118 * will read the value by atomically replace it by NULL, and then when its
1119 * done try restore it by cmpxchg. If the producer has already put a new
1120 * region there, it will be discarded (see mRegionUnused).
1121 */
1122 RegionRects volatile *mRegion;
1123 /** For keeping the unused region and thus avoid some RTMemAlloc/RTMemFree calls.
1124 * This is operated with atomic cmpxchg and atomic xchg. */
1125 RegionRects volatile *mRegionUnused;
1126};
1127
1128#endif /* Q_WS_MAC && VBOX_GUI_USE_QUARTZ2D */
1129
1130#endif // !___VBoxFrameBuffer_h___
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette