mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-12 15:34:22 +00:00
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:
parent
74b27c74af
commit
b5bc73849c
1 changed files with 48 additions and 21 deletions
|
@ -333,8 +333,8 @@ static bool _rasterTranslucentImageRle(SwSurface* surface, const SwRleData* rle,
|
||||||
for (uint32_t i = 0; i < rle->size; ++i, ++span) {
|
for (uint32_t i = 0; i < rle->size; ++i, ++span) {
|
||||||
auto dst = &surface->buffer[span->y * surface->stride + span->x];
|
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 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) {
|
for (uint32_t x = 0; x < span->len; ++x, ++dst, ++src) {
|
||||||
auto alpha = ALPHA_MULTIPLY(span->coverage, opacity);
|
|
||||||
*src = ALPHA_BLEND(*src, alpha);
|
*src = ALPHA_BLEND(*src, alpha);
|
||||||
*dst = *src + ALPHA_BLEND(*dst, 255 - surface->blender.alpha(*src));
|
*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;
|
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 ey1 = span->y * invTransform->e12 + invTransform->e13;
|
||||||
auto ey2 = span->y * invTransform->e22 + invTransform->e23;
|
auto ey2 = span->y * invTransform->e22 + invTransform->e23;
|
||||||
auto dst = &surface->buffer[span->y * surface->stride + span->x];
|
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) {
|
for (uint32_t x = 0; x < span->len; ++x, ++dst) {
|
||||||
auto rX = static_cast<uint32_t>(roundf((span->x + x) * invTransform->e11 + ey1));
|
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));
|
auto rY = static_cast<uint32_t>(roundf((span->x + x) * invTransform->e21 + ey2));
|
||||||
if (rX >= w || rY >= h) continue;
|
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
|
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));
|
*dst = src + ALPHA_BLEND(*dst, 255 - surface->blender.alpha(src));
|
||||||
}
|
}
|
||||||
++span;
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -385,7 +384,7 @@ static bool _rasterImageRle(SwSurface* surface, SwRleData* rle, uint32_t *img, u
|
||||||
{
|
{
|
||||||
auto span = rle->spans;
|
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 ey1 = span->y * invTransform->e12 + invTransform->e13;
|
||||||
auto ey2 = span->y * invTransform->e22 + invTransform->e23;
|
auto ey2 = span->y * invTransform->e22 + invTransform->e23;
|
||||||
auto dst = &surface->buffer[span->y * surface->stride + span->x];
|
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
|
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));
|
*dst = src + ALPHA_BLEND(*dst, 255 - surface->blender.alpha(src));
|
||||||
}
|
}
|
||||||
++span;
|
|
||||||
}
|
}
|
||||||
return true;
|
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)
|
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) {
|
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 ey1 = y * invTransform->e12 + invTransform->e13;
|
||||||
auto ey2 = y * invTransform->e22 + invTransform->e23;
|
auto ey2 = y * invTransform->e22 + invTransform->e23;
|
||||||
for (auto x = region.min.x; x < region.max.x; ++x, ++dst) {
|
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
|
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));
|
*dst = src + ALPHA_BLEND(*dst, 255 - surface->blender.alpha(src));
|
||||||
}
|
}
|
||||||
|
dbuffer += surface->stride;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -425,9 +426,12 @@ static bool _translucentImageAlphaMask(SwSurface* surface, const uint32_t *img,
|
||||||
#ifdef THORVG_LOG_ENABLED
|
#ifdef THORVG_LOG_ENABLED
|
||||||
cout <<"SW_ENGINE: Transformed Image Alpha Mask Composition" << endl;
|
cout <<"SW_ENGINE: Transformed Image Alpha Mask Composition" << endl;
|
||||||
#endif
|
#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) {
|
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 cmp = &surface->compositor->image.data[y * surface->stride + region.min.x];
|
auto cmp = cbuffer;
|
||||||
float ey1 = y * invTransform->e12 + invTransform->e13;
|
float ey1 = y * invTransform->e12 + invTransform->e13;
|
||||||
float ey2 = y * invTransform->e22 + invTransform->e23;
|
float ey2 = y * invTransform->e22 + invTransform->e23;
|
||||||
for (auto x = region.min.x; x < region.max.x; ++x, ++dst, ++cmp) {
|
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
|
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));
|
*dst = tmp + ALPHA_BLEND(*dst, 255 - surface->blender.alpha(tmp));
|
||||||
}
|
}
|
||||||
|
dbuffer += surface->stride;
|
||||||
|
cbuffer += surface->stride;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -446,9 +452,12 @@ static bool _translucentImageInvAlphaMask(SwSurface* surface, const uint32_t *im
|
||||||
#ifdef THORVG_LOG_ENABLED
|
#ifdef THORVG_LOG_ENABLED
|
||||||
cout <<"SW_ENGINE: Transformed Image Inverse Alpha Mask Composition" << endl;
|
cout <<"SW_ENGINE: Transformed Image Inverse Alpha Mask Composition" << endl;
|
||||||
#endif
|
#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) {
|
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 cmp = &surface->compositor->image.data[y * surface->stride + region.min.x];
|
auto cmp = cbuffer;
|
||||||
float ey1 = y * invTransform->e12 + invTransform->e13;
|
float ey1 = y * invTransform->e12 + invTransform->e13;
|
||||||
float ey2 = y * invTransform->e22 + invTransform->e23;
|
float ey2 = y * invTransform->e22 + invTransform->e23;
|
||||||
for (auto x = region.min.x; x < region.max.x; ++x, ++dst, ++cmp) {
|
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
|
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));
|
*dst = tmp + ALPHA_BLEND(*dst, 255 - surface->blender.alpha(tmp));
|
||||||
}
|
}
|
||||||
|
dbuffer += surface->stride;
|
||||||
|
cbuffer += surface->stride;
|
||||||
}
|
}
|
||||||
return true;
|
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)
|
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) {
|
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 src = img + region.min.x + (y * w); //TODO: need to use image's stride
|
auto src = sbuffer;
|
||||||
for (auto x = region.min.x; x < region.max.x; ++x, ++dst, ++src) {
|
for (auto x = region.min.x; x < region.max.x; ++x, ++dst, ++src) {
|
||||||
auto p = ALPHA_BLEND(*src, opacity);
|
auto p = ALPHA_BLEND(*src, opacity);
|
||||||
*dst = p + ALPHA_BLEND(*dst, 255 - surface->blender.alpha(p));
|
*dst = p + ALPHA_BLEND(*dst, 255 - surface->blender.alpha(p));
|
||||||
}
|
}
|
||||||
|
dbuffer += surface->stride;
|
||||||
|
sbuffer += w; //TODO: need to use image's stride
|
||||||
}
|
}
|
||||||
return true;
|
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
|
auto cbuffer = surface->compositor->image.data + (region.min.y * surface->stride) + region.min.x; //compositor buffer
|
||||||
|
|
||||||
for (uint32_t y = 0; y < h2; ++y) {
|
for (uint32_t y = 0; y < h2; ++y) {
|
||||||
auto dst = &buffer[y * surface->stride];
|
auto dst = buffer;
|
||||||
auto cmp = &cbuffer[y * surface->stride];
|
auto cmp = cbuffer;
|
||||||
auto src = &sbuffer[y * w]; //TODO: need to use image's stride
|
auto src = sbuffer;
|
||||||
for (uint32_t x = 0; x < w2; ++x, ++dst, ++src, ++cmp) {
|
for (uint32_t x = 0; x < w2; ++x, ++dst, ++src, ++cmp) {
|
||||||
auto tmp = ALPHA_BLEND(*src, ALPHA_MULTIPLY(opacity, surface->blender.alpha(*cmp)));
|
auto tmp = ALPHA_BLEND(*src, ALPHA_MULTIPLY(opacity, surface->blender.alpha(*cmp)));
|
||||||
*dst = tmp + ALPHA_BLEND(*dst, 255 - surface->blender.alpha(tmp));
|
*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;
|
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
|
auto cbuffer = surface->compositor->image.data + (region.min.y * surface->stride) + region.min.x; //compositor buffer
|
||||||
|
|
||||||
for (uint32_t y = 0; y < h2; ++y) {
|
for (uint32_t y = 0; y < h2; ++y) {
|
||||||
auto dst = &buffer[y * surface->stride];
|
auto dst = buffer;
|
||||||
auto cmp = &cbuffer[y * surface->stride];
|
auto cmp = cbuffer;
|
||||||
auto src = &sbuffer[y * w]; //TODO: need to use image's stride
|
auto src = sbuffer;
|
||||||
for (uint32_t x = 0; x < w2; ++x, ++dst, ++src, ++cmp) {
|
for (uint32_t x = 0; x < w2; ++x, ++dst, ++src, ++cmp) {
|
||||||
auto ialpha = 255 - surface->blender.alpha(*cmp);
|
auto ialpha = 255 - surface->blender.alpha(*cmp);
|
||||||
auto tmp = ALPHA_BLEND(*src, ALPHA_MULTIPLY(opacity, ialpha));
|
auto tmp = ALPHA_BLEND(*src, ALPHA_MULTIPLY(opacity, ialpha));
|
||||||
*dst = tmp + ALPHA_BLEND(*dst, 255 - surface->blender.alpha(tmp));
|
*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;
|
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)
|
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) {
|
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 src = img + region.min.x + (y * w); //TODO: need to use image's stride
|
auto src = sbuffer;
|
||||||
for (auto x = region.min.x; x < region.max.x; x++, dst++, src++) {
|
for (auto x = region.min.x; x < region.max.x; x++, dst++, src++) {
|
||||||
*dst = *src + ALPHA_BLEND(*dst, 255 - surface->blender.alpha(*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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue