VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox4/include/VBoxFrameBuffer.h@ 7237

Last change on this file since 7237 was 7220, checked in by vboxsync, 17 years ago

Compile VirtualBox with qt4 on linux.

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