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:
@@ -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.
|
||||||
|
@@ -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:
|
||||||
|
|
||||||
|
@@ -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: */
|
||||||
|
@@ -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;
|
||||||
|
|
||||||
|
@@ -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
|
||||||
|
@@ -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 );
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
@@ -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 )
|
||||||
|
@@ -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();
|
||||||
|
@@ -943,6 +943,11 @@ void OpenGLZone::hardDisable()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OpenGLVCLContextZone::OpenGLVCLContextZone()
|
||||||
|
{
|
||||||
|
OpenGLContext::makeVCLCurrent();
|
||||||
|
}
|
||||||
|
|
||||||
bool OpenGLHelper::isVCLOpenGLEnabled()
|
bool OpenGLHelper::isVCLOpenGLEnabled()
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user