[Libreoffice-commits] core.git: 6 commits - vcl/inc vcl/Library_vcl.mk vcl/opengl

Tomaž Vajngerl tomaz.vajngerl at collabora.co.uk
Wed Jun 8 02:39:56 UTC 2016


 vcl/Library_vcl.mk                            |    1 
 vcl/inc/opengl/AccumulatedTextures.hxx        |  118 -------
 vcl/inc/opengl/RenderList.hxx                 |  163 ++++++++++
 vcl/inc/opengl/VertexUtils.hxx                |  138 ++++++++
 vcl/inc/opengl/program.hxx                    |    6 
 vcl/inc/opengl/texture.hxx                    |    6 
 vcl/inc/openglgdiimpl.hxx                     |    8 
 vcl/opengl/RenderList.cxx                     |  244 +++++++++++++++
 vcl/opengl/combinedFragmentShader.glsl        |   17 -
 vcl/opengl/combinedTextureFragmentShader.glsl |    7 
 vcl/opengl/combinedTextureVertexShader.glsl   |    9 
 vcl/opengl/combinedVertexShader.glsl          |    9 
 vcl/opengl/gdiimpl.cxx                        |  417 +++++++++-----------------
 vcl/opengl/program.cxx                        |   12 
 vcl/opengl/texture.cxx                        |   52 +--
 15 files changed, 794 insertions(+), 413 deletions(-)

New commits:
commit b2179939dea723ea8695018b03903b9e85121771
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Tue May 31 16:15:21 2016 +0900

    opengl: improve overlap tracking
    
    Insteado of tracking the overlap with only one rectangle use more
    rectangles and add elements to the rectangle that increases the
    combined area the least. If a new entry overlaps with at least
    on rectangle then create a new list. Current limit the number of
    rectangles to 30.
    
    Change-Id: I3db619afc1fdd98fe7314c930e909bf2c93d7b2c

