VirtualBox

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

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

video hw accel: overlay & flip fixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 35.5 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#endif
181 VBOX_SCRIPTABLE_DISPATCH_IMPL(IFramebuffer)
182
183 // IFramebuffer COM methods
184 STDMETHOD(COMGETTER(Address)) (BYTE **aAddress);
185 STDMETHOD(COMGETTER(Width)) (ULONG *aWidth);
186 STDMETHOD(COMGETTER(Height)) (ULONG *aHeight);
187 STDMETHOD(COMGETTER(BitsPerPixel)) (ULONG *aBitsPerPixel);
188 STDMETHOD(COMGETTER(BytesPerLine)) (ULONG *aBytesPerLine);
189 STDMETHOD(COMGETTER(PixelFormat)) (ULONG *aPixelFormat);
190 STDMETHOD(COMGETTER(UsesGuestVRAM)) (BOOL *aUsesGuestVRAM);
191 STDMETHOD(COMGETTER(HeightReduction)) (ULONG *aHeightReduction);
192 STDMETHOD(COMGETTER(Overlay)) (IFramebufferOverlay **aOverlay);
193 STDMETHOD(COMGETTER(WinId)) (ULONG64 *winId);
194
195 STDMETHOD(Lock)();
196 STDMETHOD(Unlock)();
197
198 STDMETHOD(RequestResize) (ULONG aScreenId, ULONG aPixelFormat,
199 BYTE *aVRAM, ULONG aBitsPerPixel, ULONG aBytesPerLine,
200 ULONG aWidth, ULONG aHeight,
201 BOOL *aFinished);
202
203 STDMETHOD(VideoModeSupported) (ULONG aWidth, ULONG aHeight, ULONG aBPP,
204 BOOL *aSupported);
205
206 STDMETHOD(GetVisibleRegion)(BYTE *aRectangles, ULONG aCount, ULONG *aCountCopied);
207 STDMETHOD(SetVisibleRegion)(BYTE *aRectangles, ULONG aCount);
208
209 STDMETHOD(ProcessVHWACommand)(BYTE *pCommand);
210
211 ulong width() { return mWdt; }
212 ulong height() { return mHgt; }
213
214 virtual ulong pixelFormat()
215 {
216 return FramebufferPixelFormat_FOURCC_RGB;
217 }
218
219 virtual bool usesGuestVRAM()
220 {
221 return false;
222 }
223
224 void lock() { RTCritSectEnter(&mCritSect); }
225 void unlock() { RTCritSectLeave(&mCritSect); }
226
227 virtual uchar *address() = 0;
228 virtual ulong bitsPerPixel() = 0;
229 virtual ulong bytesPerLine() = 0;
230
231 /**
232 * Called on the GUI thread (from VBoxConsoleView) when some part of the
233 * VM display viewport needs to be repainted on the host screen.
234 */
235 virtual void paintEvent (QPaintEvent *pe) = 0;
236
237 /**
238 * Called on the GUI thread (from VBoxConsoleView) after it gets a
239 * VBoxResizeEvent posted from the RequestResize() method implementation.
240 */
241 virtual void resizeEvent (VBoxResizeEvent *re)
242 {
243 mWdt = re->width();
244 mHgt = re->height();
245 }
246
247 /**
248 * Called on the GUI thread (from VBoxConsoleView) when the VM console
249 * window is moved.
250 */
251 virtual void moveEvent (QMoveEvent * /*me*/ ) {}
252
253#ifdef VBOX_WITH_VIDEOHWACCEL
254 /* this method is called from the GUI thread
255 * to perform the actual Video HW Acceleration command processing */
256 virtual void doProcessVHWACommand(struct _VBOXVHWACMD * pCommand);
257#endif
258
259protected:
260
261 VBoxConsoleView *mView;
262 RTCRITSECT mCritSect;
263 int mWdt;
264 int mHgt;
265 uint64_t mWinId;
266
267#if defined (Q_OS_WIN32)
268private:
269 long refcnt;
270#endif
271};
272
273/////////////////////////////////////////////////////////////////////////////
274
275#if defined (VBOX_GUI_USE_QIMAGE)
276
277class VBoxQImageFrameBuffer : public VBoxFrameBuffer
278{
279public:
280
281 VBoxQImageFrameBuffer (VBoxConsoleView *aView);
282
283 STDMETHOD(NotifyUpdate) (ULONG aX, ULONG aY,
284 ULONG aW, ULONG aH);
285
286 ulong pixelFormat() { return mPixelFormat; }
287 bool usesGuestVRAM() { return mUsesGuestVRAM; }
288
289 uchar *address() { return mImg.bits(); }
290 ulong bitsPerPixel() { return mImg.depth(); }
291 ulong bytesPerLine() { return mImg.bytesPerLine(); }
292
293 void paintEvent (QPaintEvent *pe);
294 void resizeEvent (VBoxResizeEvent *re);
295
296private:
297
298 QPixmap mPM;
299 QImage mImg;
300 ulong mPixelFormat;
301 bool mUsesGuestVRAM;
302};
303
304#endif
305
306/////////////////////////////////////////////////////////////////////////////
307
308#if defined (VBOX_GUI_USE_QGL)
309class VBoxVHWADirtyRect
310{
311public:
312 VBoxVHWADirtyRect() :
313 mIsClear(true)
314 {}
315
316 VBoxVHWADirtyRect(const QRect & aRect)
317 {
318 if(aRect.isEmpty())
319 {
320 mIsClear = false;
321 mRect = aRect;
322 }
323 else
324 {
325 mIsClear = true;
326 }
327 }
328
329 bool isClear() const { return mIsClear; }
330
331 void add(const QRect & aRect)
332 {
333 if(aRect.isEmpty())
334 return;
335
336 mRect = mIsClear ? aRect : mRect.united(aRect);
337 mIsClear = false;
338 }
339
340 void add(const VBoxVHWADirtyRect & aRect)
341 {
342 if(aRect.isClear())
343 return;
344 add(aRect.rect());
345 }
346
347 void set(const QRect & aRect)
348 {
349 if(aRect.isEmpty())
350 {
351 mIsClear = true;
352 }
353 else
354 {
355 mRect = aRect;
356 mIsClear = false;
357 }
358 }
359
360 void clear() { mIsClear = true; }
361
362 const QRect & rect() const {return mRect;}
363
364 bool intersects(const QRect & aRect) const {return mIsClear ? false : mRect.intersects(aRect);}
365
366 bool intersects(const VBoxVHWADirtyRect & aRect) const {return mIsClear ? false : aRect.intersects(mRect);}
367
368 QRect united(const QRect & aRect) const {return mIsClear ? aRect : aRect.united(mRect);}
369
370 bool contains(const QRect & aRect) const {return mIsClear ? false : aRect.contains(mRect);}
371
372 void subst(const VBoxVHWADirtyRect & aRect) { if(!mIsClear && aRect.contains(mRect)) clear(); }
373
374private:
375 QRect mRect;
376 bool mIsClear;
377};
378
379class VBoxVHWAColorKey
380{
381public:
382 VBoxVHWAColorKey() :
383 mUpper(0),
384 mLower(0)
385 {}
386
387 VBoxVHWAColorKey(uint32_t aUpper, uint32_t aLower) :
388 mUpper(aUpper),
389 mLower(aLower)
390 {}
391
392 uint32_t upper() const {return mUpper; }
393 uint32_t lower() const {return mLower; }
394
395 bool operator==(const VBoxVHWAColorKey & other) const { return mUpper == other.mUpper && mLower == other.mLower; }
396private:
397 uint32_t mUpper;
398 uint32_t mLower;
399};
400
401//class VBoxVHWAColorKeyRef
402//{
403//public:
404// VBoxVHWAColorKeyRef() : mValid(false){}
405//
406// bool isValid() {return mValid; }
407//
408// VBoxVHWAColorKey * ckey() { isVreturn mpCKey; }
409// const VBoxVHWAColorKey * constckey() const { return mpCKey; }
410//
411// void invalidate() { mValid = false; }
412// void set(VBoxVHWAColorKey * pKey) { mValid = false; }
413//
414//private:
415// VBoxVHWAColorKey * mpCKey;
416// bool mValid;
417//};
418
419class VBoxVHWAColorComponent
420{
421public:
422 VBoxVHWAColorComponent() :
423 mMask(0),
424 mRange(0),
425 mOffset(32),
426 mcBits(0)
427 {}
428
429 VBoxVHWAColorComponent(uint32_t aMask);
430
431 uint32_t mask() const { return mMask; }
432 uint32_t range() const { return mRange; }
433 uint32_t offset() const { return mOffset; }
434 uint32_t cBits() const { return mcBits; }
435 uint32_t colorVal(uint32_t col) const { return (col & mMask) >> mOffset; }
436 float colorValNorm(uint32_t col) const { return ((float)colorVal(col))/mRange; }
437private:
438 uint32_t mMask;
439 uint32_t mRange;
440 uint32_t mOffset;
441 uint32_t mcBits;
442};
443
444class VBoxVHWAColorFormat
445{
446public:
447
448// VBoxVHWAColorFormat(GLint aInternalFormat, GLenum aFormat, GLenum aType, uint32_t aDataFormat);
449 VBoxVHWAColorFormat(uint32_t bitsPerPixel, uint32_t r, uint32_t g, uint32_t b);
450
451 GLint internalFormat() const {return mInternalFormat; }
452 GLenum format() const {return mFormat; }
453 GLenum type() const {return mType; }
454 bool isValid() const {return mBitsPerPixel != 0; }
455 uint32_t dataFormat() const {return mDataFormat;}
456 uint32_t bitsPerPixel() const { return mBitsPerPixel; }
457 void pixel2Normalized(uint32_t pix, float *r, float *g, float *b) const;
458// uint32_t r(uint32_t pix);
459// uint32_t g(uint32_t pix);
460// uint32_t b(uint32_t pix);
461
462private:
463 void VBoxVHWAColorFormat::init(uint32_t bitsPerPixel, uint32_t r, uint32_t g, uint32_t b);
464
465 GLint mInternalFormat;
466 GLenum mFormat;
467 GLenum mType;
468 uint32_t mDataFormat;
469
470 uint32_t mBitsPerPixel;
471
472 VBoxVHWAColorComponent mR;
473 VBoxVHWAColorComponent mG;
474 VBoxVHWAColorComponent mB;
475};
476
477/* data flow:
478 * I. NON-Yinverted surface:
479 * 1.direct memory update (paint, lock/unlock):
480 * mem->tex->fb
481 * 2.blt
482 * srcTex->invFB->tex->fb
483 * |->mem
484 *
485 * II. Yinverted surface:
486 * 1.direct memory update (paint, lock/unlock):
487 * mem->tex->fb
488 * 2.blt
489 * srcTex->fb->tex
490 * |->mem
491 *
492 * III. flip support:
493 * 1. Yinverted<->NON-YInverted conversion :
494 * mem->tex-(rotate model view, force LAZY complete fb update)->invFB->tex
495 * fb-->| |->mem
496 * */
497class VBoxVHWASurfaceBase
498{
499public:
500 VBoxVHWASurfaceBase(class VBoxVHWAGlContextState *aState, bool aIsYInverted, const QSize * aSize, const QSize * aTargetSize,
501 VBoxVHWAColorFormat & aColorFormat,
502 VBoxVHWAColorKey * pSrcBltCKey, VBoxVHWAColorKey * pDstBltCKey,
503 VBoxVHWAColorKey * pSrcOverlayCKey, VBoxVHWAColorKey * pDstOverlayCKey);
504
505 virtual ~VBoxVHWASurfaceBase();
506
507 virtual void init(uchar *pvMem);
508
509 virtual void uninit();
510
511 static void globalInit();
512
513 int blt(const QRect * aDstRect, VBoxVHWASurfaceBase * aSrtSurface, const QRect * aSrcRect, const VBoxVHWAColorKey * pDstCKeyOverride, const VBoxVHWAColorKey * pSrcCKeyOverride);
514 int overlay(VBoxVHWASurfaceBase * aOverlaySurface);
515
516 virtual int lock(const QRect * pRect, uint32_t flags);
517
518 virtual int unlock();
519
520 void updatedMem(const QRect * aRect);
521
522 void performDisplay();
523
524 void setRects(const QRect * aTargRect, const QRect * aSrcRect);
525 void setTargetRectPosition(const QPoint * aPoint);
526
527 static ulong calcBytesPerPixel(GLenum format, GLenum type);
528
529 static GLsizei makePowerOf2(GLsizei val);
530
531 bool addressAlocated() const { return mFreeAddress; }
532 uchar * address(){ return mAddress; }
533 uchar * pointAddress(int x, int y) { return mAddress + y*mBytesPerLine + x*mBytesPerPixel; }
534 ulong memSize(){ return mBytesPerLine * mRect.height(); }
535
536 ulong width() { return mRect.width(); }
537 ulong height() { return mRect.height(); }
538
539 GLenum format() {return mColorFormat.format(); }
540 GLint internalFormat() { return mColorFormat.internalFormat(); }
541 GLenum type() { return mColorFormat.type(); }
542 uint32_t dataFormat() {return mColorFormat.dataFormat(); }
543
544 ulong bytesPerPixel() { return mBytesPerPixel; }
545 ulong bitsPerPixel() { return mColorFormat.bitsPerPixel(); }
546 ulong bytesPerLine() { return mBytesPerLine; }
547
548 const VBoxVHWAColorKey * dstBltCKey() const { return mpDstBltCKey; }
549 const VBoxVHWAColorKey * srcBltCKey() const { return mpSrcBltCKey; }
550 const VBoxVHWAColorKey * dstOverlayCKey() const { return mpDstOverlayCKey; }
551 const VBoxVHWAColorKey * defaultSrcOverlayCKey() const { return mpDefaultSrcOverlayCKey; }
552 const VBoxVHWAColorKey * defaultDstOverlayCKey() const { return mpDefaultDstOverlayCKey; }
553 const VBoxVHWAColorKey * srcOverlayCKey() const { return mpSrcOverlayCKey; }
554 void resetDefaultSrcOverlayCKey() { mpSrcOverlayCKey = mpDefaultSrcOverlayCKey; }
555 void resetDefaultDstOverlayCKey() { mpDstOverlayCKey = mpDefaultDstOverlayCKey; }
556
557 void setDstBltCKey(const VBoxVHWAColorKey * ckey)
558 {
559 if(ckey)
560 {
561 mDstBltCKey = *ckey;
562 mpDstBltCKey = &mDstBltCKey;
563 }
564 else
565 {
566 mpDstBltCKey = NULL;
567 }
568 }
569
570 void setSrcBltCKey(const VBoxVHWAColorKey * ckey)
571 {
572 if(ckey)
573 {
574 mSrcBltCKey = *ckey;
575 mpSrcBltCKey = &mSrcBltCKey;
576 }
577 else
578 {
579 mpSrcBltCKey = NULL;
580 }
581 }
582
583 void setDefaultDstOverlayCKey(const VBoxVHWAColorKey * ckey)
584 {
585 if(ckey)
586 {
587 mDefaultDstOverlayCKey = *ckey;
588 mpDefaultDstOverlayCKey = &mDefaultDstOverlayCKey;
589 }
590 else
591 {
592 mpDefaultDstOverlayCKey = NULL;
593 }
594 }
595
596 void setDefaultSrcOverlayCKey(const VBoxVHWAColorKey * ckey)
597 {
598 if(ckey)
599 {
600 mDefaultSrcOverlayCKey = *ckey;
601 mpDefaultSrcOverlayCKey = &mDefaultSrcOverlayCKey;
602 }
603 else
604 {
605 mpDefaultSrcOverlayCKey = NULL;
606 }
607 }
608
609 void setOverriddenDstOverlayCKey(const VBoxVHWAColorKey * ckey)
610 {
611 if(ckey)
612 {
613 mOverriddenDstOverlayCKey = *ckey;
614 mpDstOverlayCKey = &mOverriddenDstOverlayCKey;
615 }
616 else
617 {
618 mpDstOverlayCKey = NULL;
619 }
620 }
621
622 void setOverriddenSrcOverlayCKey(const VBoxVHWAColorKey * ckey)
623 {
624 if(ckey)
625 {
626 mOverriddenSrcOverlayCKey = *ckey;
627 mpSrcOverlayCKey = &mOverriddenSrcOverlayCKey;
628 }
629 else
630 {
631 mpSrcOverlayCKey = NULL;
632 }
633 }
634
635
636 const VBoxVHWAColorFormat & colorFormat() {return mColorFormat; }
637
638 /* clients should treat the returned texture as read-only */
639 GLuint textureSynched(const QRect * aRect) { synchTex(aRect); return mTexture; }
640
641 void setAddress(uchar * addr);
642
643 const QRect& rect() {return mRect;}
644
645// /* surface currently being displayed in a flip chain */
646// virtual bool isPrimary() = 0;
647// /* surface representing the main framebuffer. */
648// virtual bool isMainFramebuffer() = 0;
649 virtual void makeCurrent() = 0;
650 virtual void makeYInvertedCurrent() = 0;
651
652 bool isYInverted() {return mIsYInverted; }
653
654 bool isHidden() {return mIsHidden; }
655 void setHidden(bool hidden) { mIsHidden = hidden; }
656
657 int invert();
658
659 bool isFrontBuffer() {return !mIsYInverted; }
660
661// bool isOverlay() { return mIsOverlay; }
662
663#ifdef VBOX_WITH_VIDEOHWACCEL
664 virtual class VBoxVHWAGlProgramMngr * getGlProgramMngr() = 0;
665 static int setCKey(class VBoxVHWAGlProgramVHWA * pProgram, const VBoxVHWAColorFormat * pFormat, const VBoxVHWAColorKey * pCKey);
666#endif
667private:
668 void initDisplay();
669 void deleteDisplay();
670 void initDisplay(bool bInverted);
671 void deleteDisplay(bool bInverted);
672 GLuint createDisplay(bool bInverted);
673 void synchTex(const QRect * aRect);
674 void synchTexMem(const QRect * aRect);
675 void synchTexFB(const QRect * aRect);
676 void synchMem(const QRect * aRect);
677 void synchFB(const QRect * aRect);
678 void synch(const QRect * aRect);
679
680 int performBlt(const QRect * pDstRect, VBoxVHWASurfaceBase * pSrcSurface, const QRect * pSrcRect, const VBoxVHWAColorKey * pDstCKey, const VBoxVHWAColorKey * pSrcCKey, bool blt);
681
682// void doTex2FB(const QRect * aRect);
683 void doTex2FB(const QRect * pDstRect, const QRect * pSrcRect);
684
685 void doSetupMatrix(const QSize * pSize, bool bInverted);
686
687 QRect mRect; /* == Inv FB size */
688 QRect mTexRect; /* texture size */
689
690 QRect mSrcRect;
691 QRect mTargRect; /* == Vis FB size */
692 QRect mTargSize;
693
694 GLuint mYInvertedDisplay;
695 GLuint mVisibleDisplay;
696
697 bool mYInvertedDisplayInitialized;
698 bool mVisibleDisplayInitialized;
699
700 uchar * mAddress;
701 GLuint mTexture;
702
703 VBoxVHWAColorFormat mColorFormat;
704
705 VBoxVHWAColorKey *mpSrcBltCKey;
706 VBoxVHWAColorKey *mpDstBltCKey;
707 VBoxVHWAColorKey *mpSrcOverlayCKey;
708 VBoxVHWAColorKey *mpDstOverlayCKey;
709
710 VBoxVHWAColorKey *mpDefaultDstOverlayCKey;
711 VBoxVHWAColorKey *mpDefaultSrcOverlayCKey;
712
713 VBoxVHWAColorKey mSrcBltCKey;
714 VBoxVHWAColorKey mDstBltCKey;
715 VBoxVHWAColorKey mOverriddenSrcOverlayCKey;
716 VBoxVHWAColorKey mOverriddenDstOverlayCKey;
717 VBoxVHWAColorKey mDefaultDstOverlayCKey;
718 VBoxVHWAColorKey mDefaultSrcOverlayCKey;
719
720
721 GLenum mFormat;
722 GLint mInternalFormat;
723 GLenum mType;
724// ulong mDisplayWidth;
725// ulong mDisplayHeight;
726 ulong mBytesPerPixel;
727 ulong mBytesPerLine;
728
729 int mLockCount;
730 /* memory buffer not reflected in fm and texture, e.g if memory buffer is replaced or in case of lock/unlock */
731 VBoxVHWADirtyRect mUpdateMem2TexRect;
732 /* memory buffer not reflected in fm and texture, e.g if memory buffer is replaced or in case of lock/unlock */
733 VBoxVHWADirtyRect mUpdateTex2FBRect;
734 /*in case of blit we blit from another surface's texture, so our current texture gets durty */
735 VBoxVHWADirtyRect mUpdateFB2TexRect;
736 /*in case of blit the memory buffer does not get updated until we need it, e.g. for paint or lock operations */
737 VBoxVHWADirtyRect mUpdateFB2MemRect;
738
739 /* flag for lazy invert post-processing */
740 bool mInverted;
741
742 bool mFreeAddress;
743
744 bool mIsYInverted;
745
746 bool mIsHidden;
747
748// bool mIsOverlay;
749
750protected:
751 virtual void init(uchar *pvMem, bool bInverted);
752
753 class VBoxVHWAGlContextState *mState;
754
755};
756
757class VBoxVHWADisplay
758{
759public:
760 VBoxVHWADisplay() :
761 mSurfVGA(NULL),
762 mSurfPrimary(NULL)
763 {}
764
765 VBoxVHWASurfaceBase * setVGA(VBoxVHWASurfaceBase * pVga)
766 {
767 VBoxVHWASurfaceBase * old = mSurfVGA;
768 mSurfVGA = pVga;
769 mSurfPrimary = pVga;
770 mOverlays.clear();
771 return old;
772 }
773
774 VBoxVHWASurfaceBase * getVGA()
775 {
776 return mSurfVGA;
777 }
778
779 VBoxVHWASurfaceBase * getPrimary()
780 {
781 return mSurfPrimary;
782 }
783
784 void setPrimary(VBoxVHWASurfaceBase * pSurf)
785 {
786 mSurfPrimary = pSurf;
787 }
788
789 void addOverlay(VBoxVHWASurfaceBase * pSurf)
790 {
791 mOverlays.push_back(pSurf);
792 }
793
794 void checkAddOverlay(VBoxVHWASurfaceBase * pSurf)
795 {
796 if(!hasOverlay(pSurf))
797 addOverlay(pSurf);
798 }
799
800 bool hasOverlay(VBoxVHWASurfaceBase * pSurf)
801 {
802 for (OverlayList::iterator it = mOverlays.begin();
803 it != mOverlays.end(); ++ it)
804 {
805 if((*it) == pSurf)
806 {
807 return true;
808 }
809 }
810 return false;
811 }
812
813 void removeOverlay(VBoxVHWASurfaceBase * pSurf)
814 {
815 mOverlays.remove(pSurf);
816 }
817
818 void flip(VBoxVHWASurfaceBase * pTarg, VBoxVHWASurfaceBase * pCurr)
819 {
820 pCurr->invert();
821 pTarg->invert();
822 if(pCurr == mSurfPrimary) /* flip of the primary surface */
823 {
824 mSurfPrimary = pTarg;
825 }
826 else /* flip of the overlay */
827 {
828 for (OverlayList::iterator it = mOverlays.begin();
829 it != mOverlays.end(); ++ it)
830 {
831 if((*it) == pCurr)
832 {
833 (*it) = pTarg;
834 pCurr->setHidden(false);
835 break;
836 }
837 }
838 }
839 }
840
841 void performDisplay()
842 {
843 mSurfPrimary->performDisplay();
844
845 for (OverlayList::const_iterator it = mOverlays.begin();
846 it != mOverlays.end(); ++ it)
847 {
848 mSurfPrimary->overlay(*it);
849 }
850 }
851
852private:
853 VBoxVHWASurfaceBase *mSurfVGA;
854 VBoxVHWASurfaceBase *mSurfPrimary;
855
856 typedef std::list <VBoxVHWASurfaceBase*> OverlayList;
857
858 OverlayList mOverlays;
859};
860
861
862
863class VBoxVHWAGlContextState
864{
865public:
866 VBoxVHWAGlContextState() : mContext(NULL), mInverted(false) {}
867
868 void assertCurrent(class VBoxVHWASurfaceBase *aContext, bool bInverted)
869 {
870 mContext = aContext;
871 if(aContext && aContext->isYInverted())
872 {
873 mInverted = true;
874 }
875 else
876 {
877 mInverted = bInverted;
878 }
879 }
880
881 void makeYInvertedCurrent(class VBoxVHWASurfaceBase *aContext)
882 {
883 if(mContext != aContext)
884 {
885// aContext->makeCurrent();
886 aContext->makeYInvertedCurrent();
887 assertCurrent(aContext, true);
888 }
889 else
890 {
891 if(!aContext->isYInverted() && !mInverted)
892 {
893// aContext->makeCurrent();
894 aContext->makeYInvertedCurrent();
895 mInverted = true;
896 }
897 }
898 }
899
900 void makeCurrent(class VBoxVHWASurfaceBase *aContext)
901 {
902 if(mContext != aContext)
903 {
904 aContext->makeCurrent();
905 assertCurrent(aContext, false);
906 }
907 else
908 {
909 if(!aContext->isYInverted() && mInverted)
910 {
911 aContext->makeCurrent();
912 mInverted = false;
913 }
914 }
915 }
916
917 void makeCurrent(class VBoxVHWASurfaceBase *aContext, bool mInverted)
918 {
919 if(mInverted)
920 {
921 makeYInvertedCurrent(aContext);
922 }
923 else
924 {
925 makeCurrent(aContext);
926 }
927 }
928
929 class VBoxVHWASurfaceBase * getCurrent() {return mContext; }
930 bool isCurrentYInverted() {return mInverted; }
931
932private:
933
934 class VBoxVHWASurfaceBase *mContext;
935 bool mInverted;
936};
937
938class VBoxVHWASurfaceQGL : public VBoxVHWASurfaceBase
939{
940public:
941 VBoxVHWASurfaceQGL(class VBoxVHWAGlContextState *aState, const QSize * aSize, const QSize * aTargetSize,
942 VBoxVHWAColorFormat & aColorFormat,
943 VBoxVHWAColorKey * pSrcBltCKey, VBoxVHWAColorKey * pDstBltCKey,
944 VBoxVHWAColorKey * pSrcOverlayCKey, VBoxVHWAColorKey * pDstOverlayCKey,
945 class VBoxGLWidget *pWidget,
946 bool bInvisibleBuffer) :
947 VBoxVHWASurfaceBase(aState, bInvisibleBuffer, aSize, aTargetSize,
948 aColorFormat,
949 pSrcBltCKey, pDstBltCKey, pSrcOverlayCKey, pDstOverlayCKey),
950 mWidget(pWidget),
951 mBuffer(NULL)
952 {}
953
954 ~VBoxVHWASurfaceQGL();
955
956 void makeCurrent();
957 void makeYInvertedCurrent();
958
959 void init(uchar *pvMem);
960
961 void uninit();
962
963// int unlock()
964// {
965// int rc = VBoxVHWASurfaceBase::unlock();
966// if(!mBuffer)
967// performDisplay();
968// return rc;
969// }
970#ifdef VBOX_WITH_VIDEOHWACCEL
971 class VBoxVHWAGlProgramMngr * getGlProgramMngr();
972#endif
973private:
974 class VBoxGLWidget *mWidget;
975 class QGLPixelBuffer *mBuffer;
976protected:
977 virtual void init(uchar *pvMem, bool bInverted);
978};
979
980class VBoxGLWidget : public QGLWidget
981{
982public:
983 VBoxGLWidget (QWidget *aParent);
984 ~VBoxGLWidget();
985
986 ulong vboxPixelFormat() { return mPixelFormat; }
987 bool vboxUsesGuestVRAM() { return mUsesGuestVRAM; }
988
989 uchar *vboxAddress() { return mDisplay.getVGA() ? mDisplay.getVGA()->address() : NULL; }
990 uchar *vboxVRAMAddressFromOffset(uint64_t offset);
991 ulong vboxBitsPerPixel() { return mDisplay.getVGA()->bitsPerPixel(); }
992 ulong vboxBytesPerLine() { return mDisplay.getVGA() ? mDisplay.getVGA()->bytesPerLine() : NULL; }
993
994typedef void (VBoxGLWidget::*PFNVBOXQGLOP)(void* );
995//typedef FNVBOXQGLOP *PFNVBOXQGLOP;
996
997 void vboxPaintEvent (QPaintEvent *pe) {vboxPerformGLOp(&VBoxGLWidget::vboxDoPaint, pe);}
998 void vboxResizeEvent (VBoxResizeEvent *re) {vboxPerformGLOp(&VBoxGLWidget::vboxDoResize, re);}
999#ifdef DEBUG_misha
1000 void vboxTestSurfaces () {vboxPerformGLOp(&VBoxGLWidget::vboxDoTestSurfaces, NULL);}
1001#endif
1002#ifdef VBOX_WITH_VIDEOHWACCEL
1003 void vboxVHWACmd (struct _VBOXVHWACMD * pCmd) {vboxPerformGLOp(&VBoxGLWidget::vboxDoVHWACmd, pCmd);}
1004 class VBoxVHWAGlProgramMngr * vboxVHWAGetGlProgramMngr();
1005#endif
1006
1007 VBoxVHWASurfaceBase * vboxGetVGASurface() { return mDisplay.getVGA(); }
1008protected:
1009// void resizeGL (int height, int width);
1010
1011 void paintGL()
1012 {
1013 Assert(mState.getCurrent() == NULL);
1014 /* we are called with QGLWidget context */
1015 mState.assertCurrent(mDisplay.getVGA(), false);
1016 (this->*mpfnOp)(mOpContext);
1017 /* restore the context */
1018 mState.makeCurrent(mDisplay.getVGA());
1019 /* clear*/
1020 mState.assertCurrent(NULL, false);
1021 }
1022
1023 void initializeGL();
1024
1025private:
1026// void vboxDoInitDisplay();
1027// void vboxDoDeleteDisplay();
1028// void vboxDoPerformDisplay() { Assert(mDisplayInitialized); glCallList(mDisplay); }
1029 void vboxDoResize(void *re);
1030 void vboxDoPaint(void *rec);
1031#ifdef DEBUG_misha
1032 void vboxDoTestSurfaces(void *context);
1033#endif
1034#ifdef VBOX_WITH_VIDEOHWACCEL
1035 void vboxDoVHWACmd(void *cmd);
1036 void vboxCheckUpdateAddress (VBoxVHWASurfaceBase * pSurface, uint64_t offset)
1037 {
1038 if (pSurface->addressAlocated())
1039 {
1040 uchar * addr = vboxVRAMAddressFromOffset(offset);
1041 if(addr)
1042 {
1043 pSurface->setAddress(addr);
1044 }
1045 }
1046 }
1047 int vhwaSurfaceCanCreate(struct _VBOXVHWACMD_SURF_CANCREATE *pCmd);
1048 int vhwaSurfaceCreate(struct _VBOXVHWACMD_SURF_CREATE *pCmd);
1049 int vhwaSurfaceDestroy(struct _VBOXVHWACMD_SURF_DESTROY *pCmd);
1050 int vhwaSurfaceLock(struct _VBOXVHWACMD_SURF_LOCK *pCmd);
1051 int vhwaSurfaceUnlock(struct _VBOXVHWACMD_SURF_UNLOCK *pCmd);
1052 int vhwaSurfaceBlt(struct _VBOXVHWACMD_SURF_BLT *pCmd);
1053 int vhwaSurfaceFlip(struct _VBOXVHWACMD_SURF_FLIP *pCmd);
1054 int vhwaSurfaceOverlayUpdate(struct _VBOXVHWACMD_SURF_OVERLAY_UPDATE *pCmf);
1055 int vhwaSurfaceOverlaySetPosition(struct _VBOXVHWACMD_SURF_OVERLAY_SETPOSITION *pCmd);
1056 int vhwaSurfaceColorkeySet(struct _VBOXVHWACMD_SURF_COLORKEY_SET *pCmd);
1057 int vhwaQueryInfo1(struct _VBOXVHWACMD_QUERYINFO1 *pCmd);
1058 int vhwaQueryInfo2(struct _VBOXVHWACMD_QUERYINFO2 *pCmd);
1059#endif
1060
1061// VBoxVHWASurfaceQGL * pDisplay;
1062 VBoxVHWADisplay mDisplay;
1063
1064
1065 /* we need to do all opengl stuff in the paintGL context,
1066 * submit the operation to be performed */
1067 void vboxPerformGLOp(PFNVBOXQGLOP pfn, void* pContext) {mpfnOp = pfn; mOpContext = pContext; updateGL();}
1068
1069 PFNVBOXQGLOP mpfnOp;
1070 void *mOpContext;
1071
1072// ulong mBitsPerPixel;
1073 ulong mPixelFormat;
1074 bool mUsesGuestVRAM;
1075
1076 VBoxVHWAGlContextState mState;
1077
1078#ifdef VBOX_WITH_VIDEOHWACCEL
1079 class VBoxVHWAGlProgramMngr *mpMngr;
1080#endif
1081};
1082
1083
1084class VBoxQGLFrameBuffer : public VBoxFrameBuffer
1085{
1086public:
1087
1088 VBoxQGLFrameBuffer (VBoxConsoleView *aView);
1089
1090 STDMETHOD(NotifyUpdate) (ULONG aX, ULONG aY,
1091 ULONG aW, ULONG aH);
1092
1093#ifdef VBOX_WITH_VIDEOHWACCEL
1094 STDMETHOD(ProcessVHWACommand)(BYTE *pCommand);
1095#endif
1096
1097 ulong pixelFormat() { return vboxWidget()->vboxPixelFormat(); }
1098 bool usesGuestVRAM() { return vboxWidget()->vboxUsesGuestVRAM(); }
1099
1100 uchar *address() { return vboxWidget()->vboxAddress(); }
1101 ulong bitsPerPixel() { return vboxWidget()->vboxBitsPerPixel(); }
1102 ulong bytesPerLine() { return vboxWidget()->vboxBytesPerLine(); }
1103
1104 void paintEvent (QPaintEvent *pe);
1105 void resizeEvent (VBoxResizeEvent *re);
1106#ifdef VBOX_WITH_VIDEOHWACCEL
1107 void doProcessVHWACommand(struct _VBOXVHWACMD * pCommand);
1108#endif
1109
1110private:
1111// void vboxMakeCurrent();
1112 VBoxGLWidget * vboxWidget();
1113};
1114
1115
1116#endif
1117
1118/////////////////////////////////////////////////////////////////////////////
1119
1120#if defined (VBOX_GUI_USE_SDL)
1121
1122class VBoxSDLFrameBuffer : public VBoxFrameBuffer
1123{
1124public:
1125
1126 VBoxSDLFrameBuffer (VBoxConsoleView *aView);
1127 virtual ~VBoxSDLFrameBuffer();
1128
1129 STDMETHOD(NotifyUpdate) (ULONG aX, ULONG aY,
1130 ULONG aW, ULONG aH);
1131
1132 uchar *address()
1133 {
1134 SDL_Surface *surf = mSurfVRAM ? mSurfVRAM : mScreen;
1135 return surf ? (uchar *) (uintptr_t) surf->pixels : 0;
1136 }
1137
1138 ulong bitsPerPixel()
1139 {
1140 SDL_Surface *surf = mSurfVRAM ? mSurfVRAM : mScreen;
1141 return surf ? surf->format->BitsPerPixel : 0;
1142 }
1143
1144 ulong bytesPerLine()
1145 {
1146 SDL_Surface *surf = mSurfVRAM ? mSurfVRAM : mScreen;
1147 return surf ? surf->pitch : 0;
1148 }
1149
1150 ulong pixelFormat()
1151 {
1152 return mPixelFormat;
1153 }
1154
1155 bool usesGuestVRAM()
1156 {
1157 return mSurfVRAM != NULL;
1158 }
1159
1160 void paintEvent (QPaintEvent *pe);
1161 void resizeEvent (VBoxResizeEvent *re);
1162
1163private:
1164
1165 SDL_Surface *mScreen;
1166 SDL_Surface *mSurfVRAM;
1167
1168 ulong mPixelFormat;
1169};
1170
1171#endif
1172
1173/////////////////////////////////////////////////////////////////////////////
1174
1175#if defined (VBOX_GUI_USE_DDRAW)
1176
1177class VBoxDDRAWFrameBuffer : public VBoxFrameBuffer
1178{
1179public:
1180
1181 VBoxDDRAWFrameBuffer (VBoxConsoleView *aView);
1182 virtual ~VBoxDDRAWFrameBuffer();
1183
1184 STDMETHOD(NotifyUpdate) (ULONG aX, ULONG aY,
1185 ULONG aW, ULONG aH);
1186
1187 uchar *address() { return (uchar *) mSurfaceDesc.lpSurface; }
1188 ulong bitsPerPixel() { return mSurfaceDesc.ddpfPixelFormat.dwRGBBitCount; }
1189 ulong bytesPerLine() { return (ulong) mSurfaceDesc.lPitch; }
1190
1191 ulong pixelFormat() { return mPixelFormat; };
1192
1193 bool usesGuestVRAM() { return mUsesGuestVRAM; }
1194
1195 void paintEvent (QPaintEvent *pe);
1196 void resizeEvent (VBoxResizeEvent *re);
1197 void moveEvent (QMoveEvent *me);
1198
1199private:
1200
1201 void releaseObjects();
1202
1203 bool createSurface (ULONG aPixelFormat, uchar *pvVRAM,
1204 ULONG aBitsPerPixel, ULONG aBytesPerLine,
1205 ULONG aWidth, ULONG aHeight);
1206 void deleteSurface();
1207 void drawRect (ULONG x, ULONG y, ULONG w, ULONG h);
1208 void getWindowPosition (void);
1209
1210 LPDIRECTDRAW7 mDDRAW;
1211 LPDIRECTDRAWCLIPPER mClipper;
1212 LPDIRECTDRAWSURFACE7 mSurface;
1213 DDSURFACEDESC2 mSurfaceDesc;
1214 LPDIRECTDRAWSURFACE7 mPrimarySurface;
1215
1216 ulong mPixelFormat;
1217
1218 bool mUsesGuestVRAM;
1219
1220 int mWndX;
1221 int mWndY;
1222
1223 bool mSynchronousUpdates;
1224};
1225
1226#endif
1227
1228/////////////////////////////////////////////////////////////////////////////
1229
1230#if defined (Q_WS_MAC) && defined (VBOX_GUI_USE_QUARTZ2D)
1231
1232#include <Carbon/Carbon.h>
1233
1234class VBoxQuartz2DFrameBuffer : public VBoxFrameBuffer
1235{
1236public:
1237
1238 VBoxQuartz2DFrameBuffer (VBoxConsoleView *aView);
1239 virtual ~VBoxQuartz2DFrameBuffer ();
1240
1241 STDMETHOD (NotifyUpdate) (ULONG aX, ULONG aY,
1242 ULONG aW, ULONG aH);
1243 STDMETHOD (SetVisibleRegion) (BYTE *aRectangles, ULONG aCount);
1244
1245 uchar *address() { return mDataAddress; }
1246 ulong bitsPerPixel() { return CGImageGetBitsPerPixel (mImage); }
1247 ulong bytesPerLine() { return CGImageGetBytesPerRow (mImage); }
1248 ulong pixelFormat() { return mPixelFormat; };
1249 bool usesGuestVRAM() { return mBitmapData == NULL; }
1250
1251 const CGImageRef imageRef() const { return mImage; }
1252
1253 void paintEvent (QPaintEvent *pe);
1254 void resizeEvent (VBoxResizeEvent *re);
1255
1256private:
1257
1258 void clean();
1259
1260 uchar *mDataAddress;
1261 void *mBitmapData;
1262 ulong mPixelFormat;
1263 CGImageRef mImage;
1264 typedef struct
1265 {
1266 /** The size of this structure expressed in rcts entries. */
1267 ULONG allocated;
1268 /** The number of entries in the rcts array. */
1269 ULONG used;
1270 /** Variable sized array of the rectangle that makes up the region. */
1271 CGRect rcts[1];
1272 } RegionRects;
1273 /** The current valid region, all access is by atomic cmpxchg or atomic xchg.
1274 *
1275 * The protocol for updating and using this has to take into account that
1276 * the producer (SetVisibleRegion) and consumer (paintEvent) are running
1277 * on different threads. Therefore the producer will create a new RegionRects
1278 * structure before atomically replace the existing one. While the consumer
1279 * will read the value by atomically replace it by NULL, and then when its
1280 * done try restore it by cmpxchg. If the producer has already put a new
1281 * region there, it will be discarded (see mRegionUnused).
1282 */
1283 RegionRects volatile *mRegion;
1284 /** For keeping the unused region and thus avoid some RTMemAlloc/RTMemFree calls.
1285 * This is operated with atomic cmpxchg and atomic xchg. */
1286 RegionRects volatile *mRegionUnused;
1287};
1288
1289#endif /* Q_WS_MAC && VBOX_GUI_USE_QUARTZ2D */
1290
1291#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