From 44b2fe3fc114ee5f7273c6b0fee2cc999bf244a2 Mon Sep 17 00:00:00 2001 From: Chet Haase Date: Wed, 6 Jun 2012 19:03:58 -0700 Subject: [PATCH] Track canvas clearing for swap buffers logic. A previous fix made it necessary for a frame to render something to GL in order to cause a call to eglSwapBuffers(). Besides the calls being tracked as part of issuing a DisplayList, there is also a potential call to clear the canvas (via glClear()) on non-opaque surfaces. This call is also good to track, since a surface that gets cleared without any other drawing operations is worth flipping to the screen (to erase old contents on that surface). This fix tracks the status of the pre-draw operations to find out whether glClear() was called and then sets the drawing status appropriately. Issue #6606422 QuickContact dismissal is janky again (Tracking) Change-Id: I5fcaccfdc9293dd46b83f2fc279730a5d2740ebf --- core/java/android/view/GLES20Canvas.java | 11 ++++++----- core/java/android/view/HardwareCanvas.java | 9 ++++++--- core/java/android/view/HardwareRenderer.java | 14 ++++++-------- core/jni/android_view_GLES20Canvas.cpp | 12 ++++++------ libs/hwui/DisplayListRenderer.cpp | 3 ++- libs/hwui/DisplayListRenderer.h | 2 +- libs/hwui/LayerRenderer.cpp | 6 +++--- libs/hwui/LayerRenderer.h | 2 +- libs/hwui/OpenGLRenderer.cpp | 9 ++++++--- libs/hwui/OpenGLRenderer.h | 4 ++-- 10 files changed, 39 insertions(+), 33 deletions(-) diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java index 1631fb34fea5c..055aee3e84400 100644 --- a/core/java/android/view/GLES20Canvas.java +++ b/core/java/android/view/GLES20Canvas.java @@ -215,16 +215,17 @@ class GLES20Canvas extends HardwareCanvas { private static native void nSetViewport(int renderer, int width, int height); @Override - public void onPreDraw(Rect dirty) { + public int onPreDraw(Rect dirty) { if (dirty != null) { - nPrepareDirty(mRenderer, dirty.left, dirty.top, dirty.right, dirty.bottom, mOpaque); + return nPrepareDirty(mRenderer, dirty.left, dirty.top, dirty.right, dirty.bottom, + mOpaque); } else { - nPrepare(mRenderer, mOpaque); + return nPrepare(mRenderer, mOpaque); } } - private static native void nPrepare(int renderer, boolean opaque); - private static native void nPrepareDirty(int renderer, int left, int top, int right, int bottom, + private static native int nPrepare(int renderer, boolean opaque); + private static native int nPrepareDirty(int renderer, int left, int top, int right, int bottom, boolean opaque); @Override diff --git a/core/java/android/view/HardwareCanvas.java b/core/java/android/view/HardwareCanvas.java index ee2dd5928f2c9..777552a23b5a5 100644 --- a/core/java/android/view/HardwareCanvas.java +++ b/core/java/android/view/HardwareCanvas.java @@ -41,8 +41,10 @@ public abstract class HardwareCanvas extends Canvas { * Invoked before any drawing operation is performed in this canvas. * * @param dirty The dirty rectangle to update, can be null. + * @return {@link DisplayList#STATUS_DREW} if anything was drawn (such as a call to clear + * the canvas). */ - public abstract void onPreDraw(Rect dirty); + public abstract int onPreDraw(Rect dirty); /** * Invoked after all drawing operation have been performed. @@ -58,8 +60,9 @@ public abstract class HardwareCanvas extends Canvas { * @param flags Optional flags about drawing, see {@link DisplayList} for * the possible flags. * - * @return One of {@link DisplayList#STATUS_DONE}, {@link DisplayList#STATUS_DRAW} or - * {@link DisplayList#STATUS_INVOKE} + * @return One of {@link DisplayList#STATUS_DONE}, {@link DisplayList#STATUS_DRAW}, or + * {@link DisplayList#STATUS_INVOKE}, or'd with {@link DisplayList#STATUS_DREW} + * if anything was drawn. */ public abstract int drawDisplayList(DisplayList displayList, Rect dirty, int flags); diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java index 7e86ea3a542e5..0ae6b56df6fec 100644 --- a/core/java/android/view/HardwareRenderer.java +++ b/core/java/android/view/HardwareRenderer.java @@ -1042,8 +1042,8 @@ public abstract class HardwareRenderer { return mGl != null && mCanvas != null; } - void onPreDraw(Rect dirty) { - + int onPreDraw(Rect dirty) { + return DisplayList.STATUS_DONE; } void onPostDraw() { @@ -1102,9 +1102,7 @@ public abstract class HardwareRenderer { } } - onPreDraw(dirty); - - int status = DisplayList.STATUS_DONE; + int status = onPreDraw(dirty); int saveCount = canvas.save(); callbacks.onHardwarePreDraw(canvas); @@ -1138,7 +1136,7 @@ public abstract class HardwareRenderer { drawDisplayListStartTime = System.nanoTime(); } - status = canvas.drawDisplayList(displayList, mRedrawClip, + status |= canvas.drawDisplayList(displayList, mRedrawClip, DisplayList.FLAG_CLIP_CHILDREN); if (mProfileEnabled) { @@ -1372,8 +1370,8 @@ public abstract class HardwareRenderer { } @Override - void onPreDraw(Rect dirty) { - mGlCanvas.onPreDraw(dirty); + int onPreDraw(Rect dirty) { + return mGlCanvas.onPreDraw(dirty); } @Override diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp index 82f898458eef9..a51b77e712e1d 100644 --- a/core/jni/android_view_GLES20Canvas.cpp +++ b/core/jni/android_view_GLES20Canvas.cpp @@ -133,15 +133,15 @@ static void android_view_GLES20Canvas_setViewport(JNIEnv* env, jobject clazz, renderer->setViewport(width, height); } -static void android_view_GLES20Canvas_prepare(JNIEnv* env, jobject clazz, +static int android_view_GLES20Canvas_prepare(JNIEnv* env, jobject clazz, OpenGLRenderer* renderer, jboolean opaque) { - renderer->prepare(opaque); + return renderer->prepare(opaque); } -static void android_view_GLES20Canvas_prepareDirty(JNIEnv* env, jobject clazz, +static int android_view_GLES20Canvas_prepareDirty(JNIEnv* env, jobject clazz, OpenGLRenderer* renderer, jint left, jint top, jint right, jint bottom, jboolean opaque) { - renderer->prepareDirty(left, top, right, bottom, opaque); + return renderer->prepareDirty(left, top, right, bottom, opaque); } static void android_view_GLES20Canvas_finish(JNIEnv* env, jobject clazz, @@ -868,8 +868,8 @@ static JNINativeMethod gMethods[] = { { "nCreateRenderer", "()I", (void*) android_view_GLES20Canvas_createRenderer }, { "nDestroyRenderer", "(I)V", (void*) android_view_GLES20Canvas_destroyRenderer }, { "nSetViewport", "(III)V", (void*) android_view_GLES20Canvas_setViewport }, - { "nPrepare", "(IZ)V", (void*) android_view_GLES20Canvas_prepare }, - { "nPrepareDirty", "(IIIIIZ)V", (void*) android_view_GLES20Canvas_prepareDirty }, + { "nPrepare", "(IZ)I", (void*) android_view_GLES20Canvas_prepare }, + { "nPrepareDirty", "(IIIIIZ)I", (void*) android_view_GLES20Canvas_prepareDirty }, { "nFinish", "(I)V", (void*) android_view_GLES20Canvas_finish }, { "nGetStencilSize", "()I", (void*) android_view_GLES20Canvas_getStencilSize }, diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp index 88d2209154c11..d376e3a9f2c5d 100644 --- a/libs/hwui/DisplayListRenderer.cpp +++ b/libs/hwui/DisplayListRenderer.cpp @@ -1368,13 +1368,14 @@ void DisplayListRenderer::setViewport(int width, int height) { mHeight = height; } -void DisplayListRenderer::prepareDirty(float left, float top, +int DisplayListRenderer::prepareDirty(float left, float top, float right, float bottom, bool opaque) { mSnapshot = new Snapshot(mFirstSnapshot, SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag); mSaveCount = 1; mSnapshot->setClip(0.0f, 0.0f, mWidth, mHeight); mRestoreSaveCount = -1; + return DrawGlInfo::kStatusDone; // No invalidate needed at record-time } void DisplayListRenderer::finish() { diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h index 4fa1baa741994..6b4c6b20d8639 100644 --- a/libs/hwui/DisplayListRenderer.h +++ b/libs/hwui/DisplayListRenderer.h @@ -547,7 +547,7 @@ public: virtual bool isDeferred(); virtual void setViewport(int width, int height); - virtual void prepareDirty(float left, float top, float right, float bottom, bool opaque); + virtual int prepareDirty(float left, float top, float right, float bottom, bool opaque); virtual void finish(); virtual status_t callDrawGLFunction(Functor *functor, Rect& dirty); diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp index 2a4e72be0e31e..65f8c7c8b67c0 100644 --- a/libs/hwui/LayerRenderer.cpp +++ b/libs/hwui/LayerRenderer.cpp @@ -37,7 +37,7 @@ LayerRenderer::LayerRenderer(Layer* layer): mLayer(layer) { LayerRenderer::~LayerRenderer() { } -void LayerRenderer::prepareDirty(float left, float top, float right, float bottom, bool opaque) { +int LayerRenderer::prepareDirty(float left, float top, float right, float bottom, bool opaque) { LAYER_RENDERER_LOGD("Rendering into layer, fbo = %d", mLayer->getFbo()); glBindFramebuffer(GL_FRAMEBUFFER, mLayer->getFbo()); @@ -57,9 +57,9 @@ void LayerRenderer::prepareDirty(float left, float top, float right, float botto mLayer->region.subtractSelf(r); } - OpenGLRenderer::prepareDirty(dirty.left, dirty.top, dirty.right, dirty.bottom, opaque); + return OpenGLRenderer::prepareDirty(dirty.left, dirty.top, dirty.right, dirty.bottom, opaque); #else - OpenGLRenderer::prepareDirty(0.0f, 0.0f, width, height, opaque); + return OpenGLRenderer::prepareDirty(0.0f, 0.0f, width, height, opaque); #endif } diff --git a/libs/hwui/LayerRenderer.h b/libs/hwui/LayerRenderer.h index c461ea75c7ee8..8f3a0a3111ee7 100644 --- a/libs/hwui/LayerRenderer.h +++ b/libs/hwui/LayerRenderer.h @@ -47,7 +47,7 @@ public: ANDROID_API LayerRenderer(Layer* layer); virtual ~LayerRenderer(); - virtual void prepareDirty(float left, float top, float right, float bottom, bool opaque); + virtual int prepareDirty(float left, float top, float right, float bottom, bool opaque); virtual void finish(); virtual bool hasLayer(); diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 2dc9726ab9cad..0d857bfff3513 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -164,11 +164,11 @@ void OpenGLRenderer::setViewport(int width, int height) { glEnableVertexAttribArray(Program::kBindingPosition); } -void OpenGLRenderer::prepare(bool opaque) { - prepareDirty(0.0f, 0.0f, mWidth, mHeight, opaque); +int OpenGLRenderer::prepare(bool opaque) { + return prepareDirty(0.0f, 0.0f, mWidth, mHeight, opaque); } -void OpenGLRenderer::prepareDirty(float left, float top, float right, float bottom, bool opaque) { +int OpenGLRenderer::prepareDirty(float left, float top, float right, float bottom, bool opaque) { mCaches.clearGarbage(); mSnapshot = new Snapshot(mFirstSnapshot, @@ -184,9 +184,12 @@ void OpenGLRenderer::prepareDirty(float left, float top, float right, float bott if (!opaque) { mCaches.setScissor(left, mSnapshot->height - bottom, right - left, bottom - top); glClear(GL_COLOR_BUFFER_BIT); + return DrawGlInfo::kStatusDrew; } else { mCaches.resetScissor(); } + + return DrawGlInfo::kStatusDone; } void OpenGLRenderer::syncState() { diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index 7703e805d04c4..b342f50680109 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -67,8 +67,8 @@ public: virtual void setViewport(int width, int height); - ANDROID_API void prepare(bool opaque); - virtual void prepareDirty(float left, float top, float right, float bottom, bool opaque); + ANDROID_API int prepare(bool opaque); + virtual int prepareDirty(float left, float top, float right, float bottom, bool opaque); virtual void finish(); // These two calls must not be recorded in display lists