VBoxFBOverlay.h revision e66911cff9c18da76d9bddb0505ad329a9ccd795
/** @file
*
* VBox frontends: Qt GUI ("VirtualBox"):
* VBoxFrameBuffer Overly classes 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 __VBoxFBOverlay_h__
#define __VBoxFBOverlay_h__
#if defined (VBOX_GUI_USE_QGL) || defined(VBOX_WITH_VIDEOHWACCEL)
//#define VBOXQGL_PROF_BASE 1
//#define VBOXQGL_DBG_SURF 1
#include "COMDefs.h"
#include <QGLWidget>
#include <iprt/critsect.h>
#include <VBox/VBoxGL2D.h>
#include "VBoxFBOverlayCommon.h"
#define VBOXVHWA_ALLOW_PRIMARY_AND_OVERLAY_ONLY 1
#ifdef DEBUG_misha
# define VBOXVHWA_PROFILE_FPS
#endif
#ifdef DEBUG
{
~VBoxVHWADbgTimer();
void frame();
};
#endif
{
mIsClear(true)
{}
{
{
mIsClear = false;
}
else
{
mIsClear = true;
}
}
{
return;
mIsClear = false;
}
{
return;
}
{
{
mIsClear = true;
}
else
{
mIsClear = false;
}
}
{
if(isClear())
{
}
return mRect;
}
bool intersects(const VBoxVHWADirtyRect & aRect) const {return mIsClear ? false : aRect.intersects(mRect);}
bool mIsClear;
};
{
VBoxVHWAColorKey() :
mUpper(0),
mLower(0)
{}
{}
bool operator==(const VBoxVHWAColorKey & other) const { return mUpper == other.mUpper && mLower == other.mLower; }
};
{
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 bitsPerPixelDd() const { return mBitsPerPixelDd; }
const VBoxVHWAColorComponent& r() const {return mR;}
const VBoxVHWAColorComponent& g() const {return mG;}
const VBoxVHWAColorComponent& b() const {return mB;}
const VBoxVHWAColorComponent& a() const {return mA;}
// uint32_t mBitsPerPixelDd;
};
{
VBoxVHWATexture() {}
// GLuint texture() {return mTexture;}
uint32_t rectSizeTex(const QRect * pRect) {return pRect->width() * pRect->height() * mBytesPerPixelTex;}
uchar * pointAddress(int x, int y)
{
x = toXTex(x);
y = toYTex(y);
return pointAddressTex(x, y);
}
virtual void initParams();
void uninit();
};
{
VBoxVHWATextureNP2() : VBoxVHWATexture() {}
mTexRect = QRect(0, 0, aRect.width()/aFormat.widthCompression(), aRect.height()/aFormat.heightCompression());
}
};
{
VBoxVHWATextureNP2Rect() : VBoxVHWATextureNP2() {}
};
{
};
#ifdef VBOXVHWA_USE_TEXGROUP
{
{
init(0, 0);
}
{
}
{
delete[] mpDisplays;
}
void swap()
{
if(mCur)
else
}
{
mCur = 0;
if(mcTextures)
{
}
else
{
mpDisplays = NULL;
}
}
GLuint * mpDisplays;
};
#endif
{
void** mTable;
};
/* 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
*
* III. flip support:
* 1. Yinverted<->NON-YInverted conversion :
* mem->tex-(rotate model view, force LAZY complete fb update)->invFB->tex
* fb-->| |->mem
* */
{
#if 0
bool aIsYInverted,
#endif
const QRect & aVisTargRect,
#ifdef VBOXVHWA_USE_TEXGROUP
#endif
bool bVGA);
void uninit();
static void globalInit();
// int blt(const QRect * aDstRect, VBoxVHWASurfaceBase * aSrtSurface, const QRect * aSrcRect, const VBoxVHWAColorKey * pDstCKeyOverride, const VBoxVHWAColorKey * pSrcCKeyOverride);
int unlock();
void setVisibilityReinitFlag() { mNeedVisibilityReinit = true; }
void updateVisibility (VBoxVHWASurfaceBase *pPrimary, const QRect & aVisibleTargRect, bool bNotIntersected, bool bForce);
bool addressAlocated() const { return mFreeAddress; }
// ulong bytesPerPixel() { return mpTex[0]->bytesPerPixel(); }
// ulong bitsPerPixelDd() { return mColorFormat.bitsPerPixelDd(); }
{
if(ckey)
{
mDstBltCKey = *ckey;
}
else
{
mpDstBltCKey = NULL;
}
}
{
if(ckey)
{
mSrcBltCKey = *ckey;
}
else
{
mpSrcBltCKey = NULL;
}
}
{
if(ckey)
{
}
else
{
}
}
{
if(ckey)
{
}
else
{
}
}
{
if(ckey)
{
}
else
{
}
}
{
if(ckey)
{
}
else
{
}
}
const VBoxVHWAColorKey * getActiveSrcOverlayCKey()
{
return mpSrcOverlayCKey;
}
{
}
static int setCKey(class VBoxVHWAGlProgramVHWA * pProgram, const VBoxVHWAColorFormat * pFormat, const VBoxVHWAColorKey * pCKey, bool bDst);
{
return mpProgram;
return calcProgram(pPrimary);
}
void deleteDisplay();
int createDisplay(VBoxVHWASurfaceBase *pPrimary, GLuint *pDisplay, class VBoxVHWAGlProgramVHWA ** ppProgram);
int performBlt(const QRect * pDstRect, VBoxVHWASurfaceBase * pSrcSurface, const QRect * pSrcRect, const VBoxVHWAColorKey * pDstCKey, const VBoxVHWAColorKey * pSrcCKey, bool blt);
void doMultiTex2FB(const QRect * pDstRect, VBoxVHWATexture * pDstTex, const QRect * pSrcRect, int cSrcTex);
#ifndef VBOXVHWA_USE_TEXGROUP
#endif
bool mNeedVisibilityReinit;
bool mNotIntersected;
#ifdef VBOXVHWA_USE_TEXGROUP
#else
#endif
int mLockCount;
/* memory buffer not reflected in fm and texture, e.g if memory buffer is replaced or in case of lock/unlock */
bool mFreeAddress;
#ifdef DEBUG
#endif
};
{
{
if(pOld)
{
}
}
void clear()
{
{
}
}
{
}
{
}
};
{
VBoxVHWADisplay() :
mbDisplayPrimary(true)
// ,
// mSurfPrimary(NULL)
{}
{
if(pVga)
{
}
// mSurfPrimary = pVga;
return old;
}
{
return old;
}
VBoxVHWASurfaceBase * getVGA() const
{
return mSurfVGA;
}
{
}
{
}
{
if(!hasOverlay(pSurf))
}
{
{
{
return true;
}
}
return false;
}
{
}
bool performDisplay(bool bForce)
{
if(mbDisplayPrimary)
{
#ifdef DEBUG_misha
/* should only display overlay now */
#endif
}
{
if(pOverlay)
{
}
}
return bForce;
}
bool mbDisplayPrimary;
};
typedef void (VBoxGLWidget::*PFNVBOXQGLOP)(void* );
typedef void (*PFNVBOXQGLFUNC)(void*, void*);
typedef enum
{
typedef struct VBOXVHWACALLBACKINFO
{
void * pContext;
typedef struct VBOXVHWAFUNCCALLBACKINFO
{
void * pContext1;
void * pContext2;
{
{
}
{
}
{
}
{
u.mFuncCallback = aOp;
}
{
switch(aType)
{
case VBOXVHWA_PIPECMD_PAINT:
break;
case VBOXVHWA_PIPECMD_VHWA:
break;
case VBOXVHWA_PIPECMD_OP:
break;
case VBOXVHWA_PIPECMD_FUNC:
break;
default:
Assert(0);
break;
}
}
union
{
struct _VBOXVHWACMD * mpCmd;
}u;
};
{
{}
{
if(mpLast)
{
}
else
{
}
}
{
if(mpLast)
{
return pHead;
}
return NULL;
}
};
{
{
}
{
}
{
if(mpFirst)
{
return ret;
}
return NULL;
}
};
#define VBOXVHWACMDPIPEC_NEWEVENT 0x00000001
#define VBOXVHWACMDPIPEC_COMPLETEEVENT 0x00000002
{
void completeCurrentEvent();
class VBoxVHWACommandElement * detachCmdList(class VBoxVHWACommandElement * pFirst2Free, VBoxVHWACommandElement * pLast2Free);
bool mbNewEvent;
bool mbProcessingList;
};
{
};
{
~VBoxGLWidget();
bool vboxUsesGuestVRAM() { return mUsesGuestVRAM; }
#ifdef VBOX_WITH_VIDEOHWACCEL
bool hasSurfaces() const;
bool hasVisibleOverlays();
#endif
void vboxDoResize(void *re);
// void vboxPaintEvent (QPaintEvent *pe) {vboxPerformGLOp(&VBoxGLWidget::vboxDoPaint, pe); }
void vboxResizeEvent (class VBoxResizeEvent *re) {vboxPerformGLOp(&VBoxGLWidget::vboxDoResize, re); }
void vboxProcessVHWACommands(class VBoxVHWACommandElementProcessor * pPipe) {vboxPerformGLOp(&VBoxGLWidget::vboxDoProcessVHWACommands, pPipe);}
#ifdef VBOXVHWA_OLD_COORD
#endif
#ifdef VBOXVHWA_PROFILE_FPS
void reportNewFrame() { mbNewFrame = true; }
#endif
bool performDisplayAndSwap(bool bForce)
{
// VBOXQGLLOG_METHODTIME("t:");
if(bForce)
{
swapBuffers();
}
#ifdef VBOXVHWA_PROFILE_FPS
if(mbNewFrame)
{
mFPSCounter.frame();
{
}
mbNewFrame = false;
}
#endif
return bForce;
}
void paintGL()
{
if(mpfnOp)
{
}
VBOXQGLLOG(("paintGL\n"));
// else
// {
mDisplay.performDisplay(true);
// }
}
void initializeGL();
// void vboxDoPaint(void *rec);
#ifdef VBOXQGL_DBG_SURF
void vboxDoTestSurfaces(void *context);
#endif
#ifdef VBOX_WITH_VIDEOHWACCEL
void vboxDoVHWACmdExec(void *cmd);
void vboxDoVHWACmdAndFree(void *cmd);
void vboxDoVHWACmd(void *cmd);
{
if (pSurface->addressAlocated())
{
if(addr)
{
}
}
}
static int vhwaLoadSurface(VHWACommandList * pCmdList, struct SSMHANDLE * pSSM, uint32_t cBackBuffers, uint32_t u32Version);
static int vhwaLoadOverlayData(VHWACommandList * pCmdList, struct SSMHANDLE * pSSM, uint32_t u32Version);
void vhwaDoSurfaceOverlayUpdate(VBoxVHWASurfaceBase *pDstSurf, VBoxVHWASurfaceBase *pSrcSurf, struct _VBOXVHWACMD_SURF_OVERLAY_UPDATE *pCmd);
#endif
static const QGLFormat & vboxGLFormat();
/* we do all opengl stuff in the paintGL context,
* submit the operation to be performed
* @todo: could be moved outside the updateGL */
{
updateGL();
}
// /* posts op to UI thread */
// int vboxExecOpSynch(PFNVBOXQGLOP pfn, void* pContext);
// void vboxExecOnResize(PFNVBOXQGLOP pfn, void* pContext);
void vboxDoProcessVHWACommands(void *pContext);
{
return pSurf;
}
void *mOpContext;
bool mUsesGuestVRAM;
bool mRepaintNeeded;
// bool mbVGASurfCreated;
/* this is used in saved state restore to postpone surface restoration
* till the framebuffer size is restored */
#ifdef VBOXVHWA_PROFILE_FPS
bool mbNewFrame;
#endif
};
//typedef enum
//{
// VBOXFBOVERLAY_DONE = 1,
// VBOXFBOVERLAY_MODIFIED,
// VBOXFBOVERLAY_UNTOUCHED
//} VBOXFBOVERLAY_RESUT;
{
/**
* to be called on NotifyUpdate framebuffer call
* @return true if the request was processed & should not be forwarded to the framebuffer
* false - otherwise */
/**
* to be called on RequestResize framebuffer call
* @return true if the request was processed & should not be forwarded to the framebuffer
* false - otherwise */
BOOL * /*aFinished*/)
{
return false;
}
// VBOXFBOVERLAY_RESUT onPaintEvent (const QPaintEvent *pe, QRect *pRect);
{
mGlCurrent = false;
}
{
mGlCurrent = false;
}
static bool isAcceleration2DVideoAvailable();
/** additional video memory required for the best 2D support performance
* total amount of VRAM required is thus calculated as requiredVideoMemory + required2DOffscreenVideoMemory */
static quint64 required2DOffscreenVideoMemory();
/* not supposed to be called by clients */
void repaintMain();
void repaintOverlay()
{
{
mNeedOverlayRepaint = false;
}
if(mNeedSetVisible)
{
mNeedSetVisible = false;
mpOverlayWidget->setVisible(true);
}
}
void repaint()
{
repaintMain();
}
void makeCurrent()
{
if(!mGlCurrent)
{
mGlCurrent = true;
}
}
void performDisplayOverlay()
{
if(mOverlayVisible)
{
#if 0
#else
makeCurrent();
mpOverlayWidget->performDisplayAndSwap(false);
#endif
}
}
// void vboxOpExit()
// {
// performDisplayOverlay();
// mGlCurrent = false;
// }
void vboxSetGlOn(bool on);
bool vboxGetGlOn() { return mGlOn; }
bool vboxSynchGl();
void vboxDoVHWACmdExec(void *cmd);
void vboxShowOverlay(bool show);
void vboxDoCheckUpdateViewport();
void vboxDoVHWACmd(void *cmd);
// void vboxUpdateOverlayPosition(const QPoint & pos);
int reset();
int resetGl();
void initGl();
bool mGlOn;
bool mOverlayWidgetVisible;
bool mOverlayVisible;
bool mGlCurrent;
bool mProcessingCommands;
bool mNeedOverlayRepaint;
bool mNeedSetVisible;
/* this is used in saved state restore to postpone surface restoration
* till the framebuffer size is restored */
};
{
: T(aView),
{}
{
}
{
}
{
{
return S_OK;
}
}
{
return S_OK;
}
// void paintEvent (QPaintEvent *pe)
// {
// QRect rect;
// VBOXFBOVERLAY_RESUT res = mOverlay.onPaintEvent(pe, &rect);
// switch(res)
// {
// case VBOXFBOVERLAY_MODIFIED:
// {
// QPaintEvent modified(rect);
// T::paintEvent(&modified);
// } break;
// case VBOXFBOVERLAY_UNTOUCHED:
// T::paintEvent(pe);
// break;
// default:
// break;
// }
// }
{
T::resizeEvent(re);
}
{
T::viewportResized(re);
}
{
}
};
#endif
#endif /* #ifndef __VBoxFBOverlay_h__ */