vcl: opengl - Kill the last glErrors on common paths.

Re-work the makeSomeOpenGLContextCurrent logic into a shared function
with the existing AcquireContext logic in the SalOpenGLGraphics impl.
Use an OpenGLVCLContextZone placeholder to do both context and zone
management - to include destructors into the zone.

Fix a number of error cases around SalBitmaps where we did not have
a GL context associated when allocating, and/or freeing textures..

Don't drag a (potentially) slower context around in the
OpenGLSalBitmap when we're going to check / fetch a better VCL
context anyway.

Change-Id: Ibbb2358c47156cd078ad28b6aad4f03af36aaf23
Reviewed-on: https://gerrit.libreoffice.org/21127
Reviewed-by: Michael Meeks <michael.meeks@collabora.com>
Tested-by: Michael Meeks <michael.meeks@collabora.com>
This commit is contained in:
Michael Meeks
2016-01-05 16:17:41 +00:00
parent 3576a87d72
commit 1479ad1c63
10 changed files with 120 additions and 97 deletions

View File

@@ -174,6 +174,11 @@ public:
static void prepareForYield(); static void prepareForYield();
/// Is there a current GL context ? /// Is there a current GL context ?
static bool hasCurrent(); static bool hasCurrent();
/// make a VCL context (any context) current, create it if necessary.
static void makeVCLCurrent();
/// fetch any VCL context, creating one if @bMakeIfNecessary is set.
static rtl::Reference<OpenGLContext> getVCLContext(bool bMakeIfNecessary = true);
/// make this GL context current - so it is implicit in subsequent GL calls /// make this GL context current - so it is implicit in subsequent GL calls
void makeCurrent(); void makeCurrent();
/// Put this GL context to the end of the context list. /// Put this GL context to the end of the context list.

View File

@@ -37,7 +37,6 @@ class BitmapPalette;
class VCL_PLUGIN_PUBLIC OpenGLSalBitmap : public SalBitmap class VCL_PLUGIN_PUBLIC OpenGLSalBitmap : public SalBitmap
{ {
private: private:
rtl::Reference<OpenGLContext> mpContext;
OpenGLTexture maTexture; OpenGLTexture maTexture;
bool mbDirtyTexture; bool mbDirtyTexture;
BitmapPalette maPalette; BitmapPalette maPalette;
@@ -50,7 +49,6 @@ private:
int mnBufHeight; int mnBufHeight;
std::deque< OpenGLSalBitmapOp* > maPendingOps; std::deque< OpenGLSalBitmapOp* > maPendingOps;
void makeSomeOpenGLContextCurrent();
virtual void updateChecksum() const override; virtual void updateChecksum() const override;
bool calcChecksumGL(OpenGLTexture& rInputTexture, ChecksumType& rChecksum) const; bool calcChecksumGL(OpenGLTexture& rInputTexture, ChecksumType& rChecksum) const;
@@ -98,10 +96,11 @@ private:
private: private:
bool ImplScaleFilter( const double& rScaleX, const double& rScaleY, GLenum nFilter ); bool ImplScaleFilter( const rtl::Reference< OpenGLContext > &xContext, const double& rScaleX, const double& rScaleY, GLenum nFilter );
static void ImplCreateKernel( const double& fScale, const vcl::Kernel& rKernel, GLfloat*& pWeights, sal_uInt32& aKernelSize ); static void ImplCreateKernel( const double& fScale, const vcl::Kernel& rKernel, GLfloat*& pWeights, sal_uInt32& aKernelSize );
bool ImplScaleConvolution(const double& rScaleX, const double& rScaleY, const vcl::Kernel& rKernel); bool ImplScaleConvolution(const rtl::Reference< OpenGLContext > &xContext, const double& rScaleX, const double& rScaleY, const vcl::Kernel& rKernel);
bool ImplScaleArea( double rScaleX, double rScaleY ); bool ImplScaleArea( const rtl::Reference< OpenGLContext > &xContext,
double rScaleX, double rScaleY );
public: public:

View File

@@ -40,6 +40,13 @@ public:
static void hardDisable(); static void hardDisable();
}; };
/// Create this to not only enter the zone, but set VCL context.
class OpenGLVCLContextZone {
OpenGLZone aZone;
public:
OpenGLVCLContextZone();
};
#endif // INCLUDED_VCL_INC_OPENGL_ZONE_H #endif // INCLUDED_VCL_INC_OPENGL_ZONE_H
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View File

