blob: f32b8589983b073481447d114e50310f9312087f [file] [log] [blame]
Chris Craikb565df12015-10-05 13:00:52 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ANDROID_HWUI_OP_REORDERER_H
18#define ANDROID_HWUI_OP_REORDERER_H
19
20#include "BakedOpState.h"
21#include "CanvasState.h"
22#include "DisplayList.h"
23#include "RecordedOp.h"
24
25#include <vector>
26#include <unordered_map>
27
Chris Craikddf22152015-10-14 17:42:47 -070028struct SkRect;
29
Chris Craikb565df12015-10-05 13:00:52 -070030namespace android {
31namespace uirenderer {
32
33class BakedOpState;
34class BatchBase;
35class MergingOpBatch;
36class OpBatch;
37class Rect;
38
39typedef int batchid_t;
40typedef const void* mergeid_t;
41
42namespace OpBatchType {
43 enum {
44 None = 0, // Don't batch
45 Bitmap,
46 Patch,
47 AlphaVertices,
48 Vertices,
49 AlphaMaskTexture,
50 Text,
51 ColorText,
52
53 Count // must be last
54 };
55}
56
Chris Craik6fe991e52015-10-20 09:39:42 -070057class OpReorderer : public CanvasStateClient {
58 typedef std::function<void(void*, const RecordedOp&, const BakedOpState&)> BakedOpReceiver;
59
60 /**
61 * Stores the deferred render operations and state used to compute ordering
62 * for a single FBO/layer.
63 */
64 class LayerReorderer {
65 public:
Chris Craik818c9fb2015-10-23 14:33:42 -070066 LayerReorderer(uint32_t width, uint32_t height)
67 : width(width)
68 , height(height) {}
69
Chris Craik6fe991e52015-10-20 09:39:42 -070070 // iterate back toward target to see if anything drawn since should overlap the new op
71 // if no target, merging ops still iterate to find similar batch to insert after
72 void locateInsertIndex(int batchId, const Rect& clippedBounds,
73 BatchBase** targetBatch, size_t* insertBatchIndex) const;
74
75 void deferUnmergeableOp(LinearAllocator& allocator, BakedOpState* op, batchid_t batchId);
76
77 // insertion point of a new batch, will hopefully be immediately after similar batch
78 // (generally, should be similar shader)
79 void deferMergeableOp(LinearAllocator& allocator,
80 BakedOpState* op, batchid_t batchId, mergeid_t mergeId);
81
82 void replayBakedOpsImpl(void* arg, BakedOpReceiver* receivers) const;
83
Chris Craik818c9fb2015-10-23 14:33:42 -070084 bool empty() const {
85 return mBatches.empty();
86 }
87
Chris Craik6fe991e52015-10-20 09:39:42 -070088 void clear() {
89 mBatches.clear();
90 }
91
92 void dump() const;
93
Chris Craik818c9fb2015-10-23 14:33:42 -070094 Layer* layer = nullptr;
Chris Craik6fe991e52015-10-20 09:39:42 -070095 const BeginLayerOp* beginLayerOp = nullptr;
Chris Craik818c9fb2015-10-23 14:33:42 -070096 const uint32_t width;
97 const uint32_t height;
Chris Craik6fe991e52015-10-20 09:39:42 -070098 private:
Chris Craik818c9fb2015-10-23 14:33:42 -070099
Chris Craik6fe991e52015-10-20 09:39:42 -0700100 std::vector<BatchBase*> mBatches;
101
102 /**
103 * Maps the mergeid_t returned by an op's getMergeId() to the most recently seen
104 * MergingDrawBatch of that id. These ids are unique per draw type and guaranteed to not
105 * collide, which avoids the need to resolve mergeid collisions.
106 */
107 std::unordered_map<mergeid_t, MergingOpBatch*> mMergingBatchLookup[OpBatchType::Count];
108
109 // Maps batch ids to the most recent *non-merging* batch of that id
110 OpBatch* mBatchLookup[OpBatchType::Count] = { nullptr };
111
112 };
Chris Craikb565df12015-10-05 13:00:52 -0700113public:
Chris Craikb565df12015-10-05 13:00:52 -0700114 // TODO: not final, just presented this way for simplicity. Layers too?
Chris Craik818c9fb2015-10-23 14:33:42 -0700115 OpReorderer(const SkRect& clip, uint32_t viewportWidth, uint32_t viewportHeight,
Chris Craikddf22152015-10-14 17:42:47 -0700116 const std::vector< sp<RenderNode> >& nodes);
Chris Craikb565df12015-10-05 13:00:52 -0700117
Chris Craik818c9fb2015-10-23 14:33:42 -0700118 OpReorderer(int viewportWidth, int viewportHeight, const DisplayList& displayList);
119
120 virtual ~OpReorderer() {}
Chris Craikb565df12015-10-05 13:00:52 -0700121
122 /**
Chris Craik6fe991e52015-10-20 09:39:42 -0700123 * replayBakedOps() is templated based on what class will receive ops being replayed.
Chris Craikb565df12015-10-05 13:00:52 -0700124 *
125 * It constructs a lookup array of lambdas, which allows a recorded BakeOpState to use
126 * state->op->opId to lookup a receiver that will be called when the op is replayed.
127 *
128 * For example a BitmapOp would resolve, via the lambda lookup, to calling:
129 *
130 * StaticReceiver::onBitmapOp(Arg* arg, const BitmapOp& op, const BakedOpState& state);
131 */
132#define BAKED_OP_RECEIVER(Type) \
133 [](void* internalArg, const RecordedOp& op, const BakedOpState& state) { \
Chris Craik6fe991e52015-10-20 09:39:42 -0700134 StaticReceiver::on##Type(*(static_cast<Arg*>(internalArg)), static_cast<const Type&>(op), state); \
Chris Craikb565df12015-10-05 13:00:52 -0700135 },
136 template <typename StaticReceiver, typename Arg>
Chris Craik6fe991e52015-10-20 09:39:42 -0700137 void replayBakedOps(Arg& arg) {
Chris Craikb565df12015-10-05 13:00:52 -0700138 static BakedOpReceiver receivers[] = {
139 MAP_OPS(BAKED_OP_RECEIVER)
140 };
Chris Craik818c9fb2015-10-23 14:33:42 -0700141
142 // Relay through layers in reverse order, since layers
143 // later in the list will be drawn by earlier ones
144 for (int i = mLayerReorderers.size() - 1; i >= 1; i--) {
145 LayerReorderer& layer = mLayerReorderers[i];
146 if (!layer.empty()) {
147 layer.layer = StaticReceiver::startLayer(arg, layer.width, layer.height);
148 layer.replayBakedOpsImpl((void*)&arg, receivers);
149 StaticReceiver::endLayer(arg);
150 }
151 }
152
153 const LayerReorderer& fbo0 = mLayerReorderers[0];
154 StaticReceiver::startFrame(arg, fbo0.width, fbo0.height);
155 fbo0.replayBakedOpsImpl((void*)&arg, receivers);
Chris Craik6fe991e52015-10-20 09:39:42 -0700156 StaticReceiver::endFrame(arg);
Chris Craikb565df12015-10-05 13:00:52 -0700157 }
Chris Craik6fe991e52015-10-20 09:39:42 -0700158
159 void dump() const {
160 for (auto&& layer : mLayerReorderers) {
161 layer.dump();
162 }
163 }
164
165 ///////////////////////////////////////////////////////////////////
166 /// CanvasStateClient interface
167 ///////////////////////////////////////////////////////////////////
168 virtual void onViewportInitialized() override;
169 virtual void onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) override;
170 virtual GLuint getTargetFbo() const override { return 0; }
171
Chris Craikb565df12015-10-05 13:00:52 -0700172private:
Chris Craik6fe991e52015-10-20 09:39:42 -0700173 LayerReorderer& currentLayer() { return mLayerReorderers[mLayerStack.back()]; }
174
175 BakedOpState* tryBakeOpState(const RecordedOp& recordedOp) {
176 return BakedOpState::tryConstruct(mAllocator, *mCanvasState.currentSnapshot(), recordedOp);
177 }
Chris Craikb565df12015-10-05 13:00:52 -0700178
Chris Craikb36af872015-10-16 14:23:12 -0700179 void deferImpl(const DisplayList& displayList);
Chris Craikb565df12015-10-05 13:00:52 -0700180
181 void replayBakedOpsImpl(void* arg, BakedOpReceiver* receivers);
182
183 /**
184 * Declares all OpReorderer::onXXXXOp() methods for every RecordedOp type.
185 *
186 * These private methods are called from within deferImpl to defer each individual op
187 * type differently.
188 */
189#define INTERNAL_OP_HANDLER(Type) \
190 void on##Type(const Type& op);
191 MAP_OPS(INTERNAL_OP_HANDLER)
192
Chris Craik6fe991e52015-10-20 09:39:42 -0700193 // List of every deferred layer's render state. Replayed in reverse order to render a frame.
194 std::vector<LayerReorderer> mLayerReorderers;
Chris Craikb565df12015-10-05 13:00:52 -0700195
Chris Craik6fe991e52015-10-20 09:39:42 -0700196 /*
197 * Stack of indices within mLayerReorderers representing currently active layers. If drawing
198 * layerA within a layerB, will contain, in order:
199 * - 0 (representing FBO 0, always present)
200 * - layerB's index
201 * - layerA's index
202 *
203 * Note that this doesn't vector doesn't always map onto all values of mLayerReorderers. When a
204 * layer is finished deferring, it will still be represented in mLayerReorderers, but it's index
205 * won't be in mLayerStack. This is because it can be replayed, but can't have any more drawing
206 * ops added to it.
207 */
208 std::vector<size_t> mLayerStack;
Chris Craikb565df12015-10-05 13:00:52 -0700209
Chris Craikb565df12015-10-05 13:00:52 -0700210 CanvasState mCanvasState;
211
212 // contains ResolvedOps and Batches
213 LinearAllocator mAllocator;
Chris Craikb565df12015-10-05 13:00:52 -0700214};
215
216}; // namespace uirenderer
217}; // namespace android
218
219#endif // ANDROID_HWUI_OP_REORDERER_H