Kaydet (Commit) e26237f6 authored tarafından Louis-Francis Ratté-Boulianne's avatar Louis-Francis Ratté-Boulianne Kaydeden (comit) Jan Holesovsky

vcl: Always use the same OpenGL context when drawing in a window

Change-Id: Ief0e947149c133aaa8e81973e088c4df6432bfdc
üst 90af2a6c
......@@ -175,6 +175,9 @@ public:
bool init( HDC hDC, HWND hWnd );
#endif
void AddRef();
void DeRef();
void makeCurrent();
void resetCurrent();
void swapBuffers();
......@@ -219,12 +222,17 @@ private:
SystemChildWindow* m_pChildWindow;
boost::scoped_ptr<SystemChildWindow> m_pChildWindowGC;
bool mbInitialized;
int mnRefCount;
bool mbRequestLegacyContext;
bool mbUseDoubleBufferedRendering;
bool mbRequestVirtualDevice;
#if defined( UNX ) && !defined MACOSX && !defined IOS && !defined ANDROID
bool mbPixmap; // is a pixmap instead of a window
#endif
public:
OpenGLContext* mpPrevContext;
OpenGLContext* mpNextContext;
};
#endif
......
......@@ -15,6 +15,8 @@
#include "openglgdiimpl.hxx"
#include "win/salgdi.h"
class OpenGLContext;
class WinOpenGLSalGraphicsImpl : public OpenGLSalGraphicsImpl
{
friend class WinLayout;
......@@ -24,9 +26,16 @@ private:
public:
WinOpenGLSalGraphicsImpl(WinSalGraphics& rGraphics);
virtual void Init() SAL_OVERRIDE;
protected:
virtual GLfloat GetWidth() const SAL_OVERRIDE;
virtual GLfloat GetHeight() const SAL_OVERRIDE;
virtual bool IsOffscreen() const SAL_OVERRIDE;
virtual OpenGLContext* CreateWinContext() SAL_OVERRIDE;
virtual bool CompareWinContext( OpenGLContext* pContext ) SAL_OVERRIDE;
virtual OpenGLContext* CreatePixmapContext() SAL_OVERRIDE;
public:
virtual void copyBits( const SalTwoRect& rPosAry, SalGraphics* pSrcGraphics ) SAL_OVERRIDE;
......
......@@ -28,12 +28,16 @@ public:
protected:
GLfloat GetWidth() const SAL_OVERRIDE;
GLfloat GetHeight() const SAL_OVERRIDE;
bool IsOffscreen() const SAL_OVERRIDE;
virtual OpenGLContext* CreateWinContext() SAL_OVERRIDE;
virtual bool CompareWinContext( OpenGLContext* pContext ) SAL_OVERRIDE;
virtual OpenGLContext* CreatePixmapContext() SAL_OVERRIDE;
public:
// implementation of X11GraphicsImpl
virtual void copyBits( const SalTwoRect& rPosAry, SalGraphics* pSrcGraphics ) SAL_OVERRIDE;
void Init() SAL_OVERRIDE;
bool FillPixmapFromScreen( X11Pixmap* pPixmap, int nX, int nY ) SAL_OVERRIDE;
bool RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY ) SAL_OVERRIDE;
};
......
......@@ -35,9 +35,9 @@ class VCL_PLUGIN_PUBLIC OpenGLSalGraphicsImpl : public SalGraphicsImpl
{
protected:
OpenGLContext maContext;
SalFrame* mpFrame;
int mnPainting;
OpenGLContext* mpContext;
// clipping
bool mbUseScissor;
......@@ -144,21 +144,35 @@ public:
// get the height of the device
virtual GLfloat GetHeight() const = 0;
// check whether this instance is used for offscreen rendering
virtual bool IsOffscreen() const = 0;
// operations to do before painting
virtual void PreDraw();
// operations to do after painting
virtual void PostDraw();
// enable/disable offscreen rendering
virtual void SetOffscreen( bool bOffscreen );
protected:
bool AcquireContext( bool bOffscreen );
bool ReleaseContext();
// create a new context for window rendering
virtual OpenGLContext* CreateWinContext() = 0;
// check whether the given context can be used by this instance
virtual bool CompareWinContext( OpenGLContext* pContext ) = 0;
// create a new context for window rendering
virtual OpenGLContext* CreatePixmapContext() = 0;
public:
OpenGLSalGraphicsImpl();
virtual ~OpenGLSalGraphicsImpl ();
OpenGLContext& GetOpenGLContext() { return maContext; }
OpenGLContext& GetOpenGLContext() { return *mpContext; }
virtual void Init() SAL_OVERRIDE;
virtual void freeResources() SAL_OVERRIDE;
......
......@@ -44,6 +44,8 @@ public:
virtual ~SalGraphicsImpl();
virtual void Init() = 0;
virtual void freeResources() = 0;
virtual bool setClipRegion( const vcl::Region& ) = 0;
......
......@@ -89,6 +89,7 @@ class SalI18NImeStatus;
class DockingManager;
class VclEventListeners2;
class SalData;
class OpenGLContext;
namespace vcl { class DisplayConnection; class SettingsConfigItem; class DeleteOnDeinitBase; }
......@@ -161,6 +162,8 @@ struct ImplSVGDIData
OutputDevice* mpLastPrnGraphics; // Last OutputDevice with a InfoPrinter Graphics
VirtualDevice* mpFirstVirDev; // First VirtualDevice
VirtualDevice* mpLastVirDev; // Last VirtualDevice
OpenGLContext* mpFirstContext; // First OpenGLContext
OpenGLContext* mpLastContext; // Last OpenGLContext
Printer* mpFirstPrinter; // First Printer
Printer* mpLastPrinter; // Last Printer
ImplPrnQueueList* mpPrinterQueueList; // List of all printer queue
......
......@@ -17,7 +17,6 @@ class X11GraphicsImpl
public:
virtual ~X11GraphicsImpl() {};
virtual void Init() = 0;
virtual bool FillPixmapFromScreen( X11Pixmap* pPixmap, int nX, int nY ) = 0;
virtual bool RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY ) = 0;
};
......
......@@ -181,6 +181,7 @@ public:
class WinSalGraphics : public SalGraphics
{
friend class WinSalGraphicsImpl;
friend class WinOpenGLSalGraphicsImpl;
friend class ScopedFont;
friend class OpenGLCompatibleDC;
friend class WinLayout;
......
......@@ -31,6 +31,7 @@
#include <vcl/opengl/OpenGLHelper.hxx>
#include "salgdi.hxx"
#include "svdata.hxx"
#include "opengl/salbmp.hxx"
#include <glm/glm.hpp>
......@@ -63,8 +64,7 @@
1.0f )
OpenGLSalGraphicsImpl::OpenGLSalGraphicsImpl()
: mpFrame(NULL)
, mnPainting(0)
: mpContext(0)
, mbUseScissor(false)
, mbUseStencil(false)
, mbOffscreen(false)
......@@ -109,11 +109,106 @@ OpenGLSalGraphicsImpl::OpenGLSalGraphicsImpl()
OpenGLSalGraphicsImpl::~OpenGLSalGraphicsImpl()
{
ReleaseContext();
}
bool OpenGLSalGraphicsImpl::AcquireContext( bool bOffscreen )
{
ImplSVData* pSVData = ImplGetSVData();
if( mpContext )
mpContext->DeRef();
if( bOffscreen )
{
mpContext = CreatePixmapContext();
return (mpContext != NULL);
}
OpenGLContext* pContext = pSVData->maGDIData.mpLastContext;
while( pContext )
{
// check if this context can be used by this SalGraphicsImpl instance
if( CompareWinContext( pContext ) )
break;
pContext = pContext->mpPrevContext;
}
if( pContext )
pContext->AddRef();
else
pContext = CreateWinContext();
mpContext = pContext;
return (mpContext != NULL);
}
bool OpenGLSalGraphicsImpl::ReleaseContext()
{
if( mpContext )
mpContext->DeRef();
mpContext = NULL;
return true;
}
void OpenGLSalGraphicsImpl::Init()
{
const bool bOffscreen = IsOffscreen();
// check if we can simply re-use the same context
if( mpContext )
{
if( bOffscreen != mbOffscreen || ( !mbOffscreen && CompareWinContext( mpContext ) ) )
ReleaseContext();
}
if( !mpContext && !AcquireContext( bOffscreen ) )
{
SAL_WARN( "vcl.opengl", "Couldn't acquire context for SalGraphics" );
return;
}
mpContext->makeCurrent();
if( mbOffscreen == bOffscreen )
{
// Nothing more to do for onscreen case
if( !mbOffscreen )
return;
// Already enabled and same size
if( maOffscreenTex.GetWidth() == GetWidth() &&
maOffscreenTex.GetHeight() == GetHeight() )
return;
}
else
{
mbOffscreen = bOffscreen;
if( bOffscreen )
glGenFramebuffers( 1, &mnFramebufferId );
else
glDeleteFramebuffers( 1, &mnFramebufferId );
}
// Create/update attached offscreen texture
if( mbOffscreen )
{
glBindFramebuffer( GL_FRAMEBUFFER, mnFramebufferId );
maOffscreenTex = OpenGLTexture( GetWidth(), GetHeight() );
glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, maOffscreenTex.Id(), 0 );
GLenum nStatus = glCheckFramebufferStatus( GL_FRAMEBUFFER );
if( nStatus != GL_FRAMEBUFFER_COMPLETE )
SAL_WARN( "vcl.opengl", "Incomplete framebuffer " << nStatus );
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
CHECK_GL_ERROR();
}
}
void OpenGLSalGraphicsImpl::PreDraw()
{
maContext.makeCurrent();
assert( mpContext && mpContext->isInitialized() );
mpContext->makeCurrent();
// TODO: lfrb: make sure the render target has the right size
if( mbOffscreen )
CheckOffscreenTexture();
......@@ -273,46 +368,17 @@ void OpenGLSalGraphicsImpl::SetROPFillColor( SalROPColor /*nROPColor*/ )
{
}
// enable/disbale offscreen rendering
void OpenGLSalGraphicsImpl::SetOffscreen( bool bOffscreen )
{
if( bOffscreen == mbOffscreen )
{
// Already disabled
if( !mbOffscreen )
return;
// Already enabled and same size
if( maOffscreenTex.GetWidth() == GetWidth() &&
maOffscreenTex.GetHeight() == GetHeight() )
return;
}
else
{
mbOffscreen = bOffscreen;
if( bOffscreen )
glGenFramebuffers( 1, &mnFramebufferId );
else
glDeleteFramebuffers( 1, &mnFramebufferId );
}
if( mbOffscreen )
{
glBindFramebuffer( GL_FRAMEBUFFER, mnFramebufferId );
maOffscreenTex = OpenGLTexture( GetWidth(), GetHeight() );
glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, maOffscreenTex.Id(), 0 );
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
}
CHECK_GL_ERROR();
}
bool OpenGLSalGraphicsImpl::CheckOffscreenTexture()
{
glBindFramebuffer( GL_FRAMEBUFFER, mnFramebufferId );
if( maOffscreenTex.IsUnique() )
{
GLenum nStatus = glCheckFramebufferStatus( GL_FRAMEBUFFER );
if( nStatus != GL_FRAMEBUFFER_COMPLETE )
SAL_WARN( "vcl.opengl", "Incomplete framebuffer " << nStatus );
return true;
}
SalTwoRect aPosAry;
aPosAry.mnSrcX = aPosAry.mnDestX = 0;
......@@ -1811,7 +1877,7 @@ void OpenGLSalGraphicsImpl::endPaint()
SAL_INFO( "vcl.opengl", "END PAINT " << this );
if( mnPainting == 0 )
{
maContext.makeCurrent();
mpContext->makeCurrent();
glFlush();
}
}
......
......@@ -68,4 +68,34 @@ GLfloat WinOpenGLSalGraphicsImpl::GetHeight() const
return 1;
}
bool WinOpenGLSalGraphicsImpl::IsOffscreen() const
{
WinSalFrame* pFrame = GetWindowPtr( mrParent.gethWnd() );
return ( pFrame == NULL );
}
OpenGLContext* WinOpenGLSalGraphicsImpl::CreateWinContext()
{
OpenGLContext* pContext = new OpenGLContext();
pContext->requestSingleBufferedRendering();
pContext->init( mrParent.mhLocalDC, mrParent.mhWnd );
return pContext;
}
bool WinOpenGLSalGraphicsImpl::CompareWinContext( OpenGLContext* pContext )
{
if( !pContext || !pContext->isInitialized() )
return false;
return ( pContext->getOpenGLWindow().hWnd == mrParent.mhWnd );
}
OpenGLContext* WinOpenGLSalGraphicsImpl::CreatePixmapContext()
{
OpenGLContext* pContext = new OpenGLContext();
pContext->requestVirtualDevice();
pContext->requestSingleBufferedRendering();
pContext->init( mrParent.mhLocalDC, mrParent.mhWnd );
return pContext;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
......@@ -59,31 +59,53 @@ GLfloat X11OpenGLSalGraphicsImpl::GetHeight() const
return 1;
}
void X11OpenGLSalGraphicsImpl::Init()
bool X11OpenGLSalGraphicsImpl::IsOffscreen() const
{
X11WindowProvider *pProvider = dynamic_cast<X11WindowProvider*>(mrParent.m_pFrame);
// Called after eg. a vdev re-size where we need to update the underlying pixmap
maContext.resetToReInitialize();
if (pProvider)
{
Window aWin = pProvider->GetX11Window();
maContext.init( mrParent.GetXDisplay(), aWin, mrParent.m_nXScreen.getXScreen());
SetOffscreen( false );
}
if( pProvider )
return false;
else if( mrParent.m_pVDev )
{
maContext.init( mrParent.GetXDisplay(), mrParent.m_pVDev->GetDrawable(),
mrParent.m_pVDev->GetWidth(), mrParent.m_pVDev->GetHeight(),
mrParent.m_nXScreen.getXScreen() );
SetOffscreen( true );
}
return true;
else
{
SAL_WARN( "vcl.opengl", "what happened here?" );
return true;
}
}
OpenGLContext* X11OpenGLSalGraphicsImpl::CreateWinContext()
{
X11WindowProvider *pProvider = dynamic_cast<X11WindowProvider*>(mrParent.m_pFrame);
if( !pProvider )
return NULL;
Window aWin = pProvider->GetX11Window();
OpenGLContext* pContext = new OpenGLContext();
pContext->init( mrParent.GetXDisplay(), aWin,
mrParent.m_nXScreen.getXScreen() );
return pContext;
}
bool X11OpenGLSalGraphicsImpl::CompareWinContext( OpenGLContext* pContext )
{
X11WindowProvider *pProvider = dynamic_cast<X11WindowProvider*>(mrParent.m_pFrame);
if( !pProvider || !pContext->isInitialized() )
return false;
return ( pContext->getOpenGLWindow().win == pProvider->GetX11Window() );
}
OpenGLContext* X11OpenGLSalGraphicsImpl::CreatePixmapContext()
{
if( mrParent.m_pVDev == NULL )
return NULL;
OpenGLContext* pContext = new OpenGLContext();
pContext->init( mrParent.GetXDisplay(), mrParent.m_pVDev->GetDrawable(),
mrParent.m_pVDev->GetWidth(), mrParent.m_pVDev->GetHeight(),
mrParent.m_nXScreen.getXScreen() );
return pContext;
}
void X11OpenGLSalGraphicsImpl::copyBits( const SalTwoRect& rPosAry, SalGraphics* pSrcGraphics )
{
OpenGLSalGraphicsImpl *pImpl = pSrcGraphics ? static_cast< OpenGLSalGraphicsImpl* >(pSrcGraphics->GetImpl()) : static_cast< OpenGLSalGraphicsImpl *>(mrParent.GetImpl());
......@@ -104,7 +126,7 @@ bool X11OpenGLSalGraphicsImpl::FillPixmapFromScreen( X11Pixmap* pPixmap, int nX,
return false;
// make sure everything is synced up before reading back
maContext.makeCurrent();
mpContext->makeCurrent();
glXWaitX();
// TODO: lfrb: What if offscreen?
......
......@@ -27,6 +27,8 @@
#include <win/saldata.hxx>
#endif
#include "svdata.hxx"
using namespace com::sun::star;
// TODO use rtl::Static instead of 'static'
......@@ -47,13 +49,26 @@ OpenGLContext::OpenGLContext():
mpWindow(NULL),
m_pChildWindow(NULL),
mbInitialized(false),
mnRefCount(1),
mbRequestLegacyContext(false),
mbUseDoubleBufferedRendering(true),
mbRequestVirtualDevice(false)
mbRequestVirtualDevice(false),
mpPrevContext(NULL),
mpNextContext(NULL)
{
#if defined( UNX ) && !defined MACOSX && !defined IOS && !defined ANDROID
mbPixmap = false;
#endif
ImplSVData* pSVData = ImplGetSVData();
if( pSVData->maGDIData.mpLastContext )
{
pSVData->maGDIData.mpLastContext->mpNextContext = this;
mpPrevContext = pSVData->maGDIData.mpLastContext;
}
else
pSVData->maGDIData.mpFirstContext = this;
pSVData->maGDIData.mpLastContext = this;
}
OpenGLContext::~OpenGLContext()
......@@ -67,6 +82,16 @@ OpenGLContext::~OpenGLContext()
wglDeleteContext( m_aGLWin.hRC );
ReleaseDC( m_aGLWin.hWnd, m_aGLWin.hDC );
}
ImplSVData* pSVData = ImplGetSVData();
if( mpPrevContext )
mpPrevContext->mpNextContext = mpNextContext;
else
pSVData->maGDIData.mpFirstContext = mpNextContext;
if( mpNextContext )
mpNextContext->mpPrevContext = mpPrevContext;
else
pSVData->maGDIData.mpLastContext = mpPrevContext;
#elif defined( MACOSX )
OpenGLWrapper::resetCurrent();
#elif defined( IOS ) || defined( ANDROID )
......@@ -89,6 +114,17 @@ OpenGLContext::~OpenGLContext()
#endif
}
void OpenGLContext::AddRef()
{
mnRefCount++;
}
void OpenGLContext::DeRef()
{
if( --mnRefCount == 0 )
delete this;
}
void OpenGLContext::requestLegacyContext()
{
mbRequestLegacyContext = true;
......
......@@ -151,7 +151,7 @@ void X11SalGraphics::SetDrawable( Drawable aDrawable, SalX11Screen nXScreen )
if( hDrawable_ )
{
dynamic_cast<X11GraphicsImpl&>(*mpImpl.get()).Init();
mpImpl->Init();
// TODO: moggi: FIXME nTextPixel_ = GetPixel( nTextColor_ );
}
}
......
......@@ -294,6 +294,10 @@ WinSalGraphicsImpl::~WinSalGraphicsImpl()
}
void WinSalGraphicsImpl::Init()
{
}
void WinSalGraphicsImpl::freeResources()
{
}
......
......@@ -52,6 +52,8 @@ public:
virtual ~WinSalGraphicsImpl();
virtual void Init() SAL_OVERRIDE;
virtual void freeResources() SAL_OVERRIDE;
virtual bool setClipRegion( const vcl::Region& ) SAL_OVERRIDE;
......
......@@ -482,15 +482,7 @@ void WinSalGraphics::InitGraphics()
::SetTextAlign( getHDC(), TA_BASELINE | TA_LEFT | TA_NOUPDATECP );
::SetBkMode( getHDC(), WIN32_TRANSPARENT );
::SetROP2( getHDC(), R2_COPYPEN );
OpenGLSalGraphicsImpl* pImpl = dynamic_cast<OpenGLSalGraphicsImpl*>(mpImpl.get());
if (pImpl)
{
if (mbVirDev)
pImpl->GetOpenGLContext().requestVirtualDevice();
pImpl->GetOpenGLContext().requestSingleBufferedRendering();
pImpl->GetOpenGLContext().init(mhLocalDC, mhWnd);
}
mpImpl->Init();
}
void WinSalGraphics::DeInitGraphics()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment