From 4678dcc5524258908eadc5fe1e5e1874768967eb 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 DO NOT MERGE Add a non-public API to Canvas/GLES20Canvas to provide a way to draw the touch ripple animation without using a save layer. Change-Id: I6e2095adffe515194f669fb75bb67abf813bd518 --- 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 | 45 ++++++++++++++++------ 5 files changed, 62 insertions(+), 12 deletions(-) diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java index b86455ace7b5f..6de06d4439814 100644 --- a/core/java/android/view/GLES20Canvas.java +++ b/core/java/android/view/GLES20Canvas.java @@ -994,4 +994,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 b023ebdce5b56..fe64aba3c3d30 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 // ---------------------------------------------------------------------------- @@ -964,6 +970,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 f45c0cb1b7248..6baf1aae03736 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 c2cb76ed8f126..3ec5e40f0f88a 100644 --- a/libs/hwui/DisplayListRenderer.cpp +++ b/libs/hwui/DisplayListRenderer.cpp @@ -39,6 +39,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 2cc2be36c74d6..f93a798c417c8 100644 --- a/libs/hwui/DisplayListRenderer.h +++ b/libs/hwui/DisplayListRenderer.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #include "DisplayListLogBuffer.h" @@ -161,6 +162,15 @@ public: void setHighContrastText(bool highContrastText) { mHighContrastText = highContrastText; } + + void setOverrideXfermode(int xfermode) { + if (xfermode != -1) { + SkPorterDuff::Mode porterDuffMode = static_cast(xfermode); + xfermode = SkPorterDuff::ToXfermodeMode(porterDuffMode); + } + mOverrideXfermode = xfermode; + }; + private: enum DeferredBarrierType { kBarrier_None, @@ -220,18 +230,26 @@ private: inline const SkPaint* refPaint(const SkPaint* paint) { if (!paint) return NULL; - const SkPaint* paintCopy = mPaintMap.valueFor(paint); - if (paintCopy == NULL - || paintCopy->getGenerationID() != paint->getGenerationID() - // We can't compare shader pointers because that will always - // change as we do partial copying via wrapping. However, if the - // shader changes the paint generationID will have changed and - // so we don't hit this comparison anyway - || !(paint->getShader() && paintCopy->getShader() - && paint->getShader()->getGenerationID() == paintCopy->getShader()->getGenerationID())) { - paintCopy = copyPaint(paint); - // replaceValueFor() performs an add if the entry doesn't exist - mPaintMap.replaceValueFor(paint, paintCopy); + const SkPaint* paintCopy; + + if (mOverrideXfermode != -1) { + SkPaint* overriddenPaint = copyPaint(paint); + overriddenPaint->setXfermodeMode(static_cast(mOverrideXfermode)); + paintCopy = overriddenPaint; + } else { + paintCopy = mPaintMap.valueFor(paint); + if (paintCopy == NULL + || paintCopy->getGenerationID() != paint->getGenerationID() + // We can't compare shader pointers because that will always + // change as we do partial copying via wrapping. However, if the + // shader changes the paint generationID will have changed and + // so we don't hit this comparison anyway + || !(paint->getShader() && paintCopy->getShader() + && paint->getShader()->getGenerationID() == paintCopy->getShader()->getGenerationID())) { + paintCopy = copyPaint(paint); + // replaceValueFor() performs an add if the entry doesn't exist + mPaintMap.replaceValueFor(paint, paintCopy); + } } return paintCopy; @@ -304,6 +322,9 @@ private: DeferredBarrierType mDeferredBarrierType; bool mHighContrastText; + // -1 if unset, or SkXfermode::Mode value if set + int mOverrideXfermode; + int mRestoreSaveCount; friend class RenderNode;