Merge "Use snapshot alpha for layers" into jb-mr2-dev
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 10c92ba..3a23aa1 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -869,7 +869,8 @@
 
 static void android_view_GLES20Canvas_drawLayer(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, Layer* layer, jfloat x, jfloat y, SkPaint* paint) {
-    renderer->drawLayer(layer, x, y, paint);
+    // TODO: don't pass the paint from java
+    renderer->drawLayer(layer, x, y);
 }
 
 static jboolean android_view_GLES20Canvas_copyLayer(JNIEnv* env, jobject clazz,
diff --git a/libs/hwui/DeferredDisplayList.cpp b/libs/hwui/DeferredDisplayList.cpp
index 5c5bf45..1ace42f 100644
--- a/libs/hwui/DeferredDisplayList.cpp
+++ b/libs/hwui/DeferredDisplayList.cpp
@@ -80,7 +80,7 @@
 #if DEBUG_DISPLAY_LIST_OPS_AS_EVENTS
             renderer.eventMark(strlen(op->name()), op->name());
 #endif
-            status |= op->applyDraw(renderer, dirty, 0, op->state.mMultipliedAlpha);
+            status |= op->applyDraw(renderer, dirty, 0);
             logBuffer.writeCommand(0, op->name());
         }
         return status;
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index 4944fe8..257c875 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -233,7 +233,6 @@
     mBottom = 0;
     mClipChildren = true;
     mAlpha = 1;
-    mMultipliedAlpha = 255;
     mHasOverlappingRendering = true;
     mTranslationX = 0;
     mTranslationY = 0;
@@ -362,7 +361,7 @@
             }
             ALOGD("%*sSaveLayerAlpha %.2f, %.2f, %.2f, %.2f, %d, 0x%x", level * 2, "",
                     (float) 0, (float) 0, (float) mRight - mLeft, (float) mBottom - mTop,
-                    mMultipliedAlpha, flags);
+                    (int)(mAlpha * 255), flags);
         }
     }
     if (mClipChildren && !mCaching) {
@@ -400,9 +399,9 @@
             renderer.concatMatrix(mTransformMatrix);
         }
     }
-    if (mAlpha < 1 && !mCaching) {
-        if (!mHasOverlappingRendering) {
-            renderer.setAlpha(mAlpha);
+    if (mAlpha < 1) {
+        if (mCaching || !mHasOverlappingRendering) {
+            renderer.scaleAlpha(mAlpha);
         } else {
             // TODO: should be able to store the size of a DL at record time and not
             // have to pass it into this call. In fact, this information might be in the
@@ -412,7 +411,7 @@
                 saveFlags |= SkCanvas::kClipToLayer_SaveFlag;
             }
             handler(mSaveLayerOp->reinit(0, 0, mRight - mLeft, mBottom - mTop,
-                    mMultipliedAlpha, SkXfermode::kSrcOver_Mode, saveFlags), PROPERTY_SAVECOUNT);
+                    mAlpha * 255, SkXfermode::kSrcOver_Mode, saveFlags), PROPERTY_SAVECOUNT);
         }
     }
     if (mClipChildren && !mCaching) {
@@ -423,40 +422,38 @@
 
 class DeferOperationHandler {
 public:
-    DeferOperationHandler(DeferStateStruct& deferStruct, int multipliedAlpha, int level)
-        : mDeferStruct(deferStruct), mMultipliedAlpha(multipliedAlpha), mLevel(level) {}
+    DeferOperationHandler(DeferStateStruct& deferStruct, int level)
+        : mDeferStruct(deferStruct), mLevel(level) {}
     inline void operator()(DisplayListOp* operation, int saveCount) {
-        operation->defer(mDeferStruct, saveCount, mLevel, mMultipliedAlpha);
+        operation->defer(mDeferStruct, saveCount, mLevel);
     }
 private:
     DeferStateStruct& mDeferStruct;
-    const int mMultipliedAlpha;
     const int mLevel;
 };
 
 void DisplayList::defer(DeferStateStruct& deferStruct, const int level) {
-    DeferOperationHandler handler(deferStruct, mCaching ? mMultipliedAlpha : -1, level);
+    DeferOperationHandler handler(deferStruct, level);
     iterate<DeferOperationHandler>(deferStruct.mRenderer, handler, level);
 }
 
 class ReplayOperationHandler {
 public:
-    ReplayOperationHandler(ReplayStateStruct& replayStruct, int multipliedAlpha, int level)
-        : mReplayStruct(replayStruct), mMultipliedAlpha(multipliedAlpha), mLevel(level) {}
+    ReplayOperationHandler(ReplayStateStruct& replayStruct, int level)
+        : mReplayStruct(replayStruct), mLevel(level) {}
     inline void operator()(DisplayListOp* operation, int saveCount) {
 #if DEBUG_DISPLAY_LIST_OPS_AS_EVENTS
         replayStruct.mRenderer.eventMark(operation->name());
 #endif
-        operation->replay(mReplayStruct, saveCount, mLevel, mMultipliedAlpha);
+        operation->replay(mReplayStruct, saveCount, mLevel);
     }
 private:
     ReplayStateStruct& mReplayStruct;
-    const int mMultipliedAlpha;
     const int mLevel;
 };
 
 void DisplayList::replay(ReplayStateStruct& replayStruct, const int level) {
-    ReplayOperationHandler handler(replayStruct, mCaching ? mMultipliedAlpha : -1, level);
+    ReplayOperationHandler handler(replayStruct, level);
 
     replayStruct.mRenderer.startMark(mName.string());
     iterate<ReplayOperationHandler>(replayStruct.mRenderer, handler, level);
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index 5392587..84f20ab 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -164,7 +164,6 @@
         alpha = fminf(1.0f, fmaxf(0.0f, alpha));
         if (alpha != mAlpha) {
             mAlpha = alpha;
-            mMultipliedAlpha = (int) (255 * alpha);
         }
     }
 
@@ -501,7 +500,6 @@
     // View properties
     bool mClipChildren;
     float mAlpha;
-    int mMultipliedAlpha;
     bool mHasOverlappingRendering;
     float mTranslationX, mTranslationY;
     float mRotation, mRotationX, mRotationY;
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 9988bb8..4561c61 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -78,11 +78,9 @@
         kOpLogFlag_JSON = 0x2 // TODO: add?
     };
 
