Skip to content

Commit bdfe770

Browse files
Romain GuyAndroid (Google) Code Review
authored andcommitted
Merge "Discard framebuffer rendering queues when discarding layers Bug #5581817"
2 parents b42d5e2 + 9c4b79a commit bdfe770

File tree

11 files changed

+81
-8
lines changed

11 files changed

+81
-8
lines changed

core/java/android/view/GLES20Canvas.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ static native void nUpdateTextureLayer(int layerId, int width, int height, boole
154154
static native void nSetTextureLayerTransform(int layerId, int matrix);
155155
static native void nDestroyLayer(int layerId);
156156
static native void nDestroyLayerDeferred(int layerId);
157+
static native void nFlushLayer(int layerId);
157158
static native boolean nCopyLayer(int layerId, int bitmap);
158159

159160
///////////////////////////////////////////////////////////////////////////

core/java/android/view/GLES20Layer.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,13 @@ void destroy() {
6060
}
6161
mLayer = 0;
6262
}
63+
64+
@Override
65+
void flush() {
66+
if (mLayer != 0) {
67+
GLES20Canvas.nFlushLayer(mLayer);
68+
}
69+
}
6370

6471
static class Finalizer {
6572
private int mLayerId;

core/java/android/view/HardwareLayer.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,11 @@ boolean isOpaque() {
115115
*/
116116
abstract void destroy();
117117

118+
/**
119+
* Flush the render queue associated with this layer.
120+
*/
121+
abstract void flush();
122+
118123
/**
119124
* This must be invoked before drawing onto this layer.
120125
* @param currentCanvas

core/java/android/view/View.java

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10207,6 +10207,13 @@ public void buildLayer() {
1020710207
break;
1020810208
}
1020910209
}
10210+
10211+
// Make sure the HardwareRenderer.validate() was invoked before calling this method
10212+
void flushLayer() {
10213+
if (mLayerType == LAYER_TYPE_HARDWARE && mHardwareLayer != null) {
10214+
mHardwareLayer.flush();
10215+
}
10216+
}
1021010217

1021110218
/**
1021210219
* <p>Returns a hardware layer that can be used to draw this view again
@@ -10219,6 +10226,8 @@ HardwareLayer getHardwareLayer() {
1021910226
!mAttachInfo.mHardwareRenderer.isEnabled()) {
1022010227
return null;
1022110228
}
10229+
10230+
if (!mAttachInfo.mHardwareRenderer.validate()) return null;
1022210231

1022310232
final int width = mRight - mLeft;
1022410233
final int height = mBottom - mTop;
@@ -10293,12 +10302,15 @@ HardwareLayer getHardwareLayer() {
1029310302
*/
1029410303
boolean destroyLayer() {
1029510304
if (mHardwareLayer != null) {
10296-
mHardwareLayer.destroy();
10297-
mHardwareLayer = null;
10298-
10299-
invalidate(true);
10300-
invalidateParentCaches();
10305+
AttachInfo info = mAttachInfo;
10306+
if (info != null && info.mHardwareRenderer != null &&
10307+
info.mHardwareRenderer.isEnabled() && info.mHardwareRenderer.validate()) {
10308+
mHardwareLayer.destroy();
10309+
mHardwareLayer = null;
1030110310

10311+
invalidate(true);
10312+
invalidateParentCaches();
10313+
}
1030210314
return true;
1030310315
}
1030410316
return false;

core/java/android/view/ViewGroup.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2958,6 +2958,17 @@ public void setChildrenLayersEnabled(boolean enabled) {
29582958
mDrawLayers = enabled;
29592959
invalidate(true);
29602960

2961+
boolean flushLayers = !enabled;
2962+
AttachInfo info = mAttachInfo;
2963+
if (info != null && info.mHardwareRenderer != null &&
2964+
info.mHardwareRenderer.isEnabled()) {
2965+
if (!info.mHardwareRenderer.validate()) {
2966+
flushLayers = false;
2967+
}
2968+
} else {
2969+
flushLayers = false;
2970+
}
2971+
29612972
// We need to invalidate any child with a layer. For instance,
29622973
// if a child is backed by a hardware layer and we disable layers
29632974
// the child is marked as not dirty (flags cleared the last time
@@ -2968,6 +2979,7 @@ public void setChildrenLayersEnabled(boolean enabled) {
29682979
for (int i = 0; i < mChildrenCount; i++) {
29692980
View child = mChildren[i];
29702981
if (child.mLayerType != LAYER_TYPE_NONE) {
2982+
if (flushLayers) child.flushLayer();
29712983
child.invalidate(true);
29722984
}
29732985
}

core/jni/android_view_GLES20Canvas.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,10 @@ static void android_view_GLES20Canvas_destroyLayerDeferred(JNIEnv* env,
719719
LayerRenderer::destroyLayerDeferred(layer);
720720
}
721721

722+
static void android_view_GLES20Canvas_flushLayer(JNIEnv* env, jobject clazz, Layer* layer) {
723+
LayerRenderer::flushLayer(layer);
724+
}
725+
722726
static void android_view_GLES20Canvas_drawLayer(JNIEnv* env, jobject clazz,
723727
OpenGLRenderer* renderer, Layer* layer, jfloat x, jfloat y, SkPaint* paint) {
724728
renderer->drawLayer(layer, x, y, paint);
@@ -869,6 +873,7 @@ static JNINativeMethod gMethods[] = {
869873
{ "nSetTextureLayerTransform", "(II)V", (void*) android_view_GLES20Canvas_setTextureLayerTransform },
870874
{ "nDestroyLayer", "(I)V", (void*) android_view_GLES20Canvas_destroyLayer },
871875
{ "nDestroyLayerDeferred", "(I)V", (void*) android_view_GLES20Canvas_destroyLayerDeferred },
876+
{ "nFlushLayer", "(I)V", (void*) android_view_GLES20Canvas_flushLayer },
872877
{ "nDrawLayer", "(IIFFI)V", (void*) android_view_GLES20Canvas_drawLayer },
873878
{ "nCopyLayer", "(II)Z", (void*) android_view_GLES20Canvas_copyLayer },
874879

libs/hwui/Android.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ ifeq ($(USE_OPENGL_RENDERER),true)
3838
external/skia/src/ports \
3939
external/skia/include/utils
4040

41-
LOCAL_CFLAGS += -DUSE_OPENGL_RENDERER
41+
LOCAL_CFLAGS += -DUSE_OPENGL_RENDERER -DGL_GLEXT_PROTOTYPES
4242
LOCAL_CFLAGS += -fvisibility=hidden
4343
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
4444
LOCAL_SHARED_LIBRARIES := libcutils libutils libGLESv2 libskia libui

libs/hwui/Extensions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ class Extensions {
6666

6767
mHasNPot = hasExtension("GL_OES_texture_npot");
6868
mHasFramebufferFetch = hasExtension("GL_NV_shader_framebuffer_fetch");
69+
mHasDiscardFramebuffer = hasExtension("GL_EXT_discard_framebuffer");
6970

7071
const char* vendor = (const char*) glGetString(GL_VENDOR);
7172
EXT_LOGD("Vendor: %s", vendor);
@@ -80,6 +81,7 @@ class Extensions {
8081
inline bool hasNPot() const { return mHasNPot; }
8182
inline bool hasFramebufferFetch() const { return mHasFramebufferFetch; }
8283
inline bool needsHighpTexCoords() const { return mNeedsHighpTexCoords; }
84+
inline bool hasDiscardFramebuffer() const { return mHasDiscardFramebuffer; }
8385

8486
bool hasExtension(const char* extension) const {
8587
const String8 s(extension);
@@ -98,6 +100,7 @@ class Extensions {
98100
bool mHasNPot;
99101
bool mNeedsHighpTexCoords;
100102
bool mHasFramebufferFetch;
103+
bool mHasDiscardFramebuffer;
101104
}; // class Extensions
102105

103106
}; // namespace uirenderer

libs/hwui/LayerRenderer.cpp

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -305,8 +305,10 @@ void LayerRenderer::destroyLayer(Layer* layer) {
305305
LAYER_RENDERER_LOGD("Recycling layer, %dx%d fbo = %d",
306306
layer->getWidth(), layer->getHeight(), layer->getFbo());
307307

308-
if (layer->getFbo()) {
309-
Caches::getInstance().fboCache.put(layer->getFbo());
308+
GLuint fbo = layer->getFbo();
309+
if (fbo) {
310+
flushLayer(layer);
311+
Caches::getInstance().fboCache.put(fbo);
310312
}
311313

312314
if (!Caches::getInstance().layerCache.put(layer)) {
@@ -331,6 +333,26 @@ void LayerRenderer::destroyLayerDeferred(Layer* layer) {
331333
}
332334
}
333335

336+
void LayerRenderer::flushLayer(Layer* layer) {
337+
#ifdef GL_EXT_discard_framebuffer
338+
GLuint fbo = layer->getFbo();
339+
if (layer && fbo) {
340+
// If possible, discard any enqueud operations on deferred
341+
// rendering architectures
342+
if (Caches::getInstance().extensions.hasDiscardFramebuffer()) {
343+
GLuint previousFbo;
344+
glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &previousFbo);
345+
346+
GLenum attachments = GL_COLOR_ATTACHMENT0;
347+
if (fbo != previousFbo) glBindFramebuffer(GL_FRAMEBUFFER, fbo);
348+
glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, &attachments);
349+
350+
if (fbo != previousFbo) glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
351+
}
352+
}
353+
#endif
354+
}
355+
334356
bool LayerRenderer::copyLayer(Layer* layer, SkBitmap* bitmap) {
335357
Caches& caches = Caches::getInstance();
336358
if (layer && layer->isTextureLayer() && bitmap->width() <= caches.maxTextureSize &&

libs/hwui/LayerRenderer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ class LayerRenderer: public OpenGLRenderer {
6161
bool isOpaque, GLenum renderTarget, float* transform);
6262
ANDROID_API static void destroyLayer(Layer* layer);
6363
ANDROID_API static void destroyLayerDeferred(Layer* layer);
64+
ANDROID_API static void flushLayer(Layer* layer);
6465
ANDROID_API static bool copyLayer(Layer* layer, SkBitmap* bitmap);
6566

6667
private:

0 commit comments

Comments
 (0)