RenderNodeDrawableTests.cpp revision 3c01a07fff19c5166274de5960935875ea89e455
1021693b967a2c5556dddd183eb0247df4079e1adStan Iliev/* 2021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * Copyright (C) 2016 The Android Open Source Project 3021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * 4021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * Licensed under the Apache License, Version 2.0 (the "License"); 5021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * you may not use this file except in compliance with the License. 6021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * You may obtain a copy of the License at 7021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * 8021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * http://www.apache.org/licenses/LICENSE-2.0 9021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * 10021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * Unless required by applicable law or agreed to in writing, software 11021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * distributed under the License is distributed on an "AS IS" BASIS, 12021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * See the License for the specific language governing permissions and 14021693b967a2c5556dddd183eb0247df4079e1adStan Iliev * limitations under the License. 15021693b967a2c5556dddd183eb0247df4079e1adStan Iliev */ 16021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 17021693b967a2c5556dddd183eb0247df4079e1adStan Iliev#include <gtest/gtest.h> 18021693b967a2c5556dddd183eb0247df4079e1adStan Iliev#include <VectorDrawable.h> 19021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 20021693b967a2c5556dddd183eb0247df4079e1adStan Iliev#include "AnimationContext.h" 21021693b967a2c5556dddd183eb0247df4079e1adStan Iliev#include "DamageAccumulator.h" 22021693b967a2c5556dddd183eb0247df4079e1adStan Iliev#include "IContextFactory.h" 23021693b967a2c5556dddd183eb0247df4079e1adStan Iliev#include "pipeline/skia/SkiaDisplayList.h" 24db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev#include "pipeline/skia/SkiaPipeline.h" 25021693b967a2c5556dddd183eb0247df4079e1adStan Iliev#include "pipeline/skia/SkiaRecordingCanvas.h" 26021693b967a2c5556dddd183eb0247df4079e1adStan Iliev#include "renderthread/CanvasContext.h" 27021693b967a2c5556dddd183eb0247df4079e1adStan Iliev#include "tests/common/TestUtils.h" 28021693b967a2c5556dddd183eb0247df4079e1adStan Iliev#include "SkiaCanvas.h" 29db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev#include <SkSurface_Base.h> 30021693b967a2c5556dddd183eb0247df4079e1adStan Iliev#include <SkLiteRecorder.h> 31db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev#include <SkClipStack.h> 3252771272f4f018f4fc6846224bf047497e784af1Stan Iliev#include "FatalTestCanvas.h" 33021693b967a2c5556dddd183eb0247df4079e1adStan Iliev#include <string.h> 34021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 35021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 36021693b967a2c5556dddd183eb0247df4079e1adStan Ilievusing namespace android; 37021693b967a2c5556dddd183eb0247df4079e1adStan Ilievusing namespace android::uirenderer; 38021693b967a2c5556dddd183eb0247df4079e1adStan Ilievusing namespace android::uirenderer::renderthread; 39021693b967a2c5556dddd183eb0247df4079e1adStan Ilievusing namespace android::uirenderer::skiapipeline; 40021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 41021693b967a2c5556dddd183eb0247df4079e1adStan IlievTEST(RenderNodeDrawable, create) { 42021693b967a2c5556dddd183eb0247df4079e1adStan Iliev auto rootNode = TestUtils::createNode(0, 0, 200, 400, 43021693b967a2c5556dddd183eb0247df4079e1adStan Iliev [](RenderProperties& props, Canvas& canvas) { 44021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas.drawColor(Color::Red_500, SkBlendMode::kSrcOver); 45021693b967a2c5556dddd183eb0247df4079e1adStan Iliev }); 46021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 47ea1fe9b9d6ff9f0a543489979a0a909acc9ea564Derek Sollenberger SkLiteDL skLiteDL; 48021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkLiteRecorder canvas; 49ea1fe9b9d6ff9f0a543489979a0a909acc9ea564Derek Sollenberger canvas.reset(&skLiteDL, SkIRect::MakeWH(1, 1)); 50021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas.translate(100, 100); 51021693b967a2c5556dddd183eb0247df4079e1adStan Iliev RenderNodeDrawable drawable(rootNode.get(), &canvas); 52021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 53021693b967a2c5556dddd183eb0247df4079e1adStan Iliev ASSERT_EQ(drawable.getRenderNode(), rootNode.get()); 54021693b967a2c5556dddd183eb0247df4079e1adStan Iliev ASSERT_EQ(&drawable.getNodeProperties(), &rootNode->properties()); 55021693b967a2c5556dddd183eb0247df4079e1adStan Iliev ASSERT_EQ(drawable.getRecordedMatrix(), canvas.getTotalMatrix()); 56021693b967a2c5556dddd183eb0247df4079e1adStan Iliev} 57021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 58db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Ilievnamespace { 59db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 602f06e8ad1a1c4d0866bb66854d2759e275898635Stan Ilievstatic void drawOrderedRect(Canvas* canvas, uint8_t expectedDrawOrder) { 612f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev SkPaint paint; 622f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev // order put in blue channel, transparent so overlapped content doesn't get rejected 632f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev paint.setColor(SkColorSetARGB(1, 0, 0, expectedDrawOrder)); 642f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev canvas->drawRect(0, 0, 100, 100, paint); 65021693b967a2c5556dddd183eb0247df4079e1adStan Iliev} 66021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 672f06e8ad1a1c4d0866bb66854d2759e275898635Stan Ilievstatic void drawOrderedNode(Canvas* canvas, uint8_t expectedDrawOrder, float z) { 682f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev auto node = TestUtils::createSkiaNode(0, 0, 100, 100, 692f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev [expectedDrawOrder, z](RenderProperties& props, SkiaRecordingCanvas& canvas) { 702f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev drawOrderedRect(&canvas, expectedDrawOrder); 712f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev props.setTranslationZ(z); 722f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev }); 732f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev canvas->drawRenderNode(node.get()); // canvas takes reference/sole ownership 742f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev} 75021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 76db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Ilievstatic void drawOrderedNode(Canvas* canvas, uint8_t expectedDrawOrder, 77db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev std::function<void(RenderProperties& props, SkiaRecordingCanvas& canvas)> setup) { 78db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto node = TestUtils::createSkiaNode(0, 0, 100, 100, 79db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [expectedDrawOrder, setup](RenderProperties& props, SkiaRecordingCanvas& canvas) { 80db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedRect(&canvas, expectedDrawOrder); 81db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev if (setup) { 82db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev setup(props, canvas); 832f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev } 84db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }); 85db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev canvas->drawRenderNode(node.get()); // canvas takes reference/sole ownership 86db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} 87db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 88db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Ilievclass ZReorderCanvas : public SkCanvas { 89db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Ilievpublic: 90db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev ZReorderCanvas(int width, int height) : SkCanvas(width, height) {} 91db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev void onDrawRect(const SkRect& rect, const SkPaint& paint) override { 92db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev int expectedOrder = SkColorGetB(paint.getColor()); // extract order from blue channel 9352771272f4f018f4fc6846224bf047497e784af1Stan Iliev EXPECT_EQ(expectedOrder, mDrawCounter++) << "An op was drawn out of order"; 94db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } 9552771272f4f018f4fc6846224bf047497e784af1Stan Iliev int getIndex() { return mDrawCounter; } 96db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Ilievprotected: 9752771272f4f018f4fc6846224bf047497e784af1Stan Iliev int mDrawCounter = 0; 98db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev}; 99db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 100db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} // end anonymous namespace 101db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 102db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan IlievTEST(RenderNodeDrawable, zReorder) { 1032f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev 1042f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev auto parent = TestUtils::createSkiaNode(0, 0, 100, 100, 1052f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev [](RenderProperties& props, SkiaRecordingCanvas& canvas) { 106347691f8d87157be0eaeca26f4003d8a06a275e3Stan Iliev canvas.insertReorderBarrier(true); 107347691f8d87157be0eaeca26f4003d8a06a275e3Stan Iliev canvas.insertReorderBarrier(false); 1082f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev drawOrderedNode(&canvas, 0, 10.0f); // in reorder=false at this point, so played inorder 1092f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev drawOrderedRect(&canvas, 1); 1102f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev canvas.insertReorderBarrier(true); 1112f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev drawOrderedNode(&canvas, 6, 2.0f); 1122f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev drawOrderedRect(&canvas, 3); 1132f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev drawOrderedNode(&canvas, 4, 0.0f); 1142f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev drawOrderedRect(&canvas, 5); 1152f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev drawOrderedNode(&canvas, 2, -2.0f); 1162f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev drawOrderedNode(&canvas, 7, 2.0f); 1172f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev canvas.insertReorderBarrier(false); 1182f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev drawOrderedRect(&canvas, 8); 1192f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev drawOrderedNode(&canvas, 9, -10.0f); // in reorder=false at this point, so played inorder 12088e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev canvas.insertReorderBarrier(true); //reorder a node ahead of drawrect op 12188e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev drawOrderedRect(&canvas, 11); 12288e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev drawOrderedNode(&canvas, 10, -1.0f); 12388e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev canvas.insertReorderBarrier(false); 12488e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev canvas.insertReorderBarrier(true); //test with two empty reorder sections 12588e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev canvas.insertReorderBarrier(true); 12688e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev canvas.insertReorderBarrier(false); 12788e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev drawOrderedRect(&canvas, 12); 1282f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev }); 1292f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev 1302f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev //create a canvas not backed by any device/pixels, but with dimensions to avoid quick rejection 1312f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev ZReorderCanvas canvas(100, 100); 1322f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev RenderNodeDrawable drawable(parent.get(), &canvas, false); 1332f06e8ad1a1c4d0866bb66854d2759e275898635Stan Iliev canvas.drawDrawable(&drawable); 13488e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev EXPECT_EQ(13, canvas.getIndex()); 135021693b967a2c5556dddd183eb0247df4079e1adStan Iliev} 136021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 137021693b967a2c5556dddd183eb0247df4079e1adStan IlievTEST(RenderNodeDrawable, composeOnLayer) 138021693b967a2c5556dddd183eb0247df4079e1adStan Iliev{ 139021693b967a2c5556dddd183eb0247df4079e1adStan Iliev auto surface = SkSurface::MakeRasterN32Premul(1, 1); 140021693b967a2c5556dddd183eb0247df4079e1adStan Iliev SkCanvas& canvas = *surface->getCanvas(); 141021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas.drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver); 142021693b967a2c5556dddd183eb0247df4079e1adStan Iliev ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE); 143021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 144500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev auto rootNode = TestUtils::createSkiaNode(0, 0, 1, 1, 145021693b967a2c5556dddd183eb0247df4079e1adStan Iliev [](RenderProperties& props, SkiaRecordingCanvas& recorder) { 146021693b967a2c5556dddd183eb0247df4079e1adStan Iliev recorder.drawColor(SK_ColorRED, SkBlendMode::kSrcOver); 147021693b967a2c5556dddd183eb0247df4079e1adStan Iliev }); 148021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 149021693b967a2c5556dddd183eb0247df4079e1adStan Iliev //attach a layer to the render node 150021693b967a2c5556dddd183eb0247df4079e1adStan Iliev auto surfaceLayer = SkSurface::MakeRasterN32Premul(1, 1); 151021693b967a2c5556dddd183eb0247df4079e1adStan Iliev auto canvas2 = surfaceLayer->getCanvas(); 152021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas2->drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver); 153500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev rootNode->setLayerSurface(surfaceLayer); 154021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 155021693b967a2c5556dddd183eb0247df4079e1adStan Iliev RenderNodeDrawable drawable1(rootNode.get(), &canvas, false); 156021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas.drawDrawable(&drawable1); 157021693b967a2c5556dddd183eb0247df4079e1adStan Iliev ASSERT_EQ(SK_ColorRED, TestUtils::getColor(surface, 0, 0)); 158021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 159021693b967a2c5556dddd183eb0247df4079e1adStan Iliev RenderNodeDrawable drawable2(rootNode.get(), &canvas, true); 160021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas.drawDrawable(&drawable2); 161021693b967a2c5556dddd183eb0247df4079e1adStan Iliev ASSERT_EQ(SK_ColorWHITE, TestUtils::getColor(surface, 0, 0)); 162021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 163021693b967a2c5556dddd183eb0247df4079e1adStan Iliev RenderNodeDrawable drawable3(rootNode.get(), &canvas, false); 164021693b967a2c5556dddd183eb0247df4079e1adStan Iliev canvas.drawDrawable(&drawable3); 165021693b967a2c5556dddd183eb0247df4079e1adStan Iliev ASSERT_EQ(SK_ColorRED, TestUtils::getColor(surface, 0, 0)); 166021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 167500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev rootNode->setLayerSurface(sk_sp<SkSurface>()); 168021693b967a2c5556dddd183eb0247df4079e1adStan Iliev} 169021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 170db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Ilievnamespace { 17168885e38b86405b333e3f8fd4ff0a104889147c4Stan Ilievstatic SkRect getRecorderClipBounds(const SkiaRecordingCanvas& recorder) { 17268885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev SkRect clipBounds; 17368885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev recorder.getClipBounds(&clipBounds); 17468885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev return clipBounds; 17568885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev} 17668885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev 17768885e38b86405b333e3f8fd4ff0a104889147c4Stan Ilievstatic SkMatrix getRecorderMatrix(const SkiaRecordingCanvas& recorder) { 17868885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev SkMatrix matrix; 17968885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev recorder.getMatrix(&matrix); 18068885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev return matrix; 18168885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev} 18268885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev} 18368885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev 18468885e38b86405b333e3f8fd4ff0a104889147c4Stan IlievTEST(RenderNodeDrawable, saveLayerClipAndMatrixRestore) 18568885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev{ 18668885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev auto surface = SkSurface::MakeRasterN32Premul(400, 800); 18768885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev SkCanvas& canvas = *surface->getCanvas(); 18868885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver); 18968885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorWHITE); 19068885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev 19168885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev auto rootNode = TestUtils::createSkiaNode(0, 0, 400, 800, 19268885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev [](RenderProperties& props, SkiaRecordingCanvas& recorder) { 19368885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev SkPaint layerPaint; 19468885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev ASSERT_EQ(SkRect::MakeLTRB(0, 0, 400, 800), getRecorderClipBounds(recorder)); 19568885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev EXPECT_TRUE(getRecorderMatrix(recorder).isIdentity()); 19668885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev 19768885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev //note we don't pass SaveFlags::MatrixClip, but matrix and clip will be saved 19868885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev recorder.saveLayer(0, 0, 400, 400, &layerPaint, SaveFlags::ClipToLayer); 19968885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev ASSERT_EQ(SkRect::MakeLTRB(0, 0, 400, 400), getRecorderClipBounds(recorder)); 20068885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev EXPECT_TRUE(getRecorderMatrix(recorder).isIdentity()); 20168885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev 20268885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev recorder.clipRect(50, 50, 350, 350, SkClipOp::kIntersect); 20368885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev ASSERT_EQ(SkRect::MakeLTRB(50, 50, 350, 350), getRecorderClipBounds(recorder)); 20468885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev 20568885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev recorder.translate(300.0f, 400.0f); 20668885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev EXPECT_EQ(SkMatrix::MakeTrans(300.0f, 400.0f), getRecorderMatrix(recorder)); 20768885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev 20868885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev recorder.restore(); 20968885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev ASSERT_EQ(SkRect::MakeLTRB(0, 0, 400, 800), getRecorderClipBounds(recorder)); 21068885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev EXPECT_TRUE(getRecorderMatrix(recorder).isIdentity()); 21168885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev 21268885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev SkPaint paint; 21368885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev paint.setAntiAlias(true); 21468885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev paint.setColor(SK_ColorGREEN); 21568885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev recorder.drawRect(0.0f, 400.0f, 400.0f, 800.0f, paint); 21668885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev }); 21768885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev 21868885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev RenderNodeDrawable drawable(rootNode.get(), &canvas, true); 21968885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev canvas.drawDrawable(&drawable); 22068885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev ASSERT_EQ(SK_ColorGREEN, TestUtils::getColor(surface, 200, 600)); 22168885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev} 22268885e38b86405b333e3f8fd4ff0a104889147c4Stan Iliev 22368885e38b86405b333e3f8fd4ff0a104889147c4Stan Ilievnamespace { 224db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Ilievclass ContextFactory : public IContextFactory { 225db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Ilievpublic: 226db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) override { 227db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev return new AnimationContext(clock); 228db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } 229db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev}; 230db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} // end anonymous namespace 231021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 232db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan IlievRENDERTHREAD_TEST(RenderNodeDrawable, projectionReorder) { 233db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev static const int SCROLL_X = 5; 234db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev static const int SCROLL_Y = 10; 235db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev class ProjectionTestCanvas : public SkCanvas { 236db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev public: 237db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev ProjectionTestCanvas(int width, int height) : SkCanvas(width, height) {} 238db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev void onDrawRect(const SkRect& rect, const SkPaint& paint) override { 23952771272f4f018f4fc6846224bf047497e784af1Stan Iliev const int index = mDrawCounter++; 240db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev SkMatrix expectedMatrix;; 241db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev switch (index) { 242db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev case 0: //this is node "B" 243db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(SkRect::MakeWH(100, 100), rect); 244db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(SK_ColorWHITE, paint.getColor()); 245db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev expectedMatrix.reset(); 24652771272f4f018f4fc6846224bf047497e784af1Stan Iliev EXPECT_EQ(SkRect::MakeLTRB(0, 0, 100, 100), TestUtils::getClipBounds(this)); 247db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev break; 248db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev case 1: //this is node "P" 249db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(SkRect::MakeLTRB(-10, -10, 60, 60), rect); 250db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(SK_ColorDKGRAY, paint.getColor()); 251db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev expectedMatrix.setTranslate(50 - SCROLL_X, 50 - SCROLL_Y); 25252771272f4f018f4fc6846224bf047497e784af1Stan Iliev EXPECT_EQ(SkRect::MakeLTRB(-35, -30, 45, 50), TestUtils::getLocalClipBounds(this)); 253db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev break; 254db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev case 2: //this is node "C" 255db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(SkRect::MakeWH(100, 50), rect); 256db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(SK_ColorBLUE, paint.getColor()); 257db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev expectedMatrix.setTranslate(-SCROLL_X, 50 - SCROLL_Y); 25852771272f4f018f4fc6846224bf047497e784af1Stan Iliev EXPECT_EQ(SkRect::MakeLTRB(0, 40, 95, 90), TestUtils::getClipBounds(this)); 259db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev break; 260db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev default: 261db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev ADD_FAILURE(); 262db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } 263db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(expectedMatrix, getTotalMatrix()); 264db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } 265021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 26652771272f4f018f4fc6846224bf047497e784af1Stan Iliev int getIndex() { return mDrawCounter; } 267db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev protected: 26852771272f4f018f4fc6846224bf047497e784af1Stan Iliev int mDrawCounter = 0; 269db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }; 270db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 271db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev /** 272db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev * Construct a tree of nodes, where the root (A) has a receiver background (B), and a child (C) 273db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev * with a projecting child (P) of its own. P would normally draw between B and C's "background" 274db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev * draw, but because it is projected backwards, it's drawn in between B and C. 275db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev * 276db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev * The parent is scrolled by SCROLL_X/SCROLL_Y, but this does not affect the background 277db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev * (which isn't affected by scroll). 278db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev */ 279db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto receiverBackground = TestUtils::createSkiaNode(0, 0, 100, 100, 280db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [](RenderProperties& properties, SkiaRecordingCanvas& canvas) { 281db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev properties.setProjectionReceiver(true); 282db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev // scroll doesn't apply to background, so undone via translationX/Y 283db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver! 284db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev properties.setTranslationX(SCROLL_X); 285db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev properties.setTranslationY(SCROLL_Y); 286db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 287db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev SkPaint paint; 288db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev paint.setColor(SK_ColorWHITE); 289db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev canvas.drawRect(0, 0, 100, 100, paint); 290db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }, "B"); 291db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 292db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto projectingRipple = TestUtils::createSkiaNode(50, 0, 100, 50, 293db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [](RenderProperties& properties, SkiaRecordingCanvas& canvas) { 294db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev properties.setProjectBackwards(true); 295db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev properties.setClipToBounds(false); 296db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev SkPaint paint; 297db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev paint.setColor(SK_ColorDKGRAY); 298db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev canvas.drawRect(-10, -10, 60, 60, paint); 299db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }, "P"); 300db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto child = TestUtils::createSkiaNode(0, 50, 100, 100, 301db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [&projectingRipple](RenderProperties& properties, SkiaRecordingCanvas& canvas) { 302db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev SkPaint paint; 303db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev paint.setColor(SK_ColorBLUE); 304db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev canvas.drawRect(0, 0, 100, 50, paint); 305db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev canvas.drawRenderNode(projectingRipple.get()); 306db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }, "C"); 307db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto parent = TestUtils::createSkiaNode(0, 0, 100, 100, 308db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [&receiverBackground, &child](RenderProperties& properties, SkiaRecordingCanvas& canvas) { 309db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev // Set a rect outline for the projecting ripple to be masked against. 310db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev properties.mutableOutline().setRoundRect(10, 10, 90, 90, 5, 1.0f); 311db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 312db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev canvas.save(SaveFlags::MatrixClip); 313db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev canvas.translate(-SCROLL_X, -SCROLL_Y); // Apply scroll (note: bg undoes this internally) 314db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev canvas.drawRenderNode(receiverBackground.get()); 315db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev canvas.drawRenderNode(child.get()); 316db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev canvas.restore(); 317db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }, "A"); 318db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev ContextFactory contextFactory; 319db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev std::unique_ptr<CanvasContext> canvasContext(CanvasContext::create( 320db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev renderThread, false, parent.get(), &contextFactory)); 321db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get()); 322db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev DamageAccumulator damageAccumulator; 323db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev info.damageAccumulator = &damageAccumulator; 324db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev parent->prepareTree(info); 325db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 326db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev //parent(A) -> (receiverBackground, child) 327db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev //child(C) -> (rect[0, 0, 100, 50], projectingRipple) 328db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev //projectingRipple(P) -> (rect[-10, -10, 60, 60]) -> projects backwards 329db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev //receiverBackground(B) -> (rect[0, 0, 100, 100]) -> projection receiver 330db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 331db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev //create a canvas not backed by any device/pixels, but with dimensions to avoid quick rejection 332db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev ProjectionTestCanvas canvas(100, 100); 333db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev RenderNodeDrawable drawable(parent.get(), &canvas, true); 334db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev canvas.drawDrawable(&drawable); 335db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(3, canvas.getIndex()); 336db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} 337db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 338db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan IlievRENDERTHREAD_TEST(RenderNodeDrawable, projectionHwLayer) { 339db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev /* R is backward projected on B and C is a layer. 340db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev A 341db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev / \ 342db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev B C 343db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev | 344db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev R 345db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev */ 346db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev static const int SCROLL_X = 5; 347db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev static const int SCROLL_Y = 10; 348db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev static const int CANVAS_WIDTH = 400; 349db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev static const int CANVAS_HEIGHT = 400; 350db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev static const int LAYER_WIDTH = 200; 351db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev static const int LAYER_HEIGHT = 200; 352db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev class ProjectionTestCanvas : public SkCanvas { 353db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev public: 3546acfe16b5650446dbdcce3bd779b52fb6533a41eMike Reed ProjectionTestCanvas(int* drawCounter) 3556acfe16b5650446dbdcce3bd779b52fb6533a41eMike Reed : SkCanvas(CANVAS_WIDTH, CANVAS_HEIGHT) 35652771272f4f018f4fc6846224bf047497e784af1Stan Iliev , mDrawCounter(drawCounter) 3576acfe16b5650446dbdcce3bd779b52fb6533a41eMike Reed {} 358db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev void onDrawArc(const SkRect&, SkScalar startAngle, SkScalar sweepAngle, bool useCenter, 359db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev const SkPaint&) override { 3606acfe16b5650446dbdcce3bd779b52fb6533a41eMike Reed EXPECT_EQ(0, (*mDrawCounter)++); //part of painting the layer 36152771272f4f018f4fc6846224bf047497e784af1Stan Iliev EXPECT_EQ(SkRect::MakeLTRB(0, 0, LAYER_WIDTH, LAYER_HEIGHT), TestUtils::getClipBounds(this)); 362db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } 363db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev void onDrawRect(const SkRect& rect, const SkPaint& paint) override { 3646acfe16b5650446dbdcce3bd779b52fb6533a41eMike Reed EXPECT_EQ(1, (*mDrawCounter)++); 36552771272f4f018f4fc6846224bf047497e784af1Stan Iliev EXPECT_EQ(SkRect::MakeLTRB(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT), TestUtils::getClipBounds(this)); 366db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } 367db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev void onDrawOval(const SkRect&, const SkPaint&) override { 3686acfe16b5650446dbdcce3bd779b52fb6533a41eMike Reed EXPECT_EQ(2, (*mDrawCounter)++); 369db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev SkMatrix expectedMatrix; 370db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev expectedMatrix.setTranslate(100 - SCROLL_X, 100 - SCROLL_Y); 371db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(expectedMatrix, getTotalMatrix()); 37252771272f4f018f4fc6846224bf047497e784af1Stan Iliev EXPECT_EQ(SkRect::MakeLTRB(-85, -80, 295, 300), TestUtils::getLocalClipBounds(this)); 373db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } 3746acfe16b5650446dbdcce3bd779b52fb6533a41eMike Reed int* mDrawCounter; 375db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }; 376db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 377db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev class ProjectionLayer : public SkSurface_Base { 378db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev public: 3796acfe16b5650446dbdcce3bd779b52fb6533a41eMike Reed ProjectionLayer(int* drawCounter) 380db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev : SkSurface_Base(SkImageInfo::MakeN32Premul(LAYER_WIDTH, LAYER_HEIGHT), nullptr) 3816acfe16b5650446dbdcce3bd779b52fb6533a41eMike Reed , mDrawCounter(drawCounter) { 382db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } 383db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev void onDraw(SkCanvas*, SkScalar x, SkScalar y, const SkPaint*) override { 3846acfe16b5650446dbdcce3bd779b52fb6533a41eMike Reed EXPECT_EQ(3, (*mDrawCounter)++); 385db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(SkRect::MakeLTRB(100 - SCROLL_X, 100 - SCROLL_Y, 300 - SCROLL_X, 38652771272f4f018f4fc6846224bf047497e784af1Stan Iliev 300 - SCROLL_Y), TestUtils::getClipBounds(this->getCanvas())); 387db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } 388db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev SkCanvas* onNewCanvas() override { 3896acfe16b5650446dbdcce3bd779b52fb6533a41eMike Reed return new ProjectionTestCanvas(mDrawCounter); 390db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } 391db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev sk_sp<SkSurface> onNewSurface(const SkImageInfo&) override { 3923c01a07fff19c5166274de5960935875ea89e455Robert Phillips return nullptr; 393db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } 3943c01a07fff19c5166274de5960935875ea89e455Robert Phillips sk_sp<SkImage> onNewImageSnapshot() override { 3953c01a07fff19c5166274de5960935875ea89e455Robert Phillips return nullptr; 396db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } 397db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev void onCopyOnWrite(ContentChangeMode) override {} 3986acfe16b5650446dbdcce3bd779b52fb6533a41eMike Reed int* mDrawCounter; 399db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }; 400db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 401db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto receiverBackground = TestUtils::createSkiaNode(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, 402db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [](RenderProperties& properties, SkiaRecordingCanvas& canvas) { 403db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev properties.setProjectionReceiver(true); 404db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev // scroll doesn't apply to background, so undone via translationX/Y 405db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver! 406db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev properties.setTranslationX(SCROLL_X); 407db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev properties.setTranslationY(SCROLL_Y); 408db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 409db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev canvas.drawRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, SkPaint()); 410db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }, "B"); //B 411db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto projectingRipple = TestUtils::createSkiaNode(0, 0, LAYER_WIDTH, LAYER_HEIGHT, 412db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [](RenderProperties& properties, SkiaRecordingCanvas& canvas) { 413db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev properties.setProjectBackwards(true); 414db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev properties.setClipToBounds(false); 415db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev canvas.drawOval(100, 100, 300, 300, SkPaint()); // drawn mostly out of layer bounds 416db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }, "R"); //R 417db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto child = TestUtils::createSkiaNode(100, 100, 300, 300, 418db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [&projectingRipple](RenderProperties& properties, SkiaRecordingCanvas& canvas) { 419db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev canvas.drawRenderNode(projectingRipple.get()); 420db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev canvas.drawArc(0, 0, LAYER_WIDTH, LAYER_HEIGHT, 0.0f, 280.0f, true, SkPaint()); 421db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }, "C"); //C 422db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto parent = TestUtils::createSkiaNode(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, 423db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [&receiverBackground, &child](RenderProperties& properties, 424db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev SkiaRecordingCanvas& canvas) { 425db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev // Set a rect outline for the projecting ripple to be masked against. 426db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev properties.mutableOutline().setRoundRect(10, 10, 390, 390, 0, 1.0f); 427db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev canvas.translate(-SCROLL_X, -SCROLL_Y); // Apply scroll (note: bg undoes this internally) 428db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev canvas.drawRenderNode(receiverBackground.get()); 429db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev canvas.drawRenderNode(child.get()); 430db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }, "A"); //A 431db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 432db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev //prepareTree is required to find, which receivers have backward projected nodes 433db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev ContextFactory contextFactory; 434db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev std::unique_ptr<CanvasContext> canvasContext(CanvasContext::create( 435db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev renderThread, false, parent.get(), &contextFactory)); 436db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get()); 437db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev DamageAccumulator damageAccumulator; 438db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev info.damageAccumulator = &damageAccumulator; 439db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev parent->prepareTree(info); 440db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 4416acfe16b5650446dbdcce3bd779b52fb6533a41eMike Reed int drawCounter = 0; 442db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev //set a layer after prepareTree to avoid layer logic there 443db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev child->animatorProperties().mutateLayerProperties().setType(LayerType::RenderLayer); 4446acfe16b5650446dbdcce3bd779b52fb6533a41eMike Reed sk_sp<SkSurface> surfaceLayer1(new ProjectionLayer(&drawCounter)); 445db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev child->setLayerSurface(surfaceLayer1); 446db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev Matrix4 windowTransform; 447db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev windowTransform.loadTranslate(100, 100, 0); 448db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev child->getSkiaLayer()->inverseTransformInWindow.loadInverse(windowTransform); 449db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 450db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev LayerUpdateQueue layerUpdateQueue; 451db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev layerUpdateQueue.enqueueLayerWithDamage(child.get(), 452db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev android::uirenderer::Rect(LAYER_WIDTH, LAYER_HEIGHT)); 453db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev SkiaPipeline::renderLayersImpl(layerUpdateQueue, true); 4546acfe16b5650446dbdcce3bd779b52fb6533a41eMike Reed EXPECT_EQ(1, drawCounter); //assert index 0 is drawn on the layer 455db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 4566acfe16b5650446dbdcce3bd779b52fb6533a41eMike Reed RenderNodeDrawable drawable(parent.get(), surfaceLayer1->getCanvas(), true); 4576acfe16b5650446dbdcce3bd779b52fb6533a41eMike Reed surfaceLayer1->getCanvas()->drawDrawable(&drawable); 4586acfe16b5650446dbdcce3bd779b52fb6533a41eMike Reed EXPECT_EQ(4, drawCounter); 459db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 460db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev // clean up layer pointer, so we can safely destruct RenderNode 461db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev child->setLayerSurface(nullptr); 462db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} 463db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 464db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan IlievRENDERTHREAD_TEST(RenderNodeDrawable, projectionChildScroll) { 465db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev /* R is backward projected on B. 466db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev A 467db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev / \ 468db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev B C 469db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev | 470db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev R 471db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev */ 472db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev static const int SCROLL_X = 500000; 473db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev static const int SCROLL_Y = 0; 474db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev static const int CANVAS_WIDTH = 400; 475db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev static const int CANVAS_HEIGHT = 400; 476db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev class ProjectionChildScrollTestCanvas : public SkCanvas { 477db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev public: 478db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev ProjectionChildScrollTestCanvas() : SkCanvas(CANVAS_WIDTH, CANVAS_HEIGHT) {} 479db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev void onDrawRect(const SkRect& rect, const SkPaint& paint) override { 48052771272f4f018f4fc6846224bf047497e784af1Stan Iliev EXPECT_EQ(0, mDrawCounter++); 481db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_TRUE(getTotalMatrix().isIdentity()); 482db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } 483db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev void onDrawOval(const SkRect&, const SkPaint&) override { 48452771272f4f018f4fc6846224bf047497e784af1Stan Iliev EXPECT_EQ(1, mDrawCounter++); 48552771272f4f018f4fc6846224bf047497e784af1Stan Iliev EXPECT_EQ(SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT), TestUtils::getClipBounds(this)); 486db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_TRUE(getTotalMatrix().isIdentity()); 487db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } 48852771272f4f018f4fc6846224bf047497e784af1Stan Iliev int mDrawCounter = 0; 489db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }; 490db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 491db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto receiverBackground = TestUtils::createSkiaNode(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, 492db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [](RenderProperties& properties, SkiaRecordingCanvas& canvas) { 493db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev properties.setProjectionReceiver(true); 494db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev canvas.drawRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, SkPaint()); 495db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }, "B"); //B 496db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto projectingRipple = TestUtils::createSkiaNode(0, 0, 200, 200, 497db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [](RenderProperties& properties, SkiaRecordingCanvas& canvas) { 498db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev // scroll doesn't apply to background, so undone via translationX/Y 499db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver! 500db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev properties.setTranslationX(SCROLL_X); 501db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev properties.setTranslationY(SCROLL_Y); 502db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev properties.setProjectBackwards(true); 503db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev properties.setClipToBounds(false); 504db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev canvas.drawOval(0, 0, 200, 200, SkPaint()); 505db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }, "R"); //R 506db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto child = TestUtils::createSkiaNode(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, 507db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [&projectingRipple](RenderProperties& properties, SkiaRecordingCanvas& canvas) { 508db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev // Record time clip will be ignored by projectee 5096c67f1d04591f44bccb476d715a005ad5bbdf840Mike Reed canvas.clipRect(100, 100, 300, 300, SkClipOp::kIntersect); 510db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 511db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev canvas.translate(-SCROLL_X, -SCROLL_Y); // Apply scroll (note: bg undoes this internally) 512db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev canvas.drawRenderNode(projectingRipple.get()); 513db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }, "C"); //C 514db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto parent = TestUtils::createSkiaNode(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, 515db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [&receiverBackground, &child](RenderProperties& properties, 516db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev SkiaRecordingCanvas& canvas) { 517db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev canvas.drawRenderNode(receiverBackground.get()); 518db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev canvas.drawRenderNode(child.get()); 519db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }, "A"); //A 520db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 521db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev //prepareTree is required to find, which receivers have backward projected nodes 522db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev ContextFactory contextFactory; 523db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev std::unique_ptr<CanvasContext> canvasContext(CanvasContext::create( 524db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev renderThread, false, parent.get(), &contextFactory)); 525db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get()); 526db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev DamageAccumulator damageAccumulator; 527db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev info.damageAccumulator = &damageAccumulator; 528db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev parent->prepareTree(info); 529db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 5306acfe16b5650446dbdcce3bd779b52fb6533a41eMike Reed std::unique_ptr<ProjectionChildScrollTestCanvas> canvas(new ProjectionChildScrollTestCanvas()); 531db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev RenderNodeDrawable drawable(parent.get(), canvas.get(), true); 532db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev canvas->drawDrawable(&drawable); 53352771272f4f018f4fc6846224bf047497e784af1Stan Iliev EXPECT_EQ(2, canvas->mDrawCounter); 534db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} 535db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 536db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Ilievnamespace { 537db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Ilievstatic int drawNode(RenderThread& renderThread, const sp<RenderNode>& renderNode) 538db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev{ 539db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev ContextFactory contextFactory; 540db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev std::unique_ptr<CanvasContext> canvasContext(CanvasContext::create( 541db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev renderThread, false, renderNode.get(), &contextFactory)); 542db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev TreeInfo info(TreeInfo::MODE_RT_ONLY, *canvasContext.get()); 543db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev DamageAccumulator damageAccumulator; 544db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev info.damageAccumulator = &damageAccumulator; 545db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev renderNode->prepareTree(info); 546db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 547db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev //create a canvas not backed by any device/pixels, but with dimensions to avoid quick rejection 548db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev ZReorderCanvas canvas(100, 100); 549db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev RenderNodeDrawable drawable(renderNode.get(), &canvas, false); 550db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev canvas.drawDrawable(&drawable); 551db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev return canvas.getIndex(); 552db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} 553db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} 554db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 555db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan IlievRENDERTHREAD_TEST(RenderNodeDrawable, projectionReorderProjectedInMiddle) { 556db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev /* R is backward projected on B 557db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev A 558db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev / \ 559db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev B C 560db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev | 561db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev R 562db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev */ 563db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto nodeA = TestUtils::createSkiaNode(0, 0, 100, 100, 564db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [](RenderProperties& props, SkiaRecordingCanvas& canvas) { 565db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 0, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { 566db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectionReceiver(true); 567db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeB 568db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 2, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { 569db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 1, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { 570db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectBackwards(true); 571db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setClipToBounds(false); 572db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeR 573db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeC 574db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }); //nodeA 575db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(3, drawNode(renderThread, nodeA)); 576db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} 577db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 578db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan IlievRENDERTHREAD_TEST(RenderNodeDrawable, projectionReorderProjectLast) { 579db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev /* R is backward projected on E 580db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev A 581db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev / | \ 582db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev / | \ 583db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev B C E 584db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev | 585db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev R 586db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev */ 587db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto nodeA = TestUtils::createSkiaNode(0, 0, 100, 100, 588db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [](RenderProperties& props, SkiaRecordingCanvas& canvas) { 589db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 0, nullptr); //nodeB 590db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 1, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { 591db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 3, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //drawn as 2 592db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectBackwards(true); 593db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setClipToBounds(false); 594db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeR 595db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeC 596db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 2, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //drawn as 3 597db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectionReceiver(true); 598db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeE 599db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }); //nodeA 600db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(4, drawNode(renderThread, nodeA)); 601db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} 602db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 603db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan IlievRENDERTHREAD_TEST(RenderNodeDrawable, projectionReorderNoReceivable) { 604db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev /* R is backward projected without receiver 605db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev A 606db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev / \ 607db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev B C 608db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev | 609db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev R 610db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev */ 611db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto nodeA = TestUtils::createSkiaNode(0, 0, 100, 100, 612db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [](RenderProperties& props, SkiaRecordingCanvas& canvas) { 613db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 0, nullptr); //nodeB 614db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 1, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { 615db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 255, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { 616db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev //not having a projection receiver is an undefined behavior 617db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectBackwards(true); 618db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setClipToBounds(false); 619db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeR 620db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeC 621db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }); //nodeA 622db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(2, drawNode(renderThread, nodeA)); 623db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} 624db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 625db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan IlievRENDERTHREAD_TEST(RenderNodeDrawable, projectionReorderParentReceivable) { 626db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev /* R is backward projected on C 627db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev A 628db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev / \ 629db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev B C 630db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev | 631db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev R 632db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev */ 633db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto nodeA = TestUtils::createSkiaNode(0, 0, 100, 100, 634db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [](RenderProperties& props, SkiaRecordingCanvas& canvas) { 635db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 0, nullptr); //nodeB 636db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 1, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { 637db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectionReceiver(true); 638db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 2, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { 639db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectBackwards(true); 640db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setClipToBounds(false); 641db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeR 642db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeC 643db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }); //nodeA 644db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(3, drawNode(renderThread, nodeA)); 645db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} 646db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 647db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan IlievRENDERTHREAD_TEST(RenderNodeDrawable, projectionReorderSameNodeReceivable) { 648db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev /* R is backward projected on R 649db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev A 650db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev / \ 651db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev B C 652db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev | 653db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev R 654db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev */ 655db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto nodeA = TestUtils::createSkiaNode(0, 0, 100, 100, 656db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [](RenderProperties& props, SkiaRecordingCanvas& canvas) { 657db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 0, nullptr); //nodeB 658db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 1, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { 659db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 255, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { 660db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev //having a node that is projected on itself is an undefined/unexpected behavior 661db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectionReceiver(true); 662db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectBackwards(true); 663db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setClipToBounds(false); 664db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeR 665db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeC 666db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }); //nodeA 667db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(2, drawNode(renderThread, nodeA)); 668db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} 669db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 670db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev//Note: the outcome for this test is different in HWUI 671db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan IlievRENDERTHREAD_TEST(RenderNodeDrawable, projectionReorderProjectedSibling) { 672db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev /* R is set to project on B, but R is not drawn because projecting on a sibling is not allowed. 673db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev A 674db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev /|\ 675db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev / | \ 676db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev B C R 677db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev */ 678db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto nodeA = TestUtils::createSkiaNode(0, 0, 100, 100, 679db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [](RenderProperties& props, SkiaRecordingCanvas& canvas) { 680db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 0, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { 681db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectionReceiver(true); 682db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeB 683db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 1, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { 684db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeC 685db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 255, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { 686db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectBackwards(true); 687db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setClipToBounds(false); 688db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeR 689db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }); //nodeA 690db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(2, drawNode(renderThread, nodeA)); 691db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} 692db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 693db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan IlievRENDERTHREAD_TEST(RenderNodeDrawable, projectionReorderProjectedSibling2) { 694db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev /* R is set to project on B, but R is not drawn because projecting on a sibling is not allowed. 695db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev A 696db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev | 697db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev G 698db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev /|\ 699db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev / | \ 700db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev B C R 701db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev */ 702db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto nodeA = TestUtils::createSkiaNode(0, 0, 100, 100, 703db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [](RenderProperties& props, SkiaRecordingCanvas& canvas) { 704db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 0, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { 705db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 1, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { 706db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectionReceiver(true); 707db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeB 708db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 2, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { 709db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeC 710db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 255, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { 711db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectBackwards(true); 712db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setClipToBounds(false); 713db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeR 714db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeG 715db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }); //nodeA 716db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(3, drawNode(renderThread, nodeA)); 717db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} 718db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 719db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan IlievRENDERTHREAD_TEST(RenderNodeDrawable, projectionReorderGrandparentReceivable) { 720db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev /* R is backward projected on B 721db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev A 722db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev | 723db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev B 724db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev | 725db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev C 726db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev | 727db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev R 728db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev */ 729db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto nodeA = TestUtils::createSkiaNode(0, 0, 100, 100, 730db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [](RenderProperties& props, SkiaRecordingCanvas& canvas) { 731db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 0, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { 732db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectionReceiver(true); 733db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 1, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { 734db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 2, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { 735db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectBackwards(true); 736db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setClipToBounds(false); 737db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeR 738db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeC 739db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeB 740db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }); //nodeA 741db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(3, drawNode(renderThread, nodeA)); 742db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} 743db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 744db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan IlievRENDERTHREAD_TEST(RenderNodeDrawable, projectionReorderTwoReceivables) { 745db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev /* B and G are receivables, R is backward projected 746db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev A 747db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev / \ 748db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev B C 749db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev / \ 750db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev G R 751db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev */ 752db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto nodeA = TestUtils::createSkiaNode(0, 0, 100, 100, 753db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [](RenderProperties& props, SkiaRecordingCanvas& canvas) { 754db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 0, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //B 755db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectionReceiver(true); 756db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeB 757db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 2, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //C 758db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 3, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //G 759db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectionReceiver(true); 760db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeG 761db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 1, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //R 762db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectBackwards(true); 763db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setClipToBounds(false); 764db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeR 765db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeC 766db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }); //nodeA 767db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(4, drawNode(renderThread, nodeA)); 768db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} 769db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 770db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan IlievRENDERTHREAD_TEST(RenderNodeDrawable, projectionReorderTwoReceivablesLikelyScenario) { 771db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev /* B and G are receivables, G is backward projected 772db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev A 773db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev / \ 774db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev B C 775db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev / \ 776db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev G R 777db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev */ 778db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto nodeA = TestUtils::createSkiaNode(0, 0, 100, 100, 779db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [](RenderProperties& props, SkiaRecordingCanvas& canvas) { 780db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 0, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //B 781db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectionReceiver(true); 782db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeB 783db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 2, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //C 784db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 1, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //G 785db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectionReceiver(true); 786db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectBackwards(true); 787db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setClipToBounds(false); 788db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeG 789db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 3, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //R 790db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeR 791db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeC 792db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }); //nodeA 793db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(4, drawNode(renderThread, nodeA)); 794db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} 795db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 796db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan IlievRENDERTHREAD_TEST(RenderNodeDrawable, projectionReorderTwoReceivablesDeeper) { 797db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev /* B and G are receivables, R is backward projected 798db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev A 799db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev / \ 800db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev B C 801db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev / \ 802db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev G D 803db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev | 804db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev R 805db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev */ 806db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto nodeA = TestUtils::createSkiaNode(0, 0, 100, 100, 807db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [](RenderProperties& props, SkiaRecordingCanvas& canvas) { 808db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 0, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //B 809db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectionReceiver(true); 810db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeB 811db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 1, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //C 812db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 2, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //G 813db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectionReceiver(true); 814db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeG 815db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 4, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //D 816db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 3, [](RenderProperties& props, SkiaRecordingCanvas& canvas) { //R 817db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectBackwards(true); 818db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setClipToBounds(false); 819db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeR 820db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeD 821db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeC 822db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }); //nodeA 823db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(5, drawNode(renderThread, nodeA)); 824021693b967a2c5556dddd183eb0247df4079e1adStan Iliev} 82552771272f4f018f4fc6846224bf047497e784af1Stan Iliev 82652771272f4f018f4fc6846224bf047497e784af1Stan IlievRENDERTHREAD_TEST(RenderNodeDrawable, simple) { 82752771272f4f018f4fc6846224bf047497e784af1Stan Iliev static const int CANVAS_WIDTH = 100; 82852771272f4f018f4fc6846224bf047497e784af1Stan Iliev static const int CANVAS_HEIGHT = 200; 82952771272f4f018f4fc6846224bf047497e784af1Stan Iliev class SimpleTestCanvas : public TestCanvasBase { 83052771272f4f018f4fc6846224bf047497e784af1Stan Iliev public: 83152771272f4f018f4fc6846224bf047497e784af1Stan Iliev SimpleTestCanvas() : TestCanvasBase(CANVAS_WIDTH, CANVAS_HEIGHT) { 83252771272f4f018f4fc6846224bf047497e784af1Stan Iliev } 83352771272f4f018f4fc6846224bf047497e784af1Stan Iliev void onDrawRect(const SkRect& rect, const SkPaint& paint) override { 83452771272f4f018f4fc6846224bf047497e784af1Stan Iliev EXPECT_EQ(0, mDrawCounter++); 83552771272f4f018f4fc6846224bf047497e784af1Stan Iliev } 83652771272f4f018f4fc6846224bf047497e784af1Stan Iliev void onDrawImage(const SkImage*, SkScalar dx, SkScalar dy, const SkPaint*) override { 83752771272f4f018f4fc6846224bf047497e784af1Stan Iliev EXPECT_EQ(1, mDrawCounter++); 83852771272f4f018f4fc6846224bf047497e784af1Stan Iliev } 83952771272f4f018f4fc6846224bf047497e784af1Stan Iliev }; 84052771272f4f018f4fc6846224bf047497e784af1Stan Iliev 84152771272f4f018f4fc6846224bf047497e784af1Stan Iliev auto node = TestUtils::createSkiaNode(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, 84252771272f4f018f4fc6846224bf047497e784af1Stan Iliev [](RenderProperties& props, SkiaRecordingCanvas& canvas) { 84352771272f4f018f4fc6846224bf047497e784af1Stan Iliev sk_sp<Bitmap> bitmap(TestUtils::createBitmap(25, 25)); 84452771272f4f018f4fc6846224bf047497e784af1Stan Iliev canvas.drawRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, SkPaint()); 84552771272f4f018f4fc6846224bf047497e784af1Stan Iliev canvas.drawBitmap(*bitmap, 10, 10, nullptr); 84652771272f4f018f4fc6846224bf047497e784af1Stan Iliev }); 84752771272f4f018f4fc6846224bf047497e784af1Stan Iliev 84852771272f4f018f4fc6846224bf047497e784af1Stan Iliev SimpleTestCanvas canvas; 84952771272f4f018f4fc6846224bf047497e784af1Stan Iliev RenderNodeDrawable drawable(node.get(), &canvas, true); 85052771272f4f018f4fc6846224bf047497e784af1Stan Iliev canvas.drawDrawable(&drawable); 85152771272f4f018f4fc6846224bf047497e784af1Stan Iliev EXPECT_EQ(2, canvas.mDrawCounter); 85252771272f4f018f4fc6846224bf047497e784af1Stan Iliev} 85352771272f4f018f4fc6846224bf047497e784af1Stan Iliev 85452771272f4f018f4fc6846224bf047497e784af1Stan IlievRENDERTHREAD_TEST(RenderNodeDrawable, colorOp_unbounded) { 85552771272f4f018f4fc6846224bf047497e784af1Stan Iliev static const int CANVAS_WIDTH = 200; 85652771272f4f018f4fc6846224bf047497e784af1Stan Iliev static const int CANVAS_HEIGHT = 200; 85752771272f4f018f4fc6846224bf047497e784af1Stan Iliev class ColorTestCanvas : public TestCanvasBase { 85852771272f4f018f4fc6846224bf047497e784af1Stan Iliev public: 85952771272f4f018f4fc6846224bf047497e784af1Stan Iliev ColorTestCanvas() : TestCanvasBase(CANVAS_WIDTH, CANVAS_HEIGHT) { 86052771272f4f018f4fc6846224bf047497e784af1Stan Iliev } 86152771272f4f018f4fc6846224bf047497e784af1Stan Iliev void onDrawPaint(const SkPaint&) { 86252771272f4f018f4fc6846224bf047497e784af1Stan Iliev switch (mDrawCounter++) { 86352771272f4f018f4fc6846224bf047497e784af1Stan Iliev case 0: 864c1db0e0ff701c81aa909789e3c6c4d3d5b3aca84Stan Iliev EXPECT_EQ(SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT), 865c1db0e0ff701c81aa909789e3c6c4d3d5b3aca84Stan Iliev TestUtils::getClipBounds(this)); 86652771272f4f018f4fc6846224bf047497e784af1Stan Iliev break; 86752771272f4f018f4fc6846224bf047497e784af1Stan Iliev case 1: 86852771272f4f018f4fc6846224bf047497e784af1Stan Iliev EXPECT_EQ(SkRect::MakeWH(10, 10), TestUtils::getClipBounds(this)); 86952771272f4f018f4fc6846224bf047497e784af1Stan Iliev break; 87052771272f4f018f4fc6846224bf047497e784af1Stan Iliev default: 87152771272f4f018f4fc6846224bf047497e784af1Stan Iliev ADD_FAILURE(); 87252771272f4f018f4fc6846224bf047497e784af1Stan Iliev } 87352771272f4f018f4fc6846224bf047497e784af1Stan Iliev } 87452771272f4f018f4fc6846224bf047497e784af1Stan Iliev }; 87552771272f4f018f4fc6846224bf047497e784af1Stan Iliev 87652771272f4f018f4fc6846224bf047497e784af1Stan Iliev auto unclippedColorView = TestUtils::createSkiaNode(0, 0, 10, 10, 87752771272f4f018f4fc6846224bf047497e784af1Stan Iliev [](RenderProperties& props, SkiaRecordingCanvas& canvas) { 87852771272f4f018f4fc6846224bf047497e784af1Stan Iliev props.setClipToBounds(false); 87952771272f4f018f4fc6846224bf047497e784af1Stan Iliev canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver); 88052771272f4f018f4fc6846224bf047497e784af1Stan Iliev }); 88152771272f4f018f4fc6846224bf047497e784af1Stan Iliev 88252771272f4f018f4fc6846224bf047497e784af1Stan Iliev auto clippedColorView = TestUtils::createSkiaNode(0, 0, 10, 10, 88352771272f4f018f4fc6846224bf047497e784af1Stan Iliev [](RenderProperties& props, SkiaRecordingCanvas& canvas) { 88452771272f4f018f4fc6846224bf047497e784af1Stan Iliev canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver); 88552771272f4f018f4fc6846224bf047497e784af1Stan Iliev }); 88652771272f4f018f4fc6846224bf047497e784af1Stan Iliev 88752771272f4f018f4fc6846224bf047497e784af1Stan Iliev ColorTestCanvas canvas; 88852771272f4f018f4fc6846224bf047497e784af1Stan Iliev RenderNodeDrawable drawable(unclippedColorView.get(), &canvas, true); 88952771272f4f018f4fc6846224bf047497e784af1Stan Iliev canvas.drawDrawable(&drawable); 89052771272f4f018f4fc6846224bf047497e784af1Stan Iliev EXPECT_EQ(1, canvas.mDrawCounter); 89152771272f4f018f4fc6846224bf047497e784af1Stan Iliev RenderNodeDrawable drawable2(clippedColorView.get(), &canvas, true); 89252771272f4f018f4fc6846224bf047497e784af1Stan Iliev canvas.drawDrawable(&drawable2); 89352771272f4f018f4fc6846224bf047497e784af1Stan Iliev EXPECT_EQ(2, canvas.mDrawCounter); 89452771272f4f018f4fc6846224bf047497e784af1Stan Iliev} 89552771272f4f018f4fc6846224bf047497e784af1Stan Iliev 89652771272f4f018f4fc6846224bf047497e784af1Stan IlievTEST(RenderNodeDrawable, renderNode) { 89752771272f4f018f4fc6846224bf047497e784af1Stan Iliev static const int CANVAS_WIDTH = 200; 89852771272f4f018f4fc6846224bf047497e784af1Stan Iliev static const int CANVAS_HEIGHT = 200; 89952771272f4f018f4fc6846224bf047497e784af1Stan Iliev class RenderNodeTestCanvas : public TestCanvasBase { 90052771272f4f018f4fc6846224bf047497e784af1Stan Iliev public: 90152771272f4f018f4fc6846224bf047497e784af1Stan Iliev RenderNodeTestCanvas() : TestCanvasBase(CANVAS_WIDTH, CANVAS_HEIGHT) { 90252771272f4f018f4fc6846224bf047497e784af1Stan Iliev } 90352771272f4f018f4fc6846224bf047497e784af1Stan Iliev void onDrawRect(const SkRect& rect, const SkPaint& paint) override { 90452771272f4f018f4fc6846224bf047497e784af1Stan Iliev switch(mDrawCounter++) { 90552771272f4f018f4fc6846224bf047497e784af1Stan Iliev case 0: 90652771272f4f018f4fc6846224bf047497e784af1Stan Iliev EXPECT_EQ(SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT), TestUtils::getClipBounds(this)); 90752771272f4f018f4fc6846224bf047497e784af1Stan Iliev EXPECT_EQ(SK_ColorDKGRAY, paint.getColor()); 90852771272f4f018f4fc6846224bf047497e784af1Stan Iliev break; 90952771272f4f018f4fc6846224bf047497e784af1Stan Iliev case 1: 91052771272f4f018f4fc6846224bf047497e784af1Stan Iliev EXPECT_EQ(SkRect::MakeLTRB(50, 50, 150, 150), TestUtils::getClipBounds(this)); 91152771272f4f018f4fc6846224bf047497e784af1Stan Iliev EXPECT_EQ(SK_ColorWHITE, paint.getColor()); 91252771272f4f018f4fc6846224bf047497e784af1Stan Iliev break; 91352771272f4f018f4fc6846224bf047497e784af1Stan Iliev default: 91452771272f4f018f4fc6846224bf047497e784af1Stan Iliev ADD_FAILURE(); 91552771272f4f018f4fc6846224bf047497e784af1Stan Iliev } 91652771272f4f018f4fc6846224bf047497e784af1Stan Iliev } 91752771272f4f018f4fc6846224bf047497e784af1Stan Iliev }; 91852771272f4f018f4fc6846224bf047497e784af1Stan Iliev 91952771272f4f018f4fc6846224bf047497e784af1Stan Iliev auto child = TestUtils::createSkiaNode(10, 10, 110, 110, 92052771272f4f018f4fc6846224bf047497e784af1Stan Iliev [](RenderProperties& props, SkiaRecordingCanvas& canvas) { 92152771272f4f018f4fc6846224bf047497e784af1Stan Iliev SkPaint paint; 92252771272f4f018f4fc6846224bf047497e784af1Stan Iliev paint.setColor(SK_ColorWHITE); 92352771272f4f018f4fc6846224bf047497e784af1Stan Iliev canvas.drawRect(0, 0, 100, 100, paint); 92452771272f4f018f4fc6846224bf047497e784af1Stan Iliev }); 92552771272f4f018f4fc6846224bf047497e784af1Stan Iliev 92652771272f4f018f4fc6846224bf047497e784af1Stan Iliev auto parent = TestUtils::createSkiaNode(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, 92752771272f4f018f4fc6846224bf047497e784af1Stan Iliev [&child](RenderProperties& props, SkiaRecordingCanvas& canvas) { 92852771272f4f018f4fc6846224bf047497e784af1Stan Iliev SkPaint paint; 92952771272f4f018f4fc6846224bf047497e784af1Stan Iliev paint.setColor(SK_ColorDKGRAY); 93052771272f4f018f4fc6846224bf047497e784af1Stan Iliev canvas.drawRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, paint); 93152771272f4f018f4fc6846224bf047497e784af1Stan Iliev 93252771272f4f018f4fc6846224bf047497e784af1Stan Iliev canvas.save(SaveFlags::MatrixClip); 93352771272f4f018f4fc6846224bf047497e784af1Stan Iliev canvas.translate(40, 40); 93452771272f4f018f4fc6846224bf047497e784af1Stan Iliev canvas.drawRenderNode(child.get()); 93552771272f4f018f4fc6846224bf047497e784af1Stan Iliev canvas.restore(); 93652771272f4f018f4fc6846224bf047497e784af1Stan Iliev }); 93752771272f4f018f4fc6846224bf047497e784af1Stan Iliev 93852771272f4f018f4fc6846224bf047497e784af1Stan Iliev RenderNodeTestCanvas canvas; 93952771272f4f018f4fc6846224bf047497e784af1Stan Iliev RenderNodeDrawable drawable(parent.get(), &canvas, true); 94052771272f4f018f4fc6846224bf047497e784af1Stan Iliev canvas.drawDrawable(&drawable); 94152771272f4f018f4fc6846224bf047497e784af1Stan Iliev EXPECT_EQ(2, canvas.mDrawCounter); 94252771272f4f018f4fc6846224bf047497e784af1Stan Iliev} 94352771272f4f018f4fc6846224bf047497e784af1Stan Iliev 944