diff options
Diffstat (limited to 'libs')
| -rw-r--r-- | libs/hwui/RenderNode.cpp | 12 | ||||
| -rw-r--r-- | libs/hwui/renderthread/CanvasContext.cpp | 5 | ||||
| -rw-r--r-- | libs/hwui/renderthread/CanvasContext.h | 5 | ||||
| -rw-r--r-- | libs/hwui/tests/unit/RenderNodeTests.cpp | 41 |
4 files changed, 58 insertions, 5 deletions
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index b31c554c1914..5a3300ab8044 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -421,12 +421,14 @@ void RenderNode::prepareTreeImpl(TreeInfo& info, bool functorsNeedLayer) { prepareSubTree(info, childFunctorsNeedLayer, mDisplayList); pushLayerUpdate(info); - for (auto& vectorDrawable : mDisplayList->getVectorDrawables()) { - // If any vector drawable in the display list needs update, damage the node. - if (vectorDrawable->isDirty()) { - damageSelf(info); + if (mDisplayList) { + for (auto& vectorDrawable : mDisplayList->getVectorDrawables()) { + // If any vector drawable in the display list needs update, damage the node. + if (vectorDrawable->isDirty()) { + damageSelf(info); + } + vectorDrawable->setPropertyChangeWillBeConsumed(true); } - vectorDrawable->setPropertyChangeWillBeConsumed(true); } info.damageAccumulator->popTransform(); diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index 597c5c56eec2..d4956bed25e8 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -149,6 +149,8 @@ void CanvasContext::setStopped(bool stopped) { if (mEglManager.isCurrent(mEglSurface)) { mEglManager.makeCurrent(EGL_NO_SURFACE); } + } else if (mIsDirty && hasSurface()) { + mRenderThread.postFrameCallback(this); } } } @@ -231,6 +233,8 @@ void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo, freePrefetchedLayers(info.observer); GL_CHECKPOINT(MODERATE); + mIsDirty = true; + if (CC_UNLIKELY(!mNativeSurface.get())) { mCurrentFrameInfo->addFlag(FrameInfoFlags::SkippedFrame); info.out.canDrawThisFrame = false; @@ -504,6 +508,7 @@ void CanvasContext::draw() { // Even if we decided to cancel the frame, from the perspective of jank // metrics the frame was swapped at this point mCurrentFrameInfo->markSwapBuffers(); + mIsDirty = false; if (drew || mEglManager.damageRequiresSwap()) { if (CC_UNLIKELY(!mEglManager.swapBuffers(frame, screenDirty))) { diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h index e739b2949cf9..a6eb7adc3568 100644 --- a/libs/hwui/renderthread/CanvasContext.h +++ b/libs/hwui/renderthread/CanvasContext.h @@ -187,7 +187,12 @@ private: EglManager& mEglManager; sp<Surface> mNativeSurface; EGLSurface mEglSurface = EGL_NO_SURFACE; + // stopped indicates the CanvasContext will reject actual redraw operations, + // and defer repaint until it is un-stopped bool mStopped = false; + // CanvasContext is dirty if it has received an update that it has not + // painted onto its surface. + bool mIsDirty = false; bool mBufferPreserved = false; SwapBehavior mSwapBehavior = kSwap_default; struct SwapHistory { diff --git a/libs/hwui/tests/unit/RenderNodeTests.cpp b/libs/hwui/tests/unit/RenderNodeTests.cpp index b2997dfb357f..cf76a8691dcd 100644 --- a/libs/hwui/tests/unit/RenderNodeTests.cpp +++ b/libs/hwui/tests/unit/RenderNodeTests.cpp @@ -16,13 +16,26 @@ #include <gtest/gtest.h> +#include "AnimationContext.h" +#include "DamageAccumulator.h" +#include "IContextFactory.h" #include "RenderNode.h" #include "TreeInfo.h" +#include "renderthread/CanvasContext.h" #include "tests/common/TestUtils.h" #include "utils/Color.h" using namespace android; using namespace android::uirenderer; +using namespace android::uirenderer::renderthread; + +class ContextFactory : public android::uirenderer::IContextFactory { +public: + android::uirenderer::AnimationContext* createAnimationContext + (android::uirenderer::renderthread::TimeLord& clock) override { + return new android::uirenderer::AnimationContext(clock); + } +}; TEST(RenderNode, hasParents) { auto child = TestUtils::createNode(0, 0, 200, 400, @@ -89,3 +102,31 @@ TEST(RenderNode, releasedCallback) { TestUtils::syncHierarchyPropertiesAndDisplayList(node); EXPECT_EQ(0, refcnt); } + +RENDERTHREAD_TEST(RenderNode, prepareTree_nullableDisplayList) { + ContextFactory contextFactory; + CanvasContext canvasContext(renderThread, false, nullptr, &contextFactory); + TreeInfo info(TreeInfo::MODE_RT_ONLY, canvasContext); + DamageAccumulator damageAccumulator; + info.damageAccumulator = &damageAccumulator; + info.observer = nullptr; + + { + auto nonNullDLNode = TestUtils::createNode(0, 0, 200, 400, + [](RenderProperties& props, TestCanvas& canvas) { + canvas.drawColor(Color::Red_500, SkXfermode::kSrcOver_Mode); + }); + TestUtils::syncHierarchyPropertiesAndDisplayList(nonNullDLNode); + EXPECT_TRUE(nonNullDLNode->getDisplayList()); + nonNullDLNode->prepareTree(info); + } + + { + auto nullDLNode = TestUtils::createNode(0, 0, 200, 400, nullptr); + TestUtils::syncHierarchyPropertiesAndDisplayList(nullDLNode); + EXPECT_FALSE(nullDLNode->getDisplayList()); + nullDLNode->prepareTree(info); + } + + canvasContext.destroy(nullptr); +} |