gl_engine: implement gl infrastructure interfaces & test Gl shape sample 57/235957/4
authorPranay Kumar Samanta <pranay.ks@samsung.com>
Wed, 10 Jun 2020 12:44:42 +0000 (18:14 +0530)
committerHermet Park <chuneon.park@samsung.com>
Thu, 18 Jun 2020 09:36:10 +0000 (18:36 +0900)
Change-Id: Ie142616bf02f9bd50ac8e88e31ed9f782dd6324b
Signed-off-by: Pranay Kumar Samanta <pranay.ks@samsung.com>
20 files changed:
.gitignore
src/lib/gl_engine/meson.build [changed mode: 0644->0755]
src/lib/gl_engine/tvgGlCommon.h [changed mode: 0644->0755]
src/lib/gl_engine/tvgGlGeometry.cpp [new file with mode: 0755]
src/lib/gl_engine/tvgGlGeometry.h [changed mode: 0644->0755]
src/lib/gl_engine/tvgGlGpuBuffer.cpp [new file with mode: 0755]
src/lib/gl_engine/tvgGlGpuBuffer.h [changed mode: 0644->0755]
src/lib/gl_engine/tvgGlProgram.cpp [new file with mode: 0755]
src/lib/gl_engine/tvgGlProgram.h [changed mode: 0644->0755]
src/lib/gl_engine/tvgGlRenderer.cpp [changed mode: 0644->0755]
src/lib/gl_engine/tvgGlRenderer.h [changed mode: 0644->0755]
src/lib/gl_engine/tvgGlShader.cpp [new file with mode: 0755]
src/lib/gl_engine/tvgGlShader.h [changed mode: 0644->0755]
src/lib/gl_engine/tvgGlShaderSrc.cpp [new file with mode: 0755]
src/lib/gl_engine/tvgGlShaderSrc.h [new file with mode: 0755]
src/lib/tvgGlCanvas.cpp [changed mode: 0644->0755]
src/lib/tvgRenderCommon.h [changed mode: 0644->0755]
src/lib/tvgShape.cpp [changed mode: 0644->0755]
test/makefile [changed mode: 0644->0755]
test/testGlShape.cpp [new file with mode: 0755]

index 3b90d3a..af30a22 100644 (file)
@@ -19,3 +19,4 @@ testRadialGradient
 testGradientTransform
 testSvg
 testSvg2
