VirtualBox

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

Last change on this file since 3761 was 3761, checked in by vboxsync, 18 years ago

Main/Frontends: Cleaned up IFramebuffer interface.

  • 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 innotek GmbH
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 as published by the Free Software Foundation,
14 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
15 * distribution. VirtualBox OSE is distributed in the hope that it will
16 * be useful, but WITHOUT ANY WARRANTY of any kind.
17 *
18 * If you received this file as part of a commercial VirtualBox
19 * distribution, then only the terms of your commercial VirtualBox
20 * license agreement apply instead of the previous paragraph.
21 */
22
23#ifndef __VBoxFrameBuffer_h__
24#define __VBoxFrameBuffer_h__
25
26#include "COMDefs.h"
27
28class VBoxConsoleView;
29
30#include <qmutex.h>
31#include <qevent.h>
32#include <qpixmap.h>
33#include <qimage.h>
34
35#if defined (VBOX_GUI_USE_SDL)
36#include <SDL.h>
37#include <signal.h>
38#endif
39
40#if defined (Q_WS_WIN) && defined (VBOX_GUI_USE_DDRAW)
41// VBox/cdefs.h defines these:
42#undef LOWORD
43#undef HIWORD
44#undef LOBYTE
45#undef HIBYTE
46#include <ddraw.h>
47#endif
48
49//#define VBOX_GUI_FRAMEBUF_STAT
50
51#if defined (VBOX_GUI_DEBUG) && defined (VBOX_GUI_FRAMEBUF_STAT)
52#define FRAMEBUF_DEBUG_START(prefix) \
53 uint64_t prefix##elapsed = VMCPUTimer::ticks();
54#define FRAMEBUF_DEBUG_STOP(prefix,w,h) { \
55 prefix##elapsed = VMCPUTimer::ticks() - prefix##elapsed; \
56 V_DEBUG(( "Last update: %04d x %04d px, %03.3f ms, %.0f ticks", \
57 (w), (h), \
58 (double) prefix##elapsed / (double) VMCPUTimer::ticksPerMsec(), \
59 (double) prefix##elapsed \
60 )); \
61 }
62#else
63#define FRAMEBUF_DEBUG_START(prefix) {}
64#define FRAMEBUF_DEBUG_STOP(prefix,w,h) {}
65#endif
66
67/////////////////////////////////////////////////////////////////////////////
68
69/**
70 * Frame buffer resize event.
71 */
72class VBoxResizeEvent : public QEvent
73{
74public:
75
76 VBoxResizeEvent (ulong aPixelFormat, uchar *aVRAM,
77 ulong aBitsPerPixel, ulong aBytesPerLine,
78 ulong aWidth, ulong aHeight) :
79 QEvent ((QEvent::Type) VBoxDefs::ResizeEventType),
80 mPixelFormat (aPixelFormat), mVRAM (aVRAM), mBitsPerPixel (aBitsPerPixel),
81 mBytesPerLine (aBytesPerLine), mWidth (aWidth), mHeight (aHeight) {}
82 ulong pixelFormat() { return mPixelFormat; }
83 uchar *VRAM() { return mVRAM; }
84 ulong bitsPerPixel() { return mBitsPerPixel; }
85 ulong bytesPerLine() { return mBytesPerLine; }
86 ulong width() { return mWidth; }
87 ulong height() { return mHeight; }
88
89private:
90
91 ulong mPixelFormat;
92 uchar *mVRAM;
93 ulong mBitsPerPixel;
94 ulong mBytesPerLine;
95 ulong mWidth;
96 ulong mHeight;
97};
98
99/**
100 * Frame buffer repaint event.
101 */
102class VBoxRepaintEvent : public QEvent
103{
104public:
105 VBoxRepaintEvent (int x, int y, int w, int h) :
106 QEvent ((QEvent::Type) VBoxDefs::RepaintEventType),
107 ex (x), ey (y), ew (w), eh (h)
108 {}
109 int x() { return ex; }
110 int y() { return ey; }
111 int width() { return ew; }
112 int height() { return eh; }
113private:
114 int ex, ey, ew, eh;
115};
116
117/**
118 * Frame buffer set region event.
119 */
120class VBoxSetRegionEvent : public QEvent
121{
122public:
123 VBoxSetRegionEvent (const QRegion &aReg)
124 : QEvent ((QEvent::Type) VBoxDefs::SetRegionEventType)
125 , mReg (aReg) {}
126 QRegion region() { return mReg; }
127private:
128 QRegion mReg;
129};
130
131/////////////////////////////////////////////////////////////////////////////
132
133#if defined (VBOX_GUI_USE_REFRESH_TIMER)
134
135/**
136 * Copies the current VM video buffer contents to the pixmap referenced
137 * by the argument. The return value indicates whether the
138 * buffer has been updated since the last call to this method or not.
139 *
140 * The copy operation is atomic (guarded by a mutex).
141 *
142 * This method is intentionally inlined for faster execution and should be
143 * called only by VBoxConsoleView members.
144 *
145 * @return true if the pixmap is updated, and false otherwise.
146 */
147inline bool display_to_pixmap( const CConsole &c, QPixmap &pm )
148{
149 CDisplay display = c.GetDisplay();
150
151 uint8_t *addr = (uint8_t *) display.LockFramebuffer();
152 AssertMsg (addr, ("The buffer address must not be null"));
153
154 bool rc = pm.convertFromImage (QImage (addr,
155 display.GetWidth(), display.GetHeight(),
156 display.GetBitsPerPixel(),
157 0, 0, QImage::LittleEndian));
158 AssertMsg (rc, ("convertFromImage() must always return true"));
159
160 display.UnlockFramebuffer();
161
162 return rc;
163}
164
165#endif
166
167/////////////////////////////////////////////////////////////////////////////
168
169/**
170 * Common IFramebuffer implementation for all methods used by GUI to maintain
171 * the VM display video memory.
172 *
173 * Note that although this class can be called from multiple threads
174 * (in particular, the GUI thread and EMT) it doesn't protect access to every
175 * data field using its mutex lock. This is because all synchronization between
176 * the GUI and the EMT thread is supposed to be done using the
177 * IFramebuffer::NotifyUpdate() and IFramebuffer::RequestResize() methods
178 * (in particular, the \a aFinished parameter of these methods is responsible
179 * for the synchronization). These methods are always called on EMT and
180 * therefore always follow one another but never in parallel.
181 *
182 * Using this object's mutex lock (exposed also in IFramebuffer::Lock() and
183 * IFramebuffer::Unlock() implementations) usually makes sense only if some
184 * third-party thread (i.e. other than GUI or EMT) needs to make sure that
185 * *no* VM display update or resize event can occur while it is accessing
186 * IFramebuffer properties or the underlying display memory storage area.
187 *
188 * See IFramebuffer documentation for more info.
189 */
190
191class VBoxFrameBuffer : public IFramebuffer
192{
193public:
194
195 VBoxFrameBuffer (VBoxConsoleView *aView);
196 virtual ~VBoxFrameBuffer();
197
198 NS_DECL_ISUPPORTS
199
200#if defined (Q_OS_WIN32)
201
202 STDMETHOD_(ULONG, AddRef)()
203 {
204 return ::InterlockedIncrement (&refcnt);
205 }
206
207 STDMETHOD_(ULONG, Release)()
208 {
209 long cnt = ::InterlockedDecrement (&refcnt);
210 if (cnt == 0)
211 delete this;
212 return cnt;
213 }
214
215 STDMETHOD(QueryInterface) (REFIID riid , void **ppObj)
216 {
217 if (riid == IID_IUnknown) {
218 *ppObj = this;
219 AddRef();
220 return S_OK;
221 }
222 if (riid == IID_IFramebuffer) {
223 *ppObj = this;
224 AddRef();
225 return S_OK;
226 }
227 *ppObj = NULL;
228 return E_NOINTERFACE;
229 }
230
231#endif
232
233 // IFramebuffer COM methods
234 STDMETHOD(COMGETTER(Address)) (BYTE **aAddress);
235 STDMETHOD(COMGETTER(Width)) (ULONG *aWidth);
236 STDMETHOD(COMGETTER(Height)) (ULONG *aHeight);
237 STDMETHOD(COMGETTER(BitsPerPixel)) (ULONG *aBitsPerPixel);
238 STDMETHOD(COMGETTER(BytesPerLine)) (ULONG *aBytesPerLine);
239 STDMETHOD(COMGETTER(PixelFormat)) (ULONG *aPixelFormat);
240 STDMETHOD(COMGETTER(UsesGuestVRAM)) (BOOL *aUsesGuestVRAM);
241 STDMETHOD(COMGETTER(HeightReduction)) (ULONG *aHeightReduction);
242 STDMETHOD(COMGETTER(Overlay)) (IFramebufferOverlay **aOverlay);
243
244 STDMETHOD(Lock)();
245 STDMETHOD(Unlock)();
246
247 STDMETHOD(RequestResize) (ULONG aScreenId, ULONG aPixelFormat,
248 BYTE *aVRAM, ULONG aBitsPerPixel, ULONG aBytesPerLine,
249 ULONG aWidth, ULONG aHeight,
250 BOOL *aFinished);
251
252 STDMETHOD(OperationSupported)(FramebufferAccelerationOperation_T aOperation,
253 BOOL *aSupported);
254 STDMETHOD(VideoModeSupported) (ULONG aWidth, ULONG aHeight, ULONG aBPP,
255 BOOL *aSupported);
256 STDMETHOD(SolidFill) (ULONG aX, ULONG aY, ULONG aWidth, ULONG aHeight,
257 ULONG aColor, BOOL *aHandled);
258 STDMETHOD(CopyScreenBits) (ULONG aXDst, ULONG aYDst, ULONG aXSrc, ULONG aYSrc,
259 ULONG aWidth, ULONG aHeight, BOOL *aHandled);
260
261 STDMETHOD(GetVisibleRegion)(BYTE *aRectangles, ULONG aCount, ULONG *aCountCopied);
262 STDMETHOD(SetVisibleRegion)(BYTE *aRectangles, ULONG aCount);
263
264 ulong width() { return mWdt; }
265 ulong height() { return mHgt; }
266
267 virtual ulong pixelFormat()
268 {
269 return FramebufferPixelFormat_FOURCC_RGB;
270 }
271
272 virtual bool usesGuestVRAM()
273 {
274 return false;
275 }
276
277 void lock() { mMutex->lock(); }
278 void unlock() { mMutex->unlock(); }
279
280 virtual uchar *address() = 0;
281 virtual ulong bitsPerPixel() = 0;
282 virtual ulong bytesPerLine() = 0;
283
284 /**
285 * Called on the GUI thread (from VBoxConsoleView) when some part of the
286 * VM display viewport needs to be repainted on the host screen.
287 */
288 virtual void paintEvent (QPaintEvent *pe) = 0;
289
290 /**
291 * Called on the GUI thread (from VBoxConsoleView) after it gets a
292 * VBoxResizeEvent posted from the RequestResize() method implementation.
293 */
294 virtual void resizeEvent (VBoxResizeEvent *re)
295 {
296 mWdt = re->width();
297 mHgt = re->height();
298 }
299
300 /**
301 * Called on the GUI thread (from VBoxConsoleView) when the VM console
302 * window is moved.
303 */
304 virtual void moveEvent (QMoveEvent * /*me*/ ) {}
305
306protected:
307
308 VBoxConsoleView *mView;
309 QMutex *mMutex;
310 int mWdt;
311 int mHgt;
312
313#if defined (Q_OS_WIN32)
314private:
315 long refcnt;
316#endif
317};
318
319/////////////////////////////////////////////////////////////////////////////
320
321#if defined (VBOX_GUI_USE_QIMAGE)
322
323class VBoxQImageFrameBuffer : public VBoxFrameBuffer
324{
325public:
326
327 VBoxQImageFrameBuffer (VBoxConsoleView *aView);
328
329 STDMETHOD(NotifyUpdate) (ULONG aX, ULONG aY,
330 ULONG aW, ULONG aH,
331 BOOL *aFinished);
332
333 ulong pixelFormat() { return mPixelFormat; }
334 bool usesGuestVRAM() { return mUsesGuestVRAM; }
335
336 uchar *address() { return mImg.bits(); }
337 ulong bitsPerPixel() { return mImg.depth(); }
338 ulong bytesPerLine() { return mImg.bytesPerLine(); }
339
340 void paintEvent (QPaintEvent *pe);
341 void resizeEvent (VBoxResizeEvent *re);
342
343private:
344
345 QPixmap mPM;
346 QImage mImg;
347 ulong mPixelFormat;
348 bool mUsesGuestVRAM;
349};
350
351#endif
352
353/////////////////////////////////////////////////////////////////////////////
354
355#if defined (VBOX_GUI_USE_SDL)
356
357class VBoxSDLFrameBuffer : public VBoxFrameBuffer
358{
359public:
360
361 VBoxSDLFrameBuffer (VBoxConsoleView *aView);
362 virtual ~VBoxSDLFrameBuffer();
363
364 STDMETHOD(NotifyUpdate) (ULONG aX, ULONG aY,
365 ULONG aW, ULONG aH,
366 BOOL *aFinished);
367
368 uchar *address()
369 {
370 SDL_Surface *surf = mSurfVRAM ? mSurfVRAM : mScreen;
371 return surf ? (uchar *) (uintptr_t) mScreen->pixels : 0;
372 }
373
374 ulong bitsPerPixel()
375 {
376 SDL_Surface *surf = mSurfVRAM ? mSurfVRAM : mScreen;
377 return surf ? surf->format->BitsPerPixel : 0;
378 }
379
380 ulong bytesPerLine()
381 {
382 SDL_Surface *surf = mSurfVRAM ? mSurfVRAM : mScreen;
383 return surf ? surf->pitch : 0;
384 }
385
386 ulong pixelFormat()
387 {
388 return mPixelFormat;
389 }
390
391 bool usesGuestVRAM()
392 {
393 return mSurfVRAM != NULL;
394 }
395
396 void paintEvent (QPaintEvent *pe);
397 void resizeEvent (VBoxResizeEvent *re);
398
399private:
400
401 SDL_Surface *mScreen;
402 SDL_Surface *mSurfVRAM;
403
404 ulong mPixelFormat;
405};
406
407#endif
408
409/////////////////////////////////////////////////////////////////////////////
410
411#if defined (VBOX_GUI_USE_DDRAW)
412
413class VBoxDDRAWFrameBuffer : public VBoxFrameBuffer
414{
415public:
416
417 VBoxDDRAWFrameBuffer (VBoxConsoleView *aView);
418 virtual ~VBoxDDRAWFrameBuffer();
419
420 STDMETHOD(NotifyUpdate) (ULONG aX, ULONG aY,
421 ULONG aW, ULONG aH,
422 BOOL *aFinished);
423
424 uchar *address() { return (uchar *) mSurfaceDesc.lpSurface; }
425 ulong bitsPerPixel() { return mSurfaceDesc.ddpfPixelFormat.dwRGBBitCount; }
426 ulong bytesPerLine() { return (ulong) mSurfaceDesc.lPitch; }
427
428 ulong pixelFormat() { return mPixelFormat; };
429
430 bool usesGuestVRAM() { return mUsesGuestVRAM; }
431
432 void paintEvent (QPaintEvent *pe);
433 void resizeEvent (VBoxResizeEvent *re);
434 void moveEvent (QMoveEvent *me);
435
436private:
437
438 void releaseObjects();
439
440 bool createSurface (ULONG aPixelFormat, uchar *pvVRAM,
441 ULONG aBitsPerPixel, ULONG aBytesPerLine,
442 ULONG aWidth, ULONG aHeight);
443 void deleteSurface();
444 void drawRect (ULONG x, ULONG y, ULONG w, ULONG h);
445 void getWindowPosition (void);
446
447 LPDIRECTDRAW7 mDDRAW;
448 LPDIRECTDRAWCLIPPER mClipper;
449 LPDIRECTDRAWSURFACE7 mSurface;
450 DDSURFACEDESC2 mSurfaceDesc;
451 LPDIRECTDRAWSURFACE7 mPrimarySurface;
452
453 ulong mPixelFormat;
454
455 bool mUsesGuestVRAM;
456
457 int mWndX;
458 int mWndY;
459
460 bool mSynchronousUpdates;
461};
462
463#endif
464
465#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