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
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index b86455a..6de06d4 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -994,4 +994,15 @@
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 b023ebd..fe64aba 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -172,6 +172,12 @@
return Caches::getInstance().maxTextureSize;
}
+static void android_view_GLES20Canvas_setOverrideXfermode(JNIEnv* env, jobject clazz,
+ jlong rendererPtr, int xfermode) {
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
+ renderer->setOverrideXfermode(xfermode);
+}
+
// ----------------------------------------------------------------------------
// State
// ----------------------------------------------------------------------------
@@ -964,6 +970,8 @@
{ "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 f45c0cb..6baf1aa 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -250,6 +250,15 @@
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 c2cb76e..3ec5e40 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -39,6 +39,7 @@
, 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 2cc2be3..f93a798 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -20,6 +20,7 @@
#include <SkMatrix.h>
#include <SkPaint.h>
#include <SkPath.h>
+#include <SkPorterDuff.h>
#include <cutils/compiler.h>
#include "DisplayListLogBuffer.h"
@@ -161,6 +162,15 @@
void setHighContrastText(bool highContrastText) {
mHighContrastText = highContrastText;
}
+
+ void setOverrideXfermode(int xfermode) {
+ if (xfermode != -1) {
+ SkPorterDuff::Mode porterDuffMode = static_cast<SkPorterDuff::Mode>(xfermode);
+ xfermode = SkPorterDuff::ToXfermodeMode(porterDuffMode);
+ }
+ mOverrideXfermode = xfermode;
+ };
+
private:
enum DeferredBarrierType {
kBarrier_None,
@@ -220,18 +230,26 @@
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<SkXfermode::Mode>(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 @@
DeferredBarrierType mDeferredBarrierType;
bool mHighContrastText;
+ // -1 if unset, or SkXfermode::Mode value if set
+ int mOverrideXfermode;
+
int mRestoreSaveCount;
friend class RenderNode;