+testGlShape
old mode 100644 (file)
new mode 100755 (executable)
index 5494f69..a5409a7
@@ -5,7 +5,13 @@ source_file = [
    'tvgGlProgram.h',
    'tvgGlRenderer.h',
    'tvgGlShader.h',
+   'tvgGlShaderSrc.h',
+   'tvgGlGeometry.cpp',
+   'tvgGlGpuBuffer.cpp',
+   'tvgGlProgram.cpp',
    'tvgGlRenderer.cpp',
+   'tvgGlShader.cpp',
+   'tvgGlShaderSrc.cpp',
 ]
 
 glraster_dep = declare_dependency(
old mode 100644 (file)
new mode 100755 (executable)
index f68666a..c596954
@@ -2,11 +2,31 @@
 #define _TVG_GL_COMMON_H_\r
 \r
 #include "tvgCommon.h"\r
-#include "tvgGlProgram.h"\r
-#include "tvgGlShader.h"\r
-#include "tvgGlGeometry.h"\r
 \r
 \r
+#define GL_CHECK(x) \\r
+        x; \\r
+        do { \\r
+          GLenum glError = glGetError(); \\r
+          if(glError != GL_NO_ERROR) { \\r
+            printf("glGetError() = %i (0x%.8x) at line %s : %i\n", glError, glError, __FILE__, __LINE__); \\r
+            assert(0); \\r
+          } \\r
+        } while(0)\r
+\r
+#define EGL_CHECK(x) \\r
+    x; \\r
+    do { \\r
+        EGLint eglError = eglGetError(); \\r
+        if(eglError != EGL_SUCCESS) { \\r
+            printf("eglGetError() = %i (0x%.8x) at line %s : %i\n", eglError, eglError, __FILE__, __LINE__); \\r
+            assert(0); \\r
+        } \\r
+    } while(0)\r
+\r
+\r
+class GlGeometry;\r
+\r
 struct GlShape\r
 {\r
   float             viewWd;\r
diff --git a/src/lib/gl_engine/tvgGlGeometry.cpp b/src/lib/gl_engine/tvgGlGeometry.cpp
new file mode 100755 (executable)
index 0000000..59b730b
--- /dev/null
@@ -0,0 +1,319 @@
+#include "tvgGlGpuBuffer.h"
+#include "tvgGlGeometry.h"
+#include "tvgGlCommon.h"
+
+#include <GLES2/gl2.h>
+
+
+uint32_t GlGeometry::getPrimitiveCount()
+{
+    return mPrimitives.size();
+}
+
+
+bool GlGeometry::decomposeOutline(const Shape &shape)
+{
+    const PathCommand *cmds = nullptr;
+    auto cmdCnt = shape.pathCommands(&cmds);
+
+    Point *pts = nullptr;
+    auto ptsCnt = shape.pathCoords(const_cast<const Point**>(&pts));
+
+    //No actual shape data
+    if (cmdCnt == 0 || ptsCnt == 0)
+        return false;
+
+    GlPrimitive* curPrimitive = nullptr;
+    for (size_t i = 0; i < cmdCnt; ++i)
+    {
+        switch (*(cmds + i))
+        {
+            case PathCommand::Close:
+            {
+                if (curPrimitive && curPrimitive->mAAPoints.size() > 0 &&
+                (curPrimitive->mAAPoints[0].orgPt != curPrimitive->mAAPoints.back().orgPt) )
+                {
+                    curPrimitive->mAAPoints.push_back(curPrimitive->mAAPoints[0].orgPt);
+                }
+                break;
+            }
+            case PathCommand::MoveTo:
+                mPrimitives.push_back(GlPrimitive());
+                curPrimitive = &mPrimitives.back();
+            case PathCommand::LineTo:
+            {
+                if (curPrimitive)
+                {
+                    addPoint(*curPrimitive, pts[0]);
+                }
+                pts++;
+                break;
+            }
+            case PathCommand::CubicTo:
+            {
+                if (curPrimitive)
+                {
+                    decomposeCubicCurve(*curPrimitive, curPrimitive->mAAPoints.back().orgPt, pts[0], pts[1], pts[2]);
+                }
+                pts += 3;
+                break;
+            }
+        }
+    }
+    return true;
+}
+
+bool GlGeometry::generateAAPoints(const Shape &shape, float strokeWd, RenderUpdateFlag flag)
+{
+    for (auto& shapeGeometry : mPrimitives)
+    {
+        std::vector<PointNormals> normalInfo;
+        constexpr float blurDir = -1.0f;
+        float antiAliasWidth = 1.0f;
+        vector<SmoothPoint>& aaPts = shapeGeometry.mAAPoints;
+
+        const float stroke = (strokeWd > 1) ? strokeWd - antiAliasWidth : strokeWd;
+
+        size_t nPoints = aaPts.size();
+        if (nPoints < 2)
+        {
+            return false;
+        }
+
+        normalInfo.resize(nPoints);
+
+        size_t fPoint = 0;
+        size_t sPoint = 1;
+        for (size_t i = 0; i < nPoints - 1; ++i)
+        {
+            fPoint = i;
+            sPoint = i + 1;
+            if (sPoint == nPoints - 1)
+                sPoint = 0;
+
+            GlPoint normal = getNormal(aaPts[fPoint].orgPt, aaPts[sPoint].orgPt);
+
+            normalInfo[fPoint].normal1 = normal;
+            normalInfo[sPoint].normal2 = normal;
+        }
+        normalInfo[nPoints - 1].normal1 = normalInfo[0].normal1;
+        normalInfo[nPoints - 1].normal2 = normalInfo[0].normal2;
+
+        for (uint32_t i = 0; i < nPoints; ++i)
+        {
+            normalInfo[i].normalF = normalInfo[i].normal1 + normalInfo[i].normal2;
+            normalInfo[i].normalF.normalize();
+
+            float angle = dotProduct(normalInfo[i].normal2, normalInfo[i].normalF);
+            if (angle != 0)
+                normalInfo[i].normalF = normalInfo[i].normalF / angle;
+            else
+                normalInfo[i].normalF = GlPoint(0, 0);
+
+            if (flag & RenderUpdateFlag::Color)
+            {
+                aaPts[i].fillOuterBlur = extendEdge(aaPts[i].orgPt, normalInfo[i].normalF, blurDir * stroke);
+                aaPts[i].fillOuter = extendEdge(aaPts[i].fillOuterBlur, normalInfo[i].normalF, blurDir*antiAliasWidth);
+            }
+            if (flag & RenderUpdateFlag::Stroke)
+            {
+                aaPts[i].strokeOuterBlur = aaPts[i].orgPt;
+                aaPts[i].strokeOuter = extendEdge(aaPts[i].strokeOuterBlur, normalInfo[i].normalF, blurDir*antiAliasWidth);
+                aaPts[i].strokeInner = extendEdge(aaPts[i].strokeOuter, normalInfo[i].normalF, blurDir * stroke);
+                aaPts[i].strokeInnerBlur = extendEdge(aaPts[i].strokeInner, normalInfo[i].normalF, blurDir*antiAliasWidth);
+            }
+        }
+    }
+
+    return true;
+}
+
+bool GlGeometry::tesselate(const Shape &shape, float viewWd, float viewHt, RenderUpdateFlag flag)
+{
+    for (auto& shapeGeometry : mPrimitives)
+    {
+        constexpr float opaque = 1.0f;
+        constexpr float transparent = 0.0f;
+        vector<SmoothPoint>& aaPts = shapeGeometry.mAAPoints;
+        VertexDataArray& fill = shapeGeometry.mFill;
+        VertexDataArray& stroke = shapeGeometry.mStroke;
+
+        if (flag & RenderUpdateFlag::Color)
+        {
+            uint32_t i = 0;
+            for (size_t pt = 0; pt < aaPts.size(); ++pt)
+            {
+                addGeometryPoint(fill, aaPts[pt].fillOuter, viewWd, viewHt, opaque);
+                if (i > 1)
+                {
+                    addTriangleFanIndices(i, fill.indices);
+                }
+                ++i;
+            }
+            for (size_t pt = 1; pt < aaPts.size(); ++pt)
+            {
+                addGeometryPoint(fill, aaPts[pt - 1].fillOuterBlur, viewWd, viewHt, transparent);
+                addGeometryPoint(fill, aaPts[pt - 1].fillOuter, viewWd, viewHt, opaque);
+                addGeometryPoint(fill, aaPts[pt].fillOuterBlur, viewWd, viewHt, transparent);
+                addGeometryPoint(fill, aaPts[pt].fillOuter, viewWd, viewHt, opaque);
+                addQuadIndices(i, fill.indices);
+            }
+        }
+        if (flag & RenderUpdateFlag::Stroke)
+        {
+            uint32_t i = 0;
+            for (size_t pt = 1; pt < aaPts.size(); ++pt)
+            {
+                addGeometryPoint(stroke, aaPts[pt - 1].strokeOuter, viewWd, viewHt, opaque);
+                addGeometryPoint(stroke, aaPts[pt - 1].strokeInner, viewWd, viewHt, opaque);
+                addGeometryPoint(stroke, aaPts[pt].strokeOuter, viewWd, viewHt, opaque);
+                addGeometryPoint(stroke, aaPts[pt].strokeInner, viewWd, viewHt, opaque);
+                addQuadIndices(i, stroke.indices);
+            }
+            for (size_t pt = 1; pt < aaPts.size(); ++pt)
+            {
+                addGeometryPoint(stroke, aaPts[pt - 1].strokeOuterBlur, viewWd, viewHt, transparent);
+                addGeometryPoint(stroke, aaPts[pt - 1].strokeOuter, viewWd, viewHt, opaque);
+                addGeometryPoint(stroke, aaPts[pt].strokeOuterBlur, viewWd, viewHt, transparent);
+                addGeometryPoint(stroke, aaPts[pt].strokeOuter, viewWd, viewHt, opaque);
+                addQuadIndices(i, stroke.indices);
+            }
+            for (size_t pt = 1; pt < aaPts.size(); ++pt)
+            {
+                addGeometryPoint(stroke, aaPts[pt - 1].strokeInner, viewWd, viewHt, opaque);
+                addGeometryPoint(stroke, aaPts[pt - 1].strokeInnerBlur, viewWd, viewHt, transparent);
+                addGeometryPoint(stroke, aaPts[pt].strokeInner, viewWd, viewHt, opaque);
+                addGeometryPoint(stroke, aaPts[pt].strokeInnerBlur, viewWd, viewHt, transparent);
+                addQuadIndices(i, stroke.indices);
+            }
+        }
+        aaPts.clear();
+    }
+    return true;
+}
+
+
+void GlGeometry::disableVertex(uint32_t location)
+{
+    GL_CHECK(glDisableVertexAttribArray(location));
+    mGpuBuffer->unbind(GlGpuBuffer::Target::ARRAY_BUFFER);
+}
+
+
+void GlGeometry::draw(const uint32_t location, const uint32_t primitiveIndex, RenderUpdateFlag flag)
+{
+    if (primitiveIndex >= mPrimitives.size())
+    {
+        return;
+    }
+    VertexDataArray& geometry = (flag == RenderUpdateFlag::Color) ? mPrimitives[primitiveIndex].mFill : mPrimitives[primitiveIndex].mStroke;
+
+    updateBuffer(location, geometry);
+    GL_CHECK(glDrawElements(GL_TRIANGLES, geometry.indices.size(), GL_UNSIGNED_INT, geometry.indices.data()));
+}
+
+
+void GlGeometry::updateBuffer(uint32_t location, const VertexDataArray& vertexArray)
+{
+    if (mGpuBuffer.get() == nullptr)
+    {
+        mGpuBuffer = make_unique<GlGpuBuffer>();
+    }
+    mGpuBuffer->updateBufferData(GlGpuBuffer::Target::ARRAY_BUFFER, vertexArray.vertices.size() * sizeof(VertexData), vertexArray.vertices.data());
+    GL_CHECK(glVertexAttribPointer(location, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), 0));
+    GL_CHECK(glEnableVertexAttribArray(location));
+}
+
+
+GlPoint GlGeometry::normalizePoint(const GlPoint &pt, float viewWd, float viewHt)
+{
+    GlPoint p;
+    p.x = (pt.x * 2.0f / viewWd) - 1.0f;
+    p.y = -1.0f * ((pt.y * 2.0f / viewHt) - 1.0f);
+    return p;
+}
+
+void GlGeometry::addGeometryPoint(VertexDataArray &geometry, const GlPoint &pt, float viewWd, float viewHt, float opacity)
+{
+    VertexData tv = { normalizePoint(pt, viewWd, viewHt), opacity};
+    geometry.vertices.push_back(tv);
+}
+
+GlPoint GlGeometry::getNormal(const GlPoint &p1, const GlPoint &p2)
+{
+    GlPoint normal = p1 - p2;
+    normal.normalize();
+    return GlPoint(-normal.y, normal.x);
+}
+
+float GlGeometry::dotProduct(const GlPoint &p1, const GlPoint &p2)
+{
+    return (p1.x * p2.x + p1.y * p2.y);
+}
+
+GlPoint GlGeometry::extendEdge(const GlPoint &pt, const GlPoint &normal, float scalar)
+{
+    GlPoint tmp = (normal * scalar);
+    return (pt + tmp);
+}
+
+void GlGeometry::addPoint(GlPrimitive& primitve, const GlPoint &pt)
+{
+    primitve.mAAPoints.push_back(GlPoint(pt.x, pt.y));
+}
+
+void GlGeometry::addTriangleFanIndices(uint32_t &curPt, std::vector<uint32_t> &indices)
+{
+    indices.push_back(0);
+    indices.push_back(curPt - 1);
+    indices.push_back(curPt);
+}
+
+void GlGeometry::addQuadIndices(uint32_t &curPt, std::vector<uint32_t> &indices)
+{
+    indices.push_back(curPt);
+    indices.push_back(curPt + 1);
+    indices.push_back(curPt + 2);
+    indices.push_back(curPt + 1);
+    indices.push_back(curPt + 3);
+    indices.push_back(curPt + 2);
+    curPt += 4;
+}
+
+bool GlGeometry::isBezierFlat(const GlPoint &p1, const GlPoint &c1, const GlPoint &c2, const GlPoint &p2)
+{
+    GlPoint diff1 = (c1 * 3.0f) - (p1 * 2.0f) - p2;
+    GlPoint diff2 = (c2 * 3.0f) - (p2 * 2.0f) - p1;
+
+    diff1.mod();
+    diff2.mod();
+    if (diff1.x < diff2.x)
+        diff1.x = diff2.x;
+    if (diff1.y < diff2.y)
+        diff1.y = diff2.y;
+
+    if (diff1.x + diff1.y <= 0.5f)
+        return true;
+    return false;
+}
+
+void GlGeometry::decomposeCubicCurve(GlPrimitive& primitve, const GlPoint &pt1, const GlPoint &cpt1, const GlPoint &cpt2, const GlPoint &pt2)
+{
+    if (isBezierFlat(pt1, cpt1, cpt2, pt2))
+    {
+        addPoint(primitve, pt2);
+        return;
+    }
+    GlPoint p12 = (pt1 + cpt1) * 0.5f;
+    GlPoint p23 = (cpt1 + cpt2) * 0.5f;
+    GlPoint p34 = (cpt2 + pt2) * 0.5f;
+
+    GlPoint p123 = (p12 + p23) * 0.5f;
+    GlPoint p234 = (p23 + p34) * 0.5f;
+
+    GlPoint p1234 = (p123 + p234) * 0.5f;
+
+    decomposeCubicCurve(primitve, pt1, p12, p123, p1234);
+    decomposeCubicCurve(primitve, p1234, p234, p34, pt2);
+}
+
old mode 100644 (file)
new mode 100755 (executable)
index 8f7cc61..9f87efa
@@ -1,7 +1,7 @@
 #ifndef _TVG_GL_GEOMETRY_H_
 #define _TVG_GL_GEOMETRY_H_
 
-#include "tvgGlGpuBuffer.h"
+#include "tvgGlCommon.h"
 
 class GlPoint
 {
@@ -9,6 +9,8 @@ public:
     float x = 0.0f;
     float y = 0.0f;
 
+    GlPoint() = default;
+
     GlPoint(float pX, float pY):x(pX), y(pY)
     {}
 
@@ -145,36 +147,42 @@ struct VertexDataArray
     vector<uint32_t>     indices;
 };
 
+struct GlPrimitive
+{
+    vector<SmoothPoint> mAAPoints;
+    VertexDataArray mFill;
+    VertexDataArray mStroke;
+};
+
+class GlGpuBuffer;
+
 class GlGeometry
 {
 public:
-    GlGeometry();
-    void reset();
-    void updateBuffer(const uint32_t location, const VertexDataArray& geometry);
-    void draw(const VertexDataArray& geometry);
+
+    uint32_t getPrimitiveCount();
     bool decomposeOutline(const Shape& shape);
     bool generateAAPoints(const Shape& shape, float strokeWd, RenderUpdateFlag flag);
     bool tesselate(const Shape &shape, float viewWd, float viewHt, RenderUpdateFlag flag);
-
-    const VertexDataArray& getFill();
-    const VertexDataArray& getStroke();
+    void disableVertex(uint32_t location);
+    void draw(const uint32_t location, const uint32_t primitiveIndex, RenderUpdateFlag flag);
 
 private:
-    GlPoint normalizePoint(GlPoint &pt, float viewWd, float viewHt);
-    void addGeometryPoint(VertexDataArray &geometry, GlPoint &pt, float viewWd, float viewHt, float opacity);
-    GlPoint getNormal(GlPoint &p1, GlPoint &p2);
-    float dotProduct(GlPoint &p1, GlPoint &p2);
-    GlPoint extendEdge(GlPoint &pt, GlPoint &normal, float scalar);
-    void addPoint(const GlPoint &pt);
+    GlPoint normalizePoint(const GlPoint &pt, float viewWd, float viewHt);
+    void addGeometryPoint(VertexDataArray &geometry, const GlPoint &pt, float viewWd, float viewHt, float opacity);
+    GlPoint getNormal(const GlPoint &p1, const GlPoint &p2);
+    float dotProduct(const GlPoint &p1, const GlPoint &p2);
+    GlPoint extendEdge(const GlPoint &pt, const GlPoint &normal, float scalar);
+
+    void addPoint(GlPrimitive& primitve, const GlPoint &pt);
     void addTriangleFanIndices(uint32_t &curPt, vector<uint32_t> &indices);
     void addQuadIndices(uint32_t &curPt, vector<uint32_t> &indices);
     bool isBezierFlat(const GlPoint &p1, const GlPoint &c1, const GlPoint &c2, const GlPoint &p2);
-    void decomposeCubicCurve(const GlPoint &pt1, const GlPoint &cpt1, const GlPoint &cpt2, const GlPoint &pt2);
+    void decomposeCubicCurve(GlPrimitive& primitve, const GlPoint &pt1, const GlPoint &cpt1, const GlPoint &cpt2, const GlPoint &pt2);
+    void updateBuffer(const uint32_t location, const VertexDataArray& vertexArray);
 
     unique_ptr<GlGpuBuffer> mGpuBuffer;
-    vector<SmoothPoint> mAAPoints;
-    VertexDataArray mFill;
-    VertexDataArray mStroke;
+    vector<GlPrimitive>     mPrimitives;
 };
 
 #endif /* _TVG_GL_GEOMETRY_H_ */
diff --git a/src/lib/gl_engine/tvgGlGpuBuffer.cpp b/src/lib/gl_engine/tvgGlGpuBuffer.cpp
new file mode 100755 (executable)
index 0000000..2aaba19
--- /dev/null
@@ -0,0 +1,32 @@
+#include "tvgGlCommon.h"
+#include "tvgGlGpuBuffer.h"
+
+#include <assert.h>
+
+GlGpuBuffer::GlGpuBuffer()
+{
+    GL_CHECK(glGenBuffers(1, &mGlBufferId));
+    assert(mGlBufferId != GL_INVALID_VALUE);
+}
+
+
+GlGpuBuffer::~GlGpuBuffer()
+{
+    if (mGlBufferId)
+    {
+        GL_CHECK(glDeleteBuffers(1, &mGlBufferId));
+    }
+}
+
+
+void GlGpuBuffer::updateBufferData(Target target, uint32_t size, const void* data)
+{
+    GL_CHECK(glBindBuffer(static_cast<uint32_t>(target), mGlBufferId));
+    GL_CHECK(glBufferData(static_cast<uint32_t>(target), size, data, GL_STATIC_DRAW));
+}
+
+
+void GlGpuBuffer::unbind(Target target)
+{
+    GL_CHECK(glBindBuffer(static_cast<uint32_t>(target), 0));
+}
\ No newline at end of file
old mode 100644 (file)
new mode 100755 (executable)
index 79dd26d..3116001
@@ -15,8 +15,8 @@ public:
 
     GlGpuBuffer();
     ~GlGpuBuffer();
-    void updateBufferData(Target target, uint32_t size, void* data);
-
+    void updateBufferData(Target target, uint32_t size, const void* data);
+    void unbind(Target target);
 private:
     uint32_t    mGlBufferId = 0;
 
diff --git a/src/lib/gl_engine/tvgGlProgram.cpp b/src/lib/gl_engine/tvgGlProgram.cpp
new file mode 100755 (executable)
index 0000000..dbf8762
--- /dev/null
@@ -0,0 +1,144 @@
+#include "tvgGlCommon.h"
+#include "tvgGlProgram.h"
+
+#include <GLES2/gl2.h>
+
+
+static std::vector<string> gStdAttributes = {
+    "aLocation"
+};
+
+static std::vector<string> gStdUniforms = {
+    "uColor"
+};
+
+uint32_t GlProgram::mCurrentProgram = 0;
+map<string, int32_t> GlProgram::mAttributeBuffer;
+map<string, int32_t> GlProgram::mUniformBuffer;
+
+
+unique_ptr<GlProgram> GlProgram::gen(std::shared_ptr<GlShader> shader)
+{
+    return make_unique<GlProgram>(shader);
+}
+
+
+GlProgram::GlProgram(std::shared_ptr<GlShader> shader)
+{
+    linkProgram(shader);
+    load();
+
+    for (auto name : gStdAttributes)
+    {
+        getAttributeLocation(name.c_str());
+    }
+    for (auto name : gStdUniforms)
+    {
+        getUniformLocation(name.c_str());
+    }
+
+}
+
+
+GlProgram::~GlProgram()
+{
+    if (mCurrentProgram == mProgramObj)
+    {
+        unload();
+    }
+    glDeleteProgram(mProgramObj);
+}
+
+
+void GlProgram::load()
+{
+    if (mCurrentProgram == mProgramObj)
+    {
+        return;
+    }
+
+    mCurrentProgram = mProgramObj;
+    GL_CHECK(glUseProgram(mProgramObj));
+
+}
+
+
+void GlProgram::unload()
+{
+    mCurrentProgram = 0;
+}
+
+
+int32_t GlProgram::getAttributeLocation(const char* name)
+{
+    if (mAttributeBuffer.find(name) != mAttributeBuffer.end())
+    {
+        return mAttributeBuffer[name];
+    }
+    GL_CHECK(int32_t location = glGetAttribLocation(mCurrentProgram, name));
+    if (location != -1)
+    {
+        mAttributeBuffer[name] = location;
+    }
+    return location;
+}
+
+
+int32_t GlProgram::getUniformLocation(const char* name)
+{
+    if (mUniformBuffer.find(name) != mUniformBuffer.end())
+    {
+        return mUniformBuffer[name];
+    }
+    GL_CHECK(int32_t location = glGetUniformLocation(mCurrentProgram, name));
+    if (location != -1)
+    {
+        mUniformBuffer[name] = location;
+    }
+    return location;
+
+}
+
+
+void GlProgram::setUniformValue(int32_t location, float r, float g, float b, float a)
+{
+    glUniform4f(location, r, g, b, a);
+}
+
+
+void GlProgram::linkProgram(std::shared_ptr<GlShader> shader)
+{
+    GLint linked;
+
+    // Create the program object
+    uint32_t progObj = glCreateProgram();
+    assert(progObj);
+
+    glAttachShader(progObj, shader->getVertexShader());
+    glAttachShader(progObj, shader->getFragmentShader());
+
+    // Link the program
+    glLinkProgram(progObj);
+
+    // Check the link status
+    glGetProgramiv(progObj, GL_LINK_STATUS, &linked);
+
+    if (!linked)
+    {
+        GLint infoLen = 0;
+        glGetProgramiv(progObj, GL_INFO_LOG_LENGTH, &infoLen);
+        if (infoLen > 0)
+        {
+            char* infoLog = new char[infoLen];
+            glGetProgramInfoLog(progObj, infoLen, NULL, infoLog);
+            std::cout << "Error linking shader: " << infoLog << std::endl;
+            delete[] infoLog;
+
+        }
+        glDeleteProgram(progObj);
+        progObj = 0;
+        assert(0);
+    }
+    mProgramObj = progObj;
+}
+
old mode 100644 (file)
new mode 100755 (executable)
index d485d3d..5df0e4f
@@ -3,22 +3,25 @@
 
 #include "tvgGlShader.h"
 
+#include <memory>
 #include <map>
 
-
 class GlProgram
 {
 public:
-    GlProgram(shared_ptr<GlShader> shader);
-    void create();
+    static std::unique_ptr<GlProgram> gen(std::shared_ptr<GlShader> shader);
+    GlProgram(std::shared_ptr<GlShader> shader);
+    ~GlProgram();
+
     void load();
+    void unload();
     int32_t getAttributeLocation(const char* name);
     int32_t getUniformLocation(const char* name);
     void setUniformValue(int32_t location, float r, float g, float b, float a);
 
 private:
-    void linkProgram();
-    std::shared_ptr<GlShader> mShader;
+
+    void linkProgram(std::shared_ptr<GlShader> shader);
     uint32_t mProgramObj;
     static uint32_t mCurrentProgram;
 
old mode 100644 (file)
new mode 100755 (executable)
index 1ca9588..ecabf6a
 #ifndef _TVG_GL_RENDERER_CPP_
 #define _TVG_GL_RENDERER_CPP_
 
-#include "tvgCommon.h"
+#include "tvgGlShaderSrc.h"
+#include "tvgGlGpuBuffer.h"
+#include "tvgGlGeometry.h"
+#include "tvgGlCommon.h"
 #include "tvgGlRenderer.h"
 
 /************************************************************************/
@@ -33,16 +36,55 @@ static RenderInitializer renderInit;
 bool GlRenderer::clear()
 {
     //TODO: (Request) to clear target
+    // Will be adding glClearColor for input buffer
+    return true;
+}
+
+
+bool GlRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h)
+{
+    assert(w > 0 && h > 0);
+
+    surface.stride = stride;
+    surface.w = w;
+    surface.h = h;
 
     return true;
 }
 
+
+void GlRenderer::flush()
+{
+    GL_CHECK(glFinish());
+    mColorProgram->unload();
+}
+
+
 bool GlRenderer::render(const Shape& shape, void *data)
 {
     GlShape* sdata = static_cast<GlShape*>(data);
     if (!sdata) return false;
 
-    //TODO:
+    uint8_t r, g, b, a;
+    size_t flags = static_cast<size_t>(sdata->updateFlag);
+
+    GL_CHECK(glViewport(0, 0, sdata->viewWd, sdata->viewHt));
+
+    uint32_t geometryCnt = sdata->geometry->getPrimitiveCount();
+    for (uint32_t i = 0; i < geometryCnt; ++i)
+    {
+        mColorProgram->load();
+        if (flags & RenderUpdateFlag::Color)
+        {
+            shape.fill(&r, &g, &b, &a);
+            drawPrimitive(*(sdata->geometry), (float)r / 255.0f, (float)g / 255.0f, (float)b / 255.0f, (float)a / 255.0f, i, RenderUpdateFlag::Color);
+        }
+        if (flags & RenderUpdateFlag::Stroke)
+        {
+            shape.strokeColor(&r, &g, &b, &a);
+            drawPrimitive(*(sdata->geometry), (float)r / 255.0f, (float)g / 255.0f, (float)b / 255.0f, (float)a / 255.0f, i, RenderUpdateFlag::Stroke);
+        }
+    }
 
     return true;
 }
@@ -53,9 +95,7 @@ bool GlRenderer::dispose(const Shape& shape, void *data)
     GlShape* sdata = static_cast<GlShape*>(data);
     if (!sdata) return false;
 
-    //TODO:
-
-    free(sdata);
+    delete sdata;
     return true;
 }
 
