common paint: alpha masking optimization

applying fast track approach to the alpha mask when its condition is matched.
(simple rectangle alpha masking which isn't half-translucent)

From time to time, designers brutally use the alpha masking to clip simple region,
thorvg can help the situation by avoiding masking usage internally.

This can reduce the 1-step render pass composition.

@Issue: https://github.com/Samsung/thorvg/issues/344
This commit is contained in:
Hermet Park 2021-11-11 14:03:10 +09:00 committed by Hermet Park
parent 91668143e1
commit 44ccfc46d8
2 changed files with 23 additions and 8 deletions

View file

@ -34,7 +34,7 @@ static inline bool FLT_SAME(float a, float b)
} }
static bool _clipPathFastTrack(Paint* cmpTarget, const RenderTransform* pTransform, RenderTransform* rTransform, RenderRegion& viewport) static bool _compFastTrack(Paint* cmpTarget, const RenderTransform* pTransform, RenderTransform* rTransform, RenderRegion& viewport)
{ {
/* Access Shape class by Paint is bad... but it's ok still it's an internal usage. */ /* Access Shape class by Paint is bad... but it's ok still it's an internal usage. */
auto shape = static_cast<Shape*>(cmpTarget); auto shape = static_cast<Shape*>(cmpTarget);
@ -164,9 +164,11 @@ bool Paint::Impl::render(RenderMethod& renderer)
{ {
Compositor* cmp = nullptr; Compositor* cmp = nullptr;
//OPTIMIZE_ME: Can we replace the simple AlphaMasking with ClipPath?
/* Note: only ClipPath is processed in update() step. /* Note: only ClipPath is processed in update() step.
Create a composition image. */ Create a composition image. */
if (cmpTarget && cmpMethod != CompositeMethod::ClipPath) { if (cmpTarget && cmpMethod != CompositeMethod::ClipPath && !(cmpTarget->pImpl->ctxFlag & ContextFlag::FastTrack)) {
auto region = smethod->bounds(renderer); auto region = smethod->bounds(renderer);
if (region.w == 0 || region.h == 0) return false; if (region.w == 0 || region.h == 0) return false;
cmp = renderer.target(region); cmp = renderer.target(region);
@ -200,17 +202,27 @@ void* Paint::Impl::update(RenderMethod& renderer, const RenderTransform* pTransf
bool cmpFastTrack = false; bool cmpFastTrack = false;
if (cmpTarget) { if (cmpTarget) {
/* If transform has no rotation factors && ClipPath is a simple rectangle, /* If transform has no rotation factors && ClipPath / AlphaMasking is a simple rectangle,
we can avoid regular ClipPath sequence but use viewport for performance */ we can avoid regular ClipPath / AlphaMasking sequence but use viewport for performance */
if (cmpMethod == CompositeMethod::ClipPath) { auto tryFastTrack = false;
if (cmpMethod == CompositeMethod::ClipPath) tryFastTrack = true;
else if (cmpMethod == CompositeMethod::AlphaMask) {
auto shape = static_cast<Shape*>(cmpTarget);
uint8_t a;
shape->fillColor(nullptr, nullptr, nullptr, &a);
if (a == 255 && shape->opacity() == 255 && !shape->fill()) tryFastTrack = true;
}
if (tryFastTrack) {
RenderRegion viewport2; RenderRegion viewport2;
if ((cmpFastTrack = _clipPathFastTrack(cmpTarget, pTransform, cmpTarget->pImpl->rTransform, viewport2))) { if ((cmpFastTrack = _compFastTrack(cmpTarget, pTransform, cmpTarget->pImpl->rTransform, viewport2))) {
viewport = renderer.viewport(); viewport = renderer.viewport();
viewport2.intersect(viewport); viewport2.intersect(viewport);
renderer.viewport(viewport2); renderer.viewport(viewport2);
cmpTarget->pImpl->ctxFlag |= ContextFlag::FastTrack;
} else {
cmpTarget->pImpl->ctxFlag &= ~ContextFlag::FastTrack;
} }
} }
if (!cmpFastTrack) { if (!cmpFastTrack) {
cmpData = cmpTarget->pImpl->update(renderer, pTransform, 255, clips, pFlag); cmpData = cmpTarget->pImpl->update(renderer, pTransform, 255, clips, pFlag);
if (cmpMethod == CompositeMethod::ClipPath) clips.push(cmpData); if (cmpMethod == CompositeMethod::ClipPath) clips.push(cmpData);

View file

@ -27,6 +27,8 @@
namespace tvg namespace tvg
{ {
enum ContextFlag {Invalid = 0, FastTrack = 1};
struct Iterator struct Iterator
{ {
virtual ~Iterator() {} virtual ~Iterator() {}
@ -51,10 +53,11 @@ namespace tvg
struct Paint::Impl struct Paint::Impl
{ {
StrategyMethod* smethod = nullptr; StrategyMethod* smethod = nullptr;
RenderTransform *rTransform = nullptr; RenderTransform* rTransform = nullptr;
uint32_t renderFlag = RenderUpdateFlag::None; uint32_t renderFlag = RenderUpdateFlag::None;
Paint* cmpTarget = nullptr; Paint* cmpTarget = nullptr;
CompositeMethod cmpMethod = CompositeMethod::None; CompositeMethod cmpMethod = CompositeMethod::None;
uint32_t ctxFlag = ContextFlag::Invalid;
uint8_t opacity = 255; uint8_t opacity = 255;
~Impl() { ~Impl() {