common paint: alpha masking optimization
authorHermet Park <chuneon.park@samsung.com>
Thu, 11 Nov 2021 05:03:10 +0000 (14:03 +0900)
committerJunsuChoi <jsuya.choi@samsung.com>
Fri, 12 Nov 2021 01:46:50 +0000 (10:46 +0900)
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

src/lib/tvgPaint.cpp
src/lib/tvgPaint.h

index 18f261f..a8f6e5e 100644 (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. */
     auto shape = static_cast<Shape*>(cmpTarget);
@@ -164,9 +164,11 @@ bool Paint::Impl::render(RenderMethod& renderer)
 {
     Compositor* cmp = nullptr;
 
+    //OPTIMIZE_ME: Can we replace the simple AlphaMasking with ClipPath?
+
     /* Note: only ClipPath is processed in update() step.
         Create a composition image. */
-    if (cmpTarget && cmpMethod != CompositeMethod::ClipPath) {
+    if (cmpTarget && cmpMethod != CompositeMethod::ClipPath && !(cmpTarget->pImpl->ctxFlag & ContextFlag::FastTrack)) {
         auto region = smethod->bounds(renderer);
         if (region.w == 0 || region.h == 0) return false;
         cmp = renderer.target(region);
@@ -200,17 +202,27 @@ void* Paint::Impl::update(RenderMethod& renderer, const RenderTransform* pTransf
     bool cmpFastTrack = false;
 
     if (cmpTarget) {
-        /* If transform has no rotation factors && ClipPath is a simple rectangle,
-           we can avoid regular ClipPath sequence but use viewport for performance */
-        if (cmpMethod == CompositeMethod::ClipPath) {
+        /* If transform has no rotation factors && ClipPath / AlphaMasking is a simple rectangle,
+           we can avoid regular ClipPath / AlphaMasking sequence but use viewport for performance */
+        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;
-            if ((cmpFastTrack = _clipPathFastTrack(cmpTarget, pTransform, cmpTarget->pImpl->rTransform, viewport2))) {
+            if ((cmpFastTrack = _compFastTrack(cmpTarget, pTransform, cmpTarget->pImpl->rTransform, viewport2))) {
                 viewport = renderer.viewport();
                 viewport2.intersect(viewport);
                 renderer.viewport(viewport2);
+                cmpTarget->pImpl->ctxFlag |= ContextFlag::FastTrack;
+            } else {
+                cmpTarget->pImpl->ctxFlag &= ~ContextFlag::FastTrack;
             }
         }
-
         if (!cmpFastTrack) {
             cmpData = cmpTarget->pImpl->update(renderer, pTransform, 255, clips, pFlag);
             if (cmpMethod == CompositeMethod::ClipPath) clips.push(cmpData);
index f2b681a..5b9e0db 100644 (file)
@@ -27,6 +27,8 @@
 
 namespace tvg
 {
+    enum ContextFlag {Invalid = 0, FastTrack = 1};
+
     struct Iterator
     {
         virtual ~Iterator() {}
@@ -51,10 +53,11 @@ namespace tvg
     struct Paint::Impl
     {
         StrategyMethod* smethod = nullptr;
-        RenderTransform *rTransform = nullptr;
+        RenderTransformrTransform = nullptr;
         uint32_t renderFlag = RenderUpdateFlag::None;
         Paint* cmpTarget = nullptr;
         CompositeMethod cmpMethod = CompositeMethod::None;
+        uint32_t ctxFlag = ContextFlag::Invalid;
         uint8_t opacity = 255;
 
         ~Impl() {