diff options
author | Louis-Francis Ratté-Boulianne <lfrb@collabora.com> | 2014-11-13 21:37:54 -0500 |
---|---|---|
committer | Markus Mohrhard <markus.mohrhard@googlemail.com> | 2014-11-15 12:17:43 +0100 |
commit | dce9610afed674ecec23497a1a004193a6cf3bf1 (patch) | |
tree | 7b0e2063667645ae3a4259a08c0ab1d2fce0eaf1 /vcl | |
parent | 330b7b310193f3290cbd4c340659f72d12c352e1 (diff) |
vcl: Improve OpenGLTexture implementation by allowing implicit sharing
Conflicts:
vcl/opengl/gdiimpl.cxx
Change-Id: I6421265325e72023d1affe671d75488185772786
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/inc/opengl/salbmp.hxx | 7 | ||||
-rw-r--r-- | vcl/inc/opengl/texture.hxx | 67 | ||||
-rw-r--r-- | vcl/inc/openglgdiimpl.hxx | 10 | ||||
-rw-r--r-- | vcl/opengl/gdiimpl.cxx | 82 | ||||
-rw-r--r-- | vcl/opengl/salbmp.cxx | 71 | ||||
-rw-r--r-- | vcl/opengl/scale.cxx | 97 | ||||
-rw-r--r-- | vcl/opengl/texture.cxx | 243 | ||||
-rw-r--r-- | vcl/opengl/x11/gdiimpl.cxx | 13 | ||||
-rw-r--r-- | vcl/win/source/gdi/winlayout.cxx | 2 |
9 files changed, 377 insertions, 215 deletions
diff --git a/vcl/inc/opengl/salbmp.hxx b/vcl/inc/opengl/salbmp.hxx index c1f0cdb817ad..dbb29d80f802 100644 --- a/vcl/inc/opengl/salbmp.hxx +++ b/vcl/inc/opengl/salbmp.hxx @@ -40,7 +40,7 @@ class VCL_PLUGIN_PUBLIC OpenGLSalBitmap : public SalBitmap { private: OpenGLContext* mpContext; - OpenGLTextureSharedPtr mpTexture; + OpenGLTexture maTexture; bool mbDirtyTexture; BitmapPalette maPalette; basebmp::RawMemorySharedArray maUserBuffer; @@ -81,9 +81,8 @@ public: public: - bool Create( OpenGLContext& rContext, OpenGLTextureSharedPtr pTex, long nX, long nY, long nWidth, long nHeight ); - bool Draw( OpenGLContext& rContext, const SalTwoRect& rPosAry ); - GLuint GetTexture( OpenGLContext& rContext ) const; + bool Create( OpenGLContext& rContext, const OpenGLTexture& rTex, long nX, long nY, long nWidth, long nHeight ); + OpenGLTexture& GetTexture( OpenGLContext& rContext ) const; private: diff --git a/vcl/inc/opengl/texture.hxx b/vcl/inc/opengl/texture.hxx index c0b6541d7700..eb003cfe5b96 100644 --- a/vcl/inc/opengl/texture.hxx +++ b/vcl/inc/opengl/texture.hxx @@ -20,37 +20,62 @@ #ifndef INCLUDED_VCL_INC_OPENGL_TEXTURE_H #define INCLUDED_VCL_INC_OPENGL_TEXTURE_H -#include <boost/shared_ptr.hpp> #include <GL/glew.h> +#include <vcl/dllapi.h> -class OpenGLTexture +class ImplOpenGLTexture { -private: +public: + int mnRefCount; GLuint mnTexture; int mnWidth; int mnHeight; GLenum mnFilter; -public: - OpenGLTexture(); - OpenGLTexture( int nWidth, int nHeight ); - OpenGLTexture( int nWidth, int nHeight, int nFormat, int nType, sal_uInt8* pData ); - OpenGLTexture( int nX, int nY, int nWidth, int nHeight ); - virtual ~OpenGLTexture(); - - GLuint Id() const; - int GetWidth() const; - int GetHeight() const; - - void Bind(); - void Unbind(); - bool Draw(); - - GLenum GetFilter() const; - void SetFilter( GLenum nFilter ); + ImplOpenGLTexture( int nWidth, int nHeight, bool bAllocate ); + ImplOpenGLTexture( int nWidth, int nHeight, int nFormat, int nType, sal_uInt8* pData ); + ImplOpenGLTexture( int nX, int nY, int nWidth, int nHeight ); + ~ImplOpenGLTexture(); }; -typedef boost::shared_ptr< OpenGLTexture > OpenGLTextureSharedPtr; +class VCL_PLUGIN_PUBLIC OpenGLTexture +{ +private: + // if the rect size doesn't match the mpImpl one, this instance + // is a sub-area from the real OpenGL texture + Rectangle maRect; + + ImplOpenGLTexture* mpImpl; + +public: + OpenGLTexture(); + OpenGLTexture( int nWidth, int nHeight, bool bAllocate = true ); + OpenGLTexture( int nWidth, int nHeight, int nFormat, int nType, sal_uInt8* pData ); + OpenGLTexture( int nX, int nY, int nWidth, int nHeight ); + OpenGLTexture( const OpenGLTexture& rTexture ); + OpenGLTexture( const OpenGLTexture& rTexture, int nX, int nY, int nWidth, int nHeight ); + virtual ~OpenGLTexture(); + + bool IsUnique() const; + + GLuint Id() const; + int GetWidth() const; + int GetHeight() const; + void GetCoord( GLfloat* pCoord, const SalTwoRect& rPosAry, bool bInverted=false ) const; + + void Bind(); + void Unbind(); + bool Draw(); + void Read( GLenum nFormat, GLenum nType, sal_uInt8* pData ); + + GLenum GetFilter() const; + void SetFilter( GLenum nFilter ); + + operator bool() const; + OpenGLTexture& operator=( const OpenGLTexture& rTexture ); + bool operator==( const OpenGLTexture& rTexture ) const; + bool operator!=( const OpenGLTexture& rTexture ) const; +}; #endif // INCLUDED_VCL_INC_OPENGL_TEXTURE_H diff --git a/vcl/inc/openglgdiimpl.hxx b/vcl/inc/openglgdiimpl.hxx index 1fb0d6167c3e..965365e8760a 100644 --- a/vcl/inc/openglgdiimpl.hxx +++ b/vcl/inc/openglgdiimpl.hxx @@ -45,7 +45,7 @@ protected: bool mbOffscreen; GLuint mnFramebufferId; - OpenGLTextureSharedPtr mpOffscreenTex; + OpenGLTexture maOffscreenTex; SalColor mnLineColor; SalColor mnFillColor; @@ -98,10 +98,10 @@ protected: void DrawRect( const Rectangle& rRect ); void DrawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry ); void DrawPolyPolygon( const basegfx::B2DPolyPolygon& rPolyPolygon ); - void DrawTextureRect( const Size& rSize, const SalTwoRect& rPosAry, bool bInverted = false ); - void DrawTexture( GLuint nTexture, const Size& rSize, const SalTwoRect& rPosAry, bool bInverted = false ); - void DrawTextureWithMask( GLuint nTexture, GLuint nMask, const Size& rSize, const SalTwoRect& rPosAry ); - void DrawMask( GLuint nMask, SalColor nMaskColor, const SalTwoRect& rPosAry ); + void DrawTextureRect( OpenGLTexture& rTexture, const SalTwoRect& rPosAry, bool bInverted = false ); + void DrawTexture( OpenGLTexture& rTexture, const SalTwoRect& rPosAry, bool bInverted = false ); + void DrawTextureWithMask( OpenGLTexture& rTexture, OpenGLTexture& rMask, const SalTwoRect& rPosAry ); + void DrawMask( OpenGLTexture& rTexture, SalColor nMaskColor, const SalTwoRect& rPosAry ); void DrawLinearGradient( const Gradient& rGradient, const Rectangle& rRect ); void DrawRadialGradient( const Gradient& rGradient, const Rectangle& rRect ); diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx index 801130ffbb29..6a4ee80d2e7c 100644 --- a/vcl/opengl/gdiimpl.cxx +++ b/vcl/opengl/gdiimpl.cxx @@ -66,7 +66,6 @@ OpenGLSalGraphicsImpl::OpenGLSalGraphicsImpl() , mbUseStencil(false) , mbOffscreen(false) , mnFramebufferId(0) - , mpOffscreenTex(nullptr) , mnLineColor(SALCOLOR_NONE) , mnFillColor(SALCOLOR_NONE) , mnSolidProgram(0) @@ -260,8 +259,8 @@ void OpenGLSalGraphicsImpl::SetOffscreen( bool bOffscreen ) return; // Already enabled and same size - if( mpOffscreenTex->GetWidth() == GetWidth() && - mpOffscreenTex->GetHeight() == GetHeight() ) + if( maOffscreenTex.GetWidth() == GetWidth() && + maOffscreenTex.GetHeight() == GetHeight() ) return; } else @@ -276,8 +275,8 @@ void OpenGLSalGraphicsImpl::SetOffscreen( bool bOffscreen ) if( mbOffscreen ) { glBindFramebuffer( GL_FRAMEBUFFER, mnFramebufferId ); - mpOffscreenTex.reset( new OpenGLTexture( GetWidth(), GetHeight() ) ); - glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mpOffscreenTex->Id(), 0 ); + maOffscreenTex = OpenGLTexture( GetWidth(), GetHeight() ); + glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, maOffscreenTex.Id(), 0 ); } CHECK_GL_ERROR(); @@ -611,24 +610,11 @@ void OpenGLSalGraphicsImpl::DrawPolyPolygon( const basegfx::B2DPolyPolygon& rPol CHECK_GL_ERROR(); } -void OpenGLSalGraphicsImpl::DrawTextureRect( const Size& rSize, const SalTwoRect& rPosAry, bool bInverted ) +void OpenGLSalGraphicsImpl::DrawTextureRect( OpenGLTexture& rTexture, const SalTwoRect& rPosAry, bool bInverted ) { GLfloat aTexCoord[8]; - aTexCoord[0] = aTexCoord[2] = rPosAry.mnSrcX / (double) rSize.Width(); - aTexCoord[4] = aTexCoord[6] = (rPosAry.mnSrcX + rPosAry.mnSrcWidth) / (double) rSize.Width(); - - if( !bInverted ) - { - aTexCoord[3] = aTexCoord[5] = (rSize.Height() - rPosAry.mnSrcY) / (double) rSize.Height(); - aTexCoord[1] = aTexCoord[7] = (rSize.Height() - rPosAry.mnSrcY - rPosAry.mnSrcHeight) / (double) rSize.Height(); - } - else - { - aTexCoord[1] = aTexCoord[7] = (rSize.Height() - rPosAry.mnSrcY) / (double) rSize.Height(); - aTexCoord[3] = aTexCoord[5] = (rSize.Height() - rPosAry.mnSrcY - rPosAry.mnSrcHeight) / (double) rSize.Height(); - } - + rTexture.GetCoord( aTexCoord, rPosAry, bInverted ); glEnableVertexAttribArray( GL_ATTRIB_TEX ); glVertexAttribPointer( GL_ATTRIB_TEX, 2, GL_FLOAT, GL_FALSE, 0, aTexCoord ); @@ -639,7 +625,7 @@ void OpenGLSalGraphicsImpl::DrawTextureRect( const Size& rSize, const SalTwoRect CHECK_GL_ERROR(); } -void OpenGLSalGraphicsImpl::DrawTexture( GLuint nTexture, const Size& rSize, const SalTwoRect& pPosAry, bool bInverted ) +void OpenGLSalGraphicsImpl::DrawTexture( OpenGLTexture& rTexture, const SalTwoRect& pPosAry, bool bInverted ) { if( mnTextureProgram == 0 ) { @@ -651,18 +637,18 @@ void OpenGLSalGraphicsImpl::DrawTexture( GLuint nTexture, const Size& rSize, con glUniform1i( mnSamplerUniform, 0 ); glActiveTexture( GL_TEXTURE0 ); CHECK_GL_ERROR(); - glBindTexture( GL_TEXTURE_2D, nTexture ); - DrawTextureRect( rSize, pPosAry, bInverted ); + rTexture.Bind(); + DrawTextureRect( rTexture, pPosAry, bInverted ); + rTexture.Unbind(); CHECK_GL_ERROR(); - glBindTexture( GL_TEXTURE_2D, 0 ); glUseProgram( 0 ); CHECK_GL_ERROR(); } -void OpenGLSalGraphicsImpl::DrawTextureWithMask( GLuint nTexture, GLuint nMask, const Size& rSize, const SalTwoRect& pPosAry ) +void OpenGLSalGraphicsImpl::DrawTextureWithMask( OpenGLTexture& rTexture, OpenGLTexture& rMask, const SalTwoRect& pPosAry ) { if( mnMaskedTextureProgram == 0 ) { @@ -674,25 +660,25 @@ void OpenGLSalGraphicsImpl::DrawTextureWithMask( GLuint nTexture, GLuint nMask, glUniform1i( mnMaskedSamplerUniform, 0 ); glUniform1i( mnMaskSamplerUniform, 1 ); glActiveTexture( GL_TEXTURE0 ); - glBindTexture( GL_TEXTURE_2D, nTexture ); + rTexture.Bind(); glActiveTexture( GL_TEXTURE1 ); - glBindTexture( GL_TEXTURE_2D, nMask ); + rMask.Bind(); glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); - DrawTextureRect( rSize, pPosAry ); + DrawTextureRect( rTexture, pPosAry ); glDisable( GL_BLEND ); glActiveTexture( GL_TEXTURE1 ); - glBindTexture( GL_TEXTURE_2D, 0 ); + rMask.Unbind(); glActiveTexture( GL_TEXTURE0 ); - glBindTexture( GL_TEXTURE_2D, 0 ); + rTexture.Unbind(); glUseProgram( 0 ); CHECK_GL_ERROR(); } -void OpenGLSalGraphicsImpl::DrawMask( GLuint nMask, SalColor nMaskColor, const SalTwoRect& /*pPosAry*/ ) +void OpenGLSalGraphicsImpl::DrawMask( OpenGLTexture& rMask, SalColor nMaskColor, const SalTwoRect& /*pPosAry*/ ) { if( mnMaskProgram == 0 ) { @@ -704,12 +690,11 @@ void OpenGLSalGraphicsImpl::DrawMask( GLuint nMask, SalColor nMaskColor, const S glUniformColor( mnMaskColorUniform, nMaskColor, 0 ); glUniform1i( mnMaskUniform, 0 ); glActiveTexture( GL_TEXTURE0 ); - glBindTexture( GL_TEXTURE_2D, nMask ); + rMask.Bind(); - //DrawTextureRect( pPosAry ); + //DrawTextureRect( rMask, pPosAry ); - glActiveTexture( GL_TEXTURE0 ); - glBindTexture( GL_TEXTURE_2D, 0 ); + rMask.Unbind(); glUseProgram( 0 ); CHECK_GL_ERROR(); @@ -1122,12 +1107,11 @@ void OpenGLSalGraphicsImpl::drawBitmap( const SalTwoRect& rPosAry, const SalBitm assert(dynamic_cast<const OpenGLSalBitmap*>(&rSalBitmap)); const OpenGLSalBitmap& rBitmap = static_cast<const OpenGLSalBitmap&>(rSalBitmap); - GLuint nTexture = rBitmap.GetTexture( maContext ); - const Size aSize = rSalBitmap.GetSize(); + OpenGLTexture& rTexture = rBitmap.GetTexture( maContext ); SAL_INFO( "vcl.opengl", "::drawBitmap" ); PreDraw(); - DrawTexture( nTexture, aSize, rPosAry ); + DrawTexture( rTexture, rPosAry ); PostDraw(); } @@ -1146,12 +1130,12 @@ void OpenGLSalGraphicsImpl::drawBitmap( { const OpenGLSalBitmap& rBitmap = static_cast<const OpenGLSalBitmap&>(rSalBitmap); const OpenGLSalBitmap& rMask = static_cast<const OpenGLSalBitmap&>(rMaskBitmap); - const GLuint nTexture( rBitmap.GetTexture( maContext ) ); - const GLuint nMask( rMask.GetTexture( maContext ) ); + OpenGLTexture& rTexture( rBitmap.GetTexture( maContext ) ); + OpenGLTexture& rMaskTex( rMask.GetTexture( maContext ) ); SAL_INFO( "vcl.opengl", "::drawBitmap with MASK" ); PreDraw(); - DrawTextureWithMask( nTexture, nMask, rBitmap.GetSize(), rPosAry ); + DrawTextureWithMask( rTexture, rMaskTex, rPosAry ); PostDraw(); } @@ -1161,11 +1145,11 @@ void OpenGLSalGraphicsImpl::drawMask( SalColor nMaskColor ) { const OpenGLSalBitmap& rBitmap = static_cast<const OpenGLSalBitmap&>(rSalBitmap); - const GLuint nTexture( rBitmap.GetTexture( maContext ) ); + OpenGLTexture& rTexture( rBitmap.GetTexture( maContext ) ); SAL_INFO( "vcl.opengl", "::drawMask" ); PreDraw(); - DrawMask( nTexture, nMaskColor, rPosAry ); + DrawMask( rTexture, nMaskColor, rPosAry ); PostDraw(); } @@ -1175,7 +1159,7 @@ SalBitmap* OpenGLSalGraphicsImpl::getBitmap( long nX, long nY, long nWidth, long SAL_INFO( "vcl.opengl", "::getBitmap " << nX << "," << nY << " " << nWidth << "x" << nHeight ); PreDraw(); - if( !pBitmap->Create( maContext, mpOffscreenTex, nX, nY, nWidth, nHeight ) ) + if( !pBitmap->Create( maContext, maOffscreenTex, nX, nY, nWidth, nHeight ) ) { delete pBitmap; pBitmap = NULL; @@ -1276,12 +1260,12 @@ bool OpenGLSalGraphicsImpl::drawAlphaBitmap( { const OpenGLSalBitmap& rBitmap = static_cast<const OpenGLSalBitmap&>(rSalBitmap); const OpenGLSalBitmap& rAlpha = static_cast<const OpenGLSalBitmap&>(rAlphaBitmap); - const GLuint nTexture( rBitmap.GetTexture( maContext ) ); - const GLuint nAlpha( rAlpha.GetTexture( maContext ) ); + OpenGLTexture& rTexture( rBitmap.GetTexture( maContext ) ); + OpenGLTexture& rAlphaTex( rAlpha.GetTexture( maContext ) ); SAL_INFO( "vcl.opengl", "::drawAlphaBitmap" ); PreDraw(); - DrawTextureWithMask( nTexture, nAlpha, rBitmap.GetSize(), rPosAry ); + DrawTextureWithMask( rTexture, rAlphaTex, rPosAry ); PostDraw(); return true; } @@ -1291,13 +1275,13 @@ bool OpenGLSalGraphicsImpl::drawAlphaBitmap( const SalBitmap& rSalBitmap ) { const OpenGLSalBitmap& rBitmap = static_cast<const OpenGLSalBitmap&>(rSalBitmap); - const GLuint nTexture( rBitmap.GetTexture( maContext ) ); + OpenGLTexture& rTexture( rBitmap.GetTexture( maContext ) ); SAL_INFO( "vcl.opengl", "::drawAlphaBitmap" ); PreDraw(); glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); - DrawTexture( nTexture, rBitmap.GetSize(), rPosAry ); + DrawTexture( rTexture, rPosAry ); glDisable( GL_BLEND ); PostDraw(); diff --git a/vcl/opengl/salbmp.cxx b/vcl/opengl/salbmp.cxx index d7e38b052b59..2e197d320bf0 100644 --- a/vcl/opengl/salbmp.cxx +++ b/vcl/opengl/salbmp.cxx @@ -37,7 +37,6 @@ static bool isValidBitCount( sal_uInt16 nBitCount ) OpenGLSalBitmap::OpenGLSalBitmap() : mpContext(NULL) -, mpTexture() , mbDirtyTexture(true) , mnBits(0) , mnBytesPerRow(0) @@ -61,7 +60,7 @@ OpenGLSalBitmap::~OpenGLSalBitmap() SAL_INFO( "vcl.opengl", "~OpenGLSalBitmap" ); } -bool OpenGLSalBitmap::Create( OpenGLContext& rContext, OpenGLTextureSharedPtr pTex, long nX, long nY, long nWidth, long nHeight ) +bool OpenGLSalBitmap::Create( OpenGLContext& rContext, const OpenGLTexture& rTex, long nX, long nY, long nWidth, long nHeight ) { static const BitmapPalette aEmptyPalette; @@ -78,13 +77,12 @@ bool OpenGLSalBitmap::Create( OpenGLContext& rContext, OpenGLTextureSharedPtr pT mnBits = 32; maPalette = aEmptyPalette; - // TODO: lfrb: Crop texture if size doesn't match the texture one - if( pTex ) - mpTexture = pTex; + if( rTex ) + maTexture = OpenGLTexture( rTex, nX, nY, nWidth, nHeight ); else - mpTexture.reset( new OpenGLTexture( nX, nY, nWidth, nHeight ) ); + maTexture = OpenGLTexture( nX, nY, nWidth, nHeight ); mbDirtyTexture = false; - SAL_INFO( "vcl.opengl", "Created texture " << mpTexture->Id() ); + SAL_INFO( "vcl.opengl", "Created texture " << maTexture.Id() ); return true; } @@ -133,7 +131,7 @@ bool OpenGLSalBitmap::Create( const SalBitmap& rSalBmp, sal_uInt16 nNewBitCount mnBufHeight = rSourceBitmap.mnBufHeight; maPalette = rSourceBitmap.maPalette; mpContext = rSourceBitmap.mpContext; - mpTexture = rSourceBitmap.mpTexture; + maTexture = rSourceBitmap.maTexture; mbDirtyTexture = false; maUserBuffer = rSourceBitmap.maUserBuffer; @@ -149,36 +147,22 @@ bool OpenGLSalBitmap::Create( const ::com::sun::star::uno::Reference< ::com::sun return false; } -bool OpenGLSalBitmap::Draw( OpenGLContext& rContext, const SalTwoRect& /*rPosAry*/ ) +OpenGLTexture& OpenGLSalBitmap::GetTexture( OpenGLContext& rContext ) const { + OpenGLSalBitmap* pThis = const_cast<OpenGLSalBitmap*>(this); if( !mpContext ) - mpContext = &rContext; - - if( !mpTexture || mbDirtyTexture ) - { - if( !CreateTexture() ) - return false; - } - - //DrawTexture( mnTexture, rPosAry ); - return true; -} - -GLuint OpenGLSalBitmap::GetTexture( OpenGLContext& rContext ) const -{ - if( !mpContext ) - const_cast<OpenGLSalBitmap*>(this)->mpContext = &rContext; - if( !mpTexture || mbDirtyTexture ) - const_cast<OpenGLSalBitmap*>(this)->CreateTexture(); - SAL_INFO( "vcl.opengl", "Got texture " << mpTexture->Id() ); - return mpTexture->Id(); + pThis->mpContext = &rContext; + if( !maTexture || mbDirtyTexture ) + pThis->CreateTexture(); + SAL_INFO( "vcl.opengl", "Got texture " << maTexture.Id() ); + return pThis->maTexture; } void OpenGLSalBitmap::Destroy() { SAL_INFO( "vcl.opengl", "Destroy OpenGLSalBitmap" ); maPendingOps.clear(); - mpTexture.reset(); + maTexture = OpenGLTexture(); maUserBuffer.reset(); } @@ -410,8 +394,8 @@ GLuint OpenGLSalBitmap::CreateTexture() } mpContext->makeCurrent(); - mpTexture.reset( new OpenGLTexture (mnBufWidth, mnBufHeight, nFormat, nType, pData ) ); - SAL_INFO( "vcl.opengl", "Created texture " << mpTexture->Id() ); + maTexture = OpenGLTexture (mnBufWidth, mnBufHeight, nFormat, nType, pData ); + SAL_INFO( "vcl.opengl", "Created texture " << maTexture.Id() ); if( bAllocated ) delete[] pData; @@ -426,12 +410,11 @@ GLuint OpenGLSalBitmap::CreateTexture() mbDirtyTexture = false; CHECK_GL_ERROR(); - return mpTexture->Id(); + return maTexture.Id(); } bool OpenGLSalBitmap::ReadTexture() { - GLuint nFramebufferId; sal_uInt8* pData = maUserBuffer.get(); GLenum nFormat = GL_RGBA; GLenum nType = GL_UNSIGNED_BYTE; @@ -459,18 +442,16 @@ bool OpenGLSalBitmap::ReadTexture() break; } } + else + { + return false; + } mpContext->makeCurrent(); - glGenFramebuffers( 1, &nFramebufferId ); - glBindFramebuffer( GL_FRAMEBUFFER, nFramebufferId ); - - glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mpTexture->Id(), 0 ); - glReadPixels( 0, 0, mnWidth, mnHeight, nFormat, nType, pData ); + maTexture.Read( nFormat, nType, pData ); + mnBufWidth = mnWidth; + mnBufHeight = mnHeight; - glBindFramebuffer( GL_FRAMEBUFFER, 0 ); - glDeleteFramebuffers( 1, &nFramebufferId ); - - CHECK_GL_ERROR(); return true; } @@ -485,7 +466,7 @@ BitmapBuffer* OpenGLSalBitmap::AcquireBuffer( bool /*bReadOnly*/ ) { if( !AllocateUserData() ) return NULL; - if( mpTexture && !ReadTexture() ) + if( maTexture && !ReadTexture() ) return NULL; } @@ -533,6 +514,7 @@ void OpenGLSalBitmap::ReleaseBuffer( BitmapBuffer* pBuffer, bool bReadOnly ) { if( !bReadOnly ) { + maTexture = OpenGLTexture(); mbDirtyTexture = true; } delete pBuffer; @@ -540,6 +522,7 @@ void OpenGLSalBitmap::ReleaseBuffer( BitmapBuffer* pBuffer, bool bReadOnly ) bool OpenGLSalBitmap::GetSystemData( BitmapSystemData& /*rData*/ ) { + SAL_WARN( "vcl.opengl", "*** NOT IMPLEMENTED *** GetSystemData" ); #if 0 // TODO Implement for ANDROID/OSX/IOS/WIN32 X11SalBitmap rBitmap; diff --git a/vcl/opengl/scale.cxx b/vcl/opengl/scale.cxx index d1b85a52d532..92fdd3f27830 100644 --- a/vcl/opengl/scale.cxx +++ b/vcl/opengl/scale.cxx @@ -86,7 +86,6 @@ bool OpenGLSalBitmap::ImplScaleFilter( const double& rScaleY, GLenum nFilter ) { - OpenGLTexture* pNewTex; GLuint nProgram; GLuint nFramebufferId; GLenum nOldFilter; @@ -102,15 +101,15 @@ bool OpenGLSalBitmap::ImplScaleFilter( glUseProgram( nProgram ); glUniform1i( mnTexSamplerUniform, 0 ); - pNewTex = new OpenGLTexture( nNewWidth, nNewHeight ); - glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pNewTex->Id(), 0 ); + OpenGLTexture aNewTex = OpenGLTexture( nNewWidth, nNewHeight ); + glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, aNewTex.Id(), 0 ); - mpTexture->Bind(); - nOldFilter = mpTexture->GetFilter(); - mpTexture->SetFilter( nFilter ); - mpTexture->Draw(); - mpTexture->SetFilter( nOldFilter ); - mpTexture->Unbind(); + maTexture.Bind(); + nOldFilter = maTexture.GetFilter(); + maTexture.SetFilter( nFilter ); + maTexture.Draw(); + maTexture.SetFilter( nOldFilter ); + maTexture.Unbind(); glUseProgram( 0 ); glBindFramebuffer( GL_FRAMEBUFFER, 0 ); @@ -118,7 +117,7 @@ bool OpenGLSalBitmap::ImplScaleFilter( mnWidth = nNewWidth; mnHeight = nNewHeight; - mpTexture.reset( pNewTex ); + maTexture = aNewTex; CHECK_GL_ERROR(); return true; @@ -167,8 +166,6 @@ bool OpenGLSalBitmap::ImplScaleConvolution( const double& rScaleY, const Kernel& aKernel ) { - OpenGLTexture* pScratchTex; - OpenGLTexture* pNewTex; GLfloat* pWeights( 0 ); GLuint nFramebufferId; GLuint nProgram; @@ -190,51 +187,59 @@ bool OpenGLSalBitmap::ImplScaleConvolution( CHECK_GL_ERROR(); // horizontal scaling in scratch texture - pScratchTex = new OpenGLTexture( nNewWidth, mnHeight ); - glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pScratchTex->Id(), 0 ); - CHECK_GL_ERROR(); - - for( sal_uInt32 i = 0; i < 16; i++ ) + if( mnWidth != nNewWidth ) { - aOffsets[i * 2] = i / (double) mnWidth; - aOffsets[i * 2 + 1] = 0; - } - ImplCreateKernel( rScaleX, aKernel, pWeights, nKernelSize ); - glUniform1fv( mnConvKernelUniform, 16, pWeights ); - CHECK_GL_ERROR(); - glUniform2fv( mnConvOffsetsUniform, 16, aOffsets ); - CHECK_GL_ERROR(); + OpenGLTexture aScratchTex = OpenGLTexture( nNewWidth, mnHeight ); + glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, aScratchTex.Id(), 0 ); + CHECK_GL_ERROR(); - glViewport( 0, 0, nNewWidth, mnHeight ); - mpTexture->Bind(); - mpTexture->Draw(); - mpTexture->Unbind(); + for( sal_uInt32 i = 0; i < 16; i++ ) + { + aOffsets[i * 2] = i / (double) mnWidth; + aOffsets[i * 2 + 1] = 0; + } + ImplCreateKernel( rScaleX, aKernel, pWeights, nKernelSize ); + glUniform1fv( mnConvKernelUniform, 16, pWeights ); + CHECK_GL_ERROR(); + glUniform2fv( mnConvOffsetsUniform, 16, aOffsets ); + CHECK_GL_ERROR(); + + glViewport( 0, 0, nNewWidth, mnHeight ); + maTexture.Bind(); + maTexture.Draw(); + maTexture.Unbind(); + + maTexture = aScratchTex; + } // vertical scaling in final texture - pNewTex = new OpenGLTexture( nNewWidth, nNewHeight ); - glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pNewTex->Id(), 0 ); - - for( sal_uInt32 i = 0; i < 16; i++ ) + if( mnHeight != nNewHeight ) { - aOffsets[i * 2] = 0; - aOffsets[i * 2 + 1] = i / (double) mnHeight; - } - ImplCreateKernel( rScaleY, aKernel, pWeights, nKernelSize ); - glUniform1fv( mnConvKernelUniform, 16, pWeights ); - glUniform2fv( mnConvOffsetsUniform, 16, aOffsets ); - CHECK_GL_ERROR(); + OpenGLTexture aScratchTex = OpenGLTexture( nNewWidth, nNewHeight ); + glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, aScratchTex.Id(), 0 ); + + for( sal_uInt32 i = 0; i < 16; i++ ) + { + aOffsets[i * 2] = 0; + aOffsets[i * 2 + 1] = i / (double) mnHeight; + } + ImplCreateKernel( rScaleY, aKernel, pWeights, nKernelSize ); + glUniform1fv( mnConvKernelUniform, 16, pWeights ); + glUniform2fv( mnConvOffsetsUniform, 16, aOffsets ); + CHECK_GL_ERROR(); - glViewport( 0, 0, nNewWidth, nNewHeight ); - pScratchTex->Bind(); - pScratchTex->Draw(); - pScratchTex->Unbind(); + glViewport( 0, 0, nNewWidth, nNewHeight ); + maTexture.Bind(); + maTexture.Draw(); + maTexture.Unbind(); + + maTexture = aScratchTex; + } glUseProgram( 0 ); glBindFramebuffer( GL_FRAMEBUFFER, 0 ); glDeleteFramebuffers( 1, &nFramebufferId ); - delete pScratchTex; - mpTexture.reset( pNewTex ); mnWidth = nNewWidth; mnHeight = nNewHeight; 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: */ diff --git a/vcl/opengl/x11/gdiimpl.cxx b/vcl/opengl/x11/gdiimpl.cxx index 3d242ac5719e..3bbb3d359344 100644 --- a/vcl/opengl/x11/gdiimpl.cxx +++ b/vcl/opengl/x11/gdiimpl.cxx @@ -15,6 +15,7 @@ #include "unx/salgdi.h" #include "unx/salvd.h" +#include "opengl/texture.hxx" #include "opengl/x11/gdiimpl.hxx" #include <vcl/opengl/OpenGLContext.hxx> @@ -125,7 +126,6 @@ bool X11OpenGLSalGraphicsImpl::RenderPixmapToScreen( X11Pixmap* pPixmap, int nX, Display* pDisplay = mrParent.GetXDisplay(); GLXFBConfig pFbConfig; GLXPixmap pGlxPixmap; - GLuint nTexture; SalTwoRect aPosAry; bool bInverted; @@ -145,21 +145,18 @@ bool X11OpenGLSalGraphicsImpl::RenderPixmapToScreen( X11Pixmap* pPixmap, int nX, PreDraw(); - glGenTextures( 1, &nTexture ); + OpenGLTexture aTexture( pPixmap->GetWidth(), pPixmap->GetHeight(), false ); glActiveTexture( GL_TEXTURE0 ); - glBindTexture( GL_TEXTURE_2D, nTexture ); + aTexture.Bind(); //TODO: lfrb: glXGetProc to get the functions glXBindTexImageEXT( pDisplay, pGlxPixmap, GLX_FRONT_LEFT_EXT, NULL ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); - - DrawTexture( nTexture, pPixmap->GetSize(), aPosAry, !bInverted ); + DrawTexture( aTexture, aPosAry, !bInverted ); glXReleaseTexImageEXT( pDisplay, pGlxPixmap, GLX_FRONT_LEFT_EXT ); - glDeleteTextures( 1, &nTexture ); glXDestroyPixmap( pDisplay, pGlxPixmap ); + aTexture.Unbind(); PostDraw(); diff --git a/vcl/win/source/gdi/winlayout.cxx b/vcl/win/source/gdi/winlayout.cxx index ca988bc512fb..0ec756645f11 100644 --- a/vcl/win/source/gdi/winlayout.cxx +++ b/vcl/win/source/gdi/winlayout.cxx @@ -204,7 +204,7 @@ void WinLayout::DrawText(SalGraphics& rGraphics) const // FIXME We don't have a method that could paint a texture with // transparency yet, use it when we have it - pImpl->DrawTexture(aTexture.Id(), Size(width, height), aRects); + pImpl->DrawTexture(aTexture, aRects); } DeleteObject(hBitmap); |