VirtualBox

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

Last change on this file since 23962 was 23899, checked in by vboxsync, 15 years ago

FE/Qt4-OSX: fix redraw problem on Snow Leopard/Carbon in a dual screen setup (public bug #4942)

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