summaryrefslogtreecommitdiff
path: root/vcl/opengl/texture.cxx
diff options
context:
space:
mode:
authorLouis-Francis Ratté-Boulianne <lfrb@collabora.com>2014-11-13 21:37:54 -0500
committerMarkus Mohrhard <markus.mohrhard@googlemail.com>2014-11-15 12:17:43 +0100
commitdce9610afed674ecec23497a1a004193a6cf3bf1 (patch)
tree7b0e2063667645ae3a4259a08c0ab1d2fce0eaf1 /vcl/opengl/texture.cxx
parent330b7b310193f3290cbd4c340659f72d12c352e1 (diff)
vcl: Improve OpenGLTexture implementation by allowing implicit sharing
Conflicts: vcl/opengl/gdiimpl.cxx Change-Id: I6421265325e72023d1affe671d75488185772786
Diffstat (limited to 'vcl/opengl/texture.cxx')
-rw-r--r--vcl/opengl/texture.cxx243
1 files changed, 206 insertions, 37 deletions
diff --git a/vcl/opengl/texture.cxx b/vcl/opengl/texture.cxx
index 0c8dc1d69b8e..005fb66afa2e 100644
--- a/vcl/opengl/texture.cxx
+++ b/vcl/opengl/texture.cxx
@@ -24,19 +24,12 @@
#include "opengl/texture.hxx"
-OpenGLTexture::OpenGLTexture()
-: mnTexture( 0 )
-, mnWidth( -1 )
-, mnHeight( -1 )
-, mnFilter( GL_NEAREST )
-{
-}
-
-OpenGLTexture::OpenGLTexture( int nWidth, int nHeight )
-: mnTexture( 0 )
-, mnWidth( nWidth )
-, mnHeight( nHeight )
-, mnFilter( GL_NEAREST )
+// texture with allocated size
+ImplOpenGLTexture::ImplOpenGLTexture( int nWidth, int nHeight, bool bAllocate ) :
+ mnRefCount( 1 ),
+ mnWidth( nWidth ),
+ mnHeight( nHeight ),
+ mnFilter( GL_NEAREST )
{
glGenTextures( 1, &mnTexture );
glBindTexture( GL_TEXTURE_2D, mnTexture );
@@ -44,15 +37,18 @@ OpenGLTexture::OpenGLTexture( int nWidth, int nHeight )
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
- glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, nWidth, nHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
+ if( bAllocate )
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, nWidth, nHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
glBindTexture( GL_TEXTURE_2D, 0 );
}
-OpenGLTexture::OpenGLTexture( int nX, int nY, int nWidth, int nHeight )
-: mnTexture( 0 )
-, mnWidth( nWidth )
-, mnHeight( nHeight )
-, mnFilter( GL_NEAREST )
+// texture with content retrieved from FBO
+ImplOpenGLTexture::ImplOpenGLTexture( int nX, int nY, int nWidth, int nHeight ) :
+ mnRefCount( 1 ),
+ mnTexture( 0 ),
+ mnWidth( nWidth ),
+ mnHeight( nHeight ),
+ mnFilter( GL_NEAREST )
{
glGenTextures( 1, &mnTexture );
glBindTexture( GL_TEXTURE_2D, mnTexture );
@@ -66,11 +62,13 @@ OpenGLTexture::OpenGLTexture( int nX, int nY, int nWidth, int nHeight )
CHECK_GL_ERROR();
}
-OpenGLTexture::OpenGLTexture( int nWidth, int nHeight, int nFormat, int nType, sal_uInt8* pData )
-: mnTexture( 0 )
-, mnWidth( nWidth )
-, mnHeight( nHeight )
-, mnFilter( GL_NEAREST )
+// texture from buffer data
+ImplOpenGLTexture::ImplOpenGLTexture( int nWidth, int nHeight, int nFormat, int nType, sal_uInt8* pData ) :
+ mnRefCount( 1 ),
+ mnTexture( 0 ),
+ mnWidth( nWidth ),
+ mnHeight( nHeight ),
+ mnFilter( GL_NEAREST )
{
if( !mnTexture )
glGenTextures( 1, &mnTexture );
@@ -84,37 +82,119 @@ OpenGLTexture::OpenGLTexture( int nWidth, int nHeight, int nFormat, int nType, s
glBindTexture( GL_TEXTURE_2D, 0 );
}
-OpenGLTexture::~OpenGLTexture()
+ImplOpenGLTexture::~ImplOpenGLTexture()
{
+ SAL_INFO( "vcl.opengl", "~OpenGLTexture " << mnTexture );
if( mnTexture != 0 )
glDeleteTextures( 1, &mnTexture );
}
+OpenGLTexture::OpenGLTexture() :
+ maRect( 0, 0, 0, 0 ),
+ mpImpl( NULL )
+{
+}
+
+OpenGLTexture::OpenGLTexture( int nWidth, int nHeight, bool bAllocate ) :
+ maRect( Point( 0, 0 ), Size( nWidth, nHeight ) )
+{
+ mpImpl = new ImplOpenGLTexture( nWidth, nHeight, bAllocate );
+}
+
+OpenGLTexture::OpenGLTexture( int nX, int nY, int nWidth, int nHeight ) :
+ maRect( Point( 0, 0 ), Size( nWidth, nHeight ) )
+{
+ mpImpl = new ImplOpenGLTexture( nX, nY, nWidth, nHeight );
+}
+
+OpenGLTexture::OpenGLTexture( int nWidth, int nHeight, int nFormat, int nType, sal_uInt8* pData ) :
+ maRect( Point( 0, 0 ), Size( nWidth, nHeight ) )
+{
+ mpImpl = new ImplOpenGLTexture( nWidth, nHeight, nFormat, nType, pData );
+}
+
+OpenGLTexture::OpenGLTexture( const OpenGLTexture& rTexture )
+{
+ maRect = rTexture.maRect;
+ mpImpl = rTexture.mpImpl;
+ if( mpImpl )
+ mpImpl->mnRefCount++;
+}
+
+OpenGLTexture::OpenGLTexture( const OpenGLTexture& rTexture,
+ int nX, int nY, int nWidth, int nHeight )
+{
+ maRect = Rectangle( Point( rTexture.maRect.Left() + nX, rTexture.maRect.Top() + nY ),
+ Size( nWidth, nHeight ) );
+ mpImpl = rTexture.mpImpl;
+ if( mpImpl )
+ mpImpl->mnRefCount++;
+ SAL_INFO( "vcl.opengl", "Copying texture " << Id() << " [" << maRect.Left() << "," << maRect.Top() << "] " << GetWidth() << "x" << GetHeight() );
+}
+
+OpenGLTexture::~OpenGLTexture()
+{
+ if( mpImpl )
+ {
+ if( mpImpl->mnRefCount == 1 )
+ delete mpImpl;
+ else
+ mpImpl->mnRefCount--;
+ }
+}
+
+bool OpenGLTexture::IsUnique() const
+{
+ return ( mpImpl == NULL || mpImpl->mnRefCount == 1 );
+}
+
GLuint OpenGLTexture::Id() const
{
- return mnTexture;
+ if( mpImpl )
+ return mpImpl->mnTexture;
+ return 0;
}
int OpenGLTexture::GetWidth() const
{
- return mnWidth;
+ return maRect.GetWidth();
}
int OpenGLTexture::GetHeight() const
{
- return mnHeight;
+ return maRect.GetHeight();
+}
+
+void OpenGLTexture::GetCoord( GLfloat* pCoord, const SalTwoRect& rPosAry, bool bInverted ) const
+{
+ SAL_INFO( "vcl.opengl", "Getting coord " << Id() << " [" << maRect.Left() << "," << maRect.Top() << "] " << GetWidth() << "x" << GetHeight() );
+ pCoord[0] = pCoord[2] = (maRect.Left() + rPosAry.mnSrcX) / (double) mpImpl->mnWidth;
+ pCoord[4] = pCoord[6] = (maRect.Left() + rPosAry.mnSrcX + rPosAry.mnSrcWidth) / (double) mpImpl->mnWidth;
+
+ if( !bInverted )
+ {
+ pCoord[3] = pCoord[5] = 1.0f - (maRect.Top() + rPosAry.mnSrcY) / (double) mpImpl->mnHeight;
+ pCoord[1] = pCoord[7] = 1.0f - (maRect.Top() + rPosAry.mnSrcY + rPosAry.mnSrcHeight) / (double) mpImpl->mnHeight;
+ }
+ else
+ {
+ pCoord[1] = pCoord[7] = 1.0f - (maRect.Top() + rPosAry.mnSrcY) / (double) mpImpl->mnHeight;
+ pCoord[3] = pCoord[5] = 1.0f - (maRect.Top() + rPosAry.mnSrcY + rPosAry.mnSrcHeight) / (double) mpImpl->mnHeight;
+ }
}
GLenum OpenGLTexture::GetFilter() const
{
- return mnFilter;
+ if( mpImpl )
+ return mpImpl->mnFilter;
+ return GL_NEAREST;
}
void OpenGLTexture::SetFilter( GLenum nFilter )
{
- mnFilter = nFilter;
- if( mnTexture )
+ if( mpImpl )
{
+ mpImpl->mnFilter = nFilter;
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, nFilter );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, nFilter );
}
@@ -122,23 +202,38 @@ void OpenGLTexture::SetFilter( GLenum nFilter )
void OpenGLTexture::Bind()
{
- glBindTexture( GL_TEXTURE_2D, mnTexture );
+ if( mpImpl )
+ glBindTexture( GL_TEXTURE_2D, mpImpl->mnTexture );
}
void OpenGLTexture::Unbind()
{
- glBindTexture( GL_TEXTURE_2D, 0 );
+ if( mpImpl )
+ glBindTexture( GL_TEXTURE_2D, 0 );
}
bool OpenGLTexture::Draw()
{
- const GLfloat aPosition[8] = { -1, -1, -1, 1, 1, 1, 1, -1 };
- const GLfloat aTexCoord[8] = { 0, 0, 0, 1, 1, 1, 1, 0 };
+ GLfloat aPosition[8] = { -1, -1, -1, 1, 1, 1, 1, -1 };
+ GLfloat aTexCoord[8] = { 0, 0, 0, 1, 1, 1, 1, 0 };
- if( mnTexture == 0 )
+ if( mpImpl == NULL )
+ {
+ SAL_WARN( "vcl.opengl", "Can't draw invalid texture" );
return false;
+ }
- glBindTexture( GL_TEXTURE_2D, mnTexture );
+ SAL_INFO( "vcl.opengl", "Drawing texture " << Id() << " [" << maRect.Left() << "," << maRect.Top() << "] " << GetWidth() << "x" << GetHeight() );
+ if( GetWidth() != mpImpl->mnWidth || GetHeight() != mpImpl->mnHeight )
+ {
+ // FIXME: lfrb: check math
+ aTexCoord[0] = aTexCoord[2] = maRect.Left() / (double) mpImpl->mnWidth;
+ aTexCoord[4] = aTexCoord[6] = maRect.Right() / (double) mpImpl->mnWidth;
+ aTexCoord[1] = aTexCoord[7] = maRect.Top() / (double) mpImpl->mnHeight;
+ aTexCoord[3] = aTexCoord[5] = maRect.Bottom() / (double) mpImpl->mnHeight;
+ }
+
+ glBindTexture( GL_TEXTURE_2D, mpImpl->mnTexture );
glEnableVertexAttribArray( 0 );
glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, 0, aPosition );
glEnableVertexAttribArray( 1 );
@@ -151,4 +246,78 @@ bool OpenGLTexture::Draw()
return true;
}
+void OpenGLTexture::Read( GLenum nFormat, GLenum nType, sal_uInt8* pData )
+{
+ if( mpImpl == NULL )
+ {
+ SAL_WARN( "vcl.opengl", "Can't read invalid texture" );
+ return;
+ }
+
+ Bind();
+ glPixelStorei( GL_PACK_ALIGNMENT, 1 );
+
+ SAL_INFO( "vcl.opengl", "Reading texture " << Id() << " " << GetWidth() << "x" << GetHeight() );
+
+ if( GetWidth() == mpImpl->mnWidth && GetHeight() == mpImpl->mnHeight )
+ {
+ // XXX: Call not available with GLES 2.0
+ glGetTexImage( GL_TEXTURE_2D, 0, nFormat, nType, pData );
+ }
+ else
+ {
+ GLuint nFramebufferId;
+ glGenFramebuffers( 1, &nFramebufferId );
+ glBindFramebuffer( GL_FRAMEBUFFER, nFramebufferId );
+ CHECK_GL_ERROR();
+
+ glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, Id(), 0 );
+ CHECK_GL_ERROR();
+ glReadPixels( maRect.Left(), mpImpl->mnHeight - maRect.Top(), GetWidth(), GetHeight(), nFormat, nType, pData );
+ CHECK_GL_ERROR();
+
+ glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+ glDeleteFramebuffers( 1, &nFramebufferId );
+
+ int bpp = (nFormat == GL_RGB) ? 3 : 4;
+ memset( pData, 255, GetWidth() * GetHeight() * bpp );
+ }
+
+ Unbind();
+ CHECK_GL_ERROR();
+}
+
+OpenGLTexture::operator bool() const
+{
+ return ( mpImpl != NULL );
+}
+
+OpenGLTexture& OpenGLTexture::operator=( const OpenGLTexture& rTexture )
+{
+ if( rTexture.mpImpl )
+ rTexture.mpImpl->mnRefCount++;
+ if( mpImpl )
+ {
+ if( mpImpl->mnRefCount == 1 )
+ delete mpImpl;
+ else
+ mpImpl->mnRefCount--;
+ }
+
+ maRect = rTexture.maRect;
+ mpImpl = rTexture.mpImpl;
+
+ return *this;
+}
+
+bool OpenGLTexture::operator==( const OpenGLTexture& rTexture ) const
+{
+ return (mpImpl == rTexture.mpImpl && maRect == rTexture.maRect );
+}
+
+bool OpenGLTexture::operator!=( const OpenGLTexture& rTexture ) const
+{
+ return !( *this == rTexture );
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */