Merge "Keep the SkPaint used when creating a layer."
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index e50ef6f..4742f91 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -456,8 +456,7 @@
             }
 
             SaveLayerOp* op = new (handler.allocator()) SaveLayerOp(
-                    0, 0, mRight - mLeft, mBottom - mTop,
-                    mAlpha * 255, SkXfermode::kSrcOver_Mode, saveFlags);
+                    0, 0, mRight - mLeft, mBottom - mTop, mAlpha * 255, saveFlags);
             handler(op, PROPERTY_SAVECOUNT, mClipToBounds);
         }
     }
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index dec796a..d4f82ea 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -327,9 +327,13 @@
 
 class SaveLayerOp : public StateOp {
 public:
-    SaveLayerOp(float left, float top, float right, float bottom,
-            int alpha, SkXfermode::Mode mode, int flags)
-            : mArea(left, top, right, bottom), mAlpha(alpha), mMode(mode), mFlags(flags) {}
+    SaveLayerOp(float left, float top, float right, float bottom, int alpha, int flags)
+            : mArea(left, top, right, bottom), mPaint(&mCachedPaint), mFlags(flags) {
+        mCachedPaint.setAlpha(alpha);
+    }
+
+    SaveLayerOp(float left, float top, float right, float bottom, const SkPaint* paint, int flags)
+            : mArea(left, top, right, bottom), mPaint(paint), mFlags(flags) {}
 
     virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
             bool useQuickReject) {
@@ -340,11 +344,11 @@
         // NOTE: don't issue full saveLayer, since that has side effects/is costly. instead just
         // setup the snapshot for deferral, and re-issue the op at flush time
         deferStruct.mRenderer.saveLayerDeferred(mArea.left, mArea.top, mArea.right, mArea.bottom,
-                mAlpha, mMode, mFlags);
+                mPaint, mFlags);
     }
 
     virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