@@ -64,21 +104,35 @@ void* GlRenderer::prepare(const Shape& shape, void* data, const RenderTransform*
 {
     //prepare shape data
     GlShape* sdata = static_cast<GlShape*>(data);
-    if (!sdata) {
-        sdata = static_cast<GlShape*>(calloc(1, sizeof(GlShape)));
+    if (!sdata)
+    {
+        sdata = new GlShape;
         assert(sdata);
     }
+    sdata->viewWd = static_cast<float>(surface.w);
+    sdata->viewHt = static_cast<float>(surface.h);
+    sdata->updateFlag = flags;
 
-    if (flags & RenderUpdateFlag::Path) {
-        //TODO: Updated Vertices
-    }
+    if (sdata->updateFlag == RenderUpdateFlag::None) return nullptr;
 
-    if (flags & RenderUpdateFlag::Transform) {
-        //TODO: Updated Transform
-    }
+    initShaders();
+
+    sdata->geometry = make_unique<GlGeometry>();
 
-    //TODO:
+    //invisible?
+    uint8_t alphaF, alphaS;
+    shape.fill(nullptr, nullptr, nullptr, &alphaF);
+    shape.strokeColor(nullptr, nullptr, nullptr, &alphaS);
+    auto strokeWd = shape.strokeWidth();
 
+    if (alphaF == 0 && alphaS == 0) return sdata;
+
+    if (sdata->updateFlag & (RenderUpdateFlag::Color | RenderUpdateFlag::Stroke) )
+    {
+        if (!sdata->geometry->decomposeOutline(shape)) return sdata;
+        if (!sdata->geometry->generateAAPoints(shape, static_cast<float>(strokeWd), sdata->updateFlag)) return sdata;
+        if (!sdata->geometry->tesselate(shape, sdata->viewWd, sdata->viewHt, sdata->updateFlag)) return sdata;
+    }
     return sdata;
 }
 
@@ -91,6 +145,10 @@ int GlRenderer::init()
 
 int GlRenderer::term()
 {
+    if (inst()->mColorProgram.get())
+    {
+        inst()->mColorProgram.reset(nullptr);
+    }
     return RenderInitializer::term(renderInit);
 }
 
@@ -114,4 +172,25 @@ GlRenderer* GlRenderer::inst()
 }
 
 
+void GlRenderer::initShaders()
+{
+    if (!mColorProgram.get())
+    {
+        shared_ptr<GlShader> shader = GlShader::gen(COLOR_VERT_SHADER, COLOR_FRAG_SHADER);
+        mColorProgram = GlProgram::gen(shader);
+    }
+    mColorProgram->load();
+    mColorUniformLoc = mColorProgram->getUniformLocation("uColor");
+    mVertexAttrLoc = mColorProgram->getAttributeLocation("aLocation");
+}
+
+
+void GlRenderer::drawPrimitive(GlGeometry& geometry, float r, float g, float b, float a, uint32_t primitiveIndex, RenderUpdateFlag flag)
+{
+    mColorProgram->setUniformValue(mColorUniformLoc, r, g, b, a);
+    geometry.draw(mVertexAttrLoc, primitiveIndex, flag);
+    geometry.disableVertex(mVertexAttrLoc);
+
+}
+
 #endif /* _TVG_GL_RENDERER_CPP_ */
old mode 100644 (file)
new mode 100755 (executable)
index 3ef0ee9..5214a63
@@ -18,9 +18,8 @@
 #define _TVG_GL_RENDERER_H_
 
 #include "tvgGlCommon.h"
+#include "tvgGlProgram.h"
 
-namespace tvg
-{
 
 class GlRenderer : public RenderMethod
 {
@@ -30,10 +29,8 @@ public:
     void* prepare(const Shape& shape, void* data, const RenderTransform* transform, RenderUpdateFlag flags) override;
     bool dispose(const Shape& shape, void *data) override;
     bool render(const Shape& shape, void *data) override;
-    bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h)
-    {
-        return 0;
-    };
+    bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h);
+    void flush();
     bool clear() override;
     uint32_t ref() override;
     uint32_t unref() override;
@@ -46,11 +43,12 @@ private:
     GlRenderer(){};
     ~GlRenderer(){};
 
-    std::unique_ptr<GlProgram>   mColorProgram;
-    int32_t   mColorUniform;
-    uint32_t  mVertexAttrID;
-};
+    void initShaders();
+    void drawPrimitive(GlGeometry& geometry, float r, float g, float b, float a, uint32_t primitiveIndex, RenderUpdateFlag flag);
 
