[Libreoffice-commits] core.git: 3 commits - vcl/inc vcl/opengl vcl/README.vars vcl/source vcl/unx
Michael Meeks
michael.meeks at collabora.com
Fri Dec 11 03:30:36 PST 2015
vcl/README.vars | 2
vcl/inc/opengl/texture.hxx | 8 -
vcl/inc/opengl/win/gdiimpl.hxx | 1
vcl/inc/opengl/x11/gdiimpl.hxx | 1
vcl/inc/openglgdiimpl.hxx | 44 ++++-
vcl/opengl/framebuffer.cxx | 15 +
vcl/opengl/gdiimpl.cxx | 282 +++++++++++++++++++++++++++++++-----
vcl/opengl/texture.cxx | 44 +++++
vcl/opengl/win/gdiimpl.cxx | 11 -
vcl/opengl/x11/gdiimpl.cxx | 12 -
vcl/source/opengl/OpenGLContext.cxx | 23 ++
vcl/unx/gtk/gtksalframe.cxx | 7
12 files changed, 367 insertions(+), 83 deletions(-)
New commits:
commit 7bc1f1285e82982b5d900f54f3c6f877517598b8
Author: Michael Meeks <michael.meeks at collabora.com>
Date: Fri Nov 13 12:00:59 2015 +0000
tdf#93529 - move to a Mac-like double-buffered OpenGL model.
This moves us to always rendering to an off-screen texture, and then
(at idle) blitting this to the screen & swapping buffers. Ideally we
should never see any rendering, or flicker again with this approach.
Several fixes are included:
+ avoid multiple OpenGL contexts being created for the same window,
created excessive flicker problems.
+ de-virtualize UseContext - which context we use is less critical.
+ kill 'mbOffscreen' distinction - all VCL rendering is offscreen.
+ implement 'doFlush' and high priority idle flushing.
+ bind stencil buffer for clipping vs. textures - fixing complex
clopping when rendering to virtual-devices, and off-screen.
+ document environment. variables.
+ use white as default background glClear color, but red or
random color for DBGUTIL.
Change-Id: I6be08595b6c8deb7e6db0dbd81308b2c97d2b4ff
diff --git a/vcl/README.vars b/vcl/README.vars
index 4f62333..bf85485 100644
--- a/vcl/README.vars
+++ b/vcl/README.vars
@@ -21,6 +21,8 @@ EMF_PLUS_DISABLE - use EMF rendering and ignore EMF+ specifics
OpenGL
------
SAL_FORCEGL - force enable OpenGL
+SAL_GL_NO_SWAP - disable buffer swapping if set (should show nothing)
+SAL_GL_SLEEP_ON_SWAP - sleep for half a second on each swap-buffers.
SAL_WITHOUT_WIDGET_CACHE - disable LRU caching of native widget texutres
SAL_DISABLE_GLYPH_CACHING - don't render glyphs through OpenGL textures
SAL_DISABLE_GL_WATCHDOG - don't start the thread that watches for broken GL drivers
diff --git a/vcl/inc/opengl/texture.hxx b/vcl/inc/opengl/texture.hxx
index f67b334..e57aa9e 100644
--- a/vcl/inc/opengl/texture.hxx
+++ b/vcl/inc/opengl/texture.hxx
@@ -37,6 +37,8 @@ public:
int mnWidth;
int mnHeight;
GLenum mnFilter;
+ GLuint mnOptStencil;
+ bool mbHasOptStencil;
std::unique_ptr<std::vector<int>> mpSlotReferences;
int mnFreeSlots;
@@ -76,7 +78,8 @@ public:
}
bool InitializeSlots(int nSlotSize);
- int FindFreeSlot();
+ int FindFreeSlot();
+ GLuint AddStencil();
};
class VCL_DLLPUBLIC OpenGLTexture
@@ -110,6 +113,9 @@ public:
void Bind();
void Unbind();
void Read( GLenum nFormat, GLenum nType, sal_uInt8* pData );
+ GLuint AddStencil();
+ bool HasStencil() const;
+ GLuint StencilId() const;
void SaveToFile(const OUString& rFileName);
diff --git a/vcl/inc/opengl/win/gdiimpl.hxx b/vcl/inc/opengl/win/gdiimpl.hxx
index ecefede..8102d2e 100644
--- a/vcl/inc/opengl/win/gdiimpl.hxx
+++ b/vcl/inc/opengl/win/gdiimpl.hxx
@@ -31,7 +31,6 @@ public:
protected:
virtual rtl::Reference<OpenGLContext> CreateWinContext() override;
- virtual bool UseContext( const rtl::Reference<OpenGLContext> &pContext ) override;
bool RenderTextureCombo(TextureCombo& rCombo, int nX, int nY);
diff --git a/vcl/inc/opengl/x11/gdiimpl.hxx b/vcl/inc/opengl/x11/gdiimpl.hxx
index f07468d..eccd0ef 100644
--- a/vcl/inc/opengl/x11/gdiimpl.hxx
+++ b/vcl/inc/opengl/x11/gdiimpl.hxx
@@ -29,7 +29,6 @@ public:
protected:
virtual rtl::Reference<OpenGLContext> CreateWinContext() override;
- virtual bool UseContext( const rtl::Reference<OpenGLContext> &pContext ) override;
bool RenderPixmap(X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY, TextureCombo& rCombo);
diff --git a/vcl/inc/openglgdiimpl.hxx b/vcl/inc/openglgdiimpl.hxx
index 667b2ec..a1c2a25 100644
--- a/vcl/inc/openglgdiimpl.hxx
+++ b/vcl/inc/openglgdiimpl.hxx
@@ -52,12 +52,20 @@ struct TextureCombo
std::unique_ptr<OpenGLTexture> mpMask;
};
+class OpenGLFlushIdle;
+
class VCL_DLLPUBLIC OpenGLSalGraphicsImpl : public SalGraphicsImpl
{
friend class OpenGLTests;
protected:
+ /// This context is solely for blitting @maOffscreenTex
+ rtl::Reference<OpenGLContext> mpWindowContext;
+
+ /// This context is whatever is most convenient to render
+ /// to @maOffscreenTex with.
rtl::Reference<OpenGLContext> mpContext;
+
SalGraphics& mrParent;
/// Pointer to the SalFrame or SalVirtualDevice
SalGeometryProvider* mpProvider;
@@ -67,12 +75,19 @@ protected:
/// Is it someone else's context we shouldn't be fiddling with ?
static bool IsForeignContext(const rtl::Reference<OpenGLContext> &xContext);
+ /// This idle handler is used to swap buffers after rendering.
+ OpenGLFlushIdle *mpFlush;
+
// clipping
vcl::Region maClipRegion;
bool mbUseScissor;
bool mbUseStencil;
- bool mbOffscreen;
+ /**
+ * All rendering happens to this off-screen texture. For
+ * non-virtual devices, ie. windows - we will blit it and
+ * swapBuffers later.
+ */
OpenGLTexture maOffscreenTex;
SalColor mnLineColor;
@@ -80,6 +95,8 @@ protected:
#ifdef DBG_UTIL
bool mProgramIsSolidColor;
#endif
+ sal_uInt32 mnDrawCount;
+ sal_uInt32 mnDrawCountAtFlush;
SalColor mProgramSolidColor;
double mProgramSolidTransparency;
@@ -131,7 +148,10 @@ public:
// get the height of the device
GLfloat GetHeight() const { return mpProvider ? mpProvider->GetHeight() : 1; }
- // check whether this instance is used for offscreen rendering
+ /**
+ * check whether this instance is used for offscreen (Virtual Device)
+ * rendering ie. does it need its own context.
+ */
bool IsOffscreen() const { return mpProvider == nullptr || mpProvider->IsOffScreen(); }
// operations to do before painting
@@ -144,14 +164,18 @@ protected:
bool AcquireContext();
bool ReleaseContext();
- // retrieve the default context for offscreen rendering
+ /// retrieve the default context for offscreen rendering
static rtl::Reference<OpenGLContext> GetDefaultContext();
- // create a new context for window rendering
+ /// create a new context for rendering to the underlying window
virtual rtl::Reference<OpenGLContext> CreateWinContext() = 0;
- // check whether the given context can be used by this instance
- virtual bool UseContext( const rtl::Reference<OpenGLContext> &pContext ) = 0;
+ /// check whether the given context can be used for off-screen rendering
+ bool UseContext( const rtl::Reference<OpenGLContext> &pContext )
+ {
+ return pContext->isInitialized() && // not released by the OS etc.
+ IsForeignContext( pContext ); // a genuine VCL context.
+ }
public:
OpenGLSalGraphicsImpl(SalGraphics& pParent, SalGeometryProvider *pProvider);
@@ -328,8 +352,12 @@ public:
virtual bool drawGradient(const tools::PolyPolygon& rPolygon, const Gradient& rGradient) override;
- virtual OpenGLContext *beginPaint() override;
-private:
+ /// queue an idle flush of contents of the back-buffer to the screen
+ void flush();
+
+public:
+ /// do flush of contents of the back-buffer to the screen & swap.
+ void doFlush();
};
#endif
diff --git a/vcl/opengl/framebuffer.cxx b/vcl/opengl/framebuffer.cxx
index c009ccb..464662d 100644
--- a/vcl/opengl/framebuffer.cxx
+++ b/vcl/opengl/framebuffer.cxx
@@ -72,6 +72,16 @@ void OpenGLFramebuffer::AttachTexture( const OpenGLTexture& rTexture )
mnHeight = rTexture.GetHeight();
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mnAttachedTexture, 0);
CHECK_GL_ERROR();
+
+ GLuint nStencil = rTexture.StencilId();
+ if( nStencil )
+ {
+ VCL_GL_INFO( "Attaching stencil " << nStencil << " to framebuffer " << (int)mnId );
+ glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
+ GL_RENDERBUFFER, nStencil );
+ CHECK_GL_ERROR();
+ }
+
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
CHECK_GL_ERROR();
if (status != GL_FRAMEBUFFER_COMPLETE)
@@ -87,6 +97,11 @@ void OpenGLFramebuffer::DetachTexture()
mnAttachedTexture = 0;
glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0 );
CHECK_GL_ERROR();
+
+ // FIXME: we could make this conditional on having a stencil ?
+ glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
+ GL_RENDERBUFFER, 0 );
+ CHECK_GL_ERROR();
}
}
diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx
index 3771d3c..380417d 100644
--- a/vcl/opengl/gdiimpl.cxx
+++ b/vcl/opengl/gdiimpl.cxx
@@ -37,20 +37,44 @@
#include <vector>
+#include <stdlib.h>
+
+class OpenGLFlushIdle : public Idle
+{
+ OpenGLSalGraphicsImpl *m_pImpl;
+public:
+ OpenGLFlushIdle( OpenGLSalGraphicsImpl *pImpl )
+ : Idle( "gl idle swap" )
+ , m_pImpl( pImpl )
+ {
+ SetPriority( SchedulerPriority::HIGHEST );
+ }
+ ~OpenGLFlushIdle()
+ {
+ }
+ virtual void Invoke() override
+ {
+ m_pImpl->doFlush();
+ Stop();
+ }
+};
+
OpenGLSalGraphicsImpl::OpenGLSalGraphicsImpl(SalGraphics& rParent, SalGeometryProvider *pProvider)
: mpContext(nullptr)
, mrParent(rParent)
, mpProvider(pProvider)
, mpFramebuffer(nullptr)
, mpProgram(nullptr)
+ , mpFlush(new OpenGLFlushIdle(this))
, mbUseScissor(false)
, mbUseStencil(false)
- , mbOffscreen(false)
, mnLineColor(SALCOLOR_NONE)
, mnFillColor(SALCOLOR_NONE)
#ifdef DBG_UTIL
, mProgramIsSolidColor(false)
#endif
+ , mnDrawCount(0)
+ , mnDrawCountAtFlush(0)
, mProgramSolidColor(SALCOLOR_NONE)
, mProgramSolidTransparency(0.0)
{
@@ -58,6 +82,11 @@ OpenGLSalGraphicsImpl::OpenGLSalGraphicsImpl(SalGraphics& rParent, SalGeometryPr
OpenGLSalGraphicsImpl::~OpenGLSalGraphicsImpl()
{
+ if( !IsOffscreen() && mnDrawCountAtFlush != mnDrawCount )
+ VCL_GL_INFO( "Destroying un-flushed on-screen graphics" );
+
+ delete mpFlush;
+
ReleaseContext();
}
@@ -79,10 +108,9 @@ bool OpenGLSalGraphicsImpl::AcquireContext( )
// We always prefer to bind our VirtualDevice / offscreen graphics
// to the current OpenGLContext - to avoid switching contexts.
- if (mpContext.is() && mbOffscreen)
+ if (mpContext.is() && OpenGLContext::hasCurrent() && !mpContext->isCurrent())
{
- if (OpenGLContext::hasCurrent() && !mpContext->isCurrent())
- mpContext.clear();
+ mpContext.clear();
}
if( mpContext.is() )
@@ -97,15 +125,17 @@ bool OpenGLSalGraphicsImpl::AcquireContext( )
while( pContext )
{
// check if this context can be used by this SalGraphicsImpl instance
- if( UseContext( pContext ) )
+ if( UseContext( pContext ) )
break;
pContext = pContext->mpPrevContext;
}
- if( pContext )
+ if( mpContext.is() )
mpContext = pContext;
+ else if( mpWindowContext.is() )
+ mpContext = mpWindowContext;
else
- mpContext = mbOffscreen ? GetDefaultContext() : CreateWinContext();
+ mpContext = GetDefaultContext();
return mpContext.is();
}
@@ -119,19 +149,20 @@ bool OpenGLSalGraphicsImpl::ReleaseContext()
void OpenGLSalGraphicsImpl::Init()
{
- mbOffscreen = IsOffscreen();
+ // Our init phase is strange ::Init is called twice for vdevs.
+ // the first time around with a NULL geometry provider.
+ if( !mpProvider )
+ return;
// check if we can simply re-use the same context
if( mpContext.is() )
{
- if( !mpContext->isInitialized() ||
- !UseContext( mpContext ) )
+ if( !UseContext( mpContext ) )
ReleaseContext();
}
- // reset the offscreen texture
- if( !mbOffscreen ||
- maOffscreenTex.GetWidth() != GetWidth() ||
+ // Always create the offscreen texture
+ if( maOffscreenTex.GetWidth() != GetWidth() ||
maOffscreenTex.GetHeight() != GetHeight() )
{
if( maOffscreenTex && // don't work to release empty textures
@@ -141,6 +172,14 @@ void OpenGLSalGraphicsImpl::Init()
mpContext->ReleaseFramebuffer( maOffscreenTex );
}
maOffscreenTex = OpenGLTexture();
+ VCL_GL_INFO("::Init - re-size offscreen texture");
+ }
+
+ if( !IsOffscreen() )
+ {
+ if( mpWindowContext.is() )
+ mpWindowContext->reset();
+ mpWindowContext = CreateWinContext();
}
}
@@ -155,12 +194,15 @@ void OpenGLSalGraphicsImpl::DeInit()
// get a shiny new context in AcquireContext:: next PreDraw.
if( mpContext.is() && !IsOffscreen() )
mpContext->reset();
+ mpContext.clear();
}
void OpenGLSalGraphicsImpl::PreDraw()
{
OpenGLZone::enter();
+ mnDrawCount++;
+
if( !AcquireContext() )
{
SAL_WARN( "vcl.opengl", "Couldn't acquire context" );
@@ -170,10 +212,7 @@ void OpenGLSalGraphicsImpl::PreDraw()
mpContext->makeCurrent();
CHECK_GL_ERROR();
- if( !mbOffscreen )
- mpContext->AcquireDefaultFramebuffer();
- else
- CheckOffscreenTexture();
+ CheckOffscreenTexture();
CHECK_GL_ERROR();
glViewport( 0, 0, GetWidth(), GetHeight() );
@@ -185,15 +224,13 @@ void OpenGLSalGraphicsImpl::PreDraw()
void OpenGLSalGraphicsImpl::PostDraw()
{
- if( !mbOffscreen && mpContext->mnPainting == 0 )
- glFlush();
if( mbUseScissor )
{
glDisable( GL_SCISSOR_TEST );
CHECK_GL_ERROR();
}
- if( mbUseStencil )
- {
+ if( mbUseStencil )
+ {
glDisable( GL_STENCIL_TEST );
CHECK_GL_ERROR();
}
@@ -205,6 +242,18 @@ void OpenGLSalGraphicsImpl::PostDraw()
mProgramIsSolidColor = false;
#endif
}
+
+ assert (maOffscreenTex);
+
+ if( IsOffscreen() )
+ assert( !mpWindowContext.is() );
+ else
+ assert( mpWindowContext.is() );
+
+ // Always queue the flush.
+ if( !IsOffscreen() )
+ flush();
+
OpenGLZone::leave();
}
@@ -216,8 +265,9 @@ void OpenGLSalGraphicsImpl::ApplyProgramMatrices(float fPixelOffset)
void OpenGLSalGraphicsImpl::freeResources()
{
// TODO Delete shaders, programs and textures if not shared
- if( mbOffscreen && mpContext.is() && mpContext->isInitialized() )
+ if( mpContext.is() && mpContext->isInitialized() )
{
+ VCL_GL_INFO( "freeResources" );
mpContext->makeCurrent();
mpContext->ReleaseFramebuffer( maOffscreenTex );
}
@@ -227,6 +277,20 @@ void OpenGLSalGraphicsImpl::freeResources()
void OpenGLSalGraphicsImpl::ImplSetClipBit( const vcl::Region& rClip, GLuint nMask )
{
glEnable( GL_STENCIL_TEST );
+
+ VCL_GL_INFO( "Adding complex clip / stencil" );
+ GLuint nStencil = maOffscreenTex.StencilId();
+ if( nStencil == 0 )
+ {
+ nStencil = maOffscreenTex.AddStencil();
+ glFramebufferRenderbuffer(
+ GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
+ GL_RENDERBUFFER, nStencil );
+ CHECK_GL_ERROR();
+ }
+ // else - we associated the stencil in
+ // AcquireFrameBuffer / AttachTexture
+
CHECK_GL_ERROR();
glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
CHECK_GL_ERROR();
@@ -261,7 +325,7 @@ void OpenGLSalGraphicsImpl::ImplInitClipRegion()
if( maClipRegion != mpContext->maClipRegion )
{
mpContext->maClipRegion = maClipRegion;
- if( maClipRegion.IsRectangle() )
+ if( mbUseScissor )
{
Rectangle aRect( maClipRegion.GetBoundRect() );
glScissor( aRect.Left(), GetHeight() - aRect.Bottom() - 1, aRect.GetWidth() + 1, aRect.GetHeight() + 1 );
@@ -382,8 +446,29 @@ void OpenGLSalGraphicsImpl::SetROPFillColor( SalROPColor /*nROPColor*/ )
bool OpenGLSalGraphicsImpl::CheckOffscreenTexture()
{
+ bool bClearTexture = false;
+
+ VCL_GL_INFO( "Check Offscreen texture" );
+
+ // Always create the offscreen texture
+ if( maOffscreenTex )
+ {
+ if( maOffscreenTex.GetWidth() != GetWidth() ||
+ maOffscreenTex.GetHeight() != GetHeight() )
+ {
+ mpContext->ReleaseFramebuffer( maOffscreenTex );
+ maOffscreenTex = OpenGLTexture();
+ VCL_GL_INFO( "re-size offscreen texture" );
+ }
+ }
+
if( !maOffscreenTex )
+ {
+ VCL_GL_INFO( "create texture of size "
+ << GetWidth() << " x " << GetHeight() );
maOffscreenTex = OpenGLTexture( GetWidth(), GetHeight() );
+ bClearTexture = true;
+ }
if( !maOffscreenTex.IsUnique() )
{
@@ -400,8 +485,23 @@ bool OpenGLSalGraphicsImpl::CheckOffscreenTexture()
else
{
mpFramebuffer = mpContext->AcquireFramebuffer( maOffscreenTex );
+ CHECK_GL_ERROR();
+
+ if( bClearTexture )
+ {
+ glDrawBuffer( GL_COLOR_ATTACHMENT0 );
+#if OSL_DEBUG_LEVEL > 0 // lets have some red debugging background.
+ GLfloat clearColor[4] = { 1.0, 0, 0, 0 };
+#else
+ GLfloat clearColor[4] = { 1.0, 1.0, 1.0, 0 };
+#endif
+ glClearBufferfv( GL_COLOR, 0, clearColor );
+ // FIXME: use glClearTexImage if we have it ?
+ }
}
+ assert( maOffscreenTex );
+
CHECK_GL_ERROR();
return true;
}
@@ -1541,17 +1641,9 @@ void OpenGLSalGraphicsImpl::DoCopyBits( const SalTwoRect& rPosAry, OpenGLSalGrap
return;
}
- if( rImpl.mbOffscreen )
- {
- PreDraw();
- DrawTexture( rImpl.maOffscreenTex, rPosAry );
- PostDraw();
- return;
- }
-
- SAL_WARN( "vcl.opengl", "*** NOT IMPLEMENTED *** copyBits" );
- // TODO: Copy from one FBO to the other (glBlitFramebuffer)
- // ie. copying from one visible window to another visible window
+ PreDraw();
+ DrawTexture( rImpl.maOffscreenTex, rPosAry );
+ PostDraw();
}
void OpenGLSalGraphicsImpl::drawBitmap( const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap )
@@ -1878,12 +1970,126 @@ bool OpenGLSalGraphicsImpl::drawGradient(const tools::PolyPolygon& rPolyPoly,
return true;
}
-OpenGLContext *OpenGLSalGraphicsImpl::beginPaint()
+void OpenGLSalGraphicsImpl::flush()
{
- if( mbOffscreen || !AcquireContext() )
- return nullptr;
+ if( IsOffscreen() )
+ return;
+
+ if( !Application::IsInExecute() )
+ {
+ // otherwise nothing would trigger idle rendering
+ doFlush();
+ }
+ else if( !mpFlush->IsActive() )
+ mpFlush->Start();
+}
+
+void OpenGLSalGraphicsImpl::doFlush()
+{
+ if( IsOffscreen() )
+ return;
+
+ assert( mpWindowContext.is() );
+
+ if( !maOffscreenTex )
+ {
+ VCL_GL_INFO( "flushAndSwap - odd no texture !" );
+ return;
+ }
+
+ if (mnDrawCountAtFlush == mnDrawCount)
+ {
+ VCL_GL_INFO( "eliding redundant flushAndSwap, no drawing since last!" );
+ return;
+ }
+
+ mnDrawCountAtFlush = mnDrawCount;
+
+ OpenGLZone aZone;
+
+ VCL_GL_INFO( "flushAndSwap" );
+
+ // Interesting ! -> this destroys a context [ somehow ] ...
+ mpWindowContext->makeCurrent();
+ CHECK_GL_ERROR();
+
+ VCL_GL_INFO( "flushAndSwap - acquire default frame buffer" );
+
+ mpWindowContext->AcquireDefaultFramebuffer();
+ glBindFramebuffer( GL_FRAMEBUFFER, 0 ); // FIXME: paranoid double check.
+ CHECK_GL_ERROR();
+
+ VCL_GL_INFO( "flushAndSwap - acquired default frame buffer" );
+
+ glDisable( GL_SCISSOR_TEST ); // FIXME: paranoia ...
+ CHECK_GL_ERROR();
+ glDisable( GL_STENCIL_TEST ); // FIXME: paranoia ...
+ CHECK_GL_ERROR();
+
+ glViewport( 0, 0, GetWidth(), GetHeight() );
+ CHECK_GL_ERROR();
+
+#if OSL_DEBUG_LEVEL > 0 // random background glClear
+ glClearColor((float)rand()/RAND_MAX, (float)rand()/RAND_MAX,
+ (float)rand()/RAND_MAX, 1.0);
+#else
+ glClearColor(1.0, 1.0, 1.0, 1.0);
+#endif
+ glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
+ CHECK_GL_ERROR();
+
+ SalTwoRect aPosAry( 0, 0, maOffscreenTex.GetWidth(), maOffscreenTex.GetHeight(),
+ 0, 0, maOffscreenTex.GetWidth(), maOffscreenTex.GetHeight() );
+ VCL_GL_INFO( "Texture height " << maOffscreenTex.GetHeight() << " vs. window height " << GetHeight() );
+
+ OpenGLProgram *pProgram =
+ mpWindowContext->UseProgram( "textureVertexShader", "textureFragmentShader", "" );
+ if( !pProgram )
+ VCL_GL_INFO( "Can't compile simple copying shader !" );
else
- return mpContext.get();
+ {
+ pProgram->Use(); // FIXME: paranoia ...
+ VCL_GL_INFO( "done paranoid re-use." );
+ pProgram->SetTexture( "sampler", maOffscreenTex );
+ maOffscreenTex.Bind(); // FIXME: paranoia ...
+
+ VCL_GL_INFO( "bound bits etc." );
+
+ GLfloat aTexCoord[8];
+ maOffscreenTex.GetCoord( aTexCoord, aPosAry, false );
+ pProgram->SetTextureCoord( aTexCoord );
+
+ long nX1( aPosAry.mnDestX );
+ long nY1( aPosAry.mnDestY );
+ long nX2( nX1 + aPosAry.mnDestWidth );
+ long nY2( nY1 + aPosAry.mnDestHeight );
+ const SalPoint aPoints[] = { { nX1, nY2 }, { nX1, nY1 },
+ { nX2, nY1 }, { nX2, nY2 }};
+
+ sal_uInt32 nPoints = 4;
+ std::vector<GLfloat> aVertices(nPoints * 2);
+ sal_uInt32 i, j;
+
+ for( i = 0, j = 0; i < nPoints; i++, j += 2 )
+ {
+ aVertices[j] = GLfloat(aPoints[i].mnX);
+ aVertices[j+1] = GLfloat(aPoints[i].mnY);
+ }
+
+ pProgram->ApplyMatrix(GetWidth(), GetHeight(), 0.0);
+ pProgram->SetVertices( &aVertices[0] );
+ glDrawArrays( GL_TRIANGLE_FAN, 0, nPoints );
+
+ pProgram->Clean();
+
+ glBindTexture( GL_TEXTURE_2D, 0 );
+
+ static bool bNoSwap = getenv("SAL_GL_NO_SWAP");
+ if (!bNoSwap)
+ mpWindowContext->swapBuffers();
+ }
+
+ VCL_GL_INFO( "flushAndSwap - end." );
}
bool OpenGLSalGraphicsImpl::IsForeignContext(const rtl::Reference<OpenGLContext> &xContext)
diff --git a/vcl/opengl/texture.cxx b/vcl/opengl/texture.cxx
index 2d4cb40..bf4aa1d 100644
--- a/vcl/opengl/texture.cxx
+++ b/vcl/opengl/texture.cxx
@@ -35,6 +35,7 @@ ImplOpenGLTexture::ImplOpenGLTexture( int nWidth, int nHeight, bool bAllocate )
mnWidth( nWidth ),
mnHeight( nHeight ),
mnFilter( GL_NEAREST ),
+ mnOptStencil( 0 ),
mnFreeSlots(-1)
{
glGenTextures( 1, &mnTexture );
@@ -67,6 +68,7 @@ ImplOpenGLTexture::ImplOpenGLTexture( int nX, int nY, int nWidth, int nHeight )
mnWidth( nWidth ),
mnHeight( nHeight ),
mnFilter( GL_NEAREST ),
+ mnOptStencil( 0 ),
mnFreeSlots(-1)
{
// FIXME We need the window height here
@@ -99,6 +101,7 @@ ImplOpenGLTexture::ImplOpenGLTexture( int nWidth, int nHeight, int nFormat, int
mnWidth( nWidth ),
mnHeight( nHeight ),
mnFilter( GL_NEAREST ),
+ mnOptStencil( 0 ),
mnFreeSlots(-1)
{
if( !mnTexture )
@@ -126,6 +129,21 @@ ImplOpenGLTexture::ImplOpenGLTexture( int nWidth, int nHeight, int nFormat, int
VCL_GL_INFO( "OpenGLTexture " << mnTexture << " " << nWidth << "x" << nHeight << " from data" );
}
+GLuint ImplOpenGLTexture::AddStencil()
+{
+ assert( mnOptStencil == 0 );
+
+ glGenRenderbuffers( 1, &mnOptStencil );
+ glBindRenderbuffer( GL_RENDERBUFFER, mnOptStencil );
+ CHECK_GL_ERROR();
+ VCL_GL_INFO( "Allocate stencil " << mnWidth << " x " << mnHeight );
+ glRenderbufferStorage( GL_RENDERBUFFER, GL_STENCIL_INDEX,
+ mnWidth, mnHeight );
+ CHECK_GL_ERROR();
+
+ return mnOptStencil;
+}
+
ImplOpenGLTexture::~ImplOpenGLTexture()
{
VCL_GL_INFO( "~OpenGLTexture " << mnTexture );
@@ -136,9 +154,11 @@ ImplOpenGLTexture::~ImplOpenGLTexture()
// Check we have been correctly un-bound from all framebuffers.
ImplSVData* pSVData = ImplGetSVData();
rtl::Reference<OpenGLContext> pContext = pSVData->maGDIData.mpLastContext;
- if (pContext.is())
+ if( pContext.is() )
pContext->UnbindTextureFromFramebuffers( mnTexture );
+ if( mnOptStencil != 0 )
+ glDeleteRenderbuffers( 1, &mnOptStencil );
glDeleteTextures( 1, &mnTexture );
}
}
@@ -279,6 +299,24 @@ int OpenGLTexture::GetHeight() const
return maRect.GetHeight();
}
+bool OpenGLTexture::HasStencil() const
+{
+ return mpImpl && mpImpl->mnOptStencil != 0;
+}
+
+GLuint OpenGLTexture::StencilId() const
+{
+ return mpImpl ? mpImpl->mnOptStencil : 0;
+}
+
+GLuint OpenGLTexture::AddStencil()
+{
+ if (mpImpl)
+ return mpImpl->AddStencil();
+ else
+ return 0;
+}
+
void OpenGLTexture::GetCoord( GLfloat* pCoord, const SalTwoRect& rPosAry, bool bInverted ) const
{
VCL_GL_INFO( "Getting coord " << Id() << " [" << maRect.Left() << "," << maRect.Top() << "] " << GetWidth() << "x" << GetHeight() );
@@ -349,6 +387,10 @@ void OpenGLTexture::Bind()
glBindTexture( GL_TEXTURE_2D, mpImpl->mnTexture );
CHECK_GL_ERROR();
}
+ else
+ VCL_GL_INFO( "OpenGLTexture::Binding invalid texture" );
+
+ CHECK_GL_ERROR();
}
void OpenGLTexture::Unbind()
diff --git a/vcl/opengl/win/gdiimpl.cxx b/vcl/opengl/win/gdiimpl.cxx
index f57c82d..666cdbf 100644
--- a/vcl/opengl/win/gdiimpl.cxx
+++ b/vcl/opengl/win/gdiimpl.cxx
@@ -29,21 +29,10 @@ void WinOpenGLSalGraphicsImpl::copyBits( const SalTwoRect& rPosAry, SalGraphics*
rtl::Reference<OpenGLContext> WinOpenGLSalGraphicsImpl::CreateWinContext()
{
rtl::Reference<OpenGLContext> pContext = OpenGLContext::Create();
- pContext->requestSingleBufferedRendering();
pContext->init( mrParent.mhLocalDC, mrParent.mhWnd );
return pContext;
}
-bool WinOpenGLSalGraphicsImpl::UseContext( const rtl::Reference<OpenGLContext> &pContext )
-{
- if( !pContext.is() || !pContext->isInitialized() || IsForeignContext( pContext ) )
- return false;
- if( IsOffscreen() )
- return true;
- return pContext->getOpenGLWindow().hWnd == mrParent.mhWnd &&
- pContext->getOpenGLWindow().hDC == mrParent.mhLocalDC;
-}
-
void WinOpenGLSalGraphicsImpl::Init()
{
if ( !IsOffscreen() && mpContext.is() && mpContext->isInitialized() &&
diff --git a/vcl/opengl/x11/gdiimpl.cxx b/vcl/opengl/x11/gdiimpl.cxx
index 2418bc6..595ca45c 100644
--- a/vcl/opengl/x11/gdiimpl.cxx
+++ b/vcl/opengl/x11/gdiimpl.cxx
@@ -58,18 +58,6 @@ rtl::Reference<OpenGLContext> X11OpenGLSalGraphicsImpl::CreateWinContext()
return pContext;
}
-bool X11OpenGLSalGraphicsImpl::UseContext( const rtl::Reference<OpenGLContext> &pContext )
-{
- X11WindowProvider *pProvider = dynamic_cast<X11WindowProvider*>(mrParent.m_pFrame);
-
- if( !pContext->isInitialized() || IsForeignContext( pContext ) )
- return false;
- if( !pProvider )
- return pContext->getOpenGLWindow().win != None;
- else
- return pContext->getOpenGLWindow().win == pProvider->GetX11Window();
-}
-
void X11OpenGLSalGraphicsImpl::copyBits( const SalTwoRect& rPosAry, SalGraphics* pSrcGraphics )
{
OpenGLSalGraphicsImpl *pImpl = pSrcGraphics ? static_cast< OpenGLSalGraphicsImpl* >(pSrcGraphics->GetImpl()) : static_cast< OpenGLSalGraphicsImpl *>(mrParent.GetImpl());
diff --git a/vcl/source/opengl/OpenGLContext.cxx b/vcl/source/opengl/OpenGLContext.cxx
index 26148a6..98be555 100644
--- a/vcl/source/opengl/OpenGLContext.cxx
+++ b/vcl/source/opengl/OpenGLContext.cxx
@@ -18,6 +18,8 @@
#include <vcl/bmpacc.hxx>
#include <vcl/graph.hxx>
+#include <osl/thread.hxx>
+
#if defined(MACOSX)
#include <premac.h>
#include <AppKit/NSOpenGLView.h>
@@ -1487,6 +1489,14 @@ void OpenGLContext::swapBuffers()
#elif defined( UNX )
glXSwapBuffers(m_aGLWin.dpy, m_aGLWin.win);
#endif
+
+ static bool bSleep = getenv("SAL_GL_SLEEP_ON_SWAP");
+ if (bSleep)
+ {
+ // half a second.
+ TimeValue aSleep( 0, 500*1000*1000 );
+ osl::Thread::wait( aSleep );
+ }
}
void OpenGLContext::sync()
commit 93185f720aab0e58564c050ea3518746d8597803
Author: Michael Meeks <michael.meeks at collabora.com>
Date: Mon Nov 16 18:18:36 2015 +0000
Get Double-buffered context creation working on linux.
Change-Id: I3db1d6792fcd51577f047b82029124ec825ea319
diff --git a/vcl/source/opengl/OpenGLContext.cxx b/vcl/source/opengl/OpenGLContext.cxx
index 8c5db0f..26148a6 100644
--- a/vcl/source/opengl/OpenGLContext.cxx
+++ b/vcl/source/opengl/OpenGLContext.cxx
@@ -706,9 +706,7 @@ bool GLWindow::HasGLXExtension( const char* name ) const
bool OpenGLContext::ImplInit()
{
if (!m_aGLWin.dpy)
- {
return false;
- }
OpenGLZone aZone;
@@ -722,11 +720,10 @@ bool OpenGLContext::ImplInit()
if (!g_vShareList.empty())
pSharedCtx = g_vShareList.front();
-#ifdef DBG_UTIL
if (glXCreateContextAttribsARB && !mbRequestLegacyContext)
{
int best_fbc = -1;
- GLXFBConfig* pFBC = getFBConfig(m_aGLWin.dpy, m_aGLWin.win, best_fbc, mbUseDoubleBufferedRendering, true);
+ GLXFBConfig* pFBC = getFBConfig(m_aGLWin.dpy, m_aGLWin.win, best_fbc, mbUseDoubleBufferedRendering, false);
if (!pFBC)
return false;
@@ -734,24 +731,28 @@ bool OpenGLContext::ImplInit()
{
int pContextAttribs[] =
{
+#if 0 // defined(DBG_UTIL)
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
GLX_CONTEXT_MINOR_VERSION_ARB, 2,
+#endif
None
+
};
m_aGLWin.ctx = glXCreateContextAttribsARB(m_aGLWin.dpy, pFBC[best_fbc], pSharedCtx, /* direct, not via X */ GL_TRUE, pContextAttribs);
SAL_INFO_IF(m_aGLWin.ctx, "vcl.opengl", "created a 3.2 core context");
}
else
SAL_WARN("vcl.opengl", "unable to find correct FBC");
-
}
-#endif
if (!m_aGLWin.ctx)
{
if (!m_aGLWin.vi)
return false;
+ SAL_WARN("vcl.opengl", "attempting to create a non-double-buffered "
+ "visual matching the context");
+
m_aGLWin.ctx = glXCreateContext(m_aGLWin.dpy,
m_aGLWin.vi,
pSharedCtx,
commit ef414f70426f5e6b9170a6e3565f30f44bb41254
Author: Michael Meeks <michael.meeks at collabora.com>
Date: Mon Nov 30 16:13:42 2015 +0000
vcl: gtk frames should DeInitialize properly, to handle GL cleanup.
Change-Id: Ie6a5464c28b89f08639939690052023e685a3d33
diff --git a/vcl/unx/gtk/gtksalframe.cxx b/vcl/unx/gtk/gtksalframe.cxx
index 085eb0e..1772990 100644
--- a/vcl/unx/gtk/gtksalframe.cxx
+++ b/vcl/unx/gtk/gtksalframe.cxx
@@ -777,8 +777,10 @@ void GtkSalFrame::InvalidateGraphics()
{
if( m_pGraphics )
{
- m_pGraphics->SetDrawable( None, m_nXScreen );
+ m_pGraphics->DeInit();
m_pGraphics->SetWindow(nullptr);
+ delete m_pGraphics;
+ m_pGraphics = nullptr;
m_bGraphics = false;
}
}
@@ -846,9 +848,6 @@ GtkSalFrame::~GtkSalFrame()
g_object_unref( G_OBJECT( m_pForeignParent ) );
if( m_pForeignTopLevel )
g_object_unref( G_OBJECT( m_pForeignTopLevel) );
-
- delete m_pGraphics;
- m_pGraphics = nullptr;
}
void GtkSalFrame::moveWindow( long nX, long nY )
More information about the Libreoffice-commits
mailing list