Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7a7c921e authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add more Skia pipeline unit tests."

parents 88797216 52771272
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -308,6 +308,7 @@ LOCAL_SRC_FILES += \
    tests/unit/SkiaBehaviorTests.cpp \
    tests/unit/SkiaDisplayListTests.cpp \
    tests/unit/SkiaPipelineTests.cpp \
    tests/unit/SkiaRenderPropertiesTests.cpp \
    tests/unit/SkiaCanvasTests.cpp \
    tests/unit/SnapshotTests.cpp \
    tests/unit/StringUtilsTests.cpp \
+84 −48
Original line number Diff line number Diff line
@@ -221,6 +221,14 @@ void SkiaPipeline::renderFrame(const LayerUpdateQueue& layers, const SkRect& cli
    canvas->flush();
}

namespace {
static Rect nodeBounds(RenderNode& node) {
    auto& props = node.properties();
    return Rect(props.getLeft(), props.getTop(),
            props.getRight(), props.getBottom());
}
}

void SkiaPipeline::renderFrameImpl(const LayerUpdateQueue& layers, const SkRect& clip,
        const std::vector<sp<RenderNode>>& nodes, bool opaque, const Rect &contentDrawBounds,
        SkCanvas* canvas) {
@@ -231,9 +239,18 @@ void SkiaPipeline::renderFrameImpl(const LayerUpdateQueue& layers, const SkRect&
        canvas->clear(SK_ColorTRANSPARENT);
    }

    // If there are multiple render nodes, they are laid out as follows:
    if (1 == nodes.size()) {
        if (!nodes[0]->nothingToDraw()) {
            SkAutoCanvasRestore acr(canvas, true);
            RenderNodeDrawable root(nodes[0].get(), canvas);
            root.draw(canvas);
        }
    } else if (0 == nodes.size()) {
        //nothing to draw
    } else {
        // It there are multiple render nodes, they are laid out as follows:
        // #0 - backdrop (content + caption)
    // #1 - content (positioned at (0,0) and clipped to - its bounds mContentDrawBounds)
        // #1 - content (local bounds are at (0,0), will be translated and clipped to backdrop)
        // #2 - additional overlay nodes
        // Usually the backdrop cannot be seen since it will be entirely covered by the content. While
        // resizing however it might become partially visible. The following render loop will crop the
@@ -242,46 +259,65 @@ void SkiaPipeline::renderFrameImpl(const LayerUpdateQueue& layers, const SkRect&
        //
        // Additional nodes will be drawn on top with no particular clipping semantics.

    // The bounds of the backdrop against which the content should be clipped.
    Rect backdropBounds = contentDrawBounds;
        // Usually the contents bounds should be mContentDrawBounds - however - we will
        // move it towards the fixed edge to give it a more stable appearance (for the moment).
        // If there is no content bounds we ignore the layering as stated above and start with 2.
    int layer = (contentDrawBounds.isEmpty() || nodes.size() == 1) ? 2 : 0;

    for (const sp<RenderNode>& node : nodes) {
        if (node->nothingToDraw()) continue;

        SkASSERT(node->getDisplayList()->isSkiaDL());

        int count = canvas->save();

        if (layer == 0) {
            const RenderProperties& properties = node->properties();
            Rect targetBounds(properties.getLeft(), properties.getTop(),
                              properties.getRight(), properties.getBottom());
            // Move the content bounds towards the fixed corner of the backdrop.
            const int x = targetBounds.left;
            const int y = targetBounds.top;
            // Remember the intersection of the target bounds and the intersection bounds against
            // which we have to crop the content.
            backdropBounds.set(x, y, x + backdropBounds.getWidth(), y + backdropBounds.getHeight());
            backdropBounds.doIntersect(targetBounds);
        } else if (layer == 1) {
            // We shift and clip the content to match its final location in the window.
            const SkRect clip = SkRect::MakeXYWH(contentDrawBounds.left, contentDrawBounds.top,
                                                 backdropBounds.getWidth(), backdropBounds.getHeight());
            const float dx = backdropBounds.left - contentDrawBounds.left;
            const float dy = backdropBounds.top - contentDrawBounds.top;

        // Backdrop bounds in render target space
        const Rect backdrop = nodeBounds(*nodes[0]);

        // Bounds that content will fill in render target space (note content node bounds may be bigger)
        Rect content(contentDrawBounds.getWidth(), contentDrawBounds.getHeight());
        content.translate(backdrop.left, backdrop.top);
        if (!content.contains(backdrop) && !nodes[0]->nothingToDraw()) {
            // Content doesn't entirely overlap backdrop, so fill around content (right/bottom)

            // Note: in the future, if content doesn't snap to backdrop's left/top, this may need to
            // also fill left/top. Currently, both 2up and freeform position content at the top/left of
            // the backdrop, so this isn't necessary.
            RenderNodeDrawable backdropNode(nodes[0].get(), canvas);
            if (content.right < backdrop.right) {
                // draw backdrop to right side of content
                SkAutoCanvasRestore acr(canvas, true);
                canvas->clipRect(SkRect::MakeLTRB(content.right, backdrop.top,
                        backdrop.right, backdrop.bottom));
                backdropNode.draw(canvas);
            }
            if (content.bottom < backdrop.bottom) {
                // draw backdrop to bottom of content
                // Note: bottom fill uses content left/right, to avoid overdrawing left/right fill
                SkAutoCanvasRestore acr(canvas, true);
                canvas->clipRect(SkRect::MakeLTRB(content.left, content.bottom,
                        content.right, backdrop.bottom));
                backdropNode.draw(canvas);
            }
        }

        RenderNodeDrawable contentNode(nodes[1].get(), canvas);
        if (!backdrop.isEmpty()) {
            // content node translation to catch up with backdrop
            float dx = backdrop.left - contentDrawBounds.left;
            float dy = backdrop.top - contentDrawBounds.top;

            SkAutoCanvasRestore acr(canvas, true);
            canvas->translate(dx, dy);
            // It gets cropped against the bounds of the backdrop to stay inside.
            canvas->clipRect(clip);
            const SkRect contentLocalClip = SkRect::MakeXYWH(contentDrawBounds.left,
                    contentDrawBounds.top, backdrop.getWidth(), backdrop.getHeight());
            canvas->clipRect(contentLocalClip);
            contentNode.draw(canvas);
        } else {
            SkAutoCanvasRestore acr(canvas, true);
            contentNode.draw(canvas);
        }

        RenderNodeDrawable root(node.get(), canvas);
        root.draw(canvas);
        canvas->restoreToCount(count);
        layer++;
        // remaining overlay nodes, simply defer
        for (size_t index = 2; index < nodes.size(); index++) {
            if (!nodes[index]->nothingToDraw()) {
                SkAutoCanvasRestore acr(canvas, true);
                RenderNodeDrawable overlayNode(nodes[index].get(), canvas);
                overlayNode.draw(canvas);
            }
        }
    }
}

+19 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
#include <renderthread/EglManager.h>
#include <renderthread/OpenGLPipeline.h>
#include <utils/Unicode.h>
#include <SkClipStack.h>

namespace android {
namespace uirenderer {
@@ -164,5 +165,23 @@ SkColor TestUtils::getColor(const sk_sp<SkSurface>& surface, int x, int y) {
    return 0;
}

SkRect TestUtils::getClipBounds(const SkCanvas* canvas) {
    SkClipStack::BoundsType boundType;
    SkRect clipBounds;
    canvas->getClipStack()->getBounds(&clipBounds, &boundType);
    return clipBounds;
}

SkRect TestUtils::getLocalClipBounds(const SkCanvas* canvas) {
    SkMatrix invertedTotalMatrix;
    if (!canvas->getTotalMatrix().invert(&invertedTotalMatrix)) {
        return SkRect::MakeEmpty();
    }
    SkRect outlineInDeviceCoord = TestUtils::getClipBounds(canvas);
    SkRect outlineInLocalCoord;
    invertedTotalMatrix.mapRect(&outlineInLocalCoord, outlineInDeviceCoord);
    return outlineInLocalCoord;
}

} /* namespace uirenderer */
} /* namespace android */
+3 −0
Original line number Diff line number Diff line
@@ -293,6 +293,9 @@ public:

    static SkColor getColor(const sk_sp<SkSurface>& surface, int x, int y);

    static SkRect getClipBounds(const SkCanvas* canvas);
    static SkRect getLocalClipBounds(const SkCanvas* canvas);

private:
    static void syncHierarchyPropertiesAndDisplayListImpl(RenderNode* node) {
        node->syncProperties();
+143 −0
Original line number Diff line number Diff line
/*
 * 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.
 */

#pragma once

#include <gtest/gtest.h>
#include <SkCanvas.h>

namespace {

class TestCanvasBase : public SkCanvas {
public:
    TestCanvasBase(int width, int height) : SkCanvas(width, height) {
    }
    void onDrawAnnotation(const SkRect&, const char key[], SkData* value) {
        ADD_FAILURE() << "onDrawAnnotation not expected in this test";
    }
    void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) {
        ADD_FAILURE() << "onDrawDRRect not expected in this test";
    }
    void onDrawText(const void* text, size_t byteLength, SkScalar x, SkScalar y,
            const SkPaint& paint) {
        ADD_FAILURE() << "onDrawText not expected in this test";
    }
    void onDrawPosText(const void* text, size_t byteLength, const SkPoint pos[],
            const SkPaint& paint) {
        ADD_FAILURE() << "onDrawPosText not expected in this test";
    }
    void onDrawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], SkScalar constY,
            const SkPaint& paint) {
        ADD_FAILURE() << "onDrawPosTextH not expected in this test";
    }
    void onDrawTextOnPath(const void* text, size_t byteLength, const SkPath& path,
            const SkMatrix* matrix, const SkPaint& paint) {
        ADD_FAILURE() << "onDrawTextOnPath not expected in this test";
    }
    void onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform[],
            const SkRect* cullRect, const SkPaint& paint) {
        ADD_FAILURE() << "onDrawTextRSXform not expected in this test";
    }
    void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint) {
        ADD_FAILURE() << "onDrawTextBlob not expected in this test";
    }
    void onDrawPatch(const SkPoint cubics[12], const SkColor colors[4], const SkPoint texCoords[4],
            SkBlendMode, const SkPaint& paint) {
        ADD_FAILURE() << "onDrawPatch not expected in this test";
    }
    void onDrawPaint(const SkPaint&) {
        ADD_FAILURE() << "onDrawPaint not expected in this test";
    }
    void onDrawRect(const SkRect&, const SkPaint&) {
        ADD_FAILURE() << "onDrawRect not expected in this test";
    }
    void onDrawRegion(const SkRegion& region, const SkPaint& paint) {
        ADD_FAILURE() << "onDrawRegion not expected in this test";
    }
    void onDrawOval(const SkRect&, const SkPaint&) {
        ADD_FAILURE() << "onDrawOval not expected in this test";
    }
    void onDrawArc(const SkRect&, SkScalar startAngle, SkScalar sweepAngle, bool useCenter,
            const SkPaint&) {
        ADD_FAILURE() << "onDrawArc not expected in this test";
    }
    void onDrawRRect(const SkRRect&, const SkPaint&) {
        ADD_FAILURE() << "onDrawRRect not expected in this test";
    }
    void onDrawPoints(PointMode, size_t count, const SkPoint pts[], const SkPaint&) {
        ADD_FAILURE() << "onDrawPoints not expected in this test";
    }
    void onDrawVertices(VertexMode, int vertexCount, const SkPoint vertices[], const SkPoint texs[],
            const SkColor colors[], SkBlendMode, const uint16_t indices[], int indexCount,
            const SkPaint&) {
        ADD_FAILURE() << "onDrawVertices not expected in this test";
    }
    void onDrawAtlas(const SkImage*, const SkRSXform[], const SkRect[], const SkColor[], int count,
            SkBlendMode, const SkRect* cull, const SkPaint*) {
        ADD_FAILURE() << "onDrawAtlas not expected in this test";
    }
    void onDrawPath(const SkPath&, const SkPaint&) {
        ADD_FAILURE() << "onDrawPath not expected in this test";
    }
    void onDrawImage(const SkImage*, SkScalar dx, SkScalar dy, const SkPaint*) {
        ADD_FAILURE() << "onDrawImage not expected in this test";
    }
    void onDrawImageRect(const SkImage*, const SkRect*, const SkRect&, const SkPaint*,
            SrcRectConstraint) {
        ADD_FAILURE() << "onDrawImageRect not expected in this test";
    }
    void onDrawImageNine(const SkImage*, const SkIRect& center, const SkRect& dst, const SkPaint*) {
        ADD_FAILURE() << "onDrawImageNine not expected in this test";
    }
    void onDrawImageLattice(const SkImage*, const Lattice& lattice, const SkRect& dst,
            const SkPaint*) {
        ADD_FAILURE() << "onDrawImageLattice not expected in this test";
    }
    void onDrawBitmap(const SkBitmap&, SkScalar dx, SkScalar dy, const SkPaint*) {
        ADD_FAILURE() << "onDrawBitmap not expected in this test";
    }
    void onDrawBitmapRect(const SkBitmap&, const SkRect*, const SkRect&, const SkPaint*,
            SrcRectConstraint) {
        ADD_FAILURE() << "onDrawBitmapRect not expected in this test";
    }
    void onDrawBitmapNine(const SkBitmap&, const SkIRect& center, const SkRect& dst,
            const SkPaint*) {
        ADD_FAILURE() << "onDrawBitmapNine not expected in this test";
    }
    void onDrawBitmapLattice(const SkBitmap&, const Lattice& lattice, const SkRect& dst,
            const SkPaint*) {
        ADD_FAILURE() << "onDrawBitmapLattice not expected in this test";
    }
    void onClipRRect(const SkRRect& rrect, ClipOp, ClipEdgeStyle) {
        ADD_FAILURE() << "onClipRRect not expected in this test";
    }
    void onClipPath(const SkPath& path, ClipOp, ClipEdgeStyle) {
        ADD_FAILURE() << "onClipPath not expected in this test";
    }
    void onClipRegion(const SkRegion& deviceRgn, ClipOp) {
        ADD_FAILURE() << "onClipRegion not expected in this test";
    }
    void onDiscard() {
        ADD_FAILURE() << "onDiscard not expected in this test";
    }
    void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*) {
        ADD_FAILURE() << "onDrawPicture not expected in this test";
    }

    int mDrawCounter = 0; //counts how may draw calls of any kind were made to this canvas
};

}
 No newline at end of file
Loading