From c495e611b9fa1fc6b47a647c714bbbf94dd63461 Mon Sep 17 00:00:00 2001 From: Rob Tsuk Date: Tue, 11 Nov 2014 15:44:13 -0800 Subject: [PATCH] Add a way to override Xfermode Add a non-public API to Canvas/GLES20Canvas to provide a way to draw the touch ripple animation without using a save layer. Bug: 18226391 Change-Id: I6f8fb8938505e976892c4e14f6f864362c43e73c --- core/java/android/view/GLES20Canvas.java | 11 ++++++++++ core/jni/android_view_GLES20Canvas.cpp | 8 ++++++++ graphics/java/android/graphics/Canvas.java | 9 ++++++++ libs/hwui/DisplayListRenderer.cpp | 1 + libs/hwui/DisplayListRenderer.h | 24 +++++++++++++++++++--- 5 files changed, 50 insertions(+), 3 deletions(-) diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java index 41a4a7c19d45b..1138aaba30878 100644 --- a/core/java/android/view/GLES20Canvas.java +++ b/core/java/android/view/GLES20Canvas.java @@ -988,4 +988,15 @@ class GLES20Canvas extends HardwareCanvas { int indexOffset, int indexCount, Paint paint) { // TODO: Implement } + + @Override + public void setOverrideXfermode(PorterDuff.Mode xfermode) { + int xfermodeValue = -1; + if (xfermode != null) { + xfermodeValue = xfermode.nativeInt; + } + nSetOverrideXfermode(mRenderer, xfermodeValue); + } + + private static native void nSetOverrideXfermode(long renderer, int xfermode); } diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp index 78e92530d0dc0..814e1c86186a5 100644 --- a/core/jni/android_view_GLES20Canvas.cpp +++ b/core/jni/android_view_GLES20Canvas.cpp @@ -172,6 +172,12 @@ static jint android_view_GLES20Canvas_getMaxTextureHeight(JNIEnv* env, jobject c return Caches::getInstance().maxTextureSize; } +static void android_view_GLES20Canvas_setOverrideXfermode(JNIEnv* env, jobject clazz, + jlong rendererPtr, int xfermode) { + DisplayListRenderer* renderer = reinterpret_cast(rendererPtr); + renderer->setOverrideXfermode(xfermode); +} + // ---------------------------------------------------------------------------- // State // ---------------------------------------------------------------------------- @@ -953,6 +959,8 @@ static JNINativeMethod gMethods[] = { { "nGetMaximumTextureWidth", "()I", (void*) android_view_GLES20Canvas_getMaxTextureWidth }, { "nGetMaximumTextureHeight", "()I", (void*) android_view_GLES20Canvas_getMaxTextureHeight }, + { "nSetOverrideXfermode", "(JI)V", (void*) android_view_GLES20Canvas_setOverrideXfermode }, + #endif }; diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java index edf0fb9c48ce7..b9af794d2ef1c 100644 --- a/graphics/java/android/graphics/Canvas.java +++ b/graphics/java/android/graphics/Canvas.java @@ -249,6 +249,15 @@ public class Canvas { /** @hide */ public void insertInorderBarrier() {} + /** + * Set a transfer mode that overrides any transfer modes + * in paints used for drawing. Pass null to disable this + * override. Only implemented in GLES20Canvas. + * + * @hide + */ + public void setOverrideXfermode(@Nullable PorterDuff.Mode xfermode) {} + /** * Return true if the device that the current layer draws into is opaque * (i.e. does not support per-pixel alpha). diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp index 8887aa76ba2e8..f5247e7224e6e 100644 --- a/libs/hwui/DisplayListRenderer.cpp +++ b/libs/hwui/DisplayListRenderer.cpp @@ -40,6 +40,7 @@ DisplayListRenderer::DisplayListRenderer() , mTranslateY(0.0f) , mDeferredBarrierType(kBarrier_None) , mHighContrastText(false) + , mOverrideXfermode(-1) , mRestoreSaveCount(-1) { } diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h index 6646da774e9bf..c8a974245069d 100644 --- a/libs/hwui/DisplayListRenderer.h +++ b/libs/hwui/DisplayListRenderer.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include "CanvasState.h" @@ -189,6 +190,14 @@ public: virtual void onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) { } virtual GLuint onGetTargetFbo() const { return -1; } + void setOverrideXfermode(int xfermode) { + if (xfermode != -1) { + SkPorterDuff::Mode porterDuffMode = static_cast(xfermode); + xfermode = SkPorterDuff::ToXfermodeMode(porterDuffMode); + } + mOverrideXfermode = xfermode; + }; + private: CanvasState mState; @@ -253,10 +262,16 @@ private: // If there is a draw filter apply it here and store the modified paint // so that we don't need to modify the paint every time we access it. - SkTLazy filteredPaint; + SkTLazy localPaint; if (mDrawFilter.get()) { - paint = filteredPaint.init(); - mDrawFilter->filter(filteredPaint.get(), SkDrawFilter::kPaint_Type); + paint = localPaint.set(*paint); + mDrawFilter->filter(localPaint.get(), SkDrawFilter::kPaint_Type); + } + + if (mOverrideXfermode != -1) { + SkPaint* overriddenPaint = localPaint.set(*paint); + overriddenPaint->setXfermodeMode(static_cast(mOverrideXfermode)); + paint = overriddenPaint; } // compute the hash key for the paint and check the cache. @@ -334,6 +349,9 @@ private: DeferredBarrierType mDeferredBarrierType; bool mHighContrastText; + // -1 if unset, or SkXfermode::Mode value if set + int mOverrideXfermode; + int mRestoreSaveCount; SkAutoTUnref mDrawFilter;