From 2929fa5c57c17549da1b65e86140806b12823fc3 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Fri, 3 Jul 2020 18:17:43 +0900 Subject: [PATCH] sw_engine: optimize rle rendering. we don't need to apply anti-aliasing if stroke is there. here turns off anti-alias if stroke width is more than 2. magic number 2 is experimentally confirmed. Change-Id: I09031dc2a0a84f31c5904651ed1e62004645ba9a --- src/lib/sw_engine/tvgSwCommon.h | 4 ++-- src/lib/sw_engine/tvgSwRenderer.cpp | 10 ++++++---- src/lib/sw_engine/tvgSwRle.cpp | 17 +++++++---------- src/lib/sw_engine/tvgSwShape.cpp | 6 +++--- test/testShape.cpp | 2 +- 5 files changed, 19 insertions(+), 20 deletions(-) diff --git a/src/lib/sw_engine/tvgSwCommon.h b/src/lib/sw_engine/tvgSwCommon.h index 5db4cd7..8d90342 100644 --- a/src/lib/sw_engine/tvgSwCommon.h +++ b/src/lib/sw_engine/tvgSwCommon.h @@ -265,7 +265,7 @@ SwFixed mathMean(SwFixed angle1, SwFixed angle2); void shapeReset(SwShape& shape); bool shapeGenOutline(SwShape& shape, const Shape* sdata); bool shapePrepare(SwShape& shape, const Shape* sdata, const SwSize& clip, const Matrix* transform); -bool shapeGenRle(SwShape& shape, const Shape* sdata, const SwSize& clip); +bool shapeGenRle(SwShape& shape, const Shape* sdata, const SwSize& clip, bool antiAlias); void shapeDelOutline(SwShape& shape); void shapeResetStroke(SwShape& shape, const Shape* sdata); bool shapeGenStrokeRle(SwShape& shape, const Shape* sdata, const SwSize& clip); @@ -286,7 +286,7 @@ void fillFree(SwFill* fill); void fillFetchLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len); void fillFetchRadial(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len); -SwRleData* rleRender(const SwOutline* outline, const SwBBox& bbox, const SwSize& clip); +SwRleData* rleRender(const SwOutline* outline, const SwBBox& bbox, const SwSize& clip, bool antiAlias); void rleFree(SwRleData* rle); bool rasterGradientShape(Surface& surface, SwShape& shape, unsigned id); diff --git a/src/lib/sw_engine/tvgSwRenderer.cpp b/src/lib/sw_engine/tvgSwRenderer.cpp index b9ce7c0..adc3e9f 100644 --- a/src/lib/sw_engine/tvgSwRenderer.cpp +++ b/src/lib/sw_engine/tvgSwRenderer.cpp @@ -109,7 +109,7 @@ void SwRenderer::doRender() if (a > 0) rasterSolidShape(surface, task->shape, r, g, b, a); } task->sdata->strokeColor(&r, &g, &b, &a); - if (a > 0) rasterStroke(surface, task->shape, r, g, b, a); + if (a > 0) rasterStroke(surface, task->shape, r, g, b, a); renderTasks.pop(); } } @@ -178,7 +178,8 @@ void* SwRenderer::prepare(const Shape& sdata, void* data, const RenderTransform* //Valid Stroking? uint8_t strokeAlpha = 0; - if (task->sdata->strokeWidth() > FLT_EPSILON) { + auto strokeWidth = task->sdata->strokeWidth(); + if (strokeWidth > FLT_EPSILON) { task->sdata->strokeColor(nullptr, nullptr, nullptr, &strokeAlpha); } @@ -188,10 +189,11 @@ void* SwRenderer::prepare(const Shape& sdata, void* data, const RenderTransform* uint8_t alpha = 0; task->sdata->fill(nullptr, nullptr, nullptr, &alpha); bool renderShape = (alpha > 0 || task->sdata->fill()); - if (renderShape || strokeAlpha > 0) { + if (renderShape || strokeAlpha) { if (!shapePrepare(task->shape, task->sdata, task->clip, task->transform)) return; if (renderShape) { - if (!shapeGenRle(task->shape, task->sdata, task->clip)) return; + auto antiAlias = (strokeAlpha > 0 && strokeWidth >= 2) ? false : true; + if (!shapeGenRle(task->shape, task->sdata, task->clip, antiAlias)) return; } } } diff --git a/src/lib/sw_engine/tvgSwRle.cpp b/src/lib/sw_engine/tvgSwRle.cpp index 5bb3a31..6ee6f7c 100644 --- a/src/lib/sw_engine/tvgSwRle.cpp +++ b/src/lib/sw_engine/tvgSwRle.cpp @@ -87,6 +87,7 @@ struct RleWorker SwSize clip; bool invalid; + bool antiAlias; }; @@ -196,6 +197,7 @@ static void _horizLine(RleWorker& rw, SwCoord x, SwCoord y, SwCoord area, SwCoor } if (coverage > 0) { + if (!rw.antiAlias) coverage = 255; auto count = rw.spansCnt; auto span = rw.spans + count - 1; assert(span); @@ -261,22 +263,16 @@ static void _sweep(RleWorker& rw) while (cell) { - if (cell->x > x && cover != 0) - _horizLine(rw, x, y, cover * (ONE_PIXEL * 2), cell->x - x); - + if (cell->x > x && cover != 0) _horizLine(rw, x, y, cover * (ONE_PIXEL * 2), cell->x - x); cover += cell->cover; auto area = cover * (ONE_PIXEL * 2) - cell->area; - - //OPTIMIZE ME: This occurs 1 length span data. - if (area != 0 && cell->x >= 0) - _horizLine(rw, cell->x, y, area, 1); + if (area != 0 && cell->x >= 0) _horizLine(rw, cell->x, y, area, 1); x = cell->x + 1; cell = cell->next; } - if (cover != 0) - _horizLine(rw, x, y, cover * (ONE_PIXEL * 2), rw.cellXCnt - x); + if (cover != 0) _horizLine(rw, x, y, cover * (ONE_PIXEL * 2), rw.cellXCnt - x); } if (rw.spansCnt > 0) _genSpan(rw.rle, rw.spans, rw.spansCnt); @@ -648,7 +644,7 @@ static bool _genRle(RleWorker& rw) /* External Class Implementation */ /************************************************************************/ -SwRleData* rleRender(const SwOutline* outline, const SwBBox& bbox, const SwSize& clip) +SwRleData* rleRender(const SwOutline* outline, const SwBBox& bbox, const SwSize& clip, bool antiAlias) { //Please adjust when you out of cell memory (default: 16384L) constexpr auto RENDER_POOL_SIZE = 163840L * 2; @@ -681,6 +677,7 @@ SwRleData* rleRender(const SwOutline* outline, const SwBBox& bbox, const SwSize& rw.bandSize = rw.bufferSize / (sizeof(Cell) * 8); //bandSize: 64 rw.bandShoot = 0; rw.clip = clip; + rw.antiAlias = antiAlias; rw.rle = reinterpret_cast(calloc(1, sizeof(SwRleData))); assert(rw.rle); diff --git a/src/lib/sw_engine/tvgSwShape.cpp b/src/lib/sw_engine/tvgSwShape.cpp index dbdfb6a..a2ca5c6 100644 --- a/src/lib/sw_engine/tvgSwShape.cpp +++ b/src/lib/sw_engine/tvgSwShape.cpp @@ -477,7 +477,7 @@ bool shapePrepare(SwShape& shape, const Shape* sdata, const SwSize& clip, const } -bool shapeGenRle(SwShape& shape, const Shape* sdata, const SwSize& clip) +bool shapeGenRle(SwShape& shape, const Shape* sdata, const SwSize& clip, bool antiAlias) { //FIXME: Should we draw it? //Case: Stroke Line @@ -486,7 +486,7 @@ bool shapeGenRle(SwShape& shape, const Shape* sdata, const SwSize& clip) //Case A: Fast Track Rectangle Drawing if ((shape.rect = _fastTrack(shape.outline))) return true; //Case B: Normale Shape RLE Drawing - if ((shape.rle = rleRender(shape.outline, shape.bbox, clip))) return true; + if ((shape.rle = rleRender(shape.outline, shape.bbox, clip, antiAlias))) return true; return false; } @@ -667,7 +667,7 @@ bool shapeGenStrokeRle(SwShape& shape, const Shape* sdata, const SwSize& clip) if (!_checkValid(strokeOutline, bbox, clip)) return false; - shape.strokeRle = rleRender(strokeOutline, bbox, clip); + shape.strokeRle = rleRender(strokeOutline, bbox, clip, true); _delOutline(strokeOutline); diff --git a/test/testShape.cpp b/test/testShape.cpp index 5bf9e65..617d024 100644 --- a/test/testShape.cpp +++ b/test/testShape.cpp @@ -119,4 +119,4 @@ int main(int argc, char **argv) //Terminate ThorVG Engine tvg::Initializer::term(tvgEngine); -} \ No newline at end of file +} -- 2.7.4