summaryrefslogtreecommitdiff
path: root/vcl/inc
diff options
context:
space:
mode:
authorTomaž Vajngerl <tomaz.vajngerl@collabora.co.uk>2016-06-07 20:45:14 +0900
committerTomaž Vajngerl <tomaz.vajngerl@collabora.co.uk>2016-06-08 17:12:28 +0900
commitce72e34b359c323ef7ff96a70500810a9cd8703a (patch)
tree7436ef509b6670c4331d2e2f0c552728e13ea1f8 /vcl/inc
parent4bdbfdd6426460c562746c67c29a3b5e2bef8563 (diff)
opengl: batch drawing of polylines
To get polylines to draw in a batch it was necessary to refactor the polyline code to work with GL_TRIANGLES instead of the previous used GL_TRIANGLE_STRIP. For this and to make the code easier to handle a new class was introduced: LineBuilder, which purpose is to assemble vertices for a polyline (line ends, line joints). In addition we need to know the line width, anti-aliasing (AA) per vertex basis (in addition to color, normal and extrusion) so we can draw many polylines with one draw call. This info is now stored in Vertex struct which is used when drawing lines or triangles (fills). Uploading of vertices has also been changed, previously we uploaded the vertices with the drawcall. a convention in Modern OpenGL is however to use VBO (Vertex Buffer Object) for this. With this we can upload the to the GPU vertices independently and not upload them if this is not needed (which is currently not used yet). A vector of Vertex structs is now uploaded to the GPU using a VBO which is handeled with a new VertexBufferObject class. In addition to reduce the ammount of duplicated vertices, we use a index vector (handled by IndexBufferObject class) where we only define the indices of the vertex buffer which should be drawn. Change-Id: I49dc9c6260b459f4f4ce3a5e4fa4c8ad05a7b878
Diffstat (limited to 'vcl/inc')
-rw-r--r--vcl/inc/opengl/BufferObject.hxx89
-rw-r--r--vcl/inc/opengl/LineRenderUtils.hxx54
-rw-r--r--vcl/inc/opengl/RenderList.hxx30
-rw-r--r--vcl/inc/opengl/VertexUtils.hxx112
-rw-r--r--vcl/inc/opengl/program.hxx14
-rw-r--r--vcl/inc/openglgdiimpl.hxx4
6 files changed, 221 insertions, 82 deletions
diff --git a/vcl/inc/opengl/BufferObject.hxx b/vcl/inc/opengl/BufferObject.hxx
new file mode 100644
index 000000000000..3cda66deed0e
--- /dev/null
+++ b/vcl/inc/opengl/BufferObject.hxx
@@ -0,0 +1,89 @@
+/* -*- 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_BUFFEROBJECT_H
+#define INCLUDED_VCL_INC_OPENGL_BUFFEROBJECT_H
+
+namespace vcl
+{
+
+template<typename TYPE, GLenum BUFFER_TYPE>
+class BufferObject
+{
+private:
+ GLuint mId;
+
+public:
+ BufferObject()
+ : mId(0)
+ {
+ glGenBuffers(1, &mId);
+ CHECK_GL_ERROR();
+ }
+
+ virtual ~BufferObject()
+ {
+ dispose();
+ }
+
+ void bind()
+ {
+ if (mId)
+ {
+ glBindBuffer(BUFFER_TYPE, mId);
+ CHECK_GL_ERROR();
+ }
+ }
+
+ void unbind()
+ {
+ if (mId)
+ {
+ glBindBuffer(BUFFER_TYPE, 0);
+ CHECK_GL_ERROR();
+ }
+ }
+
+ void upload(const std::vector<TYPE>& rData)
+ {
+ if (mId)
+ {
+ bind();
+ glBufferData(BUFFER_TYPE, sizeof(TYPE) * rData.size(), rData.data(), GL_STATIC_DRAW);
+ CHECK_GL_ERROR();
+ }
+ }
+
+ void dispose()
+ {
+ if (mId)
+ {
+ glDeleteBuffers(1, &mId);
+ CHECK_GL_ERROR();
+ mId = 0;
+ }
+ }
+
+};
+
+template<typename TYPE>
+class VertexBufferObject : public BufferObject<TYPE, GL_ARRAY_BUFFER>
+{
+};
+
+class IndexBufferObject : public BufferObject<GLuint, GL_ELEMENT_ARRAY_BUFFER>
+{
+};
+
+} // end vcl
+
+#endif // INCLUDED_VCL_INC_OPENGL_BUFFEROBJECT_H
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/opengl/LineRenderUtils.hxx b/vcl/inc/opengl/LineRenderUtils.hxx
new file mode 100644
index 000000000000..7c9018a67fa9
--- /dev/null
+++ b/vcl/inc/opengl/LineRenderUtils.hxx
@@ -0,0 +1,54 @@
+/* -*- 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_LINERENDERUTILS_H
+#define INCLUDED_VCL_INC_OPENGL_LINERENDERUTILS_H
+
+#include <GL/glew.h>
+#include "opengl/VertexUtils.hxx"
+#include "opengl/RenderList.hxx"
+
+namespace vcl
+{
+class LineBuilder
+{
+private:
+ std::vector<Vertex>& mrVertices;
+ std::vector<GLuint>& mrIndices;
+ GLubyte mR, mG, mB, mA;
+ GLfloat mfLineWidth;
+ GLfloat mfLineWidthAndAA;
+ size_t mnInitialIndexSize;
+ bool mbIncomplete;
+
+public:
+ LineBuilder(std::vector<Vertex>& rVertices, std::vector<GLuint>& rIndices,
+ SalColor nColor, GLfloat fTransparency,
+ GLfloat fLineWidth, bool bUseAA);
+
+ void appendLineSegment(const glm::vec2& rPoint1, const glm::vec2& rNormal1, GLfloat aExtrusion1,
+ const glm::vec2& rPoint2, const glm::vec2& rNormal2, GLfloat aExtrusion2);
+
+ void appendLine(const glm::vec2& rPoint1, const glm::vec2& rPoint2);
+
+ void appendAndConnectLinePoint(const glm::vec2& rPoint, const glm::vec2& aNormal, GLfloat aExtrusion);
+
+ void appendMiterJoint(glm::vec2 point, glm::vec2 prevLineVector, glm::vec2 nextLineVector);
+ void appendBevelJoint(glm::vec2 point, glm::vec2 prevLineVector, glm::vec2 nextLineVector);
+ void appendRoundJoint(glm::vec2 point, glm::vec2 prevLineVector, glm::vec2 nextLineVector);
+ void appendRoundLineCapVertices(const glm::vec2& rPoint1, const glm::vec2& rPoint2);
+ void appendSquareLineCapVertices(const glm::vec2& rPoint1, const glm::vec2& rPoint2);
+};
+
+} // end vcl
+
+#endif // INCLUDED_VCL_INC_OPENGL_LINERENDERUTILS_H
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/opengl/RenderList.hxx b/vcl/inc/opengl/RenderList.hxx
index f6f59f5fec6e..062971ec29f3 100644
--- a/vcl/inc/opengl/RenderList.hxx
+++ b/vcl/inc/opengl/RenderList.hxx
@@ -21,18 +21,29 @@
#include "opengl/texture.hxx"
+#include <com/sun/star/drawing/LineCap.hpp>
+
+struct Vertex
+{
+ glm::vec2 position;
+ glm::vec4 color;
+ glm::vec4 lineData;
+};
+
+static_assert(sizeof(Vertex) == (2*4 + 4*4 + 4*4), "Vertex struct has wrong size/alignment");
+
+
struct RenderParameters
{
- std::vector<GLfloat> maVertices;
- std::vector<GLfloat> maExtrusionVectors;
- std::vector<glm::vec4> maColors;
+ std::vector<Vertex> maVertices;
+ std::vector<GLuint> maIndices;
};
struct RenderTextureParameters
{
std::vector<GLfloat> maVertices;
- std::vector<glm::vec4> maColors;
std::vector<GLfloat> maTextureCoords;
+ std::vector<GLubyte> maColors;
OpenGLTexture maTexture;
};
@@ -42,7 +53,6 @@ struct RenderEntry
RenderParameters maTriangleParameters;
RenderParameters maLineParameters;
- RenderParameters maLineAAParameters;
std::unordered_map<GLuint, RenderTextureParameters> maTextureParametersMap;
@@ -56,11 +66,6 @@ struct RenderEntry
return !maLineParameters.maVertices.empty();
}
- bool hasLinesAA()
- {
- return !maLineAAParameters.maVertices.empty();
- }
-
bool hasTextures()
{
return !maTextureParametersMap.empty();
@@ -156,6 +161,11 @@ public:
void addDrawPolyPolygon(const basegfx::B2DPolyPolygon& rPolyPolygon, double fTransparency,
SalColor nLineColor, SalColor nFillColor, bool bUseAA);
+
+ void addDrawPolyLine(const basegfx::B2DPolygon& rPolygon, double fTransparency,
+ const basegfx::B2DVector& rLineWidth, basegfx::B2DLineJoin eLineJoin,
+ css::drawing::LineCap eLineCap, double fMiterMinimumAngle,
+ SalColor nLineColor, bool bUseAA);
};
#endif // INCLUDED_VCL_INC_OPENGL_RENDERLIST_H
diff --git a/vcl/inc/opengl/VertexUtils.hxx b/vcl/inc/opengl/VertexUtils.hxx
index 6de658e14d54..f9804ecd978f 100644
--- a/vcl/inc/opengl/VertexUtils.hxx
+++ b/vcl/inc/opengl/VertexUtils.hxx
@@ -11,7 +11,11 @@
#ifndef INCLUDED_VCL_INC_OPENGL_VERTEXUTILS_H
#define INCLUDED_VCL_INC_OPENGL_VERTEXUTILS_H
+#include <basegfx/numeric/ftools.hxx>
+#include <GL/glew.h>
#include <glm/gtx/norm.hpp>
+#include <vcl/salgtype.hxx>
+#include <vector>
namespace vcl
{
@@ -39,96 +43,74 @@ inline void addRectangle<GL_TRIANGLE_FAN>(std::vector<GLfloat>& rVertices, GLflo
});
}
-template<GLenum TYPE>
-inline void addTrapezoid(std::vector<GLfloat>& rVertices, GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2,
- GLfloat x3, GLfloat y3, GLfloat x4, GLfloat y4);
-
-template<>
-inline void addTrapezoid<GL_TRIANGLES>(std::vector<GLfloat>& rVertices, GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2,
- GLfloat x3, GLfloat y3, GLfloat x4, GLfloat y4)
+inline void createColor(SalColor nColor, GLfloat fTransparency, GLubyte& nR, GLubyte& nG, GLubyte& nB, GLubyte& nA)
{
- rVertices.insert(rVertices.end(), {
- x1, y1, x2, y2, x3, y3,
- x3, y3, x2, y2, x4, y4
- });
-}
-
-inline glm::vec4 createGLColor(SalColor nColor, GLfloat rTransparency)
-{
- return glm::vec4(SALCOLOR_RED(nColor) / 255.0f,
- SALCOLOR_GREEN(nColor) / 255.0f,
- SALCOLOR_BLUE(nColor) / 255.0f,
- 1.0f - rTransparency);
+ nR = SALCOLOR_RED(nColor);
+ nG = SALCOLOR_GREEN(nColor);
+ nB = SALCOLOR_BLUE(nColor);
+ nA = (1.0f - fTransparency) * 255.0f;
}
template<GLenum TYPE>
-inline void addQuadColors(std::vector<glm::vec4>& rColors, SalColor nColor, GLfloat rTransparency);
+inline void addQuadColors(std::vector<GLubyte>& rColors, SalColor nColor, GLfloat fTransparency);
template<>
-inline void addQuadColors<GL_TRIANGLES>(std::vector<glm::vec4>& rColors, SalColor nColor, GLfloat rTransparency)
+inline void addQuadColors<GL_TRIANGLES>(std::vector<GLubyte>& rColors, SalColor nColor, GLfloat fTransparency)
{
- glm::vec4 color = createGLColor(nColor, rTransparency);
+ GLubyte nR, nG, nB, nA;
+ createColor(nColor, fTransparency, nR, nG, nB, nA);
rColors.insert(rColors.end(), {
- color, color, color,
- color, color, color
+ nR, nG, nB, nA,
+ nR, nG, nB, nA,
+ nR, nG, nB, nA,
+ nR, nG, nB, nA,
+ nR, nG, nB, nA,
+ nR, nG, nB, nA,
});
}
-template<GLenum TYPE>
-inline void addQuadEmptyExtrusionVectors(std::vector<GLfloat>& rExtrusions);
-
-template<>
-inline void addQuadEmptyExtrusionVectors<GL_TRIANGLES>(std::vector<GLfloat>& rExtrusions)
+inline void addLineSegmentVertices(std::vector<GLfloat>& rVertices, std::vector<GLfloat>& rExtrusionVectors,
+ glm::vec2 prevPoint, glm::vec2 prevExtrusionVector, GLfloat prevLength,
+ glm::vec2 currPoint, glm::vec2 currExtrusionVector, GLfloat currLength)
{
- 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,
+ rVertices.insert(rVertices.end(), {
+ prevPoint.x, prevPoint.y,
+ prevPoint.x, prevPoint.y,
+ currPoint.x, currPoint.y,
+ currPoint.x, currPoint.y,
+ prevPoint.x, prevPoint.y,
+ currPoint.x, currPoint.y,
});
-}
-inline void addLineVertex(std::vector<GLfloat>& rVertices, std::vector<GLfloat>& rExtrusionVectors, glm::vec2 point, glm::vec2 extrusionVector, float length)
-{
- rVertices.push_back(point.x);
- rVertices.push_back(point.y);
-
- rExtrusionVectors.push_back(extrusionVector.x);
- rExtrusionVectors.push_back(extrusionVector.y);
- rExtrusionVectors.push_back(length);
+ rExtrusionVectors.insert(rExtrusionVectors.end(), {
+ -prevExtrusionVector.x, -prevExtrusionVector.y, -prevLength,
+ prevExtrusionVector.x, prevExtrusionVector.y, prevLength,
+ -currExtrusionVector.x, -currExtrusionVector.y, -currLength,
+ -currExtrusionVector.x, -currExtrusionVector.y, -currLength,
+ prevExtrusionVector.x, prevExtrusionVector.y, prevLength,
+ currExtrusionVector.x, currExtrusionVector.y, currLength,
+ });
}
-inline void addLineVertexPair(std::vector<GLfloat>& rVertices, std::vector<GLfloat>& rExtrusionVectors, const glm::vec2& point, const glm::vec2& extrusionVector, float length)
+inline glm::vec2 normalize(const glm::vec2& vector)
{
- addLineVertex(rVertices, rExtrusionVectors, point, -extrusionVector, -length);
- addLineVertex(rVertices, rExtrusionVectors, point, extrusionVector, length);
+ if (glm::length(vector) > 0.0)
+ return glm::normalize(vector);
+ return vector;
}
-inline void addLinePointFirst(std::vector<GLfloat>& rVertices, std::vector<GLfloat>& rExtrusionVectors,
- glm::vec2 point, glm::vec2 extrusionVector, float length)
+inline glm::vec2 perpendicular(const glm::vec2& vector)
{
- addLineVertex(rVertices, rExtrusionVectors, point, -extrusionVector, -length);
- addLineVertex(rVertices, rExtrusionVectors, point, extrusionVector, length);
+ return glm::vec2(-vector.y, vector.x);
}
-inline void addLinePointNext(std::vector<GLfloat>& rVertices, std::vector<GLfloat>& rExtrusionVectors,
- glm::vec2 prevPoint, glm::vec2 prevExtrusionVector, float prevLength,
- glm::vec2 currPoint, glm::vec2 currExtrusionVector, float currLength)
+inline float lineVectorAngle(const glm::vec2& previous, const glm::vec2& next)
{
- addLineVertex(rVertices, rExtrusionVectors, currPoint, -currExtrusionVector, -currLength);
- addLineVertex(rVertices, rExtrusionVectors, currPoint, -currExtrusionVector, -currLength);
- addLineVertex(rVertices, rExtrusionVectors, prevPoint, prevExtrusionVector, prevLength);
- addLineVertex(rVertices, rExtrusionVectors, currPoint, currExtrusionVector, currLength);
-}
+ float angle = std::atan2(previous.x * next.y - previous.y * next.x,
+ previous.x * next.x + previous.y * next.y);
-inline glm::vec2 normalize(const glm::vec2& vector)
-{
- if (glm::length(vector) > 0.0)
- return glm::normalize(vector);
- return vector;
+ return F_PI - std::fabs(angle);
}
}} // end vcl::vertex
diff --git a/vcl/inc/opengl/program.hxx b/vcl/inc/opengl/program.hxx
index c737c1250aaa..b32aa05f250e 100644
--- a/vcl/inc/opengl/program.hxx
+++ b/vcl/inc/opengl/program.hxx
@@ -22,7 +22,6 @@
#include <tools/color.hxx>
#include <opengl/texture.hxx>
-#include <glm/glm.hpp>
#include <unordered_map>
typedef std::unordered_map< OString, GLuint, OStringHash > UniformCache;
@@ -82,7 +81,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 SetVertexColors(std::vector<GLubyte>& rColorVector);
void SetUniform1f( const OString& rName, GLfloat v1 );
void SetUniform2f( const OString& rName, GLfloat v1, GLfloat v2 );
@@ -107,11 +106,16 @@ public:
bool DrawTexture( const OpenGLTexture& rTexture );
- void DrawArrays(GLenum GLenum, std::vector<GLfloat>& aVertices);
+ void DrawArrays(GLenum aMode, std::vector<GLfloat>& aVertices);
+ void DrawElements(GLenum aMode, GLuint nNumberOfVertices);
-protected:
bool EnableVertexAttrib(GLuint& rAttrib, const OString& rName);
- void SetVertexAttrib( GLuint& rAttrib, const OString& rName, const GLvoid* pData, GLint nSize = 2 );
+
+ void SetVertexAttrib(GLuint& rAttrib, const OString& rName, GLint nSize,
+ GLenum eType, GLboolean bNormalized, GLsizei aStride,
+ const GLvoid* pPointer);
+
+protected:
GLuint GetUniformLocation( const OString& rName );
};
diff --git a/vcl/inc/openglgdiimpl.hxx b/vcl/inc/openglgdiimpl.hxx
index 2c8d47c9b33d..d0b5f9aa478a 100644
--- a/vcl/inc/openglgdiimpl.hxx
+++ b/vcl/inc/openglgdiimpl.hxx
@@ -127,8 +127,6 @@ public:
void DrawRect( const Rectangle& rRect );
void DrawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry );
void DrawLineSegment(float x1, float y1, float x2, float y2);
- void DrawLineCap(float x1, float y1, float x2, float y2, css::drawing::LineCap eLineCap, float fLineWidth);
- void DrawPolyLine( const basegfx::B2DPolygon& rPolygon, float fLineWidth, basegfx::B2DLineJoin eLineJoin, css::drawing::LineCap eLineCap, float fMiterMinimumAngle);
void DrawPolyPolygon( const basegfx::B2DPolyPolygon& rPolyPolygon, bool blockAA = false );
void DrawRegionBand( const RegionBand& rRegion );
void DrawTextureRect( OpenGLTexture& rTexture, const SalTwoRect& rPosAry, bool bInverted = false );
@@ -143,7 +141,9 @@ public:
void DrawAxialGradient( const Gradient& rGradient, const Rectangle& rRect );
void DrawRadialGradient( const Gradient& rGradient, const Rectangle& rRect );
void DeferredTextDraw(OpenGLTexture& rTexture, const SalColor nMaskColor, const SalTwoRect& rPosAry);
+
void FlushDeferredDrawing();
+ bool FlushLinesOrTriangles(DrawShaderType eType, RenderParameters& rParameters);
public:
// get the width of the device