VirtualBox

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

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

IFramebuffer cleanup next part:

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