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;
}