VirtualBox

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

Last change on this file since 21470 was 21414, checked in by vboxsync, 16 years ago

video hw accel: basis for overlay impl in QGLFramebuffer, bugfixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 31.7 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, const QSize * aSize, const QSize * aTargetSize,
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 void setRects(const QRect * aTargRect, const QRect * aSrcRect);
520 void setTargetRectPosition(const QPoint * aPoint);
521
522 static ulong calcBytesPerPixel(GLenum format, GLenum type);
523
524 static GLsizei makePowerOf2(GLsizei val);
525
526 bool addressAlocated() const { return mFreeAddress; }
527 uchar * address(){ return mAddress; }
528 uchar * pointAddress(int x, int y) { return mAddress + y*mBytesPerLine + x*mBytesPerPixel; }
529 ulong memSize(){ return mBytesPerLine * mRect.height(); }
530
531 ulong width() { return mRect.width(); }
532 ulong height() { return mRect.height(); }
533
534 GLenum format() {return mColorFormat.format(); }
535 GLint internalFormat() { return mColorFormat.internalFormat(); }
536 GLenum type() { return mColorFormat.type(); }
537 uint32_t dataFormat() {return mColorFormat.dataFormat(); }
538
539 ulong bytesPerPixel() { return mBytesPerPixel; }
540 ulong bitsPerPixel() { return mColorFormat.bitsPerPixel(); }
541 ulong bytesPerLine() { return mBytesPerLine; }
542
543 const VBoxVHWAColorKey * dstBltCKey() { return mDstBltCKeyValid ? &mDstBltCKey : NULL; }
544 const VBoxVHWAColorKey * srcBltCKey() { return mSrcBltCKeyValid ? &mSrcBltCKey : NULL; }
545 const VBoxVHWAColorKey * dstOverlayCKey() { return mDstOverlayCKeyValid ? &mDstOverlayCKey : NULL; }
546 const VBoxVHWAColorKey * srcOverlayCKey() { return mSrcOverlayCKeyValid ? &mSrcOverlayCKey : NULL; }
547 const VBoxVHWAColorFormat & colorFormat() {return mColorFormat; }
548
549 /* clients should treat the returned texture as read-only */
550 GLuint textureSynched(const QRect * aRect) { synchTex(aRect); return mTexture; }
551
552 void setAddress(uchar * addr);
553
554 const QRect& rect() {return mRect;}
555
556// /* surface currently being displayed in a flip chain */
557// virtual bool isPrimary() = 0;
558// /* surface representing the main framebuffer. */
559// virtual bool isMainFramebuffer() = 0;
560 virtual void makeCurrent() = 0;
561 virtual void makeYInvertedCurrent() = 0;
562
563 bool isYInverted() {return mIsYInverted; }
564
565 int invert();
566
567 bool isFrontBuffer() {return !mIsYInverted; }
568
569// bool isOverlay() { return mIsOverlay; }
570
571#ifdef VBOX_WITH_VIDEOHWACCEL
572 virtual class VBoxVHWAGlProgramMngr * getGlProgramMngr() = 0;
573 static int setCKey(class VBoxVHWAGlProgramVHWA * pProgram, const VBoxVHWAColorFormat * pFormat, const VBoxVHWAColorKey * pCKey);
574#endif
575private:
576 void initDisplay();
577 void deleteDisplay();
578 void initDisplay(bool bInverted);
579 void deleteDisplay(bool bInverted);
580 GLuint createDisplay(bool bInverted);
581 void synchTex(const QRect * aRect);
582 void synchTexMem(const QRect * aRect);
583 void synchTexFB(const QRect * aRect);
584 void synchMem(const QRect * aRect);
585 void synchFB(const QRect * aRect);
586 void synch(const QRect * aRect);
587
588// void doTex2FB(const QRect * aRect);
589 void doTex2FB(const QRect * pDstRect, const QRect * pSrcRect);
590
591 void doSetupMatrix(const QSize * pSize, bool bInverted);
592
593 QRect mRect; /* == Inv FB size */
594 QRect mTexRect; /* texture size */
595
596 QRect mSrcRect;
597 QRect mTargRect; /* == Vis FB size */
598 QRect mTargSize;
599
600 GLuint mYInvertedDisplay;
601 GLuint mVisibleDisplay;
602
603 bool mYInvertedDisplayInitialized;
604 bool mVisibleDisplayInitialized;
605
606 uchar * mAddress;
607 GLuint mTexture;
608
609 VBoxVHWAColorFormat mColorFormat;
610 VBoxVHWAColorKey mSrcBltCKey;
611 VBoxVHWAColorKey mDstBltCKey;
612 VBoxVHWAColorKey mSrcOverlayCKey;
613 VBoxVHWAColorKey mDstOverlayCKey;
614 bool mSrcBltCKeyValid;
615 bool mDstBltCKeyValid;
616 bool mSrcOverlayCKeyValid;
617 bool mDstOverlayCKeyValid;
618 GLenum mFormat;
619 GLint mInternalFormat;
620 GLenum mType;
621// ulong mDisplayWidth;
622// ulong mDisplayHeight;
623 ulong mBytesPerPixel;
624 ulong mBytesPerLine;
625
626 int mLockCount;
627 /* memory buffer not reflected in fm and texture, e.g if memory buffer is replaced or in case of lock/unlock */
628 VBoxVHWADirtyRect mUpdateMem2TexRect;
629 /* memory buffer not reflected in fm and texture, e.g if memory buffer is replaced or in case of lock/unlock */
630 VBoxVHWADirtyRect mUpdateTex2FBRect;
631 /*in case of blit we blit from another surface's texture, so our current texture gets durty */
632 VBoxVHWADirtyRect mUpdateFB2TexRect;
633 /*in case of blit the memory buffer does not get updated until we need it, e.g. for paint or lock operations */
634 VBoxVHWADirtyRect mUpdateFB2MemRect;
635
636 /* flag for lazy invert post-processing */
637 bool mInverted;
638
639 bool mFreeAddress;
640
641 bool mIsYInverted;
642
643// bool mIsOverlay;
644
645protected:
646 virtual void init(uchar *pvMem, bool bInverted);
647
648 class VBoxVHWAGlContextState *mState;
649
650};
651
652class VBoxVHWADisplay
653{
654public:
655 VBoxVHWADisplay() :
656 mSurfVGA(NULL),
657 mSurfPrimary(NULL)
658 {}
659
660 VBoxVHWASurfaceBase * setVGA(VBoxVHWASurfaceBase * pVga)
661 {
662 VBoxVHWASurfaceBase * old = mSurfVGA;
663 mSurfVGA = pVga;
664 mSurfPrimary = pVga;
665 mOverlays.clear();
666 return old;
667 }
668
669 VBoxVHWASurfaceBase * getVGA()
670 {
671 return mSurfVGA;
672 }
673
674 void setPrimary(VBoxVHWASurfaceBase * pSurf)
675 {
676 mSurfPrimary = pSurf;
677 }
678
679 void addOverlay(VBoxVHWASurfaceBase * pSurf)
680 {
681 mOverlays.push_back(pSurf);
682 }
683
684 void removeOverlay(VBoxVHWASurfaceBase * pSurf)
685 {
686 mOverlays.remove(pSurf);
687 }
688
689 void flip(VBoxVHWASurfaceBase * pTarg, VBoxVHWASurfaceBase * pCurr)
690 {
691 pCurr->invert();
692 pTarg->invert();
693 if(pCurr == mSurfPrimary) /* flip of the primary surface */
694 {
695 mSurfPrimary = pTarg;
696 }
697 else /* flip of the overlay */
698 {
699 for (OverlayList::iterator it = mOverlays.begin();
700 it != mOverlays.end(); ++ it)
701 {
702 if((*it) == pCurr)
703 {
704 (*it) = pTarg;
705 }
706 }
707 }
708 }
709
710 void performDisplay()
711 {
712 mSurfPrimary->performDisplay();
713
714 for (OverlayList::const_iterator it = mOverlays.begin();
715 it != mOverlays.end(); ++ it)
716 {
717 (*it)->performDisplay();
718 }
719 }
720
721private:
722 VBoxVHWASurfaceBase *mSurfVGA;
723 VBoxVHWASurfaceBase *mSurfPrimary;
724
725 typedef std::list <VBoxVHWASurfaceBase*> OverlayList;
726
727 OverlayList mOverlays;
728};
729
730
731
732class VBoxVHWAGlContextState
733{
734public:
735 VBoxVHWAGlContextState() : mContext(NULL), mInverted(false) {}
736
737 void assertCurrent(class VBoxVHWASurfaceBase *aContext, bool bInverted)
738 {
739 mContext = aContext;
740 if(aContext && aContext->isYInverted())
741 {
742 mInverted = true;
743 }
744 else
745 {
746 mInverted = bInverted;
747 }
748 }
749
750 void makeYInvertedCurrent(class VBoxVHWASurfaceBase *aContext)
751 {
752 if(mContext != aContext)
753 {
754// aContext->makeCurrent();
755 aContext->makeYInvertedCurrent();
756 assertCurrent(aContext, true);
757 }
758 else
759 {
760 if(!aContext->isYInverted() && !mInverted)
761 {
762// aContext->makeCurrent();
763 aContext->makeYInvertedCurrent();
764 mInverted = true;
765 }
766 }
767 }
768
769 void makeCurrent(class VBoxVHWASurfaceBase *aContext)
770 {
771 if(mContext != aContext)
772 {
773 aContext->makeCurrent();
774 assertCurrent(aContext, false);
775 }
776 else
777 {
778 if(!aContext->isYInverted() && mInverted)
779 {
780 aContext->makeCurrent();
781 mInverted = false;
782 }
783 }
784 }
785
786 class VBoxVHWASurfaceBase * getCurrent() {return mContext; }
787 bool isCurrentYInverted() {return mInverted; }
788
789private:
790
791 class VBoxVHWASurfaceBase *mContext;
792 bool mInverted;
793};
794
795class VBoxVHWASurfaceQGL : public VBoxVHWASurfaceBase
796{
797public:
798 VBoxVHWASurfaceQGL(class VBoxVHWAGlContextState *aState, const QSize * aSize, const QSize * aTargetSize,
799 VBoxVHWAColorFormat & aColorFormat,
800 VBoxVHWAColorKey * pSrcBltCKey, VBoxVHWAColorKey * pDstBltCKey,
801 VBoxVHWAColorKey * pSrcOverlayCKey, VBoxVHWAColorKey * pDstOverlayCKey,
802 class VBoxGLWidget *pWidget,
803 bool bInvisibleBuffer) :
804 VBoxVHWASurfaceBase(aState, bInvisibleBuffer, aSize, aTargetSize,
805 aColorFormat,
806 pSrcBltCKey, pDstBltCKey, pSrcOverlayCKey, pDstOverlayCKey),
807 mWidget(pWidget),
808 mBuffer(NULL)
809 {}
810
811 ~VBoxVHWASurfaceQGL();
812
813 void makeCurrent();
814 void makeYInvertedCurrent();
815
816 void init(uchar *pvMem);
817
818 void uninit();
819
820// int unlock()
821// {
822// int rc = VBoxVHWASurfaceBase::unlock();
823// if(!mBuffer)
824// performDisplay();
825// return rc;
826// }
827#ifdef VBOX_WITH_VIDEOHWACCEL
828 class VBoxVHWAGlProgramMngr * getGlProgramMngr();
829#endif
830private:
831 class VBoxGLWidget *mWidget;
832 class QGLPixelBuffer *mBuffer;
833protected:
834 virtual void init(uchar *pvMem, bool bInverted);
835};
836
837class VBoxGLWidget : public QGLWidget
838{
839public:
840 VBoxGLWidget (QWidget *aParent);
841 ~VBoxGLWidget();
842
843 ulong vboxPixelFormat() { return mPixelFormat; }
844 bool vboxUsesGuestVRAM() { return mUsesGuestVRAM; }
845
846 uchar *vboxAddress() { return mDisplay.getVGA() ? mDisplay.getVGA()->address() : NULL; }
847 uchar *vboxVRAMAddressFromOffset(uint64_t offset);
848 ulong vboxBitsPerPixel() { return mDisplay.getVGA()->bitsPerPixel(); }
849 ulong vboxBytesPerLine() { return mDisplay.getVGA() ? mDisplay.getVGA()->bytesPerLine() : NULL; }
850
851typedef void (VBoxGLWidget::*PFNVBOXQGLOP)(void* );
852//typedef FNVBOXQGLOP *PFNVBOXQGLOP;
853
854 void vboxPaintEvent (QPaintEvent *pe) {vboxPerformGLOp(&VBoxGLWidget::vboxDoPaint, pe);}
855 void vboxResizeEvent (VBoxResizeEvent *re) {vboxPerformGLOp(&VBoxGLWidget::vboxDoResize, re);}
856#ifdef DEBUG_misha
857 void vboxTestSurfaces () {vboxPerformGLOp(&VBoxGLWidget::vboxDoTestSurfaces, NULL);}
858#endif
859#ifdef VBOX_WITH_VIDEOHWACCEL
860 void vboxVHWACmd (struct _VBOXVHWACMD * pCmd) {vboxPerformGLOp(&VBoxGLWidget::vboxDoVHWACmd, pCmd);}
861 class VBoxVHWAGlProgramMngr * vboxVHWAGetGlProgramMngr();
862#endif
863
864 VBoxVHWASurfaceBase * vboxGetVGASurface() { return mDisplay.getVGA(); }
865protected:
866// void resizeGL (int height, int width);
867
868 void paintGL()
869 {
870 Assert(mState.getCurrent() == NULL);
871 /* we are called with QGLWidget context */
872 mState.assertCurrent(mDisplay.getVGA(), false);
873 (this->*mpfnOp)(mOpContext);
874 /* restore the context */
875 mState.makeCurrent(mDisplay.getVGA());
876 /* clear*/
877 mState.assertCurrent(NULL, false);
878 }
879
880 void initializeGL();
881
882private:
883// void vboxDoInitDisplay();
884// void vboxDoDeleteDisplay();
885// void vboxDoPerformDisplay() { Assert(mDisplayInitialized); glCallList(mDisplay); }
886 void vboxDoResize(void *re);
887 void vboxDoPaint(void *rec);
888#ifdef DEBUG_misha
889 void vboxDoTestSurfaces(void *context);
890#endif
891#ifdef VBOX_WITH_VIDEOHWACCEL
892 void vboxDoVHWACmd(void *cmd);
893 void vboxCheckUpdateAddress (VBoxVHWASurfaceBase * pSurface, uint64_t offset)
894 {
895 if (pSurface->addressAlocated())
896 {
897 uchar * addr = vboxVRAMAddressFromOffset(offset);
898 if(addr)
899 {
900 pSurface->setAddress(addr);
901 }
902 }
903 }
904 int vhwaSurfaceCanCreate(struct _VBOXVHWACMD_SURF_CANCREATE *pCmd);
905 int vhwaSurfaceCreate(struct _VBOXVHWACMD_SURF_CREATE *pCmd);
906 int vhwaSurfaceDestroy(struct _VBOXVHWACMD_SURF_DESTROY *pCmd);
907 int vhwaSurfaceLock(struct _VBOXVHWACMD_SURF_LOCK *pCmd);
908 int vhwaSurfaceUnlock(struct _VBOXVHWACMD_SURF_UNLOCK *pCmd);
909 int vhwaSurfaceBlt(struct _VBOXVHWACMD_SURF_BLT *pCmd);
910 int vhwaSurfaceFlip(struct _VBOXVHWACMD_SURF_FLIP *pCmd);
911 int vhwaQueryInfo1(struct _VBOXVHWACMD_QUERYINFO1 *pCmd);
912 int vhwaQueryInfo2(struct _VBOXVHWACMD_QUERYINFO2 *pCmd);
913#endif
914
915// VBoxVHWASurfaceQGL * pDisplay;
916 VBoxVHWADisplay mDisplay;
917
918
919 /* we need to do all opengl stuff in the paintGL context,
920 * submit the operation to be performed */
921 void vboxPerformGLOp(PFNVBOXQGLOP pfn, void* pContext) {mpfnOp = pfn; mOpContext = pContext; updateGL();}
922
923 PFNVBOXQGLOP mpfnOp;
924 void *mOpContext;
925
926// ulong mBitsPerPixel;
927 ulong mPixelFormat;
928 bool mUsesGuestVRAM;
929
930 VBoxVHWAGlContextState mState;
931
932#ifdef VBOX_WITH_VIDEOHWACCEL
933 class VBoxVHWAGlProgramMngr *mpMngr;
934#endif
935};
936
937
938class VBoxQGLFrameBuffer : public VBoxFrameBuffer
939{
940public:
941
942 VBoxQGLFrameBuffer (VBoxConsoleView *aView);
943
944 STDMETHOD(NotifyUpdate) (ULONG aX, ULONG aY,
945 ULONG aW, ULONG aH);
946
947#ifdef VBOX_WITH_VIDEOHWACCEL
948 STDMETHOD(ProcessVHWACommand)(BYTE *pCommand);
949#endif
950
951 ulong pixelFormat() { return vboxWidget()->vboxPixelFormat(); }
952 bool usesGuestVRAM() { return vboxWidget()->vboxUsesGuestVRAM(); }
953
954 uchar *address() { return vboxWidget()->vboxAddress(); }
955 ulong bitsPerPixel() { return vboxWidget()->vboxBitsPerPixel(); }
956 ulong bytesPerLine() { return vboxWidget()->vboxBytesPerLine(); }
957
958 void paintEvent (QPaintEvent *pe);
959 void resizeEvent (VBoxResizeEvent *re);
960#ifdef VBOX_WITH_VIDEOHWACCEL
961 void doProcessVHWACommand(struct _VBOXVHWACMD * pCommand);
962#endif
963
964private:
965// void vboxMakeCurrent();
966 VBoxGLWidget * vboxWidget();
967};
968
969
970#endif
971
972/////////////////////////////////////////////////////////////////////////////
973
974#if defined (VBOX_GUI_USE_SDL)
975
976class VBoxSDLFrameBuffer : public VBoxFrameBuffer
977{
978public:
979
980 VBoxSDLFrameBuffer (VBoxConsoleView *aView);
981 virtual ~VBoxSDLFrameBuffer();
982
983 STDMETHOD(NotifyUpdate) (ULONG aX, ULONG aY,
984 ULONG aW, ULONG aH);
985
986 uchar *address()
987 {
988 SDL_Surface *surf = mSurfVRAM ? mSurfVRAM : mScreen;
989 return surf ? (uchar *) (uintptr_t) surf->pixels : 0;
990 }
991
992 ulong bitsPerPixel()
993 {
994 SDL_Surface *surf = mSurfVRAM ? mSurfVRAM : mScreen;
995 return surf ? surf->format->BitsPerPixel : 0;
996 }
997
998 ulong bytesPerLine()
999 {
1000 SDL_Surface *surf = mSurfVRAM ? mSurfVRAM : mScreen;
1001 return surf ? surf->pitch : 0;
1002 }
1003
1004 ulong pixelFormat()
1005 {
1006 return mPixelFormat;
1007 }
1008
1009 bool usesGuestVRAM()
1010 {
1011 return mSurfVRAM != NULL;
1012 }
1013
1014 void paintEvent (QPaintEvent *pe);
1015 void resizeEvent (VBoxResizeEvent *re);
1016
1017private:
1018
1019 SDL_Surface *mScreen;
1020 SDL_Surface *mSurfVRAM;
1021
1022 ulong mPixelFormat;
1023};
1024
1025#endif
1026
1027/////////////////////////////////////////////////////////////////////////////
1028
1029#if defined (VBOX_GUI_USE_DDRAW)
1030
1031class VBoxDDRAWFrameBuffer : public VBoxFrameBuffer
1032{
1033public:
1034
1035 VBoxDDRAWFrameBuffer (VBoxConsoleView *aView);
1036 virtual ~VBoxDDRAWFrameBuffer();
1037
1038 STDMETHOD(NotifyUpdate) (ULONG aX, ULONG aY,
1039 ULONG aW, ULONG aH);
1040
1041 uchar *address() { return (uchar *) mSurfaceDesc.lpSurface; }
1042 ulong bitsPerPixel() { return mSurfaceDesc.ddpfPixelFormat.dwRGBBitCount; }
1043 ulong bytesPerLine() { return (ulong) mSurfaceDesc.lPitch; }
1044
1045 ulong pixelFormat() { return mPixelFormat; };
1046
1047 bool usesGuestVRAM() { return mUsesGuestVRAM; }
1048
1049 void paintEvent (QPaintEvent *pe);
1050 void resizeEvent (VBoxResizeEvent *re);
1051 void moveEvent (QMoveEvent *me);
1052
1053private:
1054
1055 void releaseObjects();
1056
1057 bool createSurface (ULONG aPixelFormat, uchar *pvVRAM,
1058 ULONG aBitsPerPixel, ULONG aBytesPerLine,
1059 ULONG aWidth, ULONG aHeight);
1060 void deleteSurface();
1061 void drawRect (ULONG x, ULONG y, ULONG w, ULONG h);
1062 void getWindowPosition (void);
1063
1064 LPDIRECTDRAW7 mDDRAW;
1065 LPDIRECTDRAWCLIPPER mClipper;
1066 LPDIRECTDRAWSURFACE7 mSurface;
1067 DDSURFACEDESC2 mSurfaceDesc;
1068 LPDIRECTDRAWSURFACE7 mPrimarySurface;
1069
1070 ulong mPixelFormat;
1071
1072 bool mUsesGuestVRAM;
1073
1074 int mWndX;
1075 int mWndY;
1076
1077 bool mSynchronousUpdates;
1078};
1079
1080#endif
1081
1082/////////////////////////////////////////////////////////////////////////////
1083
1084#if defined (Q_WS_MAC) && defined (VBOX_GUI_USE_QUARTZ2D)
1085
1086#include <Carbon/Carbon.h>
1087
1088class VBoxQuartz2DFrameBuffer : public VBoxFrameBuffer
1089{
1090public:
1091
1092 VBoxQuartz2DFrameBuffer (VBoxConsoleView *aView);
1093 virtual ~VBoxQuartz2DFrameBuffer ();
1094
1095 STDMETHOD (NotifyUpdate) (ULONG aX, ULONG aY,
1096 ULONG aW, ULONG aH);
1097 STDMETHOD (SetVisibleRegion) (BYTE *aRectangles, ULONG aCount);
1098
1099 uchar *address() { return mDataAddress; }
1100 ulong bitsPerPixel() { return CGImageGetBitsPerPixel (mImage); }
1101 ulong bytesPerLine() { return CGImageGetBytesPerRow (mImage); }
1102 ulong pixelFormat() { return mPixelFormat; };
1103 bool usesGuestVRAM() { return mBitmapData == NULL; }
1104
1105 const CGImageRef imageRef() const { return mImage; }
1106
1107 void paintEvent (QPaintEvent *pe);
1108 void resizeEvent (VBoxResizeEvent *re);
1109
1110private:
1111
1112 void clean();
1113
1114 uchar *mDataAddress;
1115 void *mBitmapData;
1116 ulong mPixelFormat;
1117 CGImageRef mImage;
1118 typedef struct
1119 {
1120 /** The size of this structure expressed in rcts entries. */
1121 ULONG allocated;
1122 /** The number of entries in the rcts array. */
1123 ULONG used;
1124 /** Variable sized array of the rectangle that makes up the region. */
1125 CGRect rcts[1];
1126 } RegionRects;
1127 /** The current valid region, all access is by atomic cmpxchg or atomic xchg.
1128 *
1129 * The protocol for updating and using this has to take into account that
1130 * the producer (SetVisibleRegion) and consumer (paintEvent) are running
1131 * on different threads. Therefore the producer will create a new RegionRects
1132 * structure before atomically replace the existing one. While the consumer
1133 * will read the value by atomically replace it by NULL, and then when its
1134 * done try restore it by cmpxchg. If the producer has already put a new
1135 * region there, it will be discarded (see mRegionUnused).
1136 */
1137 RegionRects volatile *mRegion;
1138 /** For keeping the unused region and thus avoid some RTMemAlloc/RTMemFree calls.
1139 * This is operated with atomic cmpxchg and atomic xchg. */
1140 RegionRects volatile *mRegionUnused;
1141};
1142
1143#endif /* Q_WS_MAC && VBOX_GUI_USE_QUARTZ2D */
1144
1145#endif // !___VBoxFrameBuffer_h___
Note: See TracBrowser for help on using the repository browser.

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