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

Commit 711b6aec authored by Matt Sarett's avatar Matt Sarett Committed by Android (Google) Code Review
Browse files

Merge "Add overdraw debugging feature to Skia pipelines"

parents ffbaf9a0 f58cc920
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -188,8 +188,9 @@ void RenderNode::prepareTree(TreeInfo& info) {
    ATRACE_CALL();
    LOG_ALWAYS_FATAL_IF(!info.damageAccumulator, "DamageAccumulator missing");

    // Functors don't correctly handle stencil usage of overdraw debugging - shove 'em in a layer.
    bool functorsNeedLayer = Properties::debugOverdraw;
    // The OpenGL renderer reserves the stencil buffer for overdraw debugging.  Functors
    // will need to be drawn in a layer.
    bool functorsNeedLayer = Properties::debugOverdraw && !Properties::isSkiaEnabled();

    prepareTreeImpl(info, functorsNeedLayer);
}
+14 −5
Original line number Diff line number Diff line
@@ -174,13 +174,22 @@ void RenderNodeDrawable::drawContent(SkCanvas* canvas) const {
            }
            renderNode->getLayerSurface()->draw(canvas, 0, 0, paint);

            if (CC_UNLIKELY(Properties::debugLayersUpdates
                    && !renderNode->getSkiaLayer()->hasRenderedSinceRepaint)) {
            if (!renderNode->getSkiaLayer()->hasRenderedSinceRepaint) {
                renderNode->getSkiaLayer()->hasRenderedSinceRepaint = true;
                if (CC_UNLIKELY(Properties::debugLayersUpdates)) {
                    SkPaint layerPaint;
                    layerPaint.setColor(0x7f00ff00);
                    canvas->drawRect(bounds, layerPaint);
                } else if (CC_UNLIKELY(Properties::debugOverdraw)) {
                    // Render transparent rect to increment overdraw for repaint area.
                    // This can be "else if" because flashing green on layer updates
                    // will also increment the overdraw if it happens to be turned on.
                    SkPaint transparentPaint;
                    transparentPaint.setColor(SK_ColorTRANSPARENT);
                    canvas->drawRect(bounds, transparentPaint);
                }
            }

        // composing a software layer with alpha
        } else if (properties.effectiveLayerType() == LayerType::Software) {
            SkPaint paint;
+64 −17
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@

#include "utils/TraceUtils.h"
#include <SkOSFile.h>
#include <SkOverdrawCanvas.h>
#include <SkOverdrawColorFilter.h>
#include <SkPicture.h>
#include <SkPictureRecorder.h>
#include <SkPixelSerializer.h>
@@ -192,6 +194,34 @@ void SkiaPipeline::renderFrame(const LayerUpdateQueue& layers, const SkRect& cli
        }
    }

    renderFrameImpl(layers, clip, nodes, opaque, contentDrawBounds, canvas);

    if (skpCaptureEnabled() && recordingPicture) {
        sk_sp<SkPicture> picture = recorder->finishRecordingAsPicture();
        if (picture->approximateOpCount() > 0) {
            SkFILEWStream stream(prop);
            if (stream.isValid()) {
                PngPixelSerializer serializer;
                picture->serialize(&stream, &serializer);
                stream.flush();
                SkDebugf("Captured Drawing Output (%d bytes) for frame. %s", stream.bytesWritten(), prop);
            }
        }
        surface->getCanvas()->drawPicture(picture);
    }

    if (CC_UNLIKELY(Properties::debugOverdraw)) {
        renderOverdraw(layers, clip, nodes, contentDrawBounds, surface);
    }

    ATRACE_NAME("flush commands");
    canvas->flush();
}

