diff options
author | Romain Guy <romainguy@google.com> | 2012-03-02 13:37:47 -0800 |
---|---|---|
committer | Romain Guy <romainguy@google.com> | 2012-03-02 13:37:47 -0800 |
commit | 2bf68f063b0077ddef6ebfe54f2ae5e063c2c229 (patch) | |
tree | da02b6113cb29371fb1e7321ffaf567bdf0fca8a | |
parent | d8f45c16a896d76d06550a91d78e8c5a3a57275a (diff) | |
download | frameworks_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.java | 9 | ||||
-rw-r--r-- | core/java/android/view/GLES20RenderLayer.java | 8 | ||||
-rw-r--r-- | core/java/android/view/GLES20TextureLayer.java | 5 | ||||
-rw-r--r-- | core/java/android/view/HardwareLayer.java | 10 | ||||
-rw-r--r-- | core/java/android/view/TextureView.java | 2 | ||||
-rw-r--r-- | core/java/android/view/View.java | 65 | ||||
-rw-r--r-- | core/jni/android_view_GLES20Canvas.cpp | 10 | ||||
-rw-r--r-- | libs/hwui/Layer.h | 24 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 18 |
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; |