Loading libs/hwui/FrameInfo.h +5 −0 Original line number Diff line number Diff line Loading @@ -53,6 +53,7 @@ enum class FrameInfoFlags { kWindowLayoutChanged = 1 << 0, kRTAnimation = 1 << 1, kSurfaceCanvas = 1 << 2, kSkippedFrame = 1 << 3, }; MAKE_FLAGS_ENUM(FrameInfoFlags) Loading Loading @@ -101,6 +102,10 @@ public: set(FrameInfoIndex::kFrameCompleted) = systemTime(CLOCK_MONOTONIC); } void addFlag(FrameInfoFlags flag) { set(FrameInfoIndex::kFlags) |= static_cast<uint64_t>(flag); } int64_t operator[](FrameInfoIndex index) const { if (index == FrameInfoIndex::kNumIndexes) return 0; return mFrameInfo[static_cast<int>(index)]; Loading libs/hwui/renderthread/CanvasContext.cpp +26 −3 Original line number Diff line number Diff line Loading @@ -27,12 +27,25 @@ #include "../OpenGLRenderer.h" #include <algorithm> #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 @@ -45,6 +58,9 @@ 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 @@ -203,12 +219,17 @@ void CanvasContext::draw() { LOG_ALWAYS_FATAL_IF(!mCanvas || mEglSurface == EGL_NO_SURFACE, "drawRenderNode called on a context with no canvas or surface!"); profiler().markPlaybackStart(); mCurrentFrameInfo->markIssueDrawCommandsStart(); SkRect dirty; mDamageAccumulator.finish(&dirty); if (dirty.isEmpty() && sSkipEmptyDamage) { mCurrentFrameInfo->addFlag(FrameInfoFlags::kSkippedFrame); return; } profiler().markPlaybackStart(); mCurrentFrameInfo->markIssueDrawCommandsStart(); EGLint width, height; mEglManager.beginFrame(mEglSurface, &width, &height); if (width != mCanvas->getViewportWidth() || height != mCanvas->getViewportHeight()) { Loading Loading @@ -277,6 +298,8 @@ void CanvasContext::doFrame() { prepareTree(info, frameInfo); if (info.out.canDrawThisFrame) { draw(); } else { mCurrentFrameInfo->addFlag(FrameInfoFlags::kSkippedFrame); } } Loading Loading
libs/hwui/FrameInfo.h +5 −0 Original line number Diff line number Diff line Loading @@ -53,6 +53,7 @@ enum class FrameInfoFlags { kWindowLayoutChanged = 1 << 0, kRTAnimation = 1 << 1, kSurfaceCanvas = 1 << 2, kSkippedFrame = 1 << 3, }; MAKE_FLAGS_ENUM(FrameInfoFlags) Loading Loading @@ -101,6 +102,10 @@ public: set(FrameInfoIndex::kFrameCompleted) = systemTime(CLOCK_MONOTONIC); } void addFlag(FrameInfoFlags flag) { set(FrameInfoIndex::kFlags) |= static_cast<uint64_t>(flag); } int64_t operator[](FrameInfoIndex index) const { if (index == FrameInfoIndex::kNumIndexes) return 0; return mFrameInfo[static_cast<int>(index)]; Loading
libs/hwui/renderthread/CanvasContext.cpp +26 −3 Original line number Diff line number Diff line Loading @@ -27,12 +27,25 @@ #include "../OpenGLRenderer.h" #include <algorithm> #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 @@ -45,6 +58,9 @@ 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 @@ -203,12 +219,17 @@ void CanvasContext::draw() { LOG_ALWAYS_FATAL_IF(!mCanvas || mEglSurface == EGL_NO_SURFACE, "drawRenderNode called on a context with no canvas or surface!"); profiler().markPlaybackStart(); mCurrentFrameInfo->markIssueDrawCommandsStart(); SkRect dirty; mDamageAccumulator.finish(&dirty); if (dirty.isEmpty() && sSkipEmptyDamage) { mCurrentFrameInfo->addFlag(FrameInfoFlags::kSkippedFrame); return; } profiler().markPlaybackStart(); mCurrentFrameInfo->markIssueDrawCommandsStart(); EGLint width, height; mEglManager.beginFrame(mEglSurface, &width, &height); if (width != mCanvas->getViewportWidth() || height != mCanvas->getViewportHeight()) { Loading Loading @@ -277,6 +298,8 @@ void CanvasContext::doFrame() { prepareTree(info, frameInfo); if (info.out.canDrawThisFrame) { draw(); } else { mCurrentFrameInfo->addFlag(FrameInfoFlags::kSkippedFrame); } } Loading