VBoxFrameBuffer.h revision e7556810b5751af1bf99f56663d2266f5b3758d5
/** @file
*
* VBox frontends: Qt GUI ("VirtualBox"):
* VBoxFrameBuffer class and subclasses declarations
*/
/*
* Copyright (C) 2006-2007 Sun Microsystems, Inc.
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 USA or visit http://www.sun.com if you need
* additional information or have any questions.
*/
#ifndef ___VBoxFrameBuffer_h___
#define ___VBoxFrameBuffer_h___
#include "COMDefs.h"
#include <iprt/critsect.h>
/* Qt includes */
#include <QImage>
#include <QPixmap>
#include <QMutex>
#include <QPaintEvent>
#include <QMoveEvent>
#if defined (VBOX_GUI_USE_QGL)
#include <QGLWidget>
#endif
#if defined (VBOX_GUI_USE_SDL)
#include <SDL.h>
#include <signal.h>
#endif
#if defined (Q_WS_WIN) && defined (VBOX_GUI_USE_DDRAW)
#include <ddraw.h>
#endif
/////////////////////////////////////////////////////////////////////////////
/**
* Frame buffer resize event.
*/
{
};
/**
* Frame buffer repaint event.
*/
{
VBoxRepaintEvent (int x, int y, int w, int h) :
{}
int x() { return ex; }
int y() { return ey; }
};
/**
* Frame buffer set region event.
*/
{
};
#ifdef VBOX_WITH_VIDEOHWACCEL
{
struct _VBOXVHWACMD * mpCmd;
};
#endif
/////////////////////////////////////////////////////////////////////////////
/**
* Common IFramebuffer implementation for all methods used by GUI to maintain
* the VM display video memory.
*
* Note that although this class can be called from multiple threads
* (in particular, the GUI thread and EMT) it doesn't protect access to every
* data field using its mutex lock. This is because all synchronization between
* the GUI and the EMT thread is supposed to be done using the
* IFramebuffer::NotifyUpdate() and IFramebuffer::RequestResize() methods
* (in particular, the \a aFinished parameter of these methods is responsible
* for the synchronization). These methods are always called on EMT and
* therefore always follow one another but never in parallel.
*
* Using this object's mutex lock (exposed also in IFramebuffer::Lock() and
* IFramebuffer::Unlock() implementations) usually makes sense only if some
* third-party thread (i.e. other than GUI or EMT) needs to make sure that
* *no* VM display update or resize event can occur while it is accessing
* IFramebuffer properties or the underlying display memory storage area.
*
* See IFramebuffer documentation for more info.
*/
{
#if defined (Q_OS_WIN32)
{
return ::InterlockedIncrement (&refcnt);
}
{
if (cnt == 0)
return cnt;
}
{
if (riid == IID_IUnknown) {
AddRef();
return S_OK;
}
if (riid == IID_IFramebuffer) {
AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
#endif
// IFramebuffer COM methods
BOOL *aSupported);
{
}
virtual bool usesGuestVRAM()
{
return false;
}
/**
* Called on the GUI thread (from VBoxConsoleView) when some part of the
* VM display viewport needs to be repainted on the host screen.
*/
/**
* Called on the GUI thread (from VBoxConsoleView) after it gets a
* VBoxResizeEvent posted from the RequestResize() method implementation.
*/
{
}
/**
* Called on the GUI thread (from VBoxConsoleView) when the VM console
* window is moved.
*/
#ifdef VBOX_WITH_VIDEOHWACCEL
/* this method is called from the GUI thread
* to perform the actual Video HW Acceleration command processing */
#endif
int mWdt;
int mHgt;
#if defined (Q_OS_WIN32)
long refcnt;
#endif
};
/////////////////////////////////////////////////////////////////////////////
#if defined (VBOX_GUI_USE_QIMAGE)
{
bool usesGuestVRAM() { return mUsesGuestVRAM; }
bool mUsesGuestVRAM;
};
#endif
/////////////////////////////////////////////////////////////////////////////
#if defined (VBOX_GUI_USE_QGL)
{
mIsClear(true)
{}
{
{
mIsClear = false;
}
else
{
mIsClear = true;
}
}
{
return;
mIsClear = false;
}
{
return;
}
{
{
mIsClear = true;
}
else
{
mIsClear = false;
}
}
bool intersects(const VBoxVHWADirtyRect & aRect) const {return mIsClear ? false : aRect.intersects(mRect);}
bool mIsClear;
};
{
VBoxVHWAColorKey() :
mUpper(0),
mLower(0)
{}
{}
};
{
mMask(0),
mRange(0),
mOffset(32),
mcBits(0)
{}
};
{
// VBoxVHWAColorFormat(GLint aInternalFormat, GLenum aFormat, GLenum aType, uint32_t aDataFormat);
bool isValid() const {return mBitsPerPixel != 0; }
// uint32_t r(uint32_t pix);
// uint32_t g(uint32_t pix);
// uint32_t b(uint32_t pix);
};
/* data flow:
* I. NON-Yinverted surface:
* mem->tex->fb
* 2.blt
* srcTex->invFB->tex->fb
* |->mem
*
* II. Yinverted surface:
* mem->tex->fb
* 2.blt
* srcTex->fb->tex
* |->mem
* */
{
VBoxVHWASurfaceBase(class VBoxVHWAGlContextState *aState, bool aIsYInverted, GLsizei aWidth, GLsizei aHeight,
static void globalInit();
int blt(const QRect * aDstRect, VBoxVHWASurfaceBase * aSrtSurface, const QRect * aSrcRect, const VBoxVHWAColorKey * pDstCKeyOverride, const VBoxVHWAColorKey * pSrcCKeyOverride);
void performDisplay();
bool addressAlocated() const { return mFreeAddress; }
const VBoxVHWAColorKey * dstOverlayCKey() { return mDstOverlayCKeyValid ? &mDstOverlayCKey : NULL; }
const VBoxVHWAColorKey * srcOverlayCKey() { return mSrcOverlayCKeyValid ? &mSrcOverlayCKey : NULL; }
/* clients should treat the returned texture as read-only */
// /* surface currently being displayed in a flip chain */
// virtual bool isPrimary() = 0;
// /* surface representing the main framebuffer. */
// virtual bool isMainFramebuffer() = 0;
virtual void makeCurrent() = 0;
virtual void makeYInvertedCurrent() = 0;
bool isYInverted() {return mIsYInverted; }
#ifdef VBOX_WITH_VIDEOHWACCEL
static int setCKey(class VBoxVHWAGlProgramVHWA * pProgram, const VBoxVHWAColorFormat * pFormat, const VBoxVHWAColorKey * pCKey);
#endif
void initDisplay();
void deleteDisplay();
bool mDisplayInitialized;
bool mSrcBltCKeyValid;
bool mDstBltCKeyValid;
bool mSrcOverlayCKeyValid;
bool mDstOverlayCKeyValid;
// ulong mDisplayWidth;
// ulong mDisplayHeight;
int mLockCount;
/* memory buffer not reflected in fm and texture, e.g if memory buffer is replaced or in case of lock/unlock */
/* memory buffer not reflected in fm and texture, e.g if memory buffer is replaced or in case of lock/unlock */
/*in case of blit we blit from another surface's texture, so our current texture gets durty */
/*in case of blit the memory buffer does not get updated until we need it, e.g. for paint or lock operations */
bool mFreeAddress;
bool mIsYInverted;
};
{
{
{
mInverted = true;
}
else
{
}
}
{
{
// aContext->makeCurrent();
assertCurrent(aContext, true);
}
else
{
{
// aContext->makeCurrent();
mInverted = true;
}
}
}
{
{
aContext->makeCurrent();
assertCurrent(aContext, false);
}
else
{
{
aContext->makeCurrent();
mInverted = false;
}
}
}
bool isCurrentYInverted() {return mInverted; }
bool mInverted;
};
{
bool bInvisibleBuffer) :
{}
void makeCurrent();
void makeYInvertedCurrent();
void uninit();
// int unlock()
// {
// int rc = VBoxVHWASurfaceBase::unlock();
// if(!mBuffer)
// performDisplay();
// return rc;
// }
#ifdef VBOX_WITH_VIDEOHWACCEL
#endif
};
{
~VBoxGLWidget();
bool vboxUsesGuestVRAM() { return mUsesGuestVRAM; }
typedef void (VBoxGLWidget::*PFNVBOXQGLOP)(void* );
//typedef FNVBOXQGLOP *PFNVBOXQGLOP;
#ifdef DEBUG_misha
#endif
#ifdef VBOX_WITH_VIDEOHWACCEL
void vboxVHWACmd (struct _VBOXVHWACMD * pCmd) {vboxPerformGLOp(&VBoxGLWidget::vboxDoVHWACmd, pCmd);}
#endif
// void resizeGL (int height, int width);
void paintGL()
{
/* we are called with QGLWidget context */
/* restore the context */
/* clear*/
}
void initializeGL();
// void vboxDoInitDisplay();
// void vboxDoDeleteDisplay();
// void vboxDoPerformDisplay() { Assert(mDisplayInitialized); glCallList(mDisplay); }
void vboxDoResize(void *re);
void vboxDoPaint(void *rec);
#ifdef DEBUG_misha
void vboxDoTestSurfaces(void *context);
#endif
#ifdef VBOX_WITH_VIDEOHWACCEL
void vboxDoVHWACmd(void *cmd);
{
if (pSurface->addressAlocated())
{
if(addr)
{
}
}
}
#endif
/* we need to do all opengl stuff in the paintGL context,
* submit the operation to be performed */
void vboxPerformGLOp(PFNVBOXQGLOP pfn, void* pContext) {mpfnOp = pfn; mOpContext = pContext; updateGL();}
void *mOpContext;
// ulong mBitsPerPixel;
bool mUsesGuestVRAM;
#ifdef VBOX_WITH_VIDEOHWACCEL
#endif
};
{
#ifdef VBOX_WITH_VIDEOHWACCEL
#endif
#ifdef VBOX_WITH_VIDEOHWACCEL
#endif
// void vboxMakeCurrent();
VBoxGLWidget * vboxWidget();
};
#endif
/////////////////////////////////////////////////////////////////////////////
#if defined (VBOX_GUI_USE_SDL)
{
{
}
{
}
{
}
{
return mPixelFormat;
}
bool usesGuestVRAM()
{
}
};
#endif
/////////////////////////////////////////////////////////////////////////////
#if defined (VBOX_GUI_USE_DDRAW)
{
bool usesGuestVRAM() { return mUsesGuestVRAM; }
void releaseObjects();
void deleteSurface();
void getWindowPosition (void);
bool mUsesGuestVRAM;
int mWndX;
int mWndY;
bool mSynchronousUpdates;
};
#endif
/////////////////////////////////////////////////////////////////////////////
#if defined (Q_WS_MAC) && defined (VBOX_GUI_USE_QUARTZ2D)
{
void clean();
void *mBitmapData;
typedef struct
{
/** The size of this structure expressed in rcts entries. */
/** The number of entries in the rcts array. */
/** Variable sized array of the rectangle that makes up the region. */
} RegionRects;
/** The current valid region, all access is by atomic cmpxchg or atomic xchg.
*
* The protocol for updating and using this has to take into account that
* the producer (SetVisibleRegion) and consumer (paintEvent) are running
* on different threads. Therefore the producer will create a new RegionRects
* structure before atomically replace the existing one. While the consumer
* will read the value by atomically replace it by NULL, and then when its
* done try restore it by cmpxchg. If the producer has already put a new
* region there, it will be discarded (see mRegionUnused).
*/
RegionRects volatile *mRegion;
/** For keeping the unused region and thus avoid some RTMemAlloc/RTMemFree calls.
* This is operated with atomic cmpxchg and atomic xchg. */
RegionRects volatile *mRegionUnused;
};
#endif /* Q_WS_MAC && VBOX_GUI_USE_QUARTZ2D */
#endif // !___VBoxFrameBuffer_h___