opengl: batch drawing of pixel, line, rect draw calls
Change-Id: Ib1619fa476f488c5315411b1ad4d1b7464c70c69
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index 83383ff..06e3153 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -621,6 +621,7 @@ else
vcl/opengl/texture \
vcl/opengl/FixedTextureAtlas \
vcl/opengl/PackedTextureAtlas \
vcl/opengl/RenderList \
vcl/source/opengl/OpenGLContext \
vcl/source/opengl/OpenGLHelper \
vcl/source/window/openglwin \
diff --git a/vcl/inc/opengl/RenderList.hxx b/vcl/inc/opengl/RenderList.hxx
new file mode 100644
index 0000000..0ba977a
--- /dev/null
+++ b/vcl/inc/opengl/RenderList.hxx
@@ -0,0 +1,98 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
*/
#ifndef INCLUDED_VCL_INC_OPENGL_RENDERLIST_H
#define INCLUDED_VCL_INC_OPENGL_RENDERLIST_H
#include <glm/glm.hpp>
#include <vcl/opengl/OpenGLHelper.hxx>
#include <vcl/salgtype.hxx>
#include <basegfx/range/b2drange.hxx>
struct RenderParameters
{
std::vector<GLfloat> maVertices;
std::vector<GLfloat> maExtrusionVectors;
std::vector<glm::vec4> maColors;
};
struct RenderEntry
{
RenderParameters maTriangleParameters;
RenderParameters maLineParameters;
RenderParameters maLineAAParameters;
bool hasTriangles()
{
return !maTriangleParameters.maVertices.empty();
}
bool hasLines()
{
return !maLineParameters.maVertices.empty();
}
bool hasLinesAA()
{
return !maLineAAParameters.maVertices.empty();
}
};
class RenderList
{
private:
basegfx::B2DRange maOverlapTrackingRectangle;
std::vector<RenderEntry> maRenderEntries;
void checkOverlapping(const basegfx::B2DRange& rDrawRectangle)
{
if (maRenderEntries.empty() || maOverlapTrackingRectangle.overlaps(rDrawRectangle))
{
maRenderEntries.resize(maRenderEntries.size() + 1);
maOverlapTrackingRectangle = rDrawRectangle;
}
else
{
maOverlapTrackingRectangle.expand(rDrawRectangle);
}
}
public:
RenderList() = default;
bool empty()
{
return maRenderEntries.empty();
}
void clear()
{
maRenderEntries.clear();
maOverlapTrackingRectangle.reset();
}
std::vector<RenderEntry>& getEntries()
{
return maRenderEntries;
}
void addDrawPixel(long nX, long nY, const SalColor& rColor);
void addDrawRectangle(long nX, long nY, long nWidth, long nHeight,
const SalColor& rLineColor, const SalColor& rFillColor);
void addDrawLine(long nX1, long nY1, long nX2, long nY2, const SalColor& rLineColor, bool bUseAA);
};
#endif // INCLUDED_VCL_INC_OPENGL_RENDERLIST_H
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/opengl/VertexUtils.hxx b/vcl/inc/opengl/VertexUtils.hxx
index becc62b..c64340b 100644
--- a/vcl/inc/opengl/VertexUtils.hxx
+++ b/vcl/inc/opengl/VertexUtils.hxx
@@ -39,6 +39,44 @@ inline void addRectangle<GL_TRIANGLE_FAN>(std::vector<GLfloat>& rVertices, GLflo
});
}
inline glm::vec4 createGLColor(const SalColor& rColor, GLfloat rTransparency)
{
return glm::vec4(SALCOLOR_RED(rColor) / 255.0f,
SALCOLOR_GREEN(rColor) / 255.0f,
SALCOLOR_BLUE(rColor) / 255.0f,
1.0f - rTransparency);
}
template<GLenum TYPE>
inline void addQuadColors(std::vector<glm::vec4>& rColors, const SalColor& rColor, GLfloat rTransparency);
template<>
inline void addQuadColors<GL_TRIANGLES>(std::vector<glm::vec4>& rColors, const SalColor& rColor, GLfloat rTransparency)
{
glm::vec4 color = createGLColor(rColor, rTransparency);
rColors.insert(rColors.end(), {
color, color, color,
color, color, color
});
}
template<GLenum TYPE>
inline void addQuadEmptyExtrusionVectors(std::vector<GLfloat>& rExtrusions);
template<>
inline void addQuadEmptyExtrusionVectors<GL_TRIANGLES>(std::vector<GLfloat>& rExtrusions)
{
rExtrusions.insert(rExtrusions.end(), {
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f,
});
}
inline void addLineVertex(std::vector<GLfloat>& rVertices, std::vector<GLfloat>& rExtrusionVectors, glm::vec2 point, glm::vec2 extrusionVector, float length)
{
rVertices.push_back(point.x);
diff --git a/vcl/inc/opengl/program.hxx b/vcl/inc/opengl/program.hxx
index 3c194d8..c737c12 100644
--- a/vcl/inc/opengl/program.hxx
+++ b/vcl/inc/opengl/program.hxx
@@ -22,6 +22,7 @@
#include <tools/color.hxx>
#include <opengl/texture.hxx>
#include <glm/glm.hpp>
#include <unordered_map>
typedef std::unordered_map< OString, GLuint, OStringHash > UniformCache;
@@ -52,7 +53,9 @@ private:
GLuint mnTexCoordAttrib;
GLuint mnAlphaCoordAttrib;
GLuint mnMaskCoordAttrib;
GLuint mnNormalAttrib;
GLuint mnExtrusionVectorsAttrib;
GLuint mnVertexColorsAttrib;
TextureList maTextures;
bool mbBlending;
@@ -79,6 +82,7 @@ public:
void SetAlphaCoord( const GLvoid* pData );
void SetMaskCoord(const GLvoid* pData);
void SetExtrusionVectors(const GLvoid* pData);
void SetVertexColors(std::vector<glm::vec4>& rColorVector);
void SetUniform1f( const OString& rName, GLfloat v1 );
void SetUniform2f( const OString& rName, GLfloat v1, GLfloat v2 );
diff --git a/vcl/inc/opengl/texture.hxx b/vcl/inc/opengl/texture.hxx
index 5b4ccff..e120c08 100644
--- a/vcl/inc/opengl/texture.hxx
+++ b/vcl/inc/opengl/texture.hxx
@@ -78,6 +78,8 @@ private:
ImplOpenGLTexture* mpImpl;
int mnSlotNumber;
inline bool GetTextureRect(const SalTwoRect& rPosAry, bool bInverted, GLfloat& x1, GLfloat& x2, GLfloat& y1, GLfloat& y2) const;
public:
OpenGLTexture();
OpenGLTexture(ImplOpenGLTexture* pImpl, Rectangle aRectangle, int nSlotNumber);
@@ -124,6 +126,10 @@ template<> void OpenGLTexture::FillCoords<GL_TRIANGLES>(
std::vector<GLfloat>& aCoord, const SalTwoRect& rPosAry, bool bInverted)
const;
template<> void OpenGLTexture::FillCoords<GL_TRIANGLE_FAN>(
std::vector<GLfloat>& aCoord, const SalTwoRect& rPosAry, bool bInverted)
const;
#endif // INCLUDED_VCL_INC_OPENGL_TEXTURE_H
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/openglgdiimpl.hxx b/vcl/inc/openglgdiimpl.hxx
index ee8c7e2..09343c8 100644
--- a/vcl/inc/openglgdiimpl.hxx
+++ b/vcl/inc/openglgdiimpl.hxx
@@ -30,6 +30,7 @@
#include "opengl/program.hxx"
#include "opengl/texture.hxx"
#include "opengl/AccumulatedTextures.hxx"
#include "opengl/RenderList.hxx"
#include <memory>
@@ -100,7 +101,8 @@ protected:
SalColor mProgramSolidColor;
double mProgramSolidTransparency;
std::unique_ptr<AccumulatedTextures> mpAccumulatedTextures;
std::unique_ptr<AccumulatedTextures> mpAccumulatedTextures;
std::unique_ptr<RenderList> mpRenderList;
void ImplInitClipRegion();
void ImplSetClipBit( const vcl::Region& rClip, GLuint nMask );
@@ -114,12 +116,12 @@ public:
bool UseSolid( SalColor nColor, sal_uInt8 nTransparency );
bool UseSolid( SalColor nColor, double fTransparency );
bool UseSolid( SalColor nColor );
bool UseSolid();
bool UseLine(SalColor nColor, double fTransparency, GLfloat fLineWidth, bool bUseAA);
bool UseLine(GLfloat fLineWidth, bool bUseAA);
bool UseInvert50();
bool UseInvert(SalInvert nFlags);
void DrawPoint( long nX, long nY );
void DrawLine( double nX1, double nY1, double nX2, double nY2 );
void DrawConvexPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry, bool blockAA = false );
void DrawConvexPolygon( const tools::Polygon& rPolygon, bool blockAA = false );
void DrawTrapezoid( const basegfx::B2DTrapezoid& trapezoid, bool blockAA = false );
diff --git a/vcl/opengl/RenderList.cxx b/vcl/opengl/RenderList.cxx
new file mode 100644
index 0000000..008be02
--- /dev/null
+++ b/vcl/opengl/RenderList.cxx
@@ -0,0 +1,122 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
*/
#include "opengl/RenderList.hxx"
#include "opengl/VertexUtils.hxx"
namespace
{
inline void lclAddLineSegmentVertices(RenderParameters& rRenderParameter, GLfloat fX1, GLfloat fY1, GLfloat fX2, GLfloat fY2,
const SalColor& rColor, double fTransparency)
{
glm::vec2 aPoint1(fX1, fY1);
glm::vec2 aPoint2(fX2, fY2);
glm::vec2 aLineVector = vcl::vertex::normalize(aPoint2 - aPoint1);
glm::vec2 aNormal = glm::vec2(-aLineVector.y, aLineVector.x);
vcl::vertex::addLinePointFirst(rRenderParameter.maVertices, rRenderParameter.maExtrusionVectors,
aPoint1, aNormal, 1.0f);
vcl::vertex::addLinePointNext (rRenderParameter.maVertices, rRenderParameter.maExtrusionVectors,
aPoint1, aNormal, 1.0f,
aPoint2, aNormal, 1.0f);
vcl::vertex::addQuadColors<GL_TRIANGLES>(rRenderParameter.maColors, rColor, fTransparency);
}
} // end anonymous namespace
void RenderList::addDrawPixel(long nX, long nY, const SalColor& rColor)
{
if (rColor == SALCOLOR_NONE)
return;
checkOverlapping(basegfx::B2DRange(nX, nY, nX, nY));
RenderParameters& rRenderParameter = maRenderEntries.back().maTriangleParameters;
vcl::vertex::addRectangle<GL_TRIANGLES>(rRenderParameter.maVertices, nX - 0.5f, nY - 0.5f, nX + 0.5f, nY + 0.5f);
vcl::vertex::addQuadColors<GL_TRIANGLES>(rRenderParameter.maColors, rColor, 0.0f);
vcl::vertex::addQuadEmptyExtrusionVectors<GL_TRIANGLES>(rRenderParameter.maExtrusionVectors);
}
void RenderList::addDrawRectangle(long nX, long nY, long nWidth, long nHeight, const SalColor& rLineColor, const SalColor& rFillColor)
{
if (rLineColor == SALCOLOR_NONE && rFillColor == SALCOLOR_NONE)
return;
GLfloat fX1(nX);
GLfloat fY1(nY);
GLfloat fX2(nX + nWidth - 1);
GLfloat fY2(nY + nHeight - 1);
checkOverlapping(basegfx::B2DRange(fX1, fY1, fX2, fY2));
RenderParameters& rRenderParameter = maRenderEntries.back().maTriangleParameters;
// Draw rectangle stroke with line color
if (rLineColor != SALCOLOR_NONE)
{
vcl::vertex::addRectangle<GL_TRIANGLES>(rRenderParameter.maVertices, fX1 - 0.5f, fY1 - 0.5f, fX1 + 0.5f, fY2 + 0.5f);
vcl::vertex::addRectangle<GL_TRIANGLES>(rRenderParameter.maVertices, fX1 - 0.5f, fY1 - 0.5f, fX2 + 0.5f, fY1 + 0.5f);
vcl::vertex::addRectangle<GL_TRIANGLES>(rRenderParameter.maVertices, fX2 - 0.5f, fY1 - 0.5f, fX2 + 0.5f, fY2 + 0.5f);
vcl::vertex::addRectangle<GL_TRIANGLES>(rRenderParameter.maVertices, fX1 - 0.5f, fY2 - 0.5f, fX2 + 0.5f, fY2 + 0.5f);
vcl::vertex::addQuadColors<GL_TRIANGLES>(rRenderParameter.maColors, rLineColor, 0.0f);
vcl::vertex::addQuadColors<GL_TRIANGLES>(rRenderParameter.maColors, rLineColor, 0.0f);
vcl::vertex::addQuadColors<GL_TRIANGLES>(rRenderParameter.maColors, rLineColor, 0.0f);
vcl::vertex::addQuadColors<GL_TRIANGLES>(rRenderParameter.maColors, rLineColor, 0.0f);
vcl::vertex::addQuadEmptyExtrusionVectors<GL_TRIANGLES>(rRenderParameter.maExtrusionVectors);
vcl::vertex::addQuadEmptyExtrusionVectors<GL_TRIANGLES>(rRenderParameter.maExtrusionVectors);
vcl::vertex::addQuadEmptyExtrusionVectors<GL_TRIANGLES>(rRenderParameter.maExtrusionVectors);
vcl::vertex::addQuadEmptyExtrusionVectors<GL_TRIANGLES>(rRenderParameter.maExtrusionVectors);
}
if (rFillColor != SALCOLOR_NONE)
{
if (rLineColor == SALCOLOR_NONE)
{
// Draw rectangle stroke with fill color
vcl::vertex::addRectangle<GL_TRIANGLES>(rRenderParameter.maVertices, fX1 - 0.5f, fY1 - 0.5f, fX1 + 0.5f, fY2 + 0.5f);
vcl::vertex::addRectangle<GL_TRIANGLES>(rRenderParameter.maVertices, fX1 - 0.5f, fY1 - 0.5f, fX2 + 0.5f, fY1 + 0.5f);
vcl::vertex::addRectangle<GL_TRIANGLES>(rRenderParameter.maVertices, fX2 - 0.5f, fY1 - 0.5f, fX2 + 0.5f, fY2 + 0.5f);
vcl::vertex::addRectangle<GL_TRIANGLES>(rRenderParameter.maVertices, fX1 - 0.5f, fY2 - 0.5f, fX2 + 0.5f, fY2 + 0.5f);
vcl::vertex::addQuadColors<GL_TRIANGLES>(rRenderParameter.maColors, rFillColor, 0.0f);
vcl::vertex::addQuadColors<GL_TRIANGLES>(rRenderParameter.maColors, rFillColor, 0.0f);
vcl::vertex::addQuadColors<GL_TRIANGLES>(rRenderParameter.maColors, rFillColor, 0.0f);
vcl::vertex::addQuadColors<GL_TRIANGLES>(rRenderParameter.maColors, rFillColor, 0.0f);
vcl::vertex::addQuadEmptyExtrusionVectors<GL_TRIANGLES>(rRenderParameter.maExtrusionVectors);
vcl::vertex::addQuadEmptyExtrusionVectors<GL_TRIANGLES>(rRenderParameter.maExtrusionVectors);
vcl::vertex::addQuadEmptyExtrusionVectors<GL_TRIANGLES>(rRenderParameter.maExtrusionVectors);
vcl::vertex::addQuadEmptyExtrusionVectors<GL_TRIANGLES>(rRenderParameter.maExtrusionVectors);
}
// Draw rectangle fill with fill color
vcl::vertex::addRectangle<GL_TRIANGLES>(rRenderParameter.maVertices, fX1 + 0.5f, fY1 + 0.5f, fX2 - 0.5f, fY2 - 0.5f);
vcl::vertex::addQuadColors<GL_TRIANGLES>(rRenderParameter.maColors, rFillColor, 0.0f);
vcl::vertex::addQuadEmptyExtrusionVectors<GL_TRIANGLES>(rRenderParameter.maExtrusionVectors);
}
}
void RenderList::addDrawLine(long nX1, long nY1, long nX2, long nY2, const SalColor& rLineColor, bool bUseAA)
{
if (rLineColor == SALCOLOR_NONE)
return;
checkOverlapping(basegfx::B2DRange(nX1, nY1, nX2, nY2));
RenderParameters& rRenderParameter = bUseAA ? maRenderEntries.back().maLineAAParameters :
maRenderEntries.back().maLineParameters;
lclAddLineSegmentVertices(rRenderParameter, nX1, nY1, nX2, nY2, rLineColor, 0.0f);
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/opengl/combinedFragmentShader.glsl b/vcl/opengl/combinedFragmentShader.glsl
index 8d73d08..b200601 100644
--- a/vcl/opengl/combinedFragmentShader.glsl
+++ b/vcl/opengl/combinedFragmentShader.glsl
@@ -8,8 +8,12 @@
*/
varying float fade_factor; // 0->1 fade factor used for AA
uniform vec4 color;
#ifdef USE_VERTEX_COLORS
varying vec4 vertex_color;
#endif
uniform vec4 color;
uniform float line_width;
uniform float feather;
@@ -22,6 +26,12 @@ void main()
{
float alpha = 1.0;
#ifdef USE_VERTEX_COLORS
vec4 result = vertex_color;
#else
vec4 result = color;
#endif
if (type == TYPE_LINE)
{
float start = (line_width / 2.0) - feather; // where we start to apply alpha
@@ -36,10 +46,9 @@ void main()
alpha = clamp(dist, 0.0, 1.0);
}
vec4 result_color = color;
result_color.a = result_color.a * alpha;
result.a = result.a * alpha;
gl_FragColor = result_color;
gl_FragColor = result;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/opengl/combinedVertexShader.glsl b/vcl/opengl/combinedVertexShader.glsl
index 9272544..8c6a856 100644
--- a/vcl/opengl/combinedVertexShader.glsl
+++ b/vcl/opengl/combinedVertexShader.glsl
@@ -9,8 +9,14 @@
attribute vec2 position;
attribute vec4 extrusion_vectors;
#ifdef USE_VERTEX_COLORS
attribute vec4 vertex_color_in;
#endif
varying float fade_factor; // fade factor for anti-aliasing
#ifdef USE_VERTEX_COLORS
varying vec4 vertex_color;
#endif
uniform float line_width;
uniform float feather; // width where we fade the line
@@ -42,6 +48,9 @@ void main()
}
gl_Position = mvp * final_position;
#ifdef USE_VERTEX_COLORS
vertex_color = vertex_color_in;
#endif
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx
index 7c8f65a..fe2151e 100644
--- a/vcl/opengl/gdiimpl.cxx
+++ b/vcl/opengl/gdiimpl.cxx
@@ -85,6 +85,7 @@ OpenGLSalGraphicsImpl::OpenGLSalGraphicsImpl(SalGraphics& rParent, SalGeometryPr
, mProgramSolidColor(SALCOLOR_NONE)
, mProgramSolidTransparency(0.0)
, mpAccumulatedTextures(new AccumulatedTextures)
, mpRenderList(new RenderList)
{
}
@@ -549,9 +550,7 @@ bool OpenGLSalGraphicsImpl::UseSolid( SalColor nColor, sal_uInt8 nTransparency )
{
if( nColor == SALCOLOR_NONE )
return false;
if (!UseProgram("combinedVertexShader", "combinedFragmentShader"))
return false;
mpProgram->SetShaderType(DrawShaderType::Normal);
UseSolid();
mpProgram->SetColor( "color", nColor, nTransparency );
#ifdef DBG_UTIL
mProgramIsSolidColor = true;
@@ -566,9 +565,7 @@ bool OpenGLSalGraphicsImpl::UseSolid( SalColor nColor, double fTransparency )
{
if( nColor == SALCOLOR_NONE )
return false;
if (!UseProgram("combinedVertexShader", "combinedFragmentShader"))
return false;
mpProgram->SetShaderType(DrawShaderType::Normal);
UseSolid();
mpProgram->SetColorf( "color", nColor, fTransparency );
#ifdef DBG_UTIL
mProgramIsSolidColor = true;
@@ -578,6 +575,14 @@ bool OpenGLSalGraphicsImpl::UseSolid( SalColor nColor, double fTransparency )
return true;
}
bool OpenGLSalGraphicsImpl::UseSolid()
{
if (!UseProgram("combinedVertexShader", "combinedFragmentShader"))
return false;
mpProgram->SetShaderType(DrawShaderType::Normal);
return true;
}
bool OpenGLSalGraphicsImpl::UseInvert50()
{
if( !UseProgram( "dumbVertexShader", "invert50FragmentShader" ) )
@@ -612,35 +617,6 @@ bool OpenGLSalGraphicsImpl::UseInvert( SalInvert nFlags )
return true;
}
void OpenGLSalGraphicsImpl::DrawPoint( long nX, long nY )
{
OpenGLZone aZone;
std::vector<GLfloat> pPoint {
GLfloat(nX), GLfloat(nY)
};
std::vector<GLfloat> aExtrusion(3, 0);
mpProgram->SetExtrusionVectors(aExtrusion.data());
ApplyProgramMatrices(0.5f);
mpProgram->DrawArrays(GL_POINTS, pPoint);
CHECK_GL_ERROR();
}
void OpenGLSalGraphicsImpl::DrawLine( double nX1, double nY1, double nX2, double nY2 )
{
OpenGLZone aZone;
std::vector<GLfloat> pPoint {
GLfloat(nX1), GLfloat(nY1),
GLfloat(nX2), GLfloat(nY2)
};
ApplyProgramMatrices(0.5f);
mpProgram->DrawArrays(GL_LINES, pPoint);
CHECK_GL_ERROR();
}
void OpenGLSalGraphicsImpl::DrawLineCap(float x1, float y1, float x2, float y2, css::drawing::LineCap eLineCap, float fLineWidth)
{
if (eLineCap != css::drawing::LineCap_ROUND && eLineCap != css::drawing::LineCap_SQUARE)
@@ -906,16 +882,8 @@ bool OpenGLSalGraphicsImpl::UseLine(SalColor nColor, double fTransparency, GLflo
{
if( nColor == SALCOLOR_NONE )
return false;
if (!UseProgram("combinedVertexShader", "combinedFragmentShader"))
return false;
mpProgram->SetShaderType(DrawShaderType::Line);
UseLine(fLineWidth, bUseAA);
mpProgram->SetColorf("color", nColor, fTransparency);
mpProgram->SetUniform1f("line_width", fLineWidth);
// The width of the feather - area we make lineary transparent in VS.
// Good AA value is 0.5f, no AA if feather 0.0f
mpProgram->SetUniform1f("feather", bUseAA ? 0.5f : 0.0f);
// We need blending or AA won't work correctly
mpProgram->SetBlendMode( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
#ifdef DBG_UTIL
mProgramIsSolidColor = true;
#endif
@@ -924,6 +892,20 @@ bool OpenGLSalGraphicsImpl::UseLine(SalColor nColor, double fTransparency, GLflo
return true;
}
bool OpenGLSalGraphicsImpl::UseLine(GLfloat fLineWidth, bool bUseAA)
{
if (!UseProgram("combinedVertexShader", "combinedFragmentShader"))
return false;
mpProgram->SetShaderType(DrawShaderType::Line);
mpProgram->SetUniform1f("line_width", fLineWidth);
// The width of the feather - area we make lineary transparent in VS.
// Good AA value is 0.5f, no AA if feather 0.0f
mpProgram->SetUniform1f("feather", bUseAA ? 0.5f : 0.0f);
// We need blending or AA won't work correctly
mpProgram->SetBlendMode(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
return true;
}
void OpenGLSalGraphicsImpl::DrawConvexPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry, bool blockAA )
{
OpenGLZone aZone;
@@ -1524,76 +1506,101 @@ void OpenGLSalGraphicsImpl::DeferredTextDraw(OpenGLTexture& rTexture, SalColor a
void OpenGLSalGraphicsImpl::FlushDeferredDrawing()
{
if (mpAccumulatedTextures->empty())
if (mpAccumulatedTextures->empty() && mpRenderList->empty())
return;
InitializePreDrawState();
VCL_GL_INFO("FlushDeferredDrawing: " << mpRenderList->getEntries().size());
VCL_GL_INFO("FlushDeferredDrawing");
OpenGLZone aZone;
#if 0 // Draw a background rect under text for debugging - same color shows text from the same texture
static sal_uInt8 r = 0xBE;
static sal_uInt8 g = 0xF0;
static sal_uInt8 b = 0xFF;
static std::unordered_map<GLuint, Color> aColorForTextureMap;
for (auto& rPair : mpAccumulatedTextures->getAccumulatedTexturesMap())
if (!mpAccumulatedTextures->empty())
{
OpenGLTexture& rTexture = rPair.second->maTexture;
Color aUseColor;
if (aColorForTextureMap.find(rTexture.Id()) == aColorForTextureMap.end())
{
Color aColor(r, g, b);
sal_uInt16 h,s,br;
aColor.RGBtoHSB(h, s, br);
aColor = Color::HSBtoRGB((h + 40) % 360, s, br);
r = aColor.GetRed();
g = aColor.GetGreen();
b = aColor.GetBlue();
aColorForTextureMap[rTexture.Id()] = aColor;
}
aUseColor = aColorForTextureMap[rTexture.Id()];
InitializePreDrawState();
if (!UseSolid(MAKE_SALCOLOR(aUseColor.GetRed(), aUseColor.GetGreen(), aUseColor.GetBlue())))
OpenGLZone aZone;
if (!UseProgram("combinedTextureVertexShader", "combinedTextureFragmentShader"))
return;
for (auto rColorTwoRectPair: rPair.second->maColorTextureDrawParametersMap)
mpProgram->SetShaderType(TextureShaderType::MaskedColor);
mpProgram->SetIdentityTransform("transform");
mpProgram->SetBlendMode(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
for (auto& rPair : mpAccumulatedTextures->getAccumulatedTexturesMap())
{
TextureDrawParameters& rParameters = rColorTwoRectPair.second;
ApplyProgramMatrices();
mpProgram->SetTextureCoord(rParameters.maTextureCoords.data());
mpProgram->DrawArrays(GL_TRIANGLES, rParameters.maVertices);
OpenGLTexture& rTexture = rPair.second->maTexture;
mpProgram->SetTexture("texture", rTexture);
for (auto& rColorTwoRectPair: rPair.second->maColorTextureDrawParametersMap)
{
mpProgram->SetColor("color", rColorTwoRectPair.first, 0);
TextureDrawParameters& rParameters = rColorTwoRectPair.second;
ApplyProgramMatrices();
mpProgram->SetTextureCoord(rParameters.maTextureCoords.data());
mpProgram->SetMaskCoord(rParameters.maTextureCoords.data());
mpProgram->SetAlphaCoord(rParameters.maTextureCoords.data());
mpProgram->DrawArrays(GL_TRIANGLES, rParameters.maVertices);
}
}
mpProgram->Clean();
mpAccumulatedTextures->clear();
PostDraw();
}
#endif
if (!UseProgram("combinedTextureVertexShader", "combinedTextureFragmentShader"))
return;
mpProgram->SetShaderType(TextureShaderType::MaskedColor);
mpProgram->SetIdentityTransform("transform");
mpProgram->SetBlendMode(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
for (auto& rPair : mpAccumulatedTextures->getAccumulatedTexturesMap())
if (!mpRenderList->empty())
{
OpenGLTexture& rTexture = rPair.second->maTexture;
mpProgram->SetTexture("texture", rTexture);
for (auto& rColorTwoRectPair: rPair.second->maColorTextureDrawParametersMap)
{
mpProgram->SetColor("color", rColorTwoRectPair.first, 0);
TextureDrawParameters& rParameters = rColorTwoRectPair.second;
ApplyProgramMatrices();
mpProgram->SetTextureCoord(rParameters.maTextureCoords.data());
mpProgram->SetMaskCoord(rParameters.maTextureCoords.data());
mpProgram->SetAlphaCoord(rParameters.maTextureCoords.data());
mpProgram->DrawArrays(GL_TRIANGLES, rParameters.maVertices);
}
}
mpProgram->Clean();
mpAccumulatedTextures->clear();
InitializePreDrawState(XOROption::IMPLEMENT_XOR);
PostDraw();
OpenGLZone aZone;
for (RenderEntry& rRenderEntry : mpRenderList->getEntries())
{
if (rRenderEntry.hasTriangles() && UseProgram("combinedVertexShader", "combinedFragmentShader", "#define USE_VERTEX_COLORS"))
{
RenderParameters& rParameters = rRenderEntry.maTriangleParameters;
VCL_GL_INFO("Flush Triangles: " << rParameters.maVertices.size());
mpProgram->SetShaderType(DrawShaderType::Normal);
ApplyProgramMatrices(0.5f);
mpProgram->SetExtrusionVectors(rParameters.maExtrusionVectors.data());
mpProgram->SetVertexColors(rParameters.maColors);
mpProgram->DrawArrays(GL_TRIANGLES, rParameters.maVertices);
CHECK_GL_ERROR();
mpProgram->Clean();
}
if (rRenderEntry.hasLines() && UseProgram("combinedVertexShader", "combinedFragmentShader", "#define USE_VERTEX_COLORS"))
{
RenderParameters& rParameters = rRenderEntry.maLineParameters;
VCL_GL_INFO("Flush Lines: " << rParameters.maVertices.size());
mpProgram->SetShaderType(DrawShaderType::Line);
mpProgram->SetUniform1f("line_width", 1.0f);
mpProgram->SetUniform1f("feather", 0.0f); // Anti-Aliasing disabled
mpProgram->SetBlendMode(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
ApplyProgramMatrices(0.5f);
mpProgram->SetExtrusionVectors(rParameters.maExtrusionVectors.data());
mpProgram->SetVertexColors(rParameters.maColors);
mpProgram->DrawArrays(GL_TRIANGLES, rParameters.maVertices);
CHECK_GL_ERROR();
mpProgram->Clean();
}
if (rRenderEntry.hasLinesAA() && UseProgram("combinedVertexShader", "combinedFragmentShader", "#define USE_VERTEX_COLORS"))
{
RenderParameters& rParameters = rRenderEntry.maLineAAParameters;
VCL_GL_INFO("Flush Lines AA: " << rParameters.maVertices.size());
mpProgram->SetShaderType(DrawShaderType::Line);
mpProgram->SetUniform1f("line_width", 1.0f);
mpProgram->SetUniform1f("feather", 0.5f); // Anti-Aliasing enabled
mpProgram->SetBlendMode(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
ApplyProgramMatrices(0.5f);
mpProgram->SetExtrusionVectors(rParameters.maExtrusionVectors.data());
mpProgram->SetVertexColors(rParameters.maColors);
mpProgram->DrawArrays(GL_TRIANGLES, rParameters.maVertices);
CHECK_GL_ERROR();
mpProgram->Clean();
}
}
mpRenderList->clear();
PostDraw();
}
VCL_GL_INFO("End FlushDeferredDrawing");
}
void OpenGLSalGraphicsImpl::DrawLinearGradient( const Gradient& rGradient, const Rectangle& rRect )
@@ -1702,72 +1709,28 @@ void OpenGLSalGraphicsImpl::DrawRadialGradient( const Gradient& rGradient, const
DrawRect( rRect );
}
// draw --> LineColor and FillColor and RasterOp and ClipRegion
void OpenGLSalGraphicsImpl::drawPixel( long nX, long nY )
void OpenGLSalGraphicsImpl::drawPixel(long nX, long nY)
{
VCL_GL_INFO( "::drawPixel" );
if( mnLineColor != SALCOLOR_NONE )
{
PreDraw( XOROption::IMPLEMENT_XOR );
if( UseSolid( mnLineColor ) )
DrawPoint( nX, nY );
PostDraw();
}
VCL_GL_INFO("::drawPixel: (" << nX << ", " << nY << ")");
mpRenderList->addDrawPixel(nX, nY, mnLineColor);
}
void OpenGLSalGraphicsImpl::drawPixel( long nX, long nY, SalColor nSalColor )
void OpenGLSalGraphicsImpl::drawPixel(long nX, long nY, SalColor nSalColor)
{
VCL_GL_INFO( "::drawPixel" );
if( nSalColor != SALCOLOR_NONE )
{
PreDraw( XOROption::IMPLEMENT_XOR );
if( UseSolid( nSalColor ) )
DrawPoint( nX, nY );
PostDraw();
}
VCL_GL_INFO("::drawPixel: (" << nX << ", " << nY << ")");
mpRenderList->addDrawPixel(nX, nY, nSalColor);
}
void OpenGLSalGraphicsImpl::drawLine( long nX1, long nY1, long nX2, long nY2 )
void OpenGLSalGraphicsImpl::drawLine(long nX1, long nY1, long nX2, long nY2)
{
VCL_GL_INFO( "::drawLine" );
if( mnLineColor != SALCOLOR_NONE )
{
PreDraw( XOROption::IMPLEMENT_XOR );
if (UseLine(mnLineColor, 0.0, 1.0f, mrParent.getAntiAliasB2DDraw()))
DrawLineSegment(nX1, nY1, nX2, nY2);
PostDraw();
}
VCL_GL_INFO("::drawLine (" << nX1 << ", " << nY1 << ") (" << nX2 << ", " << nY2 << ")");
mpRenderList->addDrawLine(nX1, nY1, nX2, nY2, mnLineColor, mrParent.getAntiAliasB2DDraw());
}
void OpenGLSalGraphicsImpl::drawRect( long nX, long nY, long nWidth, long nHeight )
{
VCL_GL_INFO( "::drawRect" );
PreDraw( XOROption::IMPLEMENT_XOR );
if( UseSolid( mnFillColor ) )
DrawRect( nX, nY, nWidth, nHeight );
if( UseSolid( mnLineColor ) )
{
GLfloat fX1(nX);
GLfloat fY1(nY);
GLfloat fX2(nX + nWidth - 1);
GLfloat fY2(nY + nHeight - 1);
std::vector<GLfloat> pPoints {
fX1, fY1,
fX2, fY1,
fX2, fY2,
fX1, fY2
};
ApplyProgramMatrices(0.5f);
mpProgram->DrawArrays(GL_LINE_LOOP, pPoints);
CHECK_GL_ERROR();
}
PostDraw();
VCL_GL_INFO("::drawRect (" << nX << ", " << nY << ") [" << nWidth << ", " << nHeight << "]");
mpRenderList->addDrawRectangle(nX, nY, nWidth, nHeight, mnLineColor, mnFillColor);
}
void OpenGLSalGraphicsImpl::drawPolyLine( sal_uInt32 nPoints, const SalPoint* pPtAry )
diff --git a/vcl/opengl/program.cxx b/vcl/opengl/program.cxx
index de6cec7..8aadb9d 100644
--- a/vcl/opengl/program.cxx
+++ b/vcl/opengl/program.cxx
@@ -24,8 +24,9 @@ OpenGLProgram::OpenGLProgram() :
mnTexCoordAttrib( SAL_MAX_UINT32 ),
mnAlphaCoordAttrib( SAL_MAX_UINT32 ),
mnMaskCoordAttrib( SAL_MAX_UINT32 ),
mnNormalAttrib( SAL_MAX_UINT32 ),
mbBlending( false ),
mnExtrusionVectorsAttrib( SAL_MAX_UINT32 ),
mnVertexColorsAttrib( SAL_MAX_UINT32 ),
mbBlending(false),
mfLastWidth(0.0),
mfLastHeight(0.0),
mfLastPixelOffset(0.0)
@@ -147,7 +148,12 @@ void OpenGLProgram::SetMaskCoord(const GLvoid* pData)
void OpenGLProgram::SetExtrusionVectors(const GLvoid* pData)
{
SetVertexAttrib(mnNormalAttrib, "extrusion_vectors", pData, 3);
SetVertexAttrib(mnExtrusionVectorsAttrib, "extrusion_vectors", pData, 3);
}
void OpenGLProgram::SetVertexColors(std::vector<glm::vec4>& rColorVector)
{
SetVertexAttrib(mnVertexColorsAttrib, "vertex_color_in", glm::value_ptr(rColorVector[0]), 4);
}
void OpenGLProgram::SetShaderType(TextureShaderType eTextureShaderType)
diff --git a/vcl/opengl/texture.cxx b/vcl/opengl/texture.cxx
index 0999484..3de7ac8 100644
--- a/vcl/opengl/texture.cxx
+++ b/vcl/opengl/texture.cxx
@@ -386,18 +386,8 @@ void OpenGLTexture::GetCoord( GLfloat* pCoord, const SalTwoRect& rPosAry, bool b
}
}
template <>
void OpenGLTexture::FillCoords<GL_TRIANGLES>(std::vector<GLfloat>& aCoord, const SalTwoRect& rPosAry, bool bInverted) const
bool OpenGLTexture::GetTextureRect(const SalTwoRect& rPosAry, bool bInverted, GLfloat& x1, GLfloat& x2, GLfloat& y1, GLfloat& y2) const
{
VCL_GL_INFO("Add coord " << Id() << " [" << maRect.Left() << "," << maRect.Top() << "] " << GetWidth() << "x" << GetHeight() );
VCL_GL_INFO(" With 2Rect Src [" << rPosAry.mnSrcX << ", " << rPosAry.mnSrcY << "] wh (" << rPosAry.mnSrcWidth << ", " << rPosAry.mnSrcHeight << ")");
VCL_GL_INFO(" With 2Rect Dest [" << rPosAry.mnDestX << ", " << rPosAry.mnDestY << "] wh (" << rPosAry.mnDestWidth << ", " << rPosAry.mnDestHeight << ")");
GLfloat x1 = 0.0f;
GLfloat x2 = 0.0f;
GLfloat y1 = 0.0f;
GLfloat y2 = 0.0f;
if (mpImpl)
{
double fTextureWidth(mpImpl->mnWidth);
@@ -416,25 +406,41 @@ void OpenGLTexture::FillCoords<GL_TRIANGLES>(std::vector<GLfloat>& aCoord, const
y1 = 1.0f - (maRect.Top() + rPosAry.mnSrcY) / fTextureHeight;
y2 = 1.0f - (maRect.Top() + rPosAry.mnSrcY + rPosAry.mnSrcHeight) / fTextureHeight;
}
return true;
}
return false;
}
aCoord.push_back(x1);
aCoord.push_back(y1);
template <>
void OpenGLTexture::FillCoords<GL_TRIANGLE_FAN>(std::vector<GLfloat>& rCoords, const SalTwoRect& rPosAry, bool bInverted) const
{
GLfloat x1 = 0.0f;
GLfloat x2 = 0.0f;
GLfloat y1 = 0.0f;
GLfloat y2 = 0.0f;
aCoord.push_back(x2);
aCoord.push_back(y1);
GetTextureRect(rPosAry, bInverted, x1, x2, y1, y2);
aCoord.push_back(x1);
aCoord.push_back(y2);
rCoords.insert(rCoords.end(), {
x1, y2, x1, y1,
x2, y1, x2, y2
});
}
aCoord.push_back(x1);
aCoord.push_back(y2);
template <>
void OpenGLTexture::FillCoords<GL_TRIANGLES>(std::vector<GLfloat>& rCoords, const SalTwoRect& rPosAry, bool bInverted) const
{
GLfloat x1 = 0.0f;
GLfloat x2 = 0.0f;
GLfloat y1 = 0.0f;
GLfloat y2 = 0.0f;
aCoord.push_back(x2);
aCoord.push_back(y1);
GetTextureRect(rPosAry, bInverted, x1, x2, y1, y2);
aCoord.push_back(x2);
aCoord.push_back(y2);
rCoords.insert(rCoords.end(), {
x1, y1, x2, y1, x1, y2,
x1, y2, x2, y1, x2, y2
});
}
void OpenGLTexture::GetWholeCoord( GLfloat* pCoord ) const