-}
+    unique_ptr<GlProgram>   mColorProgram;
+    int32_t   mColorUniformLoc;
+    uint32_t  mVertexAttrLoc;
+};
 
 #endif /* _TVG_GL_RENDERER_H_ */
diff --git a/src/lib/gl_engine/tvgGlShader.cpp b/src/lib/gl_engine/tvgGlShader.cpp
new file mode 100755 (executable)
index 0000000..a655159
--- /dev/null
@@ -0,0 +1,77 @@
+#include "tvgGlCommon.h"
+#include "tvgGlShader.h"
+
+#include <GLES2/gl2.h>
+
+
+shared_ptr<GlShader> GlShader::gen(const char * vertSrc, const char * fragSrc)
+{
+    shared_ptr<GlShader> shader = make_shared<GlShader>();
+    shader->createShader(vertSrc, fragSrc);
+    return shader;
+}
+
+
+GlShader::~GlShader()
+{
+    glDeleteShader(mVtShader);
+    glDeleteShader(mFrShader);
+}
+
+uint32_t GlShader::getVertexShader()
+{
+    return mVtShader;
+}
+
+
+uint32_t GlShader::getFragmentShader()
+{
+    return mFrShader;
+}
+
+
+void GlShader::createShader(const char* vertSrc, const char* fragSrc)
+{
+    mVtShader = complileShader(GL_VERTEX_SHADER, const_cast<char*>(vertSrc));
+    mFrShader = complileShader(GL_FRAGMENT_SHADER, const_cast<char*>(fragSrc));
+}
+
+
+uint32_t GlShader::complileShader(uint32_t type, char* shaderSrc)
+{
+    GLuint shader;
+    GLint compiled;
+
+    // Create the shader object
+    shader = glCreateShader(type);
+    assert(shader);
+
+    // Load the shader source
+    glShaderSource(shader, 1, &shaderSrc, NULL);
+
+    // Compile the shader
+    glCompileShader(shader);
+
+    // Check the compile status
+    glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
+
+    if (!compiled)
+    {
+        GLint infoLen = 0;
+
+        glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
+
+        if (infoLen > 0)
+        {
+            char* infoLog = new char[infoLen];
+            glGetShaderInfoLog(shader, infoLen, NULL, infoLog);
+            std::cout << "Error compiling shader: " << infoLog << std::endl;
+            delete[] infoLog;
+        }
+        glDeleteShader(shader);
+        assert(0);
+    }
+
+    return shader;
+}
+
old mode 100644 (file)
new mode 100755 (executable)
index 36b125a..85bf116
@@ -1,10 +1,13 @@
 #ifndef _TVG_GL_SHADER_H_
 #define _TVG_GL_SHADER_H_
 
