summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRomain Guy <romainguy@google.com>2012-03-02 13:37:47 -0800
committerRomain Guy <romainguy@google.com>2012-03-02 13:37:47 -0800
commit2bf68f063b0077ddef6ebfe54f2ae5e063c2c229 (patch)
treeda02b6113cb29371fb1e7321ffaf567bdf0fca8a
parentd8f45c16a896d76d06550a91d78e8c5a3a57275a (diff)
downloadframeworks_base-2bf68f063b0077ddef6ebfe54f2ae5e063c2c229.zip
frameworks_base-2bf68f063b0077ddef6ebfe54f2ae5e063c2c229.tar.gz
frameworks_base-2bf68f063b0077ddef6ebfe54f2ae5e063c2c229.tar.bz2
Deferred layer updates
Change-Id: I83d9e564fe274db658dcee9e0cc5bbf9223ebb49
-rw-r--r--core/java/android/view/GLES20Canvas.java9
-rw-r--r--core/java/android/view/GLES20RenderLayer.java8
-rw-r--r--core/java/android/view/GLES20TextureLayer.java5
-rw-r--r--core/java/android/view/HardwareLayer.java10
-rw-r--r--core/java/android/view/TextureView.java2
-rw-r--r--core/java/android/view/View.java65
-rw-r--r--core/jni/android_view_GLES20Canvas.cpp10
-rw-r--r--libs/hwui/Layer.h24
-rw-r--r--libs/hwui/OpenGLRenderer.cpp18
9 files changed, 112 insertions, 39 deletions
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index ee0fa86..1f75e70 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -157,6 +157,8 @@ class GLES20Canvas extends HardwareCanvas {
static native void nDestroyLayer(int layerId);
static native void nDestroyLayerDeferred(int layerId);
static native void nFlushLayer(int layerId);
+ static native void nUpdateRenderLayer(int layerId, int renderer, int displayList,
+ int left, int top, int right, int bottom);
static native boolean nCopyLayer(int layerId, int bitmap);
///////////////////////////////////////////////////////////////////////////
@@ -191,6 +193,13 @@ class GLES20Canvas extends HardwareCanvas {
private static native int nGetMaximumTextureWidth();
private static native int nGetMaximumTextureHeight();
+ /**
+ * Returns the native OpenGLRenderer object.
+ */
+ int getRenderer() {
+ return mRenderer;
+ }
+
///////////////////////////////////////////////////////////////////////////
// Setup
///////////////////////////////////////////////////////////////////////////
diff --git a/core/java/android/view/GLES20RenderLayer.java b/core/java/android/view/GLES20RenderLayer.java
index 23a7166..c727a36 100644
--- a/core/java/android/view/GLES20RenderLayer.java
+++ b/core/java/android/view/GLES20RenderLayer.java
@@ -18,6 +18,7 @@ package android.view;
import android.graphics.Canvas;
import android.graphics.Matrix;
+import android.graphics.Rect;
/**
* An OpenGL ES 2.0 implementation of {@link HardwareLayer}. This
@@ -95,4 +96,11 @@ class GLES20RenderLayer extends GLES20Layer {
@Override
void setTransform(Matrix matrix) {
}
+
+ @Override
+ void redraw(DisplayList displayList, Rect dirtyRect) {
+ GLES20Canvas.nUpdateRenderLayer(mLayer, mCanvas.getRenderer(),
+ ((GLES20DisplayList) displayList).getNativeDisplayList(),
+ dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom);
+ }
}
diff --git a/core/java/android/view/GLES20TextureLayer.java b/core/java/android/view/GLES20TextureLayer.java
index 6c41023..cbb908b 100644
--- a/core/java/android/view/GLES20TextureLayer.java
+++ b/core/java/android/view/GLES20TextureLayer.java
@@ -18,6 +18,7 @@ package android.view;
import android.graphics.Canvas;
import android.graphics.Matrix;
+import android.graphics.Rect;
import android.graphics.SurfaceTexture;
/**
@@ -81,4 +82,8 @@ class GLES20TextureLayer extends GLES20Layer {
void setTransform(Matrix matrix) {
GLES20Canvas.nSetTextureLayerTransform(mLayer, matrix.native_instance);
}
+
+ @Override
+ void redraw(DisplayList displayList, Rect dirtyRect) {
+ }
}
diff --git a/core/java/android/view/HardwareLayer.java b/core/java/android/view/HardwareLayer.java
index d5666f3..49450bd 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.Rect;
/**
* A hardware layer can be used to render graphics operations into a hardware
@@ -163,4 +164,13 @@ abstract class HardwareLayer {
* @param matrix The transform to apply to the layer.
*/
abstract void setTransform(Matrix matrix);
+
+ /**
+ * Specifies the display list to use to refresh the layer.
+ *
+ * @param displayList The display list containing the drawing commands to
+ * execute in this layer
+ * @param dirtyRect The dirty region of the layer that needs to be redrawn
+ */
+ abstract void redraw(DisplayList displayList, Rect dirtyRect);
}
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index 74916f0..865f9d2 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -315,7 +315,7 @@ public class TextureView extends View {
}
@Override
- HardwareLayer getHardwareLayer() {
+ HardwareLayer getHardwareLayer(boolean immediateRefresh) {
if (mLayer == null) {
if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null) {
return null;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 5cf0459..294c31d 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -10125,7 +10125,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* dynamic.
*/
boolean hasStaticLayer() {
- return mLayerType == LAYER_TYPE_NONE;
+ return true;
}
/**
@@ -10172,7 +10172,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
if (mAttachInfo.mHardwareRenderer != null &&
mAttachInfo.mHardwareRenderer.isEnabled() &&
mAttachInfo.mHardwareRenderer.validate()) {
- getHardwareLayer();
+ getHardwareLayer(true);
}
break;
case LAYER_TYPE_SOFTWARE:
@@ -10194,7 +10194,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
*
* @return A HardwareLayer ready to render, or null if an error occurred.
*/
- HardwareLayer getHardwareLayer() {
+ HardwareLayer getHardwareLayer(boolean immediateRefresh) {
if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null ||
!mAttachInfo.mHardwareRenderer.isEnabled()) {
return null;
@@ -10224,41 +10224,32 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
return null;
}
- HardwareCanvas currentCanvas = mAttachInfo.mHardwareCanvas;
- final HardwareCanvas canvas = mHardwareLayer.start(currentCanvas);
-
- // Make sure all the GPU resources have been properly allocated
- if (canvas == null) {
- mHardwareLayer.end(currentCanvas);
- return null;
- }
-
- mAttachInfo.mHardwareCanvas = canvas;
- try {
- canvas.setViewport(width, height);
- canvas.onPreDraw(mLocalDirtyRect);
+ if (!immediateRefresh) {
+ mHardwareLayer.redraw(getDisplayList(), mLocalDirtyRect);
mLocalDirtyRect.setEmpty();
-
- final int restoreCount = canvas.save();
-
- computeScroll();
- canvas.translate(-mScrollX, -mScrollY);
-
- 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);
+ } else {
+ HardwareCanvas currentCanvas = mAttachInfo.mHardwareCanvas;
+ final HardwareCanvas canvas = mHardwareLayer.start(currentCanvas);
+
+ // Make sure all the GPU resources have been properly allocated
+ if (canvas == null) {
+ mHardwareLayer.end(currentCanvas);
+ return null;
+ }
+
+ mAttachInfo.mHardwareCanvas = canvas;
+ try {
+ canvas.setViewport(width, height);
+ canvas.onPreDraw(mLocalDirtyRect);
+ mLocalDirtyRect.setEmpty();
+
+ canvas.drawDisplayList(getDisplayList(), mRight - mLeft, mBottom - mTop, null,
+ DisplayList.FLAG_CLIP_CHILDREN);
+ } finally {
+ canvas.onPostDraw();
+ mHardwareLayer.end(currentCanvas);
+ mAttachInfo.mHardwareCanvas = currentCanvas;
}
-
- canvas.restoreToCount(restoreCount);
- } finally {
- canvas.onPostDraw();
- mHardwareLayer.end(currentCanvas);
- mAttachInfo.mHardwareCanvas = currentCanvas;
}
}
@@ -11226,7 +11217,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
if (hasNoCache) {
boolean layerRendered = false;
if (layerType == LAYER_TYPE_HARDWARE) {
- final HardwareLayer layer = getHardwareLayer();
+ final HardwareLayer layer = getHardwareLayer(false);
if (layer != null && layer.isValid()) {
mLayerPaint.setAlpha((int) (alpha * 255));
((HardwareCanvas) canvas).drawHardwareLayer(layer, 0, 0, mLayerPaint);
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index f0560c1..77a6e52 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -770,6 +770,12 @@ static void android_view_GLES20Canvas_updateTextureLayer(JNIEnv* env, jobject cl
LayerRenderer::updateTextureLayer(layer, width, height, isOpaque, renderTarget, transform);
}
+static void android_view_GLES20Canvas_updateRenderLayer(JNIEnv* env, jobject clazz,
+ Layer* layer, OpenGLRenderer* renderer, DisplayList* displayList,
+ jint left, jint top, jint right, jint bottom) {
+ layer->updateDeferred(renderer, displayList, left, top, right, bottom);
+}
+
static void android_view_GLES20Canvas_setTextureLayerTransform(JNIEnv* env, jobject clazz,
Layer* layer, SkMatrix* matrix) {
@@ -953,13 +959,15 @@ static JNINativeMethod gMethods[] = {
{ "nCreateTextureLayer", "(Z[I)I", (void*) android_view_GLES20Canvas_createTextureLayer },
{ "nUpdateTextureLayer", "(IIIZLandroid/graphics/SurfaceTexture;)V",
(void*) android_view_GLES20Canvas_updateTextureLayer },
- { "nSetTextureLayerTransform", "(II)V", (void*) android_view_GLES20Canvas_setTextureLayerTransform },
+ { "nUpdateRenderLayer", "(IIIIIII)V", (void*) android_view_GLES20Canvas_updateRenderLayer },
{ "nDestroyLayer", "(I)V", (void*) android_view_GLES20Canvas_destroyLayer },
{ "nDestroyLayerDeferred", "(I)V", (void*) android_view_GLES20Canvas_destroyLayerDeferred },
{ "nFlushLayer", "(I)V", (void*) android_view_GLES20Canvas_flushLayer },
{ "nDrawLayer", "(IIFFI)V", (void*) android_view_GLES20Canvas_drawLayer },
{ "nCopyLayer", "(II)Z", (void*) android_view_GLES20Canvas_copyLayer },
+ { "nSetTextureLayerTransform", "(II)V", (void*) android_view_GLES20Canvas_setTextureLayerTransform },
+
{ "nGetMaximumTextureWidth", "()I", (void*) android_view_GLES20Canvas_getMaxTextureWidth },
{ "nGetMaximumTextureHeight", "()I", (void*) android_view_GLES20Canvas_getMaxTextureHeight },
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index ee6ef1a..f243177 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -37,6 +37,10 @@ namespace uirenderer {
// Layers
///////////////////////////////////////////////////////////////////////////////
+// Forward declarations
+class OpenGLRenderer;
+class DisplayList;
+
/**
* A layer has dimensions and is backed by an OpenGL texture or FBO.
*/
@@ -51,6 +55,9 @@ struct Layer {
texture.width = layerWidth;
texture.height = layerHeight;
colorFilter = NULL;
+ deferredUpdateScheduled = false;
+ renderer = NULL;
+ displayList = NULL;
}
~Layer() {
@@ -77,6 +84,15 @@ struct Layer {
regionRect.translate(layer.left, layer.top);
}
+ void updateDeferred(OpenGLRenderer* renderer, DisplayList* displayList,
+ int left, int top, int right, int bottom) {
+ this->renderer = renderer;
+ this->displayList = displayList;
+ const Rect r(left, top, right, bottom);
+ dirtyRect.unionWith(r);
+ deferredUpdateScheduled = true;
+ }
+
inline uint32_t getWidth() {
return texture.width;
}
@@ -234,6 +250,14 @@ struct Layer {
uint16_t* meshIndices;
GLsizei meshElementCount;
+ /**
+ * Used for deferred updates.
+ */
+ bool deferredUpdateScheduled;
+ OpenGLRenderer* renderer;
+ DisplayList* displayList;
+ Rect dirtyRect;
+
private:
/**
* Name of the FBO used to render the layer. If the name is 0
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index e3148e8..339ae0a 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -2364,6 +2364,24 @@ void OpenGLRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* paint) {
return;
}
+ if (layer->deferredUpdateScheduled && layer->renderer && layer->displayList) {
+ OpenGLRenderer* renderer = layer->renderer;
+ Rect& dirty = layer->dirtyRect;
+
+ interrupt();
+ renderer->setViewport(layer->layer.getWidth(), layer->layer.getHeight());
+ renderer->prepareDirty(dirty.left, dirty.top, dirty.right, dirty.bottom, !layer->isBlend());
+ renderer->drawDisplayList(layer->displayList, layer->getWidth(), layer->getHeight(),
+ dirty, DisplayList::kReplayFlag_ClipChildren);
+ renderer->finish();
+ resume();
+
+ dirty.setEmpty();
+ layer->deferredUpdateScheduled = false;
+ layer->renderer = NULL;
+ layer->displayList = NULL;
+ }
+
mCaches.activeTexture(0);
int alpha;