From: Hermet Park Date: Fri, 19 Nov 2021 04:46:25 +0000 (+0900) Subject: sw_engine image: introduced scaled image raster logics. X-Git-Tag: accepted/tizen/unified/20211126.111840~17 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7c92d27cffdff6a295ddc0edd75e305bfef54375;p=platform%2Fcore%2Fgraphics%2Ftizenvg.git sw_engine image: introduced scaled image raster logics. These raster functions are accelerated only for the scaled images. (no rotation, skrewed) --- diff --git a/src/lib/sw_engine/tvgSwCommon.h b/src/lib/sw_engine/tvgSwCommon.h index e46eee7..ce69e37 100644 --- a/src/lib/sw_engine/tvgSwCommon.h +++ b/src/lib/sw_engine/tvgSwCommon.h @@ -229,6 +229,7 @@ struct SwImage float scale; bool direct = false; //draw image directly (with offset) + bool scaled = false; //draw scaled image }; struct SwBlender diff --git a/src/lib/sw_engine/tvgSwImage.cpp b/src/lib/sw_engine/tvgSwImage.cpp index 76631cc..8176d8c 100644 --- a/src/lib/sw_engine/tvgSwImage.cpp +++ b/src/lib/sw_engine/tvgSwImage.cpp @@ -91,6 +91,9 @@ bool imagePrepare(SwImage* image, const Matrix* transform, const SwBBox& clipReg auto scaleX = sqrtf((transform->e11 * transform->e11) + (transform->e21 * transform->e21)); auto scaleY = sqrtf((transform->e22 * transform->e22) + (transform->e12 * transform->e12)); image->scale = (fabsf(scaleX - scaleY) > 0.01f) ? 1.0f : scaleX; + + if (mathZero(transform->e12) && mathZero(transform->e21)) image->scaled = true; + else image->scaled = false; } if (!_genOutline(image, transform, mpool, tid)) return false; diff --git a/src/lib/sw_engine/tvgSwRaster.cpp b/src/lib/sw_engine/tvgSwRaster.cpp index efecb63..3c23117 100644 --- a/src/lib/sw_engine/tvgSwRaster.cpp +++ b/src/lib/sw_engine/tvgSwRaster.cpp @@ -71,20 +71,20 @@ static bool _translucent(const SwSurface* surface, uint8_t a) //Bilinear Interpolation -static uint32_t _interpUpScaler(const uint32_t *img, uint32_t w, uint32_t h, float fX, float fY) +static uint32_t _interpUpScaler(const uint32_t *img, uint32_t w, uint32_t h, float sx, float sy) { - auto rX = static_cast(fX); - auto rY = static_cast(fY); + auto rx = static_cast(sx); + auto ry = static_cast(sy); - auto dX = static_cast((fX - rX) * 255.0f); - auto dY = static_cast((fY - rY) * 255.0f); + auto dx = static_cast((sx - rx) * 255.0f); + auto dy = static_cast((sy - ry) * 255.0f); - auto c1 = img[rX + (rY * w)]; - auto c2 = img[(rX + 1) + (rY * w)]; - auto c3 = img[(rX + 1) + ((rY + 1) * w)]; - auto c4 = img[rX + ((rY + 1) * w)]; + auto c1 = img[rx + (ry * w)]; + auto c2 = img[(rx + 1) + (ry * w)]; + auto c3 = img[(rx + 1) + ((ry + 1) * w)]; + auto c4 = img[rx + ((ry + 1) * w)]; - return COLOR_INTERPOLATE(COLOR_INTERPOLATE(c1, 255 - dX, c2, dX), 255 - dY, COLOR_INTERPOLATE(c4, 255 - dX, c3, dX), dY); + return COLOR_INTERPOLATE(COLOR_INTERPOLATE(c1, 255 - dx, c2, dx), 255 - dy, COLOR_INTERPOLATE(c4, 255 - dx, c3, dx), dy); } @@ -884,7 +884,7 @@ static bool _rasterTransformedTranslucentImage(SwSurface* surface, const SwImage /************************************************************************/ -/* Whole Transformed Solid Image */ +/* Whole Transformed Solid Image */ /************************************************************************/ static bool _rasterTransformedSolidImage(SwSurface* surface, const SwImage* image, const SwBBox& region, const Matrix* itransform) @@ -967,10 +967,204 @@ static bool _rasterTransformedSolidImage(SwSurface* surface, const SwImage* imag /************************************************************************/ -/* Whole (Solid + Translucent) Direct Image */ +/* Whole Scaled RGBA Image */ /************************************************************************/ -static bool _rasterDirectMaskedImage(SwSurface* surface, const SwImage* image, uint32_t opacity, const SwBBox& region, uint32_t (*blendMethod)(uint32_t)) +static bool _rasterScaledMaskedRGBAImage(SwSurface* surface, const SwImage* image, uint32_t opacity, const SwBBox& region, const Matrix* itransform, uint32_t halfScale, uint32_t (*blendMethod)(uint32_t)) +{ + TVGLOG("SW_ENGINE", "Scaled Masked Image"); + + //Top, Bottom Lines + SwCoord ys[2] = {region.min.y, region.max.y - 1}; + + for (auto i = 0; i < 2; ++i) { + auto y = ys[i]; + auto dst = surface->buffer + (y * surface->stride + region.min.x); + auto cmp = surface->compositor->image.data + (y * surface->stride + region.min.x); + auto img = image->data + static_cast(y * itransform->e22 + itransform->e23) * image->stride; + for (auto x = region.min.x; x < region.max.x; ++x, ++dst, ++cmp) { + auto src = ALPHA_BLEND(img[static_cast(x * itransform->e11 + itransform->e13)], _multiplyAlpha(opacity, blendMethod(*cmp))); + *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src)); + } + } + //Left, Right Lines + SwCoord xs[2] = {region.min.x, region.max.x - 1}; + + for (auto i = 0; i < 2; ++i) { + auto x = xs[i]; + auto dst = surface->buffer + ((region.min.y + 1) * surface->stride + x); + auto cmp = surface->compositor->image.data + ((region.min.y + 1) * surface->stride + x); + auto img = image->data + static_cast(x * itransform->e11 + itransform->e13); + for (auto y = region.min.y + 1; y < region.max.y - 1; ++y, dst += surface->stride, cmp += surface->stride) { + auto src = ALPHA_BLEND(img[static_cast(y * itransform->e22 + itransform->e23) * image->stride], _multiplyAlpha(opacity, blendMethod(*cmp))); + *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src)); + } + } + //Center (Down-Scaled) + if (image->scale < DOWN_SCALE_TOLERANCE) { + auto dbuffer = surface->buffer + ((region.min.y + 1) * surface->stride + (region.min.x + 1)); + auto cbuffer = surface->compositor->image.data + ((region.min.y + 1) * surface->stride + (region.min.x + 1)); + for (auto y = region.min.y + 1; y < region.max.y - 1; ++y) { + auto dst = dbuffer; + auto cmp = cbuffer; + auto sy = static_cast(y * itransform->e22 + itransform->e23); + for (auto x = region.min.x + 1; x < region.max.x - 1; ++x, ++dst, ++cmp) { + auto sx = static_cast(x * itransform->e11 + itransform->e13); + auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->w, image->h, sx, sy, halfScale), _multiplyAlpha(opacity, blendMethod(*cmp))); + *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src)); + } + dbuffer += surface->stride; + cbuffer += surface->compositor->image.stride; + } + //Center (Up-Scaled) + } else { + 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 - 1; ++y) { + auto dst = dbuffer; + auto cmp = cbuffer; + auto sy = y * itransform->e22 + itransform->e23; + for (auto x = region.min.x; x < region.max.x - 1; ++x, ++dst, ++cmp) { + auto sx = x * itransform->e11 + itransform->e13; + auto src = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), _multiplyAlpha(opacity, blendMethod(*cmp))); + *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src)); + } + dbuffer += surface->stride; + cbuffer += surface->compositor->image.stride; + } + } + return true; +} + + +static bool __rasterScaledTranslucentRGBAImage(SwSurface* surface, const SwImage* image, uint32_t opacity, const SwBBox& region, const Matrix* itransform, uint32_t halfScale) +{ + //Top, Bottom Lines + SwCoord ys[2] = {region.min.y, region.max.y - 1}; + + for (auto i = 0; i < 2; ++i) { + auto y = ys[i]; + auto dst = surface->buffer + (y * surface->stride + region.min.x); + auto img = image->data + static_cast(y * itransform->e22 + itransform->e23) * image->stride; + for (auto x = region.min.x; x < region.max.x; ++x, ++dst) { + auto src = ALPHA_BLEND(img[static_cast(x * itransform->e11 + itransform->e13)], opacity); + *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src)); + } + } + //Left, Right Lines + SwCoord xs[2] = {region.min.x, region.max.x - 1}; + + for (auto i = 0; i < 2; ++i) { + auto x = xs[i]; + auto dst = surface->buffer + ((region.min.y + 1) * surface->stride + x); + auto img = image->data + static_cast(x * itransform->e11 + itransform->e13); + for (auto y = region.min.y + 1; y < region.max.y - 1; ++y, dst += surface->stride) { + auto src = ALPHA_BLEND(img[static_cast(y * itransform->e22 + itransform->e23) * image->stride], opacity); + *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src)); + } + } + //Center (Down-Scaled) + if (image->scale < DOWN_SCALE_TOLERANCE) { + auto dbuffer = surface->buffer + ((region.min.y + 1) * surface->stride + (region.min.x + 1)); + for (auto y = region.min.y + 1; y < region.max.y - 1; ++y, dbuffer += surface->stride) { + auto sy = static_cast(y * itransform->e22 + itransform->e23); + auto dst = dbuffer; + for (auto x = region.min.x + 1; x < region.max.x - 1; ++x, ++dst) { + auto sx = static_cast(x * itransform->e11 + itransform->e13); + auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->w, image->h, sx, sy, halfScale), opacity); + *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src)); + } + } + //Center (Up-Scaled) + } else { + auto dbuffer = surface->buffer + (region.min.y * surface->stride + region.min.x); + for (auto y = region.min.y; y < region.max.y - 1; ++y, dbuffer += surface->stride) { + auto sy = y * itransform->e22 + itransform->e23; + auto dst = dbuffer; + for (auto x = region.min.x; x < region.max.x - 1; ++x, ++dst) { + auto sx = x * itransform->e11 + itransform->e13; + auto src = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), opacity); + *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src)); + } + } + } + return true; +} + + +static bool _rasterScaledTranslucentRGBAImage(SwSurface* surface, const SwImage* image, uint32_t opacity, const SwBBox& region, const Matrix* itransform, uint32_t halfScale) +{ + if (surface->compositor) { + if (surface->compositor->method == CompositeMethod::AlphaMask) { + return _rasterScaledMaskedRGBAImage(surface, image, opacity, region, itransform, halfScale, surface->blender.alpha); + } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { + return _rasterScaledMaskedRGBAImage(surface, image, opacity, region, itransform, halfScale, surface->blender.ialpha); + } + } + return __rasterScaledTranslucentRGBAImage(surface, image, opacity, region, itransform, halfScale); +} + + +static bool _rasterScaledRGBAImage(SwSurface* surface, const SwImage* image, const SwBBox& region, const Matrix* itransform, uint32_t halfScale) +{ + //Top, Bottom Lines + SwCoord ys[2] = {region.min.y, region.max.y - 1}; + + for (auto i = 0; i < 2; ++i) { + auto y = ys[i]; + auto dst = surface->buffer + (y * surface->stride + region.min.x); + auto img = image->data + static_cast((y * itransform->e22 + itransform->e23)) * image->stride; + for (auto x = region.min.x; x < region.max.x; ++x, ++dst) { + auto src = img[static_cast(x * itransform->e11 + itransform->e13)]; + *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src)); + } + } + //Left, Right Lines + SwCoord xs[2] = {region.min.x, region.max.x - 1}; + + for (auto i = 0; i < 2; ++i) { + auto x = xs[i]; + auto dst = surface->buffer + ((region.min.y + 1) * surface->stride + x); + auto img = image->data + static_cast(x * itransform->e11 + itransform->e13); + for (auto y = region.min.y + 1; y < region.max.y - 1; ++y, dst += surface->stride) { + auto src = img[static_cast(y * itransform->e22 + itransform->e23) * image->stride]; + *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src)); + } + } + //Center (Down-Scaled) + if (image->scale < DOWN_SCALE_TOLERANCE) { + auto dbuffer = surface->buffer + ((region.min.y + 1) * surface->stride + (region.min.x + 1)); + for (auto y = region.min.y + 1; y < region.max.y - 1; ++y, dbuffer += surface->stride) { + auto sy = static_cast(y * itransform->e22 + itransform->e23); + auto dst = dbuffer; + for (auto x = region.min.x + 1; x < region.max.x - 1; ++x, ++dst) { + auto sx = static_cast(x * itransform->e11 + itransform->e13); + auto src = _interpDownScaler(image->data, image->w, image->h, sx, sy, halfScale); + *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src)); + } + } + //Center (Up-Scaled) + } else { + auto dbuffer = surface->buffer + (region.min.y * surface->stride + region.min.x); + for (auto y = region.min.y; y < region.max.y - 1; ++y, dbuffer += surface->stride) { + auto sy = y * itransform->e22 + itransform->e23; + auto dst = dbuffer; + for (auto x = region.min.x; x < region.max.x - 1; ++x, ++dst) { + auto sx = x * itransform->e11 + itransform->e13; + auto src = _interpUpScaler(image->data, image->w, image->h, sx, sy); + *dst = src + ALPHA_BLEND(*dst, surface->blender.ialpha(src)); + } + } + } + return true; +} + + +/************************************************************************/ +/* Whole Direct RGBA Image */ +/************************************************************************/ + +static bool _rasterDirectMaskedRGBAImage(SwSurface* surface, const SwImage* image, uint32_t opacity, const SwBBox& region, uint32_t (*blendMethod)(uint32_t)) { auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x; auto h2 = static_cast(region.max.y - region.min.y); @@ -997,7 +1191,7 @@ static bool _rasterDirectMaskedImage(SwSurface* surface, const SwImage* image, u } -static bool __rasterDirectTranslucentImage(SwSurface* surface, const SwImage* image, uint32_t opacity, const SwBBox& region) +static bool __rasterDirectTranslucentRGBAImage(SwSurface* surface, const SwImage* image, uint32_t opacity, const SwBBox& region) { auto dbuffer = &surface->buffer[region.min.y * surface->stride + region.min.x]; auto sbuffer = image->data + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox); @@ -1016,20 +1210,20 @@ static bool __rasterDirectTranslucentImage(SwSurface* surface, const SwImage* im } -static bool _rasterDirectTranslucentImage(SwSurface* surface, const SwImage* image, uint32_t opacity, const SwBBox& region) +static bool _rasterDirectTranslucentRGBAImage(SwSurface* surface, const SwImage* image, uint32_t opacity, const SwBBox& region) { if (surface->compositor) { if (surface->compositor->method == CompositeMethod::AlphaMask) { - return _rasterDirectMaskedImage(surface, image, opacity, region, surface->blender.alpha); + return _rasterDirectMaskedRGBAImage(surface, image, opacity, region, surface->blender.alpha); } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { - return _rasterDirectMaskedImage(surface, image, opacity, region, surface->blender.ialpha); + return _rasterDirectMaskedRGBAImage(surface, image, opacity, region, surface->blender.ialpha); } } - return __rasterDirectTranslucentImage(surface, image, opacity, region); + return __rasterDirectTranslucentRGBAImage(surface, image, opacity, region); } -static bool _rasterDirectSolidImage(SwSurface* surface, const SwImage* image, const SwBBox& region) +static bool _rasterDirectRGBAImage(SwSurface* surface, const SwImage* image, const SwBBox& region) { auto dbuffer = &surface->buffer[region.min.y * surface->stride + region.min.x]; auto sbuffer = image->data + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox); @@ -1038,7 +1232,7 @@ static bool _rasterDirectSolidImage(SwSurface* surface, const SwImage* image, co auto dst = dbuffer; auto src = sbuffer; for (auto x = region.min.x; x < region.max.x; x++, dst++, src++) { - *dst = *src; + *dst = *src + ALPHA_BLEND(*dst, surface->blender.ialpha(*src)); } dbuffer += surface->stride; sbuffer += image->stride; @@ -1579,15 +1773,24 @@ void rasterUnpremultiply(SwSurface* surface) } } - +/* FIXME: Current SolidImage assumes always be RGBA. + Applying Blenders for the following scenarios: + - [Whole / RLE] + - [Direct / Scaled / Transformed] + - [RGB / RGBA] + - [None / Opacity / Composition / Opacity + Composition] */ bool rasterImage(SwSurface* surface, SwImage* image, const Matrix* transform, const SwBBox& bbox, uint32_t opacity) { + //Boundary check + if (bbox.max.x < 0 || bbox.max.y < 0 || bbox.min.x >= surface->w || bbox.min.y >= surface->h) return false; + Matrix itransform; if (transform && !mathInverse(transform, &itransform)) return false; auto halfScale = static_cast(0.5f / image->scale); if (halfScale == 0) halfScale = 1; + //OPTIMIZE_ME: we can split the condition: Opacity & Composition! auto translucent = _translucent(surface, opacity); //Clipped Image @@ -1602,9 +1805,13 @@ bool rasterImage(SwSurface* surface, SwImage* image, const Matrix* transform, co //Whole Image } else { if (image->direct) { - if (translucent) return _rasterDirectTranslucentImage(surface, image, opacity, bbox); - else return _rasterDirectSolidImage(surface, image, bbox); + if (translucent) return _rasterDirectTranslucentRGBAImage(surface, image, opacity, bbox); + else return _rasterDirectRGBAImage(surface, image, bbox); + } else if (image->scaled) { + if (translucent) return _rasterScaledTranslucentRGBAImage(surface, image, opacity, bbox, &itransform, halfScale); + else return _rasterScaledRGBAImage(surface, image, bbox, &itransform, halfScale); } else { + //OPTIMIZE_ME: Replace with the TexMap Rasterizer if (translucent) return _rasterTransformedTranslucentImage(surface, image, opacity, bbox, &itransform, halfScale); else return _rasterTransformedSolidImage(surface, image, bbox, &itransform, halfScale); }