sw_engine raster: functions optimization in the image block

The alpha value calculation pulled out outside the inner loop
to reduce the number of unnecessary operations.
Added local variables to reduce the number of costly
multiplications performed in a loop.
This commit is contained in:
Mira Grudzinska 2021-02-22 22:18:34 +01:00 committed by Hermet Park
parent 74b27c74af
commit b5bc73849c

View file

@ -333,8 +333,8 @@ static bool _rasterTranslucentImageRle(SwSurface* surface, const SwRleData* rle,
for (uint32_t i = 0; i < rle->size; ++i, ++span) {
auto dst = &surface->buffer[span->y * surface->stride + span->x];
auto src = img + span->x + span->y * w; //TODO: need to use image's stride
auto alpha = ALPHA_MULTIPLY(span->coverage, opacity);
for (uint32_t x = 0; x < span->len; ++x, ++dst, ++src) {
auto alpha = ALPHA_MULTIPLY(span->coverage, opacity);
*src = ALPHA_BLEND(*src, alpha);
*dst = *src + ALPHA_BLEND(*dst, 255 - surface->blender.alpha(*src));
}
@ -347,19 +347,18 @@ static bool _rasterTranslucentImageRle(SwSurface* surface, const SwRleData* rle,
{
auto span = rle->spans;
for (uint32_t i = 0; i < rle->size; ++i) {
for (uint32_t i = 0; i < rle->size; ++i, ++span) {
auto ey1 = span->y * invTransform->e12 + invTransform->e13;
auto ey2 = span->y * invTransform->e22 + invTransform->e23;
auto dst = &surface->buffer[span->y * surface->stride + span->x];
auto alpha = ALPHA_MULTIPLY(span->coverage, opacity);
for (uint32_t x = 0; x < span->len; ++x, ++dst) {
auto rX = static_cast<uint32_t>(roundf((span->x + x) * invTransform->e11 + ey1));
auto rY = static_cast<uint32_t>(roundf((span->x + x) * invTransform->e21 + ey2));
if (rX >= w || rY >= h) continue;
auto alpha = ALPHA_MULTIPLY(span->coverage, opacity);
auto src = ALPHA_BLEND(img[rY * w + rX], alpha); //TODO: need to use image's stride
*dst = src + ALPHA_BLEND(*dst, 255 - surface->blender.alpha(src));
}
++span;
}
return true;
}
@ -385,7 +384,7 @@ static bool _rasterImageRle(SwSurface* surface, SwRleData* rle, uint32_t *img, u
{
auto span = rle->spans;
for (uint32_t i = 0; i < rle->size; ++i) {
for (uint32_t i = 0; i < rle->size; ++i, ++span) {
auto ey1 = span->y * invTransform->e12 + invTransform->e13;
auto ey2 = span->y * invTransform->e22 + invTransform->e23;
auto dst = &surface->buffer[span->y * surface->stride + span->x];
@ -396,7 +395,6 @@ static bool _rasterImageRle(SwSurface* surface, SwRleData* rle, uint32_t *img, u
auto src = ALPHA_BLEND(img[rY * w + rX], span->coverage); //TODO: need to use image's stride
*dst = src + ALPHA_BLEND(*dst, 255 - surface->blender.alpha(src));
}
++span;
}
return true;
}
@ -404,8 +402,10 @@ static bool _rasterImageRle(SwSurface* surface, SwRleData* rle, uint32_t *img, u
static bool _translucentImage(SwSurface* surface, const uint32_t *img, uint32_t w, TVG_UNUSED uint32_t h, uint32_t opacity, const SwBBox& region, const Matrix* invTransform)
{
auto dbuffer = &surface->buffer[region.min.y * surface->stride + region.min.x];
for (auto y = region.min.y; y < region.max.y; ++y) {
auto dst = &surface->buffer[y * surface->stride + region.min.x];
auto dst = dbuffer;
auto ey1 = y * invTransform->e12 + invTransform->e13;
auto ey2 = y * invTransform->e22 + invTransform->e23;
for (auto x = region.min.x; x < region.max.x; ++x, ++dst) {
@ -415,6 +415,7 @@ static bool _translucentImage(SwSurface* surface, const uint32_t *img, uint32_t
auto src = ALPHA_BLEND(img[rX + (rY * w)], opacity); //TODO: need to use image's stride
*dst = src + ALPHA_BLEND(*dst, 255 - surface->blender.alpha(src));
}
dbuffer += surface->stride;
}
return true;
}
@ -425,9 +426,12 @@ static bool _translucentImageAlphaMask(SwSurface* surface, const uint32_t *img,
#ifdef THORVG_LOG_ENABLED
cout <<"SW_ENGINE: Transformed Image Alpha Mask Composition" << endl;
#endif
auto dbuffer = &surface->buffer[region.min.y * surface->stride + region.min.x];
auto cbuffer = &surface->compositor->image.data[region.min.y * surface->stride + region.min.x];
for (auto y = region.min.y; y < region.max.y; ++y) {
auto dst = &surface->buffer[y * surface->stride + region.min.x];
auto cmp = &surface->compositor->image.data[y * surface->stride + region.min.x];
auto dst = dbuffer;
auto cmp = cbuffer;
float ey1 = y * invTransform->e12 + invTransform->e13;
float ey2 = y * invTransform->e22 + invTransform->e23;
for (auto x = region.min.x; x < region.max.x; ++x, ++dst, ++cmp) {
@ -437,6 +441,8 @@ static bool _translucentImageAlphaMask(SwSurface* surface, const uint32_t *img,
auto tmp = ALPHA_BLEND(img[rX + (rY * w)], ALPHA_MULTIPLY(opacity, surface->blender.alpha(*cmp))); //TODO: need to use image's stride
*dst = tmp + ALPHA_BLEND(*dst, 255 - surface->blender.alpha(tmp));
}
dbuffer += surface->stride;
cbuffer += surface->stride;
}
return true;
}
@ -446,9 +452,12 @@ static bool _translucentImageInvAlphaMask(SwSurface* surface, const uint32_t *im
#ifdef THORVG_LOG_ENABLED
cout <<"SW_ENGINE: Transformed Image Inverse Alpha Mask Composition" << endl;
#endif
auto dbuffer = &surface->buffer[region.min.y * surface->stride + region.min.x];
auto cbuffer = &surface->compositor->image.data[region.min.y * surface->stride + region.min.x];
for (auto y = region.min.y; y < region.max.y; ++y) {
auto dst = &surface->buffer[y * surface->stride + region.min.x];
auto cmp = &surface->compositor->image.data[y * surface->stride + region.min.x];
auto dst = dbuffer;
auto cmp = cbuffer;
float ey1 = y * invTransform->e12 + invTransform->e13;
float ey2 = y * invTransform->e22 + invTransform->e23;
for (auto x = region.min.x; x < region.max.x; ++x, ++dst, ++cmp) {
@ -459,6 +468,8 @@ static bool _translucentImageInvAlphaMask(SwSurface* surface, const uint32_t *im
auto tmp = ALPHA_BLEND(img[rX + (rY * w)], ALPHA_MULTIPLY(opacity, ialpha)); //TODO: need to use image's stride
*dst = tmp + ALPHA_BLEND(*dst, 255 - surface->blender.alpha(tmp));
}
dbuffer += surface->stride;
cbuffer += surface->stride;
}
return true;
}
@ -479,13 +490,18 @@ static bool _rasterTranslucentImage(SwSurface* surface, const uint32_t *img, uin
static bool _translucentImage(SwSurface* surface, uint32_t *img, uint32_t w, uint32_t h, uint32_t opacity, const SwBBox& region)
{
auto dbuffer = &surface->buffer[region.min.y * surface->stride + region.min.x];
auto sbuffer = img + region.min.x + region.min.y * w; //TODO: need to use image's stride
for (auto y = region.min.y; y < region.max.y; ++y) {
auto dst = &surface->buffer[y * surface->stride + region.min.x];
auto src = img + region.min.x + (y * w); //TODO: need to use image's stride
auto dst = dbuffer;
auto src = sbuffer;
for (auto x = region.min.x; x < region.max.x; ++x, ++dst, ++src) {
auto p = ALPHA_BLEND(*src, opacity);
*dst = p + ALPHA_BLEND(*dst, 255 - surface->blender.alpha(p));
}
dbuffer += surface->stride;
sbuffer += w; //TODO: need to use image's stride
}
return true;
}
@ -505,13 +521,16 @@ static bool _translucentImageAlphaMask(SwSurface* surface, uint32_t *img, uint32
auto cbuffer = surface->compositor->image.data + (region.min.y * surface->stride) + region.min.x; //compositor buffer
for (uint32_t y = 0; y < h2; ++y) {
auto dst = &buffer[y * surface->stride];
auto cmp = &cbuffer[y * surface->stride];
auto src = &sbuffer[y * w]; //TODO: need to use image's stride
auto dst = buffer;
auto cmp = cbuffer;
auto src = sbuffer;
for (uint32_t x = 0; x < w2; ++x, ++dst, ++src, ++cmp) {
auto tmp = ALPHA_BLEND(*src, ALPHA_MULTIPLY(opacity, surface->blender.alpha(*cmp)));
*dst = tmp + ALPHA_BLEND(*dst, 255 - surface->blender.alpha(tmp));
}
buffer += surface->stride;
cbuffer += surface->stride;
sbuffer += w; //TODO: need to use image's stride
}
return true;
}
@ -531,14 +550,17 @@ static bool _translucentImageInvAlphaMask(SwSurface* surface, uint32_t *img, uin
auto cbuffer = surface->compositor->image.data + (region.min.y * surface->stride) + region.min.x; //compositor buffer
for (uint32_t y = 0; y < h2; ++y) {
auto dst = &buffer[y * surface->stride];
auto cmp = &cbuffer[y * surface->stride];
auto src = &sbuffer[y * w]; //TODO: need to use image's stride
auto dst = buffer;
auto cmp = cbuffer;
auto src = sbuffer;
for (uint32_t x = 0; x < w2; ++x, ++dst, ++src, ++cmp) {
auto ialpha = 255 - surface->blender.alpha(*cmp);
auto tmp = ALPHA_BLEND(*src, ALPHA_MULTIPLY(opacity, ialpha));
*dst = tmp + ALPHA_BLEND(*dst, 255 - surface->blender.alpha(tmp));
}
buffer += surface->stride;
cbuffer += surface->stride;
sbuffer += w; //TODO: need to use image's stride
}
return true;
}
@ -559,12 +581,17 @@ static bool _rasterTranslucentImage(SwSurface* surface, uint32_t *img, uint32_t
static bool _rasterImage(SwSurface* surface, uint32_t *img, uint32_t w, TVG_UNUSED uint32_t h, const SwBBox& region)
{
auto dbuffer = &surface->buffer[region.min.y * surface->stride + region.min.x];
auto sbuffer = img + region.min.x + region.min.y * w; //TODO: need to use image's stride
for (auto y = region.min.y; y < region.max.y; ++y) {
auto dst = &surface->buffer[y * surface->stride + region.min.x];
auto src = img + region.min.x + (y * w); //TODO: need to use image's stride
auto dst = dbuffer;
auto src = sbuffer;
for (auto x = region.min.x; x < region.max.x; x++, dst++, src++) {
*dst = *src + ALPHA_BLEND(*dst, 255 - surface->blender.alpha(*src));
}
dbuffer += surface->stride;
sbuffer += w; //TODO: need to use image's stride
}
return true;
}