Implement SkiaRecordingCanvas, RenderNodeDrawable and other drawables.

Implement SkiaRecordingCanvas, RenderNodeDrawable, GLFunctorDrawable,
LayerDrawable, StartReorderBarrierDrawable, EndReorderBarrierDrawable.
Move AnimatedRoundRect and AnimatedCircle in a separate file.
All Skia pipeline files are moved in hwui/pipeline/skia folder.
Add unit tests for RenderNodeDrawable, StartReorderBarrierDrawable,
EndReorderBarrierDrawable and SkiaRecordingCanvas.

Test: I tested manually on 6P devices and did run the unit tests.
Change-Id: If2a347bd1fc4689953822294ce5bf98c7f3f57c7
diff --git a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
new file mode 100644
index 0000000..19c311c
--- /dev/null
+++ b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+#include <VectorDrawable.h>
+
+#include "AnimationContext.h"
+#include "DamageAccumulator.h"
+#include "IContextFactory.h"
+#include "pipeline/skia/SkiaDisplayList.h"
+#include "pipeline/skia/SkiaRecordingCanvas.h"
+#include "renderthread/CanvasContext.h"
+#include "tests/common/TestUtils.h"
+#include "SkiaCanvas.h"
+#include <SkLiteRecorder.h>
+#include <string.h>
+
+
+using namespace android;
+using namespace android::uirenderer;
+using namespace android::uirenderer::renderthread;
+using namespace android::uirenderer::skiapipeline;
+
+static sp<RenderNode> createSkiaNode(int left, int top, int right, int bottom,
+        std::function<void(RenderProperties& props, SkiaRecordingCanvas& canvas)> setup,
+        const char* name = nullptr, SkiaDisplayList* displayList = nullptr) {
+#if HWUI_NULL_GPU
+    // if RenderNodes are being sync'd/used, device info will be needed, since
+    // DeviceInfo::maxTextureSize() affects layer property
+    DeviceInfo::initialize();
+#endif
+    sp<RenderNode> node = new RenderNode();
+    if (name) {
+        node->setName(name);
+    }
+    RenderProperties& props = node->mutateStagingProperties();
+    props.setLeftTopRightBottom(left, top, right, bottom);
+    if (displayList) {
+        node->setStagingDisplayList(displayList, nullptr);
+    }
+    if (setup) {
+        std::unique_ptr<SkiaRecordingCanvas> canvas(new SkiaRecordingCanvas(nullptr,
+            props.getWidth(), props.getHeight()));
+        setup(props, *canvas.get());
+        node->setStagingDisplayList(canvas->finishRecording(), nullptr);
+    }
+    node->setPropertyFieldsDirty(0xFFFFFFFF);
+    TestUtils::syncHierarchyPropertiesAndDisplayList(node);
+    return node;
+}
+
+TEST(RenderNodeDrawable, create) {
+    auto rootNode = TestUtils::createNode(0, 0, 200, 400,
+            [](RenderProperties& props, Canvas& canvas) {
+                canvas.drawColor(Color::Red_500, SkBlendMode::kSrcOver);
+            });
+
+    auto skLiteDL = SkLiteDL::New(SkRect::MakeWH(1, 1));
+    SkLiteRecorder canvas;
+    canvas.reset(skLiteDL.get());
+    canvas.translate(100, 100);
+    RenderNodeDrawable drawable(rootNode.get(), &canvas);
+
+    ASSERT_EQ(drawable.getRenderNode(), rootNode.get());
+    ASSERT_EQ(&drawable.getNodeProperties(), &rootNode->properties());
+    ASSERT_EQ(drawable.getRecordedMatrix(), canvas.getTotalMatrix());
+}
+
+TEST(RenderNodeDrawable, drawContent) {
+    auto surface = SkSurface::MakeRasterN32Premul(1, 1);
+    SkCanvas& canvas = *surface->getCanvas();
+    canvas.drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
+    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
+
+    //create a RenderNodeDrawable backed by a RenderNode backed by a SkLiteRecorder
+    auto rootNode = createSkiaNode(0, 0, 1, 1,
+        [](RenderProperties& props, SkiaRecordingCanvas& recorder) {
+            recorder.drawColor(SK_ColorRED, SkBlendMode::kSrcOver);
+        });
+    RenderNodeDrawable drawable(rootNode.get(), &canvas, false);
+
+    //negative and positive Z order are drawn out of order
+    rootNode->animatorProperties().setElevation(10.0f);
+    canvas.drawDrawable(&drawable);
+    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
+    rootNode->animatorProperties().setElevation(-10.0f);
+    canvas.drawDrawable(&drawable);
+    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
+
+    //zero Z are drawn immediately
+    rootNode->animatorProperties().setElevation(0.0f);
+    canvas.drawDrawable(&drawable);
+    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorRED);
+}
+
+//TODO: another test that verifies equal z values are drawn in order, and barriers prevent Z
+//intermixing (model after FrameBuilder zReorder)
+TEST(RenderNodeDrawable, drawAndReorder) {
+    //this test exercises StartReorderBarrierDrawable, EndReorderBarrierDrawable and
+    //SkiaRecordingCanvas
+    auto surface = SkSurface::MakeRasterN32Premul(4, 4);
+    SkCanvas& canvas = *surface->getCanvas();
+
+    canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
+    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorWHITE);
+
+    //-z draws to all 4 pixels (RED)
+    auto redNode = createSkiaNode(0, 0, 4, 4,
+        [](RenderProperties& props, SkiaRecordingCanvas& redCanvas) {
+            redCanvas.drawColor(SK_ColorRED, SkBlendMode::kSrcOver);
+            props.setElevation(-10.0f);
+        }, "redNode");
+
+    //0z draws to bottom 2 pixels (GREEN)
+    auto bottomHalfGreenNode = createSkiaNode(0, 0, 4, 4,
+            [](RenderProperties& props, SkiaRecordingCanvas& bottomHalfGreenCanvas) {
+                SkPaint greenPaint;
+                greenPaint.setColor(SK_ColorGREEN);
+                greenPaint.setStyle(SkPaint::kFill_Style);
+                bottomHalfGreenCanvas.drawRect(0, 2, 4, 4, greenPaint);
+                props.setElevation(0.0f);
+            }, "bottomHalfGreenNode");
+
+    //+z draws to right 2 pixels (BLUE)
+    auto rightHalfBlueNode = createSkiaNode(0, 0, 4, 4,
+        [](RenderProperties& props, SkiaRecordingCanvas& rightHalfBlueCanvas) {
+            SkPaint bluePaint;
+            bluePaint.setColor(SK_ColorBLUE);
+            bluePaint.setStyle(SkPaint::kFill_Style);
+            rightHalfBlueCanvas.drawRect(2, 0, 4, 4, bluePaint);
+            props.setElevation(10.0f);
+        }, "rightHalfBlueNode");
+
+    auto rootNode = createSkiaNode(0, 0, 4, 4,
+            [&](RenderProperties& props, SkiaRecordingCanvas& rootRecorder) {
+                rootRecorder.insertReorderBarrier(true);
+                //draw in reverse Z order, so Z alters draw order
+                rootRecorder.drawRenderNode(rightHalfBlueNode.get());
+                rootRecorder.drawRenderNode(bottomHalfGreenNode.get());
+                rootRecorder.drawRenderNode(redNode.get());
+            }, "rootNode");
+
+    RenderNodeDrawable drawable3(rootNode.get(), &canvas, false);
+    canvas.drawDrawable(&drawable3);
+    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorRED);
+    ASSERT_EQ(TestUtils::getColor(surface, 0, 3), SK_ColorGREEN);
+    ASSERT_EQ(TestUtils::getColor(surface, 3, 3), SK_ColorBLUE);
+}
+
+TEST(RenderNodeDrawable, composeOnLayer)
+{
+    auto surface = SkSurface::MakeRasterN32Premul(1, 1);
+    SkCanvas& canvas = *surface->getCanvas();
+    canvas.drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
+    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
+
+    auto rootNode = createSkiaNode(0, 0, 1, 1,
+        [](RenderProperties& props, SkiaRecordingCanvas& recorder) {
+            recorder.drawColor(SK_ColorRED, SkBlendMode::kSrcOver);
+        });
+
+    //attach a layer to the render node
+    auto surfaceLayer = SkSurface::MakeRasterN32Premul(1, 1);
+    auto canvas2 = surfaceLayer->getCanvas();
+    canvas2->drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
+    rootNode->setLayerSurface( surfaceLayer  );
+
+    RenderNodeDrawable drawable1(rootNode.get(), &canvas, false);
+    canvas.drawDrawable(&drawable1);
+    ASSERT_EQ(SK_ColorRED, TestUtils::getColor(surface, 0, 0));
+
+    RenderNodeDrawable drawable2(rootNode.get(), &canvas, true);
+    canvas.drawDrawable(&drawable2);
+    ASSERT_EQ(SK_ColorWHITE, TestUtils::getColor(surface, 0, 0));
+
+    RenderNodeDrawable drawable3(rootNode.get(), &canvas, false);
+    canvas.drawDrawable(&drawable3);
+    ASSERT_EQ(SK_ColorRED, TestUtils::getColor(surface, 0, 0));
+
+    rootNode->setLayerSurface( sk_sp<SkSurface>()  );
+}
+
+//TODO: refactor to cover test cases from FrameBuilderTests_projectionReorder
+//validate with bounds and projection path mask.
+//TODO: research if we could hook in and mock/validate different aspects of the drawing,
+//instead of validating pixels
+TEST(RenderNodeDrawable, projectDraw) {
+    auto surface = SkSurface::MakeRasterN32Premul(1, 1);
+    SkCanvas& canvas = *surface->getCanvas();
+    canvas.drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
+    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);
+
+    auto redNode = createSkiaNode(0, 0, 1, 1,
+        [](RenderProperties& props, SkiaRecordingCanvas& redCanvas) {
+            redCanvas.drawColor(SK_ColorRED, SkBlendMode::kSrcOver);
+        }, "redNode");
+
+    auto greenNodeWithRedChild = createSkiaNode(0, 0, 1, 1,
+        [&](RenderProperties& props, SkiaRecordingCanvas& greenCanvasWithRedChild) {
+            greenCanvasWithRedChild.drawRenderNode(redNode.get());
+            greenCanvasWithRedChild.drawColor(SK_ColorGREEN, SkBlendMode::kSrcOver);
+        }, "greenNodeWithRedChild");
+
+    auto rootNode = createSkiaNode(0, 0, 1, 1,
+        [&](RenderProperties& props, SkiaRecordingCanvas& rootCanvas) {
+            rootCanvas.drawRenderNode(greenNodeWithRedChild.get());
+        }, "rootNode");
+    SkiaDisplayList* rootDisplayList = static_cast<SkiaDisplayList*>(
+        (const_cast<DisplayList*>(rootNode->getDisplayList())));
+
+    RenderNodeDrawable rootDrawable(rootNode.get(), &canvas, false);
+    canvas.drawDrawable(&rootDrawable);
+    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorGREEN);
+
+    //project redNode on rootNode, which will change the test outcome,
+    //because redNode will draw after greenNodeWithRedChild
+    rootDisplayList->mIsProjectionReceiver = true;
+    redNode->animatorProperties().setProjectBackwards(true);
+    canvas.drawDrawable(&rootDrawable);
+    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorRED);
+}