@@ -162,9 +162,6 @@ protected:
bool AcquireContext(bool bForceCreate = false); bool AcquireContext(bool bForceCreate = false);
bool ReleaseContext(); bool ReleaseContext();
/// retrieve the default context for offscreen rendering
static rtl::Reference<OpenGLContext> GetDefaultContext();
/// create a new context for rendering to the underlying window /// create a new context for rendering to the underlying window
virtual rtl::Reference<OpenGLContext> CreateWinContext() = 0; virtual rtl::Reference<OpenGLContext> CreateWinContext() = 0;

View File

@@ -97,52 +97,22 @@ rtl::Reference<OpenGLContext> OpenGLSalGraphicsImpl::GetOpenGLContext()
return mpContext; return mpContext;
} }
rtl::Reference<OpenGLContext> OpenGLSalGraphicsImpl::GetDefaultContext()
{
return ImplGetDefaultWindow()->GetGraphics()->GetOpenGLContext();
}
bool OpenGLSalGraphicsImpl::AcquireContext( bool bForceCreate ) bool OpenGLSalGraphicsImpl::AcquireContext( bool bForceCreate )
{ {
ImplSVData* pSVData = ImplGetSVData(); mpContext = OpenGLContext::getVCLContext( false );
// We always prefer to bind our VirtualDevice / offscreen graphics if( !mpContext.is() && mpWindowContext.is() )
// to the current OpenGLContext - to avoid switching contexts.
if (mpContext.is() && OpenGLContext::hasCurrent() && !mpContext->isCurrent())
{ {
mpContext.clear();
}
if( mpContext.is() )
{
// Check whether the context was reset underneath us.
if( mpContext->isInitialized() )
return true;
mpContext.clear();
}
// We don't care what context we have - but not switching context
// is rather useful from a performance perspective.
OpenGLContext *pContext = pSVData->maGDIData.mpLastContext;
while( pContext )
{
// check if this context can be used by this SalGraphicsImpl instance
if( UseContext( pContext ) )
break;
pContext = pContext->mpPrevContext;
}
if( mpContext.is() )
mpContext = pContext;
else if( mpWindowContext.is() )
mpContext = mpWindowContext; mpContext = mpWindowContext;
}
else if( bForceCreate && !IsOffscreen() ) else if( bForceCreate && !IsOffscreen() )
{ {
mpWindowContext = CreateWinContext(); mpWindowContext = CreateWinContext();
mpContext = mpWindowContext; mpContext = mpWindowContext;
} }
if( !mpContext.is() ) if( !mpContext.is() )
mpContext = GetDefaultContext(); mpContext = OpenGLContext::getVCLContext( true );
return mpContext.is(); return mpContext.is();
} }
@@ -2077,7 +2047,7 @@ void OpenGLSalGraphicsImpl::doFlush()
VCL_GL_INFO( "Texture height " << maOffscreenTex.GetHeight() << " vs. window height " << GetHeight() ); VCL_GL_INFO( "Texture height " << maOffscreenTex.GetHeight() << " vs. window height " << GetHeight() );
OpenGLProgram *pProgram = OpenGLProgram *pProgram =
mpWindowContext->UseProgram( "textureVertexShader", "textureFragmentShader", "" ); mpWindowContext->UseProgram( "textureVertexShader", "textureFragmentShader", "// flush shader\n" ); // flush helps profiling
if( !pProgram ) if( !pProgram )
VCL_GL_INFO( "Can't compile simple copying shader !" ); VCL_GL_INFO( "Can't compile simple copying shader !" );
else else

View File