-    virtual void defer(DeferStateStruct& deferStruct, int saveCount,
-            int level, int multipliedAlpha) = 0;
+    virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level) = 0;
 
-    virtual void replay(ReplayStateStruct& replayStruct, int saveCount,
-            int level, int multipliedAlpha) = 0;
+    virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level) = 0;
 
     virtual void output(int level, uint32_t logFlags = 0) = 0;
 
@@ -106,8 +104,7 @@
 
     virtual ~StateOp() {}
 
-    virtual void defer(DeferStateStruct& deferStruct, int saveCount,
-            int level, int multipliedAlpha) {
+    virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level) {
         // default behavior only affects immediate, deferrable state, issue directly to renderer
         applyState(deferStruct.mRenderer, saveCount);
     }
@@ -116,8 +113,7 @@
      * State operations are applied directly to the renderer, but can cause the deferred drawing op
      * list to flush
      */
-    virtual void replay(ReplayStateStruct& replayStruct, int saveCount,
-            int level, int multipliedAlpha) {
+    virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level) {
         applyState(replayStruct.mRenderer, saveCount);
     }
 
@@ -129,14 +125,12 @@
     DrawOp(SkPaint* paint)
             : mPaint(paint), mQuickRejected(false) {}
 
-    virtual void defer(DeferStateStruct& deferStruct, int saveCount,
-            int level, int multipliedAlpha) {
+    virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level) {
         if (mQuickRejected &&
                 CC_LIKELY(deferStruct.mReplayFlags & DisplayList::kReplayFlag_ClipChildren)) {
             return;
         }
 
-        state.mMultipliedAlpha = multipliedAlpha;
         if (!getLocalBounds(state.mBounds)) {
             // empty bounds signify bounds can't be calculated
             state.mBounds.setEmpty();
@@ -145,19 +139,16 @@
         deferStruct.mDeferredList.addDrawOp(deferStruct.mRenderer, this);
     }
 
-    virtual void replay(ReplayStateStruct& replayStruct, int saveCount,
-            int level, int multipliedAlpha) {
+    virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level) {
         if (mQuickRejected &&
                 CC_LIKELY(replayStruct.mReplayFlags & DisplayList::kReplayFlag_ClipChildren)) {
             return;
         }
 
-        replayStruct.mDrawGlStatus |= applyDraw(replayStruct.mRenderer, replayStruct.mDirty,
-                level, multipliedAlpha);
+        replayStruct.mDrawGlStatus |= applyDraw(replayStruct.mRenderer, replayStruct.mDirty, level);
     }
 
-    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
-            int multipliedAlpha) = 0;
+    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) = 0;
 
     virtual void onDrawOpDeferred(OpenGLRenderer& renderer) {
     }
