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 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 RenderSurface* image, RenderUpdateFlag flag);
void disableVertex(uint32_t location);
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);
RenderRegion getBounds() const;
private:
GlGeometryBuffer fill, stroke;
Matrix matrix = {};
RenderRegion viewport = {};
Array<float> fillVertex;
Array<float> strokeVertex;
Array<uint32_t> fillIndex;
Array<uint32_t> strokeIndex;
Matrix mMatrix = {};
FillRule mFillRule = FillRule::NonZero;
RenderRegion mBounds = {};
RenderRegion bounds = {};
FillRule fillRule = FillRule::NonZero;
};
struct GlShape
{
const RenderShape* rshape = nullptr;

View file

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

View file

@ -146,7 +146,7 @@ void GlRenderer::initShaders()
void GlRenderer::drawPrimitive(GlShape& sdata, const RenderColor& c, RenderUpdateFlag flag, int32_t depth)
{
auto vp = currentPass()->getViewport();
auto bbox = sdata.geometry.getViewport();
auto bbox = sdata.geometry.viewport;
bbox.intersect(vp);
@ -186,7 +186,7 @@ void GlRenderer::drawPrimitive(GlShape& sdata, const RenderColor& c, RenderUpdat
auto a = MULTIPLY(c.a, sdata.opacity);
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) {
float alpha = strokeWidth / MIN_GL_STROKE_WIDTH;
a = MULTIPLY(a, static_cast<uint8_t>(alpha * 255));
@ -194,10 +194,8 @@ void GlRenderer::drawPrimitive(GlShape& sdata, const RenderColor& c, RenderUpdat
}
// matrix buffer
const auto& matrix = sdata.geometry.getTransformMatrix();
float matrix44[16];
currentPass()->getMatrix(matrix44, matrix);
currentPass()->getMatrix(matrix44, sdata.geometry.matrix);
auto viewOffset = mGpuBuffer.push(matrix44, 16 * sizeof(float), true);
task->addBindResource(GlBindingResource{
@ -235,7 +233,7 @@ void GlRenderer::drawPrimitive(GlShape& sdata, const RenderColor& c, RenderUpdat
if (complexBlend) {
auto task = new GlRenderTask(mPrograms[RT_Stencil]);
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)
{
auto vp = currentPass()->getViewport();
auto bbox = sdata.geometry.getViewport();
auto bbox = sdata.geometry.viewport;
bbox.intersect(vp);
@ -285,14 +283,13 @@ void GlRenderer::drawPrimitive(GlShape& sdata, const Fill* fill, RenderUpdateFla
}
// matrix buffer
const auto& matrix = sdata.geometry.getTransformMatrix();
float invMat4[16];
Matrix inv;
inverse(&fill->transform(), &inv);
GET_MATRIX44(inv, invMat4);
float matrix44[16];
currentPass()->getMatrix(matrix44, matrix);
currentPass()->getMatrix(matrix44, sdata.geometry.matrix);
auto viewOffset = mGpuBuffer.push(matrix44, 16 * sizeof(float), true);
@ -423,7 +420,7 @@ void GlRenderer::drawPrimitive(GlShape& sdata, const Fill* fill, RenderUpdateFla
if (complexBlend) {
auto task = new GlRenderTask(mPrograms[RT_Stencil]);
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);
auto bbox = sdata->geometry.getViewport();
auto bbox = sdata->geometry.viewport;
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});
const auto& matrix = sdata->geometry.getTransformMatrix();
float matrix44[16];
currentPass()->getMatrix(matrix44, matrix);
currentPass()->getMatrix(matrix44, sdata->geometry.matrix);
auto loc = clipTask->getProgram()->getUniformBlockIndex("Matrix");
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;
auto vp = currentPass()->getViewport();
auto bbox = sdata->geometry.getViewport();
auto bbox = sdata->geometry.viewport;
bbox.intersect(vp);
@ -1035,9 +1029,8 @@ bool GlRenderer::renderImage(void* data)
if (complexBlend) vp = currentPass()->getViewport();
// matrix buffer
const auto& matrix = sdata->geometry.getTransformMatrix();
float matrix44[16];
currentPass()->getMatrix(matrix44, matrix);
currentPass()->getMatrix(matrix44, sdata->geometry.matrix);
task->addBindResource(GlBindingResource{
0,
@ -1068,7 +1061,7 @@ bool GlRenderer::renderImage(void* data)
if (complexBlend) {
auto task = new GlRenderTask(mPrograms[RT_Stencil]);
sdata->geometry.draw(task, &mGpuBuffer, RenderUpdateFlag::Image);
endBlendingCompose(task, sdata->geometry.getTransformMatrix());
endBlendingCompose(task, sdata->geometry.matrix);
}
return true;
@ -1085,7 +1078,7 @@ bool GlRenderer::renderShape(RenderData data)
const auto& vp = currentPass()->getViewport();
auto bbox = sdata->geometry.getViewport();
auto bbox = sdata->geometry.viewport;
bbox.intersect(vp);
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.updateTransform(transform);
sdata->geometry.setViewport(mViewport);
sdata->geometry.matrix = transform;
sdata->geometry.viewport = mViewport;
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;
sdata->geometry.updateTransform(transform);
sdata->geometry.setViewport(mViewport);
sdata->geometry.matrix = transform;
sdata->geometry.viewport = mViewport;
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(y);
return (array->count - 2) / 2;
array.push(x);
array.push(y);
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),
outlines(),
pMesh(new VertexList),
pPolygon(),
resGlPoints(points),
resIndices(indices)
buffer(buffer)
{
}
@ -917,9 +916,9 @@ void Tessellator::visitShape(const PathCommand *cmds, uint32_t cmd_count, const
{
// all points at least need to be visit once
// 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
resIndices->reserve((pts_count - 2) * 3);
buffer->index.reserve((pts_count - 2) * 3);
const Point *firstPt = nullptr;
@ -1513,17 +1512,17 @@ void Tessellator::emitPoly(MonotonePolygon *poly)
void Tessellator::emitTriangle(Vertex *p1, Vertex *p2, Vertex *p3)
{
// check if index is generated
if (p1->index == 0xFFFFFFFF) p1->index = _pushVertex(resGlPoints, _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 (p3->index == 0xFFFFFFFF) p3->index = _pushVertex(resGlPoints, _downScaleFloat(p3->point.x), _downScaleFloat(p3->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(buffer->vertex, _downScaleFloat(p2->point.x), _downScaleFloat(p2->point.y));
if (p3->index == 0xFFFFFFFF) p3->index = _pushVertex(buffer->vertex, _downScaleFloat(p3->point.x), _downScaleFloat(p3->point.y));
resIndices->push(p1->index);
resIndices->push(p2->index);
resIndices->push(p3->index);
buffer->index.push(p1->index);
buffer->index.push(p2->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)
{
mResGlPoints->reserve(pts_count * 4 + 16);
mResIndices->reserve(pts_count * 3);
mBuffer->vertex.reserve(pts_count * 4 + 16);
mBuffer->index.reserve(pts_count * 3);
auto validStrokeCap = false;
@ -1678,10 +1677,10 @@ void Stroker::strokeLineTo(const Point& curr)
auto c = curr + normal * strokeRadius();
auto d = curr - normal * strokeRadius();
auto ia = _pushVertex(mResGlPoints, a.x, a.y);
auto ib = _pushVertex(mResGlPoints, b.x, b.y);
auto ic = _pushVertex(mResGlPoints, c.x, c.y);
auto id = _pushVertex(mResGlPoints, d.x, d.y);
auto ia = _pushVertex(mBuffer->vertex, a.x, a.y);
auto ib = _pushVertex(mBuffer->vertex, b.x, b.y);
auto ic = _pushVertex(mBuffer->vertex, c.x, c.y);
auto id = _pushVertex(mBuffer->vertex, d.x, d.y);
/**
* a --------- c
@ -1690,13 +1689,13 @@ void Stroker::strokeLineTo(const Point& curr)
* b-----------d
*/
this->mResIndices->push(ia);
this->mResIndices->push(ib);
this->mResIndices->push(ic);
this->mBuffer->index.push(ia);
this->mBuffer->index.push(ib);
this->mBuffer->index.push(ic);
this->mResIndices->push(ib);
this->mResIndices->push(id);
this->mResIndices->push(ic);
this->mBuffer->index.push(ib);
this->mBuffer->index.push(id);
this->mBuffer->index.push(ic);
if (mStrokeState.prevPt == mStrokeState.firstPt) {
// 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
auto count = _bezierCurveCount(_bezFromArc(prev, curr, strokeRadius()));
auto c = _pushVertex(mResGlPoints, center.x, center.y);
auto pi = _pushVertex(mResGlPoints, prev.x, prev.y);
auto c = _pushVertex(mBuffer->vertex, center.x, center.y);
auto pi = _pushVertex(mBuffer->vertex, prev.x, prev.y);
auto step = 1.f / (count - 1);
auto dir = curr - prev;
@ -1814,11 +1813,11 @@ void Stroker::strokeRound(const Point &prev, const Point& curr, const Point& cen
normalize(o_dir);
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);
mResIndices->push(pi);
mResIndices->push(oi);
mBuffer->index.push(c);
mBuffer->index.push(pi);
mBuffer->index.push(oi);
pi = oi;
@ -1834,19 +1833,19 @@ void Stroker::strokeRoundPoint(const Point &p)
{
// Fixme: just use bezier curve to calculate step count
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);
for (uint32_t i = 1; i <= static_cast<uint32_t>(count); i++) {
float angle = i * step;
Point dir = {cos(angle), sin(angle)};
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) {
mResIndices->push(c);
mResIndices->push(oi);
mResIndices->push(oi - 1);
mBuffer->index.push(c);
mBuffer->index.push(oi);
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 c = _pushVertex(mResGlPoints, center.x, center.y);
auto cp1 = _pushVertex(mResGlPoints, prev.x, prev.y);
auto cp2 = _pushVertex(mResGlPoints, curr.x, curr.y);
auto e = _pushVertex(mResGlPoints, join.x, join.y);
auto c = _pushVertex(mBuffer->vertex, center.x, center.y);
auto cp1 = _pushVertex(mBuffer->vertex, prev.x, prev.y);
auto cp2 = _pushVertex(mBuffer->vertex, curr.x, curr.y);
auto e = _pushVertex(mBuffer->vertex, join.x, join.y);
mResIndices->push(c);
mResIndices->push(cp1);
mResIndices->push(e);
mBuffer->index.push(c);
mBuffer->index.push(cp1);
mBuffer->index.push(e);
mResIndices->push(e);
mResIndices->push(cp2);
mResIndices->push(c);
mBuffer->index.push(e);
mBuffer->index.push(cp2);
mBuffer->index.push(c);
mLeftTop.x = std::min(mLeftTop.x, join.x);
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)
{
auto a = _pushVertex(mResGlPoints, prev.x, prev.y);
auto b = _pushVertex(mResGlPoints, curr.x, curr.y);
auto c = _pushVertex(mResGlPoints, center.x, center.y);
auto a = _pushVertex(mBuffer->vertex, prev.x, prev.y);
auto b = _pushVertex(mBuffer->vertex, curr.x, curr.y);
auto c = _pushVertex(mBuffer->vertex, center.x, center.y);
mResIndices->push(a);
mResIndices->push(b);
mResIndices->push(c);
mBuffer->index.push(a);
mBuffer->index.push(b);
mBuffer->index.push(c);
}
@ -1913,18 +1912,18 @@ void Stroker::strokeSquare(const Point& p, const Point& outDir)
auto c = a + outDir * strokeRadius();
auto d = b + outDir * strokeRadius();
auto ai = _pushVertex(mResGlPoints, a.x, a.y);
auto bi = _pushVertex(mResGlPoints, b.x, b.y);
auto ci = _pushVertex(mResGlPoints, c.x, c.y);
auto di = _pushVertex(mResGlPoints, d.x, d.y);
auto ai = _pushVertex(mBuffer->vertex, a.x, a.y);
auto bi = _pushVertex(mBuffer->vertex, b.x, b.y);
auto ci = _pushVertex(mBuffer->vertex, c.x, c.y);
auto di = _pushVertex(mBuffer->vertex, d.x, d.y);
mResIndices->push(ai);
mResIndices->push(bi);
mResIndices->push(ci);
mBuffer->index.push(ai);
mBuffer->index.push(bi);
mBuffer->index.push(ci);
mResIndices->push(ci);
mResIndices->push(bi);
mResIndices->push(di);
mBuffer->index.push(ci);
mBuffer->index.push(bi);
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.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 d = p + offsetX - offsetY;
auto ai = _pushVertex(mResGlPoints, a.x, a.y);
auto bi = _pushVertex(mResGlPoints, b.x, b.y);
auto ci = _pushVertex(mResGlPoints, c.x, c.y);
auto di = _pushVertex(mResGlPoints, d.x, d.y);
auto ai = _pushVertex(mBuffer->vertex, a.x, a.y);
auto bi = _pushVertex(mBuffer->vertex, b.x, b.y);
auto ci = _pushVertex(mBuffer->vertex, c.x, c.y);
auto di = _pushVertex(mBuffer->vertex, d.x, d.y);
mResIndices->push(ai);
mResIndices->push(bi);
mResIndices->push(ci);
mBuffer->index.push(ai);
mBuffer->index.push(bi);
mBuffer->index.push(ci);
mResIndices->push(ci);
mResIndices->push(di);
mResIndices->push(ai);
mBuffer->index.push(ci);
mBuffer->index.push(di);
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.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 prevIndex = 0;
mResPoints->reserve(ptsCnt * 2);
mResIndices->reserve((ptsCnt - 2) * 3);
mBuffer->vertex.reserve(ptsCnt * 2);
mBuffer->index.reserve((ptsCnt - 2) * 3);
for (uint32_t i = 0; i < cmdCnt; i++) {
switch(cmds[i]) {
@ -2252,7 +2251,7 @@ RenderRegion BWTessellator::bounds() const
uint32_t BWTessellator::pushVertex(float x, float y)
{
auto index = _pushVertex(mResPoints, x, y);
auto index = _pushVertex(mBuffer->vertex, x, y);
if (index == 0) {
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)
{
mResIndices->push(a);
mResIndices->push(b);
mResIndices->push(c);
mBuffer->index.push(a);
mBuffer->index.push(b);
mBuffer->index.push(c);
}
} // namespace tvg

View file

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