VirtualBox

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

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

crOpenGL: don't touch qt from non gui threads, fix for #3782

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

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