SkiaPipeline.cpp revision 52771272f4f018f4fc6846224bf047497e784af1
1500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev/*
2500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev * Copyright (C) 2016 The Android Open Source Project
3500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev *
4500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev * Licensed under the Apache License, Version 2.0 (the "License");
5500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev * you may not use this file except in compliance with the License.
6500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev * You may obtain a copy of the License at
7500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev *
8500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev *      http://www.apache.org/licenses/LICENSE-2.0
9500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev *
10500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev * Unless required by applicable law or agreed to in writing, software
11500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev * distributed under the License is distributed on an "AS IS" BASIS,
12500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev * See the License for the specific language governing permissions and
14500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev * limitations under the License.
15500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev */
16500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
17500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev#include "SkiaPipeline.h"
18500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
19500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev#include "utils/TraceUtils.h"
2010219fb261606fcc71c607167b28295b4578a10dHal Canary#include <SkImageEncoder.h>
21500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev#include <SkOSFile.h>
22f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett#include <SkOverdrawCanvas.h>
23f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett#include <SkOverdrawColorFilter.h>
24500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev#include <SkPicture.h>
25500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev#include <SkPictureRecorder.h>
26500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev#include <SkPixelSerializer.h>
27500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev#include <SkStream.h>
28500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
29500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievusing namespace android::uirenderer::renderthread;
30500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
31500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievnamespace android {
32500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievnamespace uirenderer {
33500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievnamespace skiapipeline {
34500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
35500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievfloat   SkiaPipeline::mLightRadius = 0;
36500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievuint8_t SkiaPipeline::mAmbientShadowAlpha = 0;
37500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievuint8_t SkiaPipeline::mSpotShadowAlpha = 0;
38500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
39500a0c30d4dcd012218c3e44a62926a1c34a259fStan IlievVector3 SkiaPipeline::mLightCenter = {FLT_MIN, FLT_MIN, FLT_MIN};
40500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
41500a0c30d4dcd012218c3e44a62926a1c34a259fStan IlievSkiaPipeline::SkiaPipeline(RenderThread& thread) :  mRenderThread(thread) { }
42500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
43500a0c30d4dcd012218c3e44a62926a1c34a259fStan IlievTaskManager* SkiaPipeline::getTaskManager() {
44500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    return &mTaskManager;
45500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev}
46500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
47500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievvoid SkiaPipeline::onDestroyHardwareResources() {
48500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    // No need to flush the caches here. There is a timer
49500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    // which will flush temporary resources over time.
50500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev}
51500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
52b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenbergerbool SkiaPipeline::pinImages(std::vector<SkImage*>& mutableImages) {
53b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger    for (SkImage* image : mutableImages) {
54189e87498f666e94dc8c8201e7bac56bb09b9251Derek Sollenberger        if (SkImage_pinAsTexture(image, mRenderThread.getGrContext())) {
55189e87498f666e94dc8c8201e7bac56bb09b9251Derek Sollenberger            mPinnedImages.emplace_back(sk_ref_sp(image));
56189e87498f666e94dc8c8201e7bac56bb09b9251Derek Sollenberger        } else {
57189e87498f666e94dc8c8201e7bac56bb09b9251Derek Sollenberger            return false;
58189e87498f666e94dc8c8201e7bac56bb09b9251Derek Sollenberger        }
59b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger    }
60b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger    return true;
61b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger}
62b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger
63b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenbergervoid SkiaPipeline::unpinImages() {
64b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger    for (auto& image : mPinnedImages) {
65b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger        SkImage_unpinAsTexture(image.get(), mRenderThread.getGrContext());
66b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger    }
67b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger    mPinnedImages.clear();
68b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger}
69b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger
70500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievvoid SkiaPipeline::renderLayers(const FrameBuilder::LightGeometry& lightGeometry,
71500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        LayerUpdateQueue* layerUpdateQueue, bool opaque,
72500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        const BakedOpRenderer::LightInfo& lightInfo) {
73500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    updateLighting(lightGeometry, lightInfo);
74500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    ATRACE_NAME("draw layers");
75500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    renderLayersImpl(*layerUpdateQueue, opaque);
76500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    layerUpdateQueue->clear();
77500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev}
78500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
79500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievvoid SkiaPipeline::renderLayersImpl(const LayerUpdateQueue& layers, bool opaque) {
80500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    // Render all layers that need to be updated, in order.
81500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    for (size_t i = 0; i < layers.entries().size(); i++) {
82500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        RenderNode* layerNode = layers.entries()[i].renderNode;
83500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        // only schedule repaint if node still on layer - possible it may have been
84500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        // removed during a dropped frame, but layers may still remain scheduled so
85500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        // as not to lose info on what portion is damaged
86500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        if (CC_LIKELY(layerNode->getLayerSurface() != nullptr)) {
87500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            SkASSERT(layerNode->getLayerSurface());
88500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            SkASSERT(layerNode->getDisplayList()->isSkiaDL());
89500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            SkiaDisplayList* displayList = (SkiaDisplayList*)layerNode->getDisplayList();
90500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            if (!displayList || displayList->isEmpty()) {
91500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev                SkDEBUGF(("%p drawLayers(%s) : missing drawable", this, layerNode->getName()));
92500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev                return;
93500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            }
94500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
95500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            const Rect& layerDamage = layers.entries()[i].damage;
96500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
97500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            SkCanvas* layerCanvas = layerNode->getLayerSurface()->getCanvas();
98500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
99500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            int saveCount = layerCanvas->save();
100500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            SkASSERT(saveCount == 1);
101500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
1026e49c9f007c879f05b035c40c0ba543c00f9d0d0Mike Reed            layerCanvas->clipRect(layerDamage.toSkRect(), kReplace_SkClipOp);
103500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
104500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            auto savedLightCenter = mLightCenter;
105500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            // map current light center into RenderNode's coordinate space
106500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            layerNode->getSkiaLayer()->inverseTransformInWindow.mapPoint3d(mLightCenter);
107500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
108500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            const RenderProperties& properties = layerNode->properties();
109500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            const SkRect bounds = SkRect::MakeWH(properties.getWidth(), properties.getHeight());
110500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            if (properties.getClipToBounds() && layerCanvas->quickReject(bounds)) {
111500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev                return;
112500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            }
113500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
11479756be175dea78ee9d51bb22abba7621bd9b5ccMatt Sarett            layerNode->getSkiaLayer()->hasRenderedSinceRepaint = false;
115500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            layerCanvas->clear(SK_ColorTRANSPARENT);
116500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
117500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            RenderNodeDrawable root(layerNode, layerCanvas, false);
118500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            root.forceDraw(layerCanvas);
119500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            layerCanvas->restoreToCount(saveCount);
120500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            layerCanvas->flush();
121500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            mLightCenter = savedLightCenter;
122500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        }
123500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    }
124500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev}
125500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
126500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievbool SkiaPipeline::createOrUpdateLayer(RenderNode* node,
127500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        const DamageAccumulator& damageAccumulator) {
128500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    SkSurface* layer = node->getLayerSurface();
129500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    if (!layer || layer->width() != node->getWidth() || layer->height() != node->getHeight()) {
130500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        SkImageInfo info = SkImageInfo::MakeN32Premul(node->getWidth(), node->getHeight());
131500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
132500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        SkASSERT(mRenderThread.getGrContext() != nullptr);
133500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        node->setLayerSurface(
134500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev                SkSurface::MakeRenderTarget(mRenderThread.getGrContext(), SkBudgeted::kYes,
135500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev                        info, 0, &props));
136500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        if (node->getLayerSurface()) {
137500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            // update the transform in window of the layer to reset its origin wrt light source
138500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            // position
139500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            Matrix4 windowTransform;
140500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            damageAccumulator.computeCurrentTransform(&windowTransform);
141500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            node->getSkiaLayer()->inverseTransformInWindow = windowTransform;
142500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        }
143500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        return true;
144500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    }
145500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    return false;
146500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev}
147500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
148500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievvoid SkiaPipeline::destroyLayer(RenderNode* node) {
149500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    node->setLayerSurface(nullptr);
150500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev}
151500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
152500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievvoid SkiaPipeline::prepareToDraw(const RenderThread& thread, Bitmap* bitmap) {
153500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    GrContext* context = thread.getGrContext();
154500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    if (context) {
155500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        ATRACE_FORMAT("Bitmap#prepareToDraw %dx%d", bitmap->width(), bitmap->height());
156500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        SkBitmap skiaBitmap;
157500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        bitmap->getSkBitmap(&skiaBitmap);
158500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(skiaBitmap, kNever_SkCopyPixelsMode);
159500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        SkImage_pinAsTexture(image.get(), context);
160500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        SkImage_unpinAsTexture(image.get(), context);
161500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    }
162500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev}
163500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
164500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev// Encodes to PNG, unless there is already encoded data, in which case that gets
165500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev// used.
166500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievclass PngPixelSerializer : public SkPixelSerializer {
167500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievpublic:
168500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    bool onUseEncodedData(const void*, size_t) override { return true; }
169500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    SkData* onEncode(const SkPixmap& pixmap) override {
17010219fb261606fcc71c607167b28295b4578a10dHal Canary        SkDynamicMemoryWStream buf;
17110219fb261606fcc71c607167b28295b4578a10dHal Canary        return SkEncodeImage(&buf, pixmap, SkEncodedImageFormat::kPNG, 100)
17210219fb261606fcc71c607167b28295b4578a10dHal Canary               ? buf.detachAsData().release()
17310219fb261606fcc71c607167b28295b4578a10dHal Canary               : nullptr;
174500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    }
175500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev};
176500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
177500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievvoid SkiaPipeline::renderFrame(const LayerUpdateQueue& layers, const SkRect& clip,
178500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        const std::vector<sp<RenderNode>>& nodes, bool opaque, const Rect &contentDrawBounds,
179500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        sk_sp<SkSurface> surface) {
180500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
181500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    // draw all layers up front
182500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    renderLayersImpl(layers, opaque);
183500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
184500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    // initialize the canvas for the current frame
185500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    SkCanvas* canvas = surface->getCanvas();
186500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
187500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    std::unique_ptr<SkPictureRecorder> recorder;
188500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    bool recordingPicture = false;
189500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    char prop[PROPERTY_VALUE_MAX];
190500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    if (skpCaptureEnabled()) {
191500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        property_get("debug.hwui.capture_frame_as_skp", prop, "0");
192500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        recordingPicture = prop[0] != '0' && !sk_exists(prop);
193500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        if (recordingPicture) {
194500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            recorder.reset(new SkPictureRecorder());
195500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            canvas = recorder->beginRecording(surface->width(), surface->height(),
196500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev                    nullptr, SkPictureRecorder::kPlaybackDrawPicture_RecordFlag);
197500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        }
198500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    }
199500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
200f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett    renderFrameImpl(layers, clip, nodes, opaque, contentDrawBounds, canvas);
201f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett
202f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett    if (skpCaptureEnabled() && recordingPicture) {
203f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett        sk_sp<SkPicture> picture = recorder->finishRecordingAsPicture();
204f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett        if (picture->approximateOpCount() > 0) {
205f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett            SkFILEWStream stream(prop);
206f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett            if (stream.isValid()) {
207f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett                PngPixelSerializer serializer;
208f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett                picture->serialize(&stream, &serializer);
209f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett                stream.flush();
210f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett                SkDebugf("Captured Drawing Output (%d bytes) for frame. %s", stream.bytesWritten(), prop);
211f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett            }
212f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett        }
213f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett        surface->getCanvas()->drawPicture(picture);
214f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett    }
215f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett
216f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett    if (CC_UNLIKELY(Properties::debugOverdraw)) {
217f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett        renderOverdraw(layers, clip, nodes, contentDrawBounds, surface);
218f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett    }
219f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett
220f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett    ATRACE_NAME("flush commands");
221f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett    canvas->flush();
222f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett}
223f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett
22452771272f4f018f4fc6846224bf047497e784af1Stan Ilievnamespace {
22552771272f4f018f4fc6846224bf047497e784af1Stan Ilievstatic Rect nodeBounds(RenderNode& node) {
22652771272f4f018f4fc6846224bf047497e784af1Stan Iliev    auto& props = node.properties();
22752771272f4f018f4fc6846224bf047497e784af1Stan Iliev    return Rect(props.getLeft(), props.getTop(),
22852771272f4f018f4fc6846224bf047497e784af1Stan Iliev            props.getRight(), props.getBottom());
22952771272f4f018f4fc6846224bf047497e784af1Stan Iliev}
23052771272f4f018f4fc6846224bf047497e784af1Stan Iliev}
23152771272f4f018f4fc6846224bf047497e784af1Stan Iliev
232f58cc92066903b900396f640159ea3ea992fc67dMatt Sarettvoid SkiaPipeline::renderFrameImpl(const LayerUpdateQueue& layers, const SkRect& clip,
233f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett        const std::vector<sp<RenderNode>>& nodes, bool opaque, const Rect &contentDrawBounds,
234f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett        SkCanvas* canvas) {
235f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett
2366e49c9f007c879f05b035c40c0ba543c00f9d0d0Mike Reed    canvas->clipRect(clip, kReplace_SkClipOp);
237500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
238500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    if (!opaque) {
239500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        canvas->clear(SK_ColorTRANSPARENT);
240500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    }
241500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
24252771272f4f018f4fc6846224bf047497e784af1Stan Iliev    if (1 == nodes.size()) {
24352771272f4f018f4fc6846224bf047497e784af1Stan Iliev        if (!nodes[0]->nothingToDraw()) {
24452771272f4f018f4fc6846224bf047497e784af1Stan Iliev            SkAutoCanvasRestore acr(canvas, true);
24552771272f4f018f4fc6846224bf047497e784af1Stan Iliev            RenderNodeDrawable root(nodes[0].get(), canvas);
24652771272f4f018f4fc6846224bf047497e784af1Stan Iliev            root.draw(canvas);
24752771272f4f018f4fc6846224bf047497e784af1Stan Iliev        }
24852771272f4f018f4fc6846224bf047497e784af1Stan Iliev    } else if (0 == nodes.size()) {
24952771272f4f018f4fc6846224bf047497e784af1Stan Iliev        //nothing to draw
25052771272f4f018f4fc6846224bf047497e784af1Stan Iliev    } else {
25152771272f4f018f4fc6846224bf047497e784af1Stan Iliev        // It there are multiple render nodes, they are laid out as follows:
25252771272f4f018f4fc6846224bf047497e784af1Stan Iliev        // #0 - backdrop (content + caption)
25352771272f4f018f4fc6846224bf047497e784af1Stan Iliev        // #1 - content (local bounds are at (0,0), will be translated and clipped to backdrop)
25452771272f4f018f4fc6846224bf047497e784af1Stan Iliev        // #2 - additional overlay nodes
25552771272f4f018f4fc6846224bf047497e784af1Stan Iliev        // Usually the backdrop cannot be seen since it will be entirely covered by the content. While
25652771272f4f018f4fc6846224bf047497e784af1Stan Iliev        // resizing however it might become partially visible. The following render loop will crop the
25752771272f4f018f4fc6846224bf047497e784af1Stan Iliev        // backdrop against the content and draw the remaining part of it. It will then draw the content
25852771272f4f018f4fc6846224bf047497e784af1Stan Iliev        // cropped to the backdrop (since that indicates a shrinking of the window).
25952771272f4f018f4fc6846224bf047497e784af1Stan Iliev        //
26052771272f4f018f4fc6846224bf047497e784af1Stan Iliev        // Additional nodes will be drawn on top with no particular clipping semantics.
26152771272f4f018f4fc6846224bf047497e784af1Stan Iliev
26252771272f4f018f4fc6846224bf047497e784af1Stan Iliev        // Usually the contents bounds should be mContentDrawBounds - however - we will
26352771272f4f018f4fc6846224bf047497e784af1Stan Iliev        // move it towards the fixed edge to give it a more stable appearance (for the moment).
26452771272f4f018f4fc6846224bf047497e784af1Stan Iliev        // If there is no content bounds we ignore the layering as stated above and start with 2.
26552771272f4f018f4fc6846224bf047497e784af1Stan Iliev
26652771272f4f018f4fc6846224bf047497e784af1Stan Iliev        // Backdrop bounds in render target space
26752771272f4f018f4fc6846224bf047497e784af1Stan Iliev        const Rect backdrop = nodeBounds(*nodes[0]);
26852771272f4f018f4fc6846224bf047497e784af1Stan Iliev
26952771272f4f018f4fc6846224bf047497e784af1Stan Iliev        // Bounds that content will fill in render target space (note content node bounds may be bigger)
27052771272f4f018f4fc6846224bf047497e784af1Stan Iliev        Rect content(contentDrawBounds.getWidth(), contentDrawBounds.getHeight());
27152771272f4f018f4fc6846224bf047497e784af1Stan Iliev        content.translate(backdrop.left, backdrop.top);
27252771272f4f018f4fc6846224bf047497e784af1Stan Iliev        if (!content.contains(backdrop) && !nodes[0]->nothingToDraw()) {
27352771272f4f018f4fc6846224bf047497e784af1Stan Iliev            // Content doesn't entirely overlap backdrop, so fill around content (right/bottom)
27452771272f4f018f4fc6846224bf047497e784af1Stan Iliev
27552771272f4f018f4fc6846224bf047497e784af1Stan Iliev            // Note: in the future, if content doesn't snap to backdrop's left/top, this may need to
27652771272f4f018f4fc6846224bf047497e784af1Stan Iliev            // also fill left/top. Currently, both 2up and freeform position content at the top/left of
27752771272f4f018f4fc6846224bf047497e784af1Stan Iliev            // the backdrop, so this isn't necessary.
27852771272f4f018f4fc6846224bf047497e784af1Stan Iliev            RenderNodeDrawable backdropNode(nodes[0].get(), canvas);
27952771272f4f018f4fc6846224bf047497e784af1Stan Iliev            if (content.right < backdrop.right) {
28052771272f4f018f4fc6846224bf047497e784af1Stan Iliev                // draw backdrop to right side of content
28152771272f4f018f4fc6846224bf047497e784af1Stan Iliev                SkAutoCanvasRestore acr(canvas, true);
28252771272f4f018f4fc6846224bf047497e784af1Stan Iliev                canvas->clipRect(SkRect::MakeLTRB(content.right, backdrop.top,
28352771272f4f018f4fc6846224bf047497e784af1Stan Iliev                        backdrop.right, backdrop.bottom));
28452771272f4f018f4fc6846224bf047497e784af1Stan Iliev                backdropNode.draw(canvas);
28552771272f4f018f4fc6846224bf047497e784af1Stan Iliev            }
28652771272f4f018f4fc6846224bf047497e784af1Stan Iliev            if (content.bottom < backdrop.bottom) {
28752771272f4f018f4fc6846224bf047497e784af1Stan Iliev                // draw backdrop to bottom of content
28852771272f4f018f4fc6846224bf047497e784af1Stan Iliev                // Note: bottom fill uses content left/right, to avoid overdrawing left/right fill
28952771272f4f018f4fc6846224bf047497e784af1Stan Iliev                SkAutoCanvasRestore acr(canvas, true);
29052771272f4f018f4fc6846224bf047497e784af1Stan Iliev                canvas->clipRect(SkRect::MakeLTRB(content.left, content.bottom,
29152771272f4f018f4fc6846224bf047497e784af1Stan Iliev                        content.right, backdrop.bottom));
29252771272f4f018f4fc6846224bf047497e784af1Stan Iliev                backdropNode.draw(canvas);
29352771272f4f018f4fc6846224bf047497e784af1Stan Iliev            }
29452771272f4f018f4fc6846224bf047497e784af1Stan Iliev        }
29552771272f4f018f4fc6846224bf047497e784af1Stan Iliev
29652771272f4f018f4fc6846224bf047497e784af1Stan Iliev        RenderNodeDrawable contentNode(nodes[1].get(), canvas);
29752771272f4f018f4fc6846224bf047497e784af1Stan Iliev        if (!backdrop.isEmpty()) {
29852771272f4f018f4fc6846224bf047497e784af1Stan Iliev            // content node translation to catch up with backdrop
29952771272f4f018f4fc6846224bf047497e784af1Stan Iliev            float dx = backdrop.left - contentDrawBounds.left;
30052771272f4f018f4fc6846224bf047497e784af1Stan Iliev            float dy = backdrop.top - contentDrawBounds.top;
30152771272f4f018f4fc6846224bf047497e784af1Stan Iliev
30252771272f4f018f4fc6846224bf047497e784af1Stan Iliev            SkAutoCanvasRestore acr(canvas, true);
303500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            canvas->translate(dx, dy);
30452771272f4f018f4fc6846224bf047497e784af1Stan Iliev            const SkRect contentLocalClip = SkRect::MakeXYWH(contentDrawBounds.left,
30552771272f4f018f4fc6846224bf047497e784af1Stan Iliev                    contentDrawBounds.top, backdrop.getWidth(), backdrop.getHeight());
30652771272f4f018f4fc6846224bf047497e784af1Stan Iliev            canvas->clipRect(contentLocalClip);
30752771272f4f018f4fc6846224bf047497e784af1Stan Iliev            contentNode.draw(canvas);
30852771272f4f018f4fc6846224bf047497e784af1Stan Iliev        } else {
30952771272f4f018f4fc6846224bf047497e784af1Stan Iliev            SkAutoCanvasRestore acr(canvas, true);
31052771272f4f018f4fc6846224bf047497e784af1Stan Iliev            contentNode.draw(canvas);
311500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        }
312500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
31352771272f4f018f4fc6846224bf047497e784af1Stan Iliev        // remaining overlay nodes, simply defer
31452771272f4f018f4fc6846224bf047497e784af1Stan Iliev        for (size_t index = 2; index < nodes.size(); index++) {
31552771272f4f018f4fc6846224bf047497e784af1Stan Iliev            if (!nodes[index]->nothingToDraw()) {
31652771272f4f018f4fc6846224bf047497e784af1Stan Iliev                SkAutoCanvasRestore acr(canvas, true);
31752771272f4f018f4fc6846224bf047497e784af1Stan Iliev                RenderNodeDrawable overlayNode(nodes[index].get(), canvas);
31852771272f4f018f4fc6846224bf047497e784af1Stan Iliev                overlayNode.draw(canvas);
31952771272f4f018f4fc6846224bf047497e784af1Stan Iliev            }
32052771272f4f018f4fc6846224bf047497e784af1Stan Iliev        }
321500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    }
322500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev}
323500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
3244bda6bfaa6b8cb775f18f2453720d05f4cb29152Matt Sarettvoid SkiaPipeline::dumpResourceCacheUsage() const {
3254bda6bfaa6b8cb775f18f2453720d05f4cb29152Matt Sarett    int resources, maxResources;
3264bda6bfaa6b8cb775f18f2453720d05f4cb29152Matt Sarett    size_t bytes, maxBytes;
3274bda6bfaa6b8cb775f18f2453720d05f4cb29152Matt Sarett    mRenderThread.getGrContext()->getResourceCacheUsage(&resources, &bytes);
3284bda6bfaa6b8cb775f18f2453720d05f4cb29152Matt Sarett    mRenderThread.getGrContext()->getResourceCacheLimits(&maxResources, &maxBytes);
3294bda6bfaa6b8cb775f18f2453720d05f4cb29152Matt Sarett
3304bda6bfaa6b8cb775f18f2453720d05f4cb29152Matt Sarett    SkString log("Resource Cache Usage:\n");
3314bda6bfaa6b8cb775f18f2453720d05f4cb29152Matt Sarett    log.appendf("%8d items out of %d maximum items\n", resources, maxResources);
3324bda6bfaa6b8cb775f18f2453720d05f4cb29152Matt Sarett    log.appendf("%8zu bytes (%.2f MB) out of %.2f MB maximum\n",
3334bda6bfaa6b8cb775f18f2453720d05f4cb29152Matt Sarett            bytes, bytes * (1.0f / (1024.0f * 1024.0f)), maxBytes * (1.0f / (1024.0f * 1024.0f)));
3344bda6bfaa6b8cb775f18f2453720d05f4cb29152Matt Sarett
3354bda6bfaa6b8cb775f18f2453720d05f4cb29152Matt Sarett    ALOGD("%s", log.c_str());
3364bda6bfaa6b8cb775f18f2453720d05f4cb29152Matt Sarett}
3374bda6bfaa6b8cb775f18f2453720d05f4cb29152Matt Sarett
338f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett// Overdraw debugging
339f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett
340f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett// These colors should be kept in sync with Caches::getOverdrawColor() with a few differences.
341f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett// This implementation:
342f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett// (1) Requires transparent entries for "no overdraw" and "single draws".
343f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett// (2) Requires premul colors (instead of unpremul).
344f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett// (3) Requires RGBA colors (instead of BGRA).
345f58cc92066903b900396f640159ea3ea992fc67dMatt Sarettstatic const uint32_t kOverdrawColors[2][6] = {
346f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett        { 0x00000000, 0x00000000, 0x2f2f0000, 0x2f002f00, 0x3f00003f, 0x7f00007f, },
347f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett        { 0x00000000, 0x00000000, 0x2f2f0000, 0x4f004f4f, 0x5f50335f, 0x7f00007f, },
348f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett};
349f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett
350f58cc92066903b900396f640159ea3ea992fc67dMatt Sarettvoid SkiaPipeline::renderOverdraw(const LayerUpdateQueue& layers, const SkRect& clip,
351f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett        const std::vector<sp<RenderNode>>& nodes, const Rect &contentDrawBounds,
352f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett        sk_sp<SkSurface> surface) {
353f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett    // Set up the overdraw canvas.
354f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett    SkImageInfo offscreenInfo = SkImageInfo::MakeA8(surface->width(), surface->height());
355f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett    sk_sp<SkSurface> offscreen = surface->makeSurface(offscreenInfo);
356f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett    SkOverdrawCanvas overdrawCanvas(offscreen->getCanvas());
357f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett
358f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett    // Fake a redraw to replay the draw commands.  This will increment the alpha channel
359f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett    // each time a pixel would have been drawn.
360f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett    // Pass true for opaque so we skip the clear - the overdrawCanvas is already zero
361f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett    // initialized.
362f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett    renderFrameImpl(layers, clip, nodes, true, contentDrawBounds, &overdrawCanvas);
363f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett    sk_sp<SkImage> counts = offscreen->makeImageSnapshot();
364f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett
365f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett    // Draw overdraw colors to the canvas.  The color filter will convert counts to colors.
366f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett    SkPaint paint;
367f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett    const SkPMColor* colors = kOverdrawColors[static_cast<int>(Properties::overdrawColorSet)];
368f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett    paint.setColorFilter(SkOverdrawColorFilter::Make(colors));
369f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett    surface->getCanvas()->drawImage(counts.get(), 0.0f, 0.0f, &paint);
370f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett}
371f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett
372500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev} /* namespace skiapipeline */
373500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev} /* namespace uirenderer */
374500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev} /* namespace android */
375