sw_engine raster: ++tiny optimization

Attempt to perform as much computation as possible
before entering the rasterization stage.

This contains the code refactoring as well.
This commit is contained in:
Hermet Park 2023-06-19 17:58:45 +09:00 committed by Hermet Park
parent 0cc7833000
commit 0b65d1fce5

View file

@ -217,17 +217,17 @@ struct DifMaskAOp
#include "tvgSwRasterNeon.h" #include "tvgSwRasterNeon.h"
static inline uint32_t _halfScale(float scale) static inline uint32_t _sampleSize(float scale)
{ {
auto halfScale = static_cast<uint32_t>(0.5f / scale); auto sampleSize = static_cast<uint32_t>(0.5f / scale);
if (halfScale == 0) halfScale = 1; if (sampleSize == 0) sampleSize = 1;
return halfScale; return sampleSize;
} }
//Bilinear Interpolation //Bilinear Interpolation
//OPTIMIZE_ME: Skip the function pointer access //OPTIMIZE_ME: Skip the function pointer access
static uint32_t _interpUpScaler(const uint32_t *img, TVG_UNUSED uint32_t stride, uint32_t w, uint32_t h, float sx, float sy, TVG_UNUSED uint32_t n) static uint32_t _interpUpScaler(const uint32_t *img, TVG_UNUSED uint32_t stride, uint32_t w, uint32_t h, float sx, float sy, TVG_UNUSED uint32_t n, TVG_UNUSED uint32_t n2)
{ {
auto rx = (uint32_t)(sx); auto rx = (uint32_t)(sx);
auto ry = (uint32_t)(sy); auto ry = (uint32_t)(sy);
@ -250,12 +250,11 @@ static uint32_t _interpUpScaler(const uint32_t *img, TVG_UNUSED uint32_t stride,
//2n x 2n Mean Kernel //2n x 2n Mean Kernel
//OPTIMIZE_ME: Skip the function pointer access //OPTIMIZE_ME: Skip the function pointer access
static uint32_t _interpDownScaler(const uint32_t *img, uint32_t stride, uint32_t w, uint32_t h, float sx, float sy, uint32_t n) static uint32_t _interpDownScaler(const uint32_t *img, uint32_t stride, uint32_t w, uint32_t h, float sx, float sy, uint32_t n, uint32_t n2)
{ {
uint32_t rx = sx; uint32_t rx = sx;
uint32_t ry = sy; uint32_t ry = sy;
uint32_t c[4] = {0, 0, 0, 0}; uint32_t c[4] = {0, 0, 0, 0};
auto n2 = n * n;
auto src = img + rx - n + (ry - n) * stride; auto src = img + rx - n + (ry - n) * stride;
for (auto y = ry - n; y < ry + n; ++y) { for (auto y = ry - n; y < ry + n; ++y) {
@ -686,9 +685,11 @@ static bool _transformedRleRGBAImage(SwSurface* surface, const SwImage* image, c
/************************************************************************/ /************************************************************************/
template<typename maskOp, typename amaskOp> template<typename maskOp, typename amaskOp>
static void _rasterScaledMaskedRleRGBAImageDup(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t opacity, uint32_t halfScale) static void _rasterScaledMaskedRleRGBAImageDup(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t opacity)
{ {
auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler;
auto sampleSize = _sampleSize(image->scale);
auto sampleSize2 = sampleSize * sampleSize;
auto span = image->rle->spans; auto span = image->rle->spans;
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
@ -700,14 +701,14 @@ static void _rasterScaledMaskedRleRGBAImageDup(SwSurface* surface, const SwImage
for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++cmp) { for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++cmp) {
auto sx = x * itransform->e11 + itransform->e13; auto sx = x * itransform->e11 + itransform->e13;
if ((uint32_t)sx >= image->w) continue; if ((uint32_t)sx >= image->w) continue;
auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale); auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2);
*cmp = maskOp()(src, *cmp, 255); *cmp = maskOp()(src, *cmp, 255);
} }
} else { } else {
for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++cmp) { for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++cmp) {
auto sx = x * itransform->e11 + itransform->e13; auto sx = x * itransform->e11 + itransform->e13;
if ((uint32_t)sx >= image->w) continue; if ((uint32_t)sx >= image->w) continue;
auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale); auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2);
*cmp = amaskOp()(src, *cmp, a); *cmp = amaskOp()(src, *cmp, a);
} }
} }
@ -715,9 +716,11 @@ static void _rasterScaledMaskedRleRGBAImageDup(SwSurface* surface, const SwImage
} }
static void _rasterScaledMaskedRleRGBAImageInt(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t opacity, uint32_t halfScale) static void _rasterScaledMaskedRleRGBAImageInt(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t opacity)
{ {
auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler;
auto sampleSize = _sampleSize(image->scale);
auto sampleSize2 = sampleSize * sampleSize;
auto span = image->rle->spans; auto span = image->rle->spans;
auto cbuffer = surface->compositor->image.buf32; auto cbuffer = surface->compositor->image.buf32;
auto cstride = surface->compositor->image.stride; auto cstride = surface->compositor->image.stride;
@ -733,14 +736,14 @@ static void _rasterScaledMaskedRleRGBAImageInt(SwSurface* surface, const SwImage
for (uint32_t i = 0; i < span->len; ++i) { for (uint32_t i = 0; i < span->len; ++i) {
auto sx = (x + i) * itransform->e11 + itransform->e13; auto sx = (x + i) * itransform->e11 + itransform->e13;
if ((uint32_t)sx >= image->w) continue; if ((uint32_t)sx >= image->w) continue;
auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale); auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2);
cmp[x + i] = ALPHA_BLEND(cmp[x + i], A(src)); cmp[x + i] = ALPHA_BLEND(cmp[x + i], A(src));
} }
} else { } else {
for (uint32_t i = 0; i < span->len; ++i) { for (uint32_t i = 0; i < span->len; ++i) {
auto sx = (x + i) * itransform->e11 + itransform->e13; auto sx = (x + i) * itransform->e11 + itransform->e13;
if ((uint32_t)sx >= image->w) continue; if ((uint32_t)sx >= image->w) continue;
auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale); auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2);
cmp[x + i] = ALPHA_BLEND(cmp[x + i], A(ALPHA_BLEND(src, alpha))); cmp[x + i] = ALPHA_BLEND(cmp[x + i], A(ALPHA_BLEND(src, alpha)));
} }
} }
@ -754,16 +757,16 @@ static void _rasterScaledMaskedRleRGBAImageInt(SwSurface* surface, const SwImage
} }
static bool _rasterScaledMaskedRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t opacity, uint32_t halfScale) static bool _rasterScaledMaskedRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t opacity)
{ {
TVGLOG("SW_ENGINE", "Scaled Masked(%d) Rle Image", (int)surface->compositor->method); TVGLOG("SW_ENGINE", "Scaled Masked(%d) Rle Image", (int)surface->compositor->method);
auto method = surface->compositor->method; auto method = surface->compositor->method;
if (method == CompositeMethod::AddMask) _rasterScaledMaskedRleRGBAImageDup<AddMaskOp, AddMaskAOp>(surface, image, itransform, region, opacity, halfScale); if (method == CompositeMethod::AddMask) _rasterScaledMaskedRleRGBAImageDup<AddMaskOp, AddMaskAOp>(surface, image, itransform, region, opacity);
else if (method == CompositeMethod::SubtractMask) _rasterScaledMaskedRleRGBAImageDup<SubMaskOp, SubMaskAOp>(surface, image, itransform, region, opacity, halfScale); else if (method == CompositeMethod::SubtractMask) _rasterScaledMaskedRleRGBAImageDup<SubMaskOp, SubMaskAOp>(surface, image, itransform, region, opacity);
else if (method == CompositeMethod::DifferenceMask) _rasterScaledMaskedRleRGBAImageDup<DifMaskOp, DifMaskAOp>(surface, image, itransform, region, opacity, halfScale); else if (method == CompositeMethod::DifferenceMask) _rasterScaledMaskedRleRGBAImageDup<DifMaskOp, DifMaskAOp>(surface, image, itransform, region, opacity);
else if (method == CompositeMethod::IntersectMask) _rasterScaledMaskedRleRGBAImageInt(surface, image, itransform, region, opacity, halfScale); else if (method == CompositeMethod::IntersectMask) _rasterScaledMaskedRleRGBAImageInt(surface, image, itransform, region, opacity);
else return false; else return false;
//Masking Composition //Masking Composition
@ -771,7 +774,7 @@ static bool _rasterScaledMaskedRleRGBAImage(SwSurface* surface, const SwImage* i
} }
static bool _rasterScaledMattedRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t opacity, uint32_t halfScale) static bool _rasterScaledMattedRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t opacity)
{ {
TVGLOG("SW_ENGINE", "Scaled Matted(%d) Rle Image", (int)surface->compositor->method); TVGLOG("SW_ENGINE", "Scaled Matted(%d) Rle Image", (int)surface->compositor->method);
@ -780,6 +783,8 @@ static bool _rasterScaledMattedRleRGBAImage(SwSurface* surface, const SwImage* i
auto alpha = surface->alpha(surface->compositor->method); auto alpha = surface->alpha(surface->compositor->method);
auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler;
auto sampleSize = _sampleSize(image->scale);
auto sampleSize2 = sampleSize * sampleSize;
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
auto sy = span->y * itransform->e22 + itransform->e23; auto sy = span->y * itransform->e22 + itransform->e23;
@ -791,14 +796,14 @@ static bool _rasterScaledMattedRleRGBAImage(SwSurface* surface, const SwImage* i
for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst, cmp += csize) { for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst, cmp += csize) {
auto sx = x * itransform->e11 + itransform->e13; auto sx = x * itransform->e11 + itransform->e13;
if ((uint32_t)sx >= image->w) continue; if ((uint32_t)sx >= image->w) continue;
auto tmp = ALPHA_BLEND(scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale), alpha(cmp)); auto tmp = ALPHA_BLEND(scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2), alpha(cmp));
*dst = tmp + ALPHA_BLEND(*dst, IA(tmp)); *dst = tmp + ALPHA_BLEND(*dst, IA(tmp));
} }
} else { } else {
for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst, cmp += csize) { for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst, cmp += csize) {
auto sx = x * itransform->e11 + itransform->e13; auto sx = x * itransform->e11 + itransform->e13;
if ((uint32_t)sx >= image->w) continue; if ((uint32_t)sx >= image->w) continue;
auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale); auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2);
auto tmp = ALPHA_BLEND(src, MULTIPLY(alpha(cmp), a)); auto tmp = ALPHA_BLEND(src, MULTIPLY(alpha(cmp), a));
*dst = tmp + ALPHA_BLEND(*dst, IA(tmp)); *dst = tmp + ALPHA_BLEND(*dst, IA(tmp));
} }
@ -809,10 +814,12 @@ static bool _rasterScaledMattedRleRGBAImage(SwSurface* surface, const SwImage* i
} }
static bool _rasterScaledBlendingRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t opacity, uint32_t halfScale) static bool _rasterScaledBlendingRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t opacity)
{ {
auto span = image->rle->spans; auto span = image->rle->spans;
auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler;
auto sampleSize = _sampleSize(image->scale);
auto sampleSize2 = sampleSize * sampleSize;
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
auto sy = span->y * itransform->e22 + itransform->e23; auto sy = span->y * itransform->e22 + itransform->e23;
@ -823,7 +830,7 @@ static bool _rasterScaledBlendingRleRGBAImage(SwSurface* surface, const SwImage*
for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst) { for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst) {
auto sx = x * itransform->e11 + itransform->e13; auto sx = x * itransform->e11 + itransform->e13;
if ((uint32_t)sx >= image->w) continue; if ((uint32_t)sx >= image->w) continue;
auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale); auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2);
auto tmp = surface->blender(src, *dst, 255); auto tmp = surface->blender(src, *dst, 255);
*dst = INTERPOLATE(tmp, *dst, A(src)); *dst = INTERPOLATE(tmp, *dst, A(src));
} }
@ -831,7 +838,7 @@ static bool _rasterScaledBlendingRleRGBAImage(SwSurface* surface, const SwImage*
for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst) { for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst) {
auto sx = x * itransform->e11 + itransform->e13; auto sx = x * itransform->e11 + itransform->e13;
if ((uint32_t)sx >= image->w) continue; if ((uint32_t)sx >= image->w) continue;
auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale); auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2);
auto tmp = surface->blender(src, *dst, 255); auto tmp = surface->blender(src, *dst, 255);
*dst = INTERPOLATE(tmp, *dst, MULTIPLY(span->coverage, A(src))); *dst = INTERPOLATE(tmp, *dst, MULTIPLY(span->coverage, A(src)));
} }
@ -839,7 +846,7 @@ static bool _rasterScaledBlendingRleRGBAImage(SwSurface* surface, const SwImage*
for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst) { for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst) {
auto sx = x * itransform->e11 + itransform->e13; auto sx = x * itransform->e11 + itransform->e13;
if ((uint32_t)sx >= image->w) continue; if ((uint32_t)sx >= image->w) continue;
auto src = ALPHA_BLEND(scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale), opacity); auto src = ALPHA_BLEND(scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2), opacity);
auto tmp = surface->blender(src, *dst, 255); auto tmp = surface->blender(src, *dst, 255);
*dst = INTERPOLATE(tmp, *dst, MULTIPLY(span->coverage, A(src))); *dst = INTERPOLATE(tmp, *dst, MULTIPLY(span->coverage, A(src)));
} }
@ -849,11 +856,12 @@ static bool _rasterScaledBlendingRleRGBAImage(SwSurface* surface, const SwImage*
} }
static bool _rasterScaledRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t opacity, uint32_t halfScale) static bool _rasterScaledRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t opacity)
{ {
auto span = image->rle->spans; auto span = image->rle->spans;
auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler;
auto sampleSize = _sampleSize(image->scale);
auto sampleSize2 = sampleSize * sampleSize;
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
auto sy = span->y * itransform->e22 + itransform->e23; auto sy = span->y * itransform->e22 + itransform->e23;
@ -864,14 +872,14 @@ static bool _rasterScaledRleRGBAImage(SwSurface* surface, const SwImage* image,
for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst) { for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst) {
auto sx = x * itransform->e11 + itransform->e13; auto sx = x * itransform->e11 + itransform->e13;
if ((uint32_t)sx >= image->w) continue; if ((uint32_t)sx >= image->w) continue;
auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale); auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2);
*dst = src + ALPHA_BLEND(*dst, IA(src)); *dst = src + ALPHA_BLEND(*dst, IA(src));
} }
} else { } else {
for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst) { for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst) {
auto sx = x * itransform->e11 + itransform->e13; auto sx = x * itransform->e11 + itransform->e13;
if ((uint32_t)sx >= image->w) continue; if ((uint32_t)sx >= image->w) continue;
auto src = ALPHA_BLEND(scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale), alpha); auto src = ALPHA_BLEND(scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2), alpha);
*dst = src + ALPHA_BLEND(*dst, IA(src)); *dst = src + ALPHA_BLEND(*dst, IA(src));
} }
} }
@ -888,15 +896,13 @@ static bool _scaledRleRGBAImage(SwSurface* surface, const SwImage* image, const
if (!mathInverse(transform, &itransform)) return false; if (!mathInverse(transform, &itransform)) return false;
} else mathIdentity(&itransform); } else mathIdentity(&itransform);
auto halfScale = _halfScale(image->scale);
if (_compositing(surface)) { if (_compositing(surface)) {
if (_matting(surface)) _rasterScaledMattedRleRGBAImage(surface, image, &itransform, region, opacity, halfScale); if (_matting(surface)) return _rasterScaledMattedRleRGBAImage(surface, image, &itransform, region, opacity);
else _rasterScaledMaskedRleRGBAImage(surface, image, &itransform, region, opacity, halfScale); else return _rasterScaledMaskedRleRGBAImage(surface, image, &itransform, region, opacity);
} else if (_blending(surface)) { } else if (_blending(surface)) {
return _rasterScaledBlendingRleRGBAImage(surface, image, &itransform, region, opacity, halfScale); return _rasterScaledBlendingRleRGBAImage(surface, image, &itransform, region, opacity);
} else { } else {
return _rasterScaledRleRGBAImage(surface, image, &itransform, region, opacity, halfScale); return _rasterScaledRleRGBAImage(surface, image, &itransform, region, opacity);
} }
return false; return false;
} }
@ -1106,9 +1112,11 @@ static bool _transformedRGBAImageMesh(SwSurface* surface, const SwImage* image,
/************************************************************************/ /************************************************************************/
template<typename maskOp, typename amaskOp> template<typename maskOp, typename amaskOp>
static void _rasterScaledMaskedRGBAImageDup(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t opacity, uint32_t halfScale) static void _rasterScaledMaskedRGBAImageDup(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t opacity)
{ {
auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler;
auto sampleSize = _sampleSize(image->scale);
auto sampleSize2 = sampleSize * sampleSize;
auto cstride = surface->compositor->image.stride; auto cstride = surface->compositor->image.stride;
auto cbuffer = surface->compositor->image.buf32 + (region.min.y * cstride + region.min.x); auto cbuffer = surface->compositor->image.buf32 + (region.min.y * cstride + region.min.x);
@ -1120,14 +1128,14 @@ static void _rasterScaledMaskedRGBAImageDup(SwSurface* surface, const SwImage* i
for (auto x = region.min.x; x < region.max.x; ++x, ++cmp) { for (auto x = region.min.x; x < region.max.x; ++x, ++cmp) {
auto sx = x * itransform->e11 + itransform->e13; auto sx = x * itransform->e11 + itransform->e13;
if ((uint32_t)sx >= image->w) continue; if ((uint32_t)sx >= image->w) continue;
auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale); auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2);
*cmp = maskOp()(src, *cmp, IA(src)); *cmp = maskOp()(src, *cmp, IA(src));
} }
} else { } else {
for (auto x = region.min.x; x < region.max.x; ++x, ++cmp) { for (auto x = region.min.x; x < region.max.x; ++x, ++cmp) {
auto sx = x * itransform->e11 + itransform->e13; auto sx = x * itransform->e11 + itransform->e13;
if ((uint32_t)sx >= image->w) continue; if ((uint32_t)sx >= image->w) continue;
auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale); auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2);
*cmp = amaskOp()(src, *cmp, opacity); *cmp = amaskOp()(src, *cmp, opacity);
} }
} }
@ -1135,9 +1143,11 @@ static void _rasterScaledMaskedRGBAImageDup(SwSurface* surface, const SwImage* i
} }
} }
static void _rasterScaledMaskedRGBAImageInt(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t opacity, uint32_t halfScale) static void _rasterScaledMaskedRGBAImageInt(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t opacity)
{ {
auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler;
auto sampleSize = _sampleSize(image->scale);
auto sampleSize2 = sampleSize * sampleSize;
auto h = static_cast<uint32_t>(region.max.y - region.min.y); auto h = static_cast<uint32_t>(region.max.y - region.min.y);
auto w = static_cast<uint32_t>(region.max.x - region.min.x); auto w = static_cast<uint32_t>(region.max.x - region.min.x);
auto cstride = surface->compositor->image.stride; auto cstride = surface->compositor->image.stride;
@ -1157,14 +1167,14 @@ static void _rasterScaledMaskedRGBAImageInt(SwSurface* surface, const SwImage* i
for (uint32_t i = 0; i < w; ++i, ++tmp) { for (uint32_t i = 0; i < w; ++i, ++tmp) {
auto sx = (x + i) * itransform->e11 + itransform->e13; auto sx = (x + i) * itransform->e11 + itransform->e13;
if ((uint32_t)sx >= image->w) continue; if ((uint32_t)sx >= image->w) continue;
auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale); auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2);
*tmp = ALPHA_BLEND(*tmp, A(src)); *tmp = ALPHA_BLEND(*tmp, A(src));
} }
} else { } else {
for (uint32_t i = 0; i < w; ++i, ++tmp) { for (uint32_t i = 0; i < w; ++i, ++tmp) {
auto sx = (x + i) * itransform->e11 + itransform->e13; auto sx = (x + i) * itransform->e11 + itransform->e13;
if ((uint32_t)sx >= image->w) continue; if ((uint32_t)sx >= image->w) continue;
auto src = ALPHA_BLEND(scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale), opacity); auto src = ALPHA_BLEND(scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2), opacity);
*tmp = ALPHA_BLEND(*tmp, A(src)); *tmp = ALPHA_BLEND(*tmp, A(src));
} }
} }
@ -1189,16 +1199,16 @@ static void _rasterScaledMaskedRGBAImageInt(SwSurface* surface, const SwImage* i
} }
static bool _rasterScaledMaskedRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t opacity, uint32_t halfScale) static bool _rasterScaledMaskedRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t opacity)
{ {
auto method = surface->compositor->method; auto method = surface->compositor->method;
TVGLOG("SW_ENGINE", "Scaled Masked(%d) Image [Region: %lu %lu %lu %lu]", (int)surface->compositor->method, region.min.x, region.min.y, region.max.x - region.min.x, region.max.y - region.min.y); TVGLOG("SW_ENGINE", "Scaled Masked(%d) Image [Region: %lu %lu %lu %lu]", (int)surface->compositor->method, region.min.x, region.min.y, region.max.x - region.min.x, region.max.y - region.min.y);
if (method == CompositeMethod::AddMask) _rasterScaledMaskedRGBAImageDup<AddMaskOp, AddMaskAOp>(surface, image, itransform, region, opacity, halfScale); if (method == CompositeMethod::AddMask) _rasterScaledMaskedRGBAImageDup<AddMaskOp, AddMaskAOp>(surface, image, itransform, region, opacity);
else if (method == CompositeMethod::SubtractMask) _rasterScaledMaskedRGBAImageDup<SubMaskOp, SubMaskAOp>(surface, image, itransform, region, opacity, halfScale); else if (method == CompositeMethod::SubtractMask) _rasterScaledMaskedRGBAImageDup<SubMaskOp, SubMaskAOp>(surface, image, itransform, region, opacity);
else if (method == CompositeMethod::DifferenceMask) _rasterScaledMaskedRGBAImageDup<DifMaskOp, DifMaskAOp>(surface, image, itransform, region, opacity, halfScale); else if (method == CompositeMethod::DifferenceMask) _rasterScaledMaskedRGBAImageDup<DifMaskOp, DifMaskAOp>(surface, image, itransform, region, opacity);
else if (method == CompositeMethod::IntersectMask) _rasterScaledMaskedRGBAImageInt(surface, image, itransform, region, opacity, halfScale); else if (method == CompositeMethod::IntersectMask) _rasterScaledMaskedRGBAImageInt(surface, image, itransform, region, opacity);
else return false; else return false;
//Masking Composition //Masking Composition
@ -1206,7 +1216,7 @@ static bool _rasterScaledMaskedRGBAImage(SwSurface* surface, const SwImage* imag
} }
static bool _rasterScaledMattedRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t opacity, uint32_t halfScale) static bool _rasterScaledMattedRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t opacity)
{ {
auto dbuffer = surface->buf32 + (region.min.y * surface->stride + region.min.x); auto dbuffer = surface->buf32 + (region.min.y * surface->stride + region.min.x);
auto csize = surface->compositor->image.channelSize; auto csize = surface->compositor->image.channelSize;
@ -1216,6 +1226,8 @@ static bool _rasterScaledMattedRGBAImage(SwSurface* surface, const SwImage* imag
TVGLOG("SW_ENGINE", "Scaled Matted(%d) Image [Region: %lu %lu %lu %lu]", (int)surface->compositor->method, region.min.x, region.min.y, region.max.x - region.min.x, region.max.y - region.min.y); TVGLOG("SW_ENGINE", "Scaled Matted(%d) Image [Region: %lu %lu %lu %lu]", (int)surface->compositor->method, region.min.x, region.min.y, region.max.x - region.min.x, region.max.y - region.min.y);
auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler;
auto sampleSize = _sampleSize(image->scale);
auto sampleSize2 = sampleSize * sampleSize;
for (auto y = region.min.y; y < region.max.y; ++y) { for (auto y = region.min.y; y < region.max.y; ++y) {
auto sy = y * itransform->e22 + itransform->e23; auto sy = y * itransform->e22 + itransform->e23;
@ -1226,7 +1238,7 @@ static bool _rasterScaledMattedRGBAImage(SwSurface* surface, const SwImage* imag
for (auto x = region.min.x; x < region.max.x; ++x, ++dst, cmp += csize) { for (auto x = region.min.x; x < region.max.x; ++x, ++dst, cmp += csize) {
auto sx = x * itransform->e11 + itransform->e13; auto sx = x * itransform->e11 + itransform->e13;
if ((uint32_t)sx >= image->w) continue; if ((uint32_t)sx >= image->w) continue;
auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale); auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2);
auto temp = ALPHA_BLEND(src, alpha(cmp)); auto temp = ALPHA_BLEND(src, alpha(cmp));
*dst = temp + ALPHA_BLEND(*dst, IA(temp)); *dst = temp + ALPHA_BLEND(*dst, IA(temp));
} }
@ -1234,7 +1246,7 @@ static bool _rasterScaledMattedRGBAImage(SwSurface* surface, const SwImage* imag
for (auto x = region.min.x; x < region.max.x; ++x, ++dst, cmp += csize) { for (auto x = region.min.x; x < region.max.x; ++x, ++dst, cmp += csize) {
auto sx = x * itransform->e11 + itransform->e13; auto sx = x * itransform->e11 + itransform->e13;
if ((uint32_t)sx >= image->w) continue; if ((uint32_t)sx >= image->w) continue;
auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale); auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2);
auto temp = ALPHA_BLEND(src, MULTIPLY(opacity, alpha(cmp))); auto temp = ALPHA_BLEND(src, MULTIPLY(opacity, alpha(cmp)));
*dst = temp + ALPHA_BLEND(*dst, IA(temp)); *dst = temp + ALPHA_BLEND(*dst, IA(temp));
} }
@ -1246,10 +1258,12 @@ static bool _rasterScaledMattedRGBAImage(SwSurface* surface, const SwImage* imag
} }
static bool _rasterScaledBlendingRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t opacity, uint32_t halfScale) static bool _rasterScaledBlendingRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t opacity)
{ {
auto dbuffer = surface->buf32 + (region.min.y * surface->stride + region.min.x); auto dbuffer = surface->buf32 + (region.min.y * surface->stride + region.min.x);
auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler;
auto sampleSize = _sampleSize(image->scale);
auto sampleSize2 = sampleSize * sampleSize;
for (auto y = region.min.y; y < region.max.y; ++y, dbuffer += surface->stride) { for (auto y = region.min.y; y < region.max.y; ++y, dbuffer += surface->stride) {
auto sy = y * itransform->e22 + itransform->e23; auto sy = y * itransform->e22 + itransform->e23;
@ -1259,7 +1273,7 @@ static bool _rasterScaledBlendingRGBAImage(SwSurface* surface, const SwImage* im
for (auto x = region.min.x; x < region.max.x; ++x, ++dst) { for (auto x = region.min.x; x < region.max.x; ++x, ++dst) {
auto sx = x * itransform->e11 + itransform->e13; auto sx = x * itransform->e11 + itransform->e13;
if ((uint32_t)sx >= image->w) continue; if ((uint32_t)sx >= image->w) continue;
auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale); auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2);
auto tmp = surface->blender(src, *dst, 255); auto tmp = surface->blender(src, *dst, 255);
*dst = INTERPOLATE(tmp, *dst, A(src)); *dst = INTERPOLATE(tmp, *dst, A(src));
} }
@ -1267,7 +1281,7 @@ static bool _rasterScaledBlendingRGBAImage(SwSurface* surface, const SwImage* im
for (auto x = region.min.x; x < region.max.x; ++x, ++dst) { for (auto x = region.min.x; x < region.max.x; ++x, ++dst) {
auto sx = x * itransform->e11 + itransform->e13; auto sx = x * itransform->e11 + itransform->e13;
if ((uint32_t)sx >= image->w) continue; if ((uint32_t)sx >= image->w) continue;
auto src = ALPHA_BLEND(scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale), opacity); auto src = ALPHA_BLEND(scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2), opacity);
auto tmp = surface->blender(src, *dst, 255); auto tmp = surface->blender(src, *dst, 255);
*dst = INTERPOLATE(tmp, *dst, A(src)); *dst = INTERPOLATE(tmp, *dst, A(src));
} }
@ -1277,10 +1291,12 @@ static bool _rasterScaledBlendingRGBAImage(SwSurface* surface, const SwImage* im
} }
static bool _rasterScaledRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t opacity, uint32_t halfScale) static bool _rasterScaledRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t opacity)
{ {
auto dbuffer = surface->buf32 + (region.min.y * surface->stride + region.min.x); auto dbuffer = surface->buf32 + (region.min.y * surface->stride + region.min.x);
auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler;
auto sampleSize = _sampleSize(image->scale);
auto sampleSize2 = sampleSize * sampleSize;
for (auto y = region.min.y; y < region.max.y; ++y, dbuffer += surface->stride) { for (auto y = region.min.y; y < region.max.y; ++y, dbuffer += surface->stride) {
auto sy = y * itransform->e22 + itransform->e23; auto sy = y * itransform->e22 + itransform->e23;
@ -1290,14 +1306,14 @@ static bool _rasterScaledRGBAImage(SwSurface* surface, const SwImage* image, con
for (auto x = region.min.x; x < region.max.x; ++x, ++dst) { for (auto x = region.min.x; x < region.max.x; ++x, ++dst) {
auto sx = x * itransform->e11 + itransform->e13; auto sx = x * itransform->e11 + itransform->e13;
if ((uint32_t)sx >= image->w) continue; if ((uint32_t)sx >= image->w) continue;
auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale); auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2);
*dst = src + ALPHA_BLEND(*dst, IA(src)); *dst = src + ALPHA_BLEND(*dst, IA(src));
} }
} else { } else {
for (auto x = region.min.x; x < region.max.x; ++x, ++dst) { for (auto x = region.min.x; x < region.max.x; ++x, ++dst) {
auto sx = x * itransform->e11 + itransform->e13; auto sx = x * itransform->e11 + itransform->e13;
if ((uint32_t)sx >= image->w) continue; if ((uint32_t)sx >= image->w) continue;
auto src = ALPHA_BLEND(scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale), opacity); auto src = ALPHA_BLEND(scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2), opacity);
*dst = src + ALPHA_BLEND(*dst, IA(src)); *dst = src + ALPHA_BLEND(*dst, IA(src));
} }
} }
@ -1314,15 +1330,13 @@ static bool _scaledRGBAImage(SwSurface* surface, const SwImage* image, const Mat
if (!mathInverse(transform, &itransform)) return false; if (!mathInverse(transform, &itransform)) return false;
} else mathIdentity(&itransform); } else mathIdentity(&itransform);
auto halfScale = _halfScale(image->scale);
if (_compositing(surface)) { if (_compositing(surface)) {
if (_matting(surface)) return _rasterScaledMattedRGBAImage(surface, image, &itransform, region, opacity, halfScale); if (_matting(surface)) return _rasterScaledMattedRGBAImage(surface, image, &itransform, region, opacity);
else return _rasterScaledMaskedRGBAImage(surface, image, &itransform, region, opacity, halfScale); else return _rasterScaledMaskedRGBAImage(surface, image, &itransform, region, opacity);
} else if (_blending(surface)) { } else if (_blending(surface)) {
return _rasterScaledBlendingRGBAImage(surface, image, &itransform, region, opacity, halfScale); return _rasterScaledBlendingRGBAImage(surface, image, &itransform, region, opacity);
} else { } else {
return _rasterScaledRGBAImage(surface, image, &itransform, region, opacity, halfScale); return _rasterScaledRGBAImage(surface, image, &itransform, region, opacity);
} }
return false; return false;
} }