@@ -177,8 +168,8 @@
     float strokeWidthOutset() { return mPaint->getStrokeWidth() * 0.5f; }
 
 protected:
-    SkPaint* getPaint(OpenGLRenderer& renderer, bool alwaysCopy = false) {
-        return renderer.filterPaint(mPaint, alwaysCopy);
+    SkPaint* getPaint(OpenGLRenderer& renderer) {
+        return renderer.filterPaint(mPaint);
     }
 
     SkPaint* mPaint; // should be accessed via getPaint() when applying
@@ -227,8 +218,7 @@
     SaveOp(int flags)
             : mFlags(flags) {}
 
-    virtual void defer(DeferStateStruct& deferStruct, int saveCount,
-            int level, int multipliedAlpha) {
+    virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level) {
         int newSaveCount = deferStruct.mRenderer.save(mFlags);
         deferStruct.mDeferredList.addSave(deferStruct.mRenderer, this, newSaveCount);
     }
@@ -260,8 +250,7 @@
     RestoreToCountOp(int count)
             : mCount(count) {}
 
-    virtual void defer(DeferStateStruct& deferStruct, int saveCount,
-            int level, int multipliedAlpha) {
+    virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level) {
         deferStruct.mDeferredList.addRestoreToCount(deferStruct.mRenderer, saveCount + mCount);
         deferStruct.mRenderer.restoreToCount(saveCount + mCount);
     }
@@ -293,8 +282,7 @@
             int alpha, SkXfermode::Mode mode, int flags)
             : mArea(left, top, right, bottom), mAlpha(alpha), mMode(mode), mFlags(flags) {}
 
-    virtual void defer(DeferStateStruct& deferStruct, int saveCount,
-            int level, int multipliedAlpha) {
+    virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level) {
         // NOTE: don't bother with actual saveLayer, instead issuing it at flush time
         int newSaveCount = deferStruct.mRenderer.save(mFlags);
         deferStruct.mDeferredList.addSaveLayer(deferStruct.mRenderer, this, newSaveCount);
@@ -453,8 +441,7 @@
 public:
     ClipOp(SkRegion::Op op) : mOp(op) {}
 
-    virtual void defer(DeferStateStruct& deferStruct, int saveCount,
-            int level, int multipliedAlpha) {
+    virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level) {
         // NOTE: must defer op BEFORE applying state, since it may read clip
         deferStruct.mDeferredList.addClip(deferStruct.mRenderer, this);
 
@@ -689,16 +676,9 @@
                     paint),
             mBitmap(bitmap) {}
 
-    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
-            int multipliedAlpha) {
-        bool makeCopy = multipliedAlpha >= 0 && multipliedAlpha < 255;
-        SkPaint* paint = getPaint(renderer, makeCopy);
-        if (makeCopy) {
-            // The paint is safe to modify since we're working on a copy
-            paint->setAlpha(multipliedAlpha);
-        }
-        status_t ret = renderer.drawBitmap(mBitmap, mLocalBounds.left, mLocalBounds.top, paint);
-        return ret;
+    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) {
+        return renderer.drawBitmap(mBitmap, mLocalBounds.left, mLocalBounds.top,
+                getPaint(renderer));
     }
 
     virtual void output(int level, uint32_t logFlags) {
@@ -723,8 +703,7 @@
         transform.mapRect(mLocalBounds);
     }
 
-    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
-            int multipliedAlpha) {
+    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) {
         return renderer.drawBitmap(mBitmap, mMatrix, getPaint(renderer));
     }
 
@@ -749,8 +728,7 @@
             : DrawBoundedOp(dstLeft, dstTop, dstRight, dstBottom, paint),
             mBitmap(bitmap), mSrc(srcLeft, srcTop, srcRight, srcBottom) {}
 
