summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRomain Guy <romainguy@google.com>2011-11-10 19:23:58 -0800
committerRomain Guy <romainguy@google.com>2011-12-06 16:37:10 -0800
commit9c4b79af221b53f602f946faa9ff317a596a0c39 (patch)
tree134a3a19b685c55dc23a08ae8929fb292333f768
parente98ae0a050d6ce4b3e2aec7c070a87922086c256 (diff)
downloadframeworks_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.java1
-rw-r--r--core/java/android/view/GLES20Layer.java7
-rw-r--r--core/java/android/view/HardwareLayer.java5
-rw-r--r--core/java/android/view/View.java22
-rw-r--r--core/java/android/view/ViewGroup.java12
-rw-r--r--core/jni/android_view_GLES20Canvas.cpp5
-rw-r--r--libs/hwui/Android.mk2
-rw-r--r--libs/hwui/Extensions.h3
-rw-r--r--libs/hwui/LayerRenderer.cpp26
-rw-r--r--libs/hwui/LayerRenderer.h1
-rw-r--r--libs/hwui/OpenGLRenderer.cpp5
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);