Loading libs/hwui/RenderNode.cpp +3 −2 Original line number Diff line number Diff line Loading @@ -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); } Loading libs/hwui/pipeline/skia/RenderNodeDrawable.cpp +14 −5 Original line number Diff line number Diff line Loading @@ -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; Loading libs/hwui/pipeline/skia/SkiaPipeline.cpp +64 −17 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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) { Loading Loading @@ -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 { Loading @@ -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 */ libs/hwui/pipeline/skia/SkiaPipeline.h +12 −0 Original line number Diff line number Diff line Loading @@ -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; Loading libs/hwui/tests/unit/SkiaPipelineTests.cpp +50 −0 Original line number Diff line number Diff line Loading @@ -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); } Loading
libs/hwui/RenderNode.cpp +3 −2 Original line number Diff line number Diff line Loading @@ -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); } Loading
libs/hwui/pipeline/skia/RenderNodeDrawable.cpp +14 −5 Original line number Diff line number Diff line Loading @@ -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; Loading
libs/hwui/pipeline/skia/SkiaPipeline.cpp +64 −17 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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) { Loading Loading @@ -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 { Loading @@ -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 */
libs/hwui/pipeline/skia/SkiaPipeline.h +12 −0 Original line number Diff line number Diff line Loading @@ -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; Loading
libs/hwui/tests/unit/SkiaPipelineTests.cpp +50 −0 Original line number Diff line number Diff line Loading @@ -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); }