+#include <memory>
+
 class GlShader
 {
 public:
-    static shared_ptr<GlShader> gen(const char * vertSrc, const char * fragSrc);
+    static std::shared_ptr<GlShader> gen(const char * vertSrc, const char * fragSrc);
+    ~GlShader();
 
     uint32_t getVertexShader();
     uint32_t getFragmentShader();
diff --git a/src/lib/gl_engine/tvgGlShaderSrc.cpp b/src/lib/gl_engine/tvgGlShaderSrc.cpp
new file mode 100755 (executable)
index 0000000..cdd25f0
--- /dev/null
@@ -0,0 +1,22 @@
+#include "tvgGlShaderSrc.h"
+
+const char* COLOR_VERT_SHADER =
+"attribute highp vec4 aLocation;                \n"
+"uniform highp vec4 uColor;                     \n"
+"varying highp vec4 vcolor;                     \n"
+"varying highp float vOpacity;                  \n"
+"void main()                                    \n"
+"{                                              \n"
+"   gl_Position = vec4(aLocation.xy, 0.0, 1.0); \n"
+"   vcolor = uColor;                            \n"
+"   vOpacity = aLocation.z;                     \n"
+"}                                              \n";
+
+const char* COLOR_FRAG_SHADER =
+"varying highp vec4 vcolor;                             \n"
+"varying highp float vOpacity;                          \n"
+"void main()                                            \n"
+"{                                                      \n"
+"  gl_FragColor = vec4(vcolor.xyz, vcolor.w*vOpacity);  \n"
+"}                                                      \n";
+
diff --git a/src/lib/gl_engine/tvgGlShaderSrc.h b/src/lib/gl_engine/tvgGlShaderSrc.h
new file mode 100755 (executable)
index 0000000..e6d3b91
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef _TVG_GL_SHADERSRC_H_
+#define _TVG_GL_SHADERSRC_H_
+
+extern const char* COLOR_VERT_SHADER;
+extern const char* COLOR_FRAG_SHADER;
+
+#endif /* _TVG_GL_SHADERSRC_H_ */
old mode 100644 (file)
new mode 100755 (executable)
index 7d3903c..80a0017
@@ -59,6 +59,10 @@ Result GlCanvas::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t
 
 Result GlCanvas::sync() noexcept
 {
+    auto renderer = dynamic_cast<GlRenderer*>(Canvas::pImpl.get()->renderer);
+    assert(renderer);
+
+    renderer->flush();
     return Result::Success;
 }
 
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index 8dce9e9..aca250b
@@ -15,5 +15,6 @@ all:
        gcc -o testLinearGradient testLinearGradient.cpp -g -lstdc++ `pkg-config --cflags --libs elementary tizenvg`
        gcc -o testRadialGradient testRadialGradient.cpp -g -lstdc++ `pkg-config --cflags --libs elementary tizenvg`
        gcc -o testGradientTransform testGradientTransform.cpp -g -lstdc++ `pkg-config --cflags --libs elementary tizenvg`
-       gcc -o testSvg testSvg.cpp -g -lstdc++ `pkg-config --cflags --libs elementary tizenvg`
-       gcc -o testSvg2 testSvg2.cpp -g -lstdc++ `pkg-config --cflags --libs elementary tizenvg`
+#      gcc -o testSvg testSvg.cpp -g -lstdc++ `pkg-config --cflags --libs elementary tizenvg`
+#      gcc -o testSvg2 testSvg2.cpp -g -lstdc++ `pkg-config --cflags --libs elementary tizenvg`
+       gcc -o testGlShape testGlShape.cpp -g -lstdc++ `pkg-config --cflags --libs elementary tizenvg`
diff --git a/test/testGlShape.cpp b/test/testGlShape.cpp
new file mode 100755 (executable)
index 0000000..077057e
--- /dev/null
@@ -0,0 +1,113 @@
+#include <tizenvg.h>
+#include <Elementary.h>
+
+using namespace std;
+
+#define WIDTH   800
+#define HEIGHT  800
+#define BPP     4
+static Evas_GL_API *glapi;
+static unique_ptr<tvg::GlCanvas> canvas;
+
+static void
+tvgtest()
+{
+    //Initialize TizenVG Engine
+    tvg::Initializer::init(tvg::CanvasEngine::Gl);
+
+
+    //Create a Canvas
+    canvas = tvg::GlCanvas::gen();
+    canvas->target(nullptr, WIDTH * BPP, WIDTH, HEIGHT);
+
+    //Prepare a Shape (Rectangle + Rectangle + Circle + Circle)
+    auto shape1 = tvg::Shape::gen();
+    shape1->appendRect(0, 0, 200, 200, 0);          //x, y, w, h, cornerRadius
+    shape1->appendRect(100, 100, 300, 300, 100);    //x, y, w, h, cornerRadius
+    shape1->appendCircle(400, 400, 100, 100);       //cx, cy, radiusW, radiusH
+    shape1->appendCircle(400, 500, 170, 100);       //cx, cy, radiusW, radiusH
+    shape1->fill(255, 255, 0, 255);                 //r, g, b, a
+    shape1->stroke(255, 0, 0, 255);                 //r, g, b, a
+    shape1->stroke(10.0f);
+
+    /* Push the shape into the Canvas drawing list
+       When this shape is into the canvas list, the shape could update & prepare
+       internal data asynchronously for coming rendering.
+       Canvas keeps this shape node unless user call canvas->clear() */
+    canvas->push(move(shape1));
+}
+
+static void
+init_gl(Evas_Object *obj)
+{
+    tvgtest();
+}
+
+static void
+del_gl(Evas_Object *obj)
+{
+    //Terminate TizenVG Engine
+    tvg::Initializer::term(tvg::CanvasEngine::Gl);
+}
+
+static void
+draw_gl(Evas_Object *obj)
+{
+    Evas_GL_API *gl = elm_glview_gl_api_get(obj);
+    int w, h;
+    elm_glview_size_get(obj, &w, &h);
+    gl->glViewport(0, 0, w, h);
+    gl->glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+    gl->glClear(GL_COLOR_BUFFER_BIT);
+    gl->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+    gl->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);
+    gl->glEnable(GL_BLEND);
+
+    canvas->draw();
+    canvas->sync();
+}
+
+void
+win_del(void *data, Evas_Object *o, void *ev)
+{
+    elm_exit();
+}
+
+int main(int argc, char **argv)
+{
+    //Show the result using EFL...
+    elm_init(argc, argv);
+
+    Eo* win = elm_win_util_standard_add(nullptr, "TizenVG Test");
+    evas_object_smart_callback_add(win, "delete,request", win_del, 0);
+
+    // create a new glview object
+    Eo* gl = elm_glview_add(win);
+    glapi = elm_glview_gl_api_get(gl);
+    evas_object_size_hint_align_set(gl, EVAS_HINT_FILL, EVAS_HINT_FILL);
+    evas_object_size_hint_weight_set(gl, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+
+    elm_glview_mode_set(gl, ELM_GLVIEW_ALPHA);
+    elm_glview_resize_policy_set(gl, ELM_GLVIEW_RESIZE_POLICY_RECREATE);
+    elm_glview_render_policy_set(gl, ELM_GLVIEW_RENDER_POLICY_ON_DEMAND);
+
+    evas_object_resize(gl, WIDTH, HEIGHT);
+
+    // initialize callback function gets registered here
+    elm_glview_init_func_set(gl, init_gl);
+    // delete callback function gets registered here
+    elm_glview_del_func_set(gl, del_gl);
+    elm_glview_render_func_set(gl, draw_gl);
+
+    evas_object_show(gl);
+
+    elm_object_focus_set(gl, EINA_TRUE);
+
+    evas_object_geometry_set(win, 0, 0, WIDTH, HEIGHT);
+    evas_object_show(win);
+
+    elm_run();
+    elm_shutdown();
+
+    return 0;
+}