Merge "Do not cache AVDs that are off screen" into qt-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
949305fe52
@@ -25,6 +25,7 @@ TreeInfo::TreeInfo(TraversalMode mode, renderthread::CanvasContext& canvasContex
|
||||
, prepareTextures(mode == MODE_FULL)
|
||||
, canvasContext(canvasContext)
|
||||
, damageGenerationId(canvasContext.getFrameNumber())
|
||||
, disableForceDark(canvasContext.useForceDark() ? 0 : 1) {}
|
||||
, disableForceDark(canvasContext.useForceDark() ? 0 : 1)
|
||||
, screenSize(canvasContext.getNextFrameSize()) {}
|
||||
|
||||
} // namespace android::uirenderer
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "utils/Macros.h"
|
||||
|
||||
#include <utils/Timers.h>
|
||||
#include "SkSize.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
@@ -96,6 +97,8 @@ public:
|
||||
|
||||
int disableForceDark;
|
||||
|
||||
const SkISize screenSize;
|
||||
|
||||
struct Out {
|
||||
bool hasFunctors = false;
|
||||
// This is only updated if evaluateAnimations is true
|
||||
|
||||
@@ -547,6 +547,11 @@ void Tree::Cache::clear() {
|
||||
}
|
||||
|
||||
void Tree::draw(SkCanvas* canvas, const SkRect& bounds, const SkPaint& inPaint) {
|
||||
if (canvas->quickReject(bounds)) {
|
||||
// The RenderNode is on screen, but the AVD is not.
|
||||
return;
|
||||
}
|
||||
|
||||
// Update the paint for any animatable properties
|
||||
SkPaint paint = inPaint;
|
||||
paint.setAlpha(mProperties.getRootAlpha() * 255);
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "renderthread/CanvasContext.h"
|
||||
|
||||
#include <SkImagePriv.h>
|
||||
#include <SkPathOps.h>
|
||||
|
||||
namespace android {
|
||||
namespace uirenderer {
|
||||
@@ -35,7 +36,7 @@ void SkiaDisplayList::syncContents(const WebViewSyncData& data) {
|
||||
animatedImage->syncProperties();
|
||||
}
|
||||
for (auto& vectorDrawable : mVectorDrawables) {
|
||||
vectorDrawable->syncProperties();
|
||||
vectorDrawable.first->syncProperties();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,6 +52,29 @@ void SkiaDisplayList::updateChildren(std::function<void(RenderNode*)> updateFn)
|
||||
}
|
||||
}
|
||||
|
||||
static bool intersects(const SkISize screenSize, const Matrix4& mat, const SkRect& bounds) {
|
||||
Vector3 points[] = { Vector3 {bounds.fLeft, bounds.fTop, 0},
|
||||
Vector3 {bounds.fRight, bounds.fTop, 0},
|
||||
Vector3 {bounds.fRight, bounds.fBottom, 0},
|
||||
Vector3 {bounds.fLeft, bounds.fBottom, 0}};
|
||||
float minX, minY, maxX, maxY;
|
||||
bool first = true;
|
||||
for (auto& point : points) {
|
||||
mat.mapPoint3d(point);
|
||||
if (first) {
|
||||
minX = maxX = point.x;
|
||||
minY = maxY = point.y;
|
||||
first = false;
|
||||
} else {
|
||||
minX = std::min(minX, point.x);
|
||||
minY = std::min(minY, point.y);
|
||||
maxX = std::max(maxX, point.x);
|
||||
maxY = std::max(maxY, point.y);
|
||||
}
|
||||
}
|
||||
return SkRect::Make(screenSize).intersects(SkRect::MakeLTRB(minX, minY, maxX, maxY));
|
||||
}
|
||||
|
||||
bool SkiaDisplayList::prepareListAndChildren(
|
||||
TreeObserver& observer, TreeInfo& info, bool functorsNeedLayer,
|
||||
std::function<void(RenderNode*, TreeObserver&, TreeInfo&, bool)> childFn) {
|
||||
@@ -107,15 +131,23 @@ bool SkiaDisplayList::prepareListAndChildren(
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& vectorDrawable : mVectorDrawables) {
|
||||
for (auto& vectorDrawablePair : mVectorDrawables) {
|
||||
// If any vector drawable in the display list needs update, damage the node.
|
||||
auto& vectorDrawable = vectorDrawablePair.first;
|
||||
if (vectorDrawable->isDirty()) {
|
||||
isDirty = true;
|
||||
static_cast<SkiaPipeline*>(info.canvasContext.getRenderPipeline())
|
||||
->getVectorDrawables()
|
||||
->push_back(vectorDrawable);
|
||||
Matrix4 totalMatrix;
|
||||
info.damageAccumulator->computeCurrentTransform(&totalMatrix);
|
||||
Matrix4 canvasMatrix(vectorDrawablePair.second);
|
||||
totalMatrix.multiply(canvasMatrix);
|
||||
const SkRect& bounds = vectorDrawable->properties().getBounds();
|
||||
if (intersects(info.screenSize, totalMatrix, bounds)) {
|
||||
isDirty = true;
|
||||
static_cast<SkiaPipeline*>(info.canvasContext.getRenderPipeline())
|
||||
->getVectorDrawables()
|
||||
->push_back(vectorDrawable);
|
||||
vectorDrawable->setPropertyChangeWillBeConsumed(true);
|
||||
}
|
||||
}
|
||||
vectorDrawable->setPropertyChangeWillBeConsumed(true);
|
||||
}
|
||||
return isDirty;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "TreeInfo.h"
|
||||
#include "hwui/AnimatedImageDrawable.h"
|
||||
#include "utils/LinearAllocator.h"
|
||||
#include "utils/Pair.h"
|
||||
|
||||
#include <deque>
|
||||
|
||||
@@ -41,12 +42,6 @@ typedef uirenderer::VectorDrawable::Tree VectorDrawableRoot;
|
||||
|
||||
namespace skiapipeline {
|
||||
|
||||
/**
|
||||
* This class is intended to be self contained, but still subclasses from
|
||||
* DisplayList to make it easier to support switching between the two at
|
||||
* runtime. The downside of this inheritance is that we pay for the overhead
|
||||
* of the parent class construction/destruction without any real benefit.
|
||||
*/
|
||||
class SkiaDisplayList {
|
||||
public:
|
||||
size_t getUsedSize() { return allocator.usedSize() + mDisplayList.usedSize(); }
|
||||
@@ -156,7 +151,17 @@ public:
|
||||
std::deque<RenderNodeDrawable> mChildNodes;
|
||||
std::deque<FunctorDrawable*> mChildFunctors;
|
||||
std::vector<SkImage*> mMutableImages;
|
||||
std::vector<VectorDrawableRoot*> mVectorDrawables;
|
||||
private:
|
||||
std::vector<Pair<VectorDrawableRoot*, SkMatrix>> mVectorDrawables;
|
||||
public:
|
||||
void appendVD(VectorDrawableRoot* r) {
|
||||
appendVD(r, SkMatrix::I());
|
||||
}
|
||||
|
||||
void appendVD(VectorDrawableRoot* r, const SkMatrix& mat) {
|
||||
mVectorDrawables.push_back(Pair<VectorDrawableRoot*, SkMatrix>(r, mat));
|
||||
}
|
||||
|
||||
std::vector<AnimatedImageDrawable*> mAnimatedImages;
|
||||
DisplayListData mDisplayList;
|
||||
|
||||
|
||||
@@ -152,7 +152,9 @@ void SkiaRecordingCanvas::drawWebViewFunctor(int functor) {
|
||||
|
||||
void SkiaRecordingCanvas::drawVectorDrawable(VectorDrawableRoot* tree) {
|
||||
mRecorder.drawVectorDrawable(tree);
|
||||
mDisplayList->mVectorDrawables.push_back(tree);
|
||||
SkMatrix mat;
|
||||
this->getMatrix(&mat);
|
||||
mDisplayList->appendVD(tree, mat);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#include <sys/stat.h>
|
||||
#include <algorithm>
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <functional>
|
||||
|
||||
@@ -510,6 +511,17 @@ void CanvasContext::doFrame() {
|
||||
prepareAndDraw(nullptr);
|
||||
}
|
||||
|
||||
SkISize CanvasContext::getNextFrameSize() const {
|
||||
ReliableSurface* surface = mNativeSurface.get();
|
||||
if (surface) {
|
||||
SkISize size;
|
||||
surface->query(NATIVE_WINDOW_WIDTH, &size.fWidth);
|
||||
surface->query(NATIVE_WINDOW_HEIGHT, &size.fHeight);
|
||||
return size;
|
||||
}
|
||||
return {INT32_MAX, INT32_MAX};
|
||||
}
|
||||
|
||||
void CanvasContext::prepareAndDraw(RenderNode* node) {
|
||||
ATRACE_CALL();
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <EGL/egl.h>
|
||||
#include <SkBitmap.h>
|
||||
#include <SkRect.h>
|
||||
#include <SkSize.h>
|
||||
#include <cutils/compiler.h>
|
||||
#include <gui/Surface.h>
|
||||
#include <utils/Functor.h>
|
||||
@@ -112,7 +113,7 @@ public:
|
||||
void setSurface(sp<Surface>&& surface);
|
||||
bool pauseSurface();
|
||||
void setStopped(bool stopped);
|
||||
bool hasSurface() { return mNativeSurface.get(); }
|
||||
bool hasSurface() const { return mNativeSurface.get(); }
|
||||
void allocateBuffers();
|
||||
|
||||
void setLightAlpha(uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
|
||||
@@ -205,6 +206,8 @@ public:
|
||||
// Must be called before setSurface
|
||||
void setRenderAheadDepth(uint32_t renderAhead);
|
||||
|
||||
SkISize getNextFrameSize() const;
|
||||
|
||||
private:
|
||||
CanvasContext(RenderThread& thread, bool translucent, RenderNode* rootRenderNode,
|
||||
IContextFactory* contextFactory, std::unique_ptr<IRenderPipeline> renderPipeline);
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "pipeline/skia/GLFunctorDrawable.h"
|
||||
#include "pipeline/skia/SkiaDisplayList.h"
|
||||
#include "renderthread/CanvasContext.h"
|
||||
#include "tests/common/TestContext.h"
|
||||
#include "tests/common/TestUtils.h"
|
||||
|
||||
using namespace android;
|
||||
@@ -50,13 +51,13 @@ TEST(SkiaDisplayList, reset) {
|
||||
GLFunctorDrawable functorDrawable(nullptr, nullptr, &dummyCanvas);
|
||||
skiaDL->mChildFunctors.push_back(&functorDrawable);
|
||||
skiaDL->mMutableImages.push_back(nullptr);
|
||||
skiaDL->mVectorDrawables.push_back(nullptr);
|
||||
skiaDL->appendVD(nullptr);
|
||||
skiaDL->mProjectionReceiver = &drawable;
|
||||
|
||||
ASSERT_FALSE(skiaDL->mChildNodes.empty());
|
||||
ASSERT_FALSE(skiaDL->mChildFunctors.empty());
|
||||
ASSERT_FALSE(skiaDL->mMutableImages.empty());
|
||||
ASSERT_FALSE(skiaDL->mVectorDrawables.empty());
|
||||
ASSERT_TRUE(skiaDL->hasVectorDrawables());
|
||||
ASSERT_FALSE(skiaDL->isEmpty());
|
||||
ASSERT_TRUE(skiaDL->mProjectionReceiver);
|
||||
|
||||
@@ -65,7 +66,7 @@ TEST(SkiaDisplayList, reset) {
|
||||
ASSERT_TRUE(skiaDL->mChildNodes.empty());
|
||||
ASSERT_TRUE(skiaDL->mChildFunctors.empty());
|
||||
ASSERT_TRUE(skiaDL->mMutableImages.empty());
|
||||
ASSERT_TRUE(skiaDL->mVectorDrawables.empty());
|
||||
ASSERT_FALSE(skiaDL->hasVectorDrawables());
|
||||
ASSERT_TRUE(skiaDL->isEmpty());
|
||||
ASSERT_FALSE(skiaDL->mProjectionReceiver);
|
||||
}
|
||||
@@ -110,7 +111,7 @@ TEST(SkiaDisplayList, syncContexts) {
|
||||
SkRect bounds = SkRect::MakeWH(200, 200);
|
||||
VectorDrawableRoot vectorDrawable(new VectorDrawable::Group());
|
||||
vectorDrawable.mutateStagingProperties()->setBounds(bounds);
|
||||
skiaDL.mVectorDrawables.push_back(&vectorDrawable);
|
||||
skiaDL.appendVD(&vectorDrawable);
|
||||
|
||||
// ensure that the functor and vectorDrawable are properly synced
|
||||
TestUtils::runOnRenderThread([&](auto&) {
|
||||
@@ -149,9 +150,14 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaDisplayList, prepareListAndChildren) {
|
||||
|
||||
SkiaDisplayList skiaDL;
|
||||
|
||||
// The VectorDrawableRoot needs to have bounds on screen (and therefore not
|
||||
// empty) in order to have PropertyChangeWillBeConsumed set.
|
||||
const auto bounds = SkRect::MakeIWH(100, 100);
|
||||
|
||||
// prepare with a clean VD
|
||||
VectorDrawableRoot cleanVD(new VectorDrawable::Group());
|
||||
skiaDL.mVectorDrawables.push_back(&cleanVD);
|
||||
cleanVD.mutateProperties()->setBounds(bounds);
|
||||
skiaDL.appendVD(&cleanVD);
|
||||
cleanVD.getBitmapUpdateIfDirty(); // this clears the dirty bit
|
||||
|
||||
ASSERT_FALSE(cleanVD.isDirty());
|
||||
@@ -159,11 +165,12 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaDisplayList, prepareListAndChildren) {
|
||||
TestUtils::MockTreeObserver observer;
|
||||
ASSERT_FALSE(skiaDL.prepareListAndChildren(observer, info, false,
|
||||
[](RenderNode*, TreeObserver&, TreeInfo&, bool) {}));
|
||||
ASSERT_TRUE(cleanVD.getPropertyChangeWillBeConsumed());
|
||||
ASSERT_FALSE(cleanVD.getPropertyChangeWillBeConsumed());
|
||||
|
||||
// prepare again this time adding a dirty VD
|
||||
VectorDrawableRoot dirtyVD(new VectorDrawable::Group());
|
||||
skiaDL.mVectorDrawables.push_back(&dirtyVD);
|
||||
dirtyVD.mutateProperties()->setBounds(bounds);
|
||||
skiaDL.appendVD(&dirtyVD);
|
||||
|
||||
ASSERT_TRUE(dirtyVD.isDirty());
|
||||
ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
|
||||
@@ -191,6 +198,169 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaDisplayList, prepareListAndChildren) {
|
||||
canvasContext->destroy();
|
||||
}
|
||||
|
||||
RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaDisplayList, prepareListAndChildren_vdOffscreen) {
|
||||
auto rootNode = TestUtils::createNode(0, 0, 200, 400, nullptr);
|
||||
ContextFactory contextFactory;
|
||||
std::unique_ptr<CanvasContext> canvasContext(
|
||||
CanvasContext::create(renderThread, false, rootNode.get(), &contextFactory));
|
||||
|
||||
// Set up a Surface so that we can position the VectorDrawable offscreen.
|
||||
test::TestContext testContext;
|
||||
testContext.setRenderOffscreen(true);
|
||||
auto surface = testContext.surface();
|
||||
int width, height;
|
||||
surface->query(NATIVE_WINDOW_WIDTH, &width);
|
||||
surface->query(NATIVE_WINDOW_HEIGHT, &height);
|
||||
canvasContext->setSurface(std::move(surface));
|
||||
|
||||
TreeInfo info(TreeInfo::MODE_FULL, *canvasContext.get());
|
||||
DamageAccumulator damageAccumulator;
|
||||
info.damageAccumulator = &damageAccumulator;
|
||||
|
||||
// The VectorDrawableRoot needs to have bounds on screen (and therefore not
|
||||
// empty) in order to have PropertyChangeWillBeConsumed set.
|
||||
const auto bounds = SkRect::MakeIWH(100, 100);
|
||||
|
||||
for (const SkRect b : {bounds.makeOffset(width, 0),
|
||||
bounds.makeOffset(0, height),
|
||||
bounds.makeOffset(-bounds.width(), 0),
|
||||
bounds.makeOffset(0, -bounds.height())}) {
|
||||
SkiaDisplayList skiaDL;
|
||||
VectorDrawableRoot dirtyVD(new VectorDrawable::Group());
|
||||
dirtyVD.mutateProperties()->setBounds(b);
|
||||
skiaDL.appendVD(&dirtyVD);
|
||||
|
||||
ASSERT_TRUE(dirtyVD.isDirty());
|
||||
ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
|
||||
|
||||
TestUtils::MockTreeObserver observer;
|
||||
ASSERT_FALSE(skiaDL.prepareListAndChildren(
|
||||
observer, info, false, [](RenderNode*, TreeObserver&, TreeInfo&, bool) {}));
|
||||
ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
|
||||
}
|
||||
|
||||
// The DamageAccumulator's transform can also result in the
|
||||
// VectorDrawableRoot being offscreen.
|
||||
for (const SkISize translate : { SkISize{width, 0},
|
||||
SkISize{0, height},
|
||||
SkISize{-width, 0},
|
||||
SkISize{0, -height}}) {
|
||||
Matrix4 mat4;
|
||||
mat4.translate(translate.fWidth, translate.fHeight);
|
||||
damageAccumulator.pushTransform(&mat4);
|
||||
|
||||
SkiaDisplayList skiaDL;
|
||||
VectorDrawableRoot dirtyVD(new VectorDrawable::Group());
|
||||
dirtyVD.mutateProperties()->setBounds(bounds);
|
||||
skiaDL.appendVD(&dirtyVD);
|
||||
|
||||
ASSERT_TRUE(dirtyVD.isDirty());
|
||||
ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
|
||||
|
||||
TestUtils::MockTreeObserver observer;
|
||||
ASSERT_FALSE(skiaDL.prepareListAndChildren(
|
||||
observer, info, false, [](RenderNode*, TreeObserver&, TreeInfo&, bool) {}));
|
||||
ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
|
||||
damageAccumulator.popTransform();
|
||||
}
|
||||
|
||||
// Another way to be offscreen: a matrix from the draw call.
|
||||
for (const SkMatrix translate : { SkMatrix::MakeTrans(width, 0),
|
||||
SkMatrix::MakeTrans(0, height),
|
||||
SkMatrix::MakeTrans(-width, 0),
|
||||
SkMatrix::MakeTrans(0, -height)}) {
|
||||
SkiaDisplayList skiaDL;
|
||||
VectorDrawableRoot dirtyVD(new VectorDrawable::Group());
|
||||
dirtyVD.mutateProperties()->setBounds(bounds);
|
||||
skiaDL.appendVD(&dirtyVD, translate);
|
||||
|
||||
ASSERT_TRUE(dirtyVD.isDirty());
|
||||
ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
|
||||
|
||||
TestUtils::MockTreeObserver observer;
|
||||
ASSERT_FALSE(skiaDL.prepareListAndChildren(
|
||||
observer, info, false, [](RenderNode*, TreeObserver&, TreeInfo&, bool) {}));
|
||||
ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
|
||||
}
|
||||
|
||||
// Verify that the matrices are combined in the right order.
|
||||
{
|
||||
// Rotate and then translate, so the VD is offscreen.
|
||||
Matrix4 mat4;
|
||||
mat4.loadRotate(180);
|
||||
damageAccumulator.pushTransform(&mat4);
|
||||
|
||||
SkiaDisplayList skiaDL;
|
||||
VectorDrawableRoot dirtyVD(new VectorDrawable::Group());
|
||||
dirtyVD.mutateProperties()->setBounds(bounds);
|
||||
SkMatrix translate = SkMatrix::MakeTrans(50, 50);
|
||||
skiaDL.appendVD(&dirtyVD, translate);
|
||||
|
||||
ASSERT_TRUE(dirtyVD.isDirty());
|
||||
ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
|
||||
|
||||
TestUtils::MockTreeObserver observer;
|
||||
ASSERT_FALSE(skiaDL.prepareListAndChildren(
|
||||
observer, info, false, [](RenderNode*, TreeObserver&, TreeInfo&, bool) {}));
|
||||
ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
|
||||
damageAccumulator.popTransform();
|
||||
}
|
||||
{
|
||||
// Switch the order of rotate and translate, so it is on screen.
|
||||
Matrix4 mat4;
|
||||
mat4.translate(50, 50);
|
||||
damageAccumulator.pushTransform(&mat4);
|
||||
|
||||
SkiaDisplayList skiaDL;
|
||||
VectorDrawableRoot dirtyVD(new VectorDrawable::Group());
|
||||
dirtyVD.mutateProperties()->setBounds(bounds);
|
||||
SkMatrix rotate;
|
||||
rotate.setRotate(180);
|
||||
skiaDL.appendVD(&dirtyVD, rotate);
|
||||
|
||||
ASSERT_TRUE(dirtyVD.isDirty());
|
||||
ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
|
||||
|
||||
TestUtils::MockTreeObserver observer;
|
||||
ASSERT_TRUE(skiaDL.prepareListAndChildren(
|
||||
observer, info, false, [](RenderNode*, TreeObserver&, TreeInfo&, bool) {}));
|
||||
ASSERT_TRUE(dirtyVD.getPropertyChangeWillBeConsumed());
|
||||
damageAccumulator.popTransform();
|
||||
}
|
||||
{
|
||||
// An AVD that is larger than the screen.
|
||||
SkiaDisplayList skiaDL;
|
||||
VectorDrawableRoot dirtyVD(new VectorDrawable::Group());
|
||||
dirtyVD.mutateProperties()->setBounds(SkRect::MakeLTRB(-1, -1, width + 1, height + 1));
|
||||
skiaDL.appendVD(&dirtyVD);
|
||||
|
||||
ASSERT_TRUE(dirtyVD.isDirty());
|
||||
ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
|
||||
|
||||
TestUtils::MockTreeObserver observer;
|
||||
ASSERT_TRUE(skiaDL.prepareListAndChildren(
|
||||
observer, info, false, [](RenderNode*, TreeObserver&, TreeInfo&, bool) {}));
|
||||
ASSERT_TRUE(dirtyVD.getPropertyChangeWillBeConsumed());
|
||||
}
|
||||
{
|
||||
// An AVD whose bounds are not a rectangle after applying a matrix.
|
||||
SkiaDisplayList skiaDL;
|
||||
VectorDrawableRoot dirtyVD(new VectorDrawable::Group());
|
||||
dirtyVD.mutateProperties()->setBounds(bounds);
|
||||
SkMatrix mat;
|
||||
mat.setRotate(45, 50, 50);
|
||||
skiaDL.appendVD(&dirtyVD, mat);
|
||||
|
||||
ASSERT_TRUE(dirtyVD.isDirty());
|
||||
ASSERT_FALSE(dirtyVD.getPropertyChangeWillBeConsumed());
|
||||
|
||||
TestUtils::MockTreeObserver observer;
|
||||
ASSERT_TRUE(skiaDL.prepareListAndChildren(
|
||||
observer, info, false, [](RenderNode*, TreeObserver&, TreeInfo&, bool) {}));
|
||||
ASSERT_TRUE(dirtyVD.getPropertyChangeWillBeConsumed());
|
||||
}
|
||||
}
|
||||
|
||||
TEST(SkiaDisplayList, updateChildren) {
|
||||
SkiaDisplayList skiaDL;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user