diff options
| author | 2011-01-06 10:04:23 -0800 | |
|---|---|---|
| committer | 2011-01-06 18:34:30 -0800 | |
| commit | 171c592f0b7066acf279863c8a52ddabea49d3db (patch) | |
| tree | eebf9a8c82c6a6d9db6edbf077b9299a96ae36e4 | |
| parent | f0fe6d311d183c5fcf45d5e3e995fc8f9ed12f8b (diff) | |
New layers API for Views.
This API can be used to back a view and its children with either a
software layer (bitmap) or hardware layer (FBO). Layers have
various usages, including color filtering and performance
improvements during animations.
Change-Id: Ifc3bea847918042730fc5a8c2d4206dd6c9420a3
19 files changed, 664 insertions, 48 deletions
diff --git a/api/current.xml b/api/current.xml index 610542d5c0d4..f7721c4c58ee 100644 --- a/api/current.xml +++ b/api/current.xml @@ -5900,6 +5900,17 @@ visibility="public" > </field> +<field name="layerType" + type="int" + transient="false" + volatile="false" + value="16843606" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="layout" type="int" transient="false" @@ -213314,6 +213325,17 @@ visibility="public" > </method> +<method name="getLayerType" + return="int" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> <method name="getLayoutParams" return="android.view.ViewGroup.LayoutParams" abstract="false" @@ -215816,6 +215838,21 @@ <parameter name="keepScreenOn" type="boolean"> </parameter> </method> +<method name="setLayerType" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="layerType" type="int"> +</parameter> +<parameter name="paint" type="android.graphics.Paint"> +</parameter> +</method> <method name="setLayoutParams" return="void" abstract="false" @@ -216903,6 +216940,39 @@ visibility="public" > </field> +<field name="LAYER_TYPE_HARDWARE" + type="int" + transient="false" + volatile="false" + value="2" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="LAYER_TYPE_NONE" + type="int" + transient="false" + volatile="false" + value="0" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="LAYER_TYPE_SOFTWARE" + type="int" + transient="false" + volatile="false" + value="1" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="MEASURED_HEIGHT_STATE_SHIFT" type="int" transient="false" diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java index 311002cf7a69..04a521e98ab0 100644 --- a/core/java/android/view/GLES20Canvas.java +++ b/core/java/android/view/GLES20Canvas.java @@ -127,7 +127,11 @@ class GLES20Canvas extends HardwareCanvas { @Override protected void finalize() throws Throwable { - replaceNativeObject(0); + try { + replaceNativeObject(0); + } finally { + super.finalize(); + } } } @@ -395,8 +399,11 @@ class GLES20Canvas extends HardwareCanvas { @Override public int saveLayer(float left, float top, float right, float bottom, Paint paint, int saveFlags) { - int nativePaint = paint == null ? 0 : paint.mNativePaint; - return nSaveLayer(mRenderer, left, top, right, bottom, nativePaint, saveFlags); + boolean hasColorFilter = paint != null && setupColorFilter(paint); + final int nativePaint = paint == null ? 0 : paint.mNativePaint; + int count = nSaveLayer(mRenderer, left, top, right, bottom, nativePaint, saveFlags); + if (hasColorFilter) nResetModifiers(mRenderer); + return count; } private native int nSaveLayer(int renderer, float left, float top, float right, float bottom, diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 4c62358bdcb5..38777ec1d1ff 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -58,7 +58,6 @@ import android.util.PoolableManager; import android.util.Pools; import android.util.SparseArray; import android.view.ContextMenu.ContextMenuInfo; -import android.view.View.MeasureSpec; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityEventSource; import android.view.accessibility.AccessibilityManager; @@ -546,6 +545,10 @@ import java.util.WeakHashMap; * subtree rooted by that node. When an animation is started, the framework will * take care of redrawing the appropriate views until the animation completes. * </p> + * <p> + * Starting with Android 3.0, the preferred way of animating views is to use the + * {@link android.animation} package APIs. + * </p> * * <a name="Security"></a> * <h3>Security</h3> @@ -569,6 +572,7 @@ import java.util.WeakHashMap; * See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}. * </p> * + * @attr ref android.R.styleable#View_alpha * @attr ref android.R.styleable#View_background * @attr ref android.R.styleable#View_clickable * @attr ref android.R.styleable#View_contentDescription @@ -584,6 +588,7 @@ import java.util.WeakHashMap; * @attr ref android.R.styleable#View_focusableInTouchMode * @attr ref android.R.styleable#View_hapticFeedbackEnabled * @attr ref android.R.styleable#View_keepScreenOn + * @attr ref android.R.styleable#View_layerType * @attr ref android.R.styleable#View_longClickable * @attr ref android.R.styleable#View_minHeight * @attr ref android.R.styleable#View_minWidth @@ -2152,6 +2157,69 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility public static final int SCROLLBAR_POSITION_RIGHT = 2; /** + * Indicates that the view does not have a layer. + * + * @see #getLayerType() + * @see #setLayerType(int, android.graphics.Paint) + * @see #LAYER_TYPE_SOFTWARE + * @see #LAYER_TYPE_HARDWARE + */ + public static final int LAYER_TYPE_NONE = 0; + + /** + * <p>Indicates that the view has a software layer. A software layer is backed + * by a bitmap and causes the view to be rendered using Android's software + * rendering pipeline, even if hardware acceleration is enabled.</p> + * + * <p>Software layers have various usages:</p> + * <p>When the application is not using hardware acceleration, a software layer + * is useful to apply a specific color filter and/or blending mode and/or + * translucency to a view and all its children.</p> + * <p>When the application is using hardware acceleration, a software layer + * is useful to render drawing primitives not supported by the hardware + * accelerated pipeline. It can also be used to cache a complex view tree + * into a texture and reduce the complexity of drawing operations. For instance, + * when animating a complex view tree with a translation, a software layer can + * be used to render the view tree only once.</p> + * <p>Software layers should be avoided when the affected view tree updates + * often. Every update will require to re-render the software layer, which can + * potentially be slow (particularly when hardware acceleration is turned on + * since the layer will have to be uploaded into a hardware texture after every + * update.)</p> + * + * @see #getLayerType() + * @see #setLayerType(int, android.graphics.Paint) + * @see #LAYER_TYPE_NONE + * @see #LAYER_TYPE_HARDWARE + */ + public static final int LAYER_TYPE_SOFTWARE = 1; + + /** + * <p>Indicates that the view has a hardware layer. A hardware layer is backed + * by a hardware specific texture (generally Frame Buffer Objects or FBO on + * OpenGL hardware) and causes the view to be rendered using Android's hardware + * rendering pipeline, but only if hardware acceleration is turned on for the + * view hierarchy. When hardware acceleration is turned off, hardware layers + * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p> + * + * <p>A hardware layer is useful to apply a specific color filter and/or + * blending mode and/or translucency to a view and all its children.</p> + * <p>A hardware layer can also be used to increase the rendering quality when + * rotation transformations are applied on a view. It can also be used to + * prevent potential clipping issues when applying 3D transforms on a view.</p> + * + * @see #getLayerType() + * @see #setLayerType(int, android.graphics.Paint) + * @see #LAYER_TYPE_NONE + * @see #LAYER_TYPE_SOFTWARE + */ + public static final int LAYER_TYPE_HARDWARE = 2; + + @ViewDebug.ExportedProperty(category = "drawing") + int mLayerType = LAYER_TYPE_NONE; + Paint mLayerPaint; + + /** * Simple constructor to use when creating a view from code. * * @param context The Context the view is running in, through which it can @@ -2489,6 +2557,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility case R.styleable.View_verticalScrollbarPosition: mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT); break; + case R.styleable.View_layerType: + setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null); + break; } } @@ -5763,11 +5834,18 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility } /** - * Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is - * completely transparent and 1 means the view is completely opaque. + * <p>Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is + * completely transparent and 1 means the view is completely opaque.</p> + * + * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is + * responsible for applying the opacity itself. Otherwise, calling this method is + * equivalent to calling {@link #setLayerType(int, android.graphics.Paint)} and + * setting a hardware layer.</p> * * @param alpha The opacity of the view. * + * @see #setLayerType(int, android.graphics.Paint) + * * @attr ref android.R.styleable#View_alpha */ public void setAlpha(float alpha) { @@ -7747,18 +7825,107 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility } /** + * <p>Specifies the type of layer backing this view. The layer can be + * {@link #LAYER_TYPE_NONE disabled}, {@link #LAYER_TYPE_SOFTWARE software} or + * {@link #LAYER_TYPE_HARDWARE hardware}.</p> + * + * <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> + * + * <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 + * {@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 + * and can be null. It is ignored when the layer type is + * {@link #LAYER_TYPE_NONE} + * + * @see #getLayerType() + * @see #LAYER_TYPE_NONE + * @see #LAYER_TYPE_SOFTWARE + * @see #LAYER_TYPE_HARDWARE + * @see #setAlpha(float) + * + * @attr ref android.R.styleable#View_layerType + */ + public void setLayerType(int layerType, Paint paint) { + if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) { + throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, " + + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE"); + } + + // Destroy any previous software drawing cache if needed + if (mLayerType == LAYER_TYPE_SOFTWARE && layerType != LAYER_TYPE_SOFTWARE) { + if (mDrawingCache != null) { + mDrawingCache.recycle(); + mDrawingCache = null; + } + + if (mUnscaledDrawingCache != null) { + mUnscaledDrawingCache.recycle(); + mUnscaledDrawingCache = null; + } + } + + mLayerType = layerType; + mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint; + + invalidate(); + } + + /** + * Indicates what type of layer is currently associated with this view. By default + * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}. + * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)} + * for more information on the different types of layers. + * + * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or + * {@link #LAYER_TYPE_HARDWARE} + * + * @see #setLayerType(int, android.graphics.Paint) + * @see #LAYER_TYPE_NONE + * @see #LAYER_TYPE_SOFTWARE + * @see #LAYER_TYPE_HARDWARE + */ + public int getLayerType() { + return mLayerType; + } + + /** * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when * the cache is enabled. To benefit from the cache, you must request the drawing cache by * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not * null.</p> + * + * <p>Enabling the drawing cache is similar to + * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware + * acceleration is turned off. When hardware acceleration is turned on enabling the + * drawing cache has either no effect or the cache used at drawing time is not a bitmap. + * This API can however be used to manually generate a bitmap copy of this view.</p> * * @param enabled true to enable the drawing cache, false otherwise * * @see #isDrawingCacheEnabled() * @see #getDrawingCache() * @see #buildDrawingCache() + * @see #setLayerType(int, android.graphics.Paint) */ public void setDrawingCacheEnabled(boolean enabled) { setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED); @@ -8077,7 +8244,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility canvas.translate(-mScrollX, -mScrollY); mPrivateFlags |= DRAWN; - if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated) { + if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated || + mLayerType != LAYER_TYPE_NONE) { mPrivateFlags |= DRAWING_CACHE_VALID; } diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index 513844264051..82cf75337a56 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -2175,11 +2175,15 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager boolean concatMatrix = false; boolean scalingRequired = false; - boolean caching = false; + boolean caching; + final int layerType = child.getLayerType(); + if ((flags & FLAG_CHILDREN_DRAWN_WITH_CACHE) == FLAG_CHILDREN_DRAWN_WITH_CACHE || (flags & FLAG_ALWAYS_DRAWN_WITH_CACHE) == FLAG_ALWAYS_DRAWN_WITH_CACHE) { caching = true; if (mAttachInfo != null) scalingRequired = mAttachInfo.mScalingRequired; + } else { + caching = layerType != LAYER_TYPE_NONE; } if (a != null) { @@ -2270,9 +2274,17 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager Bitmap cache = null; if (caching) { if (!canvas.isHardwareAccelerated()) { + if (layerType != LAYER_TYPE_NONE) { + child.buildDrawingCache(true); + } cache = child.getDrawingCache(true); } else { - displayList = child.getDisplayList(); + if (layerType == LAYER_TYPE_SOFTWARE) { + child.buildDrawingCache(true); + cache = child.getDrawingCache(true); + } else { + displayList = child.getDisplayList(); + } } } @@ -2290,6 +2302,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager canvas.scale(scale, scale); } } + + boolean layerSaved = false; if (transformToApply != null || alpha < 1.0f || !child.hasIdentityMatrix()) { if (transformToApply != null || !childHasIdentityMatrix) { @@ -2331,12 +2345,24 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager final int multipliedAlpha = (int) (255 * alpha); if (!child.onSetAlpha(multipliedAlpha)) { int layerFlags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG; - if ((flags & FLAG_CLIP_CHILDREN) == FLAG_CLIP_CHILDREN) { + if ((flags & FLAG_CLIP_CHILDREN) == FLAG_CLIP_CHILDREN || + layerType != LAYER_TYPE_NONE) { layerFlags |= Canvas.CLIP_TO_LAYER_SAVE_FLAG; } - canvas.saveLayerAlpha(sx, sy, sx + cr - cl, sy + cb - ct, multipliedAlpha, - layerFlags); + if (layerType != LAYER_TYPE_NONE && child.mLayerPaint != null) { + child.mLayerPaint.setAlpha(multipliedAlpha); + canvas.saveLayer(sx, sy, sx + cr - cl, sy + cb - ct, + child.mLayerPaint, layerFlags); + } else { + canvas.saveLayerAlpha(sx, sy, sx + cr - cl, sy + cb - ct, + multipliedAlpha, layerFlags); + } + layerSaved = true; } else { + // Alpha is handled by the child directly, clobber the layer's alpha + if (layerType != LAYER_TYPE_NONE && child.mLayerPaint != null) { + child.mLayerPaint.setAlpha(255); + } child.mPrivateFlags |= ALPHA_SET; } } @@ -2359,6 +2385,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } if (hasNoCache) { + if (!layerSaved && layerType == LAYER_TYPE_HARDWARE) { + canvas.saveLayer(sx, sy, sx + cr - cl, sy + cb - ct, child.mLayerPaint, + Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG); + } if (!hasDisplayList) { // Fast path for layouts with no backgrounds if ((child.mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) { @@ -2376,13 +2406,22 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } } else if (cache != null) { child.mPrivateFlags &= ~DIRTY_MASK; - final Paint cachePaint = mCachePaint; - if (alpha < 1.0f) { - cachePaint.setAlpha((int) (alpha * 255)); - mGroupFlags |= FLAG_ALPHA_LOWER_THAN_ONE; - } else if ((flags & FLAG_ALPHA_LOWER_THAN_ONE) == FLAG_ALPHA_LOWER_THAN_ONE) { - cachePaint.setAlpha(255); - mGroupFlags &= ~FLAG_ALPHA_LOWER_THAN_ONE; + Paint cachePaint; + + if (layerType == LAYER_TYPE_NONE || child.mLayerPaint == null) { + cachePaint = mCachePaint; + if (alpha < 1.0f) { + cachePaint.setAlpha((int) (alpha * 255)); + mGroupFlags |= FLAG_ALPHA_LOWER_THAN_ONE; + } else if ((flags & FLAG_ALPHA_LOWER_THAN_ONE) == FLAG_ALPHA_LOWER_THAN_ONE) { + cachePaint.setAlpha(255); + mGroupFlags &= ~FLAG_ALPHA_LOWER_THAN_ONE; + } + } else { + cachePaint = child.mLayerPaint; + if (alpha < 1.0f) { + cachePaint.setAlpha((int) (alpha * 255)); + } } canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint); } diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 14c8f46e7fec..f909bd638511 100755 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -1784,6 +1784,22 @@ <!-- Place the scroll bar on the right. --> <enum name="right" value="2" /> </attr> + + <!-- Specifies the type of layer backing this view. The default value is none. + Refer to {@link android.view.View#setLayerType(int, android.graphics.Paint) + for more information.--> + <attr name="layerType"> + <!-- Don't use a layer. --> + <enum name="none" value="0" /> + <!-- Use a software layer. Refer to + {@link android.view.View#setLayerType(int, android.graphics.Paint) for + more information. --> + <enum name="software" value="1" /> + <!-- Use a hardware layer. Refer to + {@link android.view.View#setLayerType(int, android.graphics.Paint) for + more information. --> + <enum name="hardware" value="2" /> + </attr> </declare-styleable> <!-- Attributes that can be used with a {@link android.view.ViewGroup} or any diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 9daba4b209bf..0ce351ce1daf 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -1420,6 +1420,7 @@ <public type="attr" name="editTextColor" /> <public type="attr" name="editTextBackground" /> <public type="attr" name="horizontalScrollViewStyle" /> + <public type="attr" name="layerType" /> <!-- A simple fade-in animation. --> <public type="animator" name="fade_in" id="0x010b0000" /> diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h index a780183a1c33..7d54d3b3255d 100644 --- a/libs/hwui/Layer.h +++ b/libs/hwui/Layer.h @@ -26,6 +26,7 @@ #include <SkXfermode.h> #include "Rect.h" +#include "SkiaColorFilter.h" namespace android { namespace uirenderer { @@ -93,6 +94,11 @@ struct Layer { * have been drawn. */ Region region; + + /** + * Color filter used to draw this layer. Optional. + */ + SkiaColorFilter* colorFilter; }; // struct Layer }; // namespace uirenderer diff --git a/libs/hwui/LayerCache.cpp b/libs/hwui/LayerCache.cpp index 9ce0359140bb..ec186a481e7c 100644 --- a/libs/hwui/LayerCache.cpp +++ b/libs/hwui/LayerCache.cpp @@ -102,6 +102,7 @@ Layer* LayerCache::get(const uint32_t width, const uint32_t height) { layer->blend = true; layer->empty = true; layer->fbo = 0; + layer->colorFilter = NULL; glGenTextures(1, &layer->texture); glBindTexture(GL_TEXTURE_2D, layer->texture); diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index eec8d8c73fee..9613c5f6b8ff 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -406,6 +406,7 @@ bool OpenGLRenderer::createLayer(sp<Snapshot> snapshot, float left, float top, layer->layer.set(bounds); layer->texCoords.set(0.0f, bounds.getHeight() / float(layer->height), bounds.getWidth() / float(layer->width), 0.0f); + layer->colorFilter = mColorFilter; // Save the layer in the snapshot snapshot->flags |= Snapshot::kFlagIsLayer; @@ -459,7 +460,6 @@ bool OpenGLRenderer::createFboLayer(Layer* layer, Rect& bounds, sp<Snapshot> sna snapshot->flags |= Snapshot::kFlagIsFboLayer; snapshot->fbo = layer->fbo; snapshot->resetTransform(-bounds.left, -bounds.top, 0.0f); - //snapshot->resetClip(0.0f, 0.0f, bounds.getWidth(), bounds.getHeight()); snapshot->resetClip(clip.left, clip.top, clip.right, clip.bottom); snapshot->viewport.set(0.0f, 0.0f, bounds.getWidth(), bounds.getHeight()); snapshot->height = bounds.getHeight(); @@ -544,7 +544,13 @@ void OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) { // drawing only the dirty region if (fboLayer) { dirtyLayer(rect.left, rect.top, rect.right, rect.bottom, *previous->transform); + if (layer->colorFilter) { + setupColorFilter(layer->colorFilter); + } composeLayerRegion(layer, rect); + if (layer->colorFilter) { + resetColorFilter(); + } } else { dirtyLayer(rect.left, rect.top, rect.right, rect.bottom); composeLayerRect(layer, rect, true); diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml index c14988c91c8a..0fdc030b8899 100644 --- a/tests/HwAccelerationTest/AndroidManifest.xml +++ b/tests/HwAccelerationTest/AndroidManifest.xml @@ -25,6 +25,15 @@ android:hardwareAccelerated="true"> <activity + android:name="ViewLayersActivity" + android:label="_ViewLayers"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + + <activity android:name="AlphaLayersActivity" android:label="_αLayers"> <intent-filter> diff --git a/tests/HwAccelerationTest/res/layout/_advanced_blend.xml b/tests/HwAccelerationTest/res/layout/_advanced_blend.xml index 6efdd7345b69..5b6fd3c2624a 100644 --- a/tests/HwAccelerationTest/res/layout/_advanced_blend.xml +++ b/tests/HwAccelerationTest/res/layout/_advanced_blend.xml @@ -1,6 +1,19 @@ <?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2010 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. +--> <com.android.test.hwui.AdvancedBlendActivity.ShadersView - xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="fill_parent"> -</com.android.test.hwui.AdvancedBlendActivity.ShadersView> + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="fill_parent" /> diff --git a/tests/HwAccelerationTest/res/layout/_advanced_gradient.xml b/tests/HwAccelerationTest/res/layout/_advanced_gradient.xml index dd937f9b5676..5e32ed2ec7cb 100644 --- a/tests/HwAccelerationTest/res/layout/_advanced_gradient.xml +++ b/tests/HwAccelerationTest/res/layout/_advanced_gradient.xml @@ -1,6 +1,19 @@ <?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2010 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. +--> <com.android.test.hwui.AdvancedGradientsActivity.GradientsView - xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="fill_parent"> -</com.android.test.hwui.AdvancedGradientsActivity.GradientsView> + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="fill_parent" /> diff --git a/tests/HwAccelerationTest/res/layout/_layers.xml b/tests/HwAccelerationTest/res/layout/_layers.xml index c2b186d985ce..25c76ac710cf 100644 --- a/tests/HwAccelerationTest/res/layout/_layers.xml +++ b/tests/HwAccelerationTest/res/layout/_layers.xml @@ -1,6 +1,20 @@ <?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2010 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. +--> <com.android.test.hwui.LayersActivity.LayersView - xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="fill_parent"> -</com.android.test.hwui.LayersActivity.LayersView> + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="fill_parent" /> + diff --git a/tests/HwAccelerationTest/res/layout/_lines.xml b/tests/HwAccelerationTest/res/layout/_lines.xml index 00f255682932..c24dc25af9ac 100644 --- a/tests/HwAccelerationTest/res/layout/_lines.xml +++ b/tests/HwAccelerationTest/res/layout/_lines.xml @@ -1,6 +1,20 @@ <?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2010 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. +--> <com.android.test.hwui.LinesActivity.LinesView - xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="fill_parent"> -</com.android.test.hwui.LinesActivity.LinesView> + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="fill_parent" /> + diff --git a/tests/HwAccelerationTest/res/layout/_newlayers.xml b/tests/HwAccelerationTest/res/layout/_newlayers.xml index 062a2e1a2e16..5c37e371aeff 100644 --- a/tests/HwAccelerationTest/res/layout/_newlayers.xml +++ b/tests/HwAccelerationTest/res/layout/_newlayers.xml @@ -1,6 +1,20 @@ <?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2010 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. +--> <com.android.test.hwui.NewLayersActivity.LayersView - xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="fill_parent"> -</com.android.test.hwui.NewLayersActivity.LayersView> + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="fill_parent" /> + diff --git a/tests/HwAccelerationTest/res/layout/_paths.xml b/tests/HwAccelerationTest/res/layout/_paths.xml index b0534826d565..34baf8474b6c 100644 --- a/tests/HwAccelerationTest/res/layout/_paths.xml +++ b/tests/HwAccelerationTest/res/layout/_paths.xml @@ -1,6 +1,19 @@ <?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2010 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. +--> <com.android.test.hwui.PathsActivity.PathsView - xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="fill_parent"> -</com.android.test.hwui.PathsActivity.PathsView> + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="fill_parent" /> diff --git a/tests/HwAccelerationTest/res/layout/_shaders.xml b/tests/HwAccelerationTest/res/layout/_shaders.xml index dcb42fba929a..070ac1291f2c 100644 --- a/tests/HwAccelerationTest/res/layout/_shaders.xml +++ b/tests/HwAccelerationTest/res/layout/_shaders.xml @@ -1,6 +1,20 @@ <?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2010 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. +--> <com.android.test.hwui.ShadersActivity.ShadersView - xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="fill_parent"> -</com.android.test.hwui.ShadersActivity.ShadersView> + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="fill_parent" /> + diff --git a/tests/HwAccelerationTest/res/layout/view_layers.xml b/tests/HwAccelerationTest/res/layout/view_layers.xml new file mode 100644 index 000000000000..e0cdc78d2ae9 --- /dev/null +++ b/tests/HwAccelerationTest/res/layout/view_layers.xml @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2011 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. +--> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="horizontal" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <ListView + android:id="@+id/list1" + android:layout_width="0dip" + android:layout_height="match_parent" + android:layout_weight="1" /> + + <ListView + android:id="@+id/list2" + android:layout_width="0dip" + android:layout_height="match_parent" + android:layout_weight="1" /> + + <ListView + android:id="@+id/list3" + android:layout_width="0dip" + android:layout_height="match_parent" + android:layout_weight="1" /> + +</LinearLayout> diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity.java new file mode 100644 index 000000000000..359447d06995 --- /dev/null +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity.java @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2011 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. + */ + +package com.android.test.hwui; + +import android.animation.ObjectAnimator; +import android.app.Activity; +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.os.Bundle; +import android.util.DisplayMetrics; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.ListView; +import android.widget.TextView; + +@SuppressWarnings({"UnusedDeclaration"}) +public class ViewLayersActivity extends Activity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.view_layers); + + setupList(R.id.list1); + setupList(R.id.list2); + setupList(R.id.list3); + + getWindow().getDecorView().postDelayed(new Runnable() { + @Override + public void run() { + final View leftList = findViewById(R.id.list1); + final View middleList = findViewById(R.id.list2); + final View rightList = findViewById(R.id.list3); + + final ObjectAnimator moveRight = ObjectAnimator.ofFloat(leftList, + "x", 0, rightList.getLeft()); + moveRight.setDuration(1500); + moveRight.setRepeatCount(ObjectAnimator.INFINITE); + moveRight.setRepeatMode(ObjectAnimator.REVERSE); + + final ObjectAnimator moveLeft = ObjectAnimator.ofFloat(rightList, + "x", rightList.getLeft(), 0); + moveLeft.setDuration(1500); + moveLeft.setRepeatCount(ObjectAnimator.INFINITE); + moveLeft.setRepeatMode(ObjectAnimator.REVERSE); + + final ObjectAnimator rotate = ObjectAnimator.ofFloat(middleList, + "rotationY", 0, 360); + rotate.setDuration(3000); + rotate.setRepeatCount(ObjectAnimator.INFINITE); + rotate.setRepeatMode(ObjectAnimator.REVERSE); + + Paint p = new Paint(); + p.setColorFilter(new PorterDuffColorFilter(0xffff0000, PorterDuff.Mode.MULTIPLY)); + + Paint p2 = new Paint(); + p2.setAlpha(127); + + Paint p3 = new Paint(); + p3.setColorFilter(new PorterDuffColorFilter(0xff00ff00, PorterDuff.Mode.MULTIPLY)); + + leftList.setLayerType(View.LAYER_TYPE_SOFTWARE, p); + leftList.setAlpha(0.5f); + middleList.setLayerType(View.LAYER_TYPE_HARDWARE, p3); + middleList.setAlpha(0.5f); + rightList.setLayerType(View.LAYER_TYPE_SOFTWARE, p2); + + moveRight.start(); + moveLeft.start(); + rotate.start(); + } + }, 2000); + } + + private void setupList(int listId) { + final ListView list = (ListView) findViewById(listId); + list.setAdapter(new SimpleListAdapter(this)); + } + + private static class SimpleListAdapter extends ArrayAdapter<String> { + public SimpleListAdapter(Context context) { + super(context, android.R.layout.simple_list_item_1, DATA_LIST); + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + TextView v = (TextView) super.getView(position, convertView, parent); + final Resources r = getContext().getResources(); + final DisplayMetrics metrics = r.getDisplayMetrics(); + v.setCompoundDrawablePadding((int) (6 * metrics.density + 0.5f)); + v.setCompoundDrawablesWithIntrinsicBounds(r.getDrawable(R.drawable.icon), + null, null, null); + return v; + } + } + + private static final String[] DATA_LIST = { + "Afghanistan", "Albania", "Algeria", "American Samoa", "Andorra", + "Angola", "Anguilla", "Antarctica", "Antigua and Barbuda", "Argentina", + "Armenia", "Aruba", "Australia", "Austria", "Azerbaijan", + "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium", + "Belize", "Benin", "Bermuda", "Bhutan", "Bolivia", + "Bosnia and Herzegovina", "Botswana", "Bouvet Island", "Brazil", + "British Indian Ocean Territory", "British Virgin Islands", "Brunei", "Bulgaria", + "Burkina Faso", "Burundi", "Cote d'Ivoire", "Cambodia", "Cameroon", "Canada", "Cape Verde", + "Cayman Islands", "Central African Republic", "Chad", "Chile", "China", + "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo", + "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic", + "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica", "Dominican Republic", + "East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea", + "Estonia", "Ethiopia", "Faeroe Islands", "Falkland Islands", "Fiji", "Finland", + "Former Yugoslav Republic of Macedonia", "France", "French Guiana", "French Polynesia", + "French Southern Territories", "Gabon", "Georgia", "Germany", "Ghana", "Gibraltar", + "Greece", "Greenland", "Grenada", "Guadeloupe", "Guam", "Guatemala", "Guinea", "Guinea-Bissau", + "Guyana", "Haiti", "Heard Island and McDonald Islands", "Honduras", "Hong Kong", "Hungary", + "Iceland", "India", "Indonesia", "Iran", "Iraq", "Ireland", "Israel", "Italy", "Jamaica", + "Japan", "Jordan", "Kazakhstan", "Kenya", "Kiribati", "Kuwait", "Kyrgyzstan", "Laos", + "Latvia", "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein", "Lithuania", "Luxembourg", + "Macau", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands", + "Martinique", "Mauritania", "Mauritius", "Mayotte", "Mexico", "Micronesia", "Moldova", + "Monaco", "Mongolia", "Montserrat", "Morocco", "Mozambique", "Myanmar", "Namibia", + "Nauru", "Nepal", "Netherlands", "Netherlands Antilles", "New Caledonia", "New Zealand", + "Nicaragua", "Niger", "Nigeria", "Niue", "Norfolk Island", "North Korea", "Northern Marianas", + "Norway", "Oman", "Pakistan", "Palau", "Panama", "Papua New Guinea", "Paraguay", "Peru", + "Philippines", "Pitcairn Islands", "Poland", "Portugal", "Puerto Rico", "Qatar", + "Reunion", "Romania", "Russia", "Rwanda", "Sqo Tome and Principe", "Saint Helena", + "Saint Kitts and Nevis", "Saint Lucia", "Saint Pierre and Miquelon", + "Saint Vincent and the Grenadines", "Samoa", "San Marino", "Saudi Arabia", "Senegal", + "Seychelles", "Sierra Leone", "Singapore", "Slovakia", "Slovenia", "Solomon Islands", + "Somalia", "South Africa", "South Georgia and the South Sandwich Islands", "South Korea", + "Spain", "Sri Lanka", "Sudan", "Suriname", "Svalbard and Jan Mayen", "Swaziland", "Sweden", + "Switzerland", "Syria", "Taiwan", "Tajikistan", "Tanzania", "Thailand", "The Bahamas", + "The Gambia", "Togo", "Tokelau", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey", + "Turkmenistan", "Turks and Caicos Islands", "Tuvalu", "Virgin Islands", "Uganda", + "Ukraine", "United Arab Emirates", "United Kingdom", + "United States", "United States Minor Outlying Islands", "Uruguay", "Uzbekistan", + "Vanuatu", "Vatican City", "Venezuela", "Vietnam", "Wallis and Futuna", "Western Sahara", + "Yemen", "Yugoslavia", "Zambia", "Zimbabwe" + }; +} |