From 87e2f757be9b24d369bab354e37c276e851b1fc7 Mon Sep 17 00:00:00 2001 From: Romain Guy Date: Mon, 24 Sep 2012 11:37:12 -0700 Subject: [PATCH] Add a property to disable libhwui's scissor optimization Bug #7158326 When scissor optimization is enabled, OpenGLRenderer will attempt to minimize the use of scissor by selectively enabling and disabling the GL scissor test. When the optimization is disabled, OpenGLRenderer will keep the GL scissor test enabled and change the scissor rect as needed. Some GPUs (for instance the SGX 540) perform better when changing the scissor rect often than when enabling/disabling the scissor test often. Change-Id: Idb68862e287a23358f9188d577ae0f86161902fd --- core/jni/android_view_GLES20Canvas.cpp | 8 +- libs/hwui/OpenGLRenderer.cpp | 106 ++++++++++++++----------- libs/hwui/OpenGLRenderer.h | 10 +++ libs/hwui/Properties.h | 15 ++++ 4 files changed, 91 insertions(+), 48 deletions(-) diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp index b91eb28f5b9f1..a3834acba2bb4 100644 --- a/core/jni/android_view_GLES20Canvas.cpp +++ b/core/jni/android_view_GLES20Canvas.cpp @@ -116,7 +116,9 @@ static void android_view_GLES20Canvas_terminateCaches(JNIEnv* env, jobject clazz static OpenGLRenderer* android_view_GLES20Canvas_createRenderer(JNIEnv* env, jobject clazz) { RENDERER_LOGD("Create OpenGLRenderer"); - return new OpenGLRenderer; + OpenGLRenderer* renderer = new OpenGLRenderer(); + renderer->initProperties(); + return renderer; } static void android_view_GLES20Canvas_destroyRenderer(JNIEnv* env, jobject clazz, @@ -734,7 +736,9 @@ static void android_view_GLES20Canvas_resume(JNIEnv* env, jobject clazz, static OpenGLRenderer* android_view_GLES20Canvas_createLayerRenderer(JNIEnv* env, jobject clazz, Layer* layer) { if (layer) { - return new LayerRenderer(layer); + OpenGLRenderer* renderer = new LayerRenderer(layer); + renderer->initProperties(); + return renderer; } return NULL; } diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index a4403c8dc590d..35cc7160fc31c 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -34,6 +34,7 @@ #include "OpenGLRenderer.h" #include "DisplayListRenderer.h" #include "PathRenderer.h" +#include "Properties.h" #include "Vector.h" namespace android { @@ -117,6 +118,8 @@ OpenGLRenderer::OpenGLRenderer(): mCaches(Caches::getInstance()) { memcpy(mMeshVertices, gMeshVertices, sizeof(gMeshVertices)); mFirstSnapshot = new Snapshot; + + mScissorOptimizationDisabled = false; } OpenGLRenderer::~OpenGLRenderer() { @@ -124,16 +127,15 @@ OpenGLRenderer::~OpenGLRenderer() { // GL APIs. All GL state should be kept in Caches.h } -/////////////////////////////////////////////////////////////////////////////// -// Debug -/////////////////////////////////////////////////////////////////////////////// - -void OpenGLRenderer::startMark(const char* name) const { - mCaches.startMark(0, name); -} - -void OpenGLRenderer::endMark() const { - mCaches.endMark(); +void OpenGLRenderer::initProperties() { + char property[PROPERTY_VALUE_MAX]; + if (property_get(PROPERTY_DISABLE_SCISSOR_OPTIMIZATION, property, "false")) { + mScissorOptimizationDisabled = !strcasecmp(property, "true"); + INIT_LOGD(" Scissor optimization %s", + mScissorOptimizationDisabled ? "disabled" : "enabled"); + } else { + INIT_LOGD(" Scissor optimization enabled"); + } } /////////////////////////////////////////////////////////////////////////////// @@ -268,40 +270,6 @@ void OpenGLRenderer::finish() { } } -void OpenGLRenderer::debugOverdraw(bool enable, bool clear) { - if (mCaches.debugOverdraw && getTargetFbo() == 0) { - if (clear) { - mCaches.disableScissor(); - mCaches.stencil.clear(); - } - if (enable) { - mCaches.stencil.enableDebugWrite(); - } else { - mCaches.stencil.disable(); - } - } -} - -void OpenGLRenderer::renderOverdraw() { - if (mCaches.debugOverdraw && getTargetFbo() == 0) { - const Rect* clip = mTilingSnapshot->clipRect; - - mCaches.enableScissor(); - mCaches.setScissor(clip->left, mTilingSnapshot->height - clip->bottom, - clip->right - clip->left, clip->bottom - clip->top); - - mCaches.stencil.enableDebugTest(2); - drawColor(0x2f0000ff, SkXfermode::kSrcOver_Mode); - mCaches.stencil.enableDebugTest(3); - drawColor(0x2f00ff00, SkXfermode::kSrcOver_Mode); - mCaches.stencil.enableDebugTest(4); - drawColor(0x3fff0000, SkXfermode::kSrcOver_Mode); - mCaches.stencil.enableDebugTest(4, true); - drawColor(0x7fff0000, SkXfermode::kSrcOver_Mode); - mCaches.stencil.disable(); - } -} - void OpenGLRenderer::interrupt() { if (mCaches.currentProgram) { if (mCaches.currentProgram->isInUse()) { @@ -438,6 +406,52 @@ status_t OpenGLRenderer::callDrawGLFunction(Functor* functor, Rect& dirty) { return result; } +/////////////////////////////////////////////////////////////////////////////// +// Debug +/////////////////////////////////////////////////////////////////////////////// + +void OpenGLRenderer::startMark(const char* name) const { + mCaches.startMark(0, name); +} + +void OpenGLRenderer::endMark() const { + mCaches.endMark(); +} + +void OpenGLRenderer::debugOverdraw(bool enable, bool clear) { + if (mCaches.debugOverdraw && getTargetFbo() == 0) { + if (clear) { + mCaches.disableScissor(); + mCaches.stencil.clear(); + } + if (enable) { + mCaches.stencil.enableDebugWrite(); + } else { + mCaches.stencil.disable(); + } + } +} + +void OpenGLRenderer::renderOverdraw() { + if (mCaches.debugOverdraw && getTargetFbo() == 0) { + const Rect* clip = mTilingSnapshot->clipRect; + + mCaches.enableScissor(); + mCaches.setScissor(clip->left, mTilingSnapshot->height - clip->bottom, + clip->right - clip->left, clip->bottom - clip->top); + + mCaches.stencil.enableDebugTest(2); + drawColor(0x2f0000ff, SkXfermode::kSrcOver_Mode); + mCaches.stencil.enableDebugTest(3); + drawColor(0x2f00ff00, SkXfermode::kSrcOver_Mode); + mCaches.stencil.enableDebugTest(4); + drawColor(0x3fff0000, SkXfermode::kSrcOver_Mode); + mCaches.stencil.enableDebugTest(4, true); + drawColor(0x7fff0000, SkXfermode::kSrcOver_Mode); + mCaches.stencil.disable(); + } +} + /////////////////////////////////////////////////////////////////////////////// // Layers /////////////////////////////////////////////////////////////////////////////// @@ -1248,7 +1262,7 @@ bool OpenGLRenderer::quickReject(float left, float top, float right, float botto bool rejected = !clipRect.intersects(r); if (!isDeferred() && !rejected) { - mCaches.setScissorEnabled(!clipRect.contains(r)); + mCaches.setScissorEnabled(mScissorOptimizationDisabled || !clipRect.contains(r)); } return rejected; @@ -2711,7 +2725,7 @@ status_t OpenGLRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* pain debugLayerUpdate = mCaches.debugLayersUpdates; } - mCaches.setScissorEnabled(!clip.contains(transformed)); + mCaches.setScissorEnabled(mScissorOptimizationDisabled || !clip.contains(transformed)); mCaches.activeTexture(0); if (CC_LIKELY(!layer->region.isEmpty())) { diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index 46e66cbc7779c..c29e3fb3f097b 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -63,6 +63,12 @@ public: ANDROID_API OpenGLRenderer(); virtual ~OpenGLRenderer(); + /** + * Read externally defined properties to control the behavior + * of the renderer. + */ + ANDROID_API void initProperties(); + /** * Indicates whether this renderer executes drawing commands immediately. * If this method returns true, the drawing commands will be executed @@ -804,6 +810,10 @@ private: // Indicate whether we are drawing an opaque frame bool mOpaqueFrame; + // See PROPERTY_DISABLE_SCISSOR_OPTIMIZATION in + // Properties.h + bool mScissorOptimizationDisabled; + friend class DisplayListRenderer; }; // class OpenGLRenderer diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h index 31e60e4450c2b..1e8765bae9a2f 100644 --- a/libs/hwui/Properties.h +++ b/libs/hwui/Properties.h @@ -67,6 +67,21 @@ enum DebugLevel { */ #define PROPERTY_DEBUG_OVERDRAW "debug.hwui.show_overdraw" +/** + * Used to enable/disable scissor optimization. The accepted values are + * "true" and "false". The default value is "false". + * + * When scissor optimization is enabled, OpenGLRenderer will attempt to + * minimize the use of scissor by selectively enabling and disabling the + * GL scissor test. + * When the optimization is disabled, OpenGLRenderer will keep the GL + * scissor test enabled and change the scissor rect as needed. + * Some GPUs (for instance the SGX 540) perform better when changing + * the scissor rect often than when enabling/disabling the scissor test + * often. + */ +#define PROPERTY_DISABLE_SCISSOR_OPTIMIZATION "ro.hwui.disable_scissor_opt" + // These properties are defined in mega-bytes #define PROPERTY_TEXTURE_CACHE_SIZE "ro.hwui.texture_cache_size" #define PROPERTY_LAYER_CACHE_SIZE "ro.hwui.layer_cache_size"