diff --git a/src/common/tvgArray.h b/src/common/tvgArray.h index 2e5076c3..0ecb2261 100644 --- a/src/common/tvgArray.h +++ b/src/common/tvgArray.h @@ -102,6 +102,17 @@ struct Array count = rhs.count; } + void move(Array& to) + { + to.reset(); + to.data = data; + to.count = count; + to.reserved = reserved; + + data = nullptr; + count = reserved = 0; + } + const T* begin() const { return data; @@ -137,6 +148,12 @@ struct Array return data[count - 1]; } + T& next() + { + if (full()) grow(count + 1); + return data[count++]; + } + T& first() { return data[0]; @@ -164,6 +181,12 @@ struct Array return count == 0; } + + bool full() + { + return count == reserved; + } + template void sort() { qsort(data, 0, (int32_t)(count - 1)); diff --git a/src/renderer/sw_engine/tvgSwCommon.h b/src/renderer/sw_engine/tvgSwCommon.h index 1b25521f..edee5f22 100644 --- a/src/renderer/sw_engine/tvgSwCommon.h +++ b/src/renderer/sw_engine/tvgSwCommon.h @@ -121,9 +121,10 @@ struct SwSpan struct SwRle { - SwSpan *spans; - uint32_t alloc; - uint32_t size; + Array spans; + + uint32_t size() const { return spans.count; } + SwSpan* data() const { return spans.data; } }; struct SwFill diff --git a/src/renderer/sw_engine/tvgSwRaster.cpp b/src/renderer/sw_engine/tvgSwRaster.cpp index f10885ea..a967dba2 100644 --- a/src/renderer/sw_engine/tvgSwRaster.cpp +++ b/src/renderer/sw_engine/tvgSwRaster.cpp @@ -474,12 +474,12 @@ static bool _rasterRect(SwSurface* surface, const RenderRegion& bbox, const Rend static bool _rasterCompositeMaskedRle(SwSurface* surface, SwRle* rle, SwMask maskOp, uint8_t a) { - auto span = rle->spans; + auto span = rle->data(); auto cbuffer = surface->compositor->image.buf8; auto cstride = surface->compositor->image.stride; uint8_t src; - for (uint32_t i = 0; i < rle->size; ++i, ++span) { + for (uint32_t i = 0; i < rle->size(); ++i, ++span) { auto cmp = &cbuffer[span->y * cstride + span->x]; if (span->coverage == 255) src = a; else src = MULTIPLY(a, span->coverage); @@ -494,12 +494,12 @@ static bool _rasterCompositeMaskedRle(SwSurface* surface, SwRle* rle, SwMask mas static bool _rasterDirectMaskedRle(SwSurface* surface, SwRle* rle, SwMask maskOp, uint8_t a) { - auto span = rle->spans; + auto span = rle->data(); auto cbuffer = surface->compositor->image.buf8; auto cstride = surface->compositor->image.stride; uint8_t src; - for (uint32_t i = 0; i < rle->size; ++i, ++span) { + for (uint32_t i = 0; i < rle->size(); ++i, ++span) { auto cmp = &cbuffer[span->y * cstride + span->x]; auto dst = &surface->buf8[span->y * surface->stride + span->x]; if (span->coverage == 255) src = a; @@ -531,7 +531,7 @@ static bool _rasterMattedRle(SwSurface* surface, SwRle* rle, const RenderColor& { TVGLOG("SW_ENGINE", "Matted(%d) Rle", (int)surface->compositor->method); - auto span = rle->spans; + auto span = rle->data(); auto cbuffer = surface->compositor->image.buf8; auto csize = surface->compositor->image.channelSize; auto alpha = surface->alpha(surface->compositor->method); @@ -540,7 +540,7 @@ static bool _rasterMattedRle(SwSurface* surface, SwRle* rle, const RenderColor& if (surface->channelSize == sizeof(uint32_t)) { uint32_t src; auto color = surface->join(c.r, c.g, c.b, c.a); - for (uint32_t i = 0; i < rle->size; ++i, ++span) { + for (uint32_t i = 0; i < rle->size(); ++i, ++span) { auto dst = &surface->buf32[span->y * surface->stride + span->x]; auto cmp = &cbuffer[(span->y * surface->compositor->image.stride + span->x) * csize]; if (span->coverage == 255) src = color; @@ -553,7 +553,7 @@ static bool _rasterMattedRle(SwSurface* surface, SwRle* rle, const RenderColor& //8bit grayscale } else if (surface->channelSize == sizeof(uint8_t)) { uint8_t src; - for (uint32_t i = 0; i < rle->size; ++i, ++span) { + for (uint32_t i = 0; i < rle->size(); ++i, ++span) { auto dst = &surface->buf8[span->y * surface->stride + span->x]; auto cmp = &cbuffer[(span->y * surface->compositor->image.stride + span->x) * csize]; if (span->coverage == 255) src = c.a; @@ -571,10 +571,10 @@ static bool _rasterBlendingRle(SwSurface* surface, const SwRle* rle, const Rende { if (surface->channelSize != sizeof(uint32_t)) return false; - auto span = rle->spans; + auto span = rle->data(); auto color = surface->join(c.r, c.g, c.b, c.a); - for (uint32_t i = 0; i < rle->size; ++i, ++span) { + for (uint32_t i = 0; i < rle->size(); ++i, ++span) { auto dst = &surface->buf32[span->y * surface->stride + span->x]; if (span->coverage == 255) { for (uint32_t x = 0; x < span->len; ++x, ++dst) { @@ -605,12 +605,12 @@ static bool _rasterTranslucentRle(SwSurface* surface, const SwRle* rle, const Re static bool _rasterSolidRle(SwSurface* surface, const SwRle* rle, const RenderColor& c) { - auto span = rle->spans; + auto span = rle->data(); //32bit channels if (surface->channelSize == sizeof(uint32_t)) { auto color = surface->join(c.r, c.g, c.b, 255); - for (uint32_t i = 0; i < rle->size; ++i, ++span) { + for (uint32_t i = 0; i < rle->size(); ++i, ++span) { if (span->coverage == 255) { rasterPixel32(surface->buf32 + span->y * surface->stride, color, span->x, span->len); } else { @@ -624,7 +624,7 @@ static bool _rasterSolidRle(SwSurface* surface, const SwRle* rle, const RenderCo } //8bit grayscale } else if (surface->channelSize == sizeof(uint8_t)) { - for (uint32_t i = 0; i < rle->size; ++i, ++span) { + for (uint32_t i = 0; i < rle->size(); ++i, ++span) { if (span->coverage == 255) { rasterGrayscale8(surface->buf8, span->coverage, span->y * surface->stride + span->x, span->len); } else { @@ -687,14 +687,14 @@ static bool _rasterScaledMattedRleImage(SwSurface* surface, const SwImage* image { TVGLOG("SW_ENGINE", "Scaled Matted(%d) Rle Image", (int)surface->compositor->method); - auto span = image->rle->spans; + auto span = image->rle->data(); auto csize = surface->compositor->image.channelSize; auto alpha = surface->alpha(surface->compositor->method); auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; auto sampleSize = _sampleSize(image->scale); int32_t miny = 0, maxy = 0; - for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { + for (uint32_t i = 0; i < image->rle->size(); ++i, ++span) { SCALED_IMAGE_RANGE_Y(span->y) auto dst = &surface->buf32[span->y * surface->stride + span->x]; auto cmp = &surface->compositor->image.buf8[(span->y * surface->compositor->image.stride + span->x) * csize]; @@ -712,12 +712,12 @@ static bool _rasterScaledMattedRleImage(SwSurface* surface, const SwImage* image static bool _rasterScaledBlendingRleImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const RenderRegion& bbox, uint8_t opacity) { - auto span = image->rle->spans; + auto span = image->rle->data(); auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; auto sampleSize = _sampleSize(image->scale); int32_t miny = 0, maxy = 0; - for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { + for (uint32_t i = 0; i < image->rle->size(); ++i, ++span) { SCALED_IMAGE_RANGE_Y(span->y) auto dst = &surface->buf32[span->y * surface->stride + span->x]; auto alpha = MULTIPLY(span->coverage, opacity); @@ -743,12 +743,12 @@ static bool _rasterScaledBlendingRleImage(SwSurface* surface, const SwImage* ima static bool _rasterScaledRleImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const RenderRegion& bbox, uint8_t opacity) { - auto span = image->rle->spans; + auto span = image->rle->data(); auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; auto sampleSize = _sampleSize(image->scale); int32_t miny = 0, maxy = 0; - for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { + for (uint32_t i = 0; i < image->rle->size(); ++i, ++span) { SCALED_IMAGE_RANGE_Y(span->y) auto dst = &surface->buf32[span->y * surface->stride + span->x]; auto alpha = MULTIPLY(span->coverage, opacity); @@ -794,12 +794,12 @@ static bool _rasterDirectMattedRleImage(SwSurface* surface, const SwImage* image { TVGLOG("SW_ENGINE", "Direct Matted(%d) Rle Image", (int)surface->compositor->method); - auto span = image->rle->spans; + auto span = image->rle->data(); auto csize = surface->compositor->image.channelSize; auto cbuffer = surface->compositor->image.buf8; auto alpha = surface->alpha(surface->compositor->method); - for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { + for (uint32_t i = 0; i < image->rle->size(); ++i, ++span) { auto dst = &surface->buf32[span->y * surface->stride + span->x]; auto cmp = &cbuffer[(span->y * surface->compositor->image.stride + span->x) * csize]; auto img = image->buf32 + (span->y + image->oy) * image->stride + (span->x + image->ox); @@ -822,9 +822,9 @@ static bool _rasterDirectMattedRleImage(SwSurface* surface, const SwImage* image static bool _rasterDirectBlendingRleImage(SwSurface* surface, const SwImage* image, uint8_t opacity) { - auto span = image->rle->spans; + auto span = image->rle->data(); - for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { + for (uint32_t i = 0; i < image->rle->size(); ++i, ++span) { auto dst = &surface->buf32[span->y * surface->stride + span->x]; auto img = image->buf32 + (span->y + image->oy) * image->stride + (span->x + image->ox); auto alpha = MULTIPLY(span->coverage, opacity); @@ -845,9 +845,9 @@ static bool _rasterDirectBlendingRleImage(SwSurface* surface, const SwImage* ima static bool _rasterDirectRleImage(SwSurface* surface, const SwImage* image, uint8_t opacity) { - auto span = image->rle->spans; + auto span = image->rle->data(); - for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { + for (uint32_t i = 0; i < image->rle->size(); ++i, ++span) { auto dst = &surface->buf32[span->y * surface->stride + span->x]; auto img = image->buf32 + (span->y + image->oy) * image->stride + (span->x + image->ox); auto alpha = MULTIPLY(span->coverage, opacity); @@ -1378,11 +1378,11 @@ static bool _rasterRadialGradientRect(SwSurface* surface, const RenderRegion& bb template static bool _rasterCompositeGradientMaskedRle(SwSurface* surface, const SwRle* rle, const SwFill* fill, SwMask maskOp) { - auto span = rle->spans; + auto span = rle->data(); auto cstride = surface->compositor->image.stride; auto cbuffer = surface->compositor->image.buf8; - for (uint32_t i = 0; i < rle->size; ++i, ++span) { + for (uint32_t i = 0; i < rle->size(); ++i, ++span) { auto cmp = &cbuffer[span->y * cstride + span->x]; fillMethod()(fill, cmp, span->y, span->x, span->len, maskOp, span->coverage); } @@ -1393,12 +1393,12 @@ static bool _rasterCompositeGradientMaskedRle(SwSurface* surface, const SwRle* r template static bool _rasterDirectGradientMaskedRle(SwSurface* surface, const SwRle* rle, const SwFill* fill, SwMask maskOp) { - auto span = rle->spans; + auto span = rle->data(); auto cstride = surface->compositor->image.stride; auto cbuffer = surface->compositor->image.buf8; auto dbuffer = surface->buf8; - for (uint32_t i = 0; i < rle->size; ++i, ++span) { + for (uint32_t i = 0; i < rle->size(); ++i, ++span) { auto cmp = &cbuffer[span->y * cstride + span->x]; auto dst = &dbuffer[span->y * surface->stride + span->x]; fillMethod()(fill, dst, span->y, span->x, span->len, cmp, maskOp, span->coverage); @@ -1427,12 +1427,12 @@ static bool _rasterGradientMattedRle(SwSurface* surface, const SwRle* rle, const { TVGLOG("SW_ENGINE", "Matted(%d) Rle Linear Gradient", (int)surface->compositor->method); - auto span = rle->spans; + auto span = rle->data(); auto csize = surface->compositor->image.channelSize; auto cbuffer = surface->compositor->image.buf8; auto alpha = surface->alpha(surface->compositor->method); - for (uint32_t i = 0; i < rle->size; ++i, ++span) { + for (uint32_t i = 0; i < rle->size(); ++i, ++span) { auto dst = &surface->buf32[span->y * surface->stride + span->x]; auto cmp = &cbuffer[(span->y * surface->compositor->image.stride + span->x) * csize]; fillMethod()(fill, dst, span->y, span->x, span->len, cmp, alpha, csize, span->coverage); @@ -1444,9 +1444,9 @@ static bool _rasterGradientMattedRle(SwSurface* surface, const SwRle* rle, const template static bool _rasterBlendingGradientRle(SwSurface* surface, const SwRle* rle, const SwFill* fill) { - auto span = rle->spans; + auto span = rle->data(); - for (uint32_t i = 0; i < rle->size; ++i, ++span) { + for (uint32_t i = 0; i < rle->size(); ++i, ++span) { auto dst = &surface->buf32[span->y * surface->stride + span->x]; fillMethod()(fill, dst, span->y, span->x, span->len, opBlendPreNormal, surface->blender, span->coverage); } @@ -1457,18 +1457,18 @@ static bool _rasterBlendingGradientRle(SwSurface* surface, const SwRle* rle, con template static bool _rasterTranslucentGradientRle(SwSurface* surface, const SwRle* rle, const SwFill* fill) { - auto span = rle->spans; + auto span = rle->data(); //32 bits if (surface->channelSize == sizeof(uint32_t)) { - for (uint32_t i = 0; i < rle->size; ++i, ++span) { + for (uint32_t i = 0; i < rle->size(); ++i, ++span) { auto dst = &surface->buf32[span->y * surface->stride + span->x]; if (span->coverage == 255) fillMethod()(fill, dst, span->y, span->x, span->len, opBlendPreNormal, 255); else fillMethod()(fill, dst, span->y, span->x, span->len, opBlendNormal, span->coverage); } //8 bits } else if (surface->channelSize == sizeof(uint8_t)) { - for (uint32_t i = 0; i < rle->size; ++i, ++span) { + for (uint32_t i = 0; i < rle->size(); ++i, ++span) { auto dst = &surface->buf8[span->y * surface->stride + span->x]; fillMethod()(fill, dst, span->y, span->x, span->len, _opMaskAdd, span->coverage); } @@ -1480,18 +1480,18 @@ static bool _rasterTranslucentGradientRle(SwSurface* surface, const SwRle* rle, template static bool _rasterSolidGradientRle(SwSurface* surface, const SwRle* rle, const SwFill* fill) { - auto span = rle->spans; + auto span = rle->data(); //32 bits if (surface->channelSize == sizeof(uint32_t)) { - for (uint32_t i = 0; i < rle->size; ++i, ++span) { + for (uint32_t i = 0; i < rle->size(); ++i, ++span) { auto dst = &surface->buf32[span->y * surface->stride + span->x]; if (span->coverage == 255) fillMethod()(fill, dst, span->y, span->x, span->len, opBlendSrcOver, 255); else fillMethod()(fill, dst, span->y, span->x, span->len, opBlendInterp, span->coverage); } //8 bits } else if (surface->channelSize == sizeof(uint8_t)) { - for (uint32_t i = 0; i < rle->size; ++i, ++span) { + for (uint32_t i = 0; i < rle->size(); ++i, ++span) { auto dst = &surface->buf8[span->y * surface->stride + span->x]; if (span->coverage == 255) fillMethod()(fill, dst, span->y, span->x, span->len, _opMaskNone, 255); else fillMethod()(fill, dst, span->y, span->x, span->len, _opMaskAdd, span->coverage); diff --git a/src/renderer/sw_engine/tvgSwRasterAvx.h b/src/renderer/sw_engine/tvgSwRasterAvx.h index 6465243c..357e4d75 100644 --- a/src/renderer/sw_engine/tvgSwRasterAvx.h +++ b/src/renderer/sw_engine/tvgSwRasterAvx.h @@ -160,14 +160,14 @@ static bool avxRasterTranslucentRect(SwSurface* surface, const RenderRegion& bbo static bool avxRasterTranslucentRle(SwSurface* surface, const SwRle* rle, const RenderColor& c) { - auto span = rle->spans; + auto span = rle->data(); //32bit channels if (surface->channelSize == sizeof(uint32_t)) { auto color = surface->join(c.r, c.g, c.b, c.a); uint32_t src; - for (uint32_t i = 0; i < rle->size; ++i) { + for (uint32_t i = 0; i < rle->size(); ++i) { auto dst = &surface->buf32[span->y * surface->stride + span->x]; if (span->coverage < 255) src = ALPHA_BLEND(color, span->coverage); @@ -213,7 +213,7 @@ static bool avxRasterTranslucentRle(SwSurface* surface, const SwRle* rle, const } else if (surface->channelSize == sizeof(uint8_t)) { TVGLOG("SW_ENGINE", "Require AVX Optimization, Channel Size = %d", surface->channelSize); uint8_t src; - for (uint32_t i = 0; i < rle->size; ++i, ++span) { + for (uint32_t i = 0; i < rle->size(); ++i, ++span) { auto dst = &surface->buf8[span->y * surface->stride + span->x]; if (span->coverage < 255) src = MULTIPLY(span->coverage, c.a); else src = c.a; diff --git a/src/renderer/sw_engine/tvgSwRasterC.h b/src/renderer/sw_engine/tvgSwRasterC.h index 59ed98c0..ea4a485f 100644 --- a/src/renderer/sw_engine/tvgSwRasterC.h +++ b/src/renderer/sw_engine/tvgSwRasterC.h @@ -94,13 +94,13 @@ static void inline cRasterPixels(PIXEL_T* dst, PIXEL_T val, uint32_t offset, int static bool inline cRasterTranslucentRle(SwSurface* surface, const SwRle* rle, const RenderColor& c) { - auto span = rle->spans; + auto span = rle->data(); //32bit channels if (surface->channelSize == sizeof(uint32_t)) { auto color = surface->join(c.r, c.g, c.b, c.a); uint32_t src; - for (uint32_t i = 0; i < rle->size; ++i, ++span) { + for (uint32_t i = 0; i < rle->size(); ++i, ++span) { auto dst = &surface->buf32[span->y * surface->stride + span->x]; if (span->coverage < 255) src = ALPHA_BLEND(color, span->coverage); else src = color; @@ -112,7 +112,7 @@ static bool inline cRasterTranslucentRle(SwSurface* surface, const SwRle* rle, c //8bit grayscale } else if (surface->channelSize == sizeof(uint8_t)) { uint8_t src; - for (uint32_t i = 0; i < rle->size; ++i, ++span) { + for (uint32_t i = 0; i < rle->size(); ++i, ++span) { auto dst = &surface->buf8[span->y * surface->stride + span->x]; if (span->coverage < 255) src = MULTIPLY(span->coverage, c.a); else src = c.a; diff --git a/src/renderer/sw_engine/tvgSwRasterNeon.h b/src/renderer/sw_engine/tvgSwRasterNeon.h index 387b81a6..b3a73177 100644 --- a/src/renderer/sw_engine/tvgSwRasterNeon.h +++ b/src/renderer/sw_engine/tvgSwRasterNeon.h @@ -91,7 +91,7 @@ static void neonRasterPixel32(uint32_t *dst, uint32_t val, uint32_t offset, int3 static bool neonRasterTranslucentRle(SwSurface* surface, const SwRle* rle, const RenderColor& c) { - auto span = rle->spans; + auto span = rle->data(); //32bit channels if (surface->channelSize == sizeof(uint32_t)) { @@ -100,7 +100,7 @@ static bool neonRasterTranslucentRle(SwSurface* surface, const SwRle* rle, const uint8x8_t *vDst = nullptr; uint16_t align; - for (uint32_t i = 0; i < rle->size; ++i) { + for (uint32_t i = 0; i < rle->size(); ++i) { if (span->coverage < 255) src = ALPHA_BLEND(color, span->coverage); else src = color; @@ -132,7 +132,7 @@ static bool neonRasterTranslucentRle(SwSurface* surface, const SwRle* rle, const } else if (surface->channelSize == sizeof(uint8_t)) { TVGLOG("SW_ENGINE", "Require Neon Optimization, Channel Size = %d", surface->channelSize); uint8_t src; - for (uint32_t i = 0; i < rle->size; ++i, ++span) { + for (uint32_t i = 0; i < rle->size(); ++i, ++span) { auto dst = &surface->buf8[span->y * surface->stride + span->x]; if (span->coverage < 255) src = MULTIPLY(span->coverage, c.a); else src = c.a; diff --git a/src/renderer/sw_engine/tvgSwRasterTexmap.h b/src/renderer/sw_engine/tvgSwRasterTexmap.h index 4b777d6f..62b0bea3 100644 --- a/src/renderer/sw_engine/tvgSwRasterTexmap.h +++ b/src/renderer/sw_engine/tvgSwRasterTexmap.h @@ -60,8 +60,8 @@ static bool _arrange(const SwImage* image, const RenderRegion* bbox, int& yStart bboxTop = bbox->min.y; bboxBottom = bbox->max.y; } else { - bboxTop = image->rle->spans->y; - bboxBottom = image->rle->spans[image->rle->size - 1].y; + bboxTop = image->rle->spans.first().y; + bboxBottom = image->rle->spans.last().y; } if (yStart < bboxTop) yStart = bboxTop; @@ -103,7 +103,7 @@ static void _rasterBlendingPolygonImageSegment(SwSurface* surface, const SwImage minx = bbox->min.x; maxx = bbox->max.x; } else { - span = image->rle->spans; + span = image->rle->data(); while (span->y < yStart) { ++span; ++spanIdx; @@ -120,7 +120,7 @@ static void _rasterBlendingPolygonImageSegment(SwSurface* surface, const SwImage minx = INT32_MAX; maxx = 0; //one single row, could be consisted of multiple spans. - while (span->y == y && spanIdx < image->rle->size) { + while (span->y == y && spanIdx < image->rle->size()) { if (minx > span->x) minx = span->x; if (maxx < span->x + span->len) maxx = span->x + span->len; ++span; @@ -195,7 +195,7 @@ static void _rasterBlendingPolygonImageSegment(SwSurface* surface, const SwImage _ua += _dudya; _va += _dvdya; - if (!bbox && spanIdx >= image->rle->size) break; + if (!bbox && spanIdx >= image->rle->size()) break; ++y; } @@ -236,7 +236,7 @@ static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, minx = bbox->min.x; maxx = bbox->max.x; } else { - span = image->rle->spans; + span = image->rle->data(); while (span->y < yStart) { ++span; ++spanIdx; @@ -253,7 +253,7 @@ static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, minx = INT32_MAX; maxx = 0; //one single row, could be consisted of multiple spans. - while (span->y == y && spanIdx < image->rle->size) { + while (span->y == y && spanIdx < image->rle->size()) { if (minx > span->x) minx = span->x; if (maxx < span->x + span->len) maxx = span->x + span->len; ++span; @@ -387,7 +387,7 @@ static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, _ua += _dudya; _va += _dvdya; - if (!bbox && spanIdx >= image->rle->size) break; + if (!bbox && spanIdx >= image->rle->size()) break; ++y; } @@ -460,7 +460,7 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const if (tvg::equal(y[0], y[1])) side = x[0] > x[1]; if (tvg::equal(y[1], y[2])) side = x[2] > x[1]; - auto bboxTop = bbox ? bbox->min.y : image->rle->spans->y; //Normal Image or Rle Image? + auto bboxTop = bbox ? bbox->min.y : image->rle->data()->y; //Normal Image or Rle Image? auto compositing = _compositing(surface); //Composition required auto blending = _blending(surface); //Blending required @@ -871,7 +871,7 @@ static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const } //Exceptions: No dedicated drawing area? - if ((!image->rle && !bbox) || (image->rle && image->rle->size == 0)) return true; + if ((!image->rle && !bbox) || (image->rle && image->rle->size() == 0)) return true; /* Prepare vertices. shift XY coordinates to match the sub-pixeling technique. */ diff --git a/src/renderer/sw_engine/tvgSwRle.cpp b/src/renderer/sw_engine/tvgSwRle.cpp index 48ad3f91..1b8830f6 100644 --- a/src/renderer/sw_engine/tvgSwRle.cpp +++ b/src/renderer/sw_engine/tvgSwRle.cpp @@ -324,27 +324,18 @@ static void _horizLine(RleWorker& rw, SwCoord x, SwCoord y, SwCoord area, SwCoor if (!rw.antiAlias) coverage = 255; //see whether we can add this span to the current list - if (rle->size > 0) { - auto span = rle->spans + rle->size - 1; - if ((span->coverage == coverage) && (span->y == y) && (span->x + span->len == x)) { + if (!rle->spans.empty()) { + auto& span = rle->spans.last(); + if ((span.coverage == coverage) && (span.y == y) && (span.x + span.len == x)) { //Clip x range SwCoord xOver = 0; if (x + aCount >= rw.cellMax.x) xOver -= (x + aCount - rw.cellMax.x); if (x < rw.cellMin.x) xOver -= (rw.cellMin.x - x); - span->len += (aCount + xOver); + span.len += (aCount + xOver); return; } } - //span pool is full, grow it. - if (rle->size >= rle->alloc) { - auto newSize = (rle->size > 0) ? (rle->size * 2) : 256; - if (rle->alloc < newSize) { - rle->alloc = newSize; - rle->spans = tvg::realloc(rle->spans, rle->alloc * sizeof(SwSpan)); - } - } - //Clip x range SwCoord xOver = 0; if (x + aCount >= rw.cellMax.x) xOver -= (x + aCount - rw.cellMax.x); @@ -357,12 +348,7 @@ static void _horizLine(RleWorker& rw, SwCoord x, SwCoord y, SwCoord area, SwCoor if (aCount + xOver <= 0) return; //add a span to the current list - auto span = rle->spans + rle->size; - span->x = x; - span->y = y; - span->len = (aCount + xOver); - span->coverage = coverage; - rle->size++; + rle->spans.next() = {(uint16_t)x, (uint16_t)y, uint16_t(aCount + xOver), (uint8_t)coverage}; } @@ -737,109 +723,6 @@ static bool _genRle(RleWorker& rw) } -static SwSpan* _intersectSpansRegion(const SwRle *clip, const SwRle *target, SwSpan *outSpans, uint32_t outSpansCnt) -{ - auto out = outSpans; - auto spans = target->spans; - auto end = target->spans + target->size; - auto clipSpans = clip->spans; - auto clipEnd = clip->spans + clip->size; - - while (spans < end && clipSpans < clipEnd) { - //align y-coordinates. - if (clipSpans->y > spans->y) { - ++spans; - continue; - } - if (spans->y > clipSpans->y) { - ++clipSpans; - continue; - } - - //Try clipping with all clip spans which have a same y-coordinate. - auto temp = clipSpans; - while(temp < clipEnd && temp->y == clipSpans->y) { - if (outSpansCnt == 0) { - TVGERR("SW_ENGINE", "span buffer is over."); - break; - } - auto sx1 = spans->x; - auto sx2 = sx1 + spans->len; - auto cx1 = temp->x; - auto cx2 = cx1 + temp->len; - - //The span must be left(x1) to right(x2) direction. Not intersected. - if (cx2 < sx1 || sx2 < cx1) { - ++temp; - continue; - } - - //clip span region. - auto x = sx1 > cx1 ? sx1 : cx1; - auto len = (sx2 < cx2 ? sx2 : cx2) - x; - if (len > 0) { - out->x = x; - out->y = temp->y; - out->len = len; - out->coverage = (uint8_t)(((spans->coverage * temp->coverage) + 0xff) >> 8); - ++out; - --outSpansCnt; - } - ++temp; - } - ++spans; - } - return out; -} - - -static SwSpan* _intersectSpansRect(const RenderRegion *bbox, const SwRle *targetRle, SwSpan *outSpans, uint32_t outSpansCnt) -{ - auto out = outSpans; - auto spans = targetRle->spans; - auto end = targetRle->spans + targetRle->size; - auto minx = static_cast(bbox->min.x); - auto miny = static_cast(bbox->min.y); - auto maxx = minx + static_cast(bbox->max.x - bbox->min.x) - 1; - auto maxy = miny + static_cast(bbox->max.y - bbox->min.y) - 1; - - while (outSpansCnt > 0 && spans < end) { - if (spans->y > maxy) { - spans = end; - break; - } - if (spans->y < miny || spans->x > maxx || spans->x + spans->len <= minx) { - ++spans; - continue; - } - if (spans->x < minx) { - out->len = (spans->len - (minx - spans->x)) < (maxx - minx + 1) ? (spans->len - (minx - spans->x)) : (maxx - minx + 1); - out->x = minx; - } - else { - out->x = spans->x; - out->len = spans->len < (maxx - spans->x + 1) ? spans->len : (maxx - spans->x + 1); - } - if (out->len > 0) { - out->y = spans->y; - out->coverage = spans->coverage; - ++out; - --outSpansCnt; - } - ++spans; - } - return out; -} - - -void _replaceClipSpan(SwRle *rle, SwSpan* clippedSpans, uint32_t size) -{ - tvg::free(rle->spans); - rle->spans = clippedSpans; - rle->size = rle->alloc = size; -} - - /************************************************************************/ /* External Class Implementation */ /************************************************************************/ @@ -876,6 +759,7 @@ SwRle* rleRender(SwRle* rle, const SwOutline* outline, const RenderRegion& bbox, if (!rle) rw.rle = tvg::calloc(1, sizeof(SwRle)); else rw.rle = rle; + rw.rle->spans.reserve(256); //Generate RLE Band bands[BAND_SIZE]; @@ -963,20 +847,17 @@ error: SwRle* rleRender(const RenderRegion* bbox) { - auto width = static_cast(bbox->w()); - auto height = static_cast(bbox->h()); + auto rle = tvg::calloc(sizeof(SwRle), 1); + rle->spans.reserve(bbox->h()); + rle->spans.count = bbox->h(); - auto rle = tvg::malloc(sizeof(SwRle)); - rle->spans = tvg::malloc(sizeof(SwSpan) * height); - rle->size = height; - rle->alloc = height; + //cheaper without push() + auto x = uint16_t(bbox->min.x); + auto y = uint16_t(bbox->min.y); + auto len = uint16_t(bbox->w()); - auto span = rle->spans; - for (uint16_t i = 0; i < height; ++i, ++span) { - span->x = bbox->min.x; - span->y = bbox->min.y + i; - span->len = width; - span->coverage = 255; + ARRAY_FOREACH(p, rle->spans) { + *p = {x, y++, len, 255}; } return rle; @@ -985,44 +866,89 @@ SwRle* rleRender(const RenderRegion* bbox) void rleReset(SwRle* rle) { - if (!rle) return; - rle->size = 0; + if (rle) rle->spans.clear(); } void rleFree(SwRle* rle) { if (!rle) return; - if (rle->spans) tvg::free(rle->spans); + rle->spans.reset(); tvg::free(rle); } bool rleClip(SwRle *rle, const SwRle *clip) { - if (rle->size == 0 || clip->size == 0) return false; - auto spanCnt = 2 * (rle->size > clip->size ? rle->size : clip->size); //factor 2 added for safety (no real cases observed where the factor exceeded 1.4) - auto spans = tvg::malloc(sizeof(SwSpan) * (spanCnt)); - auto spansEnd = _intersectSpansRegion(clip, rle, spans, spanCnt); + if (rle->spans.empty() || clip->spans.empty()) return false; - _replaceClipSpan(rle, spans, spansEnd - spans); + Array out; + out.reserve(std::max(rle->spans.count, clip->spans.count)); - TVGLOG("SW_ENGINE", "Using Path Clipping!"); + auto spans = rle->data(); + auto end = rle->spans.end(); + auto cspans = clip->data(); + auto cend = clip->spans.end(); + while(spans < end && cspans < cend) { + //align y-coordinates. + if (cspans->y > spans->y) { + ++spans; + continue; + } + if (spans->y > cspans->y) { + ++cspans; + continue; + } + //try clipping with all clip spans which have a same y-coordinate. + auto temp = cspans; + while(temp->y == cspans->y && temp < cend) { + //span must be left(x1) to right(x2) direction. Not intersected. + if ((spans->x + spans->len) < spans->x || (temp->x + temp->len) < temp->x) { + ++temp; + continue; + } + //clip span region + auto x = std::max(spans->x, temp->x); + auto len = std::min((spans->x + spans->len), (temp->x + temp->len)) - x; + if (len > 0) out.next() = {uint16_t(x), temp->y, uint16_t(len), (uint8_t)(((spans->coverage * temp->coverage) + 0xff) >> 8)}; + ++temp; + } + ++spans; + } + out.move(rle->spans); return true; } bool rleClip(SwRle *rle, const RenderRegion* clip) { - if (rle->size == 0) return false; - auto spans = tvg::malloc(sizeof(SwSpan) * (rle->size)); - auto spansEnd = _intersectSpansRect(clip, rle, spans, rle->size); + if (rle->spans.empty() || clip->invalid()) return false; - _replaceClipSpan(rle, spans, spansEnd - spans); + auto& min = clip->min; + auto& max = clip->max; - TVGLOG("SW_ENGINE", "Using Box Clipping!"); + Array out; + out.reserve(rle->spans.count); + auto data = out.data; + uint16_t x, len; + ARRAY_FOREACH(p, rle->spans) { + if (p->y >= max.y) break; + if (p->y < min.y || p->x >= max.x || (p->x + p->len) <= min.x) continue; + if (p->x < min.x) { + x = min.x; + len = std::min((p->len - (x - p->x)), (max.x - x)); + } else { + x = p->x; + len = std::min(p->len, uint16_t(max.x - x)); + } + if (len > 0) { + *data = {x, p->y, len, p->coverage}; + ++data; + ++out.count; + } + } + out.move(rle->spans); return true; -} - +} \ No newline at end of file