SkiaPipeline.cpp revision 189e87498f666e94dc8c8201e7bac56bb09b9251
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"
20500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev#include <SkOSFile.h>
21500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev#include <SkPicture.h>
22500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev#include <SkPictureRecorder.h>
23500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev#include <SkPixelSerializer.h>
24500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev#include <SkStream.h>
25500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
26500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievusing namespace android::uirenderer::renderthread;
27500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
28500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievnamespace android {
29500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievnamespace uirenderer {
30500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievnamespace skiapipeline {
31500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
32500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievfloat   SkiaPipeline::mLightRadius = 0;
33500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievuint8_t SkiaPipeline::mAmbientShadowAlpha = 0;
34500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievuint8_t SkiaPipeline::mSpotShadowAlpha = 0;
35500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
36500a0c30d4dcd012218c3e44a62926a1c34a259fStan IlievVector3 SkiaPipeline::mLightCenter = {FLT_MIN, FLT_MIN, FLT_MIN};
37500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
38500a0c30d4dcd012218c3e44a62926a1c34a259fStan IlievSkiaPipeline::SkiaPipeline(RenderThread& thread) :  mRenderThread(thread) { }
39500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
40500a0c30d4dcd012218c3e44a62926a1c34a259fStan IlievTaskManager* SkiaPipeline::getTaskManager() {
41500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    return &mTaskManager;
42500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev}
43500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
44500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievvoid SkiaPipeline::onDestroyHardwareResources() {
45500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    // No need to flush the caches here. There is a timer
46500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    // which will flush temporary resources over time.
47500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev}
48500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
49b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenbergerbool SkiaPipeline::pinImages(std::vector<SkImage*>& mutableImages) {
50b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger    for (SkImage* image : mutableImages) {
51189e87498f666e94dc8c8201e7bac56bb09b9251Derek Sollenberger        if (SkImage_pinAsTexture(image, mRenderThread.getGrContext())) {
52189e87498f666e94dc8c8201e7bac56bb09b9251Derek Sollenberger            mPinnedImages.emplace_back(sk_ref_sp(image));
53189e87498f666e94dc8c8201e7bac56bb09b9251Derek Sollenberger        } else {
54189e87498f666e94dc8c8201e7bac56bb09b9251Derek Sollenberger            return false;
55189e87498f666e94dc8c8201e7bac56bb09b9251Derek Sollenberger        }
56b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger    }
57b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger    return true;
58b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger}
59b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger
60b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenbergervoid SkiaPipeline::unpinImages() {
61b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger    for (auto& image : mPinnedImages) {
62b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger        SkImage_unpinAsTexture(image.get(), mRenderThread.getGrContext());
63b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger    }
64b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger    mPinnedImages.clear();
65b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger}
66b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger
67500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievvoid SkiaPipeline::renderLayers(const FrameBuilder::LightGeometry& lightGeometry,
68500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        LayerUpdateQueue* layerUpdateQueue, bool opaque,
69500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        const BakedOpRenderer::LightInfo& lightInfo) {
70500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    updateLighting(lightGeometry, lightInfo);
71500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    ATRACE_NAME("draw layers");
72500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    renderLayersImpl(*layerUpdateQueue, opaque);
73500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    layerUpdateQueue->clear();
74500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev}
75500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
76500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievvoid SkiaPipeline::renderLayersImpl(const LayerUpdateQueue& layers, bool opaque) {
77500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    // Render all layers that need to be updated, in order.
78500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    for (size_t i = 0; i < layers.entries().size(); i++) {
79500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        RenderNode* layerNode = layers.entries()[i].renderNode;
80500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        // only schedule repaint if node still on layer - possible it may have been
81500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        // removed during a dropped frame, but layers may still remain scheduled so
82500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        // as not to lose info on what portion is damaged
83500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        if (CC_LIKELY(layerNode->getLayerSurface() != nullptr)) {
84500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            SkASSERT(layerNode->getLayerSurface());
85500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            SkASSERT(layerNode->getDisplayList()->isSkiaDL());
86500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            SkiaDisplayList* displayList = (SkiaDisplayList*)layerNode->getDisplayList();
87500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            if (!displayList || displayList->isEmpty()) {
88500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev                SkDEBUGF(("%p drawLayers(%s) : missing drawable", this, layerNode->getName()));
89500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev                return;
90500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            }
91500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
92500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            const Rect& layerDamage = layers.entries()[i].damage;
93500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
94500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            SkCanvas* layerCanvas = layerNode->getLayerSurface()->getCanvas();
95500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
96500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            int saveCount = layerCanvas->save();
97500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            SkASSERT(saveCount == 1);
98500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
99500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            layerCanvas->clipRect(layerDamage.toSkRect(), SkRegion::kReplace_Op);
100500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
101500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            auto savedLightCenter = mLightCenter;
102500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            // map current light center into RenderNode's coordinate space
103500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            layerNode->getSkiaLayer()->inverseTransformInWindow.mapPoint3d(mLightCenter);
104500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
105500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            const RenderProperties& properties = layerNode->properties();
106500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            const SkRect bounds = SkRect::MakeWH(properties.getWidth(), properties.getHeight());
107500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            if (properties.getClipToBounds() && layerCanvas->quickReject(bounds)) {
108500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev                return;
109500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            }
110500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
111500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            layerCanvas->clear(SK_ColorTRANSPARENT);
112500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
113500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            RenderNodeDrawable root(layerNode, layerCanvas, false);
114500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            root.forceDraw(layerCanvas);
115500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            layerCanvas->restoreToCount(saveCount);
116500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            layerCanvas->flush();
117500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            mLightCenter = savedLightCenter;
118500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        }
119500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    }
120500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev}
121500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
122500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievbool SkiaPipeline::createOrUpdateLayer(RenderNode* node,
123500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        const DamageAccumulator& damageAccumulator) {
124500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    SkSurface* layer = node->getLayerSurface();
125500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    if (!layer || layer->width() != node->getWidth() || layer->height() != node->getHeight()) {
126500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        SkImageInfo info = SkImageInfo::MakeN32Premul(node->getWidth(), node->getHeight());
127500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
128500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        SkASSERT(mRenderThread.getGrContext() != nullptr);
129500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        node->setLayerSurface(
130500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev                SkSurface::MakeRenderTarget(mRenderThread.getGrContext(), SkBudgeted::kYes,
131500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev                        info, 0, &props));
132500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        if (node->getLayerSurface()) {
133500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            // update the transform in window of the layer to reset its origin wrt light source
134500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            // position
135500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            Matrix4 windowTransform;
136500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            damageAccumulator.computeCurrentTransform(&windowTransform);
137500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            node->getSkiaLayer()->inverseTransformInWindow = windowTransform;
138500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        }
139500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        return true;
140500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    }
141500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    return false;
142500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev}
143500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
144500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievvoid SkiaPipeline::destroyLayer(RenderNode* node) {
145500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    node->setLayerSurface(nullptr);
146500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev}
147500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
148500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievvoid SkiaPipeline::prepareToDraw(const RenderThread& thread, Bitmap* bitmap) {
149500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    GrContext* context = thread.getGrContext();
150500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    if (context) {
151500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        ATRACE_FORMAT("Bitmap#prepareToDraw %dx%d", bitmap->width(), bitmap->height());
152500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        SkBitmap skiaBitmap;
153500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        bitmap->getSkBitmap(&skiaBitmap);
154500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(skiaBitmap, kNever_SkCopyPixelsMode);
155500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        SkImage_pinAsTexture(image.get(), context);
156500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        SkImage_unpinAsTexture(image.get(), context);
157500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    }
158500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev}
159500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
160500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev// Encodes to PNG, unless there is already encoded data, in which case that gets
161500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev// used.
162500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievclass PngPixelSerializer : public SkPixelSerializer {
163500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievpublic:
164500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    bool onUseEncodedData(const void*, size_t) override { return true; }
165500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    SkData* onEncode(const SkPixmap& pixmap) override {
166500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        return SkImageEncoder::EncodeData(pixmap.info(), pixmap.addr(), pixmap.rowBytes(),
167500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev                                          SkImageEncoder::kPNG_Type, 100);
168500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    }
169500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev};
170500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
171500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievvoid SkiaPipeline::renderFrame(const LayerUpdateQueue& layers, const SkRect& clip,
172500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        const std::vector<sp<RenderNode>>& nodes, bool opaque, const Rect &contentDrawBounds,
173500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        sk_sp<SkSurface> surface) {
174500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
175500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    // draw all layers up front
176500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    renderLayersImpl(layers, opaque);
177500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
178500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    // initialize the canvas for the current frame
179500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    SkCanvas* canvas = surface->getCanvas();
180500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
181500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    std::unique_ptr<SkPictureRecorder> recorder;
182500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    bool recordingPicture = false;
183500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    char prop[PROPERTY_VALUE_MAX];
184500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    if (skpCaptureEnabled()) {
185500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        property_get("debug.hwui.capture_frame_as_skp", prop, "0");
186500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        recordingPicture = prop[0] != '0' && !sk_exists(prop);
187500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        if (recordingPicture) {
188500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            recorder.reset(new SkPictureRecorder());
189500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            canvas = recorder->beginRecording(surface->width(), surface->height(),
190500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev                    nullptr, SkPictureRecorder::kPlaybackDrawPicture_RecordFlag);
191500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        }
192500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    }
193500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
194500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    canvas->clipRect(clip, SkRegion::kReplace_Op);
195500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
196500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    if (!opaque) {
197500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        canvas->clear(SK_ColorTRANSPARENT);
198500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    }
199500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
200500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    // If there are multiple render nodes, they are laid out as follows:
201500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    // #0 - backdrop (content + caption)
202500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    // #1 - content (positioned at (0,0) and clipped to - its bounds mContentDrawBounds)
203500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    // #2 - additional overlay nodes
204500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    // Usually the backdrop cannot be seen since it will be entirely covered by the content. While
205500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    // resizing however it might become partially visible. The following render loop will crop the
206500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    // backdrop against the content and draw the remaining part of it. It will then draw the content
207500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    // cropped to the backdrop (since that indicates a shrinking of the window).
208500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    //
209500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    // Additional nodes will be drawn on top with no particular clipping semantics.
210500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
211500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    // The bounds of the backdrop against which the content should be clipped.
212500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    Rect backdropBounds = contentDrawBounds;
213500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    // Usually the contents bounds should be mContentDrawBounds - however - we will
214500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    // move it towards the fixed edge to give it a more stable appearance (for the moment).
215500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    // If there is no content bounds we ignore the layering as stated above and start with 2.
216500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    int layer = (contentDrawBounds.isEmpty() || nodes.size() == 1) ? 2 : 0;
217500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
218500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    for (const sp<RenderNode>& node : nodes) {
219500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        if (node->nothingToDraw()) continue;
220500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
221500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        SkASSERT(node->getDisplayList()->isSkiaDL());
222500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
223500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        int count = canvas->save();
224500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
225500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        if (layer == 0) {
226500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            const RenderProperties& properties = node->properties();
227500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            Rect targetBounds(properties.getLeft(), properties.getTop(),
228500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev                              properties.getRight(), properties.getBottom());
229500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            // Move the content bounds towards the fixed corner of the backdrop.
230500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            const int x = targetBounds.left;
231500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            const int y = targetBounds.top;
232500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            // Remember the intersection of the target bounds and the intersection bounds against
233500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            // which we have to crop the content.
234500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            backdropBounds.set(x, y, x + backdropBounds.getWidth(), y + backdropBounds.getHeight());
235500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            backdropBounds.doIntersect(targetBounds);
236500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        } else if (layer == 1) {
237500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            // We shift and clip the content to match its final location in the window.
238500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            const SkRect clip = SkRect::MakeXYWH(contentDrawBounds.left, contentDrawBounds.top,
239500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev                                                 backdropBounds.getWidth(), backdropBounds.getHeight());
240500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            const float dx = backdropBounds.left - contentDrawBounds.left;
241500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            const float dy = backdropBounds.top - contentDrawBounds.top;
242500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            canvas->translate(dx, dy);
243500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            // It gets cropped against the bounds of the backdrop to stay inside.
244500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            canvas->clipRect(clip, SkRegion::kIntersect_Op);
245500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        }
246500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
247500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        RenderNodeDrawable root(node.get(), canvas);
248500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        root.draw(canvas);
249500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        canvas->restoreToCount(count);
250500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        layer++;
251500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    }
252500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
253500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    if (skpCaptureEnabled() && recordingPicture) {
254500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        sk_sp<SkPicture> picture = recorder->finishRecordingAsPicture();
255500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        if (picture->approximateOpCount() > 0) {
256500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            SkFILEWStream stream(prop);
257500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            if (stream.isValid()) {
258500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev                PngPixelSerializer serializer;
259500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev                picture->serialize(&stream, &serializer);
260500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev                stream.flush();
261500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev                SkDebugf("Captured Drawing Output (%d bytes) for frame. %s", stream.bytesWritten(), prop);
262500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            }
263500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        }
264500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        surface->getCanvas()->drawPicture(picture);
265500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    }
266500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
267500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    ATRACE_NAME("flush commands");
268500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    canvas->flush();
269500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev}
270500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
2714bda6bfaa6b8cb775f18f2453720d05f4cb29152Matt Sarettvoid SkiaPipeline::dumpResourceCacheUsage() const {
2724bda6bfaa6b8cb775f18f2453720d05f4cb29152Matt Sarett    int resources, maxResources;
2734bda6bfaa6b8cb775f18f2453720d05f4cb29152Matt Sarett    size_t bytes, maxBytes;
2744bda6bfaa6b8cb775f18f2453720d05f4cb29152Matt Sarett    mRenderThread.getGrContext()->getResourceCacheUsage(&resources, &bytes);
2754bda6bfaa6b8cb775f18f2453720d05f4cb29152Matt Sarett    mRenderThread.getGrContext()->getResourceCacheLimits(&maxResources, &maxBytes);
2764bda6bfaa6b8cb775f18f2453720d05f4cb29152Matt Sarett
2774bda6bfaa6b8cb775f18f2453720d05f4cb29152Matt Sarett    SkString log("Resource Cache Usage:\n");
2784bda6bfaa6b8cb775f18f2453720d05f4cb29152Matt Sarett    log.appendf("%8d items out of %d maximum items\n", resources, maxResources);
2794bda6bfaa6b8cb775f18f2453720d05f4cb29152Matt Sarett    log.appendf("%8zu bytes (%.2f MB) out of %.2f MB maximum\n",
2804bda6bfaa6b8cb775f18f2453720d05f4cb29152Matt Sarett            bytes, bytes * (1.0f / (1024.0f * 1024.0f)), maxBytes * (1.0f / (1024.0f * 1024.0f)));
2814bda6bfaa6b8cb775f18f2453720d05f4cb29152Matt Sarett
2824bda6bfaa6b8cb775f18f2453720d05f4cb29152Matt Sarett    ALOGD("%s", log.c_str());
2834bda6bfaa6b8cb775f18f2453720d05f4cb29152Matt Sarett}
2844bda6bfaa6b8cb775f18f2453720d05f4cb29152Matt Sarett
285500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev} /* namespace skiapipeline */
286500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev} /* namespace uirenderer */
287500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev} /* namespace android */
288