-    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
-            int multipliedAlpha) {
+    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) {
         return renderer.drawBitmap(mBitmap, mSrc.left, mSrc.top, mSrc.right, mSrc.bottom,
                 mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom,
                 getPaint(renderer));
@@ -776,8 +754,7 @@
     DrawBitmapDataOp(SkBitmap* bitmap, float left, float top, SkPaint* paint)
             : DrawBitmapOp(bitmap, left, top, paint) {}
 
-    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
-            int multipliedAlpha) {
+    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) {
         return renderer.drawBitmapData(mBitmap, mLocalBounds.left,
                 mLocalBounds.top, getPaint(renderer));
     }
@@ -800,8 +777,7 @@
             mBitmap(bitmap), mMeshWidth(meshWidth), mMeshHeight(meshHeight),
             mVertices(vertices), mColors(colors) {}
 
-    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
-            int multipliedAlpha) {
+    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) {
         return renderer.drawBitmapMesh(mBitmap, mMeshWidth, mMeshHeight,
                 mVertices, mColors, getPaint(renderer));
     }
@@ -834,8 +810,7 @@
             mColors(colors), mxDivsCount(width), myDivsCount(height),
             mNumColors(numColors), mAlpha(alpha), mMode(mode) {};
 
-    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
-            int multipliedAlpha) {
+    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) {
         // NOTE: not calling the virtual method, which takes a paint
         return renderer.drawPatch(mBitmap, mxDivs, myDivs, mColors,
                 mxDivsCount, myDivsCount, mNumColors,
@@ -869,8 +844,7 @@
     DrawColorOp(int color, SkXfermode::Mode mode)
             : DrawOp(0), mColor(color), mMode(mode) {};
 
-    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
-            int multipliedAlpha) {
+    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) {
         return renderer.drawColor(mColor, mMode);
     }
 
@@ -913,8 +887,7 @@
     DrawRectOp(float left, float top, float right, float bottom, SkPaint* paint)
             : DrawStrokableOp(left, top, right, bottom, paint) {}
 
-    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
-            int multipliedAlpha) {
+    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) {
         return renderer.drawRect(mLocalBounds.left, mLocalBounds.top,
                 mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer));
     }
@@ -932,8 +905,7 @@
             : DrawBoundedOp(rects, count, paint),
             mRects(rects), mCount(count) {}
 
-    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
-            int multipliedAlpha) {
+    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) {
         return renderer.drawRects(mRects, mCount, getPaint(renderer));
     }
 
@@ -958,8 +930,7 @@
             float rx, float ry, SkPaint* paint)
             : DrawStrokableOp(left, top, right, bottom, paint), mRx(rx), mRy(ry) {}
 
-    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
-            int multipliedAlpha) {
+    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) {
         return renderer.drawRoundRect(mLocalBounds.left, mLocalBounds.top,
                 mLocalBounds.right, mLocalBounds.bottom, mRx, mRy, getPaint(renderer));
     }
@@ -981,8 +952,7 @@
             : DrawStrokableOp(x - radius, y - radius, x + radius, y + radius, paint),
             mX(x), mY(y), mRadius(radius) {}
 
-    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
-            int multipliedAlpha) {
+    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) {
         return renderer.drawCircle(mX, mY, mRadius, getPaint(renderer));
     }
 
@@ -1003,8 +973,7 @@
     DrawOvalOp(float left, float top, float right, float bottom, SkPaint* paint)
             : DrawStrokableOp(left, top, right, bottom, paint) {}
 
-    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
-            int multipliedAlpha) {
+    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) {
         return renderer.drawOval(mLocalBounds.left, mLocalBounds.top,
                 mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer));
     }
@@ -1023,8 +992,7 @@
             : DrawStrokableOp(left, top, right, bottom, paint),
             mStartAngle(startAngle), mSweepAngle(sweepAngle), mUseCenter(useCenter) {}
 
-    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
-            int multipliedAlpha) {
+    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) {
         return renderer.drawArc(mLocalBounds.left, mLocalBounds.top,
                 mLocalBounds.right, mLocalBounds.bottom,
                 mStartAngle, mSweepAngle, mUseCenter, getPaint(renderer));
@@ -1055,8 +1023,7 @@
         mLocalBounds.set(left, top, left + width, top + height);
     }
 
