FrameBuilder.cpp revision 0b7e8245db728d127ada698be63d78b33fc6e4da
1b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik/* 2b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * Copyright (C) 2015 The Android Open Source Project 3b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * 4b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * Licensed under the Apache License, Version 2.0 (the "License"); 5b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * you may not use this file except in compliance with the License. 6b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * You may obtain a copy of the License at 7b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * 8b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * http://www.apache.org/licenses/LICENSE-2.0 9b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * 10b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * Unless required by applicable law or agreed to in writing, software 11b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * distributed under the License is distributed on an "AS IS" BASIS, 12b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * See the License for the specific language governing permissions and 14b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * limitations under the License. 15b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik */ 16b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 17b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include "OpReorderer.h" 18b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 19b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include "utils/PaintUtils.h" 20b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include "RenderNode.h" 210b7e8245db728d127ada698be63d78b33fc6e4daChris Craik#include "LayerUpdateQueue.h" 22b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 23b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include "SkCanvas.h" 24b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include "utils/Trace.h" 25b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 26b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craiknamespace android { 27b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craiknamespace uirenderer { 28b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 29b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikclass BatchBase { 30b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 31b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikpublic: 32b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik BatchBase(batchid_t batchId, BakedOpState* op, bool merging) 33b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik : mBatchId(batchId) 34b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik , mMerging(merging) { 35b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik mBounds = op->computedState.clippedBounds; 36b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik mOps.push_back(op); 37b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 38b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 39b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik bool intersects(const Rect& rect) const { 40b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (!rect.intersects(mBounds)) return false; 41b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 42b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik for (const BakedOpState* op : mOps) { 43b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (rect.intersects(op->computedState.clippedBounds)) { 44b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik return true; 45b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 46b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 47b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik return false; 48b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 49b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 50b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik batchid_t getBatchId() const { return mBatchId; } 51b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik bool isMerging() const { return mMerging; } 52b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 53b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik const std::vector<BakedOpState*>& getOps() const { return mOps; } 54b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 55b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik void dump() const { 566fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik ALOGD(" Batch %p, id %d, merging %d, count %d, bounds " RECT_STRING, 576fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik this, mBatchId, mMerging, mOps.size(), RECT_ARGS(mBounds)); 58b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 59b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikprotected: 60b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik batchid_t mBatchId; 61b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik Rect mBounds; 62b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik std::vector<BakedOpState*> mOps; 63b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik bool mMerging; 64b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}; 65b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 66b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikclass OpBatch : public BatchBase { 67b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikpublic: 68b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik static void* operator new(size_t size, LinearAllocator& allocator) { 69b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik return allocator.alloc(size); 70b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 71b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 72b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik OpBatch(batchid_t batchId, BakedOpState* op) 73b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik : BatchBase(batchId, op, false) { 74b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 75b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 76b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik void batchOp(BakedOpState* op) { 77b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik mBounds.unionWith(op->computedState.clippedBounds); 78b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik mOps.push_back(op); 79b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 80b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}; 81b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 82b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikclass MergingOpBatch : public BatchBase { 83b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikpublic: 84b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik static void* operator new(size_t size, LinearAllocator& allocator) { 85b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik return allocator.alloc(size); 86b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 87b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 88b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik MergingOpBatch(batchid_t batchId, BakedOpState* op) 89b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik : BatchBase(batchId, op, true) { 90b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 91b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 92b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik /* 93b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * Helper for determining if a new op can merge with a MergingDrawBatch based on their bounds 94b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * and clip side flags. Positive bounds delta means new bounds fit in old. 95b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik */ 96b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik static inline bool checkSide(const int currentFlags, const int newFlags, const int side, 97b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik float boundsDelta) { 98b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik bool currentClipExists = currentFlags & side; 99b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik bool newClipExists = newFlags & side; 100b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 101b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // if current is clipped, we must be able to fit new bounds in current 102b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (boundsDelta > 0 && currentClipExists) return false; 103b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 104b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // if new is clipped, we must be able to fit current bounds in new 105b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (boundsDelta < 0 && newClipExists) return false; 106b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 107b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik return true; 108b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 109b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 110b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik static bool paintIsDefault(const SkPaint& paint) { 111b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik return paint.getAlpha() == 255 112b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik && paint.getColorFilter() == nullptr 113b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik && paint.getShader() == nullptr; 114b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 115b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 116b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik static bool paintsAreEquivalent(const SkPaint& a, const SkPaint& b) { 117b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik return a.getAlpha() == b.getAlpha() 118b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik && a.getColorFilter() == b.getColorFilter() 119b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik && a.getShader() == b.getShader(); 120b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 121b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 122b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik /* 123b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * Checks if a (mergeable) op can be merged into this batch 124b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * 125b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * If true, the op's multiDraw must be guaranteed to handle both ops simultaneously, so it is 126b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * important to consider all paint attributes used in the draw calls in deciding both a) if an 127b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * op tries to merge at all, and b) if the op can merge with another set of ops 128b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * 129b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * False positives can lead to information from the paints of subsequent merged operations being 130b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * dropped, so we make simplifying qualifications on the ops that can merge, per op type. 131b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik */ 132b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik bool canMergeWith(BakedOpState* op) const { 133b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik bool isTextBatch = getBatchId() == OpBatchType::Text 134b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik || getBatchId() == OpBatchType::ColorText; 135b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 136b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // Overlapping other operations is only allowed for text without shadow. For other ops, 137b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // multiDraw isn't guaranteed to overdraw correctly 138b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (!isTextBatch || PaintUtils::hasTextShadow(op->op->paint)) { 139b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (intersects(op->computedState.clippedBounds)) return false; 140b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 141b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 142b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik const BakedOpState* lhs = op; 143b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik const BakedOpState* rhs = mOps[0]; 144b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 145b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (!MathUtils::areEqual(lhs->alpha, rhs->alpha)) return false; 146b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 147b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // Identical round rect clip state means both ops will clip in the same way, or not at all. 148b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // As the state objects are const, we can compare their pointers to determine mergeability 149b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (lhs->roundRectClipState != rhs->roundRectClipState) return false; 150b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (lhs->projectionPathMask != rhs->projectionPathMask) return false; 151b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 152b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik /* Clipping compatibility check 153b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * 154b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * Exploits the fact that if a op or batch is clipped on a side, its bounds will equal its 155b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * clip for that side. 156b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik */ 157b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik const int currentFlags = mClipSideFlags; 158b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik const int newFlags = op->computedState.clipSideFlags; 159b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (currentFlags != OpClipSideFlags::None || newFlags != OpClipSideFlags::None) { 160b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik const Rect& opBounds = op->computedState.clippedBounds; 161b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik float boundsDelta = mBounds.left - opBounds.left; 162b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (!checkSide(currentFlags, newFlags, OpClipSideFlags::Left, boundsDelta)) return false; 163b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik boundsDelta = mBounds.top - opBounds.top; 164b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (!checkSide(currentFlags, newFlags, OpClipSideFlags::Top, boundsDelta)) return false; 165b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 166b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // right and bottom delta calculation reversed to account for direction 167b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik boundsDelta = opBounds.right - mBounds.right; 168b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (!checkSide(currentFlags, newFlags, OpClipSideFlags::Right, boundsDelta)) return false; 169b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik boundsDelta = opBounds.bottom - mBounds.bottom; 170b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (!checkSide(currentFlags, newFlags, OpClipSideFlags::Bottom, boundsDelta)) return false; 171b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 172b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 173b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik const SkPaint* newPaint = op->op->paint; 174b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik const SkPaint* oldPaint = mOps[0]->op->paint; 175b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 176b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (newPaint == oldPaint) { 177b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // if paints are equal, then modifiers + paint attribs don't need to be compared 178b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik return true; 179b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } else if (newPaint && !oldPaint) { 180b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik return paintIsDefault(*newPaint); 181b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } else if (!newPaint && oldPaint) { 182b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik return paintIsDefault(*oldPaint); 183b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 184b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik return paintsAreEquivalent(*newPaint, *oldPaint); 185b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 186b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 187b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik void mergeOp(BakedOpState* op) { 188b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik mBounds.unionWith(op->computedState.clippedBounds); 189b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik mOps.push_back(op); 190b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 191b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik const int newClipSideFlags = op->computedState.clipSideFlags; 192b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik mClipSideFlags |= newClipSideFlags; 193b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 194b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik const Rect& opClip = op->computedState.clipRect; 195b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (newClipSideFlags & OpClipSideFlags::Left) mClipRect.left = opClip.left; 196b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (newClipSideFlags & OpClipSideFlags::Top) mClipRect.top = opClip.top; 197b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (newClipSideFlags & OpClipSideFlags::Right) mClipRect.right = opClip.right; 198b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (newClipSideFlags & OpClipSideFlags::Bottom) mClipRect.bottom = opClip.bottom; 199b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 200b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 201b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikprivate: 202b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik int mClipSideFlags = 0; 203b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik Rect mClipRect; 204b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}; 205b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 2060b7e8245db728d127ada698be63d78b33fc6e4daChris CraikOpReorderer::LayerReorderer::LayerReorderer(uint32_t width, uint32_t height, 2070b7e8245db728d127ada698be63d78b33fc6e4daChris Craik const BeginLayerOp* beginLayerOp, RenderNode* renderNode) 2080b7e8245db728d127ada698be63d78b33fc6e4daChris Craik : width(width) 2090b7e8245db728d127ada698be63d78b33fc6e4daChris Craik , height(height) 2100b7e8245db728d127ada698be63d78b33fc6e4daChris Craik , offscreenBuffer(renderNode ? renderNode->getLayer() : nullptr) 2110b7e8245db728d127ada698be63d78b33fc6e4daChris Craik , beginLayerOp(beginLayerOp) 2120b7e8245db728d127ada698be63d78b33fc6e4daChris Craik , renderNode(renderNode) {} 2130b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 2146fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik// iterate back toward target to see if anything drawn since should overlap the new op 215818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik// if no target, merging ops still iterate to find similar batch to insert after 2166fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craikvoid OpReorderer::LayerReorderer::locateInsertIndex(int batchId, const Rect& clippedBounds, 2176fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik BatchBase** targetBatch, size_t* insertBatchIndex) const { 2186fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik for (int i = mBatches.size() - 1; i >= 0; i--) { 2196fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik BatchBase* overBatch = mBatches[i]; 2206fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 2216fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik if (overBatch == *targetBatch) break; 2226fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 2236fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik // TODO: also consider shader shared between batch types 2246fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik if (batchId == overBatch->getBatchId()) { 2256fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik *insertBatchIndex = i + 1; 2266fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik if (!*targetBatch) break; // found insert position, quit 2276fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } 2286fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 2296fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik if (overBatch->intersects(clippedBounds)) { 2306fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik // NOTE: it may be possible to optimize for special cases where two operations 2316fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik // of the same batch/paint could swap order, such as with a non-mergeable 2326fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik // (clipped) and a mergeable text operation 2336fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik *targetBatch = nullptr; 2346fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik break; 2356fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } 2366fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } 2376fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} 2386fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 2396fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craikvoid OpReorderer::LayerReorderer::deferUnmergeableOp(LinearAllocator& allocator, 2406fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik BakedOpState* op, batchid_t batchId) { 2416fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik OpBatch* targetBatch = mBatchLookup[batchId]; 2426fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 2436fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik size_t insertBatchIndex = mBatches.size(); 2446fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik if (targetBatch) { 2456fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik locateInsertIndex(batchId, op->computedState.clippedBounds, 2466fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik (BatchBase**)(&targetBatch), &insertBatchIndex); 2476fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } 2486fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 2496fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik if (targetBatch) { 2506fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik targetBatch->batchOp(op); 2516fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } else { 2526fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik // new non-merging batch 2536fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik targetBatch = new (allocator) OpBatch(batchId, op); 2546fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik mBatchLookup[batchId] = targetBatch; 2556fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik mBatches.insert(mBatches.begin() + insertBatchIndex, targetBatch); 2566fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } 2576fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} 2586fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 2596fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik// insertion point of a new batch, will hopefully be immediately after similar batch 2606fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik// (generally, should be similar shader) 2616fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craikvoid OpReorderer::LayerReorderer::deferMergeableOp(LinearAllocator& allocator, 2626fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik BakedOpState* op, batchid_t batchId, mergeid_t mergeId) { 2636fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik MergingOpBatch* targetBatch = nullptr; 2646fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 2656fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik // Try to merge with any existing batch with same mergeId 2666fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik auto getResult = mMergingBatchLookup[batchId].find(mergeId); 2676fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik if (getResult != mMergingBatchLookup[batchId].end()) { 2686fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik targetBatch = getResult->second; 2696fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik if (!targetBatch->canMergeWith(op)) { 2706fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik targetBatch = nullptr; 2716fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } 2726fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } 2736fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 2746fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik size_t insertBatchIndex = mBatches.size(); 2756fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik locateInsertIndex(batchId, op->computedState.clippedBounds, 2766fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik (BatchBase**)(&targetBatch), &insertBatchIndex); 2776fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 2786fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik if (targetBatch) { 2796fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik targetBatch->mergeOp(op); 2806fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } else { 2816fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik // new merging batch 2826fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik targetBatch = new (allocator) MergingOpBatch(batchId, op); 2836fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik mMergingBatchLookup[batchId].insert(std::make_pair(mergeId, targetBatch)); 2846fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 2856fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik mBatches.insert(mBatches.begin() + insertBatchIndex, targetBatch); 2866fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } 2876fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} 2886fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 2895854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikvoid OpReorderer::LayerReorderer::replayBakedOpsImpl(void* arg, BakedOpDispatcher* receivers) const { 2905854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik ATRACE_NAME("flush drawing commands"); 2916fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik for (const BatchBase* batch : mBatches) { 2926fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik // TODO: different behavior based on batch->isMerging() 2936fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik for (const BakedOpState* op : batch->getOps()) { 2946fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik receivers[op->op->opId](arg, *op->op, *op); 2956fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } 2966fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } 2976fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} 2986fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 2996fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craikvoid OpReorderer::LayerReorderer::dump() const { 3000b7e8245db728d127ada698be63d78b33fc6e4daChris Craik ALOGD("LayerReorderer %p, %ux%u buffer %p, blo %p, rn %p", 3010b7e8245db728d127ada698be63d78b33fc6e4daChris Craik this, width, height, offscreenBuffer, beginLayerOp, renderNode); 3026fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik for (const BatchBase* batch : mBatches) { 3036fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik batch->dump(); 3046fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } 3056fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} 306b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 3070b7e8245db728d127ada698be63d78b33fc6e4daChris CraikOpReorderer::OpReorderer(const LayerUpdateQueue& layers, const SkRect& clip, 3080b7e8245db728d127ada698be63d78b33fc6e4daChris Craik uint32_t viewportWidth, uint32_t viewportHeight, 309818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik const std::vector< sp<RenderNode> >& nodes) 3106fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik : mCanvasState(*this) { 311818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik ATRACE_NAME("prepare drawing commands"); 312818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik mLayerReorderers.emplace_back(viewportWidth, viewportHeight); 3130b7e8245db728d127ada698be63d78b33fc6e4daChris Craik mLayerStack.push_back(0); 3146fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 315b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik mCanvasState.initializeSaveStack(viewportWidth, viewportHeight, 316ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik clip.fLeft, clip.fTop, clip.fRight, clip.fBottom, 317ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik Vector3()); 3180b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 3190b7e8245db728d127ada698be63d78b33fc6e4daChris Craik // Render all layers to be updated, in order. Defer in reverse order, so that they'll be 3200b7e8245db728d127ada698be63d78b33fc6e4daChris Craik // updated in the order they're passed in (mLayerReorderers are issued to Renderer in reverse) 3210b7e8245db728d127ada698be63d78b33fc6e4daChris Craik for (int i = layers.entries().size() - 1; i >= 0; i--) { 3220b7e8245db728d127ada698be63d78b33fc6e4daChris Craik RenderNode* layerNode = layers.entries()[i].renderNode; 3230b7e8245db728d127ada698be63d78b33fc6e4daChris Craik const Rect& layerDamage = layers.entries()[i].damage; 3240b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 3250b7e8245db728d127ada698be63d78b33fc6e4daChris Craik saveForLayer(layerNode->getWidth(), layerNode->getHeight(), nullptr, layerNode); 3260b7e8245db728d127ada698be63d78b33fc6e4daChris Craik mCanvasState.writableSnapshot()->setClip( 3270b7e8245db728d127ada698be63d78b33fc6e4daChris Craik layerDamage.left, layerDamage.top, layerDamage.right, layerDamage.bottom); 3280b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 3290b7e8245db728d127ada698be63d78b33fc6e4daChris Craik if (layerNode->getDisplayList()) { 3300b7e8245db728d127ada698be63d78b33fc6e4daChris Craik deferImpl(*(layerNode->getDisplayList())); 3310b7e8245db728d127ada698be63d78b33fc6e4daChris Craik } 3320b7e8245db728d127ada698be63d78b33fc6e4daChris Craik restoreForLayer(); 3330b7e8245db728d127ada698be63d78b33fc6e4daChris Craik } 3340b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 3350b7e8245db728d127ada698be63d78b33fc6e4daChris Craik // Defer Fbo0 336b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik for (const sp<RenderNode>& node : nodes) { 337b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (node->nothingToDraw()) continue; 338b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 3390b7e8245db728d127ada698be63d78b33fc6e4daChris Craik int count = mCanvasState.save(SkCanvas::kClip_SaveFlag | SkCanvas::kMatrix_SaveFlag); 3400b7e8245db728d127ada698be63d78b33fc6e4daChris Craik deferNodePropsAndOps(*node); 3410b7e8245db728d127ada698be63d78b33fc6e4daChris Craik mCanvasState.restoreToCount(count); 342b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 343b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 344b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 345818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris CraikOpReorderer::OpReorderer(int viewportWidth, int viewportHeight, const DisplayList& displayList) 346818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik : mCanvasState(*this) { 347b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik ATRACE_NAME("prepare drawing commands"); 348818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik 349818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik mLayerReorderers.emplace_back(viewportWidth, viewportHeight); 350818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik mLayerStack.push_back(0); 351818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik 352b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik mCanvasState.initializeSaveStack(viewportWidth, viewportHeight, 353b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 0, 0, viewportWidth, viewportHeight, Vector3()); 354b36af87f8275f4b982906f88193ec27600f2746aChris Craik deferImpl(displayList); 355b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 356b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 357818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craikvoid OpReorderer::onViewportInitialized() {} 358818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik 359818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craikvoid OpReorderer::onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) {} 360818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik 3610b7e8245db728d127ada698be63d78b33fc6e4daChris Craikvoid OpReorderer::deferNodePropsAndOps(RenderNode& node) { 3620b7e8245db728d127ada698be63d78b33fc6e4daChris Craik if (node.applyViewProperties(mCanvasState)) { 3630b7e8245db728d127ada698be63d78b33fc6e4daChris Craik // not rejected so render 3640b7e8245db728d127ada698be63d78b33fc6e4daChris Craik if (node.getLayer()) { 3650b7e8245db728d127ada698be63d78b33fc6e4daChris Craik // HW layer 3660b7e8245db728d127ada698be63d78b33fc6e4daChris Craik LayerOp* drawLayerOp = new (mAllocator) LayerOp(node); 3670b7e8245db728d127ada698be63d78b33fc6e4daChris Craik BakedOpState* bakedOpState = tryBakeOpState(*drawLayerOp); 3680b7e8245db728d127ada698be63d78b33fc6e4daChris Craik if (bakedOpState) { 3690b7e8245db728d127ada698be63d78b33fc6e4daChris Craik // Layer will be drawn into parent layer (which is now current, since we popped mLayerStack) 3700b7e8245db728d127ada698be63d78b33fc6e4daChris Craik currentLayer().deferUnmergeableOp(mAllocator, bakedOpState, OpBatchType::Bitmap); 3710b7e8245db728d127ada698be63d78b33fc6e4daChris Craik } 3720b7e8245db728d127ada698be63d78b33fc6e4daChris Craik } else { 3730b7e8245db728d127ada698be63d78b33fc6e4daChris Craik deferImpl(*(node.getDisplayList())); 3740b7e8245db728d127ada698be63d78b33fc6e4daChris Craik } 3750b7e8245db728d127ada698be63d78b33fc6e4daChris Craik } 3760b7e8245db728d127ada698be63d78b33fc6e4daChris Craik} 3770b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 378b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik/** 379b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * Used to define a list of lambdas referencing private OpReorderer::onXXXXOp() methods. 380b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * 381b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * This allows opIds embedded in the RecordedOps to be used for dispatching to these lambdas. E.g. a 382b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * BitmapOp op then would be dispatched to OpReorderer::onBitmapOp(const BitmapOp&) 383b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik */ 3846fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik#define OP_RECEIVER(Type) \ 385b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik [](OpReorderer& reorderer, const RecordedOp& op) { reorderer.on##Type(static_cast<const Type&>(op)); }, 386b36af87f8275f4b982906f88193ec27600f2746aChris Craikvoid OpReorderer::deferImpl(const DisplayList& displayList) { 387b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik static std::function<void(OpReorderer& reorderer, const RecordedOp&)> receivers[] = { 3886fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik MAP_OPS(OP_RECEIVER) 389b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik }; 390b36af87f8275f4b982906f88193ec27600f2746aChris Craik for (const DisplayList::Chunk& chunk : displayList.getChunks()) { 391b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik for (size_t opIndex = chunk.beginOpIndex; opIndex < chunk.endOpIndex; opIndex++) { 392b36af87f8275f4b982906f88193ec27600f2746aChris Craik const RecordedOp* op = displayList.getOps()[opIndex]; 393b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik receivers[op->opId](*this, *op); 394b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 395b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 396b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 397b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 398b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid OpReorderer::onRenderNodeOp(const RenderNodeOp& op) { 399b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (op.renderNode->nothingToDraw()) { 400b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik return; 401b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 4026fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik int count = mCanvasState.save(SkCanvas::kClip_SaveFlag | SkCanvas::kMatrix_SaveFlag); 403b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 404b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // apply state from RecordedOp 405b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik mCanvasState.concatMatrix(op.localMatrix); 406b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik mCanvasState.clipRect(op.localClipRect.left, op.localClipRect.top, 407b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik op.localClipRect.right, op.localClipRect.bottom, SkRegion::kIntersect_Op); 408b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 4090b7e8245db728d127ada698be63d78b33fc6e4daChris Craik // then apply state from node properties, and defer ops 4100b7e8245db728d127ada698be63d78b33fc6e4daChris Craik deferNodePropsAndOps(*op.renderNode); 4110b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 4126fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik mCanvasState.restoreToCount(count); 413b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 414b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 415b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikstatic batchid_t tessellatedBatchId(const SkPaint& paint) { 416b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik return paint.getPathEffect() 417b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik ? OpBatchType::AlphaMaskTexture 418b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik : (paint.isAntiAlias() ? OpBatchType::AlphaVertices : OpBatchType::Vertices); 419b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 420b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 421b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid OpReorderer::onBitmapOp(const BitmapOp& op) { 4226fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik BakedOpState* bakedStateOp = tryBakeOpState(op); 423b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (!bakedStateOp) return; // quick rejected 424b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 425b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik mergeid_t mergeId = (mergeid_t) op.bitmap->getGenerationID(); 426b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // TODO: AssetAtlas 4276fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik currentLayer().deferMergeableOp(mAllocator, bakedStateOp, OpBatchType::Bitmap, mergeId); 428b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 429b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 430b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid OpReorderer::onRectOp(const RectOp& op) { 4316fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik BakedOpState* bakedStateOp = tryBakeOpState(op); 432b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (!bakedStateOp) return; // quick rejected 4336fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik currentLayer().deferUnmergeableOp(mAllocator, bakedStateOp, tessellatedBatchId(*op.paint)); 434b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 435b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 436b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid OpReorderer::onSimpleRectsOp(const SimpleRectsOp& op) { 4376fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik BakedOpState* bakedStateOp = tryBakeOpState(op); 438b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (!bakedStateOp) return; // quick rejected 4396fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik currentLayer().deferUnmergeableOp(mAllocator, bakedStateOp, OpBatchType::Vertices); 440b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 441b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 4420b7e8245db728d127ada698be63d78b33fc6e4daChris Craikvoid OpReorderer::saveForLayer(uint32_t layerWidth, uint32_t layerHeight, 4430b7e8245db728d127ada698be63d78b33fc6e4daChris Craik const BeginLayerOp* beginLayerOp, RenderNode* renderNode) { 444818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik 4456fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik mCanvasState.save(SkCanvas::kClip_SaveFlag | SkCanvas::kMatrix_SaveFlag); 4466fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik mCanvasState.writableSnapshot()->transform->loadIdentity(); 447818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik mCanvasState.writableSnapshot()->initializeViewport(layerWidth, layerHeight); 4486fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik mCanvasState.writableSnapshot()->roundRectClipState = nullptr; 4496fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 4506fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik // create a new layer, and push its index on the stack 4516fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik mLayerStack.push_back(mLayerReorderers.size()); 4520b7e8245db728d127ada698be63d78b33fc6e4daChris Craik mLayerReorderers.emplace_back(layerWidth, layerHeight, beginLayerOp, renderNode); 453b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 454b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 4550b7e8245db728d127ada698be63d78b33fc6e4daChris Craikvoid OpReorderer::restoreForLayer() { 4560b7e8245db728d127ada698be63d78b33fc6e4daChris Craik // restore canvas, and pop finished layer off of the stack 4576fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik mCanvasState.restore(); 4580b7e8245db728d127ada698be63d78b33fc6e4daChris Craik mLayerStack.pop_back(); 4590b7e8245db728d127ada698be63d78b33fc6e4daChris Craik} 460b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 4610b7e8245db728d127ada698be63d78b33fc6e4daChris Craik// TODO: test rejection at defer time, where the bounds become empty 4620b7e8245db728d127ada698be63d78b33fc6e4daChris Craikvoid OpReorderer::onBeginLayerOp(const BeginLayerOp& op) { 4630b7e8245db728d127ada698be63d78b33fc6e4daChris Craik const uint32_t layerWidth = (uint32_t) op.unmappedBounds.getWidth(); 4640b7e8245db728d127ada698be63d78b33fc6e4daChris Craik const uint32_t layerHeight = (uint32_t) op.unmappedBounds.getHeight(); 4650b7e8245db728d127ada698be63d78b33fc6e4daChris Craik saveForLayer(layerWidth, layerHeight, &op, nullptr); 4660b7e8245db728d127ada698be63d78b33fc6e4daChris Craik} 4676fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 4680b7e8245db728d127ada698be63d78b33fc6e4daChris Craikvoid OpReorderer::onEndLayerOp(const EndLayerOp& /* ignored */) { 4690b7e8245db728d127ada698be63d78b33fc6e4daChris Craik const BeginLayerOp& beginLayerOp = *currentLayer().beginLayerOp; 4706fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik int finishedLayerIndex = mLayerStack.back(); 4710b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 4720b7e8245db728d127ada698be63d78b33fc6e4daChris Craik restoreForLayer(); 4736fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 4746fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik // record the draw operation into the previous layer's list of draw commands 4756fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik // uses state from the associated beginLayerOp, since it has all the state needed for drawing 4766fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik LayerOp* drawLayerOp = new (mAllocator) LayerOp( 4776fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik beginLayerOp.unmappedBounds, 4786fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik beginLayerOp.localMatrix, 4796fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik beginLayerOp.localClipRect, 480818c9fbf1d76d5df19253ba4eb964efa939ec9ecChris Craik beginLayerOp.paint, 4815854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik &mLayerReorderers[finishedLayerIndex].offscreenBuffer); 4826fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik BakedOpState* bakedOpState = tryBakeOpState(*drawLayerOp); 4836fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 4846fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik if (bakedOpState) { 4856fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik // Layer will be drawn into parent layer (which is now current, since we popped mLayerStack) 4866fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik currentLayer().deferUnmergeableOp(mAllocator, bakedOpState, OpBatchType::Bitmap); 4876fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } else { 4886fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik // Layer won't be drawn - delete its drawing batches to prevent it from doing any work 4896fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik mLayerReorderers[finishedLayerIndex].clear(); 4906fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik return; 491b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 492b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 493b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 4946fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craikvoid OpReorderer::onLayerOp(const LayerOp& op) { 4956fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik LOG_ALWAYS_FATAL("unsupported"); 496b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 497b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 498b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} // namespace uirenderer 499b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} // namespace android 500