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