diff options
author | Romain Guy <romainguy@google.com> | 2011-11-10 19:23:58 -0800 |
---|---|---|
committer | Romain Guy <romainguy@google.com> | 2011-12-06 16:37:10 -0800 |
commit | 9c4b79af221b53f602f946faa9ff317a596a0c39 (patch) | |
tree | 134a3a19b685c55dc23a08ae8929fb292333f768 | |
parent | e98ae0a050d6ce4b3e2aec7c070a87922086c256 (diff) | |
download | frameworks_base-9c4b79af221b53f602f946faa9ff317a596a0c39.zip frameworks_base-9c4b79af221b53f602f946faa9ff317a596a0c39.tar.gz frameworks_base-9c4b79af221b53f602f946faa9ff317a596a0c39.tar.bz2 |
Discard framebuffer rendering queues when discarding layers
Bug #5581817
Change-Id: Ie30700a29059d2ea60eb7bd3f8bd20ac48a149ab
-rw-r--r-- | core/java/android/view/GLES20Canvas.java | 1 | ||||
-rw-r--r-- | core/java/android/view/GLES20Layer.java | 7 | ||||
-rw-r--r-- | core/java/android/view/HardwareLayer.java | 5 | ||||
-rw-r--r-- | core/java/android/view/View.java | 22 | ||||
-rw-r--r-- | core/java/android/view/ViewGroup.java | 12 | ||||
-rw-r--r-- | core/jni/android_view_GLES20Canvas.cpp | 5 | ||||
-rw-r--r-- | libs/hwui/Android.mk | 2 | ||||
-rw-r--r-- | libs/hwui/Extensions.h | 3 | ||||
-rw-r--r-- | libs/hwui/LayerRenderer.cpp | 26 | ||||
-rw-r--r-- | libs/hwui/LayerRenderer.h | 1 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 5 |
11 files changed, 81 insertions, 8 deletions
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java index aa0bfd2..43a451d 100644 --- a/core/java/android/view/GLES20Canvas.java +++ b/core/java/android/view/GLES20Canvas.java @@ -154,6 +154,7 @@ class GLES20Canvas extends HardwareCanvas { static native void nSetTextureLayerTransform(int layerId, int matrix); static native void nDestroyLayer(int layerId); static native void nDestroyLayerDeferred(int layerId); + static native void nFlushLayer(int layerId); static native boolean nCopyLayer(int layerId, int bitmap); /////////////////////////////////////////////////////////////////////////// diff --git a/core/java/android/view/GLES20Layer.java b/core/java/android/view/GLES20Layer.java index fd3b9e5..4f25792 100644 --- a/core/java/android/view/GLES20Layer.java +++ b/core/java/android/view/GLES20Layer.java @@ -60,6 +60,13 @@ abstract class GLES20Layer extends HardwareLayer { } mLayer = 0; } + + @Override + void flush() { + if (mLayer != 0) { + GLES20Canvas.nFlushLayer(mLayer); + } + } static class Finalizer { private int mLayerId; diff --git a/core/java/android/view/HardwareLayer.java b/core/java/android/view/HardwareLayer.java index 28389ab..d5666f3 100644 --- a/core/java/android/view/HardwareLayer.java +++ b/core/java/android/view/HardwareLayer.java @@ -116,6 +116,11 @@ abstract class HardwareLayer { abstract void destroy(); /** + * Flush the render queue associated with this layer. + */ + abstract void flush(); + + /** * This must be invoked before drawing onto this layer. * @param currentCanvas */ diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 304a9a1..af8f8cb 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -10207,6 +10207,13 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal break; } } + + // Make sure the HardwareRenderer.validate() was invoked before calling this method + void flushLayer() { + if (mLayerType == LAYER_TYPE_HARDWARE && mHardwareLayer != null) { + mHardwareLayer.flush(); + } + } /** * <p>Returns a hardware layer that can be used to draw this view again @@ -10219,6 +10226,8 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal !mAttachInfo.mHardwareRenderer.isEnabled()) { return null; } + + if (!mAttachInfo.mHardwareRenderer.validate()) return null; final int width = mRight - mLeft; final int height = mBottom - mTop; @@ -10293,12 +10302,15 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal */ boolean destroyLayer() { if (mHardwareLayer != null) { - mHardwareLayer.destroy(); - mHardwareLayer = null; - - invalidate(true); - invalidateParentCaches(); + AttachInfo info = mAttachInfo; + if (info != null && info.mHardwareRenderer != null && + info.mHardwareRenderer.isEnabled() && info.mHardwareRenderer.validate()) { + mHardwareLayer.destroy(); + mHardwareLayer = null; + invalidate(true); + invalidateParentCaches(); + } return true; } return false; diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index 2a041f7..5035cae 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -2958,6 +2958,17 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager mDrawLayers = enabled; invalidate(true); + boolean flushLayers = !enabled; + AttachInfo info = mAttachInfo; + if (info != null && info.mHardwareRenderer != null && + info.mHardwareRenderer.isEnabled()) { + if (!info.mHardwareRenderer.validate()) { + flushLayers = false; + } + } else { + flushLayers = false; + } + // We need to invalidate any child with a layer. For instance, // if a child is backed by a hardware layer and we disable layers // the child is marked as not dirty (flags cleared the last time @@ -2968,6 +2979,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager for (int i = 0; i < mChildrenCount; i++) { View child = mChildren[i]; if (child.mLayerType != LAYER_TYPE_NONE) { + if (flushLayers) child.flushLayer(); child.invalidate(true); } } diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp index 426f4f7..9c7b108 100644 --- a/core/jni/android_view_GLES20Canvas.cpp +++ b/core/jni/android_view_GLES20Canvas.cpp @@ -719,6 +719,10 @@ static void android_view_GLES20Canvas_destroyLayerDeferred(JNIEnv* env, LayerRenderer::destroyLayerDeferred(layer); } +static void android_view_GLES20Canvas_flushLayer(JNIEnv* env, jobject clazz, Layer* layer) { + LayerRenderer::flushLayer(layer); +} + static void android_view_GLES20Canvas_drawLayer(JNIEnv* env, jobject clazz, OpenGLRenderer* renderer, Layer* layer, jfloat x, jfloat y, SkPaint* paint) { renderer->drawLayer(layer, x, y, paint); @@ -869,6 +873,7 @@ static JNINativeMethod gMethods[] = { { "nSetTextureLayerTransform", "(II)V", (void*) android_view_GLES20Canvas_setTextureLayerTransform }, { "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 }, diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk index 9bfc94c..95e0a18 100644 --- a/libs/hwui/Android.mk +++ b/libs/hwui/Android.mk @@ -38,7 +38,7 @@ ifeq ($(USE_OPENGL_RENDERER),true) external/skia/src/ports \ external/skia/include/utils - LOCAL_CFLAGS += -DUSE_OPENGL_RENDERER + LOCAL_CFLAGS += -DUSE_OPENGL_RENDERER -DGL_GLEXT_PROTOTYPES LOCAL_CFLAGS += -fvisibility=hidden LOCAL_MODULE_CLASS := SHARED_LIBRARIES LOCAL_SHARED_LIBRARIES := libcutils libutils libGLESv2 libskia libui diff --git a/libs/hwui/Extensions.h b/libs/hwui/Extensions.h index 38d1130..48e4247 100644 --- a/libs/hwui/Extensions.h +++ b/libs/hwui/Extensions.h @@ -66,6 +66,7 @@ public: mHasNPot = hasExtension("GL_OES_texture_npot"); mHasFramebufferFetch = hasExtension("GL_NV_shader_framebuffer_fetch"); + mHasDiscardFramebuffer = hasExtension("GL_EXT_discard_framebuffer"); const char* vendor = (const char*) glGetString(GL_VENDOR); EXT_LOGD("Vendor: %s", vendor); @@ -80,6 +81,7 @@ public: inline bool hasNPot() const { return mHasNPot; } inline bool hasFramebufferFetch() const { return mHasFramebufferFetch; } inline bool needsHighpTexCoords() const { return mNeedsHighpTexCoords; } + inline bool hasDiscardFramebuffer() const { return mHasDiscardFramebuffer; } bool hasExtension(const char* extension) const { const String8 s(extension); @@ -98,6 +100,7 @@ private: bool mHasNPot; bool mNeedsHighpTexCoords; bool mHasFramebufferFetch; + bool mHasDiscardFramebuffer; }; // class Extensions }; // namespace uirenderer diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp index 6bf6004..e2d9ea3 100644 --- a/libs/hwui/LayerRenderer.cpp +++ b/libs/hwui/LayerRenderer.cpp @@ -305,8 +305,10 @@ void LayerRenderer::destroyLayer(Layer* layer) { LAYER_RENDERER_LOGD("Recycling layer, %dx%d fbo = %d", layer->getWidth(), layer->getHeight(), layer->getFbo()); - if (layer->getFbo()) { - Caches::getInstance().fboCache.put(layer->getFbo()); + GLuint fbo = layer->getFbo(); + if (fbo) { + flushLayer(layer); + Caches::getInstance().fboCache.put(fbo); } if (!Caches::getInstance().layerCache.put(layer)) { @@ -331,6 +333,26 @@ void LayerRenderer::destroyLayerDeferred(Layer* layer) { } } +void LayerRenderer::flushLayer(Layer* layer) { +#ifdef GL_EXT_discard_framebuffer + GLuint fbo = layer->getFbo(); + if (layer && fbo) { + // If possible, discard any enqueud operations on deferred + // rendering architectures + if (Caches::getInstance().extensions.hasDiscardFramebuffer()) { + GLuint previousFbo; + glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &previousFbo); + + GLenum attachments = GL_COLOR_ATTACHMENT0; + if (fbo != previousFbo) glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, &attachments); + + if (fbo != previousFbo) glBindFramebuffer(GL_FRAMEBUFFER, previousFbo); + } + } +#endif +} + bool LayerRenderer::copyLayer(Layer* layer, SkBitmap* bitmap) { Caches& caches = Caches::getInstance(); if (layer && layer->isTextureLayer() && bitmap->width() <= caches.maxTextureSize && diff --git a/libs/hwui/LayerRenderer.h b/libs/hwui/LayerRenderer.h index 6104301..72d8d81 100644 --- a/libs/hwui/LayerRenderer.h +++ b/libs/hwui/LayerRenderer.h @@ -61,6 +61,7 @@ public: bool isOpaque, GLenum renderTarget, float* transform); ANDROID_API static void destroyLayer(Layer* layer); ANDROID_API static void destroyLayerDeferred(Layer* layer); + ANDROID_API static void flushLayer(Layer* layer); ANDROID_API static bool copyLayer(Layer* layer, SkBitmap* bitmap); private: diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 81c053e..1d7b99d 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -615,6 +615,11 @@ void OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) { } if (fboLayer) { + // Note: No need to use glDiscardFramebufferEXT() since we never + // create/compose layers that are not on screen with this + // code path + // See LayerRenderer::destroyLayer(Layer*) + // Detach the texture from the FBO glBindFramebuffer(GL_FRAMEBUFFER, current->fbo); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); |