@@ -104,8 +104,7 @@ static vcl::DeleteOnDeinit< TextureAtlasVector > gTextureAtlases(new TextureAtla
} }
OpenGLSalBitmap::OpenGLSalBitmap() OpenGLSalBitmap::OpenGLSalBitmap()
: mpContext(nullptr) : mbDirtyTexture(true)
, mbDirtyTexture(true)
, mnBits(0) , mnBits(0)
, mnBytesPerRow(0) , mnBytesPerRow(0)
, mnWidth(0) , mnWidth(0)
@@ -124,7 +123,7 @@ OpenGLSalBitmap::~OpenGLSalBitmap()
bool OpenGLSalBitmap::Create( const OpenGLTexture& rTex, long nX, long nY, long nWidth, long nHeight ) bool OpenGLSalBitmap::Create( const OpenGLTexture& rTex, long nX, long nY, long nWidth, long nHeight )
{ {
static const BitmapPalette aEmptyPalette; static const BitmapPalette aEmptyPalette;
OpenGLZone aZone; OpenGLVCLContextZone aContextZone;
Destroy(); Destroy();
VCL_GL_INFO( "OpenGLSalBitmap::Create from FBO: [" VCL_GL_INFO( "OpenGLSalBitmap::Create from FBO: ["
@@ -151,7 +150,7 @@ bool OpenGLSalBitmap::Create( const OpenGLTexture& rTex, long nX, long nY, long
bool OpenGLSalBitmap::Create( const Size& rSize, sal_uInt16 nBits, const BitmapPalette& rBitmapPalette ) bool OpenGLSalBitmap::Create( const Size& rSize, sal_uInt16 nBits, const BitmapPalette& rBitmapPalette )
{ {
OpenGLZone aZone; OpenGLVCLContextZone aContextZone;
Destroy(); Destroy();
VCL_GL_INFO( "OpenGLSalBitmap::Create with size: " << rSize ); VCL_GL_INFO( "OpenGLSalBitmap::Create with size: " << rSize );
@@ -421,7 +420,6 @@ Size OpenGLSalBitmap::GetSize() const
void OpenGLSalBitmap::ExecuteOperations() void OpenGLSalBitmap::ExecuteOperations()
{ {
makeSomeOpenGLContextCurrent();
while( !maPendingOps.empty() ) while( !maPendingOps.empty() )
{ {
OpenGLSalBitmapOp* pOp = maPendingOps.front(); OpenGLSalBitmapOp* pOp = maPendingOps.front();
@@ -488,7 +486,7 @@ GLuint OpenGLSalBitmap::CreateTexture()
} }
} }
makeSomeOpenGLContextCurrent(); OpenGLVCLContextZone aContextZone;
lclInstantiateTexture(maTexture, mnBufWidth, mnBufHeight, nFormat, nType, pData); lclInstantiateTexture(maTexture, mnBufWidth, mnBufHeight, nFormat, nType, pData);
@@ -516,11 +514,12 @@ bool OpenGLSalBitmap::ReadTexture()
if( pData == nullptr ) if( pData == nullptr )
return false; return false;
OpenGLVCLContextZone aContextZone;
if (mnBits == 8 || mnBits == 16 || mnBits == 24 || mnBits == 32) if (mnBits == 8 || mnBits == 16 || mnBits == 24 || mnBits == 32)
{ {
determineTextureFormat(mnBits, nFormat, nType); determineTextureFormat(mnBits, nFormat, nType);
makeSomeOpenGLContextCurrent();
maTexture.Read(nFormat, nType, pData); maTexture.Read(nFormat, nType, pData);
mnBufWidth = mnWidth; mnBufWidth = mnWidth;
mnBufHeight = mnHeight; mnBufHeight = mnHeight;
@@ -529,7 +528,7 @@ bool OpenGLSalBitmap::ReadTexture()
else if (mnBits == 1) else if (mnBits == 1)
{ // convert buffers from 24-bit RGB to 1-bit Mask { // convert buffers from 24-bit RGB to 1-bit Mask
std::vector<sal_uInt8> aBuffer(mnWidth * mnHeight * 3); std::vector<sal_uInt8> aBuffer(mnWidth * mnHeight * 3);
makeSomeOpenGLContextCurrent();
sal_uInt8* pBuffer = aBuffer.data(); sal_uInt8* pBuffer = aBuffer.data();
determineTextureFormat(24, nFormat, nType); determineTextureFormat(24, nFormat, nType);
maTexture.Read(nFormat, nType, pBuffer); maTexture.Read(nFormat, nType, pBuffer);
@@ -585,6 +584,9 @@ bool OpenGLSalBitmap::calcChecksumGL(OpenGLTexture& rInputTexture, ChecksumType&
{ {
OUString FragShader("areaHashCRC64TFragmentShader"); OUString FragShader("areaHashCRC64TFragmentShader");
OpenGLZone aZone;
rtl::Reference< OpenGLContext > xContext = OpenGLContext::getVCLContext();
static vcl::DeleteOnDeinit<OpenGLTexture> gCRCTableTexture( static vcl::DeleteOnDeinit<OpenGLTexture> gCRCTableTexture(
new OpenGLTexture(512, 1, GL_RGBA, GL_UNSIGNED_BYTE, new OpenGLTexture(512, 1, GL_RGBA, GL_UNSIGNED_BYTE,
vcl_get_crc64_table())); vcl_get_crc64_table()));
@@ -595,7 +597,7 @@ bool OpenGLSalBitmap::calcChecksumGL(OpenGLTexture& rInputTexture, ChecksumType&
int nWidth = rInputTexture.GetWidth(); int nWidth = rInputTexture.GetWidth();
int nHeight = rInputTexture.GetHeight(); int nHeight = rInputTexture.GetHeight();
OpenGLProgram* pProgram = mpContext->UseProgram("textureVertexShader", FragShader); OpenGLProgram* pProgram = xContext->UseProgram("textureVertexShader", FragShader);
if (pProgram == nullptr) if (pProgram == nullptr)
return false; return false;
@@ -603,7 +605,7 @@ bool OpenGLSalBitmap::calcChecksumGL(OpenGLTexture& rInputTexture, ChecksumType&
int nNewHeight = ceil( nHeight / 4.0 ); int nNewHeight = ceil( nHeight / 4.0 );
OpenGLTexture aFirstPassTexture = OpenGLTexture(nNewWidth, nNewHeight); OpenGLTexture aFirstPassTexture = OpenGLTexture(nNewWidth, nNewHeight);
OpenGLFramebuffer* pFramebuffer = mpContext->AcquireFramebuffer(aFirstPassTexture); OpenGLFramebuffer* pFramebuffer = xContext->AcquireFramebuffer(aFirstPassTexture);
pProgram->SetUniform1f( "xstep", 1.0 / mnWidth ); pProgram->SetUniform1f( "xstep", 1.0 / mnWidth );
pProgram->SetUniform1f( "ystep", 1.0 / mnHeight ); pProgram->SetUniform1f( "ystep", 1.0 / mnHeight );
@@ -623,7 +625,7 @@ bool OpenGLSalBitmap::calcChecksumGL(OpenGLTexture& rInputTexture, ChecksumType&
nWidth = aFirstPassTexture.GetWidth(); nWidth = aFirstPassTexture.GetWidth();
nHeight = aFirstPassTexture.GetHeight(); nHeight = aFirstPassTexture.GetHeight();
pProgram = mpContext->UseProgram("textureVertexShader", FragShader); pProgram = xContext->UseProgram("textureVertexShader", FragShader);
if (pProgram == nullptr) if (pProgram == nullptr)
return false; return false;
@@ -631,7 +633,7 @@ bool OpenGLSalBitmap::calcChecksumGL(OpenGLTexture& rInputTexture, ChecksumType&
nNewHeight = ceil( nHeight / 4.0 ); nNewHeight = ceil( nHeight / 4.0 );
OpenGLTexture aSecondPassTexture = OpenGLTexture(nNewWidth, nNewHeight); OpenGLTexture aSecondPassTexture = OpenGLTexture(nNewWidth, nNewHeight);
pFramebuffer = mpContext->AcquireFramebuffer(aSecondPassTexture); pFramebuffer = xContext->AcquireFramebuffer(aSecondPassTexture);
pProgram->SetUniform1f( "xstep", 1.0 / mnWidth ); pProgram->SetUniform1f( "xstep", 1.0 / mnWidth );
pProgram->SetUniform1f( "ystep", 1.0 / mnHeight ); pProgram->SetUniform1f( "ystep", 1.0 / mnHeight );
@@ -663,7 +665,7 @@ void OpenGLSalBitmap::updateChecksum() const
OpenGLSalBitmap* pThis = const_cast<OpenGLSalBitmap*>(this); OpenGLSalBitmap* pThis = const_cast<OpenGLSalBitmap*>(this);
if (!mpContext.is()) if (!mbDirtyTexture)
{ {
pThis->CreateTexture(); pThis->CreateTexture();
} }
@@ -687,25 +689,9 @@ rtl::Reference<OpenGLContext> OpenGLSalBitmap::GetBitmapContext()
return ImplGetDefaultWindow()->GetGraphics()->GetOpenGLContext(); return ImplGetDefaultWindow()->GetGraphics()->GetOpenGLContext();
} }
void OpenGLSalBitmap::makeSomeOpenGLContextCurrent()
{
ImplSVData* pSVData = ImplGetSVData();
// TODO: make sure we can really use the last used context
OpenGLContext *pContext = pSVData->maGDIData.mpLastContext;
while( pContext && !pContext->isInitialized() )
pContext = pContext->mpPrevContext;
if( pContext )
mpContext = pContext;
else
mpContext = GetBitmapContext();
assert(mpContext.is() && "Couldn't get an OpenGL context");
mpContext->makeCurrent();
}
BitmapBuffer* OpenGLSalBitmap::AcquireBuffer( BitmapAccessMode nMode ) BitmapBuffer* OpenGLSalBitmap::AcquireBuffer( BitmapAccessMode nMode )
{ {
OpenGLZone aZone; OpenGLVCLContextZone aContextZone;
if( nMode != BITMAP_INFO_ACCESS ) if( nMode != BITMAP_INFO_ACCESS )
{ {
@@ -816,7 +802,7 @@ BitmapBuffer* OpenGLSalBitmap::AcquireBuffer( BitmapAccessMode nMode )
void OpenGLSalBitmap::ReleaseBuffer( BitmapBuffer* pBuffer, BitmapAccessMode nMode ) void OpenGLSalBitmap::ReleaseBuffer( BitmapBuffer* pBuffer, BitmapAccessMode nMode )
{ {
OpenGLZone aZone; OpenGLVCLContextZone aContextZone;
if( nMode == BITMAP_WRITE_ACCESS ) if( nMode == BITMAP_WRITE_ACCESS )
{ {
@@ -871,23 +857,22 @@ bool OpenGLSalBitmap::GetSystemData( BitmapSystemData& /*rData*/ )
bool OpenGLSalBitmap::Replace( const Color& rSearchColor, const Color& rReplaceColor, sal_uLong nTol ) bool OpenGLSalBitmap::Replace( const Color& rSearchColor, const Color& rReplaceColor, sal_uLong nTol )
{ {
VCL_GL_INFO("::Replace"); VCL_GL_INFO("::Replace");
OpenGLZone aZone; OpenGLZone aZone;
rtl::Reference< OpenGLContext > xContext = OpenGLContext::getVCLContext();
OpenGLFramebuffer* pFramebuffer; OpenGLFramebuffer* pFramebuffer;
OpenGLProgram* pProgram; OpenGLProgram* pProgram;
GetTexture(); GetTexture();
makeSomeOpenGLContextCurrent(); pProgram = xContext->UseProgram( "textureVertexShader",
pProgram = mpContext->UseProgram( "textureVertexShader", "replaceColorFragmentShader" );
"replaceColorFragmentShader" );
if( !pProgram ) if( !pProgram )
return false; return false;
OpenGLTexture aNewTex = OpenGLTexture( mnWidth, mnHeight ); OpenGLTexture aNewTex = OpenGLTexture( mnWidth, mnHeight );
pFramebuffer = mpContext->AcquireFramebuffer( aNewTex ); pFramebuffer = xContext->AcquireFramebuffer( aNewTex );
pProgram->SetTexture( "sampler", maTexture ); pProgram->SetTexture( "sampler", maTexture );
pProgram->SetColor( "search_color", rSearchColor ); pProgram->SetColor( "search_color", rSearchColor );

View File

@@ -37,6 +37,7 @@ using vcl::BilinearKernel;
using vcl::BoxKernel; using vcl::BoxKernel;
bool OpenGLSalBitmap::ImplScaleFilter( bool OpenGLSalBitmap::ImplScaleFilter(
const rtl::Reference< OpenGLContext > &xContext,
const double& rScaleX, const double& rScaleX,
const double& rScaleY, const double& rScaleY,
GLenum nFilter ) GLenum nFilter )
@@ -47,13 +48,13 @@ bool OpenGLSalBitmap::ImplScaleFilter(
int nNewWidth( mnWidth * rScaleX ); int nNewWidth( mnWidth * rScaleX );
int nNewHeight( mnHeight * rScaleY ); int nNewHeight( mnHeight * rScaleY );
pProgram = mpContext->UseProgram( "textureVertexShader", pProgram = xContext->UseProgram( "textureVertexShader",
"textureFragmentShader" ); "textureFragmentShader" );
if( !pProgram ) if( !pProgram )
return false; return false;
OpenGLTexture aNewTex(nNewWidth, nNewHeight); OpenGLTexture aNewTex(nNewWidth, nNewHeight);
pFramebuffer = mpContext->AcquireFramebuffer( aNewTex ); pFramebuffer = xContext->AcquireFramebuffer( aNewTex );
pProgram->SetTexture( "sampler", maTexture ); pProgram->SetTexture( "sampler", maTexture );
nOldFilter = maTexture.GetFilter(); nOldFilter = maTexture.GetFilter();
@@ -112,6 +113,7 @@ void OpenGLSalBitmap::ImplCreateKernel(
} }
bool OpenGLSalBitmap::ImplScaleConvolution( bool OpenGLSalBitmap::ImplScaleConvolution(
const rtl::Reference< OpenGLContext > &xContext,
const double& rScaleX, const double& rScaleX,
const double& rScaleY, const double& rScaleY,
const Kernel& aKernel ) const Kernel& aKernel )
@@ -126,7 +128,7 @@ bool OpenGLSalBitmap::ImplScaleConvolution(
// TODO Make sure the framebuffer is alright // TODO Make sure the framebuffer is alright
pProgram = mpContext->UseProgram( "textureVertexShader", pProgram = xContext->UseProgram( "textureVertexShader",
"convolutionFragmentShader" ); "convolutionFragmentShader" );
if( pProgram == nullptr ) if( pProgram == nullptr )
return false; return false;
@@ -136,7 +138,7 @@ bool OpenGLSalBitmap::ImplScaleConvolution(
{ {
OpenGLTexture aScratchTex(nNewWidth, nNewHeight); OpenGLTexture aScratchTex(nNewWidth, nNewHeight);
pFramebuffer = mpContext->AcquireFramebuffer( aScratchTex ); pFramebuffer = xContext->AcquireFramebuffer( aScratchTex );
for( sal_uInt32 i = 0; i < 16; i++ ) for( sal_uInt32 i = 0; i < 16; i++ )
{ {
@@ -159,7 +161,7 @@ bool OpenGLSalBitmap::ImplScaleConvolution(
{ {
OpenGLTexture aScratchTex(nNewWidth, nNewHeight); OpenGLTexture aScratchTex(nNewWidth, nNewHeight);
pFramebuffer = mpContext->AcquireFramebuffer( aScratchTex ); pFramebuffer = xContext->AcquireFramebuffer( aScratchTex );
for( sal_uInt32 i = 0; i < 16; i++ ) for( sal_uInt32 i = 0; i < 16; i++ )
{ {
@@ -192,7 +194,8 @@ bool OpenGLSalBitmap::ImplScaleConvolution(
the generic case needs to also consider that some source pixels contribute the generic case needs to also consider that some source pixels contribute
only partially to their resulting pixels (because of non-integer multiples). only partially to their resulting pixels (because of non-integer multiples).
*/ */
bool OpenGLSalBitmap::ImplScaleArea( double rScaleX, double rScaleY ) bool OpenGLSalBitmap::ImplScaleArea( const rtl::Reference< OpenGLContext > &xContext,
double rScaleX, double rScaleY )
{ {
int nNewWidth( mnWidth * rScaleX ); int nNewWidth( mnWidth * rScaleX );
int nNewHeight( mnHeight * rScaleY ); int nNewHeight( mnHeight * rScaleY );
@@ -213,14 +216,14 @@ bool OpenGLSalBitmap::ImplScaleArea( double rScaleX, double rScaleY )
// TODO Make sure the framebuffer is alright // TODO Make sure the framebuffer is alright
OpenGLProgram* pProgram = mpContext->UseProgram( "textureVertexShader", OpenGLProgram* pProgram = xContext->UseProgram( "textureVertexShader",
fast ? OUString( "areaScaleFastFragmentShader" ) : OUString( "areaScaleFragmentShader" )); fast ? OUString( "areaScaleFastFragmentShader" ) : OUString( "areaScaleFragmentShader" ));
if( pProgram == nullptr ) if( pProgram == nullptr )
return false; return false;
OpenGLTexture aScratchTex(nNewWidth, nNewHeight); OpenGLTexture aScratchTex(nNewWidth, nNewHeight);
OpenGLFramebuffer* pFramebuffer = mpContext->AcquireFramebuffer( aScratchTex ); OpenGLFramebuffer* pFramebuffer = xContext->AcquireFramebuffer( aScratchTex );
// NOTE: This setup is also done in OpenGLSalGraphicsImpl::DrawTransformedTexture(). // NOTE: This setup is also done in OpenGLSalGraphicsImpl::DrawTransformedTexture().
if( fast ) if( fast )
@@ -263,31 +266,32 @@ bool OpenGLSalBitmap::ImplScale( const double& rScaleX, const double& rScaleY, B
VCL_GL_INFO( "::ImplScale" ); VCL_GL_INFO( "::ImplScale" );
maUserBuffer.reset(); maUserBuffer.reset();
makeSomeOpenGLContextCurrent(); OpenGLVCLContextZone aContextZone;
rtl::Reference<OpenGLContext> xContext = OpenGLContext::getVCLContext();
if( nScaleFlag == BmpScaleFlag::Fast ) if( nScaleFlag == BmpScaleFlag::Fast )
{ {
return ImplScaleFilter( rScaleX, rScaleY, GL_NEAREST ); return ImplScaleFilter( xContext, rScaleX, rScaleY, GL_NEAREST );
} }
if( nScaleFlag == BmpScaleFlag::BiLinear ) if( nScaleFlag == BmpScaleFlag::BiLinear )
{ {
return ImplScaleFilter( rScaleX, rScaleY, GL_LINEAR ); return ImplScaleFilter( xContext, rScaleX, rScaleY, GL_LINEAR );
} }
else if( nScaleFlag == BmpScaleFlag::Super || nScaleFlag == BmpScaleFlag::Default ) else if( nScaleFlag == BmpScaleFlag::Super || nScaleFlag == BmpScaleFlag::Default )
{ {
const Lanczos3Kernel aKernel; const Lanczos3Kernel aKernel;
return ImplScaleConvolution( rScaleX, rScaleY, aKernel ); return ImplScaleConvolution( xContext, rScaleX, rScaleY, aKernel );
} }
else if( nScaleFlag == BmpScaleFlag::BestQuality && rScaleX <= 1 && rScaleY <= 1 ) else if( nScaleFlag == BmpScaleFlag::BestQuality && rScaleX <= 1 && rScaleY <= 1 )
{ // Use are scaling for best quality, but only if downscaling. { // Use are scaling for best quality, but only if downscaling.
return ImplScaleArea( rScaleX, rScaleY ); return ImplScaleArea( xContext, rScaleX, rScaleY );
} }
else if( nScaleFlag == BmpScaleFlag::Lanczos || nScaleFlag == BmpScaleFlag::BestQuality ) else if( nScaleFlag == BmpScaleFlag::Lanczos || nScaleFlag == BmpScaleFlag::BestQuality )
{ {
const Lanczos3Kernel aKernel; const Lanczos3Kernel aKernel;
return ImplScaleConvolution( rScaleX, rScaleY, aKernel ); return ImplScaleConvolution( xContext, rScaleX, rScaleY, aKernel );
} }
SAL_WARN( "vcl.opengl", "Invalid flag for scaling operation" ); SAL_WARN( "vcl.opengl", "Invalid flag for scaling operation" );
@@ -296,7 +300,7 @@ bool OpenGLSalBitmap::ImplScale( const double& rScaleX, const double& rScaleY, B
bool OpenGLSalBitmap::Scale( const double& rScaleX, const double& rScaleY, BmpScaleFlag nScaleFlag ) bool OpenGLSalBitmap::Scale( const double& rScaleX, const double& rScaleY, BmpScaleFlag nScaleFlag )
{ {
OpenGLZone aZone; OpenGLVCLContextZone aContextZone;
VCL_GL_INFO("::Scale " << int(nScaleFlag) VCL_GL_INFO("::Scale " << int(nScaleFlag)
<< " from " << mnWidth << "x" << mnHeight << " from " << mnWidth << "x" << mnHeight
@@ -309,7 +313,6 @@ bool OpenGLSalBitmap::Scale( const double& rScaleX, const double& rScaleY, BmpSc
nScaleFlag == BmpScaleFlag::Default || nScaleFlag == BmpScaleFlag::Default ||
nScaleFlag == BmpScaleFlag::BestQuality ) nScaleFlag == BmpScaleFlag::BestQuality )
{ {
makeSomeOpenGLContextCurrent();
ImplScale( rScaleX, rScaleY, nScaleFlag ); ImplScale( rScaleX, rScaleY, nScaleFlag );
return true; return true;
} }

View File

@@ -28,6 +28,7 @@
#include "opengl/framebuffer.hxx" #include "opengl/framebuffer.hxx"
#include "opengl/texture.hxx" #include "opengl/texture.hxx"
#include "opengl/zone.hxx"
// texture with allocated size // texture with allocated size
ImplOpenGLTexture::ImplOpenGLTexture( int nWidth, int nHeight, bool bAllocate ) : ImplOpenGLTexture::ImplOpenGLTexture( int nWidth, int nHeight, bool bAllocate ) :
@@ -38,6 +39,8 @@ ImplOpenGLTexture::ImplOpenGLTexture( int nWidth, int nHeight, bool bAllocate )
mnOptStencil( 0 ), mnOptStencil( 0 ),
mnFreeSlots(-1) mnFreeSlots(-1)
{ {
OpenGLVCLContextZone aContextZone;
glGenTextures( 1, &mnTexture ); glGenTextures( 1, &mnTexture );
CHECK_GL_ERROR(); CHECK_GL_ERROR();
glBindTexture( GL_TEXTURE_2D, mnTexture ); glBindTexture( GL_TEXTURE_2D, mnTexture );
@@ -71,6 +74,8 @@ ImplOpenGLTexture::ImplOpenGLTexture( int nX, int nY, int nWidth, int nHeight )
mnOptStencil( 0 ), mnOptStencil( 0 ),
mnFreeSlots(-1) mnFreeSlots(-1)
{ {
OpenGLVCLContextZone aContextZone;
// FIXME We need the window height here // FIXME We need the window height here
// nY = GetHeight() - nHeight - nY; // nY = GetHeight() - nHeight - nY;
@@ -104,6 +109,8 @@ ImplOpenGLTexture::ImplOpenGLTexture( int nWidth, int nHeight, int nFormat, int
mnOptStencil( 0 ), mnOptStencil( 0 ),
mnFreeSlots(-1) mnFreeSlots(-1)
{ {
OpenGLVCLContextZone aContextZone;
if( !mnTexture ) if( !mnTexture )
{ {
glGenTextures( 1, &mnTexture ); glGenTextures( 1, &mnTexture );
@@ -152,13 +159,18 @@ ImplOpenGLTexture::~ImplOpenGLTexture()
VCL_GL_INFO( "~OpenGLTexture " << mnTexture ); VCL_GL_INFO( "~OpenGLTexture " << mnTexture );
if( mnTexture != 0 ) if( mnTexture != 0 )
{ {
OpenGLVCLContextZone aContextZone;
// FIXME: this is really not optimal performance-wise. // FIXME: this is really not optimal performance-wise.
// Check we have been correctly un-bound from all framebuffers. // Check we have been correctly un-bound from all framebuffers.
ImplSVData* pSVData = ImplGetSVData(); ImplSVData* pSVData = ImplGetSVData();
rtl::Reference<OpenGLContext> pContext = pSVData->maGDIData.mpLastContext; rtl::Reference<OpenGLContext> pContext = pSVData->maGDIData.mpLastContext;
if( pContext.is() ) if( pContext.is() )
{
pContext->makeCurrent();
pContext->UnbindTextureFromFramebuffers( mnTexture ); pContext->UnbindTextureFromFramebuffers( mnTexture );
}
if( mnOptStencil != 0 ) if( mnOptStencil != 0 )
glDeleteRenderbuffers( 1, &mnOptStencil ); glDeleteRenderbuffers( 1, &mnOptStencil );
@@ -426,6 +438,8 @@ void OpenGLTexture::Read( GLenum nFormat, GLenum nType, sal_uInt8* pData )
return; return;
} }
OpenGLVCLContextZone aContextZone;
VCL_GL_INFO( "Reading texture " << Id() << " " << GetWidth() << "x" << GetHeight() ); VCL_GL_INFO( "Reading texture " << Id() << " " << GetWidth() << "x" << GetHeight() );
if( GetWidth() == mpImpl->mnWidth && GetHeight() == mpImpl->mnHeight ) if( GetWidth() == mpImpl->mnWidth && GetHeight() == mpImpl->mnHeight )

View File

@@ -32,6 +32,7 @@
#endif #endif
#include "svdata.hxx" #include "svdata.hxx"
#include "salgdi.hxx"
#include <opengl/framebuffer.hxx> #include <opengl/framebuffer.hxx>
#include <opengl/program.hxx> #include <opengl/program.hxx>
@@ -1443,6 +1444,43 @@ void OpenGLContext::makeCurrent()
registerAsCurrent(); registerAsCurrent();
} }
rtl::Reference<OpenGLContext> OpenGLContext::getVCLContext(bool bMakeIfNecessary)
{
ImplSVData* pSVData = ImplGetSVData();
OpenGLContext *pContext = pSVData->maGDIData.mpLastContext;
while( pContext )
{
// check if this context is usable
if( pContext->isInitialized() && pContext->isVCLOnly() )
break;
pContext = pContext->mpPrevContext;
}
rtl::Reference<OpenGLContext> xContext;
if( !pContext && bMakeIfNecessary )
{
// create our magic fallback window context.
xContext = ImplGetDefaultContextWindow()->GetGraphics()->GetOpenGLContext();
assert(xContext.is());
}
else
xContext = pContext;
if( xContext.is() )
xContext->makeCurrent();
return xContext;
}
/*
* We don't care what context we have, but we want one that is live,
* ie. not reset underneath us, and is setup for VCL usage - ideally
* not swapping context at all.
*/
void OpenGLContext::makeVCLCurrent()
{
getVCLContext(true);
}
void OpenGLContext::registerAsCurrent() void OpenGLContext::registerAsCurrent()
{ {
ImplSVData* pSVData = ImplGetSVData(); ImplSVData* pSVData = ImplGetSVData();

View File

@@ -943,6 +943,11 @@ void OpenGLZone::hardDisable()
} }
} }
OpenGLVCLContextZone::OpenGLVCLContextZone()
{
OpenGLContext::makeVCLCurrent();
}
bool OpenGLHelper::isVCLOpenGLEnabled() bool OpenGLHelper::isVCLOpenGLEnabled()
{ {
/** /**