gl_engine: code refactoring

- introduced GlGeometryBuffer that structure ensures the pairing of vertex and index data.
- improved for clean and neat code.
This commit is contained in:
Hermet Park 2025-02-20 15:43:06 +09:00
parent 3737632e13
commit 75c9028c19
5 changed files with 181 additions and 224 deletions

View file

@ -130,31 +130,35 @@ enum class GlStencilMode {
class GlStageBuffer; class GlStageBuffer;
class GlRenderTask; class GlRenderTask;
class GlGeometry struct GlGeometryBuffer {
Array<float> vertex;
Array<uint32_t> index;
void clear()
{
vertex.clear();
index.clear();
}
};
struct GlGeometry
{ {
public:
bool tesselate(const RenderShape& rshape, RenderUpdateFlag flag); bool tesselate(const RenderShape& rshape, RenderUpdateFlag flag);
bool tesselate(const RenderSurface* image, RenderUpdateFlag flag); bool tesselate(const RenderSurface* image, RenderUpdateFlag flag);
void disableVertex(uint32_t location); void disableVertex(uint32_t location);
bool draw(GlRenderTask* task, GlStageBuffer* gpuBuffer, RenderUpdateFlag flag); bool draw(GlRenderTask* task, GlStageBuffer* gpuBuffer, RenderUpdateFlag flag);
void updateTransform(const Matrix& m);
void setViewport(const RenderRegion& viewport);
const RenderRegion& getViewport();
const Matrix& getTransformMatrix();
GlStencilMode getStencilMode(RenderUpdateFlag flag); GlStencilMode getStencilMode(RenderUpdateFlag flag);
RenderRegion getBounds() const; RenderRegion getBounds() const;
private: GlGeometryBuffer fill, stroke;
Matrix matrix = {};
RenderRegion viewport = {}; RenderRegion viewport = {};
Array<float> fillVertex; RenderRegion bounds = {};
Array<float> strokeVertex; FillRule fillRule = FillRule::NonZero;
Array<uint32_t> fillIndex;
Array<uint32_t> strokeIndex;
Matrix mMatrix = {};
FillRule mFillRule = FillRule::NonZero;
RenderRegion mBounds = {};
}; };
struct GlShape struct GlShape
{ {
const RenderShape* rshape = nullptr; const RenderShape* rshape = nullptr;

View file

@ -25,25 +25,24 @@
#include "tvgGlTessellator.h" #include "tvgGlTessellator.h"
#include "tvgGlRenderTask.h" #include "tvgGlRenderTask.h"
bool GlGeometry::tesselate(const RenderShape& rshape, RenderUpdateFlag flag) bool GlGeometry::tesselate(const RenderShape& rshape, RenderUpdateFlag flag)
{ {
if (flag & (RenderUpdateFlag::Color | RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform | RenderUpdateFlag::Path)) { if (flag & (RenderUpdateFlag::Color | RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform | RenderUpdateFlag::Path)) {
fillVertex.clear(); fill.clear();
fillIndex.clear();
BWTessellator bwTess{&fillVertex, &fillIndex}; BWTessellator bwTess{&fill};
bwTess.tessellate(&rshape, mMatrix); bwTess.tessellate(&rshape, matrix);
mFillRule = rshape.rule; fillRule = rshape.rule;
mBounds = bwTess.bounds(); bounds = bwTess.bounds();
} }
if (flag & (RenderUpdateFlag::Stroke | RenderUpdateFlag::GradientStroke | RenderUpdateFlag::Transform)) { if (flag & (RenderUpdateFlag::Stroke | RenderUpdateFlag::GradientStroke | RenderUpdateFlag::Transform)) {
strokeVertex.clear(); stroke.clear();
strokeIndex.clear();
Stroker stroke{&strokeVertex, &strokeIndex, mMatrix}; Stroker stroker{&stroke, matrix};
stroke.stroke(&rshape); stroker.stroke(&rshape);
mBounds = stroke.bounds(); bounds = stroker.bounds();
} }
return true; return true;
@ -52,11 +51,10 @@ bool GlGeometry::tesselate(const RenderShape& rshape, RenderUpdateFlag flag)
bool GlGeometry::tesselate(const RenderSurface* image, RenderUpdateFlag flag) bool GlGeometry::tesselate(const RenderSurface* image, RenderUpdateFlag flag)
{ {
if (flag & RenderUpdateFlag::Image) { if (flag & RenderUpdateFlag::Image) {
fillVertex.clear(); fill.clear();
fillIndex.clear();
fillVertex.reserve(5 * 4); fill.vertex.reserve(5 * 4);
fillIndex.reserve(6); fill.index.reserve(6);
float left = 0.f; float left = 0.f;
float top = 0.f; float top = 0.f;
@ -64,42 +62,42 @@ bool GlGeometry::tesselate(const RenderSurface* image, RenderUpdateFlag flag)
float bottom = image->h; float bottom = image->h;
// left top point // left top point
fillVertex.push(left); fill.vertex.push(left);
fillVertex.push(top); fill.vertex.push(top);
fillVertex.push(0.f); fill.vertex.push(0.f);
fillVertex.push(1.f); fill.vertex.push(1.f);
// left bottom point // left bottom point
fillVertex.push(left); fill.vertex.push(left);
fillVertex.push(bottom); fill.vertex.push(bottom);
fillVertex.push(0.f); fill.vertex.push(0.f);
fillVertex.push(0.f); fill.vertex.push(0.f);
// right top point // right top point
fillVertex.push(right); fill.vertex.push(right);
fillVertex.push(top); fill.vertex.push(top);
fillVertex.push(1.f); fill.vertex.push(1.f);
fillVertex.push(1.f); fill.vertex.push(1.f);
// right bottom point // right bottom point
fillVertex.push(right); fill.vertex.push(right);
fillVertex.push(bottom); fill.vertex.push(bottom);
fillVertex.push(1.f); fill.vertex.push(1.f);
fillVertex.push(0.f); fill.vertex.push(0.f);
fillIndex.push(0); fill.index.push(0);
fillIndex.push(1); fill.index.push(1);
fillIndex.push(2); fill.index.push(2);
fillIndex.push(2); fill.index.push(2);
fillIndex.push(1); fill.index.push(1);
fillIndex.push(3); fill.index.push(3);
mBounds.x = 0; bounds.x = 0;
mBounds.y = 0; bounds.y = 0;
mBounds.w = image->w; bounds.w = image->w;
mBounds.h = image->h; bounds.h = image->h;
} }
return true; return true;
@ -116,21 +114,11 @@ bool GlGeometry::draw(GlRenderTask* task, GlStageBuffer* gpuBuffer, RenderUpdate
{ {
if (flag == RenderUpdateFlag::None) return false; if (flag == RenderUpdateFlag::None) return false;
Array<float>* vertexBuffer = nullptr; auto buffer = ((flag & RenderUpdateFlag::Stroke) || (flag & RenderUpdateFlag::GradientStroke)) ? &stroke : &fill;
Array<uint32_t>* indexBuffer = nullptr; if (buffer->index.empty()) return false;
if ((flag & RenderUpdateFlag::Stroke) || (flag & RenderUpdateFlag::GradientStroke)) { auto vertexOffset = gpuBuffer->push(buffer->vertex.data, buffer->vertex.count * sizeof(float));
vertexBuffer = &strokeVertex; auto indexOffset = gpuBuffer->pushIndex(buffer->index.data, buffer->index.count * sizeof(uint32_t));
indexBuffer = &strokeIndex;
} else {
vertexBuffer = &fillVertex;
indexBuffer = &fillIndex;
}
if (indexBuffer->count == 0) return false;
uint32_t vertexOffset = gpuBuffer->push(vertexBuffer->data, vertexBuffer->count * sizeof(float));
uint32_t indexOffset = gpuBuffer->pushIndex(indexBuffer->data, indexBuffer->count * sizeof(uint32_t));
// vertex layout // vertex layout
if (flag & RenderUpdateFlag::Image) { if (flag & RenderUpdateFlag::Image) {
@ -140,43 +128,19 @@ bool GlGeometry::draw(GlRenderTask* task, GlStageBuffer* gpuBuffer, RenderUpdate
} else { } else {
task->addVertexLayout(GlVertexLayout{0, 2, 2 * sizeof(float), vertexOffset}); task->addVertexLayout(GlVertexLayout{0, 2, 2 * sizeof(float), vertexOffset});
} }
task->setDrawRange(indexOffset, indexBuffer->count); task->setDrawRange(indexOffset, buffer->index.count);
return true; return true;
} }
void GlGeometry::updateTransform(const Matrix& m)
{
mMatrix = m;
}
void GlGeometry::setViewport(const RenderRegion& viewport)
{
this->viewport = viewport;
}
const RenderRegion& GlGeometry::getViewport()
{
return viewport;
}
const Matrix& GlGeometry::getTransformMatrix()
{
return mMatrix;
}
GlStencilMode GlGeometry::getStencilMode(RenderUpdateFlag flag) GlStencilMode GlGeometry::getStencilMode(RenderUpdateFlag flag)
{ {
if (flag & RenderUpdateFlag::Stroke) return GlStencilMode::Stroke; if (flag & RenderUpdateFlag::Stroke) return GlStencilMode::Stroke;
if (flag & RenderUpdateFlag::GradientStroke) return GlStencilMode::Stroke; if (flag & RenderUpdateFlag::GradientStroke) return GlStencilMode::Stroke;
if (flag & RenderUpdateFlag::Image) return GlStencilMode::None; if (flag & RenderUpdateFlag::Image) return GlStencilMode::None;
if (mFillRule == FillRule::NonZero) return GlStencilMode::FillNonZero; if (fillRule == FillRule::NonZero) return GlStencilMode::FillNonZero;
if (mFillRule == FillRule::EvenOdd) return GlStencilMode::FillEvenOdd; if (fillRule == FillRule::EvenOdd) return GlStencilMode::FillEvenOdd;
return GlStencilMode::None; return GlStencilMode::None;
} }
@ -184,18 +148,18 @@ GlStencilMode GlGeometry::getStencilMode(RenderUpdateFlag flag)
RenderRegion GlGeometry::getBounds() const RenderRegion GlGeometry::getBounds() const
{ {
if (identity(&mMatrix)) { if (identity(&matrix)) {
return mBounds; return bounds;
} else { } else {
Point lt{static_cast<float>(mBounds.x), static_cast<float>(mBounds.y)}; Point lt{static_cast<float>(bounds.x), static_cast<float>(bounds.y)};
Point lb{static_cast<float>(mBounds.x), static_cast<float>(mBounds.y + mBounds.h)}; Point lb{static_cast<float>(bounds.x), static_cast<float>(bounds.y + bounds.h)};
Point rt{static_cast<float>(mBounds.x + mBounds.w), static_cast<float>(mBounds.y)}; Point rt{static_cast<float>(bounds.x + bounds.w), static_cast<float>(bounds.y)};
Point rb{static_cast<float>(mBounds.x + mBounds.w), static_cast<float>(mBounds.y + mBounds.h)}; Point rb{static_cast<float>(bounds.x + bounds.w), static_cast<float>(bounds.y + bounds.h)};
lt *= mMatrix; lt *= matrix;
lb *= mMatrix; lb *= matrix;
rt *= mMatrix; rt *= matrix;
rb *= mMatrix; rb *= matrix;
float left = min(min(lt.x, lb.x), min(rt.x, rb.x)); float left = min(min(lt.x, lb.x), min(rt.x, rb.x));
float top = min(min(lt.y, lb.y), min(rt.y, rb.y)); float top = min(min(lt.y, lb.y), min(rt.y, rb.y));
@ -208,7 +172,7 @@ RenderRegion GlGeometry::getBounds() const
static_cast<int32_t>(ceil(right - floor(left))), static_cast<int32_t>(ceil(right - floor(left))),
static_cast<int32_t>(ceil(bottom - floor(top))), static_cast<int32_t>(ceil(bottom - floor(top))),
}; };
if (bounds.w < 0 || bounds.h < 0) return mBounds; if (bounds.w < 0 || bounds.h < 0) return this->bounds;
else return bounds; else return bounds;
} }
} }

View file

@ -146,7 +146,7 @@ void GlRenderer::initShaders()
void GlRenderer::drawPrimitive(GlShape& sdata, const RenderColor& c, RenderUpdateFlag flag, int32_t depth) void GlRenderer::drawPrimitive(GlShape& sdata, const RenderColor& c, RenderUpdateFlag flag, int32_t depth)
{ {
auto vp = currentPass()->getViewport(); auto vp = currentPass()->getViewport();
auto bbox = sdata.geometry.getViewport(); auto bbox = sdata.geometry.viewport;
bbox.intersect(vp); bbox.intersect(vp);
@ -186,7 +186,7 @@ void GlRenderer::drawPrimitive(GlShape& sdata, const RenderColor& c, RenderUpdat
auto a = MULTIPLY(c.a, sdata.opacity); auto a = MULTIPLY(c.a, sdata.opacity);
if (flag & RenderUpdateFlag::Stroke) { if (flag & RenderUpdateFlag::Stroke) {
float strokeWidth = sdata.rshape->strokeWidth() * getScaleFactor(sdata.geometry.getTransformMatrix()); float strokeWidth = sdata.rshape->strokeWidth() * getScaleFactor(sdata.geometry.matrix);
if (strokeWidth < MIN_GL_STROKE_WIDTH) { if (strokeWidth < MIN_GL_STROKE_WIDTH) {
float alpha = strokeWidth / MIN_GL_STROKE_WIDTH; float alpha = strokeWidth / MIN_GL_STROKE_WIDTH;
a = MULTIPLY(a, static_cast<uint8_t>(alpha * 255)); a = MULTIPLY(a, static_cast<uint8_t>(alpha * 255));
@ -194,10 +194,8 @@ void GlRenderer::drawPrimitive(GlShape& sdata, const RenderColor& c, RenderUpdat
} }
// matrix buffer // matrix buffer
const auto& matrix = sdata.geometry.getTransformMatrix();
float matrix44[16]; float matrix44[16];
currentPass()->getMatrix(matrix44, matrix); currentPass()->getMatrix(matrix44, sdata.geometry.matrix);
auto viewOffset = mGpuBuffer.push(matrix44, 16 * sizeof(float), true); auto viewOffset = mGpuBuffer.push(matrix44, 16 * sizeof(float), true);
task->addBindResource(GlBindingResource{ task->addBindResource(GlBindingResource{
@ -235,7 +233,7 @@ void GlRenderer::drawPrimitive(GlShape& sdata, const RenderColor& c, RenderUpdat
if (complexBlend) { if (complexBlend) {
auto task = new GlRenderTask(mPrograms[RT_Stencil]); auto task = new GlRenderTask(mPrograms[RT_Stencil]);
sdata.geometry.draw(task, &mGpuBuffer, flag); sdata.geometry.draw(task, &mGpuBuffer, flag);
endBlendingCompose(task, sdata.geometry.getTransformMatrix()); endBlendingCompose(task, sdata.geometry.matrix);
} }
} }
@ -243,7 +241,7 @@ void GlRenderer::drawPrimitive(GlShape& sdata, const RenderColor& c, RenderUpdat
void GlRenderer::drawPrimitive(GlShape& sdata, const Fill* fill, RenderUpdateFlag flag, int32_t depth) void GlRenderer::drawPrimitive(GlShape& sdata, const Fill* fill, RenderUpdateFlag flag, int32_t depth)
{ {
auto vp = currentPass()->getViewport(); auto vp = currentPass()->getViewport();
auto bbox = sdata.geometry.getViewport(); auto bbox = sdata.geometry.viewport;
bbox.intersect(vp); bbox.intersect(vp);
@ -285,14 +283,13 @@ void GlRenderer::drawPrimitive(GlShape& sdata, const Fill* fill, RenderUpdateFla
} }
// matrix buffer // matrix buffer
const auto& matrix = sdata.geometry.getTransformMatrix();
float invMat4[16]; float invMat4[16];
Matrix inv; Matrix inv;
inverse(&fill->transform(), &inv); inverse(&fill->transform(), &inv);
GET_MATRIX44(inv, invMat4); GET_MATRIX44(inv, invMat4);
float matrix44[16]; float matrix44[16];
currentPass()->getMatrix(matrix44, matrix); currentPass()->getMatrix(matrix44, sdata.geometry.matrix);
auto viewOffset = mGpuBuffer.push(matrix44, 16 * sizeof(float), true); auto viewOffset = mGpuBuffer.push(matrix44, 16 * sizeof(float), true);
@ -423,7 +420,7 @@ void GlRenderer::drawPrimitive(GlShape& sdata, const Fill* fill, RenderUpdateFla
if (complexBlend) { if (complexBlend) {
auto task = new GlRenderTask(mPrograms[RT_Stencil]); auto task = new GlRenderTask(mPrograms[RT_Stencil]);
sdata.geometry.draw(task, &mGpuBuffer, flag); sdata.geometry.draw(task, &mGpuBuffer, flag);
endBlendingCompose(task, sdata.geometry.getTransformMatrix()); endBlendingCompose(task, sdata.geometry.matrix);
} }
} }
@ -482,7 +479,7 @@ void GlRenderer::drawClip(Array<RenderData>& clips)
sdata->geometry.draw(clipTask, &mGpuBuffer, RenderUpdateFlag::Path); sdata->geometry.draw(clipTask, &mGpuBuffer, RenderUpdateFlag::Path);
auto bbox = sdata->geometry.getViewport(); auto bbox = sdata->geometry.viewport;
bbox.intersect(vp); bbox.intersect(vp);
@ -491,11 +488,8 @@ void GlRenderer::drawClip(Array<RenderData>& clips)
clipTask->setViewport({x, vp.h - y - bbox.h, bbox.w, bbox.h}); clipTask->setViewport({x, vp.h - y - bbox.h, bbox.w, bbox.h});
const auto& matrix = sdata->geometry.getTransformMatrix();
float matrix44[16]; float matrix44[16];
currentPass()->getMatrix(matrix44, sdata->geometry.matrix);
currentPass()->getMatrix(matrix44, matrix);
auto loc = clipTask->getProgram()->getUniformBlockIndex("Matrix"); auto loc = clipTask->getProgram()->getUniformBlockIndex("Matrix");
auto viewOffset = mGpuBuffer.push(matrix44, 16 * sizeof(float), true); auto viewOffset = mGpuBuffer.push(matrix44, 16 * sizeof(float), true);
@ -1008,7 +1002,7 @@ bool GlRenderer::renderImage(void* data)
if ((sdata->updateFlag & RenderUpdateFlag::Image) == 0) return true; if ((sdata->updateFlag & RenderUpdateFlag::Image) == 0) return true;
auto vp = currentPass()->getViewport(); auto vp = currentPass()->getViewport();
auto bbox = sdata->geometry.getViewport(); auto bbox = sdata->geometry.viewport;
bbox.intersect(vp); bbox.intersect(vp);
@ -1035,9 +1029,8 @@ bool GlRenderer::renderImage(void* data)
if (complexBlend) vp = currentPass()->getViewport(); if (complexBlend) vp = currentPass()->getViewport();
// matrix buffer // matrix buffer
const auto& matrix = sdata->geometry.getTransformMatrix();
float matrix44[16]; float matrix44[16];
currentPass()->getMatrix(matrix44, matrix); currentPass()->getMatrix(matrix44, sdata->geometry.matrix);
task->addBindResource(GlBindingResource{ task->addBindResource(GlBindingResource{
0, 0,
@ -1068,7 +1061,7 @@ bool GlRenderer::renderImage(void* data)
if (complexBlend) { if (complexBlend) {
auto task = new GlRenderTask(mPrograms[RT_Stencil]); auto task = new GlRenderTask(mPrograms[RT_Stencil]);
sdata->geometry.draw(task, &mGpuBuffer, RenderUpdateFlag::Image); sdata->geometry.draw(task, &mGpuBuffer, RenderUpdateFlag::Image);
endBlendingCompose(task, sdata->geometry.getTransformMatrix()); endBlendingCompose(task, sdata->geometry.matrix);
} }
return true; return true;
@ -1085,7 +1078,7 @@ bool GlRenderer::renderShape(RenderData data)
const auto& vp = currentPass()->getViewport(); const auto& vp = currentPass()->getViewport();
auto bbox = sdata->geometry.getViewport(); auto bbox = sdata->geometry.viewport;
bbox.intersect(vp); bbox.intersect(vp);
if (bbox.w <= 0 || bbox.h <= 0) return true; if (bbox.w <= 0 || bbox.h <= 0) return true;
@ -1188,8 +1181,8 @@ RenderData GlRenderer::prepare(RenderSurface* image, RenderData data, const Matr
sdata->geometry = GlGeometry(); sdata->geometry = GlGeometry();
} }
sdata->geometry.updateTransform(transform); sdata->geometry.matrix = transform;
sdata->geometry.setViewport(mViewport); sdata->geometry.viewport = mViewport;
sdata->geometry.tesselate(image, flags); sdata->geometry.tesselate(image, flags);
@ -1243,8 +1236,8 @@ RenderData GlRenderer::prepare(const RenderShape& rshape, RenderData data, const
if (sdata->updateFlag == RenderUpdateFlag::None) return sdata; if (sdata->updateFlag == RenderUpdateFlag::None) return sdata;
sdata->geometry.updateTransform(transform); sdata->geometry.matrix = transform;
sdata->geometry.setViewport(mViewport); sdata->geometry.viewport = mViewport;
if (sdata->updateFlag & (RenderUpdateFlag::Color | RenderUpdateFlag::Stroke | RenderUpdateFlag::Gradient | RenderUpdateFlag::GradientStroke | RenderUpdateFlag::Transform | RenderUpdateFlag::Path)) if (sdata->updateFlag & (RenderUpdateFlag::Color | RenderUpdateFlag::Stroke | RenderUpdateFlag::Gradient | RenderUpdateFlag::GradientStroke | RenderUpdateFlag::Transform | RenderUpdateFlag::Path))
{ {

View file

@ -798,11 +798,11 @@ static float _downScaleFloat(float v)
} }
static uint32_t _pushVertex(Array<float> *array, float x, float y) static uint32_t _pushVertex(Array<float>& array, float x, float y)
{ {
array->push(x); array.push(x);
array->push(y); array.push(y);
return (array->count - 2) / 2; return (array.count - 2) / 2;
} }
@ -830,13 +830,12 @@ static Orientation _calcOrientation(const Point& dir1, const Point& dir2)
} }
Tessellator::Tessellator(Array<float> *points, Array<uint32_t> *indices) Tessellator::Tessellator(GlGeometryBuffer* buffer)
: pHeap(new ObjectHeap), : pHeap(new ObjectHeap),
outlines(), outlines(),
pMesh(new VertexList), pMesh(new VertexList),
pPolygon(), pPolygon(),
resGlPoints(points), buffer(buffer)
resIndices(indices)
{ {
} }
@ -917,9 +916,9 @@ void Tessellator::visitShape(const PathCommand *cmds, uint32_t cmd_count, const
{ {
// all points at least need to be visit once // all points at least need to be visit once
// so the points count is at least the same as the count in shape // so the points count is at least the same as the count in shape
resGlPoints->reserve(pts_count * 2); buffer->vertex.reserve(pts_count * 2);
// triangle fans, the indices count is at least triangles number * 3 // triangle fans, the indices count is at least triangles number * 3
resIndices->reserve((pts_count - 2) * 3); buffer->index.reserve((pts_count - 2) * 3);
const Point *firstPt = nullptr; const Point *firstPt = nullptr;
@ -1513,17 +1512,17 @@ void Tessellator::emitPoly(MonotonePolygon *poly)
void Tessellator::emitTriangle(Vertex *p1, Vertex *p2, Vertex *p3) void Tessellator::emitTriangle(Vertex *p1, Vertex *p2, Vertex *p3)
{ {
// check if index is generated // check if index is generated
if (p1->index == 0xFFFFFFFF) p1->index = _pushVertex(resGlPoints, _downScaleFloat(p1->point.x), _downScaleFloat(p1->point.y)); if (p1->index == 0xFFFFFFFF) p1->index = _pushVertex(buffer->vertex, _downScaleFloat(p1->point.x), _downScaleFloat(p1->point.y));
if (p2->index == 0xFFFFFFFF) p2->index = _pushVertex(resGlPoints, _downScaleFloat(p2->point.x), _downScaleFloat(p2->point.y)); if (p2->index == 0xFFFFFFFF) p2->index = _pushVertex(buffer->vertex, _downScaleFloat(p2->point.x), _downScaleFloat(p2->point.y));
if (p3->index == 0xFFFFFFFF) p3->index = _pushVertex(resGlPoints, _downScaleFloat(p3->point.x), _downScaleFloat(p3->point.y)); if (p3->index == 0xFFFFFFFF) p3->index = _pushVertex(buffer->vertex, _downScaleFloat(p3->point.x), _downScaleFloat(p3->point.y));
resIndices->push(p1->index); buffer->index.push(p1->index);
resIndices->push(p2->index); buffer->index.push(p2->index);
resIndices->push(p3->index); buffer->index.push(p3->index);
} }
Stroker::Stroker(Array<float> *points, Array<uint32_t> *indices, const Matrix& matrix) : mResGlPoints(points), mResIndices(indices), mMatrix(matrix) Stroker::Stroker(GlGeometryBuffer* buffer, const Matrix& matrix) : mBuffer(buffer), mMatrix(matrix)
{ {
} }
@ -1588,8 +1587,8 @@ RenderRegion Stroker::bounds() const
void Stroker::doStroke(const PathCommand *cmds, uint32_t cmd_count, const Point *pts, uint32_t pts_count) void Stroker::doStroke(const PathCommand *cmds, uint32_t cmd_count, const Point *pts, uint32_t pts_count)
{ {
mResGlPoints->reserve(pts_count * 4 + 16); mBuffer->vertex.reserve(pts_count * 4 + 16);
mResIndices->reserve(pts_count * 3); mBuffer->index.reserve(pts_count * 3);
auto validStrokeCap = false; auto validStrokeCap = false;
@ -1678,10 +1677,10 @@ void Stroker::strokeLineTo(const Point& curr)
auto c = curr + normal * strokeRadius(); auto c = curr + normal * strokeRadius();
auto d = curr - normal * strokeRadius(); auto d = curr - normal * strokeRadius();
auto ia = _pushVertex(mResGlPoints, a.x, a.y); auto ia = _pushVertex(mBuffer->vertex, a.x, a.y);
auto ib = _pushVertex(mResGlPoints, b.x, b.y); auto ib = _pushVertex(mBuffer->vertex, b.x, b.y);
auto ic = _pushVertex(mResGlPoints, c.x, c.y); auto ic = _pushVertex(mBuffer->vertex, c.x, c.y);
auto id = _pushVertex(mResGlPoints, d.x, d.y); auto id = _pushVertex(mBuffer->vertex, d.x, d.y);
/** /**
* a --------- c * a --------- c
@ -1690,13 +1689,13 @@ void Stroker::strokeLineTo(const Point& curr)
* b-----------d * b-----------d
*/ */
this->mResIndices->push(ia); this->mBuffer->index.push(ia);
this->mResIndices->push(ib); this->mBuffer->index.push(ib);
this->mResIndices->push(ic); this->mBuffer->index.push(ic);
this->mResIndices->push(ib); this->mBuffer->index.push(ib);
this->mResIndices->push(id); this->mBuffer->index.push(id);
this->mResIndices->push(ic); this->mBuffer->index.push(ic);
if (mStrokeState.prevPt == mStrokeState.firstPt) { if (mStrokeState.prevPt == mStrokeState.firstPt) {
// first point after moveTo // first point after moveTo
@ -1802,8 +1801,8 @@ void Stroker::strokeRound(const Point &prev, const Point& curr, const Point& cen
// Fixme: just use bezier curve to calculate step count // Fixme: just use bezier curve to calculate step count
auto count = _bezierCurveCount(_bezFromArc(prev, curr, strokeRadius())); auto count = _bezierCurveCount(_bezFromArc(prev, curr, strokeRadius()));
auto c = _pushVertex(mResGlPoints, center.x, center.y); auto c = _pushVertex(mBuffer->vertex, center.x, center.y);
auto pi = _pushVertex(mResGlPoints, prev.x, prev.y); auto pi = _pushVertex(mBuffer->vertex, prev.x, prev.y);
auto step = 1.f / (count - 1); auto step = 1.f / (count - 1);
auto dir = curr - prev; auto dir = curr - prev;
@ -1814,11 +1813,11 @@ void Stroker::strokeRound(const Point &prev, const Point& curr, const Point& cen
normalize(o_dir); normalize(o_dir);
auto out = center + o_dir * strokeRadius(); auto out = center + o_dir * strokeRadius();
auto oi = _pushVertex(mResGlPoints, out.x, out.y); auto oi = _pushVertex(mBuffer->vertex, out.x, out.y);
mResIndices->push(c); mBuffer->index.push(c);
mResIndices->push(pi); mBuffer->index.push(pi);
mResIndices->push(oi); mBuffer->index.push(oi);
pi = oi; pi = oi;
@ -1834,19 +1833,19 @@ void Stroker::strokeRoundPoint(const Point &p)
{ {
// Fixme: just use bezier curve to calculate step count // Fixme: just use bezier curve to calculate step count
auto count = _bezierCurveCount(_bezFromArc(p, p, strokeRadius())) * 2; auto count = _bezierCurveCount(_bezFromArc(p, p, strokeRadius())) * 2;
auto c = _pushVertex(mResGlPoints, p.x, p.y); auto c = _pushVertex(mBuffer->vertex, p.x, p.y);
auto step = 2 * M_PI / (count - 1); auto step = 2 * M_PI / (count - 1);
for (uint32_t i = 1; i <= static_cast<uint32_t>(count); i++) { for (uint32_t i = 1; i <= static_cast<uint32_t>(count); i++) {
float angle = i * step; float angle = i * step;
Point dir = {cos(angle), sin(angle)}; Point dir = {cos(angle), sin(angle)};
Point out = p + dir * strokeRadius(); Point out = p + dir * strokeRadius();
auto oi = _pushVertex(mResGlPoints, out.x, out.y); auto oi = _pushVertex(mBuffer->vertex, out.x, out.y);
if (oi > 1) { if (oi > 1) {
mResIndices->push(c); mBuffer->index.push(c);
mResIndices->push(oi); mBuffer->index.push(oi);
mResIndices->push(oi - 1); mBuffer->index.push(oi - 1);
} }
} }
@ -1871,18 +1870,18 @@ void Stroker::strokeMiter(const Point& prev, const Point& curr, const Point& cen
} }
auto join = center + pe; auto join = center + pe;
auto c = _pushVertex(mResGlPoints, center.x, center.y); auto c = _pushVertex(mBuffer->vertex, center.x, center.y);
auto cp1 = _pushVertex(mResGlPoints, prev.x, prev.y); auto cp1 = _pushVertex(mBuffer->vertex, prev.x, prev.y);
auto cp2 = _pushVertex(mResGlPoints, curr.x, curr.y); auto cp2 = _pushVertex(mBuffer->vertex, curr.x, curr.y);
auto e = _pushVertex(mResGlPoints, join.x, join.y); auto e = _pushVertex(mBuffer->vertex, join.x, join.y);
mResIndices->push(c); mBuffer->index.push(c);
mResIndices->push(cp1); mBuffer->index.push(cp1);
mResIndices->push(e); mBuffer->index.push(e);
mResIndices->push(e); mBuffer->index.push(e);
mResIndices->push(cp2); mBuffer->index.push(cp2);
mResIndices->push(c); mBuffer->index.push(c);
mLeftTop.x = std::min(mLeftTop.x, join.x); mLeftTop.x = std::min(mLeftTop.x, join.x);
mLeftTop.y = std::min(mLeftTop.y, join.y); mLeftTop.y = std::min(mLeftTop.y, join.y);
@ -1894,13 +1893,13 @@ void Stroker::strokeMiter(const Point& prev, const Point& curr, const Point& cen
void Stroker::strokeBevel(const Point& prev, const Point& curr, const Point& center) void Stroker::strokeBevel(const Point& prev, const Point& curr, const Point& center)
{ {
auto a = _pushVertex(mResGlPoints, prev.x, prev.y); auto a = _pushVertex(mBuffer->vertex, prev.x, prev.y);
auto b = _pushVertex(mResGlPoints, curr.x, curr.y); auto b = _pushVertex(mBuffer->vertex, curr.x, curr.y);
auto c = _pushVertex(mResGlPoints, center.x, center.y); auto c = _pushVertex(mBuffer->vertex, center.x, center.y);
mResIndices->push(a); mBuffer->index.push(a);
mResIndices->push(b); mBuffer->index.push(b);
mResIndices->push(c); mBuffer->index.push(c);
} }
@ -1913,18 +1912,18 @@ void Stroker::strokeSquare(const Point& p, const Point& outDir)
auto c = a + outDir * strokeRadius(); auto c = a + outDir * strokeRadius();
auto d = b + outDir * strokeRadius(); auto d = b + outDir * strokeRadius();
auto ai = _pushVertex(mResGlPoints, a.x, a.y); auto ai = _pushVertex(mBuffer->vertex, a.x, a.y);
auto bi = _pushVertex(mResGlPoints, b.x, b.y); auto bi = _pushVertex(mBuffer->vertex, b.x, b.y);
auto ci = _pushVertex(mResGlPoints, c.x, c.y); auto ci = _pushVertex(mBuffer->vertex, c.x, c.y);
auto di = _pushVertex(mResGlPoints, d.x, d.y); auto di = _pushVertex(mBuffer->vertex, d.x, d.y);
mResIndices->push(ai); mBuffer->index.push(ai);
mResIndices->push(bi); mBuffer->index.push(bi);
mResIndices->push(ci); mBuffer->index.push(ci);
mResIndices->push(ci); mBuffer->index.push(ci);
mResIndices->push(bi); mBuffer->index.push(bi);
mResIndices->push(di); mBuffer->index.push(di);
mLeftTop.x = std::min(mLeftTop.x, std::min(std::min(a.x, b.x), std::min(c.x, d.x))); mLeftTop.x = std::min(mLeftTop.x, std::min(std::min(a.x, b.x), std::min(c.x, d.x)));
mLeftTop.y = std::min(mLeftTop.y, std::min(std::min(a.y, b.y), std::min(c.y, d.y))); mLeftTop.y = std::min(mLeftTop.y, std::min(std::min(a.y, b.y), std::min(c.y, d.y)));
@ -1943,18 +1942,18 @@ void Stroker::strokeSquarePoint(const Point& p)
auto c = p - offsetX - offsetY; auto c = p - offsetX - offsetY;
auto d = p + offsetX - offsetY; auto d = p + offsetX - offsetY;
auto ai = _pushVertex(mResGlPoints, a.x, a.y); auto ai = _pushVertex(mBuffer->vertex, a.x, a.y);
auto bi = _pushVertex(mResGlPoints, b.x, b.y); auto bi = _pushVertex(mBuffer->vertex, b.x, b.y);
auto ci = _pushVertex(mResGlPoints, c.x, c.y); auto ci = _pushVertex(mBuffer->vertex, c.x, c.y);
auto di = _pushVertex(mResGlPoints, d.x, d.y); auto di = _pushVertex(mBuffer->vertex, d.x, d.y);
mResIndices->push(ai); mBuffer->index.push(ai);
mResIndices->push(bi); mBuffer->index.push(bi);
mResIndices->push(ci); mBuffer->index.push(ci);
mResIndices->push(ci); mBuffer->index.push(ci);
mResIndices->push(di); mBuffer->index.push(di);
mResIndices->push(ai); mBuffer->index.push(ai);
mLeftTop.x = std::min(mLeftTop.x, std::min(std::min(a.x, b.x), std::min(c.x, d.x))); mLeftTop.x = std::min(mLeftTop.x, std::min(std::min(a.x, b.x), std::min(c.x, d.x)));
mLeftTop.y = std::min(mLeftTop.y, std::min(std::min(a.y, b.y), std::min(c.y, d.y))); mLeftTop.y = std::min(mLeftTop.y, std::min(std::min(a.y, b.y), std::min(c.y, d.y)));
@ -2165,7 +2164,7 @@ void DashStroke::cubicTo(const Point& cnt1, const Point& cnt2, const Point& end)
} }
BWTessellator::BWTessellator(Array<float>* points, Array<uint32_t>* indices): mResPoints(points), mResIndices(indices) BWTessellator::BWTessellator(GlGeometryBuffer* buffer): mBuffer(buffer)
{ {
} }
@ -2182,8 +2181,8 @@ void BWTessellator::tessellate(const RenderShape *rshape, const Matrix& matrix)
uint32_t firstIndex = 0; uint32_t firstIndex = 0;
uint32_t prevIndex = 0; uint32_t prevIndex = 0;
mResPoints->reserve(ptsCnt * 2); mBuffer->vertex.reserve(ptsCnt * 2);
mResIndices->reserve((ptsCnt - 2) * 3); mBuffer->index.reserve((ptsCnt - 2) * 3);
for (uint32_t i = 0; i < cmdCnt; i++) { for (uint32_t i = 0; i < cmdCnt; i++) {
switch(cmds[i]) { switch(cmds[i]) {
@ -2252,7 +2251,7 @@ RenderRegion BWTessellator::bounds() const
uint32_t BWTessellator::pushVertex(float x, float y) uint32_t BWTessellator::pushVertex(float x, float y)
{ {
auto index = _pushVertex(mResPoints, x, y); auto index = _pushVertex(mBuffer->vertex, x, y);
if (index == 0) { if (index == 0) {
bbox.max = bbox.min = {x, y}; bbox.max = bbox.min = {x, y};
@ -2267,9 +2266,9 @@ uint32_t BWTessellator::pushVertex(float x, float y)
void BWTessellator::pushTriangle(uint32_t a, uint32_t b, uint32_t c) void BWTessellator::pushTriangle(uint32_t a, uint32_t b, uint32_t c)
{ {
mResIndices->push(a); mBuffer->index.push(a);
mResIndices->push(b); mBuffer->index.push(b);
mResIndices->push(c); mBuffer->index.push(c);
} }
} // namespace tvg } // namespace tvg

View file

@ -41,7 +41,7 @@ struct RenderShape;
class Tessellator final class Tessellator final
{ {
public: public:
Tessellator(Array<float>* points, Array<uint32_t>* indices); Tessellator(GlGeometryBuffer* buffer);
~Tessellator(); ~Tessellator();
bool tessellate(const RenderShape *rshape, bool antialias = false); bool tessellate(const RenderShape *rshape, bool antialias = false);
void tessellate(const Array<const RenderShape*> &shapes); void tessellate(const Array<const RenderShape*> &shapes);
@ -66,11 +66,10 @@ private:
Array<VertexList*> outlines; Array<VertexList*> outlines;
VertexList* pMesh; VertexList* pMesh;
Polygon* pPolygon; Polygon* pPolygon;
Array<float>* resGlPoints; GlGeometryBuffer* buffer;
Array<uint32_t>* resIndices;
}; };
class Stroker final class Stroker
{ {
struct State struct State
{ {
@ -80,7 +79,7 @@ class Stroker final
Point prevPtDir; Point prevPtDir;
}; };
public: public:
Stroker(Array<float>* points, Array<uint32_t>* indices, const Matrix& matrix); Stroker(GlGeometryBuffer* buffer, const Matrix& matrix);
~Stroker() = default; ~Stroker() = default;
void stroke(const RenderShape *rshape); void stroke(const RenderShape *rshape);
RenderRegion bounds() const; RenderRegion bounds() const;
@ -107,8 +106,7 @@ private:
void strokeRound(const Point& p, const Point& outDir); void strokeRound(const Point& p, const Point& outDir);
void strokeRoundPoint(const Point& p); void strokeRoundPoint(const Point& p);
Array<float>* mResGlPoints; GlGeometryBuffer* mBuffer;
Array<uint32_t>* mResIndices;
Matrix mMatrix; Matrix mMatrix;
float mStrokeWidth = MIN_GL_STROKE_WIDTH; float mStrokeWidth = MIN_GL_STROKE_WIDTH;
float mMiterLimit = 4.f; float mMiterLimit = 4.f;
@ -148,7 +146,7 @@ private:
class BWTessellator class BWTessellator
{ {
public: public:
BWTessellator(Array<float>* points, Array<uint32_t>* indices); BWTessellator(GlGeometryBuffer* buffer);
~BWTessellator() = default; ~BWTessellator() = default;
void tessellate(const RenderShape *rshape, const Matrix& matrix); void tessellate(const RenderShape *rshape, const Matrix& matrix);
RenderRegion bounds() const; RenderRegion bounds() const;
@ -157,8 +155,7 @@ private:
uint32_t pushVertex(float x, float y); uint32_t pushVertex(float x, float y);
void pushTriangle(uint32_t a, uint32_t b, uint32_t c); void pushTriangle(uint32_t a, uint32_t b, uint32_t c);
Array<float>* mResPoints; GlGeometryBuffer* mBuffer;
Array<uint32_t>* mResIndices;
BBox bbox = {{}, {}}; BBox bbox = {{}, {}};
}; };