-    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
-            int multipliedAlpha) {
+    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) {
         return renderer.drawPath(mPath, getPaint(renderer));
     }
 
@@ -1086,8 +1053,7 @@
         mLocalBounds.outset(strokeWidthOutset());
     }
 
-    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
-            int multipliedAlpha) {
+    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) {
         return renderer.drawLines(mPoints, mCount, getPaint(renderer));
     }
 
@@ -1113,8 +1079,7 @@
     DrawPointsOp(float* points, int count, SkPaint* paint)
             : DrawLinesOp(points, count, paint) {}
 
-    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
-            int multipliedAlpha) {
+    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) {
         return renderer.drawPoints(mPoints, mCount, getPaint(renderer));
     }
 
@@ -1160,8 +1125,7 @@
         /* TODO: inherit from DrawBounded and init mLocalBounds */
     }
 
-    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
-            int multipliedAlpha) {
+    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) {
         return renderer.drawTextOnPath(mText, mBytesCount, mCount, mPath,
                 mHOffset, mVOffset, getPaint(renderer));
     }
@@ -1182,8 +1146,7 @@
         /* TODO: inherit from DrawBounded and init mLocalBounds */
     }
 
-    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
-            int multipliedAlpha) {
+    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) {
         return renderer.drawPosText(mText, mBytesCount, mCount, mPositions, getPaint(renderer));
     }
 
@@ -1231,8 +1194,7 @@
         }
     }
 
-    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
-            int multipliedAlpha) {
+    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) {
         return renderer.drawText(mText, mBytesCount, mCount, mX, mY,
                 mPositions, getPaint(renderer), mLength);
     }
@@ -1269,8 +1231,7 @@
     DrawFunctorOp(Functor* functor)
             : DrawOp(0), mFunctor(functor) {}
 
-    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
-            int multipliedAlpha) {
+    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) {
         renderer.startMark("GL functor");
         status_t ret = renderer.callDrawGLFunction(mFunctor, dirty);
         renderer.endMark();
@@ -1293,22 +1254,21 @@
             : DrawBoundedOp(0, 0, displayList->getWidth(), displayList->getHeight(), 0),
             mDisplayList(displayList), mFlags(flags) {}
 
-    virtual void defer(DeferStateStruct& deferStruct, int saveCount,
-            int level, int multipliedAlpha) {
+    virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level) {
         if (mDisplayList && mDisplayList->isRenderable()) {
             mDisplayList->defer(deferStruct, level + 1);
         }
     }
-
-    virtual void replay(ReplayStateStruct& replayStruct, int saveCount,
-            int level, int multipliedAlpha) {
+virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level) {
         if (mDisplayList && mDisplayList->isRenderable()) {
             mDisplayList->replay(replayStruct, level + 1);
         }
     }
 
-    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
-            int multipliedAlpha) { return DrawGlInfo::kStatusDone; }
+    // NOT USED since replay() is overridden
+    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) {
+        return DrawGlInfo::kStatusDone;
+    }
 
     virtual void output(int level, uint32_t logFlags) {
         OP_LOG("Draw Display List %p, flags %#x", mDisplayList, mFlags);
@@ -1326,22 +1286,11 @@
 
 class DrawLayerOp : public DrawOp {
 public:
-    DrawLayerOp(Layer* layer, float x, float y, SkPaint* paint)
-            : DrawOp(paint), mLayer(layer), mX(x), mY(y) {}
+    DrawLayerOp(Layer* layer, float x, float y)
+            : DrawOp(0), mLayer(layer), mX(x), mY(y) {}
 
-    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
-            int multipliedAlpha) {
-        int oldAlpha = -1;
-
-        if (multipliedAlpha >= 0 && multipliedAlpha < 255) {
-            oldAlpha = mLayer->getAlpha();
-            mLayer->setAlpha(multipliedAlpha);
-        }
-        status_t ret = renderer.drawLayer(mLayer, mX, mY, getPaint(renderer));
-        if (oldAlpha >= 0) {
-            mLayer->setAlpha(oldAlpha);
-        }
-        return ret;
+    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level) {
+        return renderer.drawLayer(mLayer, mX, mY);
     }
 
     virtual void output(int level, uint32_t logFlags) {
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 8b5b54c..07daa3b 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -247,12 +247,11 @@
     return DrawGlInfo::kStatusDone;
 }
 
-status_t DisplayListRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* paint) {
+status_t DisplayListRenderer::drawLayer(Layer* layer, float x, float y) {
     mLayers.add(layer);
     mCaches.resourceCache.incrementRefcount(layer);
-    paint = refPaint(paint);
 
-    addDrawOp(new (alloc()) DrawLayerOp(layer, x, y, paint));
+    addDrawOp(new (alloc()) DrawLayerOp(layer, x, y));
     return DrawGlInfo::kStatusDone;
 }
 
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 73b9b66..50e552f 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -94,7 +94,7 @@
     virtual bool clipRegion(SkRegion* region, SkRegion::Op op);
 
     virtual status_t drawDisplayList(DisplayList* displayList, Rect& dirty, int32_t flags);
-    virtual status_t drawLayer(Layer* layer, float x, float y, SkPaint* paint);
+    virtual status_t drawLayer(Layer* layer, float x, float y);
     virtual status_t drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
     virtual status_t drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
     virtual status_t drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index e31f6f6..8030d66 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -2827,7 +2827,7 @@
     return DrawGlInfo::kStatusDrew;
 }
 
