VirtualBox

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

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

View HW Accel: guest ddraw command definitions, moved opengl framebuffer impl to a separate file

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 16.4 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)
325
326class VBoxGLWidget : public QGLWidget
327{
328public:
329 VBoxGLWidget (QWidget *aParent)
330 : QGLWidget (aParent),
331 mRe(NULL),
332 mpIntersectionRect(NULL),
333 mDisplay(0),
334 mDisplayInitialized(false),
335 mAddress(NULL),
336 mTexture(0),
337 mFormat(0),
338 mInternalFormat(0),
339 mType(0),
340 mBitsPerPixel(0),
341 mBytesPerPixel(0),
342 mBytesPerLine(0),
343 mPixelFormat(0),
344 mUsesGuestVRAM(false),
345 mDisplayWidth(0),
346 mDisplayHeight(0)
347 {
348// Assert(0);
349 /* No need for background drawing */
350// setAttribute (Qt::WA_OpaquePaintEvent);
351 }
352
353 ulong vboxPixelFormat() { return mPixelFormat; }
354 bool vboxUsesGuestVRAM() { return mUsesGuestVRAM; }
355
356 uchar *vboxAddress() { return mAddress; }
357 ulong vboxBitsPerPixel() { return mBitsPerPixel; }
358 ulong vboxBytesPerLine() { return mBytesPerLine; }
359
360 void vboxPaintEvent (QPaintEvent *pe);
361 void vboxResizeEvent (VBoxResizeEvent *re);
362
363protected:
364// void resizeGL (int height, int width);
365
366 void paintGL();
367
368 void initializeGL();
369
370private:
371 void vboxDoInitDisplay();
372 void vboxDoDeleteDisplay();
373 void vboxDoPerformDisplay() { Assert(mDisplayInitialized); glCallList(mDisplay); }
374
375 void vboxDoResize(VBoxResizeEvent *re);
376 void vboxDoPaint(const QRect *rec);
377
378 VBoxResizeEvent *mRe;
379 const QRect *mpIntersectionRect;
380 GLuint mDisplay;
381 bool mDisplayInitialized;
382 uchar * mAddress;
383 GLuint mTexture;
384
385 GLenum mFormat;
386 GLint mInternalFormat;
387 GLenum mType;
388 ulong mDisplayWidth;
389 ulong mDisplayHeight;
390 ulong mBitsPerPixel;
391 ulong mBytesPerPixel;
392 ulong mBytesPerLine;
393 ulong mPixelFormat;
394 bool mUsesGuestVRAM;
395};
396
397
398class VBoxQGLFrameBuffer : public VBoxFrameBuffer
399{
400public:
401
402 VBoxQGLFrameBuffer (VBoxConsoleView *aView);
403
404 STDMETHOD(NotifyUpdate) (ULONG aX, ULONG aY,
405 ULONG aW, ULONG aH);
406
407#ifdef VBOX_WITH_VIDEOHWACCEL
408 STDMETHOD(ProcessVHWACommand)(BYTE *pCommand);
409#endif
410
411 ulong pixelFormat() { return vboxWidget()->vboxPixelFormat(); }
412 bool usesGuestVRAM() { return vboxWidget()->vboxUsesGuestVRAM(); }
413
414 uchar *address() { /*Assert(0); */return vboxWidget()->vboxAddress(); }
415 ulong bitsPerPixel() { return vboxWidget()->vboxBitsPerPixel(); }
416 ulong bytesPerLine() { return vboxWidget()->vboxBytesPerLine(); }
417
418 void paintEvent (QPaintEvent *pe);
419 void resizeEvent (VBoxResizeEvent *re);
420#ifdef VBOX_WITH_VIDEOHWACCEL
421 void doProcessVHWACommand(struct _VBOXVHWACMD * pCommand);
422#endif
423
424private:
425 void vboxMakeCurrent();
426 VBoxGLWidget * vboxWidget();
427};
428
429
430#endif
431
432/////////////////////////////////////////////////////////////////////////////
433
434#if defined (VBOX_GUI_USE_SDL)
435
436class VBoxSDLFrameBuffer : public VBoxFrameBuffer
437{
438public:
439
440 VBoxSDLFrameBuffer (VBoxConsoleView *aView);
441 virtual ~VBoxSDLFrameBuffer();
442
443 STDMETHOD(NotifyUpdate) (ULONG aX, ULONG aY,
444 ULONG aW, ULONG aH);
445
446 uchar *address()
447 {
448 SDL_Surface *surf = mSurfVRAM ? mSurfVRAM : mScreen;
449 return surf ? (uchar *) (uintptr_t) surf->pixels : 0;
450 }
451
452 ulong bitsPerPixel()
453 {
454 SDL_Surface *surf = mSurfVRAM ? mSurfVRAM : mScreen;
455 return surf ? surf->format->BitsPerPixel : 0;
456 }
457
458 ulong bytesPerLine()
459 {
460 SDL_Surface *surf = mSurfVRAM ? mSurfVRAM : mScreen;
461 return surf ? surf->pitch : 0;
462 }
463
464 ulong pixelFormat()
465 {
466 return mPixelFormat;
467 }
468
469 bool usesGuestVRAM()
470 {
471 return mSurfVRAM != NULL;
472 }
473
474 void paintEvent (QPaintEvent *pe);
475 void resizeEvent (VBoxResizeEvent *re);
476
477private:
478
479 SDL_Surface *mScreen;
480 SDL_Surface *mSurfVRAM;
481
482 ulong mPixelFormat;
483};
484
485#endif
486
487/////////////////////////////////////////////////////////////////////////////
488
489#if defined (VBOX_GUI_USE_DDRAW)
490
491class VBoxDDRAWFrameBuffer : public VBoxFrameBuffer
492{
493public:
494
495 VBoxDDRAWFrameBuffer (VBoxConsoleView *aView);
496 virtual ~VBoxDDRAWFrameBuffer();
497
498 STDMETHOD(NotifyUpdate) (ULONG aX, ULONG aY,
499 ULONG aW, ULONG aH);
500
501 uchar *address() { return (uchar *) mSurfaceDesc.lpSurface; }
502 ulong bitsPerPixel() { return mSurfaceDesc.ddpfPixelFormat.dwRGBBitCount; }
503 ulong bytesPerLine() { return (ulong) mSurfaceDesc.lPitch; }
504
505 ulong pixelFormat() { return mPixelFormat; };
506
507 bool usesGuestVRAM() { return mUsesGuestVRAM; }
508
509 void paintEvent (QPaintEvent *pe);
510 void resizeEvent (VBoxResizeEvent *re);
511 void moveEvent (QMoveEvent *me);
512
513private:
514
515 void releaseObjects();
516
517 bool createSurface (ULONG aPixelFormat, uchar *pvVRAM,
518 ULONG aBitsPerPixel, ULONG aBytesPerLine,
519 ULONG aWidth, ULONG aHeight);
520 void deleteSurface();
521 void drawRect (ULONG x, ULONG y, ULONG w, ULONG h);
522 void getWindowPosition (void);
523
524 LPDIRECTDRAW7 mDDRAW;
525 LPDIRECTDRAWCLIPPER mClipper;
526 LPDIRECTDRAWSURFACE7 mSurface;
527 DDSURFACEDESC2 mSurfaceDesc;
528 LPDIRECTDRAWSURFACE7 mPrimarySurface;
529
530 ulong mPixelFormat;
531
532 bool mUsesGuestVRAM;
533
534 int mWndX;
535 int mWndY;
536
537 bool mSynchronousUpdates;
538};
539
540#endif
541
542/////////////////////////////////////////////////////////////////////////////
543
544#if defined (Q_WS_MAC) && defined (VBOX_GUI_USE_QUARTZ2D)
545
546#include <Carbon/Carbon.h>
547
548class VBoxQuartz2DFrameBuffer : public VBoxFrameBuffer
549{
550public:
551
552 VBoxQuartz2DFrameBuffer (VBoxConsoleView *aView);
553 virtual ~VBoxQuartz2DFrameBuffer ();
554
555 STDMETHOD (NotifyUpdate) (ULONG aX, ULONG aY,
556 ULONG aW, ULONG aH);
557 STDMETHOD (SetVisibleRegion) (BYTE *aRectangles, ULONG aCount);
558
559 uchar *address() { return mDataAddress; }
560 ulong bitsPerPixel() { return CGImageGetBitsPerPixel (mImage); }
561 ulong bytesPerLine() { return CGImageGetBytesPerRow (mImage); }
562 ulong pixelFormat() { return mPixelFormat; };
563 bool usesGuestVRAM() { return mBitmapData == NULL; }
564
565 const CGImageRef imageRef() const { return mImage; }
566
567 void paintEvent (QPaintEvent *pe);
568 void resizeEvent (VBoxResizeEvent *re);
569
570private:
571
572 void clean();
573
574 uchar *mDataAddress;
575 void *mBitmapData;
576 ulong mPixelFormat;
577 CGImageRef mImage;
578 typedef struct
579 {
580 /** The size of this structure expressed in rcts entries. */
581 ULONG allocated;
582 /** The number of entries in the rcts array. */
583 ULONG used;
584 /** Variable sized array of the rectangle that makes up the region. */
585 CGRect rcts[1];
586 } RegionRects;
587 /** The current valid region, all access is by atomic cmpxchg or atomic xchg.
588 *
589 * The protocol for updating and using this has to take into account that
590 * the producer (SetVisibleRegion) and consumer (paintEvent) are running
591 * on different threads. Therefore the producer will create a new RegionRects
592 * structure before atomically replace the existing one. While the consumer
593 * will read the value by atomically replace it by NULL, and then when its
594 * done try restore it by cmpxchg. If the producer has already put a new
595 * region there, it will be discarded (see mRegionUnused).
596 */
597 RegionRects volatile *mRegion;
598 /** For keeping the unused region and thus avoid some RTMemAlloc/RTMemFree calls.
599 * This is operated with atomic cmpxchg and atomic xchg. */
600 RegionRects volatile *mRegionUnused;
601};
602
603#endif /* Q_WS_MAC && VBOX_GUI_USE_QUARTZ2D */
604
605#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