diff options
-rw-r--r-- | vcl/inc/openglgdiimpl.hxx | 45 | ||||
-rw-r--r-- | vcl/opengl/gdiimpl.cxx | 755 |
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: */ |