Loading libs/hwui/Properties.cpp +5 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,8 @@ bool Properties::drawReorderDisabled = false; bool Properties::debugLayersUpdates = false; bool Properties::debugOverdraw = false; bool Properties::showDirtyRegions = false; bool Properties::skipEmptyFrames = true; bool Properties::swapBuffersWithDamage = false; DebugLevel Properties::debugLevel = kDebugDisabled; OverdrawColorSet Properties::overdrawColorSet = OverdrawColorSet::Default; Loading Loading @@ -101,6 +103,9 @@ bool Properties::load() { debugLevel = (DebugLevel) atoi(property); } skipEmptyFrames = property_get_bool(PROPERTY_SKIP_EMPTY_DAMAGE, true); swapBuffersWithDamage = property_get_bool(PROPERTY_SWAP_WITH_DAMAGE, false); return (prevDebugLayersUpdates != debugLayersUpdates) || (prevDebugOverdraw != debugOverdraw) || (prevDebugStencilClip != debugStencilClip); Loading libs/hwui/Properties.h +19 −0 Original line number Diff line number Diff line Loading @@ -158,6 +158,21 @@ enum DebugLevel { */ #define PROPERTY_DISABLE_DRAW_REORDER "debug.hwui.disable_draw_reorder" /** * Setting this property will enable or disable the dropping of frames with * empty damage. Default is "true". */ #define PROPERTY_SKIP_EMPTY_DAMAGE "debug.hwui.skip_empty_damage" /** * Setting this property will enable usage of EGL_KHR_swap_buffers_with_damage * See: https://www.khronos.org/registry/egl/extensions/KHR/EGL_KHR_swap_buffers_with_damage.txt * Default is "false" temporarily * TODO: Change to "true", make sure to remove the log in EglManager::swapBuffers * before changing this to default to true! */ #define PROPERTY_SWAP_WITH_DAMAGE "debug.hwui.swap_with_damage" /////////////////////////////////////////////////////////////////////////////// // Runtime configuration properties /////////////////////////////////////////////////////////////////////////////// Loading Loading @@ -288,6 +303,10 @@ public: static bool debugLayersUpdates; static bool debugOverdraw; static bool showDirtyRegions; // TODO: Remove after stabilization period static bool skipEmptyFrames; // TODO: Remove after stabilization period static bool swapBuffersWithDamage; static DebugLevel debugLevel; static OverdrawColorSet overdrawColorSet; Loading libs/hwui/renderthread/CanvasContext.cpp +13 −27 Original line number Diff line number Diff line Loading @@ -16,36 +16,25 @@ #include "CanvasContext.h" #include "AnimationContext.h" #include "Caches.h" #include "DeferredLayerUpdater.h" #include "EglManager.h" #include "LayerRenderer.h" #include "OpenGLRenderer.h" #include "Properties.h" #include "RenderThread.h" #include "../AnimationContext.h" #include "../Caches.h" #include "../DeferredLayerUpdater.h" #include "../renderstate/RenderState.h" #include "../renderstate/Stencil.h" #include "../LayerRenderer.h" #include "../OpenGLRenderer.h" #include "renderstate/RenderState.h" #include "renderstate/Stencil.h" #include <algorithm> #include <strings.h> #include <cutils/properties.h> #include <private/hwui/DrawGlInfo.h> #include <strings.h> #define TRIM_MEMORY_COMPLETE 80 #define TRIM_MEMORY_UI_HIDDEN 20 #define PROPERTY_SKIP_EMPTY_DAMAGE "debug.hwui.skip_empty_damage" static bool sInitialized = false; static bool sSkipEmptyDamage = true; static void initGlobals() { if (sInitialized) return; sInitialized = true; sSkipEmptyDamage = property_get_bool(PROPERTY_SKIP_EMPTY_DAMAGE, sSkipEmptyDamage); } namespace android { namespace uirenderer { namespace renderthread { Loading @@ -58,9 +47,6 @@ CanvasContext::CanvasContext(RenderThread& thread, bool translucent, , mAnimationContext(contextFactory->createAnimationContext(mRenderThread.timeLord())) , mRootRenderNode(rootRenderNode) , mJankTracker(thread.timeLord().frameIntervalNanos()) { // Done lazily at first draw instead of at library load to avoid // running pre-zygote fork initGlobals(); mRenderThread.renderState().registerCanvasContext(this); mProfiler.setDensity(mRenderThread.mainDisplayInfo().density); } Loading Loading @@ -106,8 +92,8 @@ void CanvasContext::setSurface(ANativeWindow* window) { } } void CanvasContext::swapBuffers() { if (CC_UNLIKELY(!mEglManager.swapBuffers(mEglSurface))) { void CanvasContext::swapBuffers(const SkRect& dirty, EGLint width, EGLint height) { if (CC_UNLIKELY(!mEglManager.swapBuffers(mEglSurface, dirty, width, height))) { setSurface(nullptr); } mHaveNewSurface = false; Loading Loading @@ -222,7 +208,7 @@ void CanvasContext::draw() { SkRect dirty; mDamageAccumulator.finish(&dirty); if (dirty.isEmpty() && sSkipEmptyDamage) { if (dirty.isEmpty() && Properties::skipEmptyFrames) { mCurrentFrameInfo->addFlag(FrameInfoFlags::kSkippedFrame); return; } Loading Loading @@ -267,7 +253,7 @@ void CanvasContext::draw() { mCurrentFrameInfo->markSwapBuffers(); if (drew) { swapBuffers(); swapBuffers(dirty, width, height); } else { mEglManager.cancelFrame(); } Loading libs/hwui/renderthread/CanvasContext.h +2 −1 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ #include <cutils/compiler.h> #include <EGL/egl.h> #include <SkBitmap.h> #include <SkRect.h> #include <utils/Functor.h> #include <utils/Vector.h> Loading Loading @@ -117,7 +118,7 @@ private: friend class android::uirenderer::RenderState; void setSurface(ANativeWindow* window); void swapBuffers(); void swapBuffers(const SkRect& dirty, EGLint width, EGLint height); void requireSurface(); void requireGlContext(); Loading libs/hwui/renderthread/EglManager.cpp +35 −3 Original line number Diff line number Diff line Loading @@ -16,9 +16,10 @@ #include "EglManager.h" #include "../Caches.h" #include "../renderstate/RenderState.h" #include "Caches.h" #include "Properties.h" #include "RenderThread.h" #include "renderstate/RenderState.h" #include <cutils/log.h> #include <cutils/properties.h> Loading Loading @@ -261,7 +262,8 @@ void EglManager::beginFrame(EGLSurface surface, EGLint* width, EGLint* height) { mInFrame = true; } bool EglManager::swapBuffers(EGLSurface surface) { bool EglManager::swapBuffers(EGLSurface surface, const SkRect& dirty, EGLint width, EGLint height) { mInFrame = false; #if WAIT_FOR_GPU_COMPLETION Loading @@ -271,7 +273,37 @@ bool EglManager::swapBuffers(EGLSurface surface) { } #endif #ifdef EGL_KHR_swap_buffers_with_damage if (CC_UNLIKELY(Properties::swapBuffersWithDamage)) { SkIRect idirty; dirty.roundOut(&idirty); /* * EGL_KHR_swap_buffers_with_damage spec states: * * The rectangles are specified relative to the bottom-left of the surface * and the x and y components of each rectangle specify the bottom-left * position of that rectangle. * * HWUI does everything with 0,0 being top-left, so need to map * the rect */ EGLint y = height - (idirty.y() + idirty.height()); // layout: {x, y, width, height} EGLint rects[4] = { idirty.x(), y, idirty.width(), idirty.height() }; EGLint numrects = dirty.isEmpty() ? 0 : 1; // TODO: Remove prior to enabling this path by default ALOGD("Swap buffers with damage %d: %d, %d, %d, %d (src=" RECT_STRING ")", dirty.isEmpty() ? 0 : 1, rects[0], rects[1], rects[2], rects[3], SK_RECT_ARGS(dirty)); eglSwapBuffersWithDamageKHR(mEglDisplay, surface, rects, numrects); } else { eglSwapBuffers(mEglDisplay, surface); } #else eglSwapBuffers(mEglDisplay, surface); #endif EGLint err = eglGetError(); if (CC_LIKELY(err == EGL_SUCCESS)) { return true; Loading Loading
libs/hwui/Properties.cpp +5 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,8 @@ bool Properties::drawReorderDisabled = false; bool Properties::debugLayersUpdates = false; bool Properties::debugOverdraw = false; bool Properties::showDirtyRegions = false; bool Properties::skipEmptyFrames = true; bool Properties::swapBuffersWithDamage = false; DebugLevel Properties::debugLevel = kDebugDisabled; OverdrawColorSet Properties::overdrawColorSet = OverdrawColorSet::Default; Loading Loading @@ -101,6 +103,9 @@ bool Properties::load() { debugLevel = (DebugLevel) atoi(property); } skipEmptyFrames = property_get_bool(PROPERTY_SKIP_EMPTY_DAMAGE, true); swapBuffersWithDamage = property_get_bool(PROPERTY_SWAP_WITH_DAMAGE, false); return (prevDebugLayersUpdates != debugLayersUpdates) || (prevDebugOverdraw != debugOverdraw) || (prevDebugStencilClip != debugStencilClip); Loading
libs/hwui/Properties.h +19 −0 Original line number Diff line number Diff line Loading @@ -158,6 +158,21 @@ enum DebugLevel { */ #define PROPERTY_DISABLE_DRAW_REORDER "debug.hwui.disable_draw_reorder" /** * Setting this property will enable or disable the dropping of frames with * empty damage. Default is "true". */ #define PROPERTY_SKIP_EMPTY_DAMAGE "debug.hwui.skip_empty_damage" /** * Setting this property will enable usage of EGL_KHR_swap_buffers_with_damage * See: https://www.khronos.org/registry/egl/extensions/KHR/EGL_KHR_swap_buffers_with_damage.txt * Default is "false" temporarily * TODO: Change to "true", make sure to remove the log in EglManager::swapBuffers * before changing this to default to true! */ #define PROPERTY_SWAP_WITH_DAMAGE "debug.hwui.swap_with_damage" /////////////////////////////////////////////////////////////////////////////// // Runtime configuration properties /////////////////////////////////////////////////////////////////////////////// Loading Loading @@ -288,6 +303,10 @@ public: static bool debugLayersUpdates; static bool debugOverdraw; static bool showDirtyRegions; // TODO: Remove after stabilization period static bool skipEmptyFrames; // TODO: Remove after stabilization period static bool swapBuffersWithDamage; static DebugLevel debugLevel; static OverdrawColorSet overdrawColorSet; Loading
libs/hwui/renderthread/CanvasContext.cpp +13 −27 Original line number Diff line number Diff line Loading @@ -16,36 +16,25 @@ #include "CanvasContext.h" #include "AnimationContext.h" #include "Caches.h" #include "DeferredLayerUpdater.h" #include "EglManager.h" #include "LayerRenderer.h" #include "OpenGLRenderer.h" #include "Properties.h" #include "RenderThread.h" #include "../AnimationContext.h" #include "../Caches.h" #include "../DeferredLayerUpdater.h" #include "../renderstate/RenderState.h" #include "../renderstate/Stencil.h" #include "../LayerRenderer.h" #include "../OpenGLRenderer.h" #include "renderstate/RenderState.h" #include "renderstate/Stencil.h" #include <algorithm> #include <strings.h> #include <cutils/properties.h> #include <private/hwui/DrawGlInfo.h> #include <strings.h> #define TRIM_MEMORY_COMPLETE 80 #define TRIM_MEMORY_UI_HIDDEN 20 #define PROPERTY_SKIP_EMPTY_DAMAGE "debug.hwui.skip_empty_damage" static bool sInitialized = false; static bool sSkipEmptyDamage = true; static void initGlobals() { if (sInitialized) return; sInitialized = true; sSkipEmptyDamage = property_get_bool(PROPERTY_SKIP_EMPTY_DAMAGE, sSkipEmptyDamage); } namespace android { namespace uirenderer { namespace renderthread { Loading @@ -58,9 +47,6 @@ CanvasContext::CanvasContext(RenderThread& thread, bool translucent, , mAnimationContext(contextFactory->createAnimationContext(mRenderThread.timeLord())) , mRootRenderNode(rootRenderNode) , mJankTracker(thread.timeLord().frameIntervalNanos()) { // Done lazily at first draw instead of at library load to avoid // running pre-zygote fork initGlobals(); mRenderThread.renderState().registerCanvasContext(this); mProfiler.setDensity(mRenderThread.mainDisplayInfo().density); } Loading Loading @@ -106,8 +92,8 @@ void CanvasContext::setSurface(ANativeWindow* window) { } } void CanvasContext::swapBuffers() { if (CC_UNLIKELY(!mEglManager.swapBuffers(mEglSurface))) { void CanvasContext::swapBuffers(const SkRect& dirty, EGLint width, EGLint height) { if (CC_UNLIKELY(!mEglManager.swapBuffers(mEglSurface, dirty, width, height))) { setSurface(nullptr); } mHaveNewSurface = false; Loading Loading @@ -222,7 +208,7 @@ void CanvasContext::draw() { SkRect dirty; mDamageAccumulator.finish(&dirty); if (dirty.isEmpty() && sSkipEmptyDamage) { if (dirty.isEmpty() && Properties::skipEmptyFrames) { mCurrentFrameInfo->addFlag(FrameInfoFlags::kSkippedFrame); return; } Loading Loading @@ -267,7 +253,7 @@ void CanvasContext::draw() { mCurrentFrameInfo->markSwapBuffers(); if (drew) { swapBuffers(); swapBuffers(dirty, width, height); } else { mEglManager.cancelFrame(); } Loading
libs/hwui/renderthread/CanvasContext.h +2 −1 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ #include <cutils/compiler.h> #include <EGL/egl.h> #include <SkBitmap.h> #include <SkRect.h> #include <utils/Functor.h> #include <utils/Vector.h> Loading Loading @@ -117,7 +118,7 @@ private: friend class android::uirenderer::RenderState; void setSurface(ANativeWindow* window); void swapBuffers(); void swapBuffers(const SkRect& dirty, EGLint width, EGLint height); void requireSurface(); void requireGlContext(); Loading
libs/hwui/renderthread/EglManager.cpp +35 −3 Original line number Diff line number Diff line Loading @@ -16,9 +16,10 @@ #include "EglManager.h" #include "../Caches.h" #include "../renderstate/RenderState.h" #include "Caches.h" #include "Properties.h" #include "RenderThread.h" #include "renderstate/RenderState.h" #include <cutils/log.h> #include <cutils/properties.h> Loading Loading @@ -261,7 +262,8 @@ void EglManager::beginFrame(EGLSurface surface, EGLint* width, EGLint* height) { mInFrame = true; } bool EglManager::swapBuffers(EGLSurface surface) { bool EglManager::swapBuffers(EGLSurface surface, const SkRect& dirty, EGLint width, EGLint height) { mInFrame = false; #if WAIT_FOR_GPU_COMPLETION Loading @@ -271,7 +273,37 @@ bool EglManager::swapBuffers(EGLSurface surface) { } #endif #ifdef EGL_KHR_swap_buffers_with_damage if (CC_UNLIKELY(Properties::swapBuffersWithDamage)) { SkIRect idirty; dirty.roundOut(&idirty); /* * EGL_KHR_swap_buffers_with_damage spec states: * * The rectangles are specified relative to the bottom-left of the surface * and the x and y components of each rectangle specify the bottom-left * position of that rectangle. * * HWUI does everything with 0,0 being top-left, so need to map * the rect */ EGLint y = height - (idirty.y() + idirty.height()); // layout: {x, y, width, height} EGLint rects[4] = { idirty.x(), y, idirty.width(), idirty.height() }; EGLint numrects = dirty.isEmpty() ? 0 : 1; // TODO: Remove prior to enabling this path by default ALOGD("Swap buffers with damage %d: %d, %d, %d, %d (src=" RECT_STRING ")", dirty.isEmpty() ? 0 : 1, rects[0], rects[1], rects[2], rects[3], SK_RECT_ARGS(dirty)); eglSwapBuffersWithDamageKHR(mEglDisplay, surface, rects, numrects); } else { eglSwapBuffers(mEglDisplay, surface); } #else eglSwapBuffers(mEglDisplay, surface); #endif EGLint err = eglGetError(); if (CC_LIKELY(err == EGL_SUCCESS)) { return true; Loading