mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 05:33:36 +00:00
gl_engine: implement gl infrastructure interfaces & test Gl shape sample
Change-Id: Ie142616bf02f9bd50ac8e88e31ed9f782dd6324b Signed-off-by: Pranay Kumar Samanta <pranay.ks@samsung.com>
This commit is contained in:
parent
ec03afa83a
commit
968286df57
20 changed files with 904 additions and 67 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -19,3 +19,4 @@ testRadialGradient
|
||||||
testGradientTransform
|
testGradientTransform
|
||||||
testSvg
|
testSvg
|
||||||
testSvg2
|
testSvg2
|
||||||
|
testGlShape
|
||||||
|
|
6
src/lib/gl_engine/meson.build
Normal file → Executable file
6
src/lib/gl_engine/meson.build
Normal file → Executable file
|
@ -5,7 +5,13 @@ source_file = [
|
||||||
'tvgGlProgram.h',
|
'tvgGlProgram.h',
|
||||||
'tvgGlRenderer.h',
|
'tvgGlRenderer.h',
|
||||||
'tvgGlShader.h',
|
'tvgGlShader.h',
|
||||||
|
'tvgGlShaderSrc.h',
|
||||||
|
'tvgGlGeometry.cpp',
|
||||||
|
'tvgGlGpuBuffer.cpp',
|
||||||
|
'tvgGlProgram.cpp',
|
||||||
'tvgGlRenderer.cpp',
|
'tvgGlRenderer.cpp',
|
||||||
|
'tvgGlShader.cpp',
|
||||||
|
'tvgGlShaderSrc.cpp',
|
||||||
]
|
]
|
||||||
|
|
||||||
glraster_dep = declare_dependency(
|
glraster_dep = declare_dependency(
|
||||||
|
|
26
src/lib/gl_engine/tvgGlCommon.h
Normal file → Executable file
26
src/lib/gl_engine/tvgGlCommon.h
Normal file → Executable file
|
@ -2,11 +2,31 @@
|
||||||
#define _TVG_GL_COMMON_H_
|
#define _TVG_GL_COMMON_H_
|
||||||
|
|
||||||
#include "tvgCommon.h"
|
#include "tvgCommon.h"
|
||||||
#include "tvgGlProgram.h"
|
|
||||||
#include "tvgGlShader.h"
|
|
||||||
#include "tvgGlGeometry.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
#define GL_CHECK(x) \
|
||||||
|
x; \
|
||||||
|
do { \
|
||||||
|
GLenum glError = glGetError(); \
|
||||||
|
if(glError != GL_NO_ERROR) { \
|
||||||
|
printf("glGetError() = %i (0x%.8x) at line %s : %i\n", glError, glError, __FILE__, __LINE__); \
|
||||||
|
assert(0); \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define EGL_CHECK(x) \
|
||||||
|
x; \
|
||||||
|
do { \
|
||||||
|
EGLint eglError = eglGetError(); \
|
||||||
|
if(eglError != EGL_SUCCESS) { \
|
||||||
|
printf("eglGetError() = %i (0x%.8x) at line %s : %i\n", eglError, eglError, __FILE__, __LINE__); \
|
||||||
|
assert(0); \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
|
||||||
|
class GlGeometry;
|
||||||
|
|
||||||
struct GlShape
|
struct GlShape
|
||||||
{
|
{
|
||||||
float viewWd;
|
float viewWd;
|
||||||
|
|
319
src/lib/gl_engine/tvgGlGeometry.cpp
Executable file
319
src/lib/gl_engine/tvgGlGeometry.cpp
Executable file
|
@ -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);
|
||||||
|
}
|
||||||
|
|
62
src/lib/gl_engine/tvgGlGeometry.h
Normal file → Executable file
62
src/lib/gl_engine/tvgGlGeometry.h
Normal file → Executable file
|
@ -1,7 +1,7 @@
|
||||||
#ifndef _TVG_GL_GEOMETRY_H_
|
#ifndef _TVG_GL_GEOMETRY_H_
|
||||||
#define _TVG_GL_GEOMETRY_H_
|
#define _TVG_GL_GEOMETRY_H_
|
||||||
|
|
||||||
#include "tvgGlGpuBuffer.h"
|
#include "tvgGlCommon.h"
|
||||||
|
|
||||||
class GlPoint
|
class GlPoint
|
||||||
{
|
{
|
||||||
|
@ -9,6 +9,8 @@ public:
|
||||||
float x = 0.0f;
|
float x = 0.0f;
|
||||||
float y = 0.0f;
|
float y = 0.0f;
|
||||||
|
|
||||||
|
GlPoint() = default;
|
||||||
|
|
||||||
GlPoint(float pX, float pY):x(pX), y(pY)
|
GlPoint(float pX, float pY):x(pX), y(pY)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
@ -145,36 +147,42 @@ struct VertexDataArray
|
||||||
vector<uint32_t> indices;
|
vector<uint32_t> indices;
|
||||||
};
|
};
|
||||||
|
|
||||||
class GlGeometry
|
struct GlPrimitive
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
GlGeometry();
|
|
||||||
void reset();
|
|
||||||
void updateBuffer(const uint32_t location, const VertexDataArray& geometry);
|
|
||||||
void draw(const VertexDataArray& geometry);
|
|
||||||
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();
|
|
||||||
|
|
||||||
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);
|
|
||||||
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);
|
|
||||||
|
|
||||||
unique_ptr<GlGpuBuffer> mGpuBuffer;
|
|
||||||
vector<SmoothPoint> mAAPoints;
|
vector<SmoothPoint> mAAPoints;
|
||||||
VertexDataArray mFill;
|
VertexDataArray mFill;
|
||||||
VertexDataArray mStroke;
|
VertexDataArray mStroke;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class GlGpuBuffer;
|
||||||
|
|
||||||
|
class GlGeometry
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
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);
|
||||||
|
void disableVertex(uint32_t location);
|
||||||
|
void draw(const uint32_t location, const uint32_t primitiveIndex, RenderUpdateFlag flag);
|
||||||
|
|
||||||
|
private:
|
||||||
|
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(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<GlPrimitive> mPrimitives;
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* _TVG_GL_GEOMETRY_H_ */
|
#endif /* _TVG_GL_GEOMETRY_H_ */
|
||||||
|
|
32
src/lib/gl_engine/tvgGlGpuBuffer.cpp
Executable file
32
src/lib/gl_engine/tvgGlGpuBuffer.cpp
Executable file
|
@ -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));
|
||||||
|
}
|
4
src/lib/gl_engine/tvgGlGpuBuffer.h
Normal file → Executable file
4
src/lib/gl_engine/tvgGlGpuBuffer.h
Normal file → Executable file
|
@ -15,8 +15,8 @@ public:
|
||||||
|
|
||||||
GlGpuBuffer();
|
GlGpuBuffer();
|
||||||
~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:
|
private:
|
||||||
uint32_t mGlBufferId = 0;
|
uint32_t mGlBufferId = 0;
|
||||||
|
|
||||||
|
|
144
src/lib/gl_engine/tvgGlProgram.cpp
Executable file
144
src/lib/gl_engine/tvgGlProgram.cpp
Executable file
|
@ -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;
|
||||||
|
}
|
||||||
|
|
13
src/lib/gl_engine/tvgGlProgram.h
Normal file → Executable file
13
src/lib/gl_engine/tvgGlProgram.h
Normal file → Executable file
|
@ -3,22 +3,25 @@
|
||||||
|
|
||||||
#include "tvgGlShader.h"
|
#include "tvgGlShader.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
|
||||||
class GlProgram
|
class GlProgram
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GlProgram(shared_ptr<GlShader> shader);
|
static std::unique_ptr<GlProgram> gen(std::shared_ptr<GlShader> shader);
|
||||||
void create();
|
GlProgram(std::shared_ptr<GlShader> shader);
|
||||||
|
~GlProgram();
|
||||||
|
|
||||||
void load();
|
void load();
|
||||||
|
void unload();
|
||||||
int32_t getAttributeLocation(const char* name);
|
int32_t getAttributeLocation(const char* name);
|
||||||
int32_t getUniformLocation(const char* name);
|
int32_t getUniformLocation(const char* name);
|
||||||
void setUniformValue(int32_t location, float r, float g, float b, float a);
|
void setUniformValue(int32_t location, float r, float g, float b, float a);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void linkProgram();
|
|
||||||
std::shared_ptr<GlShader> mShader;
|
void linkProgram(std::shared_ptr<GlShader> shader);
|
||||||
uint32_t mProgramObj;
|
uint32_t mProgramObj;
|
||||||
static uint32_t mCurrentProgram;
|
static uint32_t mCurrentProgram;
|
||||||
|
|
||||||
|
|
111
src/lib/gl_engine/tvgGlRenderer.cpp
Normal file → Executable file
111
src/lib/gl_engine/tvgGlRenderer.cpp
Normal file → Executable file
|
@ -17,7 +17,10 @@
|
||||||
#ifndef _TVG_GL_RENDERER_CPP_
|
#ifndef _TVG_GL_RENDERER_CPP_
|
||||||
#define _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"
|
#include "tvgGlRenderer.h"
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
@ -33,16 +36,55 @@ static RenderInitializer renderInit;
|
||||||
bool GlRenderer::clear()
|
bool GlRenderer::clear()
|
||||||
{
|
{
|
||||||
//TODO: (Request) to clear target
|
//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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GlRenderer::flush()
|
||||||
|
{
|
||||||
|
GL_CHECK(glFinish());
|
||||||
|
mColorProgram->unload();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool GlRenderer::render(const Shape& shape, void *data)
|
bool GlRenderer::render(const Shape& shape, void *data)
|
||||||
{
|
{
|
||||||
GlShape* sdata = static_cast<GlShape*>(data);
|
GlShape* sdata = static_cast<GlShape*>(data);
|
||||||
if (!sdata) return false;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -53,9 +95,7 @@ bool GlRenderer::dispose(const Shape& shape, void *data)
|
||||||
GlShape* sdata = static_cast<GlShape*>(data);
|
GlShape* sdata = static_cast<GlShape*>(data);
|
||||||
if (!sdata) return false;
|
if (!sdata) return false;
|
||||||
|
|
||||||
//TODO:
|
delete sdata;
|
||||||
|
|
||||||
free(sdata);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,21 +104,35 @@ void* GlRenderer::prepare(const Shape& shape, void* data, const RenderTransform*
|
||||||
{
|
{
|
||||||
//prepare shape data
|
//prepare shape data
|
||||||
GlShape* sdata = static_cast<GlShape*>(data);
|
GlShape* sdata = static_cast<GlShape*>(data);
|
||||||
if (!sdata) {
|
if (!sdata)
|
||||||
sdata = static_cast<GlShape*>(calloc(1, sizeof(GlShape)));
|
{
|
||||||
|
sdata = new GlShape;
|
||||||
assert(sdata);
|
assert(sdata);
|
||||||
}
|
}
|
||||||
|
sdata->viewWd = static_cast<float>(surface.w);
|
||||||
|
sdata->viewHt = static_cast<float>(surface.h);
|
||||||
|
sdata->updateFlag = flags;
|
||||||
|
|
||||||
if (flags & RenderUpdateFlag::Path) {
|
if (sdata->updateFlag == RenderUpdateFlag::None) return nullptr;
|
||||||
//TODO: Updated Vertices
|
|
||||||
|
initShaders();
|
||||||
|
|
||||||
|
sdata->geometry = make_unique<GlGeometry>();
|
||||||
|
|
||||||
|
//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;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & RenderUpdateFlag::Transform) {
|
|
||||||
//TODO: Updated Transform
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO:
|
|
||||||
|
|
||||||
return sdata;
|
return sdata;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,6 +145,10 @@ int GlRenderer::init()
|
||||||
|
|
||||||
int GlRenderer::term()
|
int GlRenderer::term()
|
||||||
{
|
{
|
||||||
|
if (inst()->mColorProgram.get())
|
||||||
|
{
|
||||||
|
inst()->mColorProgram.reset(nullptr);
|
||||||
|
}
|
||||||
return RenderInitializer::term(renderInit);
|
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_ */
|
#endif /* _TVG_GL_RENDERER_CPP_ */
|
||||||
|
|
20
src/lib/gl_engine/tvgGlRenderer.h
Normal file → Executable file
20
src/lib/gl_engine/tvgGlRenderer.h
Normal file → Executable file
|
@ -18,9 +18,8 @@
|
||||||
#define _TVG_GL_RENDERER_H_
|
#define _TVG_GL_RENDERER_H_
|
||||||
|
|
||||||
#include "tvgGlCommon.h"
|
#include "tvgGlCommon.h"
|
||||||
|
#include "tvgGlProgram.h"
|
||||||
|
|
||||||
namespace tvg
|
|
||||||
{
|
|
||||||
|
|
||||||
class GlRenderer : public RenderMethod
|
class GlRenderer : public RenderMethod
|
||||||
{
|
{
|
||||||
|
@ -30,10 +29,8 @@ public:
|
||||||
void* prepare(const Shape& shape, void* data, const RenderTransform* transform, RenderUpdateFlag flags) override;
|
void* prepare(const Shape& shape, void* data, const RenderTransform* transform, RenderUpdateFlag flags) override;
|
||||||
bool dispose(const Shape& shape, void *data) override;
|
bool dispose(const Shape& shape, void *data) override;
|
||||||
bool render(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)
|
bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h);
|
||||||
{
|
void flush();
|
||||||
return 0;
|
|
||||||
};
|
|
||||||
bool clear() override;
|
bool clear() override;
|
||||||
uint32_t ref() override;
|
uint32_t ref() override;
|
||||||
uint32_t unref() override;
|
uint32_t unref() override;
|
||||||
|
@ -46,11 +43,12 @@ private:
|
||||||
GlRenderer(){};
|
GlRenderer(){};
|
||||||
~GlRenderer(){};
|
~GlRenderer(){};
|
||||||
|
|
||||||
std::unique_ptr<GlProgram> mColorProgram;
|
void initShaders();
|
||||||
int32_t mColorUniform;
|
void drawPrimitive(GlGeometry& geometry, float r, float g, float b, float a, uint32_t primitiveIndex, RenderUpdateFlag flag);
|
||||||
uint32_t mVertexAttrID;
|
|
||||||
|
unique_ptr<GlProgram> mColorProgram;
|
||||||
|
int32_t mColorUniformLoc;
|
||||||
|
uint32_t mVertexAttrLoc;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _TVG_GL_RENDERER_H_ */
|
#endif /* _TVG_GL_RENDERER_H_ */
|
||||||
|
|
77
src/lib/gl_engine/tvgGlShader.cpp
Executable file
77
src/lib/gl_engine/tvgGlShader.cpp
Executable file
|
@ -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;
|
||||||
|
}
|
||||||
|
|
5
src/lib/gl_engine/tvgGlShader.h
Normal file → Executable file
5
src/lib/gl_engine/tvgGlShader.h
Normal file → Executable file
|
@ -1,10 +1,13 @@
|
||||||
#ifndef _TVG_GL_SHADER_H_
|
#ifndef _TVG_GL_SHADER_H_
|
||||||
#define _TVG_GL_SHADER_H_
|
#define _TVG_GL_SHADER_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
class GlShader
|
class GlShader
|
||||||
{
|
{
|
||||||
public:
|
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 getVertexShader();
|
||||||
uint32_t getFragmentShader();
|
uint32_t getFragmentShader();
|
||||||
|
|
22
src/lib/gl_engine/tvgGlShaderSrc.cpp
Executable file
22
src/lib/gl_engine/tvgGlShaderSrc.cpp
Executable file
|
@ -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";
|
||||||
|
|
7
src/lib/gl_engine/tvgGlShaderSrc.h
Executable file
7
src/lib/gl_engine/tvgGlShaderSrc.h
Executable file
|
@ -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_ */
|
4
src/lib/tvgGlCanvas.cpp
Normal file → Executable file
4
src/lib/tvgGlCanvas.cpp
Normal file → Executable file
|
@ -59,6 +59,10 @@ Result GlCanvas::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t
|
||||||
|
|
||||||
Result GlCanvas::sync() noexcept
|
Result GlCanvas::sync() noexcept
|
||||||
{
|
{
|
||||||
|
auto renderer = dynamic_cast<GlRenderer*>(Canvas::pImpl.get()->renderer);
|
||||||
|
assert(renderer);
|
||||||
|
|
||||||
|
renderer->flush();
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
0
src/lib/tvgRenderCommon.h
Normal file → Executable file
0
src/lib/tvgRenderCommon.h
Normal file → Executable file
0
src/lib/tvgShape.cpp
Normal file → Executable file
0
src/lib/tvgShape.cpp
Normal file → Executable file
5
test/makefile
Normal file → Executable file
5
test/makefile
Normal file → Executable file
|
@ -15,5 +15,6 @@ all:
|
||||||
gcc -o testLinearGradient testLinearGradient.cpp -g -lstdc++ `pkg-config --cflags --libs elementary tizenvg`
|
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 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 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 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 testSvg2 testSvg2.cpp -g -lstdc++ `pkg-config --cflags --libs elementary tizenvg`
|
||||||
|
gcc -o testGlShape testGlShape.cpp -g -lstdc++ `pkg-config --cflags --libs elementary tizenvg`
|
||||||
|
|
113
test/testGlShape.cpp
Executable file
113
test/testGlShape.cpp
Executable file
|
@ -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;
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue