common gl_engine: transformation support

support transformation of shapes some partial cases.
This commit is contained in:
pankajkumar20 2020-12-30 08:53:22 +05:30 committed by GitHub
parent c3d0a79d3e
commit f096570360
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 182 additions and 29 deletions

1
src/examples/CustomTransform.cpp Normal file → Executable file
View file

@ -154,6 +154,7 @@ void drawGLview(Evas_Object *obj)
void transitGlCb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progress)
{
tvgUpdateCmds(glCanvas.get(), progress);
elm_glview_changed_set((Evas_Object*)effect);
}

1
src/examples/DirectUpdate.cpp Normal file → Executable file
View file

@ -127,6 +127,7 @@ void drawGLview(Evas_Object *obj)
void transitGlCb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progress)
{
tvgUpdateCmds(glCanvas.get(), progress);
elm_glview_changed_set((Evas_Object*)effect);
}

1
src/examples/GradientTransform.cpp Normal file → Executable file
View file

@ -182,6 +182,7 @@ void drawGLview(Evas_Object *obj)
void transitGlCb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progress)
{
tvgUpdateCmds(glCanvas.get(), progress);
elm_glview_changed_set((Evas_Object*)effect);
}

1
src/examples/SceneTransform.cpp Normal file → Executable file
View file

@ -178,6 +178,7 @@ void drawGLview(Evas_Object *obj)
void transitGlCb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progress)
{
tvgUpdateCmds(glCanvas.get(), progress);
elm_glview_changed_set((Evas_Object*)effect);
}

1
src/examples/Transform.cpp Normal file → Executable file
View file

@ -145,6 +145,7 @@ void drawGLview(Evas_Object *obj)
void transitGlCb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progress)
{
tvgUpdateCmds(glCanvas.get(), progress);
elm_glview_changed_set((Evas_Object*)effect);
}

1
src/examples/Update.cpp Normal file → Executable file
View file

@ -106,6 +106,7 @@ void drawGLview(Evas_Object *obj)
void transitGlCb(Elm_Transit_Effect *effect, Elm_Transit* transit, double progress)
{
tvgUpdateCmds(glCanvas.get(), progress);
elm_glview_changed_set((Evas_Object*)effect);
}

2
src/lib/gl_engine/tvgGlCommon.h Normal file → Executable file
View file

@ -57,7 +57,7 @@ struct GlShape
const Shape* shape = nullptr;
float viewWd;
float viewHt;
RenderUpdateFlag updateFlag;
RenderUpdateFlag updateFlag = None;
unique_ptr<GlGeometry> geometry;
};

32
src/lib/gl_engine/tvgGlGeometry.cpp Normal file → Executable file
View file

@ -24,6 +24,10 @@
#include "tvgGlGpuBuffer.h"
#include "tvgGlGeometry.h"
#define NORMALIZED_TOP_3D 1.0f
#define NORMALIZED_BOTTOM_3D -1.0f
#define NORMALIZED_LEFT_3D -1.0f
#define NORMALIZED_RIGHT_3D 1.0f
uint32_t GlGeometry::getPrimitiveCount()
{
@ -172,12 +176,12 @@ bool GlGeometry::generateAAPoints(TVG_UNUSED const Shape& shape, float strokeWd,
else
normalInfo[i].normalF = GlPoint(0, 0);
if (flag & (RenderUpdateFlag::Color | RenderUpdateFlag::Gradient))
if (flag & (RenderUpdateFlag::Color | RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform))
{
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)
if (flag & (RenderUpdateFlag::Stroke | RenderUpdateFlag::Transform))
{
aaPts[i].strokeOuterBlur = aaPts[i].orgPt;
aaPts[i].strokeOuter = extendEdge(aaPts[i].strokeOuterBlur, normalInfo[i].normalF, blurDir*antiAliasWidth);
@ -200,7 +204,7 @@ bool GlGeometry::tesselate(TVG_UNUSED const Shape& shape, float viewWd, float vi
VertexDataArray& fill = shapeGeometry.mFill;
VertexDataArray& stroke = shapeGeometry.mStroke;
if (flag & (RenderUpdateFlag::Color | RenderUpdateFlag::Gradient) )
if (flag & (RenderUpdateFlag::Color | RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform) )
{
uint32_t i = 0;
for (size_t pt = 0; pt < aaPts.size(); ++pt)
@ -221,7 +225,7 @@ bool GlGeometry::tesselate(TVG_UNUSED const Shape& shape, float viewWd, float vi
addQuadIndices(i, fill.indices);
}
}
if (flag & RenderUpdateFlag::Stroke)
if (flag & (RenderUpdateFlag::Stroke | RenderUpdateFlag::Transform))
{
uint32_t i = 0;
for (size_t pt = 1; pt < aaPts.size(); ++pt)
@ -383,3 +387,23 @@ void GlGeometry::decomposeCubicCurve(GlPrimitive& primitve, const GlPoint& pt1,
decomposeCubicCurve(primitve, p1234, p234, p34, pt2, min, max);
}
void GlGeometry::updateTransform(const RenderTransform* transform, float w, float h)
{
if (transform)
{
mTransform.x = transform->x;
mTransform.y = transform->y;
mTransform.angle = transform->degree;
mTransform.scale = transform->scale;
}
mTransform.w = w;
mTransform.h = h;
GET_TRANSFORMATION(NORMALIZED_LEFT_3D, NORMALIZED_TOP_3D, mTransform.matrix);
}
float* GlGeometry::getTransforMatrix()
{
return mTransform.matrix;
}

53
src/lib/gl_engine/tvgGlGeometry.h Normal file → Executable file
View file

@ -27,6 +27,44 @@
#include <vector>
#include "tvgGlCommon.h"
#define PI 3.1415926535897932384626433832795f
#define MVP_MATRIX() \
float mvp[4*4] = { \
mTransform.scale, 0.0, 0.0f, 0.0f, \
0.0, mTransform.scale, 0.0f, 0.0f, \
0.0f, 0.0f, mTransform.scale, 0.0f, \
(mTransform.x * 2.0f) * (mTransform.scale / mTransform.w), -(mTransform.y * 2.0f) * (mTransform.scale / mTransform.h), 0.0f, 1.0f \
};
#define ROTATION_MATRIX(xPivot, yPivot) \
auto radian = mTransform.angle / 180.0f * PI; \
auto cosVal = cosf(radian); \
auto sinVal = sinf(radian); \
float rotate[4*4] = { \
cosVal, -sinVal, 0.0f, 0.0f, \
sinVal, cosVal, 0.0f, 0.0f,\
0.0f, 0.0f, 1.0f, 0.0f, \
(xPivot * (1.0f - cosVal)) - (yPivot * sinVal), (yPivot *(1.0f - cosVal)) + (xPivot * sinVal), 0.0f, 1.0f \
};
#define MULTIPLY_MATRIX(A, B, transform) \
for(auto i = 0; i < 4; ++i) \
{ \
for(auto j = 0; j < 4; ++j) \
{ \
float sum = 0.0; \
for (auto k = 0; k < 4; ++k) \
sum += A[k*4+i] * B[j*4+k]; \
transform[j*4+i] = sum; \
} \
}
#define GET_TRANSFORMATION(xPivot, yPivot, transform) \
MVP_MATRIX(); \
ROTATION_MATRIX(xPivot, yPivot); \
MULTIPLY_MATRIX(mvp, rotate, transform);
class GlPoint
{
public:
@ -183,6 +221,18 @@ struct GlPrimitive
bool mIsClosed = false;
};
struct GlTransform
{
float x = 0.0f;
float y = 0.0f;
float angle = 0.0f;
float scale = 1.0f;
float w;
float h;
float matrix[16];
};
class GlGpuBuffer;
class GlGeometry
@ -196,6 +246,8 @@ public:
bool tesselate(TVG_UNUSED 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);
void updateTransform(const RenderTransform* transform, float w, float h);
float* getTransforMatrix();
private:
GlPoint normalizePoint(const GlPoint &pt, float viewWd, float viewHt);
@ -213,6 +265,7 @@ private:
unique_ptr<GlGpuBuffer> mGpuBuffer;
vector<GlPrimitive> mPrimitives;
GlTransform mTransform;
};
#endif /* _TVG_GL_GEOMETRY_H_ */

4
src/lib/gl_engine/tvgGlProgram.cpp Normal file → Executable file
View file

@ -137,6 +137,10 @@ void GlProgram::setUniform4Value(int32_t location, int count, const float* value
GL_CHECK(glUniform4fv(location, count, values));
}
void GlProgram::setUniform4x4Value(int32_t location, int count, const float* values)
{
GL_CHECK(glUniformMatrix4fv(location, count, GL_FALSE, &values[0]));
}
void GlProgram::linkProgram(std::shared_ptr<GlShader> shader)
{

1
src/lib/gl_engine/tvgGlProgram.h Normal file → Executable file
View file

@ -45,6 +45,7 @@ public:
void setUniform2Value(int32_t location, int count, const float* values);
void setUniform3Value(int32_t location, int count, const float* values);
void setUniform4Value(int32_t location, int count, const float* values);
void setUniform4x4Value(int32_t location, int count, const float* values);
private:

19
src/lib/gl_engine/tvgGlPropertyInterface.cpp Normal file → Executable file
View file

@ -33,7 +33,7 @@ VertexProperty PropertyInterface::mEmptyProperty;
/* External Class Implementation */
/************************************************************************/
VertexProperty& PropertyInterface::addProperty(GlRenderTask* rTask, std::shared_ptr<GlProgram> prog, std::string name, uint32_t propFormatSize, VertexProperty::PropertyType propType)
VertexProperty& PropertyInterface::addProperty(GlRenderTask* rTask, std::shared_ptr<GlProgram> prog, std::string name, uint32_t propFormatSize, VertexProperty::PropertyType propType, VertexProperty::DataType dataType)
{
std::map<int32_t, VertexProperty>* vertexProperty = nullptr;
int32_t id;
@ -52,7 +52,7 @@ VertexProperty& PropertyInterface::addProperty(GlRenderTask* rTask, std::shared_
}
if (id != -1)
{
VertexProperty property = { id, name, propType, VertexProperty::DataType::FLOAT };
VertexProperty property = { id, name, propType, dataType };
property.propertyValues.setStride(propFormatSize);
if (vertexProperty)
{
@ -64,6 +64,21 @@ VertexProperty& PropertyInterface::addProperty(GlRenderTask* rTask, std::shared_
}
void PropertyInterface::setProperty(GlRenderTask* rTask, int32_t propId, int32_t count, float* data)
{
std::map<int32_t, VertexProperty>::iterator itr = rTask->getUniformVertexProperty().find(propId);
if (itr->second.propertyId == -1)
{
return;
}
VertexProperty& prop = itr->second;
for (int i = 0; i < count; ++i)
{
prop.propertyValues.set(data[i]);
}
}
int32_t PropertyInterface::getPropertyId(GlRenderTask* rTask, std::string name)
{
std::map<int32_t, VertexProperty>& vertexProperty = rTask->getUniformVertexProperty();

11
src/lib/gl_engine/tvgGlPropertyInterface.h Normal file → Executable file
View file

@ -36,15 +36,21 @@
if (var->propertyId != -1) \
location = var->propertyId
#define ADD_UNIFORM_PROPERTY_2(var, rtask, prog, varName, formatSize, location, datatype) \
var = &PropertyInterface::addProperty(rtask, prog, varName, formatSize, VertexProperty::PropertyType::UNIFORM, datatype); \
if (var->propertyId != -1) \
location = var->propertyId
#define FORMAT_SIZE_FLOAT 1
#define FORMAT_SIZE_VEC_2 2
#define FORMAT_SIZE_VEC_3 3
#define FORMAT_SIZE_VEC_4 4
#define FORMAT_SIZE_MAT_4x4 16
class PropertyInterface
{
public:
static VertexProperty& addProperty(GlRenderTask* rTask, std::shared_ptr<GlProgram> prog, std::string name, uint32_t propFormatSize, VertexProperty::PropertyType propType);
static VertexProperty& addProperty(GlRenderTask* rTask, std::shared_ptr<GlProgram> prog, std::string name, uint32_t propFormatSize, VertexProperty::PropertyType propType, VertexProperty::DataType dataType = VertexProperty::DataType::FLOAT);
template<typename... Args>
static void setProperty(GlRenderTask* rTask, std::string name, float first, Args... args)
{
@ -65,9 +71,10 @@ public:
}
VertexProperty& prop = itr->second;
prop.dataType = VertexProperty::DataType::FLOAT;
prop.propertyValues.set(first, args...);
}
static void setProperty(GlRenderTask* rTask, int32_t propId, int32_t count, float* data);
static int32_t getPropertyId(GlRenderTask* rTask, std::string name);
static VertexProperty& getProperty(GlRenderTask* rTask, std::string name);
static VertexProperty& getProperty(GlRenderTask* rTask, int32_t propId);

19
src/lib/gl_engine/tvgGlRenderTask.cpp Normal file → Executable file
View file

@ -37,6 +37,7 @@ GlRenderTask::GlRenderTask(RenderTypes renderType, shared_ptr<GlShader> shader)
VertexProperty* prop = nullptr;
ADD_ATTRIBUTE_PROPERTY(prop, this, mProgram, "aLocation", FORMAT_SIZE_VEC_4, mLocVertexAttribute);
ADD_UNIFORM_PROPERTY_2(prop, this, mProgram, "uTransform", FORMAT_SIZE_MAT_4x4, mLocTransform, VertexProperty::DataType::MATRIX);
}
@ -82,6 +83,20 @@ int32_t GlRenderTask::getLocationPropertyId() const
}
int32_t GlRenderTask::getTransformLocationPropertyId() const
{
return mLocTransform;
}
void GlRenderTask::setTransform(int count, float* transform)
{
if (mLocTransform != -1)
{
PropertyInterface::setProperty(this, mLocTransform, count, transform);
}
}
void GlRenderTask::uploadValues()
{
for (auto& property : mUniformPropertyBuffer)
@ -122,6 +137,10 @@ void GlRenderTask::uploadValues()
}
break;
}
case VertexProperty::DataType::MATRIX: {
mProgram->setUniform4x4Value(property.second.propertyId, propertyVal.getCount(), propertyVal.getData());
break;
}
}
}
}

11
src/lib/gl_engine/tvgGlRenderTask.h Normal file → Executable file
View file

@ -48,6 +48,8 @@ public:
std::map<int32_t, VertexProperty>& getAttributeVertexProperty();
std::map<int32_t, VertexProperty>& getUniformVertexProperty();
int32_t getLocationPropertyId() const;
int32_t getTransformLocationPropertyId() const;
void setTransform(int count, float* transform_matrix);
void uploadValues();
private:
@ -58,7 +60,8 @@ private:
std::map<int32_t, VertexProperty> mAttributePropertyBuffer;
std::map<int32_t, VertexProperty> mUniformPropertyBuffer;
int32_t mLocVertexAttribute;
int32_t mLocVertexAttribute = -1;
int32_t mLocTransform = -1;
};
class GlColorRenderTask : public GlRenderTask
@ -81,14 +84,14 @@ public:
void setNoise(float noise);
void setStopCount(int32_t count);
void setStopColor(int index, float stopVal, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
int32_t getTransformLocationPropertyId() const;
private:
int32_t mLocPrimitiveSize = -1;
int32_t mLocCanvasSize = -1;
int32_t mLocNoise = -1;
int32_t mLocStopCnt = -1;
int32_t mLocStops;
int32_t mLocStopColors;
int32_t mLocStops = -1;
int32_t mLocStopColors = -1;
};
class GlLinearGradientRenderTask : public GlGradientRenderTask

34
src/lib/gl_engine/tvgGlRenderer.cpp Normal file → Executable file
View file

@ -135,20 +135,31 @@ bool GlRenderer::renderShape(RenderData data, TVG_UNUSED Compositor* cmp)
uint32_t primitiveCount = sdata->geometry->getPrimitiveCount();
for (uint32_t i = 0; i < primitiveCount; ++i)
{
if (flags & RenderUpdateFlag::Gradient)
if (flags & (RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform))
{
const Fill* gradient = sdata->shape->fill();
drawPrimitive(*sdata, gradient, i, RenderUpdateFlag::Gradient);
if (gradient != nullptr)
{
drawPrimitive(*sdata, gradient, i, RenderUpdateFlag::Gradient);
}
}
else if (flags & RenderUpdateFlag::Color)
if(flags & (RenderUpdateFlag::Color | RenderUpdateFlag::Transform))
{
sdata->shape->fillColor(&r, &g, &b, &a);
drawPrimitive(*sdata, r, g, b, a, i, RenderUpdateFlag::Color);
if (a > 0)
{
drawPrimitive(*sdata, r, g, b, a, i, RenderUpdateFlag::Color);
}
}
if (flags & RenderUpdateFlag::Stroke)
if (flags & (RenderUpdateFlag::Stroke | RenderUpdateFlag::Transform))
{
sdata->shape->strokeColor(&r, &g, &b, &a);
drawPrimitive(*sdata, r, g, b, a, i, RenderUpdateFlag::Stroke);
if (a > 0)
{
drawPrimitive(*sdata, r, g, b, a, i, RenderUpdateFlag::Stroke);
}
}
}
@ -173,7 +184,7 @@ RenderData GlRenderer::prepare(TVG_UNUSED const Picture& picture, TVG_UNUSED Ren
}
RenderData GlRenderer::prepare(const Shape& shape, RenderData data, TVG_UNUSED const RenderTransform* transform, TVG_UNUSED uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags)
RenderData GlRenderer::prepare(const Shape& shape, RenderData data, const RenderTransform* transform, TVG_UNUSED uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flags)
{
//prepare shape data
GlShape* sdata = static_cast<GlShape*>(data);
@ -204,7 +215,9 @@ RenderData GlRenderer::prepare(const Shape& shape, RenderData data, TVG_UNUSED c
return sdata;
}
if (sdata->updateFlag & (RenderUpdateFlag::Color | RenderUpdateFlag::Stroke | RenderUpdateFlag::Gradient) )
sdata->geometry->updateTransform(transform, sdata->viewWd, sdata->viewHt);
if (sdata->updateFlag & (RenderUpdateFlag::Color | RenderUpdateFlag::Stroke | RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform) )
{
if (!sdata->geometry->decomposeOutline(shape)) return sdata;
if (!sdata->geometry->generateAAPoints(shape, static_cast<float>(strokeWd), sdata->updateFlag)) return sdata;
@ -272,8 +285,10 @@ void GlRenderer::drawPrimitive(GlShape& sdata, uint8_t r, uint8_t g, uint8_t b,
GlColorRenderTask* renderTask = static_cast<GlColorRenderTask*>(mRenderTasks[GlRenderTask::RenderTypes::RT_Color].get());
assert(renderTask);
renderTask->load();
float* matrix = sdata.geometry->getTransforMatrix();
PropertyInterface::clearData(renderTask);
renderTask->setColor(r, g, b, a);
renderTask->setTransform(FORMAT_SIZE_MAT_4x4, matrix);
int32_t vertexLoc = renderTask->getLocationPropertyId();
renderTask->uploadValues();
sdata.geometry->draw(vertexLoc, primitiveIndex, flag);
@ -292,6 +307,8 @@ void GlRenderer::drawPrimitive(GlShape& sdata, const Fill* fill, uint32_t primit
}
GlGradientRenderTask* rTask = nullptr;
GlSize size = sdata.geometry->getPrimitiveSize(primitiveIndex);
float* matrix = sdata.geometry->getTransforMatrix();
switch (fill->id()) {
case FILL_ID_LINEAR: {
float x1, y1, x2, y2;
@ -327,6 +344,7 @@ void GlRenderer::drawPrimitive(GlShape& sdata, const Fill* fill, uint32_t primit
rTask->setCanvasSize(sdata.viewWd, sdata.viewHt);
rTask->setNoise(NOISE_LEVEL);
rTask->setStopCount((int)stopCnt);
rTask->setTransform(FORMAT_SIZE_MAT_4x4, matrix);
for (uint32_t i = 0; i < stopCnt; ++i)
{
rTask->setStopColor(i, stops[i].offset, stops[i].r, stops[i].g, stops[i].b, stops[i].a);

3
src/lib/gl_engine/tvgGlRendererProperties.h Normal file → Executable file
View file

@ -91,7 +91,8 @@ public:
enum class DataType
{
INT = 0,
FLOAT
FLOAT,
MATRIX
};
enum class PropertyType
{

16
src/lib/gl_engine/tvgGlShaderSrc.cpp Normal file → Executable file
View file

@ -26,12 +26,13 @@
#define TVG_COMPOSE_SHADER(shader) #shader
const char* COLOR_VERT_SHADER = TVG_COMPOSE_SHADER(
attribute mediump vec4 aLocation; \n
varying highp float vOpacity; \n
void main() \n
{ \n
gl_Position = vec4(aLocation.xy, 0.0, 1.0); \n
vOpacity = aLocation.z; \n
attribute mediump vec4 aLocation; \n
uniform highp mat4 uTransform; \n
varying highp float vOpacity; \n
void main() \n
{ \n
gl_Position = uTransform * vec4(aLocation.xy, 0.0, 1.0); \n
vOpacity = aLocation.z; \n
});
const char* COLOR_FRAG_SHADER = TVG_COMPOSE_SHADER(
@ -46,10 +47,11 @@ const char* GRADIENT_VERT_SHADER = TVG_COMPOSE_SHADER(
attribute highp vec4 aLocation; \n
varying highp float vOpacity; \n
varying highp vec2 vPos; \n
uniform highp mat4 uTransform; \n
\n
void main() \n
{ \n
gl_Position = vec4(aLocation.xy, 0.0, 1.0); \n
gl_Position = uTransform * vec4(aLocation.xy, 0.0, 1.0); \n
vOpacity = aLocation.z; \n
vPos = vec2((aLocation.x + 1.0) / 2.0, ((-1.0 * aLocation.y) +1.0) / 2.0); \n
});