-status_t OpenGLRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* paint) {
+status_t OpenGLRenderer::drawLayer(Layer* layer, float x, float y) {
     if (!layer) {
         return DrawGlInfo::kStatusDone;
     }
@@ -2865,7 +2865,7 @@
         if (layer->region.isRect()) {
             composeLayerRect(layer, layer->regionRect);
         } else if (layer->mesh) {
-            const float a = layer->getAlpha() / 255.0f;
+            const float a = layer->getAlpha() / 255.0f * mSnapshot->alpha;
             setupDraw();
             setupDrawWithTexture();
             setupDrawColor(a, a, a, a);
@@ -2972,12 +2972,8 @@
     mDrawModifiers.mPaintFilterSetBits = setBits & SkPaint::kAllFlags;
 }
 
-SkPaint* OpenGLRenderer::filterPaint(SkPaint* paint, bool alwaysCopy) {
+SkPaint* OpenGLRenderer::filterPaint(SkPaint* paint) {
     if (CC_LIKELY(!mDrawModifiers.mHasDrawFilter || !paint)) {
-        if (CC_UNLIKELY(alwaysCopy)) {
-            mFilteredPaint = *paint;
-            return &mFilteredPaint;
-        }
         return paint;
     }
 
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 3aa9975..fc7c597 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -72,7 +72,6 @@
 
 struct DeferredDisplayState {
     Rect mBounds; // local bounds, mapped with matrix to be in screen space coordinates, clipped.
-    int mMultipliedAlpha; // -1 if invalid (because caching not set)
 
     // the below are set and used by the OpenGLRenderer at record and deferred playback
     Rect mClip;
@@ -226,7 +225,7 @@
 
     virtual status_t drawDisplayList(DisplayList* displayList, Rect& dirty, int32_t replayFlags);
     virtual void outputDisplayList(DisplayList* displayList);
-    virtual status_t drawLayer(Layer* layer, float x, float y, SkPaint* paint);
+    virtual status_t drawLayer(Layer* layer, float x, float y);
     virtual status_t drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
     virtual status_t drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
     virtual status_t drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
@@ -272,7 +271,7 @@
     virtual void resetPaintFilter();
     virtual void setupPaintFilter(int clearBits, int setBits);
 
-    SkPaint* filterPaint(SkPaint* paint, bool alwaysCopy = false);
+    SkPaint* filterPaint(SkPaint* paint);
 
     void resetDrawModifiers();
     bool storeDisplayState(DeferredDisplayState& state, int stateDeferFlags);
@@ -293,11 +292,11 @@
     }
 
     /**
-     * Sets the alpha on the current snapshot. This alpha value will be modulated
+     * Scales the alpha on the current snapshot. This alpha value will be modulated
      * with other alpha values when drawing primitives.
      */
-    void setAlpha(float alpha) {
-        mSnapshot->alpha = alpha;
+    void scaleAlpha(float alpha) {
+        mSnapshot->alpha *= alpha;
     }
 
     /**