summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.txt1
-rw-r--r--core/java/android/view/GLES20Canvas.java11
-rw-r--r--core/java/android/view/GLES20Layer.java10
-rw-r--r--core/java/android/view/HardwareLayer.java9
-rw-r--r--core/java/android/view/TextureView.java1
-rw-r--r--core/java/android/view/View.java49
-rw-r--r--core/jni/android_view_GLES20Canvas.cpp16
-rw-r--r--libs/hwui/Android.mk1
-rw-r--r--libs/hwui/DisplayListRenderer.cpp16
-rw-r--r--libs/hwui/Layer.cpp51
-rw-r--r--libs/hwui/Layer.h12
-rw-r--r--libs/hwui/OpenGLRenderer.cpp12
-rw-r--r--libs/hwui/OpenGLRenderer.h52
13 files changed, 189 insertions, 52 deletions
diff --git a/api/current.txt b/api/current.txt
index 7ad9cad..161909c 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -25027,6 +25027,7 @@ package android.view {
method public void setId(int);
method public void setImportantForAccessibility(int);
method public void setKeepScreenOn(boolean);
+ method public void setLayerPaint(android.graphics.Paint);
method public void setLayerType(int, android.graphics.Paint);
method public void setLayoutDirection(int);
method public void setLayoutParams(android.view.ViewGroup.LayoutParams);
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index f4ab133..869cd00 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -152,6 +152,8 @@ class GLES20Canvas extends HardwareCanvas {
static native int nCreateLayer(int width, int height, boolean isOpaque, int[] layerInfo);
static native void nResizeLayer(int layerId, int width, int height, int[] layerInfo);
static native void nSetOpaqueLayer(int layerId, boolean isOpaque);
+ static native void nSetLayerPaint(int layerId, int nativePaint);
+ static native void nSetLayerColorFilter(int layerId, int nativeColorFilter);
static native void nUpdateTextureLayer(int layerId, int width, int height, boolean opaque,
SurfaceTexture surface);
static native void nSetTextureLayerTransform(int layerId, int matrix);
@@ -394,13 +396,8 @@ class GLES20Canvas extends HardwareCanvas {
void drawHardwareLayer(HardwareLayer layer, float x, float y, Paint paint) {
final GLES20Layer glLayer = (GLES20Layer) layer;
- int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE;
- try {
- final int nativePaint = paint == null ? 0 : paint.mNativePaint;
- nDrawLayer(mRenderer, glLayer.getLayer(), x, y, nativePaint);
- } finally {
- if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier);
- }
+ final int nativePaint = paint == null ? 0 : paint.mNativePaint;
+ nDrawLayer(mRenderer, glLayer.getLayer(), x, y, nativePaint);
}
private static native void nDrawLayer(int renderer, int layer, float x, float y, int paint);
diff --git a/core/java/android/view/GLES20Layer.java b/core/java/android/view/GLES20Layer.java
index a0ae379..a462ed6 100644
--- a/core/java/android/view/GLES20Layer.java
+++ b/core/java/android/view/GLES20Layer.java
@@ -18,6 +18,7 @@
package android.view;
import android.graphics.Bitmap;
+import android.graphics.Paint;
/**
* An OpenGL ES 2.0 implementation of {@link HardwareLayer}.
@@ -43,6 +44,15 @@ abstract class GLES20Layer extends HardwareLayer {
}
@Override
+ void setLayerPaint(Paint paint) {
+ if (paint != null) {
+ GLES20Canvas.nSetLayerPaint(mLayer, paint.mNativePaint);
+ GLES20Canvas.nSetLayerColorFilter(mLayer, paint.getColorFilter() != null ?
+ paint.getColorFilter().nativeColorFilter : 0);
+ }
+ }
+
+ @Override
boolean copyInto(Bitmap bitmap) {
return GLES20Canvas.nCopyLayer(mLayer, bitmap.mNativeBitmap);
}
diff --git a/core/java/android/view/HardwareLayer.java b/core/java/android/view/HardwareLayer.java
index 06c6e7c..6e763b2 100644
--- a/core/java/android/view/HardwareLayer.java
+++ b/core/java/android/view/HardwareLayer.java
@@ -19,6 +19,7 @@ package android.view;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
+import android.graphics.Paint;
import android.graphics.Rect;
/**
@@ -62,6 +63,14 @@ abstract class HardwareLayer {
}
/**
+ * Update the paint used when drawing this layer.
+ *
+ * @param paint The paint used when the layer is drawn into the destination canvas.
+ * @see View#setLayerPaint(android.graphics.Paint)
+ */
+ void setLayerPaint(Paint paint) {}
+
+ /**
* Returns the minimum width of the layer.
*
* @return The minimum desired width of the hardware layer
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index fe14c88..7e335f0 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -367,6 +367,7 @@ public class TextureView extends View {
if (mListener != null && !mUpdateSurface) {
mListener.onSurfaceTextureAvailable(mSurface, getWidth(), getHeight());
}
+ mLayer.setLayerPaint(mLayerPaint);
}
if (mUpdateSurface) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index d268fd2..236adab 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -11932,13 +11932,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* {@link #setAlpha(float)}, the alpha value of the layer's paint is replaced by
* this view's alpha value. Calling {@link #setAlpha(float)} is therefore
* equivalent to setting a hardware layer on this view and providing a paint with
- * the desired alpha value.<p>
+ * the desired alpha value.</p>
*
* <p>Refer to the documentation of {@link #LAYER_TYPE_NONE disabled},
* {@link #LAYER_TYPE_SOFTWARE software} and {@link #LAYER_TYPE_HARDWARE hardware}
* for more information on when and how to use layers.</p>
*
- * @param layerType The ype of layer to use with this view, must be one of
+ * @param layerType The type of layer to use with this view, must be one of
* {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
* {@link #LAYER_TYPE_HARDWARE}
* @param paint The paint used to compose the layer. This argument is optional
@@ -11990,6 +11990,50 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
+ * Updates the {@link Paint} object used with the current layer (used only if the current
+ * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
+ * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
+ * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
+ * ensure that the view gets redrawn immediately.
+ *
+ * <p>A layer is associated with an optional {@link android.graphics.Paint}
+ * instance that controls how the layer is composed on screen. The following
+ * properties of the paint are taken into account when composing the layer:</p>
+ * <ul>
+ * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
+ * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
+ * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
+ * </ul>
+ *
+ * <p>If this view has an alpha value set to < 1.0 by calling
+ * {@link #setAlpha(float)}, the alpha value of the layer's paint is replaced by
+ * this view's alpha value. Calling {@link #setAlpha(float)} is therefore
+ * equivalent to setting a hardware layer on this view and providing a paint with
+ * the desired alpha value.</p>
+ *
+ * @param paint The paint used to compose the layer. This argument is optional
+ * and can be null. It is ignored when the layer type is
+ * {@link #LAYER_TYPE_NONE}
+ *
+ * @see #setLayerType(int, android.graphics.Paint)
+ */
+ public void setLayerPaint(Paint paint) {
+ int layerType = getLayerType();
+ if (layerType != LAYER_TYPE_NONE) {
+ mLayerPaint = paint == null ? new Paint() : paint;
+ if (layerType == LAYER_TYPE_HARDWARE) {
+ HardwareLayer layer = getHardwareLayer();
+ if (layer != null) {
+ layer.setLayerPaint(paint);
+ }
+ invalidateViewProperty(false, false);
+ } else {
+ invalidate();
+ }
+ }
+ }
+
+ /**
* Indicates whether this view has a static layer. A view with layer type
* {@link #LAYER_TYPE_NONE} is a static layer. Other types of layers are
* dynamic.
@@ -12101,6 +12145,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (!mHardwareLayer.isValid()) {
return null;
}
+ mHardwareLayer.setLayerPaint(mLayerPaint);
mHardwareLayer.redraw(getHardwareLayerDisplayList(mHardwareLayer), mLocalDirtyRect);
mLocalDirtyRect.setEmpty();
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 3538fef..7dbf9ec 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -776,6 +776,20 @@ static void android_view_GLES20Canvas_resizeLayer(JNIEnv* env, jobject clazz,
env->ReleaseIntArrayElements(layerInfo, storage, 0);
}
+static void android_view_GLES20Canvas_setLayerPaint(JNIEnv* env, jobject clazz,
+ Layer* layer, SkPaint* paint) {
+ if (layer) {
+ layer->setPaint(paint);
+ }
+}
+
+static void android_view_GLES20Canvas_setLayerColorFilter(JNIEnv* env, jobject clazz,
+ Layer* layer, SkiaColorFilter* colorFilter) {
+ if (layer) {
+ layer->setColorFilter(colorFilter);
+ }
+}
+
static void android_view_GLES20Canvas_setOpaqueLayer(JNIEnv* env, jobject clazz,
Layer* layer, jboolean isOpaque) {
if (layer) {
@@ -979,6 +993,8 @@ static JNINativeMethod gMethods[] = {
{ "nCreateLayerRenderer", "(I)I", (void*) android_view_GLES20Canvas_createLayerRenderer },
{ "nCreateLayer", "(IIZ[I)I", (void*) android_view_GLES20Canvas_createLayer },
{ "nResizeLayer", "(III[I)V" , (void*) android_view_GLES20Canvas_resizeLayer },
+ { "nSetLayerPaint", "(II)V", (void*) android_view_GLES20Canvas_setLayerPaint },
+ { "nSetLayerColorFilter", "(II)V", (void*) android_view_GLES20Canvas_setLayerColorFilter },
{ "nSetOpaqueLayer", "(IZ)V", (void*) android_view_GLES20Canvas_setOpaqueLayer },
{ "nCreateTextureLayer", "(Z[I)I", (void*) android_view_GLES20Canvas_createTextureLayer },
{ "nUpdateTextureLayer", "(IIIZLandroid/graphics/SurfaceTexture;)V",
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index c0f79df..e032ae4 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -16,6 +16,7 @@ ifeq ($(USE_OPENGL_RENDERER),true)
Dither.cpp \
FboCache.cpp \
GradientCache.cpp \
+ Layer.cpp \
LayerCache.cpp \
LayerRenderer.cpp \
Matrix.cpp \
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 2de70d4..3e3121e 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -1004,29 +1004,39 @@ status_t DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flag
}
break;
case DrawLayer: {
+ int oldAlpha = -1;
Layer* layer = (Layer*) getInt();
float x = getFloat();
float y = getFloat();
SkPaint* paint = getPaint(renderer);
- if (mCaching) {
- paint->setAlpha(mMultipliedAlpha);
+ if (mCaching && mMultipliedAlpha < 255) {
+ oldAlpha = layer->getAlpha();
+ layer->setAlpha(mMultipliedAlpha);
}
DISPLAY_LIST_LOGD("%s%s %p, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
layer, x, y, paint);
drawGlStatus |= renderer.drawLayer(layer, x, y, paint);
+ if (oldAlpha >= 0) {
+ layer->setAlpha(oldAlpha);
+ }
}
break;
case DrawBitmap: {
+ int oldAlpha = -1;
SkBitmap* bitmap = getBitmap();
float x = getFloat();
float y = getFloat();
SkPaint* paint = getPaint(renderer);
- if (mCaching) {
+ if (mCaching && mMultipliedAlpha < 255) {
+ oldAlpha = paint->getAlpha();
paint->setAlpha(mMultipliedAlpha);
}
DISPLAY_LIST_LOGD("%s%s %p, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
bitmap, x, y, paint);
drawGlStatus |= renderer.drawBitmap(bitmap, x, y, paint);
+ if (oldAlpha >= 0) {
+ paint->setAlpha(oldAlpha);
+ }
}
break;
case DrawBitmapMatrix: {
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
new file mode 100644
index 0000000..31e169b
--- /dev/null
+++ b/libs/hwui/Layer.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "OpenGLRenderer"
+
+#include <utils/Log.h>
+
+#include "Layer.h"
+#include "OpenGLRenderer.h"
+#include "Caches.h"
+
+namespace android {
+namespace uirenderer {
+
+Layer::~Layer() {
+ if (mesh) delete mesh;
+ if (meshIndices) delete meshIndices;
+ if (colorFilter) Caches::getInstance().resourceCache.decrementRefcount(colorFilter);
+}
+
+void Layer::setPaint(SkPaint* paint) {
+ OpenGLRenderer::getAlphaAndModeDirect(paint, &alpha, &mode);
+}
+
+void Layer::setColorFilter(SkiaColorFilter* filter) {
+ if (colorFilter) {
+ Caches::getInstance().resourceCache.decrementRefcount(colorFilter);
+ }
+ colorFilter = filter;
+ if (colorFilter) {
+ Caches::getInstance().resourceCache.incrementRefcount(colorFilter);
+ }
+}
+
+
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index f243177..76da671 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -45,6 +45,7 @@ class DisplayList;
* A layer has dimensions and is backed by an OpenGL texture or FBO.
*/
struct Layer {
+
Layer(const uint32_t layerWidth, const uint32_t layerHeight) {
mesh = NULL;
meshIndices = NULL;
@@ -60,10 +61,7 @@ struct Layer {
displayList = NULL;
}
- ~Layer() {
- if (mesh) delete mesh;
- if (meshIndices) delete meshIndices;
- }
+ ~Layer();
/**
* Sets this layer's region to a rectangle. Computes the appropriate
@@ -106,6 +104,8 @@ struct Layer {
texture.height = height;
}
+ ANDROID_API void setPaint(SkPaint* paint);
+
inline void setBlend(bool blend) {
texture.blend = blend;
}
@@ -191,9 +191,7 @@ struct Layer {
return colorFilter;
}
- inline void setColorFilter(SkiaColorFilter* filter) {
- colorFilter = filter;
- }
+ ANDROID_API void setColorFilter(SkiaColorFilter* filter);
inline void bindTexture() {
glBindTexture(renderTarget, texture.id);
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index b66c898..05c7809 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -2593,17 +2593,13 @@ status_t OpenGLRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* pain
mCaches.activeTexture(0);
- int alpha;
- SkXfermode::Mode mode;
- getAlphaAndMode(paint, &alpha, &mode);
-
- layer->setAlpha(alpha, mode);
-
if (CC_LIKELY(!layer->region.isEmpty())) {
if (layer->region.isRect()) {
composeLayerRect(layer, layer->regionRect);
} else if (layer->mesh) {
- const float a = alpha / 255.0f;
+ const float a = layer->getAlpha() / 255.0f;
+ SkiaColorFilter *oldFilter = mColorFilter;
+ mColorFilter = layer->getColorFilter();
setupDraw();
setupDrawWithTexture();
@@ -2633,6 +2629,8 @@ status_t OpenGLRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* pain
finishDrawTexture();
+ mColorFilter = oldFilter;
+
#if DEBUG_LAYERS_AS_REGIONS
drawRegionRects(layer->region);
#endif
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index f2b5f0a..7f9405f 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -227,6 +227,32 @@ public:
*/
void endMark() const;
+ /**
+ * Gets the alpha and xfermode out of a paint object. If the paint is null
+ * alpha will be 255 and the xfermode will be SRC_OVER. This method does
+ * not multiply the paint's alpha by the current snapshot's alpha.
+ *
+ * @param paint The paint to extract values from
+ * @param alpha Where to store the resulting alpha
+ * @param mode Where to store the resulting xfermode
+ */
+ static inline void getAlphaAndModeDirect(SkPaint* paint, int* alpha, SkXfermode::Mode* mode) {
+ if (paint) {
+ *mode = getXfermode(paint->getXfermode());
+
+ // Skia draws using the color's alpha channel if < 255
+ // Otherwise, it uses the paint's alpha
+ int color = paint->getColor();
+ *alpha = (color >> 24) & 0xFF;
+ if (*alpha == 255) {
+ *alpha = paint->getAlpha();
+ }
+ } else {
+ *mode = SkXfermode::kSrcOver_Mode;
+ *alpha = 255;
+ }
+ }
+
protected:
/**
* Compose the layer defined in the current snapshot with the layer
@@ -291,32 +317,6 @@ protected:
inline void getAlphaAndMode(SkPaint* paint, int* alpha, SkXfermode::Mode* mode);
/**
- * Gets the alpha and xfermode out of a paint object. If the paint is null
- * alpha will be 255 and the xfermode will be SRC_OVER. This method does
- * not multiply the paint's alpha by the current snapshot's alpha.
- *
- * @param paint The paint to extract values from
- * @param alpha Where to store the resulting alpha
- * @param mode Where to store the resulting xfermode
- */
- static inline void getAlphaAndModeDirect(SkPaint* paint, int* alpha, SkXfermode::Mode* mode) {
- if (paint) {
- *mode = getXfermode(paint->getXfermode());
-
- // Skia draws using the color's alpha channel if < 255
- // Otherwise, it uses the paint's alpha
- int color = paint->getColor();
- *alpha = (color >> 24) & 0xFF;
- if (*alpha == 255) {
- *alpha = paint->getAlpha();
- }
- } else {
- *mode = SkXfermode::kSrcOver_Mode;
- *alpha = 255;
- }
- }
-
- /**
* Safely retrieves the mode from the specified xfermode. If the specified
* xfermode is null, the mode is assumed to be SkXfermode::kSrcOver_Mode.
*/