-        renderer.saveLayer(mArea.left, mArea.top, mArea.right, mArea.bottom, mAlpha, mMode, mFlags);
+        renderer.saveLayer(mArea.left, mArea.top, mArea.right, mArea.bottom, mPaint, mFlags);
     }
 
     virtual void output(int level, uint32_t logFlags) const {
@@ -357,21 +361,15 @@
     int getFlags() { return mFlags; }
 
 private:
-    // Special case, reserved for direct DisplayList usage
-    SaveLayerOp() {}
-    DisplayListOp* reinit(float left, float top, float right, float bottom,
-            int alpha, SkXfermode::Mode mode, int flags) {
-        mArea.set(left, top, right, bottom);
-        mAlpha = alpha;
-        mMode = mode;
-        mFlags = flags;
-        return this;
+    bool isSaveLayerAlpha() const {
+        SkXfermode::Mode mode = OpenGLRenderer::getXfermodeDirect(mPaint);
+        int alpha = OpenGLRenderer::getAlphaDirect(mPaint);
+        return alpha < 255 && mode == SkXfermode::kSrcOver_Mode;
     }
 
-    bool isSaveLayerAlpha() const { return mAlpha < 255 && mMode == SkXfermode::kSrcOver_Mode; }
     Rect mArea;
-    int mAlpha;
-    SkXfermode::Mode mMode;
+    const SkPaint* mPaint;
+    SkPaint mCachedPaint;
     int mFlags;
 };
 
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index f7d7b3d..7c85297 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -174,8 +174,9 @@
 }
 
 int DisplayListRenderer::saveLayer(float left, float top, float right, float bottom,
-        int alpha, SkXfermode::Mode mode, int flags) {
-    addStateOp(new (alloc()) SaveLayerOp(left, top, right, bottom, alpha, mode, flags));
+        const SkPaint* paint, int flags) {
+    paint = refPaint(paint);
+    addStateOp(new (alloc()) SaveLayerOp(left, top, right, bottom, paint, flags));
     return StatefulBaseRenderer::save(flags);
 }
 
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index f129c10..3c14212 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -82,7 +82,7 @@
     virtual void restore();
     virtual void restoreToCount(int saveCount);
     virtual int saveLayer(float left, float top, float right, float bottom,
-            int alpha, SkXfermode::Mode mode, int flags);
+            const SkPaint* paint, int flags);
 
     // Matrix
     virtual void translate(float dx, float dy, float dz);
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index b710825..4b947a6 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -731,11 +731,11 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 int OpenGLRenderer::saveLayer(float left, float top, float right, float bottom,
-        int alpha, SkXfermode::Mode mode, int flags) {
+        const SkPaint* paint, int flags) {
     const int count = saveSnapshot(flags);
 
     if (!currentSnapshot()->isIgnored()) {
-        createLayer(left, top, right, bottom, alpha, mode, flags);
+        createLayer(left, top, right, bottom, paint, flags);
     }
 
     return count;
@@ -786,7 +786,7 @@
 }
 
 int OpenGLRenderer::saveLayerDeferred(float left, float top, float right, float bottom,
-        int alpha, SkXfermode::Mode mode, int flags) {
+        const SkPaint* paint, int flags) {
     const int count = saveSnapshot(flags);
 
     if (!currentSnapshot()->isIgnored() && (flags & SkCanvas::kClipToLayer_SaveFlag)) {
@@ -797,7 +797,7 @@
         Rect bounds(left, top, right, bottom);
         Rect clip;
         calculateLayerBoundsAndClip(bounds, clip, true);
-        updateSnapshotIgnoreForLayer(bounds, clip, true, alpha);
+        updateSnapshotIgnoreForLayer(bounds, clip, true, getAlphaDirect(paint));
 
         if (!currentSnapshot()->isIgnored()) {
             mSnapshot->resetTransform(-bounds.left, -bounds.top, 0.0f);
@@ -862,12 +862,15 @@
  *     something actually gets drawn are the layers regions cleared.
  */
 bool OpenGLRenderer::createLayer(float left, float top, float right, float bottom,
-        int alpha, SkXfermode::Mode mode, int flags) {
+        const SkPaint* paint, int flags) {
     LAYER_LOGD("Requesting layer %.2fx%.2f", right - left, bottom - top);
     LAYER_LOGD("Layer cache size = %d", mCaches.layerCache.getSize());
 
     const bool fboLayer = flags & SkCanvas::kClipToLayer_SaveFlag;
 
+    SkXfermode::Mode mode = getXfermodeDirect(paint);
+    int alpha = getAlphaDirect(paint);
+
     // Window coordinates of the layer
     Rect clip;
     Rect bounds(left, top, right, bottom);
@@ -889,6 +892,7 @@
     layer->layer.set(bounds);
     layer->texCoords.set(0.0f, bounds.getHeight() / float(layer->getHeight()),
             bounds.getWidth() / float(layer->getWidth()), 0.0f);
+
     layer->setColorFilter(mDrawModifiers.mColorFilter);
     layer->setBlend(true);
     layer->setDirty(false);
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index c8ecdda..131681e 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -154,21 +154,11 @@
     ANDROID_API void clearLayerUpdates();
     ANDROID_API void flushLayerUpdates();
 
-    ANDROID_API int saveLayer(float left, float top, float right, float bottom,
-            SkPaint* paint, int flags) {
-        SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode;
-        if (paint) mode = getXfermode(paint->getXfermode());
-        return saveLayer(left, top, right, bottom, paint ? paint->getAlpha() : 255, mode, flags);
-    }
-    ANDROID_API int saveLayerAlpha(float left, float top, float right, float bottom,
-            int alpha, int flags) {
-        return saveLayer(left, top, right, bottom, alpha, SkXfermode::kSrcOver_Mode, flags);
-    }
-    virtual int saveLayer(float left, float top, float right, float bottom,
-            int alpha, SkXfermode::Mode mode, int flags);
+    ANDROID_API virtual int saveLayer(float left, float top, float right, float bottom,
+            const SkPaint* paint, int flags);
 
     int saveLayerDeferred(float left, float top, float right, float bottom,
-            int alpha, SkXfermode::Mode mode, int flags);
+            const SkPaint* paint, int flags);
 
     virtual status_t drawDisplayList(DisplayList* displayList, Rect& dirty, int32_t replayFlags = 1);
     virtual status_t drawLayer(Layer* layer, float x, float y);
@@ -538,7 +528,7 @@
      * @return True if the layer was successfully created, false otherwise
      */
     bool createLayer(float left, float top, float right, float bottom,
-            int alpha, SkXfermode::Mode mode, int flags);
+            const SkPaint* paint, int flags);
 
     /**
      * Creates a new layer stored in the specified snapshot as an FBO.
diff --git a/libs/hwui/Renderer.h b/libs/hwui/Renderer.h
index 4799b32..058548a 100644
--- a/libs/hwui/Renderer.h
+++ b/libs/hwui/Renderer.h
@@ -146,22 +146,15 @@
     virtual void restore() = 0;
     virtual void restoreToCount(int saveCount) = 0;
 
-    int saveLayer(float left, float top, float right, float bottom,
-            const SkPaint* paint, int flags) {
-        SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode;
-        int alpha = 255;
-        if (paint) {
-            mode = getXfermode(paint->getXfermode());
-            alpha = paint->getAlpha();
-        }
-        return saveLayer(left, top, right, bottom, alpha, mode, flags);
-    }
+    virtual int saveLayer(float left, float top, float right, float bottom,
+            const SkPaint* paint, int flags) = 0;
+
     int saveLayerAlpha(float left, float top, float right, float bottom,
             int alpha, int flags) {
-        return saveLayer(left, top, right, bottom, alpha, SkXfermode::kSrcOver_Mode, flags);
+        SkPaint paint;
+        paint.setAlpha(alpha);
+        return saveLayer(left, top, right, bottom, &paint, flags);
     }
-    virtual int saveLayer(float left, float top, float right, float bottom,
-            int alpha, SkXfermode::Mode mode, int flags) = 0;
 
     // Matrix
     virtual void getMatrix(SkMatrix* outMatrix) const = 0;