diff --git a/vcl/inc/opengl/RenderList.hxx b/vcl/inc/opengl/RenderList.hxx
index 32ece73..e63f5dc 100644
--- a/vcl/inc/opengl/RenderList.hxx
+++ b/vcl/inc/opengl/RenderList.hxx
@@ -38,6 +38,8 @@ struct RenderTextureParameters
 
 struct RenderEntry
 {
+    basegfx::B2DRange maOverlapTrackingRectangle;
+
     RenderParameters maTriangleParameters;
     RenderParameters maLineParameters;
     RenderParameters maLineAAParameters;
@@ -68,19 +70,59 @@ struct RenderEntry
 class RenderList
 {
 private:
-    basegfx::B2DRange maOverlapTrackingRectangle;
     std::vector<RenderEntry> maRenderEntries;
+    std::vector<basegfx::B2DRange> maRectangles;
+
+    bool doesOverlap(const basegfx::B2DRange& rDrawRectangle)
+    {
+        if (!maRenderEntries.back().maOverlapTrackingRectangle.overlaps(rDrawRectangle))
+            return false;
+
+        for (const basegfx::B2DRange& rRectangle : maRectangles)
+        {
+            if (rRectangle.overlaps(rDrawRectangle))
+                return true;
+        }
+        return false;
+    }
 
     void checkOverlapping(const basegfx::B2DRange& rDrawRectangle)
     {
-        if (maRenderEntries.empty() || maOverlapTrackingRectangle.overlaps(rDrawRectangle))
+        if (maRenderEntries.empty() || doesOverlap(rDrawRectangle))
         {
             maRenderEntries.resize(maRenderEntries.size() + 1);
-            maOverlapTrackingRectangle = rDrawRectangle;
+            maRenderEntries.back().maOverlapTrackingRectangle = rDrawRectangle;
+
+            maRectangles.clear();
+            maRectangles.reserve(30);
+            maRectangles.push_back(rDrawRectangle);
         }
         else
         {
-            maOverlapTrackingRectangle.expand(rDrawRectangle);
+            maRenderEntries.back().maOverlapTrackingRectangle.expand(rDrawRectangle);
+
+            if (maRectangles.size() < 30)
+            {
+                maRectangles.push_back(rDrawRectangle);
+            }
+            else
+            {
+                basegfx::B2DRange aTempRectangle(maRectangles[0]);
+                aTempRectangle.expand(rDrawRectangle);
+                double minArea = aTempRectangle.getWidth() * aTempRectangle.getHeight();
+                size_t index = 0;
+
+                double area;
+                for (size_t i = 1; i < maRectangles.size(); ++i)
+                {
+                    aTempRectangle = basegfx::B2DRange(maRectangles[i]);
+                    aTempRectangle.expand(rDrawRectangle);
+                    area = aTempRectangle.getWidth() * aTempRectangle.getHeight();
+                    if (area < minArea)
+                        index = i;
+                }
+                maRectangles[index].expand(rDrawRectangle);
+            }
         }
     }
 
@@ -96,7 +138,6 @@ public:
     void clear()
     {
         maRenderEntries.clear();
-        maOverlapTrackingRectangle.reset();
     }
 
     std::vector<RenderEntry>& getEntries()
commit 18260a0d9a381a105ffb032ee8f1050c77062102
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Tue May 31 12:26:04 2016 +0900

    opengl: deferred texture drawing in RenderList, add drawAlphaRect
    
    Drawing accumulated textures (in Accumulatedtextures) is independent
    of drawing with render list which causes problems with rendering
    order when render list and accumulated textures are flushed. To
    solve this we need to combine both so we can check for overlapped
    drawing.
    
    Previously drawRect was using RenderList batch drawing but not
    drawAlphaRect which is essentially the same as drawRect but
    additionally supports alpha value. This adds support to draw
    alpha rectangles to RenderList and converts drawAlphaRect.
    
    Change-Id: I82bf0b410e5ebabb13bab7b29a2e53a6fdaa404f

diff --git a/vcl/inc/opengl/AccumulatedTextures.hxx b/vcl/inc/opengl/AccumulatedTextures.hxx
deleted file mode 100644
index 504cf6a..0000000
--- a/vcl/inc/opengl/AccumulatedTextures.hxx
+++ /dev/null
@@ -1,99 +0,0 @@
-/* -*- 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_ACCUMULATEDTEXTURES_H
-#define INCLUDED_VCL_INC_OPENGL_ACCUMULATEDTEXTURES_H
-
-#include <vcl/opengl/OpenGLHelper.hxx>
-
-#include <o3tl/make_unique.hxx>
-#include "opengl/texture.hxx"
-#include "opengl/VertexUtils.hxx"
-#include <memory>
-
-struct TextureDrawParameters
-{
-    std::vector<GLfloat> maVertices;
-    std::vector<GLfloat> maTextureCoords;
-};
-
-struct AccumulatedTexturesEntry
-{
-    OpenGLTexture maTexture;
-    std::unordered_map<SalColor, TextureDrawParameters> maColorTextureDrawParametersMap;
-
-    AccumulatedTexturesEntry(const OpenGLTexture& rTexture)
-        : maTexture(rTexture)
-    {}
-
-    void insert(const OpenGLTexture& rTexture, const SalColor& aColor, const SalTwoRect& r2Rect)
-    {
-        TextureDrawParameters& aDrawParameters = maColorTextureDrawParametersMap[aColor];
-        rTexture.FillCoords<GL_TRIANGLES>(aDrawParameters.maTextureCoords, r2Rect, false);
-
-        GLfloat fX1 = r2Rect.mnDestX;
-        GLfloat fY1 = r2Rect.mnDestY;
-        GLfloat fX2 = fX1 + r2Rect.mnDestWidth;
-        GLfloat fY2 = fY1 + r2Rect.mnDestHeight;
-
-        std::vector<GLfloat>& rVertices = aDrawParameters.maVertices;
-        vcl::vertex::addRectangle<GL_TRIANGLES>(rVertices, fX1, fY1, fX2, fY2);
-    }
-};
-
-class AccumulatedTextures
-{
-private:
-    typedef std::unordered_map<GLuint, std::unique_ptr<AccumulatedTexturesEntry>> AccumulatedTexturesMap;
-
-    AccumulatedTexturesMap maEntries;
-
-public:
-    AccumulatedTextures()
-    {}
-
-    bool empty()
-    {
-        return maEntries.empty();
-    }
-
-    void clear()
-    {
-        maEntries.clear();
-    }
-
-    bool insert(OpenGLTexture& rTexture, const SalColor& aColor, const SalTwoRect& r2Rect)
-    {
-        if (!rTexture)
-            return false;
-
-        GLuint nTextureId = rTexture.Id();
-
-        if (maEntries.find(nTextureId) == maEntries.end())
-        {
-            OpenGLTexture aWholeTexture(rTexture.GetWholeTexture());
-            maEntries[nTextureId] = o3tl::make_unique<AccumulatedTexturesEntry>(aWholeTexture);
-        }
-
-        std::unique_ptr<AccumulatedTexturesEntry>& rEntry = maEntries[nTextureId];
-        rEntry->insert(rTexture, aColor, r2Rect);
-
-        return true;
-    }
-
-    AccumulatedTexturesMap& getAccumulatedTexturesMap()
-    {
-        return maEntries;
-    }
-};
-
-#endif // INCLUDED_VCL_INC_OPENGL_ACCUMULATEDTEXTURES_H
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/opengl/RenderList.hxx b/vcl/inc/opengl/RenderList.hxx
index d533ad4..32ece73 100644
--- a/vcl/inc/opengl/RenderList.hxx
+++ b/vcl/inc/opengl/RenderList.hxx
@@ -11,12 +11,16 @@
 #ifndef INCLUDED_VCL_INC_OPENGL_RENDERLIST_H
 #define INCLUDED_VCL_INC_OPENGL_RENDERLIST_H
 
+#include <unordered_map>
+
 #include <glm/glm.hpp>
 
 #include <vcl/opengl/OpenGLHelper.hxx>
 #include <vcl/salgtype.hxx>
 #include <basegfx/range/b2drange.hxx>
 
+#include "opengl/texture.hxx"
+
 struct RenderParameters
 {
     std::vector<GLfloat>   maVertices;
@@ -24,12 +28,22 @@ struct RenderParameters
     std::vector<glm::vec4> maColors;
 };
 
+struct RenderTextureParameters
+{
+    std::vector<GLfloat>   maVertices;
+    std::vector<glm::vec4> maColors;
+    std::vector<GLfloat>   maTextureCoords;
+    OpenGLTexture          maTexture;
+};
+
 struct RenderEntry
 {
     RenderParameters maTriangleParameters;
     RenderParameters maLineParameters;
     RenderParameters maLineAAParameters;
 
+    std::unordered_map<GLuint, RenderTextureParameters> maTextureParametersMap;
+
     bool hasTriangles()
     {
         return !maTriangleParameters.maVertices.empty();
@@ -44,6 +58,11 @@ struct RenderEntry
     {
         return !maLineAAParameters.maVertices.empty();
     }
+
+    bool hasTextures()
+    {
+        return !maTextureParametersMap.empty();
+    }
 };
 
 class RenderList
@@ -85,9 +104,11 @@ public:
         return maRenderEntries;
     }
 
+    bool addDrawTextureWithMaskColor(OpenGLTexture& rTexture, const SalColor& rColor, const SalTwoRect& r2Rect);
+
     void addDrawPixel(long nX, long nY, const SalColor& rColor);
 
-    void addDrawRectangle(long nX, long nY, long nWidth, long nHeight,
+    void addDrawRectangle(long nX, long nY, long nWidth, long nHeight, double fTransparency,
                           const SalColor& rLineColor, const SalColor& rFillColor);
 
     void addDrawLine(long nX1, long nY1, long nX2, long nY2, const SalColor& rLineColor, bool bUseAA);
diff --git a/vcl/inc/openglgdiimpl.hxx b/vcl/inc/openglgdiimpl.hxx
index 09343c8..2c8d47c9 100644
--- a/vcl/inc/openglgdiimpl.hxx
+++ b/vcl/inc/openglgdiimpl.hxx
@@ -29,7 +29,6 @@
 #include "opengl/framebuffer.hxx"
 #include "opengl/program.hxx"
 #include "opengl/texture.hxx"
-#include "opengl/AccumulatedTextures.hxx"
 #include "opengl/RenderList.hxx"
 
 #include <memory>
@@ -101,7 +100,6 @@ protected:
     SalColor mProgramSolidColor;
     double mProgramSolidTransparency;
 
-    std::unique_ptr<AccumulatedTextures>  mpAccumulatedTextures;
     std::unique_ptr<RenderList> mpRenderList;
 
     void ImplInitClipRegion();
diff --git a/vcl/opengl/RenderList.cxx b/vcl/opengl/RenderList.cxx
index de5a9d6..8188319 100644
--- a/vcl/opengl/RenderList.cxx
+++ b/vcl/opengl/RenderList.cxx
@@ -52,10 +52,13 @@ void RenderList::addDrawPixel(long nX, long nY, const SalColor& rColor)
     vcl::vertex::addQuadEmptyExtrusionVectors<GL_TRIANGLES>(rRenderParameter.maExtrusionVectors);
 }
 
-void RenderList::addDrawRectangle(long nX, long nY, long nWidth, long nHeight, const SalColor& rLineColor, const SalColor& rFillColor)
+void RenderList::addDrawRectangle(long nX, long nY, long nWidth, long nHeight, double fTransparency,
+                                  const SalColor& rLineColor, const SalColor& rFillColor)
 {
     if (rLineColor == SALCOLOR_NONE && rFillColor == SALCOLOR_NONE)
         return;
+    if (fTransparency == 1.0f)
+        return;
 
     GLfloat fX1(nX);
     GLfloat fY1(nY);
@@ -74,10 +77,10 @@ void RenderList::addDrawRectangle(long nX, long nY, long nWidth, long nHeight, c
         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::addQuadColors<GL_TRIANGLES>(rRenderParameter.maColors, rLineColor, fTransparency);
+        vcl::vertex::addQuadColors<GL_TRIANGLES>(rRenderParameter.maColors, rLineColor, fTransparency);
+        vcl::vertex::addQuadColors<GL_TRIANGLES>(rRenderParameter.maColors, rLineColor, fTransparency);
+        vcl::vertex::addQuadColors<GL_TRIANGLES>(rRenderParameter.maColors, rLineColor, fTransparency);
 
         vcl::vertex::addQuadEmptyExtrusionVectors<GL_TRIANGLES>(rRenderParameter.maExtrusionVectors);
         vcl::vertex::addQuadEmptyExtrusionVectors<GL_TRIANGLES>(rRenderParameter.maExtrusionVectors);
@@ -95,10 +98,10 @@ void RenderList::addDrawRectangle(long nX, long nY, long nWidth, long nHeight, c
             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::addQuadColors<GL_TRIANGLES>(rRenderParameter.maColors, rFillColor, fTransparency);
+            vcl::vertex::addQuadColors<GL_TRIANGLES>(rRenderParameter.maColors, rFillColor, fTransparency);
+            vcl::vertex::addQuadColors<GL_TRIANGLES>(rRenderParameter.maColors, rFillColor, fTransparency);
+            vcl::vertex::addQuadColors<GL_TRIANGLES>(rRenderParameter.maColors, rFillColor, fTransparency);
 
             vcl::vertex::addQuadEmptyExtrusionVectors<GL_TRIANGLES>(rRenderParameter.maExtrusionVectors);
             vcl::vertex::addQuadEmptyExtrusionVectors<GL_TRIANGLES>(rRenderParameter.maExtrusionVectors);
@@ -107,7 +110,7 @@ void RenderList::addDrawRectangle(long nX, long nY, long nWidth, long nHeight, c
         }
         // 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::addQuadColors<GL_TRIANGLES>(rRenderParameter.maColors, rFillColor, fTransparency);
         vcl::vertex::addQuadEmptyExtrusionVectors<GL_TRIANGLES>(rRenderParameter.maExtrusionVectors);
     }
 }
@@ -213,4 +216,29 @@ void RenderList::addDrawPolyPolygon(const basegfx::B2DPolyPolygon& rPolyPolygon,
     }
 }
 
+bool RenderList::addDrawTextureWithMaskColor(OpenGLTexture& rTexture, const SalColor& rColor, const SalTwoRect& r2Rect)
+{
+    if (!rTexture)
+        return false;
+
+    GLfloat fX1 = r2Rect.mnDestX;
+    GLfloat fY1 = r2Rect.mnDestY;
+    GLfloat fX2 = fX1 + r2Rect.mnDestWidth;
+    GLfloat fY2 = fY1 + r2Rect.mnDestHeight;
+
+    checkOverlapping(basegfx::B2DRange(fX1, fY1, fX2, fY2));
+
+    GLuint nTextureId = rTexture.Id();
+
+    RenderTextureParameters& rTextureParameter = maRenderEntries.back().maTextureParametersMap[nTextureId];
+    rTextureParameter.maTexture = rTexture;
+
+    rTexture.FillCoords<GL_TRIANGLES>(rTextureParameter.maTextureCoords, r2Rect, false);
+
+    vcl::vertex::addRectangle<GL_TRIANGLES>(rTextureParameter.maVertices, fX1, fY1, fX2, fY2);
+    vcl::vertex::addQuadColors<GL_TRIANGLES>(rTextureParameter.maColors, rColor, 0.0f);
+
+    return true;
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/opengl/combinedTextureFragmentShader.glsl b/vcl/opengl/combinedTextureFragmentShader.glsl
index d8864cf..67797be 100644
--- a/vcl/opengl/combinedTextureFragmentShader.glsl
+++ b/vcl/opengl/combinedTextureFragmentShader.glsl
@@ -10,6 +10,9 @@
 varying vec2 tex_coord;
 varying vec2 alpha_coord;
 varying vec2 mask_coord;
+#ifdef USE_VERTEX_COLORS
+varying vec4 vertex_color;
+#endif
 
 uniform sampler2D texture;
 uniform sampler2D mask;
@@ -56,7 +59,11 @@ void main()
     }
     else if (type == TYPE_MASKED_COLOR)
     {
+#ifdef USE_VERTEX_COLORS
+        gl_FragColor = vertex_color;
+#else
         gl_FragColor = color;
+#endif
         gl_FragColor.a = 1.0 - texelTexture.r;
     }
 }
diff --git a/vcl/opengl/combinedTextureVertexShader.glsl b/vcl/opengl/combinedTextureVertexShader.glsl
index 883ec63..3086806 100644
--- a/vcl/opengl/combinedTextureVertexShader.glsl
+++ b/vcl/opengl/combinedTextureVertexShader.glsl
@@ -11,10 +11,16 @@ attribute vec4 position;
 attribute vec2 tex_coord_in;
 attribute vec2 mask_coord_in;
 attribute vec2 alpha_coord_in;
+#ifdef USE_VERTEX_COLORS
+attribute vec4 vertex_color_in;
+#endif
 
 varying vec2 tex_coord;
 varying vec2 mask_coord;
 varying vec2 alpha_coord;
+#ifdef USE_VERTEX_COLORS
+varying vec4 vertex_color;
+#endif
 
 uniform mat4 mvp;
 uniform mat4 transform;
@@ -27,6 +33,9 @@ void main()
    tex_coord = tex_coord_in;
    mask_coord = mask_coord_in;
    alpha_coord = alpha_coord_in;
+#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 0d939e3..245c468 100644
--- a/vcl/opengl/gdiimpl.cxx
+++ b/vcl/opengl/gdiimpl.cxx
@@ -84,7 +84,6 @@ OpenGLSalGraphicsImpl::OpenGLSalGraphicsImpl(SalGraphics& rParent, SalGeometryPr
     , mnDrawCountAtFlush(0)
     , mProgramSolidColor(SALCOLOR_NONE)
     , mProgramSolidTransparency(0.0)
-    , mpAccumulatedTextures(new AccumulatedTextures)
     , mpRenderList(new RenderList)
 {
 }
@@ -1501,107 +1500,90 @@ void OpenGLSalGraphicsImpl::DrawMask( OpenGLTexture& rMask, SalColor nMaskColor,
 
 void OpenGLSalGraphicsImpl::DeferredTextDraw(OpenGLTexture& rTexture, SalColor aMaskColor, const SalTwoRect& rPosAry)
 {
-    mpAccumulatedTextures->insert(rTexture, aMaskColor, rPosAry);
+    mpRenderList->addDrawTextureWithMaskColor(rTexture, aMaskColor, rPosAry);
 }
 
 void OpenGLSalGraphicsImpl::FlushDeferredDrawing()
 {
-    if (mpAccumulatedTextures->empty() && mpRenderList->empty())
+    if (mpRenderList->empty())
         return;
 
     VCL_GL_INFO("FlushDeferredDrawing: " << mpRenderList->getEntries().size());
 
-    if (!mpAccumulatedTextures->empty())
-    {
-        InitializePreDrawState();
-
-        OpenGLZone aZone;
+    InitializePreDrawState(XOROption::IMPLEMENT_XOR);
 
-        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())
+    OpenGLZone aZone;
+    for (RenderEntry& rRenderEntry : mpRenderList->getEntries())
+    {
+        if (rRenderEntry.hasTriangles() && UseProgram("combinedVertexShader", "combinedFragmentShader", "#define USE_VERTEX_COLORS"))
         {
-            OpenGLTexture& rTexture = rPair.second->maTexture;
-            mpProgram->SetTexture("texture", rTexture);
-            for (auto& rColorTwoRectPair: rPair.second->maColorTextureDrawParametersMap)
+            RenderParameters& rParameters = rRenderEntry.maTriangleParameters;
+            VCL_GL_INFO("Flush Triangles: " << rParameters.maVertices.size());
+            mpProgram->SetShaderType(DrawShaderType::Normal);
+            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.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();
+        }
+        if (rRenderEntry.hasTextures() && UseProgram("combinedTextureVertexShader", "combinedTextureFragmentShader", "#define USE_VERTEX_COLORS"))
+        {
+            mpProgram->SetShaderType(TextureShaderType::MaskedColor);
+            mpProgram->SetIdentityTransform("transform");
+            mpProgram->SetBlendMode(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+            for (auto& rPair : rRenderEntry.maTextureParametersMap)
             {
-                mpProgram->SetColor("color", rColorTwoRectPair.first, 0);
-                TextureDrawParameters& rParameters = rColorTwoRectPair.second;
+                RenderTextureParameters& rParameters = rPair.second;
+                mpProgram->SetTexture("texture", rParameters.maTexture);
                 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();
-    }
-
-    if (!mpRenderList->empty())
-    {
-        InitializePreDrawState(XOROption::IMPLEMENT_XOR);
-
-        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);
-                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.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();
             }
+            mpProgram->Clean();
         }
-
-        mpRenderList->clear();
-        PostDraw();
     }
 
-    VCL_GL_INFO("End FlushDeferredDrawing");
+    mpRenderList->clear();
+    PostDraw();
 
+    VCL_GL_INFO("End FlushDeferredDrawing");
 }
 
 void OpenGLSalGraphicsImpl::DrawLinearGradient( const Gradient& rGradient, const Rectangle& rRect )
@@ -1731,7 +1713,7 @@ void OpenGLSalGraphicsImpl::drawLine(long nX1, long nY1, long nX2, long nY2)
 void OpenGLSalGraphicsImpl::drawRect( long nX, long nY, long nWidth, long nHeight )
 {
     VCL_GL_INFO("::drawRect (" << nX << ", " << nY << ") [" << nWidth << ", " << nHeight << "]");
-    mpRenderList->addDrawRectangle(nX, nY, nWidth, nHeight, mnLineColor, mnFillColor);
+    mpRenderList->addDrawRectangle(nX, nY, nWidth, nHeight, 0.0, mnLineColor, mnFillColor);
 }
 
 void OpenGLSalGraphicsImpl::drawPolyLine( sal_uInt32 nPoints, const SalPoint* pPtAry )
@@ -1925,17 +1907,11 @@ void OpenGLSalGraphicsImpl::drawMask(
             const SalBitmap& rSalBitmap,
             SalColor nMaskColor )
 {
-    assert(dynamic_cast<const OpenGLSalBitmap*>(&rSalBitmap));
-
-    OpenGLZone aZone;
+    VCL_GL_INFO("::drawMask");
 
+    assert(dynamic_cast<const OpenGLSalBitmap*>(&rSalBitmap));
     const OpenGLSalBitmap& rBitmap = static_cast<const OpenGLSalBitmap&>(rSalBitmap);
-    OpenGLTexture& rTexture( rBitmap.GetTexture() );
-
-    VCL_GL_INFO( "::drawMask" );
-    PreDraw();
-    DrawMask( rTexture, nMaskColor, rPosAry );
-    PostDraw();
+    mpRenderList->addDrawTextureWithMaskColor(rBitmap.GetTexture(), nMaskColor, rPosAry);
 }
 
 SalBitmap* OpenGLSalGraphicsImpl::getBitmap( long nX, long nY, long nWidth, long nHeight )
@@ -2151,15 +2127,8 @@ bool OpenGLSalGraphicsImpl::drawAlphaRect(
                 long nWidth, long nHeight,
                 sal_uInt8 nTransparency )
 {
-    VCL_GL_INFO( "::drawAlphaRect" );
-    if( mnFillColor != SALCOLOR_NONE && nTransparency < 100 )
-    {
-        PreDraw();
-        UseSolid( mnFillColor, nTransparency );
-        DrawRect( nX, nY, nWidth, nHeight );
-        PostDraw();
-    }
-
+    VCL_GL_INFO("::drawAlphaRect (" << nX << ", " << nY << ") [" << nWidth << ", " << nHeight << "]");
+    mpRenderList->addDrawRectangle(nX, nY, nWidth, nHeight, double(nTransparency / 100.0), mnLineColor, mnFillColor);
     return true;
 }
 
commit bb157523310eb237dc16818f24df58d110242367
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Tue May 31 12:04:03 2016 +0900

    opengl: fix transparency when drawing polypolygons
    
    Change-Id: I963b1bbf322acb20bf4e21834ba9c7ae400eaf7d

diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx
index 60ffc32..0d939e3 100644
--- a/vcl/opengl/gdiimpl.cxx
+++ b/vcl/opengl/gdiimpl.cxx
@@ -1556,6 +1556,7 @@ void OpenGLSalGraphicsImpl::FlushDeferredDrawing()
                 RenderParameters& rParameters = rRenderEntry.maTriangleParameters;
                 VCL_GL_INFO("Flush Triangles: " << rParameters.maVertices.size());
                 mpProgram->SetShaderType(DrawShaderType::Normal);
+                mpProgram->SetBlendMode(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
                 ApplyProgramMatrices(0.5f);
                 mpProgram->SetExtrusionVectors(rParameters.maExtrusionVectors.data());
                 mpProgram->SetVertexColors(rParameters.maColors);
@@ -1735,6 +1736,7 @@ void OpenGLSalGraphicsImpl::drawRect( long nX, long nY, long nWidth, long nHeigh
 
 void OpenGLSalGraphicsImpl::drawPolyLine( sal_uInt32 nPoints, const SalPoint* pPtAry )
 {
+    VCL_GL_INFO("::drawPolyLine legacy -> redirecting to drawPolyLine");
     basegfx::B2DPolygon aPoly;
     aPoly.append(basegfx::B2DPoint(pPtAry->mnX, pPtAry->mnY), nPoints);
     for (sal_uInt32 i = 1; i < nPoints; ++i)
@@ -1747,6 +1749,7 @@ void OpenGLSalGraphicsImpl::drawPolyLine( sal_uInt32 nPoints, const SalPoint* pP
 
 void OpenGLSalGraphicsImpl::drawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry )
 {
+    VCL_GL_INFO("::drawPolygon legacy -> redirecting to drawPolyPolygon with transparency");
     basegfx::B2DPolygon aPoly;
     aPoly.append(basegfx::B2DPoint(pPtAry->mnX, pPtAry->mnY), nPoints);
     for (sal_uInt32 i = 1; i < nPoints; ++i)
@@ -1757,6 +1760,7 @@ void OpenGLSalGraphicsImpl::drawPolygon( sal_uInt32 nPoints, const SalPoint* pPt
 
 void OpenGLSalGraphicsImpl::drawPolyPolygon( sal_uInt32 nPoly, const sal_uInt32* pPointCounts, PCONSTSALPOINT* pPtAry )
 {
+    VCL_GL_INFO("::drawPolyPolygon legacy -> redirecting to drawPolyPolygon with transparency");
     basegfx::B2DPolyPolygon aPolyPoly;
     for(sal_uInt32 nPolygon = 0; nPolygon < nPoly; ++nPolygon)
     {
commit 2003076c4318511a3d621558d3b44b4e8e6c6529
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Sun May 29 15:36:39 2016 +0900

    opengl: batch draw polypolygons
    
    Change-Id: Ie9c41f95815a57c3a9e68ce7b7b0c1e09291988b

diff --git a/vcl/inc/opengl/RenderList.hxx b/vcl/inc/opengl/RenderList.hxx
index 0ba977a..d533ad4 100644
--- a/vcl/inc/opengl/RenderList.hxx
+++ b/vcl/inc/opengl/RenderList.hxx
@@ -91,6 +91,9 @@ public:
                           const SalColor& rLineColor, const SalColor& rFillColor);
 
     void addDrawLine(long nX1, long nY1, long nX2, long nY2, const SalColor& rLineColor, bool bUseAA);
+
+    void addDrawPolyPolygon(const basegfx::B2DPolyPolygon& rPolyPolygon, double fTransparency,
+                            const SalColor& rLineColor, const SalColor& rFillColor, bool bUseAA);
 };
 
 #endif // INCLUDED_VCL_INC_OPENGL_RENDERLIST_H
diff --git a/vcl/inc/opengl/VertexUtils.hxx b/vcl/inc/opengl/VertexUtils.hxx
index c64340b..d99998c 100644
--- a/vcl/inc/opengl/VertexUtils.hxx
+++ b/vcl/inc/opengl/VertexUtils.hxx
@@ -39,6 +39,20 @@ 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)
+{
+    rVertices.insert(rVertices.end(), {
+        x1, y1, x2, y2, x3, y3,
+        x3, y3, x2, y2, x4, y4
+    });
+}
+
 inline glm::vec4 createGLColor(const SalColor& rColor, GLfloat rTransparency)
 {
     return glm::vec4(SALCOLOR_RED(rColor)   / 255.0f,
diff --git a/vcl/opengl/RenderList.cxx b/vcl/opengl/RenderList.cxx
index 008be02..de5a9d6 100644
--- a/vcl/opengl/RenderList.cxx
+++ b/vcl/opengl/RenderList.cxx
@@ -11,6 +11,11 @@
 #include "opengl/RenderList.hxx"
 #include "opengl/VertexUtils.hxx"
 
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolygontriangulator.hxx>
+#include <basegfx/polygon/b2dpolypolygoncutter.hxx>
+#include <basegfx/polygon/b2dtrapezoid.hxx>
+
 namespace
 {
 
@@ -119,4 +124,93 @@ void RenderList::addDrawLine(long nX1, long nY1, long nX2, long nY2, const SalCo
     lclAddLineSegmentVertices(rRenderParameter, nX1, nY1, nX2, nY2, rLineColor, 0.0f);
 }
 
+void RenderList::addDrawPolyPolygon(const basegfx::B2DPolyPolygon& rPolyPolygon, double fTransparency,
+                        const SalColor& rLineColor, const SalColor& rFillColor, bool bUseAA)
+{
+    if (rPolyPolygon.count() <= 0)
+        return;
+    if (rLineColor == SALCOLOR_NONE && rFillColor == SALCOLOR_NONE)
+        return;
+    if (fTransparency == 1.0)
+        return;
+
+    checkOverlapping(rPolyPolygon.getB2DRange());
+
+    RenderParameters& rLineParameter = maRenderEntries.back().maLineParameters;
+    RenderParameters& rLineAAParameter = maRenderEntries.back().maLineAAParameters;
+
+    if (rFillColor != SALCOLOR_NONE)
+    {
+        RenderParameters& rTriangleParameter = maRenderEntries.back().maTriangleParameters;
+
+        const basegfx::B2DPolyPolygon& aSimplePolyPolygon = ::basegfx::tools::solveCrossovers(rPolyPolygon);
+        basegfx::B2DTrapezoidVector aTrapezoidVector;
+        basegfx::tools::trapezoidSubdivide(aTrapezoidVector, aSimplePolyPolygon);
+
+        if (!aTrapezoidVector.empty())
+        {
+            for (basegfx::B2DTrapezoid & rTrapezoid : aTrapezoidVector)
+            {
+                GLfloat topX1 = rTrapezoid.getTopXLeft();
+                GLfloat topX2 = rTrapezoid.getTopXRight();
+                GLfloat topY  = rTrapezoid.getTopY();
+
+                GLfloat bottomX1 = rTrapezoid.getBottomXLeft();
+                GLfloat bottomX2 = rTrapezoid.getBottomXRight();
+                GLfloat bottomY  = rTrapezoid.getBottomY();
+
+                vcl::vertex::addTrapezoid<GL_TRIANGLES>(rTriangleParameter.maVertices,
+                                                         topX1,    topY,
+                                                         topX2,    topY,
+                                                         bottomX1, bottomY,
+                                                         bottomX2, bottomY);
+                vcl::vertex::addQuadColors<GL_TRIANGLES>(rTriangleParameter.maColors, rFillColor, fTransparency);
+                vcl::vertex::addQuadEmptyExtrusionVectors<GL_TRIANGLES>(rTriangleParameter.maExtrusionVectors);
+
+                if (bUseAA)
+                {
+                    lclAddLineSegmentVertices(rLineAAParameter, topX1, topY, topX2, topY,
+                                              rFillColor, fTransparency);
+                    lclAddLineSegmentVertices(rLineAAParameter, topX2, topY, bottomX2, bottomY,
+                                              rFillColor, fTransparency);
+                    lclAddLineSegmentVertices(rLineAAParameter, bottomX2, bottomY, bottomX1, bottomY,
+                                              rFillColor, fTransparency);
+                    lclAddLineSegmentVertices(rLineAAParameter, bottomX1, bottomY, topX1, topY,
+                                              rFillColor, fTransparency);
+                }
+            }
+        }
+    }
+
+    if (rLineColor != SALCOLOR_NONE && rLineColor != rFillColor)
+    {
+        RenderParameters& rParameter = bUseAA ? rLineAAParameter : rLineParameter;
+
+        for (const basegfx::B2DPolygon& rPolygon : rPolyPolygon)
+        {
+            basegfx::B2DPolygon aPolygon(rPolygon);
+            if (rPolygon.areControlPointsUsed())
+                aPolygon = rPolygon.getDefaultAdaptiveSubdivision();
+
+            sal_uInt32 nPoints = aPolygon.count();
+
+            GLfloat x1, y1, x2, y2;
+            sal_uInt32 index1, index2;
+
+            for (sal_uInt32 i = 0; i <= nPoints; ++i)
+            {
+                index1 = (i)     % nPoints;
+                index2 = (i + 1) % nPoints;
+
+                x1 = aPolygon.getB2DPoint(index1).getX();
+                y1 = aPolygon.getB2DPoint(index1).getY();
+                x2 = aPolygon.getB2DPoint(index2).getX();
+                y2 = aPolygon.getB2DPoint(index2).getY();
+
+                lclAddLineSegmentVertices(rParameter, x1, y1, x2, y2, rLineColor, fTransparency);
+            }
+        }
+    }
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx
index fe2151e..60ffc32 100644
--- a/vcl/opengl/gdiimpl.cxx
+++ b/vcl/opengl/gdiimpl.cxx
@@ -1776,27 +1776,10 @@ void OpenGLSalGraphicsImpl::drawPolyPolygon( sal_uInt32 nPoly, const sal_uInt32*
     drawPolyPolygon(aPolyPoly, 0.0);
 }
 
-bool OpenGLSalGraphicsImpl::drawPolyPolygon( const basegfx::B2DPolyPolygon& rPolyPolygon, double fTransparency )
+bool OpenGLSalGraphicsImpl::drawPolyPolygon(const basegfx::B2DPolyPolygon& rPolyPolygon, double fTransparency)
 {
-    VCL_GL_INFO( "::drawPolyPolygon trans " << fTransparency );
-    if( rPolyPolygon.count() <= 0 )
-        return true;
-
-    PreDraw( XOROption::IMPLEMENT_XOR );
-
-    if( UseSolid( mnFillColor, fTransparency ) )
-        DrawPolyPolygon( rPolyPolygon );
-
-    if( mnLineColor != mnFillColor && UseSolid( mnLineColor, fTransparency ))
-    {
-        basegfx::B2DTrapezoidVector aB2DTrapVector;
-        basegfx::tools::createLineTrapezoidFromB2DPolyPolygon( aB2DTrapVector, rPolyPolygon );
-        for(basegfx::B2DTrapezoid & i : aB2DTrapVector)
-            DrawTrapezoid( i );
-    }
-
-    PostDraw();
-
+    VCL_GL_INFO("::drawPolyPolygon " << rPolyPolygon.getB2DRange());
+    mpRenderList->addDrawPolyPolygon(rPolyPolygon, fTransparency, mnLineColor, mnFillColor, mrParent.getAntiAliasB2DDraw());
     return true;
 }
 
commit 344dc6939c45552dc162ea8b3f892e2ae4998d64
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Sun May 29 12:37:41 2016 +0900

    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,21 +882,27 @@ bool OpenGLSalGraphicsImpl::UseLine(SalColor nColor, double fTransparency, GLflo
 {
     if( nColor == SALCOLOR_NONE )
         return false;
+    UseLine(fLineWidth, bUseAA);
+    mpProgram->SetColorf("color", nColor, fTransparency);
+#ifdef DBG_UTIL
+    mProgramIsSolidColor = true;
+#endif
+    mProgramSolidColor = nColor;
+    mProgramSolidTransparency = fTransparency;
+    return true;
+}
+
+bool OpenGLSalGraphicsImpl::UseLine(GLfloat fLineWidth, bool bUseAA)
+{
     if (!UseProgram("combinedVertexShader", "combinedFragmentShader"))
         return false;
     mpProgram->SetShaderType(DrawShaderType::Line);
-    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
-    mProgramSolidColor = nColor;
-    mProgramSolidTransparency = fTransparency;
+    mpProgram->SetBlendMode(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
     return true;
 }
 
@@ -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");
+    VCL_GL_INFO("FlushDeferredDrawing: " << mpRenderList->getEntries().size());
 
-    OpenGLZone aZone;
+    if (!mpAccumulatedTextures->empty())
+    {
+        InitializePreDrawState();
 
-#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;
+        OpenGLZone aZone;
 
+        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())
-    {
-        OpenGLTexture& rTexture = rPair.second->maTexture;
-        Color aUseColor;
-        if (aColorForTextureMap.find(rTexture.Id()) == aColorForTextureMap.end())
+        for (auto& rPair : mpAccumulatedTextures->getAccumulatedTexturesMap())
         {
-            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;
+            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);
+            }
         }
-        aUseColor = aColorForTextureMap[rTexture.Id()];
+        mpProgram->Clean();
+        mpAccumulatedTextures->clear();
 
-        if (!UseSolid(MAKE_SALCOLOR(aUseColor.GetRed(), aUseColor.GetGreen(), aUseColor.GetBlue())))
-            return;
-        for (auto rColorTwoRectPair: rPair.second->maColorTextureDrawParametersMap)
-        {
-            TextureDrawParameters& rParameters = rColorTwoRectPair.second;
-            ApplyProgramMatrices();
-            mpProgram->SetTextureCoord(rParameters.maTextureCoords.data());
-            mpProgram->DrawArrays(GL_TRIANGLES, rParameters.maVertices);
-        }
+        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)
+        InitializePreDrawState(XOROption::IMPLEMENT_XOR);
+
+        OpenGLZone aZone;
+        for (RenderEntry& rRenderEntry : mpRenderList->getEntries())
         {
-            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);
+            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();
     }
-    mpProgram->Clean();
-    mpAccumulatedTextures->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
commit d0ec6c7b72f5826b9645c997b03d6f032b4f72f7
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date:   Fri May 27 19:43:12 2016 +0900

    opengl: VertexUtils, deferred flush update, remove unneeded calls
    
    VertexUtils - collection of utils for working with Vertices.
    
    Add deferred flush to some places directly where it is called
    indirectly. This is to assure that we don't produce regressions
    if we change the behavior in the future.
    
    drawAlphaBitmap is the same as drawBitmap so when drawBitmap is
    called just redirect to drawAlphaBitmap
    
    Change-Id: Ibef1ba88865856d92d9e93734cf5d6561af785c0

diff --git a/vcl/inc/opengl/AccumulatedTextures.hxx b/vcl/inc/opengl/AccumulatedTextures.hxx
index 882a694..504cf6a 100644
--- a/vcl/inc/opengl/AccumulatedTextures.hxx
+++ b/vcl/inc/opengl/AccumulatedTextures.hxx
@@ -15,16 +15,13 @@
 
 #include <o3tl/make_unique.hxx>
 #include "opengl/texture.hxx"
+#include "opengl/VertexUtils.hxx"
 #include <memory>
 
 struct TextureDrawParameters
 {
     std::vector<GLfloat> maVertices;
     std::vector<GLfloat> maTextureCoords;
-    GLint getNumberOfVertices()
-    {
-        return maVertices.size() / 2;
-    }
 };
 
 struct AccumulatedTexturesEntry
@@ -41,29 +38,13 @@ struct AccumulatedTexturesEntry
         TextureDrawParameters& aDrawParameters = maColorTextureDrawParametersMap[aColor];
         rTexture.FillCoords<GL_TRIANGLES>(aDrawParameters.maTextureCoords, r2Rect, false);
 
-        GLfloat nX1 = r2Rect.mnDestX;
-        GLfloat nY1 = r2Rect.mnDestY;
-        GLfloat nX2 = r2Rect.mnDestX + r2Rect.mnDestWidth;
-        GLfloat nY2 = r2Rect.mnDestY + r2Rect.mnDestHeight;
-
-        auto& rVertices = aDrawParameters.maVertices;
-        rVertices.push_back(nX1);
-        rVertices.push_back(nY1);
-
-        rVertices.push_back(nX2);
-        rVertices.push_back(nY1);
-
-        rVertices.push_back(nX1);
-        rVertices.push_back(nY2);
-
-        rVertices.push_back(nX1);
-        rVertices.push_back(nY2);
-
-        rVertices.push_back(nX2);
-        rVertices.push_back(nY1);
+        GLfloat fX1 = r2Rect.mnDestX;
+        GLfloat fY1 = r2Rect.mnDestY;
+        GLfloat fX2 = fX1 + r2Rect.mnDestWidth;
+        GLfloat fY2 = fY1 + r2Rect.mnDestHeight;
 
-        rVertices.push_back(nX2);
-        rVertices.push_back(nY2);
+        std::vector<GLfloat>& rVertices = aDrawParameters.maVertices;
+        vcl::vertex::addRectangle<GL_TRIANGLES>(rVertices, fX1, fY1, fX2, fY2);
     }
 };
 
@@ -113,6 +94,6 @@ public:
     }
 };
 
-#endif // INCLUDED_VCL_INC_OPENGL_TEXTURE_H
+#endif // INCLUDED_VCL_INC_OPENGL_ACCUMULATEDTEXTURES_H
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/opengl/VertexUtils.hxx b/vcl/inc/opengl/VertexUtils.hxx
new file mode 100644
index 0000000..becc62b
--- /dev/null
+++ b/vcl/inc/opengl/VertexUtils.hxx
@@ -0,0 +1,86 @@
+/* -*- 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_VERTEXUTILS_H
+#define INCLUDED_VCL_INC_OPENGL_VERTEXUTILS_H
+
+#include <glm/gtx/norm.hpp>
+
+namespace vcl
+{
+namespace vertex
+{
+
+template<GLenum TYPE>
+inline void addRectangle(std::vector<GLfloat>& rVertices, GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2);
+
+template<>
+inline void addRectangle<GL_TRIANGLES>(std::vector<GLfloat>& rVertices, GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
+{
+    rVertices.insert(rVertices.end(), {
+        x1, y1, x2, y1, x1, y2,
+        x1, y2, x2, y1, x2, y2
+    });
+}
+
+template<>
+inline void addRectangle<GL_TRIANGLE_FAN>(std::vector<GLfloat>& rVertices, GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
+{
+    rVertices.insert(rVertices.end(), {
+        x1, y2, x1, y1,
+        x2, y1, x2, y2
+    });
+}
+
+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);
+}
+
+inline void addLineVertexPair(std::vector<GLfloat>& rVertices, std::vector<GLfloat>& rExtrusionVectors, const glm::vec2& point, const glm::vec2& extrusionVector, float length)
+{
+    addLineVertex(rVertices, rExtrusionVectors, point, -extrusionVector, -length);
+    addLineVertex(rVertices, rExtrusionVectors, point,  extrusionVector,  length);
+}
+
+inline void addLinePointFirst(std::vector<GLfloat>& rVertices, std::vector<GLfloat>& rExtrusionVectors,
+                               glm::vec2 point, glm::vec2 extrusionVector, float length)
+{
+    addLineVertex(rVertices, rExtrusionVectors, point, -extrusionVector, -length);
+    addLineVertex(rVertices, rExtrusionVectors, point,  extrusionVector,  length);
+}
+
+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)
+{
+    addLineVertex(rVertices, rExtrusionVectors, currPoint, -currExtrusionVector, -currLength);
+    addLineVertex(rVertices, rExtrusionVectors, currPoint, -currExtrusionVector, -currLength);
+    addLineVertex(rVertices, rExtrusionVectors, prevPoint,  prevExtrusionVector,  prevLength);
+    addLineVertex(rVertices, rExtrusionVectors, currPoint,  currExtrusionVector,  currLength);
+}
+
+inline glm::vec2 normalize(const glm::vec2& vector)
+{
+    if (glm::length(vector) > 0.0)
+        return glm::normalize(vector);
+    return vector;
+}
+
+}} // end vcl::vertex
+
+#endif // INCLUDED_VCL_INC_OPENGL_VERTEXUTILS_H
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/opengl/gdiimpl.cxx b/vcl/opengl/gdiimpl.cxx
index 720aa19..7c8f65a 100644
--- a/vcl/opengl/gdiimpl.cxx
+++ b/vcl/opengl/gdiimpl.cxx
@@ -35,6 +35,7 @@
 #include "opengl/zone.hxx"
 #include "opengl/salbmp.hxx"
 #include "opengl/RenderState.hxx"
+#include "opengl/VertexUtils.hxx"
 
 #include <vector>
 
@@ -172,6 +173,10 @@ void OpenGLSalGraphicsImpl::Init()
 // Currently only used to get windows ordering right.
 void OpenGLSalGraphicsImpl::DeInit()
 {
+    VCL_GL_INFO("::DeInit");
+
+    FlushDeferredDrawing();
+
     // tdf#93839:
     // Our window handles and resources are being free underneath us.
     // These can be bound into a context, which relies on them. So
@@ -636,34 +641,6 @@ void OpenGLSalGraphicsImpl::DrawLine( double nX1, double nY1, double nX2, double
     CHECK_GL_ERROR();
 }
 
-namespace
-{
-
-inline void addVertex(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);
-}
-
-inline void addVertexPair(std::vector<GLfloat>& rVertices, std::vector<GLfloat>& rExtrusionVectors, const glm::vec2& point, const glm::vec2& extrusionVector, float length)
-{
-    addVertex(rVertices, rExtrusionVectors, point, -extrusionVector, -length);
-    addVertex(rVertices, rExtrusionVectors, point,  extrusionVector,  length);
-}
-
-inline glm::vec2 normalize(const glm::vec2& vector)
-{
-    if (glm::length(vector) > 0.0)
-        return glm::normalize(vector);
-    return vector;
-}
-
-} // end anonymous namespace
-
 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)
@@ -678,7 +655,7 @@ void OpenGLSalGraphicsImpl::DrawLineCap(float x1, float y1, float x2, float y2,
 
     glm::vec2 p1(x1, y1);
     glm::vec2 p2(x2, y2);
-    glm::vec2 lineVector = normalize(p2 - p1);
+    glm::vec2 lineVector = vcl::vertex::normalize(p2 - p1);
     glm::vec2 normal = glm::vec2(-lineVector.y, lineVector.x);
 
     if (eLineCap == css::drawing::LineCap_ROUND)
@@ -689,15 +666,15 @@ void OpenGLSalGraphicsImpl::DrawLineCap(float x1, float y1, float x2, float y2,
             glm::vec2 roundNormal(normal.x * glm::cos(angle) - normal.y * glm::sin(angle),
                                   normal.x * glm::sin(angle) + normal.y * glm::cos(angle));
 
-            addVertexPair(aVertices, aExtrusionVectors, p1, roundNormal, 1.0f);
+            vcl::vertex::addLineVertexPair(aVertices, aExtrusionVectors, p1, roundNormal, 1.0f);
         }
     }
     else if (eLineCap == css::drawing::LineCap_SQUARE)
     {
         glm::vec2 extrudedPoint = p1 + -lineVector * (fLineWidth / 2.0f);
 
-        addVertexPair(aVertices, aExtrusionVectors, extrudedPoint, normal, 1.0f);
-        addVertexPair(aVertices, aExtrusionVectors, p1, normal, 1.0f);
+        vcl::vertex::addLineVertexPair(aVertices, aExtrusionVectors, extrudedPoint, normal, 1.0f);
+        vcl::vertex::addLineVertexPair(aVertices, aExtrusionVectors, p1, normal, 1.0f);
     }
 
     ApplyProgramMatrices(0.5f);
@@ -712,20 +689,20 @@ void OpenGLSalGraphicsImpl::DrawLineSegment(float x1, float y1, float x2, float
     glm::vec2 p1(x1, y1);
     glm::vec2 p2(x2, y2);
 
-    std::vector<GLfloat> aPoints;
+    std::vector<GLfloat> aVertices;
     std::vector<GLfloat> aExtrusionVectors;
 
     OpenGLZone aZone;
 
-    glm::vec2 lineVector = normalize(p2 - p1);
+    glm::vec2 lineVector = vcl::vertex::normalize(p2 - p1);
     glm::vec2 normal = glm::vec2(-lineVector.y, lineVector.x);
 
-    addVertexPair(aPoints, aExtrusionVectors, p1, normal, 1.0f);
-    addVertexPair(aPoints, aExtrusionVectors, p2, normal, 1.0f);
+    vcl::vertex::addLinePointFirst(aVertices, aExtrusionVectors, p1, normal, 1.0f);
+    vcl::vertex::addLinePointNext (aVertices, aExtrusionVectors, p1, normal, 1.0f, p2, normal, 1.0f);
 
     ApplyProgramMatrices(0.5f);
     mpProgram->SetExtrusionVectors(aExtrusionVectors.data());
-    mpProgram->DrawArrays(GL_TRIANGLE_STRIP, aPoints);
+    mpProgram->DrawArrays(GL_TRIANGLES, aVertices);
 
     CHECK_GL_ERROR();
 }
@@ -804,12 +781,12 @@ void OpenGLSalGraphicsImpl::DrawPolyLine(const basegfx::B2DPolygon& rPolygon, fl
         glm::vec2 p1(rPolygon.getB2DPoint(0).getX(), rPolygon.getB2DPoint(0).getY());
         glm::vec2 p2(rPolygon.getB2DPoint(1).getX(), rPolygon.getB2DPoint(1).getY());
 
-        nextLineVector = normalize(p2 - p1);
+        nextLineVector = vcl::vertex::normalize(p2 - p1);
 
         if (!bClosed)
         {
             normal = glm::vec2(-nextLineVector.y, nextLineVector.x); // make perpendicular
-            addVertexPair(aVertices, aExtrusionVectors, p1, normal, 1.0f);
+            vcl::vertex::addLineVertexPair(aVertices, aExtrusionVectors, p1, normal, 1.0f);
 
             i++; // first point done already
             lastPoint--; // last point will be calculated separatly from the loop
@@ -821,7 +798,7 @@ void OpenGLSalGraphicsImpl::DrawPolyLine(const basegfx::B2DPolygon& rPolygon, fl
         {
             lastPoint++; // we need to connect last point to first point so one more line segment to calculate
 
-            previousLineVector = normalize(p1 - p0);
+            previousLineVector = vcl::vertex::normalize(p1 - p0);
         }
 
         for (; i < lastPoint; ++i)
@@ -835,7 +812,7 @@ void OpenGLSalGraphicsImpl::DrawPolyLine(const basegfx::B2DPolygon& rPolygon, fl
             if (p1 == p2) // skip equal points, normals could div-by-0
                 continue;
 
-            nextLineVector = normalize(p2 - p1);
+            nextLineVector = vcl::vertex::normalize(p2 - p1);
 
             if (eLineJoin == basegfx::B2DLineJoin::Miter)
             {
@@ -859,11 +836,11 @@ void OpenGLSalGraphicsImpl::DrawPolyLine(const basegfx::B2DPolygon& rPolygon, fl
 
                 normal = glm::vec2(-previousLineVector.y, previousLineVector.x);
 
-                glm::vec2 tangent = normalize(nextLineVector + previousLineVector);
+                glm::vec2 tangent = vcl::vertex::normalize(nextLineVector + previousLineVector);
                 glm::vec2 extrusionVector(-tangent.y, tangent.x);
                 GLfloat length = glm::dot(extrusionVector, normal);
 
-                addVertexPair(aVertices, aExtrusionVectors, p1, extrusionVector, length);
+                vcl::vertex::addLineVertexPair(aVertices, aExtrusionVectors, p1, extrusionVector, length);
             }
             else if (eLineJoin == basegfx::B2DLineJoin::Bevel)
             {
@@ -875,8 +852,8 @@ void OpenGLSalGraphicsImpl::DrawPolyLine(const basegfx::B2DPolygon& rPolygon, fl
                 glm::vec2 previousNormal = glm::vec2(-previousLineVector.y, previousLineVector.x);
                 glm::vec2 nextNormal = glm::vec2(-nextLineVector.y, nextLineVector.x);
 
-                addVertexPair(aVertices, aExtrusionVectors, p1, previousNormal, 1.0f);
-                addVertexPair(aVertices, aExtrusionVectors, p1, nextNormal, 1.0f);
+                vcl::vertex::addLineVertexPair(aVertices, aExtrusionVectors, p1, previousNormal, 1.0f);
+                vcl::vertex::addLineVertexPair(aVertices, aExtrusionVectors, p1, nextNormal, 1.0f);
             }
             else if (eLineJoin == basegfx::B2DLineJoin::Round)
             {
@@ -891,15 +868,15 @@ void OpenGLSalGraphicsImpl::DrawPolyLine(const basegfx::B2DPolygon& rPolygon, fl
                 glm::vec2 previousNormal = glm::vec2(-previousLineVector.y, previousLineVector.x);
                 glm::vec2 nextNormal = glm::vec2(-nextLineVector.y, nextLineVector.x);
 
-                glm::vec2 middle = normalize(previousNormal + nextNormal);
-                glm::vec2 middleLeft  = normalize(previousNormal + middle);
-                glm::vec2 middleRight = normalize(middle + nextNormal);
+                glm::vec2 middle = vcl::vertex::normalize(previousNormal + nextNormal);
+                glm::vec2 middleLeft  = vcl::vertex::normalize(previousNormal + middle);
+                glm::vec2 middleRight = vcl::vertex::normalize(middle + nextNormal);
 
-                addVertexPair(aVertices, aExtrusionVectors, p1, previousNormal, 1.0f);
-                addVertexPair(aVertices, aExtrusionVectors, p1, middleLeft, 1.0f);
-                addVertexPair(aVertices, aExtrusionVectors, p1, middle, 1.0f);
-                addVertexPair(aVertices, aExtrusionVectors, p1, middleRight, 1.0f);
-                addVertexPair(aVertices, aExtrusionVectors, p1, nextNormal, 1.0f);
+                vcl::vertex::addLineVertexPair(aVertices, aExtrusionVectors, p1, previousNormal, 1.0f);
+                vcl::vertex::addLineVertexPair(aVertices, aExtrusionVectors, p1, middleLeft, 1.0f);
+                vcl::vertex::addLineVertexPair(aVertices, aExtrusionVectors, p1, middle, 1.0f);
+                vcl::vertex::addLineVertexPair(aVertices, aExtrusionVectors, p1, middleRight, 1.0f);
+                vcl::vertex::addLineVertexPair(aVertices, aExtrusionVectors, p1, nextNormal, 1.0f);
             }
             p0 = p1;
             previousLineVector = nextLineVector;
@@ -914,7 +891,7 @@ void OpenGLSalGraphicsImpl::DrawPolyLine(const basegfx::B2DPolygon& rPolygon, fl
 
             normal = glm::vec2(-previousLineVector.y, previousLineVector.x);
 
-            addVertexPair(aVertices, aExtrusionVectors, p1, normal, 1.0f);
+            vcl::vertex::addLineVertexPair(aVertices, aExtrusionVectors, p1, normal, 1.0f);
         }
 
         ApplyProgramMatrices(0.5f);
@@ -1184,7 +1161,18 @@ void OpenGLSalGraphicsImpl::DrawTextureRect( OpenGLTexture& /*rTexture*/, const
 
     SAL_INFO("vcl.opengl", "draw texture rect");
 
-    DrawRect( rPosAry.mnDestX, rPosAry.mnDestY, rPosAry.mnDestWidth, rPosAry.mnDestHeight );
+    long nX = rPosAry.mnDestX;
+    long nY = rPosAry.mnDestY;
+    long nWidth  = rPosAry.mnDestWidth;
+    long nHeight = rPosAry.mnDestHeight;
+
+    std::vector<GLfloat> aVertices;
+    aVertices.reserve(8);
+    vcl::vertex::addRectangle<GL_TRIANGLE_FAN>(aVertices, nX, nY, nX + nWidth, nY + nHeight);
+
+    ApplyProgramMatrices();
+    mpProgram->DrawArrays(GL_TRIANGLE_FAN, aVertices);
+    CHECK_GL_ERROR();
 }
 
 void OpenGLSalGraphicsImpl::DrawTexture( OpenGLTexture& rTexture, const SalTwoRect& rPosAry, bool bInverted )
@@ -1475,7 +1463,7 @@ void OpenGLSalGraphicsImpl::DrawTextureWithMask( OpenGLTexture& rTexture, OpenGL
     rMask.GetCoord(aMaskCoord, rPosAry);
     mpProgram->SetMaskCoord(aMaskCoord);
 
-    DrawRect(rPosAry.mnDestX, rPosAry.mnDestY, rPosAry.mnDestWidth, rPosAry.mnDestHeight);
+    DrawTextureRect(rTexture, rPosAry);
     mpProgram->Clean();
 }
 
@@ -1978,20 +1966,8 @@ void OpenGLSalGraphicsImpl::drawBitmap(
             const SalBitmap& rSalBitmap,
             const SalBitmap& rMaskBitmap )
 {
-    assert(dynamic_cast<const OpenGLSalBitmap*>(&rSalBitmap));
-    assert(dynamic_cast<const OpenGLSalBitmap*>(&rMaskBitmap));
-
-    OpenGLZone aZone;
-
-    const OpenGLSalBitmap& rBitmap = static_cast<const OpenGLSalBitmap&>(rSalBitmap);
-    const OpenGLSalBitmap& rMask = static_cast<const OpenGLSalBitmap&>(rMaskBitmap);
-    OpenGLTexture& rTexture( rBitmap.GetTexture() );
-    OpenGLTexture& rMaskTex( rMask.GetTexture() );
-
-    VCL_GL_INFO( "::drawBitmap with MASK" );
-    PreDraw();
-    DrawTextureWithMask( rTexture, rMaskTex, rPosAry );
-    PostDraw();
+    VCL_GL_INFO("::drawBitmap with MASK -> redirect to ::drawAlphaBitmap");
+    drawAlphaBitmap(rPosAry, rSalBitmap, rMaskBitmap);
 }
 
 void OpenGLSalGraphicsImpl::drawMask(
@@ -2014,6 +1990,8 @@ void OpenGLSalGraphicsImpl::drawMask(
 
 SalBitmap* OpenGLSalGraphicsImpl::getBitmap( long nX, long nY, long nWidth, long nHeight )
 {
+    FlushDeferredDrawing();
+
     OpenGLZone aZone;
 
     OpenGLSalBitmap* pBitmap = new OpenGLSalBitmap;


More information about the Libreoffice-commits mailing list