OSDN Git Service

Fix alpha fading in System UI
authorStan Iliev <stani@google.com>
Wed, 20 Sep 2017 22:05:35 +0000 (18:05 -0400)
committerStan Iliev <stani@google.com>
Thu, 21 Sep 2017 21:14:10 +0000 (17:14 -0400)
Fix alpha not being applied for Views that have non overlapping
rendering (getHasOverlappingRendering is false).

Test: Ran system UI
Bug: 65857651
Change-Id: I31001de0f67bf95ab8425189a4b78427d062585d

libs/hwui/pipeline/skia/RenderNodeDrawable.cpp

index 4ee47af..47dee9d 100644 (file)
@@ -19,6 +19,7 @@
 #include "SkiaDisplayList.h"
 #include "SkiaPipeline.h"
 #include "utils/TraceUtils.h"
+#include <SkPaintFilterCanvas.h>
 
 namespace android {
 namespace uirenderer {
@@ -151,6 +152,27 @@ static bool layerNeedsPaint(const LayerProperties& properties,
     return false;
 }
 
+class AlphaFilterCanvas : public SkPaintFilterCanvas {
+public:
+    AlphaFilterCanvas(SkCanvas* canvas, float alpha) : SkPaintFilterCanvas(canvas), mAlpha(alpha) {}
+protected:
+    bool onFilter(SkTCopyOnFirstWrite<SkPaint>* paint, Type t) const override {
+        SkTLazy<SkPaint> defaultPaint;
+        if (!*paint) {
+            paint->init(*defaultPaint.init());
+        }
+        paint->writable()->setAlpha((uint8_t)(*paint)->getAlpha()*mAlpha);
+        return true;
+    }
+    void onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) override {
+        // We unroll the drawable using "this" canvas, so that draw calls contained inside will
+        // get their alpha applied. THe default SkPaintFilterCanvas::onDrawDrawable does not unroll.
+        drawable->draw(this, matrix);
+    }
+private:
+    float mAlpha;
+};
+
 void RenderNodeDrawable::drawContent(SkCanvas* canvas) const {
     RenderNode* renderNode = mRenderNode.get();
     float alphaMultiplier = 1.0f;
@@ -211,7 +233,14 @@ void RenderNodeDrawable::drawContent(SkCanvas* canvas) const {
                 canvas->restore();
             }
         } else {
-            displayList->draw(canvas);
+            if (alphaMultiplier < 1.0f) {
+                // Non-layer draw for a view with getHasOverlappingRendering=false, will apply
+                // the alpha to the paint of each nested draw.
+                AlphaFilterCanvas alphaCanvas(canvas, alphaMultiplier);
+                displayList->draw(&alphaCanvas);
+            } else {
+                displayList->draw(canvas);
+            }
         }
     }
 }