summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--vcl/inc/openglgdiimpl.hxx45
-rw-r--r--vcl/opengl/gdiimpl.cxx755
2 files changed, 763 insertions, 37 deletions
diff --git a/vcl/inc/openglgdiimpl.hxx b/vcl/inc/openglgdiimpl.hxx
index 1a3b6e746d38..2d914199e481 100644
--- a/vcl/inc/openglgdiimpl.hxx
+++ b/vcl/inc/openglgdiimpl.hxx
@@ -31,6 +31,51 @@ private:
OpenGLContext maContext;
+ SalColor mnLineColor;
+ SalColor mnFillColor;
+
+ std::vector< GLuint > maShaders;
+
+ GLuint mnSolidProgram;
+ GLuint mnColorUniform;
+
+ GLuint mnTextureProgram;
+ GLuint mnSamplerUniform;
+
+ GLuint mnMaskedTextureProgram;
+ GLuint mnMaskedSamplerUniform;
+ GLuint mnMaskSamplerUniform;
+
+ GLuint mnMaskProgram;
+ GLuint mnMaskUniform;
+ GLuint mnMaskColorUniform;
+
+ GLuint CompileShader( GLenum nType, const char *aSrc );
+ GLuint CreateProgram( const char *aVertShaderSrc, const char *aFragShaderSrc );
+ bool CreateSolidProgram( void );
+ bool CreateTextureProgram( void );
+ bool CreateMaskedTextureProgram( void );
+ bool CreateMaskProgram( void );
+
+ void BeginSolid( SalColor nColor, sal_uInt8 nTransparency );
+ void BeginSolid( SalColor nColor );
+ void EndSolid( void );
+ void BeginInvert( void );
+ void EndInvert( void );
+
+ void DrawPoint( long nX, long nY );
+ void DrawLine( long nX1, long nY1, long nX2, long nY2 );
+ void DrawLines( sal_uInt32 nPoints, const SalPoint* pPtAry, bool bClose );
+ void DrawConvexPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry );
+ void DrawRect( long nX, long nY, long nWidth, nHeight );
+ void DrawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry );
+ void DrawPolyPolygon( const basegfx::B2DPolyPolygon& pPolyPolygon );
+ void DrawTextureRect( const SalTwoRect& pPosAry );
+ void DrawTexture( GLuint nTexture, const SalTwoRect& pPosAry );
+ void DrawTextureWithMask( GLuint nTexture, GLuint nMask, const SalTwoRect& pPosAry );
+ void DrawMask( GLuint nMask, SalColor nMaskColor, const SalTwoRect& pPosAry );
+
+
public:
virtual ~OpenGLSalGraphicsImpl ();
diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx
index 8b5d8f19df8f..fc37592a34a8 100644
--- a/vcl/opengl/gdiimpl.cxx
+++ b/vcl/opengl/gdiimpl.cxx
@@ -19,17 +19,46 @@
#include "openglgdiimpl.hxx"
+#define GL_ATTRIB_POS 0
+#define GL_ATTRIB_TEX 1
+
+#define glUniformColor(nUniform, nColor, nTransparency) \
+ glUniform4f( nUniform, \
+ ((float) SALCOLOR_RED( nColor )) / 255, \
+ ((float) SALCOLOR_GREEN( nColor )) / 255, \
+ ((float) SALCOLOR_BLUE( nColor )) / 255, \
+ (100 - nTransparency) * (1.0 / 100) )
+
OpenGLSalGraphicsImpl::~OpenGLSalGraphicsImpl()
{
}
void OpenGLSalGraphicsImpl::freeResources()
{
+ // Delete shaders, programs and textures if not shared
}
-bool OpenGLSalGraphicsImpl::setClipRegion( const vcl::Region& )
+bool OpenGLSalGraphicsImpl::setClipRegion( const vcl::Region& rClip )
{
- return false;
+ const basegfx::B2DPolyPolygon aClip( rClip.GetAsB2DPolyPolygon() );
+
+ glEnable(GL_STENCIL_TEST);
+
+ glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
+ glDepthMask( GL_FALSE );
+ glStencilMask( 0xFF );
+ glStencilFunc( GL_NEVER, 1, 0xFF );
+ glStencilOp( GL_REPLACE, GL_KEEP, GL_KEEP );
+
+ glClear( GL_STENCIL_BUFFER_BIT );
+ DrawPolyPolygon( aClip );
+
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ glDepthMask( GL_TRUE );
+ glStencilMask( 0x00 );
+ glStencilFunc(GL_EQUAL, 1, 0xFF);
+
+ return true;
}
// get the depth of the device
@@ -47,28 +76,45 @@ long OpenGLSalGraphicsImpl::GetGraphicsWidth() const
// set the clip region to empty
void OpenGLSalGraphicsImpl::ResetClipRegion()
{
+ glDisable(GL_STENCIL_TEST);
}
// set the line color to transparent (= don't draw lines)
void OpenGLSalGraphicsImpl::SetLineColor()
{
+ if( mnLineColor != SALCOLOR_NONE )
+ {
+ mnLineColor = SALCOLOR_NONE;
+ }
}
// set the line color to a specific color
-void OpenGLSalGraphicsImpl::SetLineColor( SalColor /*nSalColor*/ )
+void OpenGLSalGraphicsImpl::SetLineColor( SalColor nSalColor )
{
+ if( mnLineColor != nSalColor )
+ {
+ mnLineColor = nSalColor;
+ }
}
// set the fill color to transparent (= don't fill)
void OpenGLSalGraphicsImpl::SetFillColor()
{
+ if( mnFillColor != SALCOLOR_NONE )
+ {
+ mnFillColor = SALCOLOR_NONE;
+ }
}
// set the fill color to a specific color, shapes will be
// filled accordingly
-void OpenGLSalGraphicsImpl::SetFillColor( SalColor /*nSalColor*/ )
+void OpenGLSalGraphicsImpl::SetFillColor( SalColor nSalColor )
{
+ if( mnFillColor != nSalColor )
+ {
+ mnFillColor = nSalColor;
+ }
}
// enable/disable XOR drawing
@@ -86,34 +132,575 @@ void OpenGLSalGraphicsImpl::SetROPFillColor( SalROPColor /*nROPColor*/ )
{
}
-// draw --> LineColor and FillColor and RasterOp and ClipRegion
-void OpenGLSalGraphicsImpl::drawPixel( long /*nX*/, long /*nY*/ )
+GLuint OpenGLSalGraphicsImpl::CompileShader( GLenum nType, const char *aSrc )
+{
+ GLint nStatus;
+ GLuint nShader;
+ GLint nLogLen( 0 );
+ char *aLog( NULL );
+
+ nShader = glCreateShader( nType );
+ glShaderSource( nShader, 1, (const GLchar **) &aSrc, NULL );
+ glCompileShader( nShader );
+ glGetShaderiv( nShader, GL_COMPILE_STATUS, &nStatus );
+ if( nStatus )
+ return nShader;
+
+ glGetShaderiv( nShader, GL_INFO_LOG_LENGTH, &nLogLen );
+ if( nLogLen > 1 )
+ aLog = malloc( nLogLen );
+ if( aLog )
+ glGetShaderInfoLog( nShader, nLogLen, NULL, aLog );
+
+ OSL_FAIL( "::CompileShader failed: %s", aLog );
+
+ free( aLog );
+ glDeleteShader( nShader );
+
+ return 0;
+}
+
+GLuint OpenGLSalGraphicsImpl::CreateProgram( const char *aVertShaderSrc, const char *aFragShaderSrc )
+{
+ GLuint nProgram;
+ GLuint nVertShader, nFragShader;
+ GLint nStatus;
+
+ nVertShader = CompileShader( GL_VERTEX_SHADER, aVertShaderSrc );
+ nFragShader = CompileShader( GL_FRAGMENT_SHADER, aFragShaderSrc );
+ if( !nVertShader || !nFragShader )
+ {
+ OSL_FAIL( "::CreateProgram couldn't compile the shaders" );
+ return 0;
+ }
+
+ nProgram = glCreateProgram();
+ if( nProgram == 0 )
+ {
+ OSL_FAIL( "::CreateProgram couldn't create GL program" );
+ return 0;
+ }
+
+ glAttachShader( nProgram, nVertShader );
+ glAttachShader( nProgram, nFragShader );
+ glLinkProgram( nProgram );
+ glGetProgramiv( nProgram, GL_LINK_STATUS, &nStatus );
+ if( !nStatus )
+ {
+ GLint nLogLen( 0 );
+ char *log( NULL );
+
+ glDeleteShader( nVertShader );
+ glDeleteShader( nFragShader );
+
+ glGetProgramiv( nProgram, GL_INFO_LOG_LENGTH, &nLogLen );
+ if( nLogLen > 0 )
+ aLog = malloc( nLogLen );
+ if( aLog )
+ glGetProgramInfoLog( nProgram, nLogLen, NULL, aLog );
+
+ OSL_FAIL( "::CreateSolidShader couldn't link program: %s", aLog );
+ free( aLog );
+
+ return 0;
+ }
+
+ maShaders.push_back( nVertShader );
+ maShaders.push_back( nFragShader );
+ return nProgram;
+}
+
+bool OpenGLSalGraphicsImpl::CreateSolidProgram( void )
+{
+ static const char aVertShaderSrc[] =
+ "attribute vec4 position;\n"
+ "void main() {\n"
+ " gl_Position = position;\n"
+ "}\n";
+ static const char aFragShaderSrc[] =
+ "precision mediump float;\n"
+ "uniform vec4 color;\n"
+ "void main() {\n"
+ " gl_FragColor = color;\n"
+ "}\n";
+
+ mnSolidProgram = CreateProgram( aVertShaderSrc, aFragShaderSrc );
+ if( mnSolidProgram == 0 )
+ return false;
+
+ glBindAttribLocation( mnSolidProgram, GL_ATTRIB_POS, "position" );
+ mnColorUniform = glGetUniformLocation( mnSolidProgram, "color" );
+ return true;
+}
+
+bool OpenGLSalGraphicsImpl::CreateTextureProgram( void )
+{
+ static const char aVertShaderSrc[] =
+ "attribute vec4 position;\n"
+ "attribute vec2 tex_coord_in;\n"
+ "varying vec2 tex_coord;\n"
+ "void main() {\n"
+ " gl_Position = position;\n"
+ " tex_coord = tex_coord_in;\n"
+ "}\n";
+ static const char aFragShaderSrc[] =
+ "precision mediump float;\n"
+ "varying vec2 tex_coord;\n"
+ "uniform sampler2D sampler;\n"
+ "void main() {\n"
+ " gl_FragColor = texture2D(sampler, tex_coord);\n"
+ "}\n";
+
+ mnTextureProgram = CreateProgram( aVertShaderSrc, aFragShaderSrc );
+ if( mnTextureProgram == 0 )
+ return false;
+
+ glBindAttribLocation( mnTextureProgram, GL_ATTRIB_POS, "position" );
+ glBindAttribLocation( mnTextureProgram, GL_ATTRIB_TEX, "tex_coord_in" );
+ mnSamplerUniform = glGetUniformLocation( mnTextureProgram, "sampler" );
+ return true;
+}
+
+bool OpenGLSalGraphicsImpl::CreateMaskedTextureProgram( void )
+{
+ static const char aVertShaderSrc[] =
+ "attribute vec4 position;\n"
+ "attribute vec2 tex_coord_in;\n"
+ "varying vec2 tex_coord;\n"
+ "void main() {\n"
+ " gl_Position = position;\n"
+ " tex_coord = tex_coord_in;\n"
+ "}\n";
+ static const char aFragShaderSrc[] =
+ "precision mediump float;\n"
+ "varying vec2 tex_coord;\n"
+ "uniform sampler2D sampler;\n"
+ "uniform sampler2D mask;\n"
+ "void main() {\n"
+ " vec4 texel0, texel1;\n"
+ " texel0 = texture2D(sampler, tex_coord);\n"
+ " texel1 = texture2D(mask, tex_coord);\n"
+ " gl_FragColor = texel0 * texel1.a;\n"
+ "}\n";
+
+ mnMaskedTextureProgram = CreateProgram( aVertShaderSrc, aFragShaderSrc );
+ if( mnMaskedTextureProgram == 0 )
+ return false;
+
+ glBindAttribLocation( mnTextureProgram, GL_ATTRIB_POS, "position" );
+ glBindAttribLocation( mnTextureProgram, GL_ATTRIB_TEX, "tex_coord_in" );
+ mnMaskedSamplerUniform = glGetUniformLocation( mnMaskedTextureProgram, "sampler" );
+ mnMaskSamplerUniform = glGetUniformLocation( mnMaskedTextureProgram, "mask" );
+ return true;
+}
+
+bool OpenGLSalGraphicsImpl::CreateMaskProgram( void )
+{
+ static const char aVertShaderSrc[] =
+ "attribute vec4 position;\n"
+ "attribute vec2 tex_coord_in;\n"
+ "varying vec2 tex_coord;\n"
+ "void main() {\n"
+ " gl_Position = position;\n"
+ " tex_coord = tex_coord_in;\n"
+ "}\n";
+ static const char aFragShaderSrc[] =
+ "precision mediump float;\n"
+ "varying vec2 tex_coord;\n"
+ "uniform sampler2D sampler;\n"
+ "uniform vec4 color;
+ "void main() {\n"
+ " vec4 texel0;\n"
+ " texel0 = texture2D(sampler, tex_coord);\n"
+ " gl_FragColor = color * texel0.a;\n"
+ "}\n";
+
+ mnMaskedTextureProgram = CreateProgram( aVertShaderSrc, aFragShaderSrc );
+ if( mnMaskedTextureProgram == 0 )
+ return false;
+
+ glBindAttribLocation( mnTextureProgram, GL_ATTRIB_POS, "position" );
+ glBindAttribLocation( mnTextureProgram, GL_ATTRIB_TEX, "tex_coord_in" );
+ mnMaskUniform = glGetUniformLocation( mnMaskProgram, "sampler" );
+ mnMaskColorUniform = glGetUniformLocation( mnMaskProgram, "mask" );
+ return true;
+}
+
+void OpenGLSalGraphicsImpl::BeginSolid( SalColor nColor, sal_uInt8 nTransparency )
+{
+ if( mnSolidProgram == 0 )
+ {
+ if( !CreateSolidProgram() )
+ return;
+ }
+
+ glUseProgram( mnSolidProgram );
+ glUniformColor( mnColorUniform, nColor, nTransparency );
+}
+
+void OpenGLSalGraphicsImpl::BeginSolid( SalColor nColor )
{
+ BeginSolid( nColor, 0 );
}
-void OpenGLSalGraphicsImpl::drawPixel( long /*nX*/, long /*nY*/, SalColor /*nSalColor*/ )
+void OpenGLSalGraphicsImpl::EndSolid( void )
{
+ glUseProgram( 0 );
}
-void OpenGLSalGraphicsImpl::drawLine( long /*nX1*/, long /*nY1*/, long /*nX2*/, long /*nY2*/ )
+void OpenGLSalGraphicsImpl::BeginInvert( void )
{
+ glEnable( GL_BLEND );
+ glBlendFunc( GL_ONE_MINUS_DST_COLOR, GL_ZERO );
+ BeginSolid( MAKE_SALCOLOR( 255, 255, 255 ) );
}
-void OpenGLSalGraphicsImpl::drawRect( long /*nX*/, long /*nY*/, long /*nWidth*/, long /*nHeight*/ )
+void OpenGLSalGraphicsImpl::EndInvert( void )
{
+ EndSolid();
+ glDisable( GL_BLEND );
}
-void OpenGLSalGraphicsImpl::drawPolyLine( sal_uInt32 /*nPoints*/, const SalPoint* /*pPtAry*/ )
+void OpenGLSalGraphicsImpl::DrawPoint( long nX, long nY )
{
+ GLushort pPoint[2];
+
+ pPoint[0] = nX;
+ pPoint[1] = nY;
+
+ glEnableVertexAttribArray( GL_ATTRIB_POS );
+ glVertexAttribPointer( GL_ATTRIB_POS, 2, GL_UNSIGNED_SHORT, GL_FALSE, 0, pPoint );
+ glDrawArrays( GL_POINTS, 0, 1 );
+ glDisableVertexAttribArray( GL_ATTRIB_POS );
}
-void OpenGLSalGraphicsImpl::drawPolygon( sal_uInt32 /*nPoints*/, const SalPoint* /*pPtAry*/ )
+void OpenGLSalGraphicsImpl::DrawLine( long nX1, long nY1, long nX2, long nY2 )
{
+ GLushort pPoints[4];
+
+ pPoints[0] = nX1;
+ pPoints[1] = nY1;
+ pPoints[2] = nY2;
+ pPoints[3] = nY2;
+
+ glEnableVertexAttribArray( GL_ATTRIB_POS );
+ glVertexAttribPointer( GL_ATTRIB_POS, 4, GL_UNSIGNED_SHORT, GL_FALSE, 0, pPoints );
+ glDrawArrays( GL_LINES, 0, 2 );
+ glDisableVertexAttribArray( GL_ATTRIB_POS );
}
-void OpenGLSalGraphicsImpl::drawPolyPolygon( sal_uInt32 /*nPoly*/, const sal_uInt32* /*pPoints*/, PCONSTSALPOINT* /*pPtAry*/ )
+void OpenGLSalGraphicsImpl::DrawLines( sal_uInt32 nPoints, const SalPoint* pPtAry, bool bClose )
{
+ GLushort *pPoints;
+ sal_uInt32 i, j;
+
+ pPoints = new GLushort[nPoints * 2];
+ for( i = 0, j = 0; i < nPoints; i++, j += 2 )
+ {
+ pPoints[j] = pPtAry[i].x;
+ pPoints[j+1] = pPtAry[i].y;
+ }
+
+ glEnableVertexAttribArray( GL_ATTRIB_POS );
+ glVertexAttribPointer( GL_ATTRIB_POS, nPoints * 2, GL_UNSIGNED_SHORT, GL_FALSE, 0, pPoints );
+ if( bClose )
+ glDrawArrays( GL_LINE_LOOP, 0, nPoints );
+ else
+ glDrawArrays( GL_LINE_STRIP, 0, nPoints );
+ glDisableVertexAttribArray( GL_ATTRIB_POS );
}
+
+void OpenGLSalGraphicsImpl::DrawConvexPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry )
+{
+ GLushort pVertices[nPoints * 2];
+
+ for( i = 0, j = 0; i < nPoints; i++, j += 2 )
+ {
+ pVertices[j] = pPtAry[i].x;
+ pVertices[j+1] = pPtAry[i].y;
+ }
+
+ glEnableVertexAttribArray( GL_ATTRIB_POS );
+ glVertexAttribPointer( GL_ATTRIB_POS, nPoints * 2, GL_UNSIGNED_SHORT, GL_FALSE, 0, pVertices );
+ glDrawArrays( GL_TRIANGLE_FAN, 0, nPoints );
+ glDisableVertexAttribArray( GL_ATTRIB_POS );
+}
+
+void OpenGLSalGraphicsImpl::DrawRect( long nX, long nY, long nWidth, nHeight )
+{
+ long nX1( nX );
+ long nY1( nY );
+ long nX2( nX + nWidth - 1 );
+ long nY2( nY + nHeight - 1 );
+ const SalPoint aPoints[] = { { nX1, nY2 }, { nX1, nY1 },
+ { nX2, nY1 }, { nX2, nY2 }};
+
+ DrawConvexPolygon( 4, aPoints );
+}
+
+void OpenGLSalGraphicsImpl::DrawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry )
+{
+ ::basegfx::B2DPolygon aPolygon;
+ sal_uInt32 i, j;
+
+ for( i = 0; i < nPoints; i++ )
+ aPolygon.append( ::basegfx::B2DPoint( pPtAry[i].x, pPtAry[i].y ) );
+ aPolygon.setClosed( true );
+
+ if( aPolygon.isConvex() )
+ {
+ if( nPoints > 2L )
+ {
+ DrawConvexPolygon( nPoints, pPtAry );
+ }
+ }
+ else
+ {
+ const ::basegfx::B2DPolygon& aResult(
+ ::basegfx::triangulator::triangulate( aPolygon ) );
+ GLushort pVertices[aResult.count() * 2];
+ sal_uInt32 j( 0 );
+
+ for( sal_uInt32 i = 0; i < aResult.count(); i++ )
+ {
+ const ::basegfx::B2DPoint& rPt( aResult.getB2DPoint(i) );
+ pVertices[j++] = rPt.getX();
+ pVertices[j++] = rPt.getY();
+ }
+
+ glEnableVertexAttribArray( GL_ATTRIB_POS );
+ glVertexAttribPointer( GL_ATTRIB_POS, aResult.count() * 2, GL_UNSIGNED_SHORT, GL_FALSE, 0, pVertices );
+ glDrawArrays( GL_TRIANGLES, 0, aResult.count() );
+ glDisableVertexAttribArray( GL_ATTRIB_POS );
+ }
+}
+
+void OpenGLSalGraphicsImpl::DrawPolyPolygon( const basegfx::B2DPolyPolygon& pPolyPolygon )
+{
+ sal_uInt32 i, j;
+ ::std::vector< GLushort > pVertices;
+
+ for( i = 0; i < pPolyPolygon.count(); i++ )
+ {
+ const basegfx::B2DPolygon& pPolygon( pPolyPolygon.getB2DPolygon( i ) );
+ const ::basegfx::B2DPolygon& aResult(
+ ::basegfx::triangulator::triangulate( aPolygon ) );
+
+ for( j = 0; i < aResult.count(); j++ )
+ {
+ const ::basegfx::B2DPoint& rPt( aResult.getB2DPoint(i) );
+ pVertices.push_back( rPt.getX() );
+ pVertices.push_back( rPt.getY() );
+ }
+ }
+
+ glEnableVertexAttribArray( GL_ATTRIB_POS );
+ glVertexAttribPointer( GL_ATTRIB_POS, pVertices.count(), GL_UNSIGNED_SHORT, GL_FALSE, 0, pVertices.size() );
+ glDrawArrays( GL_TRIANGLES, 0, pVertices.size() / 2 );
+ glDisableVertexAttribArray( GL_ATTRIB_POS );
+}
+
+void OpenGLSalGraphicsImpl::DrawTextureRect( const SalTwoRect& pPosAry )
+{
+ GLushort aTexCoord[8];
+
+ glEnableVertexAttribArray( GL_ATTRIB_TEX );
+ glVertexAttribPointer( GL_ATTRIB_TEX, 8, GL_UNSIGNED_SHORT, GL_FALSE, 0, aTexCoord );
+
+ DrawRect( pPosAry.mnDestX, pPosAry.mnDestY, pPosAry.mnDestWidth, pPosAry.mnDestHeight );
+
+ glDisableVertexAttribArray( GL_ATTRIB_TEX );
+}
+
+void OpenGLSalGraphicsImpl::DrawTexture( GLuint nTexture, const SalTwoRect& pPosAry )
+{
+ if( mnTextureProgram == 0 )
+ {
+ if( !CreateTextureProgram() )
+ return;
+ }
+
+ glUseProgram( mnTextureProgram );
+ glUniform1i( mnSamplerUniform, 0 );
+ glActiveTexture( GL_TEXTURE0 );
+ glBindTexture( GL_TEXTURE_2D, nTexture );
+
+ DrawTextureRect( pPosAry );
+
+ glBindTexture( GL_TEXTURE_2D, 0 );
+ glUseProgram( 0 );
+}
+
+void OpenGLSalGraphicsImpl::DrawTextureWithMask( GLuint nTexture, GLuint nMask, const SalTwoRect& pPosAry )
+{
+ if( mnMaskedTextureProgram == 0 )
+ {
+ if( !CreateMaskedTextureProgram() )
+ return;
+ }
+
+ glUseProgram( mnMaskedTextureProgram );
+ glUniform1i( mnMaskedSamplerUniform, 0 );
+ glUniform1i( mnMaskSamplerUniform, 1 );
+ glActiveTexture( GL_TEXTURE0 );
+ glBindTexture( GL_TEXTURE_2D, nTexture );
+ glActiveTexture( GL_TEXTURE1 );
+ glBindTexture( GL_TEXTURE_2D, nMask );
+
+ DrawTextureRect( pPosAry );
+
+ glActiveTexture( GL_TEXTURE1 );
+ glBindTexture( GL_TEXTURE_2D, 0 );
+ glActiveTexture( GL_TEXTURE0 );
+ glBindTexture( GL_TEXTURE_2D, 0 );
+ glUseProgram( 0 );
+}
+
+void OpenGLSalGraphicsImpl::DrawMask( GLuint nMask, SalColor nMaskColor, const SalTwoRect& pPosAry )
+{
+ if( mnMaskProgram == 0 )
+ {
+ if( !CreateMaskProgram() )
+ return;
+ }
+
+ glUseProgram( mnMaskProgram );
+ glUniformColor( mnMaskColorUniform, nMaskColor, 0 );
+ glUniform1i( mnMaskUniform, 0 );
+ glActiveTexture( GL_TEXTURE0 );
+ glBindTexture( GL_TEXTURE_2D, nMask );
+
+ DrawTextureRect( pPosAry );
+
+ glActiveTexture( GL_TEXTURE0 );
+ glBindTexture( GL_TEXTURE_2D, 0 );
+ glUseProgram( 0 );
+}
+
+
+// draw --> LineColor and FillColor and RasterOp and ClipRegion
+void OpenGLSalGraphicsImpl::drawPixel( long nX, long nY )
+{
+ if( mnLineColor != SALCOLOR_NONE )
+ {
+ BeginSolid( mnLineColor );
+ DrawPoint( nX, nY );
+ EndSolid();
+ }
+}
+
+void OpenGLSalGraphicsImpl::drawPixel( long nX, long nY, SalColor nSalColor )
+{
+ if( nSalColor != SALCOLOR_NONE )
+ {
+ BeginSolid( nSalColor );
+ DrawPoint( nX, nY );
+ EndSolid();
+ }
+}
+
+void OpenGLSalGraphicsImpl::drawLine( long nX1, long nY1, long nX2, long nY2 )
+{
+ if( mnLineColor != SALCOLOR_NONE )
+ {
+ BeginSolid( mnLineColor );
+ DrawLine( nX1, nY1, nX2, nY2 );
+ EndSolid();
+ }
+}
+
+void OpenGLSalGraphicsImpl::drawRect( long nX, long nY, long nWidth, long nHeight )
+{
+ if( mnFillColor != SALCOLOR_NONE )
+ {
+ BeginSolid( mnFillColor );
+ DrawRect( nX, nY, nWidth, nHeight );
+ EndSolid();
+ }
+
+ if( mnLineColor != SALCOLOR_NONE )
+ {
+ const long nX1( nX );
+ const long nY1( nY );
+ const long nX2( nX + nWidth - 1 );
+ const long nY2( nY + nHeight - 1 );
+ const SalPoint aPoints[] = { { nX1, nY1 }, { nX2, nY1 },
+ { nX2, nY2 }, { nX1, nY2 } };
+
+ BeginSolid( mnLineColor );
+ DrawLines( 4, aPoints, true );
+ EndSolid();
+ }
+}
+
+void OpenGLSalGraphicsImpl::drawPolyLine( sal_uInt32 nPoints, const SalPoint* pPtAry )
+{
+ if( mnLineColor != SALCOLOR_NONE && nPoints > 1 )
+ {
+ SalPolyLine Points( nPoints, pPtAry );
+
+ BeginSolid( mnLineColor );
+ DrawLines( nPoints, Points, false );
+ EndSolid();
+ }
+}
+
+void OpenGLSalGraphicsImpl::drawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry )
+{
+ if( nPoints == 0 )
+ return;
+ if( nPoints == 1 )
+ {
+ drawPixel( pPtAry[0].mnX, pPtAry[0].mnY );
+ return;
+ }
+ if( nPoints == 2 )
+ {
+ drawLine( pPtAry[0].mnX, pPtAry[0].mnY,
+ pPtAry[1].mnX, pPtAry[1].mnY );
+ return;
+ }
+
+ if( mnFillColor != SALCOLOR_NONE )
+ {
+ BeginSolid( mnFillColor );
+ DrawPolygon( nPoints, pPtAry );
+ EndSolid();
+ }
+
+ if( mnLineColor != SALCOLOR_NONE )
+ {
+ SalPolyLine Points( nPoints, pPtAry );
+
+ BeginSolid( mnLineColor );
+ DrawLines( nPoints, Points, true );
+ EndSolid();
+ }
+}
+
+void OpenGLSalGraphicsImpl::drawPolyPolygon( sal_uInt32 nPoly, const sal_uInt32* pPoints, PCONSTSALPOINT* pPtAry )
+{
+ if( nPoly <= 0 )
+ return;
+
+ if( mnFillColor != SALCOLOR_NONE )
+ {
+ BeginSolid( mnFillColor );
+ for( i = 0; i < nPoly; i++ )
+ DrawPolygon( nPoints[i], pPtAry[i] );
+ EndSolid();
+ }
+
+ if( mnLineColor != SALCOLOR_NONE )
+ {
+ // TODO Use glMultiDrawElements or primitive restart
+ BeginSolid( mnLineColor );
+ for( i = 0; i < nPoly; i++ )
+ DrawLines( nPoints[i], pPtAry[i], true );
+ EndSolid();
+ }
+}
+
bool OpenGLSalGraphicsImpl::drawPolyPolygon( const ::basegfx::B2DPolyPolygon&, double /*fTransparency*/ )
{
return false;
@@ -165,12 +752,34 @@ void OpenGLSalGraphicsImpl::copyArea(
// CopyBits and DrawBitmap --> RasterOp and ClipRegion
// CopyBits() --> pSrcGraphics == NULL, then CopyBits on same Graphics
-void OpenGLSalGraphicsImpl::copyBits( const SalTwoRect& /*rPosAry*/, SalGraphics* /*pSrcGraphics*/ )
+void OpenGLSalGraphicsImpl::copyBits( const SalTwoRect& rPosAry, SalGraphics* pSrcGraphics )
{
+ // TODO Check if SalGraphicsImpl is the same
+ const bool bSameGraphics( false );
+
+ if( bSameGraphics &&
+ (rPosAry.mnSrcWidth == rPosAry.mnDestWidth) &&
+ (rPosAry.mnSrcHeight == rPosAry.mnDestHeight))
+ {
+ // short circuit if there is nothing to do
+ if( (rPosAry.mnSrcX == rPosAry.mnDestX) &&
+ (rPosAry.mnSrcY == rPosAry.mnDestY))
+ return;
+ // use copyArea() if source and destination context are identical
+ copyArea( rPosAry.mnDestX, rPosAry.mnDestY, rPosAry.mnSrcX, rPosAry.mnSrcY,
+ rPosAry.mnSrcWidth, rPosAry.mnSrcHeight, 0 );
+ return;
+ }
+
+ // TODO Copy from one FBO to the other (glBlitFramebuffer)
}
-void OpenGLSalGraphicsImpl::drawBitmap( const SalTwoRect& /*rPosAry*/, const SalBitmap& /*rSalBitmap*/ )
+void OpenGLSalGraphicsImpl::drawBitmap( const SalTwoRect& rPosAry, const SalBitmap& rSalBitmap )
{
+ const OpenGLSalBitmap& rBitmap = static_cast<const OpenGLSalBitmap&>(rSalBitmap);
+ GLuint nTexture = rBitmap.GetTexture();
+
+ DrawTexture( nTexture, rPosAry );
}
void OpenGLSalGraphicsImpl::drawBitmap(
@@ -178,42 +787,101 @@ void OpenGLSalGraphicsImpl::drawBitmap(
const SalBitmap& /*rSalBitmap*/,
SalColor /*nTransparentColor*/ )
{
+ OSL_FAIL( "::DrawBitmap with transparent color not supported" );
}
void OpenGLSalGraphicsImpl::drawBitmap(
- const SalTwoRect& /*rPosAry*/,
- const SalBitmap& /*rSalBitmap*/,
- const SalBitmap& /*rMaskBitmap*/ )
+ const SalTwoRect& rPosAry,
+ const SalBitmap& rSalBitmap,
+ const SalBitmap& rMaskBitmap )
{
+ const OpenGLSalBitmap& rBitmap = static_cast<const OpenGLSalBitmap&>(rSalBitmap);
+ const OpenGLSalBitmap& rMask = static_cast<const OpenGLSalBitmap&>(rMaskBitmap);
+ const GLuint nTexture( rBitmap.GetTexture() );
+ const GLuint nMask( rMask.GetTexture() );
+
+ DrawTextureWithMask( nTexture, nMask, rPosAry );
}
void OpenGLSalGraphicsImpl::drawMask(
- const SalTwoRect& /*rPosAry*/,
- const SalBitmap& /*rSalBitmap*/,
- SalColor /*nMaskColor*/ )
+ const SalTwoRect& rPosAry,
+ const SalBitmap& rSalBitmap,
+ SalColor nMaskColor )
{
+ const OpenGLSalBitmap& rBitmap = static_cast<const OpenGLSalBitmap&>(rSalBitmap);
+ const GLuint nTexture( rBitmap.GetTexture() );
+
+ DrawMask( nTexture, nMaskColor, rPosAry );
}
-SalBitmap* OpenGLSalGraphicsImpl::getBitmap( long /*nX*/, long /*nY*/, long /*nWidth*/, long /*nHeight*/ )
+SalBitmap* OpenGLSalGraphicsImpl::getBitmap( long nX, long nY, long nWidth, long nHeight )
{
- return NULL;
+ GLuint nTexture;
+
+ /*glGenTexture( 1, &nTexture );
+ glBindTexture( GL_TEXTURE_2D, nTexture );
+ glCopyTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, nX, nY, nWidth, nHeight, 0 );
+ glBindTexture( GL_TEXTURE_2D, 0 );*/
+
+ OpenGLSalBitmap* pBitmap = new OpenGLSalBitmap;
+ if( !pBitmap->Create( nX, nY, nWidth, nHeight ) )
+ {
+ delete pBitmap;
+ pBitmap = NULL;
+ }
+ return pBitmap;
}
-SalColor OpenGLSalGraphicsImpl::getPixel( long /*nX*/, long /*nY*/ )
+SalColor OpenGLSalGraphicsImpl::getPixel( long nX, long nY )
{
- return 0;
+ char pixel[3];
+
+ glReadPixels( nX, nY, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, pixel);
+ return MAKE_SALCOLOR( pixel[0], pixel[1], pixel[2] );
}
// invert --> ClipRegion (only Windows or VirDevs)
void OpenGLSalGraphicsImpl::invert(
- long /*nX*/, long /*nY*/,
- long /*nWidth*/, long /*nHeight*/,
- SalInvert /*nFlags*/)
+ long nX, long nY,
+ long nWidth, long nHeight,
+ SalInvert nFlags)
{
+ // TODO Figure out what are those:
+ // * SAL_INVERT_50 (50/50 pattern?)
+ // * SAL_INVERT_TRACKFRAME (dash-line rectangle?)
+
+ if( nFlags & SAL_INVERT_TRACKFRAME )
+ {
+
+ }
+ else if( nFlags & SAL_INVERT_50 )
+ {
+
+ }
+ else // just invert
+ {
+ BeginInvert();
+ DrawPolygon( 4, aPoints );
+ EndInvert();
+ }
}
-void OpenGLSalGraphicsImpl::invert( sal_uInt32 /*nPoints*/, const SalPoint* /*pPtAry*/, SalInvert /*nFlags*/ )
+void OpenGLSalGraphicsImpl::invert( sal_uInt32 nPoints, const SalPoint* pPtAry, SalInvert nFlags )
{
+ if( nFlags & SAL_INVERT_TRACKFRAME )
+ {
+
+ }
+ else if( nFlags & SAL_INVERT_50 )
+ {
+
+ }
+ else // just invert
+ {
+ BeginInvert();
+ DrawPolygon( nPoints, pPtAry );
+ EndInvert();
+ }
}
bool OpenGLSalGraphicsImpl::drawEPS(
@@ -238,11 +906,17 @@ bool OpenGLSalGraphicsImpl::drawEPS(
compositing themselves
*/
bool OpenGLSalGraphicsImpl::drawAlphaBitmap(
- const SalTwoRect&,
- const SalBitmap& /*rSourceBitmap*/,
- const SalBitmap& /*rAlphaBitmap*/ )
+ const SalTwoRect& rPosAry,
+ const SalBitmap& rSalBitmap,
+ const SalBitmap& rAlphaBitmap )
{
- return false;
+ const OpenGLSalBitmap& rBitmap = static_cast<const OpenGLSalBitmap&>(rSalBitmap);
+ const OpenGLSalBitmap& rAlpha = static_cast<const OpenGLSalBitmap&>(rAlphaBitmap);
+ const GLuint nTexture( rBitmap.GetTexture() );
+ const GLuint nAlpha( rAlpha.GetTexture() );
+
+ DrawTextureWithMask( nTexture, nAlpha, rPosAry );
+ return true;
}
/** draw transformed bitmap (maybe with alpha) where Null, X, Y define the coordinate system */
@@ -263,11 +937,18 @@ bool OpenGLSalGraphicsImpl::drawTransformedBitmap(
fully transparent rectangle
*/
bool OpenGLSalGraphicsImpl::drawAlphaRect(
- long /*nX*/, long /*nY*/,
- long /*nWidth*/, long /*nHeight*/,
- sal_uInt8 /*nTransparency*/ )
-{
- return false;
+ long nX, long nY,
+ long nWidth, long nHeight,
+ sal_uInt8 nTransparency )
+{
+ if( mnFillColor != SALCOLOR_NONE && nTransparency < 100 )
+ {
+ BeginSolid( mnFillColor, nTransparency );
+ DrawRect( nX, nY, nWidth, nHeight );
+ EndSolid();
+ }
+
+ return true;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */