SkiaPipeline.cpp revision 576b6a8a7994f649c0dbacfc34611d1580e16bd6
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