SkiaPipeline.cpp revision b66b8bb4a089593ee7c20ad7f59980c16dde9cc9
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>
21ee708facf127f2e8bed5970d5c05fa823fcfc1ceLeon Scroggins III#include <SkImagePriv.h>
22500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev#include <SkOSFile.h>
23f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett#include <SkOverdrawCanvas.h>
24f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett#include <SkOverdrawColorFilter.h>
25500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev#include <SkPicture.h>
26500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev#include <SkPictureRecorder.h>
27500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev#include <SkPixelSerializer.h>
28500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev#include <SkStream.h>
29500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
30500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievusing namespace android::uirenderer::renderthread;
31500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
32500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievnamespace android {
33500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievnamespace uirenderer {
34500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievnamespace skiapipeline {
35500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
36500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievfloat   SkiaPipeline::mLightRadius = 0;
37500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievuint8_t SkiaPipeline::mAmbientShadowAlpha = 0;
38500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievuint8_t SkiaPipeline::mSpotShadowAlpha = 0;
39500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
40500a0c30d4dcd012218c3e44a62926a1c34a259fStan IlievVector3 SkiaPipeline::mLightCenter = {FLT_MIN, FLT_MIN, FLT_MIN};
41500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
42500a0c30d4dcd012218c3e44a62926a1c34a259fStan IlievSkiaPipeline::SkiaPipeline(RenderThread& thread) :  mRenderThread(thread) { }
43500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
44500a0c30d4dcd012218c3e44a62926a1c34a259fStan IlievTaskManager* SkiaPipeline::getTaskManager() {
45500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    return &mTaskManager;
46500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev}
47500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
48500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievvoid SkiaPipeline::onDestroyHardwareResources() {
49500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    // No need to flush the caches here. There is a timer
50500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    // which will flush temporary resources over time.
51500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev}
52500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
53b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenbergerbool SkiaPipeline::pinImages(std::vector<SkImage*>& mutableImages) {
54b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger    for (SkImage* image : mutableImages) {
55189e87498f666e94dc8c8201e7bac56bb09b9251Derek Sollenberger        if (SkImage_pinAsTexture(image, mRenderThread.getGrContext())) {
56189e87498f666e94dc8c8201e7bac56bb09b9251Derek Sollenberger            mPinnedImages.emplace_back(sk_ref_sp(image));
57189e87498f666e94dc8c8201e7bac56bb09b9251Derek Sollenberger        } else {
58189e87498f666e94dc8c8201e7bac56bb09b9251Derek Sollenberger            return false;
59189e87498f666e94dc8c8201e7bac56bb09b9251Derek Sollenberger        }
60b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger    }
61b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger    return true;
62b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger}
63b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger
64b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenbergervoid SkiaPipeline::unpinImages() {
65b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger    for (auto& image : mPinnedImages) {
66b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger        SkImage_unpinAsTexture(image.get(), mRenderThread.getGrContext());
67b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger    }
68b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger    mPinnedImages.clear();
69b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger}
70b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger
71500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievvoid SkiaPipeline::renderLayers(const FrameBuilder::LightGeometry& lightGeometry,
72500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        LayerUpdateQueue* layerUpdateQueue, bool opaque,
73500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        const BakedOpRenderer::LightInfo& lightInfo) {
74500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    updateLighting(lightGeometry, lightInfo);
75500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    ATRACE_NAME("draw layers");
76500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    renderLayersImpl(*layerUpdateQueue, opaque);
77500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    layerUpdateQueue->clear();
78500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev}
79500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
80500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievvoid SkiaPipeline::renderLayersImpl(const LayerUpdateQueue& layers, bool opaque) {
81500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    // Render all layers that need to be updated, in order.
82500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    for (size_t i = 0; i < layers.entries().size(); i++) {
83500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        RenderNode* layerNode = layers.entries()[i].renderNode;
84500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        // only schedule repaint if node still on layer - possible it may have been
85500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        // removed during a dropped frame, but layers may still remain scheduled so
86500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        // as not to lose info on what portion is damaged
87500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        if (CC_LIKELY(layerNode->getLayerSurface() != nullptr)) {
88500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            SkASSERT(layerNode->getLayerSurface());
89500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            SkASSERT(layerNode->getDisplayList()->isSkiaDL());
90500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            SkiaDisplayList* displayList = (SkiaDisplayList*)layerNode->getDisplayList();
91500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            if (!displayList || displayList->isEmpty()) {
92500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev                SkDEBUGF(("%p drawLayers(%s) : missing drawable", this, layerNode->getName()));
93500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev                return;
94500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            }
95500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
96500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            const Rect& layerDamage = layers.entries()[i].damage;
97500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
98500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            SkCanvas* layerCanvas = layerNode->getLayerSurface()->getCanvas();
99500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
100500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            int saveCount = layerCanvas->save();
101500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            SkASSERT(saveCount == 1);
102500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
103b66b8bb4a089593ee7c20ad7f59980c16dde9cc9Stan Iliev            layerCanvas->androidFramework_setDeviceClipRestriction(layerDamage.toSkIRect());
104500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
105500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            auto savedLightCenter = mLightCenter;
106500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            // map current light center into RenderNode's coordinate space
107500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            layerNode->getSkiaLayer()->inverseTransformInWindow.mapPoint3d(mLightCenter);
108500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
109500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            const RenderProperties& properties = layerNode->properties();
110500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            const SkRect bounds = SkRect::MakeWH(properties.getWidth(), properties.getHeight());
111500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            if (properties.getClipToBounds() && layerCanvas->quickReject(bounds)) {
112500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev                return;
113500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            }
114500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
11579756be175dea78ee9d51bb22abba7621bd9b5ccMatt Sarett            layerNode->getSkiaLayer()->hasRenderedSinceRepaint = false;
116500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            layerCanvas->clear(SK_ColorTRANSPARENT);
117500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
118500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            RenderNodeDrawable root(layerNode, layerCanvas, false);
119500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            root.forceDraw(layerCanvas);
120500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            layerCanvas->restoreToCount(saveCount);
121500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            layerCanvas->flush();
122500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            mLightCenter = savedLightCenter;
123500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        }
124500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    }
125500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev}
126500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
127500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievbool SkiaPipeline::createOrUpdateLayer(RenderNode* node,
128500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        const DamageAccumulator& damageAccumulator) {
129500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    SkSurface* layer = node->getLayerSurface();
130500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    if (!layer || layer->width() != node->getWidth() || layer->height() != node->getHeight()) {
131500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        SkImageInfo info = SkImageInfo::MakeN32Premul(node->getWidth(), node->getHeight());
132500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
133500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        SkASSERT(mRenderThread.getGrContext() != nullptr);
134500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        node->setLayerSurface(
135500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev                SkSurface::MakeRenderTarget(mRenderThread.getGrContext(), SkBudgeted::kYes,
136500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev                        info, 0, &props));
137500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        if (node->getLayerSurface()) {
138500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            // update the transform in window of the layer to reset its origin wrt light source
139500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            // position
140500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            Matrix4 windowTransform;
141500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            damageAccumulator.computeCurrentTransform(&windowTransform);
142500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            node->getSkiaLayer()->inverseTransformInWindow = windowTransform;
143500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        }
144500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        return true;
145500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    }
146500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    return false;
147500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev}
148500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
149500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievvoid SkiaPipeline::destroyLayer(RenderNode* node) {
150500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    node->setLayerSurface(nullptr);
151500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev}
152500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
153500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievvoid SkiaPipeline::prepareToDraw(const RenderThread& thread, Bitmap* bitmap) {
154500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    GrContext* context = thread.getGrContext();
155500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    if (context) {
156500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        ATRACE_FORMAT("Bitmap#prepareToDraw %dx%d", bitmap->width(), bitmap->height());
157500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        SkBitmap skiaBitmap;
158500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        bitmap->getSkBitmap(&skiaBitmap);
159500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        sk_sp<SkImage> image = SkMakeImageFromRasterBitmap(skiaBitmap, kNever_SkCopyPixelsMode);
160500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        SkImage_pinAsTexture(image.get(), context);
161500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        SkImage_unpinAsTexture(image.get(), context);
162500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    }
163500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev}
164500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
165500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev// Encodes to PNG, unless there is already encoded data, in which case that gets
166500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev// used.
167500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievclass PngPixelSerializer : public SkPixelSerializer {
168500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievpublic:
169500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    bool onUseEncodedData(const void*, size_t) override { return true; }
170500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    SkData* onEncode(const SkPixmap& pixmap) override {
17110219fb261606fcc71c607167b28295b4578a10dHal Canary        SkDynamicMemoryWStream buf;
17210219fb261606fcc71c607167b28295b4578a10dHal Canary        return SkEncodeImage(&buf, pixmap, SkEncodedImageFormat::kPNG, 100)
17310219fb261606fcc71c607167b28295b4578a10dHal Canary               ? buf.detachAsData().release()
17410219fb261606fcc71c607167b28295b4578a10dHal Canary               : nullptr;
175500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    }
176500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev};
177500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
178500a0c30d4dcd012218c3e44a62926a1c34a259fStan Ilievvoid SkiaPipeline::renderFrame(const LayerUpdateQueue& layers, const SkRect& clip,
179500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        const std::vector<sp<RenderNode>>& nodes, bool opaque, const Rect &contentDrawBounds,
180500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        sk_sp<SkSurface> surface) {
181500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
182500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    // draw all layers up front
183500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    renderLayersImpl(layers, opaque);
184500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
185500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    // initialize the canvas for the current frame
186500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    SkCanvas* canvas = surface->getCanvas();
187500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
188500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    std::unique_ptr<SkPictureRecorder> recorder;
189500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    bool recordingPicture = false;
190500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    char prop[PROPERTY_VALUE_MAX];
191500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    if (skpCaptureEnabled()) {
192500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        property_get("debug.hwui.capture_frame_as_skp", prop, "0");
193500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        recordingPicture = prop[0] != '0' && !sk_exists(prop);
194500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        if (recordingPicture) {
195500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            recorder.reset(new SkPictureRecorder());
196500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            canvas = recorder->beginRecording(surface->width(), surface->height(),
197500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev                    nullptr, SkPictureRecorder::kPlaybackDrawPicture_RecordFlag);
198500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        }
199500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    }
200500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
201f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett    renderFrameImpl(layers, clip, nodes, opaque, contentDrawBounds, canvas);
202f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett
203f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett    if (skpCaptureEnabled() && recordingPicture) {
204f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett        sk_sp<SkPicture> picture = recorder->finishRecordingAsPicture();
205f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett        if (picture->approximateOpCount() > 0) {
206f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett            SkFILEWStream stream(prop);
207f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett            if (stream.isValid()) {
208f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett                PngPixelSerializer serializer;
209f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett                picture->serialize(&stream, &serializer);
210f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett                stream.flush();
211f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett                SkDebugf("Captured Drawing Output (%d bytes) for frame. %s", stream.bytesWritten(), prop);
212f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett            }
213f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett        }
214f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett        surface->getCanvas()->drawPicture(picture);
215f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett    }
216f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett
217f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett    if (CC_UNLIKELY(Properties::debugOverdraw)) {
218f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett        renderOverdraw(layers, clip, nodes, contentDrawBounds, surface);
219f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett    }
220f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett
221f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett    ATRACE_NAME("flush commands");
222f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett    canvas->flush();
223f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett}
224f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett
22552771272f4f018f4fc6846224bf047497e784af1Stan Ilievnamespace {
22652771272f4f018f4fc6846224bf047497e784af1Stan Ilievstatic Rect nodeBounds(RenderNode& node) {
22752771272f4f018f4fc6846224bf047497e784af1Stan Iliev    auto& props = node.properties();
22852771272f4f018f4fc6846224bf047497e784af1Stan Iliev    return Rect(props.getLeft(), props.getTop(),
22952771272f4f018f4fc6846224bf047497e784af1Stan Iliev            props.getRight(), props.getBottom());
23052771272f4f018f4fc6846224bf047497e784af1Stan Iliev}
23152771272f4f018f4fc6846224bf047497e784af1Stan Iliev}
23252771272f4f018f4fc6846224bf047497e784af1Stan Iliev
233f58cc92066903b900396f640159ea3ea992fc67dMatt Sarettvoid SkiaPipeline::renderFrameImpl(const LayerUpdateQueue& layers, const SkRect& clip,
234f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett        const std::vector<sp<RenderNode>>& nodes, bool opaque, const Rect &contentDrawBounds,
235f58cc92066903b900396f640159ea3ea992fc67dMatt Sarett        SkCanvas* canvas) {
236b66b8bb4a089593ee7c20ad7f59980c16dde9cc9Stan Iliev    SkAutoCanvasRestore saver(canvas, true);
237b66b8bb4a089593ee7c20ad7f59980c16dde9cc9Stan Iliev    canvas->androidFramework_setDeviceClipRestriction(clip.roundOut());
238500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
239500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    if (!opaque) {
240500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        canvas->clear(SK_ColorTRANSPARENT);
241500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    }
242500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
24352771272f4f018f4fc6846224bf047497e784af1Stan Iliev    if (1 == nodes.size()) {
24452771272f4f018f4fc6846224bf047497e784af1Stan Iliev        if (!nodes[0]->nothingToDraw()) {
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