Merge "Better backend for hardware layers." into honeycomb
This commit is contained in:
@@ -73,9 +73,21 @@ class GLES20Canvas extends HardwareCanvas {
|
||||
// Constructors
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Creates a canvas to render directly on screen.
|
||||
*/
|
||||
GLES20Canvas(boolean translucent) {
|
||||
this(false, translucent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a canvas to render into an FBO.
|
||||
*/
|
||||
GLES20Canvas(int fbo, boolean translucent) {
|
||||
mOpaque = !translucent;
|
||||
mRenderer = nCreateLayerRenderer(fbo);
|
||||
setupFinalizer();
|
||||
}
|
||||
|
||||
protected GLES20Canvas(boolean record, boolean translucent) {
|
||||
mOpaque = !translucent;
|
||||
@@ -89,7 +101,11 @@ class GLES20Canvas extends HardwareCanvas {
|
||||
} else {
|
||||
mRenderer = nCreateRenderer();
|
||||
}
|
||||
|
||||
|
||||
setupFinalizer();
|
||||
}
|
||||
|
||||
private void setupFinalizer() {
|
||||
if (mRenderer == 0) {
|
||||
throw new IllegalStateException("Could not create GLES20Canvas renderer");
|
||||
} else {
|
||||
@@ -97,7 +113,8 @@ class GLES20Canvas extends HardwareCanvas {
|
||||
}
|
||||
}
|
||||
|
||||
private native int nCreateRenderer();
|
||||
private static native int nCreateRenderer();
|
||||
private static native int nCreateLayerRenderer(int fbo);
|
||||
private static native int nGetDisplayListRenderer(int renderer);
|
||||
private static native void nDestroyRenderer(int renderer);
|
||||
|
||||
@@ -135,6 +152,15 @@ class GLES20Canvas extends HardwareCanvas {
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Hardware layers
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static native int nCreateLayer(int width, int height, int[] layerInfo);
|
||||
static native void nResizeLayer(int layerId, int layerTextureId, int width, int height,
|
||||
int[] layerInfo);
|
||||
static native void nDestroyLayer(int layerId, int layerTextureId);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Canvas management
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@@ -226,6 +252,34 @@ class GLES20Canvas extends HardwareCanvas {
|
||||
|
||||
private native void nDrawDisplayList(int renderer, int displayList);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Hardware layer
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void drawHardwareLayer(float left, float top, float right, float bottom,
|
||||
HardwareLayer layer, Paint paint) {
|
||||
final GLES20Layer glLayer = (GLES20Layer) layer;
|
||||
boolean hasColorFilter = paint != null && setupColorFilter(paint);
|
||||
final int nativePaint = paint == null ? 0 : paint.mNativePaint;
|
||||
nDrawLayer(mRenderer, left, top, right, bottom, glLayer.mLayerTextureId,
|
||||
glLayer.getU(), glLayer.getV(), nativePaint);
|
||||
if (hasColorFilter) nResetModifiers(mRenderer);
|
||||
}
|
||||
|
||||
private native void nDrawLayer(int renderer, float left, float top, float right, float bottom,
|
||||
int layerTexture, float u, float v, int paint);
|
||||
|
||||
void interrupt() {
|
||||
nInterrupt(mRenderer);
|
||||
}
|
||||
|
||||
void resume() {
|
||||
nResume(mRenderer);
|
||||
}
|
||||
|
||||
private native void nInterrupt(int renderer);
|
||||
private native void nResume(int renderer);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Clipping
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -106,7 +106,11 @@ class GLES20DisplayList extends DisplayList {
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
replaceNativeObject(0);
|
||||
try {
|
||||
replaceNativeObject(0);
|
||||
} finally {
|
||||
super.finalize();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
143
core/java/android/view/GLES20Layer.java
Normal file
143
core/java/android/view/GLES20Layer.java
Normal file
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* 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 android.view;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
|
||||
/**
|
||||
* An OpenGL ES 2.0 implementation of {@link HardwareLayer}.
|
||||
*/
|
||||
class GLES20Layer extends HardwareLayer {
|
||||
private int mLayerId;
|
||||
int mLayerTextureId;
|
||||
|
||||
private int mLayerWidth;
|
||||
private int mLayerHeight;
|
||||
|
||||
private final GLES20Canvas mCanvas;
|
||||
|
||||
private float mU;
|
||||
private float mV;
|
||||
|
||||
@SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
|
||||
private final Finalizer mFinalizer;
|
||||
|
||||
GLES20Layer(int width, int height, boolean isOpaque) {
|
||||
super(width, height, isOpaque);
|
||||
|
||||
int[] layerInfo = new int[3];
|
||||
mLayerId = GLES20Canvas.nCreateLayer(width, height, layerInfo);
|
||||
if (mLayerId != 0) {
|
||||
mLayerWidth = layerInfo[0];
|
||||
mLayerHeight = layerInfo[1];
|
||||
mLayerTextureId = layerInfo[2];
|
||||
|
||||
mCanvas = new GLES20Canvas(mLayerId, !isOpaque);
|
||||
mFinalizer = new Finalizer(mLayerId, mLayerTextureId);
|
||||
|
||||
mU = mWidth / (float) mLayerWidth;
|
||||
mV = mHeight/ (float) mLayerHeight;
|
||||
} else {
|
||||
mCanvas = null;
|
||||
mFinalizer = null;
|
||||
}
|
||||
}
|
||||
|
||||
float getU() {
|
||||
return mU;
|
||||
}
|
||||
|
||||
float getV() {
|
||||
return mV;
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isValid() {
|
||||
return mLayerId != 0 && mLayerWidth > 0 && mLayerHeight > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
void resize(int width, int height) {
|
||||
if (!isValid() || width <= 0 || height <= 0) return;
|
||||
if (width > mLayerWidth || height > mLayerHeight) {
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
|
||||
int[] layerInfo = new int[3];
|
||||
|
||||
GLES20Canvas.nResizeLayer(mLayerId, mLayerTextureId, width, height, layerInfo);
|
||||
|
||||
mLayerWidth = layerInfo[0];
|
||||
mLayerHeight = layerInfo[1];
|
||||
|
||||
mU = mWidth / (float) mLayerWidth;
|
||||
mV = mHeight/ (float) mLayerHeight;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
HardwareCanvas getCanvas() {
|
||||
return mCanvas;
|
||||
}
|
||||
|
||||
@Override
|
||||
void end(Canvas currentCanvas) {
|
||||
if (currentCanvas instanceof GLES20Canvas) {
|
||||
((GLES20Canvas) currentCanvas).resume();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
HardwareCanvas start(Canvas currentCanvas) {
|
||||
if (currentCanvas instanceof GLES20Canvas) {
|
||||
((GLES20Canvas) currentCanvas).interrupt();
|
||||
}
|
||||
return getCanvas();
|
||||
}
|
||||
|
||||
@Override
|
||||
void destroy() {
|
||||
mFinalizer.destroy();
|
||||
mLayerId = mLayerTextureId = 0;
|
||||
}
|
||||
|
||||
private static class Finalizer {
|
||||
private int mLayerId;
|
||||
private int mLayerTextureId;
|
||||
|
||||
public Finalizer(int layerId, int layerTextureId) {
|
||||
mLayerId = layerId;
|
||||
mLayerTextureId = layerTextureId;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
try {
|
||||
if (mLayerId != 0 || mLayerTextureId != 0) {
|
||||
GLES20Canvas.nDestroyLayer(mLayerId, mLayerTextureId);
|
||||
}
|
||||
} finally {
|
||||
super.finalize();
|
||||
}
|
||||
}
|
||||
|
||||
void destroy() {
|
||||
GLES20Canvas.nDestroyLayer(mLayerId, mLayerTextureId);
|
||||
mLayerId = mLayerTextureId = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -36,7 +36,8 @@ import java.util.HashSet;
|
||||
class GLES20RecordingCanvas extends GLES20Canvas {
|
||||
// These lists ensure that any Bitmaps recorded by a DisplayList are kept alive as long
|
||||
// as the DisplayList is alive.
|
||||
private HashSet<Bitmap> mBitmaps = new HashSet<Bitmap>();
|
||||
@SuppressWarnings({"MismatchedQueryAndUpdateOfCollection"})
|
||||
private final HashSet<Bitmap> mBitmaps = new HashSet<Bitmap>();
|
||||
|
||||
GLES20RecordingCanvas(boolean translucent) {
|
||||
super(true, translucent);
|
||||
@@ -56,12 +57,6 @@ class GLES20RecordingCanvas extends GLES20Canvas {
|
||||
setupRenderer(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter,
|
||||
Paint paint) {
|
||||
super.drawArc(oval, startAngle, sweepAngle, useCenter, paint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawPatch(Bitmap bitmap, byte[] chunks, RectF dst, Paint paint) {
|
||||
super.drawPatch(bitmap, chunks, dst, paint);
|
||||
|
||||
@@ -18,6 +18,7 @@ package android.view;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
|
||||
/**
|
||||
* Hardware accelerated canvas.
|
||||
@@ -48,5 +49,18 @@ abstract class HardwareCanvas extends Canvas {
|
||||
*
|
||||
* @param displayList The display list to replay.
|
||||
*/
|
||||
public abstract void drawDisplayList(DisplayList displayList);
|
||||
abstract void drawDisplayList(DisplayList displayList);
|
||||
|
||||
/**
|
||||
* Draws the specified layer onto this canvas.
|
||||
*
|
||||
* @param left The left coordinate of the layer
|
||||
* @param top The top coordinate of the layer
|
||||
* @param right The right coordinate of the layer
|
||||
* @param bottom The bottom coordinate of the layer
|
||||
* @param layer The layer to composite on this canvas
|
||||
* @param paint The paint used to draw the layer
|
||||
*/
|
||||
abstract void drawHardwareLayer(float left, float top, float right, float bottom,
|
||||
HardwareLayer layer, Paint paint);
|
||||
}
|
||||
|
||||
115
core/java/android/view/HardwareLayer.java
Normal file
115
core/java/android/view/HardwareLayer.java
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* 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 android.view;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
|
||||
/**
|
||||
* A hardware layer can be used to render graphics operations into a hardware
|
||||
* friendly buffer. For instance, with an OpenGL backend, a hardware layer
|
||||
* would use a Frame Buffer Object (FBO.) The hardware layer can be used as
|
||||
* a drawing cache when a complex set of graphics operations needs to be
|
||||
* drawn several times.
|
||||
*/
|
||||
abstract class HardwareLayer {
|
||||
int mWidth;
|
||||
int mHeight;
|
||||
|
||||
final boolean mOpaque;
|
||||
|
||||
/**
|
||||
* Creates a new hardware layer at least as large as the supplied
|
||||
* dimensions.
|
||||
*
|
||||
* @param width The minimum width of the layer
|
||||
* @param height The minimum height of the layer
|
||||
* @param isOpaque Whether the layer should be opaque or not
|
||||
*/
|
||||
HardwareLayer(int width, int height, boolean isOpaque) {
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
mOpaque = isOpaque;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the minimum width of the layer.
|
||||
*
|
||||
* @return The minimum desired width of the hardware layer
|
||||
*/
|
||||
int getWidth() {
|
||||
return mWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the minimum height of the layer.
|
||||
*
|
||||
* @return The minimum desired height of the hardware layer
|
||||
*/
|
||||
int getHeight() {
|
||||
return mHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not this layer is opaque.
|
||||
*
|
||||
* @return True if the layer is opaque, false otherwise
|
||||
*/
|
||||
boolean isOpaque() {
|
||||
return mOpaque;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this layer can be rendered.
|
||||
*
|
||||
* @return True if the layer can be rendered into, false otherwise
|
||||
*/
|
||||
abstract boolean isValid();
|
||||
|
||||
/**
|
||||
* Resizes the layer, if necessary, to be at least as large
|
||||
* as the supplied dimensions.
|
||||
*
|
||||
* @param width The new desired minimum width for this layer
|
||||
* @param height The new desired minimum height for this layer
|
||||
*/
|
||||
abstract void resize(int width, int height);
|
||||
|
||||
/**
|
||||
* Returns a hardware canvas that can be used to render onto
|
||||
* this layer.
|
||||
*
|
||||
* @return A hardware canvas, or null if a canvas cannot be created
|
||||
*/
|
||||
abstract HardwareCanvas getCanvas();
|
||||
|
||||
/**
|
||||
* Destroys resources without waiting for a GC.
|
||||
*/
|
||||
abstract void destroy();
|
||||
|
||||
/**
|
||||
* This must be invoked before drawing onto this layer.
|
||||
* @param currentCanvas
|
||||
*/
|
||||
abstract HardwareCanvas start(Canvas currentCanvas);
|
||||
|
||||
/**
|
||||
* This must be invoked after drawing onto this layer.
|
||||
* @param currentCanvas
|
||||
*/
|
||||
abstract void end(Canvas currentCanvas);
|
||||
}
|
||||
@@ -115,6 +115,17 @@ public abstract class HardwareRenderer {
|
||||
*/
|
||||
abstract DisplayList createDisplayList();
|
||||
|
||||
/**
|
||||
* Creates a new hardware layer.
|
||||
*
|
||||
* @param width The minimum width of the layer
|
||||
* @param height The minimum height of the layer
|
||||
* @param isOpaque Whether the layer should be opaque or not
|
||||
*
|
||||
* @return A hardware layer
|
||||
*/
|
||||
abstract HardwareLayer createHardwareLayer(int width, int height, boolean isOpaque);
|
||||
|
||||
/**
|
||||
* Initializes the hardware renderer for the specified surface and setup the
|
||||
* renderer for drawing, if needed. This is invoked when the ViewRoot has
|
||||
@@ -682,6 +693,11 @@ public abstract class HardwareRenderer {
|
||||
DisplayList createDisplayList() {
|
||||
return new GLES20DisplayList();
|
||||
}
|
||||
|
||||
@Override
|
||||
HardwareLayer createHardwareLayer(int width, int height, boolean isOpaque) {
|
||||
return new GLES20Layer(width, height, isOpaque);
|
||||
}
|
||||
|
||||
static HardwareRenderer create(boolean translucent) {
|
||||
if (GLES20Canvas.isAvailable()) {
|
||||
|
||||
@@ -2049,6 +2049,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
|
||||
private Bitmap mDrawingCache;
|
||||
private Bitmap mUnscaledDrawingCache;
|
||||
private DisplayList mDisplayList;
|
||||
private HardwareLayer mHardwareLayer;
|
||||
|
||||
/**
|
||||
* When this view has focus and the next focus is {@link #FOCUS_LEFT},
|
||||
@@ -2204,6 +2205,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
|
||||
*
|
||||
* <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 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 hardware layer can
|
||||
* be used to render the view tree only once.</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>
|
||||
@@ -7551,9 +7556,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
|
||||
*/
|
||||
protected void onDetachedFromWindow() {
|
||||
mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
|
||||
|
||||
removeUnsetPressCallback();
|
||||
removeLongPressCallback();
|
||||
|
||||
destroyDrawingCache();
|
||||
|
||||
if (mHardwareLayer != null) {
|
||||
mHardwareLayer.destroy();
|
||||
mHardwareLayer = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -7868,23 +7880,36 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
|
||||
throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
|
||||
+ "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
|
||||
}
|
||||
|
||||
if (layerType == mLayerType) return;
|
||||
|
||||
// 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;
|
||||
}
|
||||
switch (mLayerType) {
|
||||
case LAYER_TYPE_SOFTWARE:
|
||||
if (mDrawingCache != null) {
|
||||
mDrawingCache.recycle();
|
||||
mDrawingCache = null;
|
||||
}
|
||||
|
||||
if (mUnscaledDrawingCache != null) {
|
||||
mUnscaledDrawingCache.recycle();
|
||||
mUnscaledDrawingCache = null;
|
||||
}
|
||||
break;
|
||||
case LAYER_TYPE_HARDWARE:
|
||||
if (mHardwareLayer != null) {
|
||||
mHardwareLayer.destroy();
|
||||
mHardwareLayer = null;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
mLayerType = layerType;
|
||||
mLayerPaint = mLayerType == LAYER_TYPE_NONE ? null : paint;
|
||||
|
||||
// TODO: Make sure we invalidate the parent's display list
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@@ -7905,6 +7930,62 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
|
||||
public int getLayerType() {
|
||||
return mLayerType;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns a hardware layer that can be used to draw this view again
|
||||
* without executing its draw method.</p>
|
||||
*
|
||||
* @return A HardwareLayer ready to render, or null if an error occurred.
|
||||
*/
|
||||
HardwareLayer getHardwareLayer(Canvas currentCanvas) {
|
||||
if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final int width = mRight - mLeft;
|
||||
final int height = mBottom - mTop;
|
||||
|
||||
if (width == 0 || height == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ((mPrivateFlags & DRAWING_CACHE_VALID) == 0 || mHardwareLayer == null) {
|
||||
if (mHardwareLayer == null) {
|
||||
mHardwareLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer(
|
||||
width, height, isOpaque());
|
||||
} else if (mHardwareLayer.getWidth() != width || mHardwareLayer.getHeight() != height) {
|
||||
mHardwareLayer.resize(width, height);
|
||||
}
|
||||
|
||||
final HardwareCanvas canvas = mHardwareLayer.start(currentCanvas);
|
||||
try {
|
||||
canvas.setViewport(width, height);
|
||||
canvas.onPreDraw();
|
||||
|
||||
computeScroll();
|
||||
canvas.translate(-mScrollX, -mScrollY);
|
||||
|
||||
final int restoreCount = canvas.save();
|
||||
|
||||
mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
|
||||
|
||||
// Fast path for layouts with no backgrounds
|
||||
if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
|
||||
mPrivateFlags &= ~DIRTY_MASK;
|
||||
dispatchDraw(canvas);
|
||||
} else {
|
||||
draw(canvas);
|
||||
}
|
||||
|
||||
canvas.restoreToCount(restoreCount);
|
||||
} finally {
|
||||
canvas.onPostDraw();
|
||||
mHardwareLayer.end(currentCanvas);
|
||||
}
|
||||
}
|
||||
|
||||
return mHardwareLayer;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
|
||||
|
||||
@@ -2179,7 +2179,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
|
||||
|
||||
boolean scalingRequired = false;
|
||||
boolean caching;
|
||||
final int layerType = child.getLayerType();
|
||||
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) {
|
||||
@@ -2278,6 +2278,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
|
||||
if (caching) {
|
||||
if (!canvas.isHardwareAccelerated()) {
|
||||
if (layerType != LAYER_TYPE_NONE) {
|
||||
layerType = LAYER_TYPE_SOFTWARE;
|
||||
child.buildDrawingCache(true);
|
||||
}
|
||||
cache = child.getDrawingCache(true);
|
||||
@@ -2354,13 +2355,11 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
|
||||
}
|
||||
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;
|
||||
}
|
||||
layerSaved = true;
|
||||
} else {
|
||||
// Alpha is handled by the child directly, clobber the layer's alpha
|
||||
if (layerType != LAYER_TYPE_NONE && child.mLayerPaint != null) {
|
||||
@@ -2388,24 +2387,35 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
|
||||
}
|
||||
|
||||
if (hasNoCache) {
|
||||
boolean layerRendered = false;
|
||||
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) {
|
||||
if (ViewDebug.TRACE_HIERARCHY) {
|
||||
ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW);
|
||||
}
|
||||
child.mPrivateFlags &= ~DIRTY_MASK;
|
||||
child.dispatchDraw(canvas);
|
||||
final HardwareLayer layer = child.getHardwareLayer(canvas);
|
||||
if (layer != null && layer.isValid()) {
|
||||
((HardwareCanvas) canvas).drawHardwareLayer(0, 0, cr - cl, cb - ct,
|
||||
layer, child.mLayerPaint);
|
||||
layerRendered = true;
|
||||
} else {
|
||||
child.draw(canvas);
|
||||
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 (!layerRendered) {
|
||||
if (!hasDisplayList) {
|
||||
// Fast path for layouts with no backgrounds
|
||||
if ((child.mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
|
||||
if (ViewDebug.TRACE_HIERARCHY) {
|
||||
ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW);
|
||||
}
|
||||
child.mPrivateFlags &= ~DIRTY_MASK;
|
||||
child.dispatchDraw(canvas);
|
||||
} else {
|
||||
child.draw(canvas);
|
||||
}
|
||||
} else {
|
||||
child.mPrivateFlags &= ~DIRTY_MASK;
|
||||
((HardwareCanvas) canvas).drawDisplayList(displayList);
|
||||
}
|
||||
} else {
|
||||
child.mPrivateFlags &= ~DIRTY_MASK;
|
||||
((HardwareCanvas) canvas).drawDisplayList(displayList);
|
||||
}
|
||||
} else if (cache != null) {
|
||||
child.mPrivateFlags &= ~DIRTY_MASK;
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <SkXfermode.h>
|
||||
|
||||
#include <DisplayListRenderer.h>
|
||||
#include <LayerRenderer.h>
|
||||
#include <OpenGLDebugRenderer.h>
|
||||
#include <OpenGLRenderer.h>
|
||||
#include <SkiaShader.h>
|
||||
@@ -77,7 +78,7 @@ static struct {
|
||||
// Constructors
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static OpenGLRenderer* android_view_GLES20Canvas_createRenderer(JNIEnv* env, jobject canvas) {
|
||||
static OpenGLRenderer* android_view_GLES20Canvas_createRenderer(JNIEnv* env, jobject clazz) {
|
||||
RENDERER_LOGD("Create OpenGLRenderer");
|
||||
#if PROFILE_RENDERER
|
||||
return new OpenGLDebugRenderer;
|
||||
@@ -442,6 +443,71 @@ static void android_view_GLES20Canvas_drawDisplayList(JNIEnv* env,
|
||||
renderer->drawDisplayList(displayList);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Layers
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static void android_view_GLES20Canvas_interrupt(JNIEnv* env, jobject canvas,
|
||||
OpenGLRenderer* renderer) {
|
||||
renderer->interrupt();
|
||||
}
|
||||
|
||||
static void android_view_GLES20Canvas_resume(JNIEnv* env, jobject canvas,
|
||||
OpenGLRenderer* renderer) {
|
||||
renderer->resume();
|
||||
}
|
||||
|
||||
static OpenGLRenderer* android_view_GLES20Canvas_createLayerRenderer(JNIEnv* env,
|
||||
jobject clazz, jint fbo) {
|
||||
return new LayerRenderer(fbo);
|
||||
}
|
||||
|
||||
static jint android_view_GLES20Canvas_createLayer(JNIEnv* env,
|
||||
jobject clazz, jint width, jint height, jintArray layerInfo) {
|
||||
uint32_t layerWidth = 0;
|
||||
uint32_t layerHeight = 0;
|
||||
GLuint textureId = 0;
|
||||
|
||||
jint layerId = LayerRenderer::createLayer(width, height,
|
||||
&layerWidth, &layerHeight, &textureId);
|
||||
|
||||
if (layerId) {
|
||||
jint* storage = env->GetIntArrayElements(layerInfo, NULL);
|
||||
storage[0] = layerWidth;
|
||||
storage[1] = layerHeight;
|
||||
storage[2] = textureId;
|
||||
env->ReleaseIntArrayElements(layerInfo, storage, 0);
|
||||
}
|
||||
|
||||
return layerId;
|
||||
}
|
||||
|
||||
static void android_view_GLES20Canvas_resizeLayer(JNIEnv* env,
|
||||
jobject clazz, jint layerId, jint layerTextureId, jint width, jint height,
|
||||
jintArray layerInfo) {
|
||||
uint32_t layerWidth = 0;
|
||||
uint32_t layerHeight = 0;
|
||||
|
||||
LayerRenderer::resizeLayer(layerId, layerTextureId, width, height, &layerWidth, &layerHeight);
|
||||
|
||||
jint* storage = env->GetIntArrayElements(layerInfo, NULL);
|
||||
storage[0] = layerWidth;
|
||||
storage[1] = layerHeight;
|
||||
env->ReleaseIntArrayElements(layerInfo, storage, 0);
|
||||
}
|
||||
|
||||
static void android_view_GLES20Canvas_destroyLayer(JNIEnv* env,
|
||||
jobject clazz, jint layerId, jint layerTextureId) {
|
||||
LayerRenderer::destroyLayer(layerId, layerTextureId);
|
||||
}
|
||||
|
||||
static void android_view_GLES20Canvas_drawLayer(JNIEnv* env,
|
||||
jobject canvas, OpenGLRenderer* renderer,
|
||||
jfloat left, jfloat top, jfloat right, jfloat bottom,
|
||||
jint layerTexture, jfloat u, jfloat v, SkPaint* paint) {
|
||||
renderer->drawLayer(layerTexture, left, top, right, bottom, u, v, paint);
|
||||
}
|
||||
|
||||
#endif // USE_OPENGL_RENDERER
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -522,10 +588,20 @@ static JNINativeMethod gMethods[] = {
|
||||
{ "nGetClipBounds", "(ILandroid/graphics/Rect;)Z",
|
||||
(void*) android_view_GLES20Canvas_getClipBounds },
|
||||
|
||||
{ "nGetDisplayList", "(I)I", (void*) android_view_GLES20Canvas_getDisplayList },
|
||||
{ "nDestroyDisplayList", "(I)V", (void*) android_view_GLES20Canvas_destroyDisplayList },
|
||||
{ "nGetDisplayListRenderer", "(I)I", (void*) android_view_GLES20Canvas_getDisplayListRenderer },
|
||||
{ "nDrawDisplayList", "(II)V", (void*) android_view_GLES20Canvas_drawDisplayList },
|
||||
{ "nGetDisplayList", "(I)I", (void*) android_view_GLES20Canvas_getDisplayList },
|
||||
{ "nDestroyDisplayList", "(I)V", (void*) android_view_GLES20Canvas_destroyDisplayList },
|
||||
{ "nGetDisplayListRenderer", "(I)I", (void*) android_view_GLES20Canvas_getDisplayListRenderer },
|
||||
{ "nDrawDisplayList", "(II)V", (void*) android_view_GLES20Canvas_drawDisplayList },
|
||||
|
||||
{ "nInterrupt", "(I)V", (void*) android_view_GLES20Canvas_interrupt },
|
||||
{ "nResume", "(I)V", (void*) android_view_GLES20Canvas_resume },
|
||||
|
||||
{ "nCreateLayerRenderer", "(I)I", (void*) android_view_GLES20Canvas_createLayerRenderer },
|
||||
{ "nCreateLayer", "(II[I)I", (void*) android_view_GLES20Canvas_createLayer },
|
||||
{ "nResizeLayer", "(IIII[I)V", (void*) android_view_GLES20Canvas_resizeLayer },
|
||||
{ "nDestroyLayer", "(II)V", (void*) android_view_GLES20Canvas_destroyLayer },
|
||||
{ "nDrawLayer", "(IFFFFIFFI)V",
|
||||
(void*) android_view_GLES20Canvas_drawLayer },
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -13,6 +13,7 @@ ifeq ($(USE_OPENGL_RENDERER),true)
|
||||
FboCache.cpp \
|
||||
GradientCache.cpp \
|
||||
LayerCache.cpp \
|
||||
LayerRenderer.cpp \
|
||||
Matrix.cpp \
|
||||
OpenGLDebugRenderer.cpp \
|
||||
OpenGLRenderer.cpp \
|
||||
|
||||
@@ -241,6 +241,11 @@ void DisplayList::replay(OpenGLRenderer& renderer) {
|
||||
renderer.drawDisplayList(getDisplayList());
|
||||
}
|
||||
break;
|
||||
case DrawLayer: {
|
||||
renderer.drawLayer(getInt(), getFloat(), getFloat(), getFloat(), getFloat(),
|
||||
getFloat(), getFloat(), getPaint());
|
||||
}
|
||||
break;
|
||||
case DrawBitmap: {
|
||||
renderer.drawBitmap(getBitmap(), getFloat(), getFloat(), getPaint());
|
||||
}
|
||||
@@ -483,6 +488,16 @@ void DisplayListRenderer::drawDisplayList(DisplayList* displayList) {
|
||||
addDisplayList(displayList);
|
||||
}
|
||||
|
||||
void DisplayListRenderer::drawLayer(int texture, float left, float top, float right, float bottom,
|
||||
float u, float v, SkPaint* paint) {
|
||||
addOp(DisplayList::DrawLayer);
|
||||
addInt(texture);
|
||||
addBounds(left, top, right, bottom);
|
||||
addFloat(u);
|
||||
addFloat(v);
|
||||
addPaint(paint);
|
||||
}
|
||||
|
||||
void DisplayListRenderer::drawBitmap(SkBitmap* bitmap, float left, float top,
|
||||
SkPaint* paint) {
|
||||
addOp(DisplayList::DrawBitmap);
|
||||
|
||||
@@ -93,6 +93,7 @@ public:
|
||||
ConcatMatrix,
|
||||
ClipRect,
|
||||
DrawDisplayList,
|
||||
DrawLayer,
|
||||
DrawBitmap,
|
||||
DrawBitmapMatrix,
|
||||
DrawBitmapRect,
|
||||
@@ -245,6 +246,8 @@ public:
|
||||
bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
|
||||
|
||||
void drawDisplayList(DisplayList* displayList);
|
||||
void drawLayer(int texture, float left, float top, float right, float bottom,
|
||||
float u, float v, SkPaint* paint);
|
||||
void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
|
||||
void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
|
||||
void drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
|
||||
|
||||
121
libs/hwui/LayerRenderer.cpp
Normal file
121
libs/hwui/LayerRenderer.cpp
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "OpenGLRenderer"
|
||||
|
||||
#include "LayerRenderer.h"
|
||||
|
||||
namespace android {
|
||||
namespace uirenderer {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Rendering
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void LayerRenderer::prepare(bool opaque) {
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &mPreviousFbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mFbo);
|
||||
OpenGLRenderer::prepare(opaque);
|
||||
}
|
||||
|
||||
void LayerRenderer::finish() {
|
||||
OpenGLRenderer::finish();
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mPreviousFbo);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Static functions
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GLuint LayerRenderer::createLayer(uint32_t width, uint32_t height,
|
||||
uint32_t* layerWidth, uint32_t* layerHeight, GLuint* texture) {
|
||||
GLuint previousFbo;
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &previousFbo);
|
||||
|
||||
GLuint fbo = 0;
|
||||
glGenFramebuffers(1, &fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glGenTextures(1, texture);
|
||||
glBindTexture(GL_TEXTURE_2D, *texture);
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
|
||||
if (glGetError() != GL_NO_ERROR) {
|
||||
glDeleteBuffers(1, &fbo);
|
||||
glDeleteTextures(1, texture);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
|
||||
return 0;
|
||||
}
|
||||
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
|
||||
*texture, 0);
|
||||
|
||||
if (glGetError() != GL_NO_ERROR) {
|
||||
glDeleteBuffers(1, &fbo);
|
||||
glDeleteTextures(1, texture);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
|
||||
return 0;
|
||||
}
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
|
||||
|
||||
*layerWidth = width;
|
||||
*layerHeight = height;
|
||||
|
||||
return fbo;
|
||||
}
|
||||
|
||||
void LayerRenderer::resizeLayer(GLuint fbo, GLuint texture, uint32_t width, uint32_t height,
|
||||
uint32_t* layerWidth, uint32_t* layerHeight) {
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
|
||||
if (glGetError() != GL_NO_ERROR) {
|
||||
glDeleteBuffers(1, &fbo);
|
||||
glDeleteTextures(1, texture);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
|
||||
|
||||
*layerWidth = 0;
|
||||
*layerHeight = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
*layerWidth = width;
|
||||
*layerHeight = height;
|
||||
}
|
||||
|
||||
void LayerRenderer::destroyLayer(GLuint fbo, GLuint texture) {
|
||||
if (fbo) glDeleteFramebuffers(1, &fbo);
|
||||
if (texture) glDeleteTextures(1, &texture);
|
||||
}
|
||||
|
||||
}; // namespace uirenderer
|
||||
}; // namespace android
|
||||
55
libs/hwui/LayerRenderer.h
Normal file
55
libs/hwui/LayerRenderer.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef ANDROID_HWUI_LAYER_RENDERER_H
|
||||
#define ANDROID_HWUI_LAYER_RENDERER_H
|
||||
|
||||
#include "OpenGLRenderer.h"
|
||||
|
||||
namespace android {
|
||||
namespace uirenderer {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Renderer
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class LayerRenderer: public OpenGLRenderer {
|
||||
public:
|
||||
LayerRenderer(GLuint fbo): mFbo(fbo) {
|
||||
}
|
||||
|
||||
~LayerRenderer() {
|
||||
}
|
||||
|
||||
void prepare(bool opaque);
|
||||
void finish();
|
||||
|
||||
static GLuint createLayer(uint32_t width, uint32_t height,
|
||||
uint32_t* layerWidth, uint32_t* layerHeight, GLuint* texture);
|
||||
static void resizeLayer(GLuint fbo, GLuint texture, uint32_t width, uint32_t height,
|
||||
uint32_t* layerWidth, uint32_t* layerHeight);
|
||||
static void destroyLayer(GLuint fbo, GLuint texture);
|
||||
|
||||
private:
|
||||
GLuint mFbo;
|
||||
GLuint mPreviousFbo;
|
||||
|
||||
}; // class LayerRenderer
|
||||
|
||||
}; // namespace uirenderer
|
||||
}; // namespace android
|
||||
|
||||
#endif // ANDROID_HWUI_LAYER_RENDERER_H
|
||||
@@ -178,7 +178,7 @@ void OpenGLRenderer::finish() {
|
||||
#endif
|
||||
}
|
||||
|
||||
void OpenGLRenderer::acquireContext() {
|
||||
void OpenGLRenderer::interrupt() {
|
||||
if (mCaches.currentProgram) {
|
||||
if (mCaches.currentProgram->isInUse()) {
|
||||
mCaches.currentProgram->remove();
|
||||
@@ -188,7 +188,11 @@ void OpenGLRenderer::acquireContext() {
|
||||
mCaches.unbindMeshBuffer();
|
||||
}
|
||||
|
||||
void OpenGLRenderer::releaseContext() {
|
||||
void OpenGLRenderer::acquireContext() {
|
||||
interrupt();
|
||||
}
|
||||
|
||||
void OpenGLRenderer::resume() {
|
||||
glViewport(0, 0, mSnapshot->viewport.getWidth(), mSnapshot->viewport.getHeight());
|
||||
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
@@ -205,6 +209,10 @@ void OpenGLRenderer::releaseContext() {
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::releaseContext() {
|
||||
resume();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// State management
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@@ -1477,6 +1485,30 @@ void OpenGLRenderer::drawPath(SkPath* path, SkPaint* paint) {
|
||||
finishDrawTexture();
|
||||
}
|
||||
|
||||
void OpenGLRenderer::drawLayer(int texture, float left, float top, float right, float bottom,
|
||||
float u, float v, SkPaint* paint) {
|
||||
if (quickReject(left, top, right, bottom)) {
|
||||
return;
|
||||
}
|
||||
|
||||
glActiveTexture(gTextureUnits[0]);
|
||||
if (!texture) return;
|
||||
|
||||
mCaches.unbindMeshBuffer();
|
||||
resetDrawTextureTexCoords(0.0f, v, u, 0.0f);
|
||||
|
||||
int alpha;
|
||||
SkXfermode::Mode mode;
|
||||
getAlphaAndMode(paint, &alpha, &mode);
|
||||
|
||||
// TODO: Should get the blend info from the caller
|
||||
drawTextureMesh(left, top, right, bottom, texture, alpha / 255.0f, mode, true,
|
||||
&mMeshVertices[0].position[0], &mMeshVertices[0].texture[0],
|
||||
GL_TRIANGLE_STRIP, gMeshCount);
|
||||
|
||||
resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Shaders
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -64,6 +64,10 @@ public:
|
||||
virtual void prepare(bool opaque);
|
||||
virtual void finish();
|
||||
|
||||
// These two calls must not be recorded in display lists
|
||||
void interrupt();
|
||||
void resume();
|
||||
|
||||
virtual void acquireContext();
|
||||
virtual void releaseContext();
|
||||
|
||||
@@ -91,6 +95,8 @@ public:
|
||||
virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
|
||||
|
||||
virtual void drawDisplayList(DisplayList* displayList);
|
||||
virtual void drawLayer(int texture, float left, float top, float right, float bottom,
|
||||
float u, float v, SkPaint* paint);
|
||||
virtual void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
|
||||
virtual void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
|
||||
virtual void drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
|
||||
|
||||
@@ -33,6 +33,15 @@
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name="ViewLayersActivity2"
|
||||
android:label="_ViewLayers2">
|
||||
<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">
|
||||
|
||||
@@ -69,7 +69,7 @@ public class PathsActivity extends Activity {
|
||||
|
||||
mMediumPaint = new Paint();
|
||||
mMediumPaint.setAntiAlias(true);
|
||||
mMediumPaint.setColor(0xff0000ff);
|
||||
mMediumPaint.setColor(0xe00000ff);
|
||||
mMediumPaint.setStrokeWidth(10.0f);
|
||||
mMediumPaint.setStyle(Paint.Style.STROKE);
|
||||
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* 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.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
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 ViewLayersActivity2 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);
|
||||
}
|
||||
|
||||
private void setupList(int listId) {
|
||||
final ListView list = (ListView) findViewById(listId);
|
||||
list.setAdapter(new SimpleListAdapter(this));
|
||||
list.setLayerType(View.LAYER_TYPE_HARDWARE, null);
|
||||
}
|
||||
|
||||
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"
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user