VBoxFrameBuffer.h revision 65a24a6d074ca3422fd58830484323b3fd8096b2
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * VBox frontends: Qt GUI ("VirtualBox"):
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * VBoxFrameBuffer class and subclasses declarations
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * available from http://www.virtualbox.org. This file is free software;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * you can redistribute it and/or modify it under the terms of the GNU
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * General Public License (GPL) as published by the Free Software
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * additional information or have any questions.
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync/* Qt includes */
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync#if defined (Q_WS_WIN) && defined (VBOX_GUI_USE_DDRAW)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync// VBox/cdefs.h defines these:
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync//#define VBOX_GUI_FRAMEBUF_STAT
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync#if defined (VBOX_GUI_DEBUG) && defined (VBOX_GUI_FRAMEBUF_STAT)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync prefix##elapsed = VMCPUTimer::ticks() - prefix##elapsed; \
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync V_DEBUG(( "Last update: %04d x %04d px, %03.3f ms, %.0f ticks", \
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync (w), (h), \
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync (double) prefix##elapsed / (double) VMCPUTimer::ticksPerMsec(), \
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync/////////////////////////////////////////////////////////////////////////////
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * Frame buffer resize event.
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync mPixelFormat (aPixelFormat), mVRAM (aVRAM), mBitsPerPixel (aBitsPerPixel),
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync mBytesPerLine (aBytesPerLine), mWidth (aWidth), mHeight (aHeight) {}
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * Frame buffer repaint event.
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync VBoxRepaintEvent (int x, int y, int w, int h) :
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync QEvent ((QEvent::Type) VBoxDefs::RepaintEventType),
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync int x() { return ex; }
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync int y() { return ey; }
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * Frame buffer set region event.
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync : QEvent ((QEvent::Type) VBoxDefs::SetRegionEventType)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync/////////////////////////////////////////////////////////////////////////////
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * Common IFramebuffer implementation for all methods used by GUI to maintain
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * the VM display video memory.
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * Note that although this class can be called from multiple threads
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * (in particular, the GUI thread and EMT) it doesn't protect access to every
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * data field using its mutex lock. This is because all synchronization between
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * the GUI and the EMT thread is supposed to be done using the
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * IFramebuffer::NotifyUpdate() and IFramebuffer::RequestResize() methods
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * (in particular, the \a aFinished parameter of these methods is responsible
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * for the synchronization). These methods are always called on EMT and
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * therefore always follow one another but never in parallel.
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * Using this object's mutex lock (exposed also in IFramebuffer::Lock() and
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * IFramebuffer::Unlock() implementations) usually makes sense only if some
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * third-party thread (i.e. other than GUI or EMT) needs to make sure that
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * *no* VM display update or resize event can occur while it is accessing
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * IFramebuffer properties or the underlying display memory storage area.
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * See IFramebuffer documentation for more info.
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync STDMETHOD(QueryInterface) (REFIID riid , void **ppObj)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync // IFramebuffer COM methods
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync STDMETHOD(COMGETTER(BitsPerPixel)) (ULONG *aBitsPerPixel);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync STDMETHOD(COMGETTER(BytesPerLine)) (ULONG *aBytesPerLine);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync STDMETHOD(COMGETTER(PixelFormat)) (ULONG *aPixelFormat);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync STDMETHOD(COMGETTER(UsesGuestVRAM)) (BOOL *aUsesGuestVRAM);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync STDMETHOD(COMGETTER(HeightReduction)) (ULONG *aHeightReduction);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync STDMETHOD(COMGETTER(Overlay)) (IFramebufferOverlay **aOverlay);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync STDMETHOD(RequestResize) (ULONG aScreenId, ULONG aPixelFormat,
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync BYTE *aVRAM, ULONG aBitsPerPixel, ULONG aBytesPerLine,
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync STDMETHOD(OperationSupported)(FramebufferAccelerationOperation_T aOperation,
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync STDMETHOD(VideoModeSupported) (ULONG aWidth, ULONG aHeight, ULONG aBPP,
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync STDMETHOD(SolidFill) (ULONG aX, ULONG aY, ULONG aWidth, ULONG aHeight,
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync STDMETHOD(CopyScreenBits) (ULONG aXDst, ULONG aYDst, ULONG aXSrc, ULONG aYSrc,
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync STDMETHOD(GetVisibleRegion)(BYTE *aRectangles, ULONG aCount, ULONG *aCountCopied);
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync STDMETHOD(SetVisibleRegion)(BYTE *aRectangles, ULONG aCount);
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync return false;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * Called on the GUI thread (from VBoxConsoleView) when some part of the
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * VM display viewport needs to be repainted on the host screen.
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * Called on the GUI thread (from VBoxConsoleView) after it gets a
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * VBoxResizeEvent posted from the RequestResize() method implementation.
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * Called on the GUI thread (from VBoxConsoleView) when the VM console
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * window is moved.
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync/////////////////////////////////////////////////////////////////////////////
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsyncclass VBoxQImageFrameBuffer : public VBoxFrameBuffer
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync ulong bytesPerLine() { return mImg.bytesPerLine(); }
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync/////////////////////////////////////////////////////////////////////////////
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync SDL_Surface *surf = mSurfVRAM ? mSurfVRAM : mScreen;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync return surf ? (uchar *) (uintptr_t) surf->pixels : 0;
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync SDL_Surface *surf = mSurfVRAM ? mSurfVRAM : mScreen;
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync SDL_Surface *surf = mSurfVRAM ? mSurfVRAM : mScreen;
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync/////////////////////////////////////////////////////////////////////////////
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync uchar *address() { return (uchar *) mSurfaceDesc.lpSurface; }
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync ulong bitsPerPixel() { return mSurfaceDesc.ddpfPixelFormat.dwRGBBitCount; }
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync ulong bytesPerLine() { return (ulong) mSurfaceDesc.lPitch; }
1e8d9e04805e6cf8e90e57ee08344105c76f23fevboxsync bool createSurface (ULONG aPixelFormat, uchar *pvVRAM,
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync void drawRect (ULONG x, ULONG y, ULONG w, ULONG h);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync/////////////////////////////////////////////////////////////////////////////
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync#if defined (Q_WS_MAC) && defined (VBOX_GUI_USE_QUARTZ2D)
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsyncclass VBoxQuartz2DFrameBuffer : public VBoxFrameBuffer
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync STDMETHOD (SetVisibleRegion) (BYTE *aRectangles, ULONG aCount);
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync ulong bitsPerPixel() { return CGImageGetBitsPerPixel (mImage); }
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync ulong bytesPerLine() { return CGImageGetBytesPerRow (mImage); }
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync bool usesGuestVRAM() { return mBitmapData == NULL; }
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync const CGImageRef imageRef() const { return mImage; }
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync typedef struct
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync /** The size of this structure expressed in rcts entries. */
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync /** The number of entries in the rcts array. */
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync /** Variable sized array of the rectangle that makes up the region. */
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync /** The current valid region, all access is by atomic cmpxchg or atomic xchg.
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * The protocol for updating and using this has to take into account that
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * the producer (SetVisibleRegion) and consumer (paintEvent) are running
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * on different threads. Therefore the producer will create a new RegionRects
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * structure before atomically replace the existing one. While the consumer
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * will read the value by atomically replace it by NULL, and then when its
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * done try restore it by cmpxchg. If the producer has already put a new
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * region there, it will be discarded (see mRegionUnused).
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync /** For keeping the unused region and thus avoid some RTMemAlloc/RTMemFree calls.
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync * This is operated with atomic cmpxchg and atomic xchg. */
b0af0b78d25ede09c0d23b2be9163cf43c7ca6f8vboxsync#endif // !__VBoxFrameBuffer_h__