VirtualBox

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

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

Use RT critical sections, so we get an assertion for deadlocks

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