VirtualBox

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

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

HGSMI: post host VBVA commands to display; Video HW Accel: mechanism for passing/processing commands to framebuffer

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.3 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
36#if defined (VBOX_GUI_USE_SDL)
37#include <SDL.h>
38#include <signal.h>
39#endif
40
41#if defined (Q_WS_WIN) && defined (VBOX_GUI_USE_DDRAW)
42// VBox/cdefs.h defines these:
43#undef LOWORD
44#undef HIWORD
45#undef LOBYTE
46#undef HIBYTE
47#include <ddraw.h>
48#endif
49
50class VBoxConsoleView;
51
52/////////////////////////////////////////////////////////////////////////////
53
54/**
55 * Frame buffer resize event.
56 */
57class VBoxResizeEvent : public QEvent
58{
59public:
60
61 VBoxResizeEvent (ulong aPixelFormat, uchar *aVRAM,
62 ulong aBitsPerPixel, ulong aBytesPerLine,
63 ulong aWidth, ulong aHeight) :
64 QEvent ((QEvent::Type) VBoxDefs::ResizeEventType),
65 mPixelFormat (aPixelFormat), mVRAM (aVRAM), mBitsPerPixel (aBitsPerPixel),
66 mBytesPerLine (aBytesPerLine), mWidth (aWidth), mHeight (aHeight) {}
67 ulong pixelFormat() { return mPixelFormat; }
68 uchar *VRAM() { return mVRAM; }
69 ulong bitsPerPixel() { return mBitsPerPixel; }
70 ulong bytesPerLine() { return mBytesPerLine; }
71 ulong width() { return mWidth; }
72 ulong height() { return mHeight; }
73
74private:
75
76 ulong mPixelFormat;
77 uchar *mVRAM;
78 ulong mBitsPerPixel;
79 ulong mBytesPerLine;
80 ulong mWidth;
81 ulong mHeight;
82};
83
84/**
85 * Frame buffer repaint event.
86 */
87class VBoxRepaintEvent : public QEvent
88{
89public:
90 VBoxRepaintEvent (int x, int y, int w, int h) :
91 QEvent ((QEvent::Type) VBoxDefs::RepaintEventType),
92 ex (x), ey (y), ew (w), eh (h)
93 {}
94 int x() { return ex; }
95 int y() { return ey; }
96 int width() { return ew; }
97 int height() { return eh; }
98private:
99 int ex, ey, ew, eh;
100};
101
102/**
103 * Frame buffer set region event.
104 */
105class VBoxSetRegionEvent : public QEvent
106{
107public:
108 VBoxSetRegionEvent (const QRegion &aReg)
109 : QEvent ((QEvent::Type) VBoxDefs::SetRegionEventType)
110 , mReg (aReg) {}
111 QRegion region() { return mReg; }
112private:
113 QRegion mReg;
114};
115
116#ifdef VBOX_WITH_VIDEOHWACCEL
117class VBoxVHWACommandProcessEvent : public QEvent
118{
119public:
120 VBoxVHWACommandProcessEvent (struct _VBOXVHWACMD * pCmd)
121 : QEvent ((QEvent::Type) VBoxDefs::VHWACommandProcessType)
122 , mpCmd (pCmd) {}
123 struct _VBOXVHWACMD * command() { return mpCmd; }
124private:
125 struct _VBOXVHWACMD * mpCmd;
126};
127
128#endif
129
130/////////////////////////////////////////////////////////////////////////////
131
132/**
133 * Common IFramebuffer implementation for all methods used by GUI to maintain
134 * the VM display video memory.
135 *
136 * Note that although this class can be called from multiple threads
137 * (in particular, the GUI thread and EMT) it doesn't protect access to every
138 * data field using its mutex lock. This is because all synchronization between
139 * the GUI and the EMT thread is supposed to be done using the
140 * IFramebuffer::NotifyUpdate() and IFramebuffer::RequestResize() methods
141 * (in particular, the \a aFinished parameter of these methods is responsible
142 * for the synchronization). These methods are always called on EMT and
143 * therefore always follow one another but never in parallel.
144 *
145 * Using this object's mutex lock (exposed also in IFramebuffer::Lock() and
146 * IFramebuffer::Unlock() implementations) usually makes sense only if some
147 * third-party thread (i.e. other than GUI or EMT) needs to make sure that
148 * *no* VM display update or resize event can occur while it is accessing
149 * IFramebuffer properties or the underlying display memory storage area.
150 *
151 * See IFramebuffer documentation for more info.
152 */
153
154class VBoxFrameBuffer : VBOX_SCRIPTABLE_IMPL(IFramebuffer)
155{
156public:
157
158 VBoxFrameBuffer (VBoxConsoleView *aView);
159 virtual ~VBoxFrameBuffer();
160
161 NS_DECL_ISUPPORTS
162
163#if defined (Q_OS_WIN32)
164
165 STDMETHOD_(ULONG, AddRef)()
166 {
167 return ::InterlockedIncrement (&refcnt);
168 }
169
170 STDMETHOD_(ULONG, Release)()
171 {
172 long cnt = ::InterlockedDecrement (&refcnt);
173 if (cnt == 0)
174 delete this;
175 return cnt;
176 }
177
178 STDMETHOD(QueryInterface) (REFIID riid , void **ppObj)
179 {
180 if (riid == IID_IUnknown) {
181 *ppObj = this;
182 AddRef();
183 return S_OK;
184 }
185 if (riid == IID_IFramebuffer) {
186 *ppObj = this;
187 AddRef();
188 return S_OK;
189 }
190 *ppObj = NULL;
191 return E_NOINTERFACE;
192 }
193
194#endif
195
196 // IFramebuffer COM methods
197 STDMETHOD(COMGETTER(Address)) (BYTE **aAddress);
198 STDMETHOD(COMGETTER(Width)) (ULONG *aWidth);
199 STDMETHOD(COMGETTER(Height)) (ULONG *aHeight);
200 STDMETHOD(COMGETTER(BitsPerPixel)) (ULONG *aBitsPerPixel);
201 STDMETHOD(COMGETTER(BytesPerLine)) (ULONG *aBytesPerLine);
202 STDMETHOD(COMGETTER(PixelFormat)) (ULONG *aPixelFormat);
203 STDMETHOD(COMGETTER(UsesGuestVRAM)) (BOOL *aUsesGuestVRAM);
204 STDMETHOD(COMGETTER(HeightReduction)) (ULONG *aHeightReduction);
205 STDMETHOD(COMGETTER(Overlay)) (IFramebufferOverlay **aOverlay);
206 STDMETHOD(COMGETTER(WinId)) (ULONG64 *winId);
207
208 STDMETHOD(Lock)();
209 STDMETHOD(Unlock)();
210
211 STDMETHOD(RequestResize) (ULONG aScreenId, ULONG aPixelFormat,
212 BYTE *aVRAM, ULONG aBitsPerPixel, ULONG aBytesPerLine,
213 ULONG aWidth, ULONG aHeight,
214 BOOL *aFinished);
215
216 STDMETHOD(VideoModeSupported) (ULONG aWidth, ULONG aHeight, ULONG aBPP,
217 BOOL *aSupported);
218
219 STDMETHOD(GetVisibleRegion)(BYTE *aRectangles, ULONG aCount, ULONG *aCountCopied);
220 STDMETHOD(SetVisibleRegion)(BYTE *aRectangles, ULONG aCount);
221
222 STDMETHOD(ProcessVHWACommand)(BYTE *pCommand);
223
224 ulong width() { return mWdt; }
225 ulong height() { return mHgt; }
226
227 virtual ulong pixelFormat()
228 {
229 return FramebufferPixelFormat_FOURCC_RGB;
230 }
231
232 virtual bool usesGuestVRAM()
233 {
234 return false;
235 }
236
237 void lock() { RTCritSectEnter(&mCritSect); }
238 void unlock() { RTCritSectLeave(&mCritSect); }
239
240 virtual uchar *address() = 0;
241 virtual ulong bitsPerPixel() = 0;
242 virtual ulong bytesPerLine() = 0;
243
244 /**
245 * Called on the GUI thread (from VBoxConsoleView) when some part of the
246 * VM display viewport needs to be repainted on the host screen.
247 */
248 virtual void paintEvent (QPaintEvent *pe) = 0;
249
250 /**
251 * Called on the GUI thread (from VBoxConsoleView) after it gets a
252 * VBoxResizeEvent posted from the RequestResize() method implementation.
253 */
254 virtual void resizeEvent (VBoxResizeEvent *re)
255 {
256 mWdt = re->width();
257 mHgt = re->height();
258 }
259
260 /**
261 * Called on the GUI thread (from VBoxConsoleView) when the VM console
262 * window is moved.
263 */
264 virtual void moveEvent (QMoveEvent * /*me*/ ) {}
265
266protected:
267
268 VBoxConsoleView *mView;
269 RTCRITSECT mCritSect;
270 int mWdt;
271 int mHgt;
272 uint64_t mWinId;
273
274#if defined (Q_OS_WIN32)
275private:
276 long refcnt;
277#endif
278};
279
280/////////////////////////////////////////////////////////////////////////////
281
282#if defined (VBOX_GUI_USE_QIMAGE)
283
284class VBoxQImageFrameBuffer : public VBoxFrameBuffer
285{
286public:
287
288 VBoxQImageFrameBuffer (VBoxConsoleView *aView);
289
290 STDMETHOD(NotifyUpdate) (ULONG aX, ULONG aY,
291 ULONG aW, ULONG aH);
292
293 ulong pixelFormat() { return mPixelFormat; }
294 bool usesGuestVRAM() { return mUsesGuestVRAM; }
295
296 uchar *address() { return mImg.bits(); }
297 ulong bitsPerPixel() { return mImg.depth(); }
298 ulong bytesPerLine() { return mImg.bytesPerLine(); }
299
300 void paintEvent (QPaintEvent *pe);
301 void resizeEvent (VBoxResizeEvent *re);
302
303private:
304
305 QPixmap mPM;
306 QImage mImg;
307 ulong mPixelFormat;
308 bool mUsesGuestVRAM;
309};
310
311#endif
312
313/////////////////////////////////////////////////////////////////////////////
314
315#if defined (VBOX_GUI_USE_SDL)
316
317class VBoxSDLFrameBuffer : public VBoxFrameBuffer
318{
319public:
320
321 VBoxSDLFrameBuffer (VBoxConsoleView *aView);
322 virtual ~VBoxSDLFrameBuffer();
323
324 STDMETHOD(NotifyUpdate) (ULONG aX, ULONG aY,
325 ULONG aW, ULONG aH);
326
327 uchar *address()
328 {
329 SDL_Surface *surf = mSurfVRAM ? mSurfVRAM : mScreen;
330 return surf ? (uchar *) (uintptr_t) surf->pixels : 0;
331 }
332
333 ulong bitsPerPixel()
334 {
335 SDL_Surface *surf = mSurfVRAM ? mSurfVRAM : mScreen;
336 return surf ? surf->format->BitsPerPixel : 0;
337 }
338
339 ulong bytesPerLine()
340 {
341 SDL_Surface *surf = mSurfVRAM ? mSurfVRAM : mScreen;
342 return surf ? surf->pitch : 0;
343 }
344
345 ulong pixelFormat()
346 {
347 return mPixelFormat;
348 }
349
350 bool usesGuestVRAM()
351 {
352 return mSurfVRAM != NULL;
353 }
354
355 void paintEvent (QPaintEvent *pe);
356 void resizeEvent (VBoxResizeEvent *re);
357
358private:
359
360 SDL_Surface *mScreen;
361 SDL_Surface *mSurfVRAM;
362
363 ulong mPixelFormat;
364};
365
366#endif
367
368/////////////////////////////////////////////////////////////////////////////
369
370#if defined (VBOX_GUI_USE_DDRAW)
371
372class VBoxDDRAWFrameBuffer : public VBoxFrameBuffer
373{
374public:
375
376 VBoxDDRAWFrameBuffer (VBoxConsoleView *aView);
377 virtual ~VBoxDDRAWFrameBuffer();
378
379 STDMETHOD(NotifyUpdate) (ULONG aX, ULONG aY,
380 ULONG aW, ULONG aH);
381
382 uchar *address() { return (uchar *) mSurfaceDesc.lpSurface; }
383 ulong bitsPerPixel() { return mSurfaceDesc.ddpfPixelFormat.dwRGBBitCount; }
384 ulong bytesPerLine() { return (ulong) mSurfaceDesc.lPitch; }
385
386 ulong pixelFormat() { return mPixelFormat; };
387
388 bool usesGuestVRAM() { return mUsesGuestVRAM; }
389
390 void paintEvent (QPaintEvent *pe);
391 void resizeEvent (VBoxResizeEvent *re);
392 void moveEvent (QMoveEvent *me);
393
394private:
395
396 void releaseObjects();
397
398 bool createSurface (ULONG aPixelFormat, uchar *pvVRAM,
399 ULONG aBitsPerPixel, ULONG aBytesPerLine,
400 ULONG aWidth, ULONG aHeight);
401 void deleteSurface();
402 void drawRect (ULONG x, ULONG y, ULONG w, ULONG h);
403 void getWindowPosition (void);
404
405 LPDIRECTDRAW7 mDDRAW;
406 LPDIRECTDRAWCLIPPER mClipper;
407 LPDIRECTDRAWSURFACE7 mSurface;
408 DDSURFACEDESC2 mSurfaceDesc;
409 LPDIRECTDRAWSURFACE7 mPrimarySurface;
410
411 ulong mPixelFormat;
412
413 bool mUsesGuestVRAM;
414
415 int mWndX;
416 int mWndY;
417
418 bool mSynchronousUpdates;
419};
420
421#endif
422
423/////////////////////////////////////////////////////////////////////////////
424
425#if defined (Q_WS_MAC) && defined (VBOX_GUI_USE_QUARTZ2D)
426
427#include <Carbon/Carbon.h>
428
429class VBoxQuartz2DFrameBuffer : public VBoxFrameBuffer
430{
431public:
432
433 VBoxQuartz2DFrameBuffer (VBoxConsoleView *aView);
434 virtual ~VBoxQuartz2DFrameBuffer ();
435
436 STDMETHOD (NotifyUpdate) (ULONG aX, ULONG aY,
437 ULONG aW, ULONG aH);
438 STDMETHOD (SetVisibleRegion) (BYTE *aRectangles, ULONG aCount);
439
440 uchar *address() { return mDataAddress; }
441 ulong bitsPerPixel() { return CGImageGetBitsPerPixel (mImage); }
442 ulong bytesPerLine() { return CGImageGetBytesPerRow (mImage); }
443 ulong pixelFormat() { return mPixelFormat; };
444 bool usesGuestVRAM() { return mBitmapData == NULL; }
445
446 const CGImageRef imageRef() const { return mImage; }
447
448 void paintEvent (QPaintEvent *pe);
449 void resizeEvent (VBoxResizeEvent *re);
450
451private:
452
453 void clean();
454
455 uchar *mDataAddress;
456 void *mBitmapData;
457 ulong mPixelFormat;
458 CGImageRef mImage;
459 typedef struct
460 {
461 /** The size of this structure expressed in rcts entries. */
462 ULONG allocated;
463 /** The number of entries in the rcts array. */
464 ULONG used;
465 /** Variable sized array of the rectangle that makes up the region. */
466 CGRect rcts[1];
467 } RegionRects;
468 /** The current valid region, all access is by atomic cmpxchg or atomic xchg.
469 *
470 * The protocol for updating and using this has to take into account that
471 * the producer (SetVisibleRegion) and consumer (paintEvent) are running
472 * on different threads. Therefore the producer will create a new RegionRects
473 * structure before atomically replace the existing one. While the consumer
474 * will read the value by atomically replace it by NULL, and then when its
475 * done try restore it by cmpxchg. If the producer has already put a new
476 * region there, it will be discarded (see mRegionUnused).
477 */
478 RegionRects volatile *mRegion;
479 /** For keeping the unused region and thus avoid some RTMemAlloc/RTMemFree calls.
480 * This is operated with atomic cmpxchg and atomic xchg. */
481 RegionRects volatile *mRegionUnused;
482};
483
484#endif /* Q_WS_MAC && VBOX_GUI_USE_QUARTZ2D */
485
486#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