void SkiaPipeline::renderFrameImpl(const LayerUpdateQueue& layers, const SkRect& clip,
        const std::vector<sp<RenderNode>>& nodes, bool opaque, const Rect &contentDrawBounds,
        SkCanvas* canvas) {

    canvas->clipRect(clip, SkRegion::kReplace_Op);

    if (!opaque) {
@@ -250,23 +280,6 @@ void SkiaPipeline::renderFrame(const LayerUpdateQueue& layers, const SkRect& cli
        canvas->restoreToCount(count);
        layer++;
    }

    if (skpCaptureEnabled() && recordingPicture) {
        sk_sp<SkPicture> picture = recorder->finishRecordingAsPicture();
        if (picture->approximateOpCount() > 0) {
            SkFILEWStream stream(prop);
            if (stream.isValid()) {
                PngPixelSerializer serializer;
                picture->serialize(&stream, &serializer);
                stream.flush();
                SkDebugf("Captured Drawing Output (%d bytes) for frame. %s", stream.bytesWritten(), prop);
            }
        }
        surface->getCanvas()->drawPicture(picture);
    }

    ATRACE_NAME("flush commands");
    canvas->flush();
}

void SkiaPipeline::dumpResourceCacheUsage() const {
@@ -283,6 +296,40 @@ void SkiaPipeline::dumpResourceCacheUsage() const {
    ALOGD("%s", log.c_str());
}

// Overdraw debugging

// These colors should be kept in sync with Caches::getOverdrawColor() with a few differences.
// This implementation:
// (1) Requires transparent entries for "no overdraw" and "single draws".
// (2) Requires premul colors (instead of unpremul).
// (3) Requires RGBA colors (instead of BGRA).
static const uint32_t kOverdrawColors[2][6] = {
        { 0x00000000, 0x00000000, 0x2f2f0000, 0x2f002f00, 0x3f00003f, 0x7f00007f, },
        { 0x00000000, 0x00000000, 0x2f2f0000, 0x4f004f4f, 0x5f50335f, 0x7f00007f, },
};

void SkiaPipeline::renderOverdraw(const LayerUpdateQueue& layers, const SkRect& clip,
        const std::vector<sp<RenderNode>>& nodes, const Rect &contentDrawBounds,
        sk_sp<SkSurface> surface) {
    // Set up the overdraw canvas.
    SkImageInfo offscreenInfo = SkImageInfo::MakeA8(surface->width(), surface->height());
    sk_sp<SkSurface> offscreen = surface->makeSurface(offscreenInfo);
    SkOverdrawCanvas overdrawCanvas(offscreen->getCanvas());

    // Fake a redraw to replay the draw commands.  This will increment the alpha channel
    // each time a pixel would have been drawn.
    // Pass true for opaque so we skip the clear - the overdrawCanvas is already zero
    // initialized.
    renderFrameImpl(layers, clip, nodes, true, contentDrawBounds, &overdrawCanvas);
    sk_sp<SkImage> counts = offscreen->makeImageSnapshot();

    // Draw overdraw colors to the canvas.  The color filter will convert counts to colors.
    SkPaint paint;
    const SkPMColor* colors = kOverdrawColors[static_cast<int>(Properties::overdrawColorSet)];
    paint.setColorFilter(SkOverdrawColorFilter::Make(colors));
    surface->getCanvas()->drawImage(counts.get(), 0.0f, 0.0f, &paint);
}

} /* namespace skiapipeline */
} /* namespace uirenderer */
} /* namespace android */
+12 −0
Original line number Diff line number Diff line
@@ -107,6 +107,18 @@ protected:
    renderthread::RenderThread& mRenderThread;

private:
    void renderFrameImpl(const LayerUpdateQueue& layers, const SkRect& clip,
            const std::vector< sp<RenderNode> >& nodes, bool opaque, const Rect &contentDrawBounds,
            SkCanvas* canvas);

    /**
     *  Debugging feature.  Draws a semi-transparent overlay on each pixel, indicating
     *  how many times it has been drawn.
     */
    void renderOverdraw(const LayerUpdateQueue& layers, const SkRect& clip,
            const std::vector< sp<RenderNode> >& nodes, const Rect &contentDrawBounds,
            sk_sp<SkSurface>);

    TaskManager mTaskManager;
    std::vector<sk_sp<SkImage>> mPinnedImages;
    static float mLightRadius;
+50 −0
Original line number Diff line number Diff line
@@ -179,3 +179,53 @@ RENDERTHREAD_TEST(SkiaPipeline, renderLayer) {
    redNode->setLayerSurface(sk_sp<SkSurface>());
    blueNode->setLayerSurface(sk_sp<SkSurface>());
}

RENDERTHREAD_TEST(SkiaPipeline, renderOverdraw) {
    ScopedProperty<bool> prop(Properties::debugOverdraw, true);

    auto whiteNode = TestUtils::createSkiaNode(0, 0, 1, 1,
        [](RenderProperties& props, SkiaRecordingCanvas& canvas) {
            canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
        });
    LayerUpdateQueue layerUpdateQueue;
    SkRect dirty = SkRect::MakeXYWH(0, 0, 1, 1);
    std::vector<sp<RenderNode>> renderNodes;
    renderNodes.push_back(whiteNode);
    bool opaque = true;
    android::uirenderer::Rect contentDrawBounds(0, 0, 1, 1);
    auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
    auto surface = SkSurface::MakeRasterN32Premul(1, 1);

    // Initialize the canvas to blue.
    surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver);
    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE);

    // Single draw, should be white.
    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface);
    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorWHITE);

    // 1 Overdraw, should be blue blended onto white.
    renderNodes.push_back(whiteNode);
    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface);
    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned) 0xffd0d0ff);

    // 2 Overdraw, should be green blended onto white
    renderNodes.push_back(whiteNode);
    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface);
    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned) 0xffd0ffd0);

    // 3 Overdraw, should be pink blended onto white.
    renderNodes.push_back(whiteNode);
    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface);
    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned) 0xffffc0c0);

    // 4 Overdraw, should be red blended onto white.
    renderNodes.push_back(whiteNode);
    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface);
    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned) 0xffff8080);

    // 5 Overdraw, should be red blended onto white.
    renderNodes.push_back(whiteNode);
    pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface);
    ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned) 0xffff8080);
}