blob: 4e3cb8a15e2419ad20ff844639e6282f3e242f6d [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_BAKED_OP_STATE_H
18#define ANDROID_HWUI_BAKED_OP_STATE_H
19
20#include "Matrix.h"
21#include "RecordedOp.h"
22#include "Rect.h"
23#include "Snapshot.h"
24
25namespace android {
26namespace uirenderer {
27
28namespace OpClipSideFlags {
29 enum {
30 None = 0x0,
31 Left = 0x1,
32 Top = 0x2,
33 Right = 0x4,
34 Bottom = 0x8,
35 Full = 0xF,
36 // ConservativeFull = 0x1F needed?
37 };
38}
39
40/**
Chris Craik15c3f192015-12-03 12:16:56 -080041 * Holds a list of BakedOpStates of ops that can be drawn together
42 */
43struct MergedBakedOpList {
44 const BakedOpState*const* states;
45 size_t count;
46 int clipSideFlags;
47 Rect clip;
48};
49
50/**
Chris Craikb565df12015-10-05 13:00:52 -070051 * Holds the resolved clip, transform, and bounds of a recordedOp, when replayed with a snapshot
52 */
53class ResolvedRenderState {
54public:
Chris Craike4db79d2015-12-22 16:32:23 -080055 ResolvedRenderState(LinearAllocator& allocator, Snapshot& snapshot,
56 const RecordedOp& recordedOp, bool expandForStroke);
Chris Craikb565df12015-10-05 13:00:52 -070057
Chris Craik4c3980b2016-03-15 14:20:18 -070058 // Constructor for unbounded ops *with* transform/clip
59 ResolvedRenderState(LinearAllocator& allocator, Snapshot& snapshot,
60 const Matrix4& localTransform, const ClipBase* localClip);
61
Chris Craike4db79d2015-12-22 16:32:23 -080062 // Constructor for unbounded ops without transform/clip (namely shadows)
63 ResolvedRenderState(LinearAllocator& allocator, Snapshot& snapshot);
Chris Craikd3daa312015-11-06 10:59:56 -080064
Chris Craik7435eb12016-01-07 17:41:40 -080065 // Constructor for primitive ops provided clip, and no transform
66 ResolvedRenderState(const ClipRect* viewportRect, const Rect& dstRect);
Chris Craikb87eadd2016-01-06 09:16:05 -080067
Chris Craikd7448e62015-12-15 10:34:36 -080068 Rect computeLocalSpaceClip() const {
69 Matrix4 inverse;
70 inverse.loadInverse(transform);
71
Chris Craike4db79d2015-12-22 16:32:23 -080072 Rect outClip(clipRect());
Chris Craikd7448e62015-12-15 10:34:36 -080073 inverse.mapRect(outClip);
74 return outClip;
75 }
76
Chris Craike4db79d2015-12-22 16:32:23 -080077 const Rect& clipRect() const {
78 return clipState->rect;
79 }
Chris Craikb87eadd2016-01-06 09:16:05 -080080
Chris Craike4db79d2015-12-22 16:32:23 -080081 bool requiresClip() const {
82 return clipSideFlags != OpClipSideFlags::None
Chris Craik7435eb12016-01-07 17:41:40 -080083 || CC_UNLIKELY(clipState->mode != ClipMode::Rectangle);
Chris Craike4db79d2015-12-22 16:32:23 -080084 }
85
86 // returns the clip if it's needed to draw the operation, otherwise nullptr
87 const ClipBase* getClipIfNeeded() const {
88 return requiresClip() ? clipState : nullptr;
89 }
Chris Craikb87eadd2016-01-06 09:16:05 -080090
91 Matrix4 transform;
Chris Craike4db79d2015-12-22 16:32:23 -080092 const ClipBase* clipState = nullptr;
Chris Craikb565df12015-10-05 13:00:52 -070093 Rect clippedBounds;
Chris Craikb87eadd2016-01-06 09:16:05 -080094 int clipSideFlags = 0;
Chris Craik678ff812016-03-01 13:27:54 -080095 const SkPath* localProjectionPathMask = nullptr;
Chris Craikb565df12015-10-05 13:00:52 -070096};
97
98/**
99 * Self-contained op wrapper, containing all resolved state required to draw the op.
100 *
101 * Stashed pointers within all point to longer lived objects, with no ownership implied.
102 */
103class BakedOpState {
104public:
105 static BakedOpState* tryConstruct(LinearAllocator& allocator,
Chris Craike4db79d2015-12-22 16:32:23 -0800106 Snapshot& snapshot, const RecordedOp& recordedOp) {
Chris Craik15f04682016-01-11 17:50:08 -0800107 if (CC_UNLIKELY(snapshot.getRenderTargetClip().isEmpty())) return nullptr;
John Reck7df9ff22016-02-10 16:08:08 -0800108 BakedOpState* bakedState = allocator.create_trivial<BakedOpState>(
Chris Craike4db79d2015-12-22 16:32:23 -0800109 allocator, snapshot, recordedOp, false);
Chris Craik386aa032015-12-07 17:08:25 -0800110 if (bakedState->computedState.clippedBounds.isEmpty()) {
Chris Craikb565df12015-10-05 13:00:52 -0700111 // bounds are empty, so op is rejected
Chris Craik386aa032015-12-07 17:08:25 -0800112 allocator.rewindIfLastAlloc(bakedState);
Chris Craikb565df12015-10-05 13:00:52 -0700113 return nullptr;
114 }
Chris Craik386aa032015-12-07 17:08:25 -0800115 return bakedState;
116 }
117
Chris Craik4c3980b2016-03-15 14:20:18 -0700118 static BakedOpState* tryConstructUnbounded(LinearAllocator& allocator,
119 Snapshot& snapshot, const RecordedOp& recordedOp) {
120 if (CC_UNLIKELY(snapshot.getRenderTargetClip().isEmpty())) return nullptr;
121 return allocator.create_trivial<BakedOpState>(allocator, snapshot, recordedOp);
122 }
123
Chris Craik386aa032015-12-07 17:08:25 -0800124 enum class StrokeBehavior {
Chris Craik4c3980b2016-03-15 14:20:18 -0700125 // stroking is forced, regardless of style on paint (such as for lines)
Chris Craik386aa032015-12-07 17:08:25 -0800126 Forced,
127 // stroking is defined by style on paint
128 StyleDefined,
129 };
130
131 static BakedOpState* tryStrokeableOpConstruct(LinearAllocator& allocator,
Chris Craike4db79d2015-12-22 16:32:23 -0800132 Snapshot& snapshot, const RecordedOp& recordedOp, StrokeBehavior strokeBehavior) {
Chris Craik15f04682016-01-11 17:50:08 -0800133 if (CC_UNLIKELY(snapshot.getRenderTargetClip().isEmpty())) return nullptr;
Chris Craik386aa032015-12-07 17:08:25 -0800134 bool expandForStroke = (strokeBehavior == StrokeBehavior::StyleDefined)
135 ? (recordedOp.paint && recordedOp.paint->getStyle() != SkPaint::kFill_Style)
136 : true;
137
John Reck7df9ff22016-02-10 16:08:08 -0800138 BakedOpState* bakedState = allocator.create_trivial<BakedOpState>(
Chris Craike4db79d2015-12-22 16:32:23 -0800139 allocator, snapshot, recordedOp, expandForStroke);
Chris Craik386aa032015-12-07 17:08:25 -0800140 if (bakedState->computedState.clippedBounds.isEmpty()) {
141 // bounds are empty, so op is rejected
Chris Craik15f04682016-01-11 17:50:08 -0800142 // NOTE: this won't succeed if a clip was allocated
Chris Craik386aa032015-12-07 17:08:25 -0800143 allocator.rewindIfLastAlloc(bakedState);
144 return nullptr;
145 }
146 return bakedState;
Chris Craikb565df12015-10-05 13:00:52 -0700147 }
148
Chris Craikd3daa312015-11-06 10:59:56 -0800149 static BakedOpState* tryShadowOpConstruct(LinearAllocator& allocator,
Chris Craike4db79d2015-12-22 16:32:23 -0800150 Snapshot& snapshot, const ShadowOp* shadowOpPtr) {
Chris Craik15f04682016-01-11 17:50:08 -0800151 if (CC_UNLIKELY(snapshot.getRenderTargetClip().isEmpty())) return nullptr;
Chris Craikd3daa312015-11-06 10:59:56 -0800152
153 // clip isn't empty, so construct the op
John Reck7df9ff22016-02-10 16:08:08 -0800154 return allocator.create_trivial<BakedOpState>(allocator, snapshot, shadowOpPtr);
Chris Craikd3daa312015-11-06 10:59:56 -0800155 }
156
Chris Craikb87eadd2016-01-06 09:16:05 -0800157 static BakedOpState* directConstruct(LinearAllocator& allocator,
Chris Craik7435eb12016-01-07 17:41:40 -0800158 const ClipRect* clip, const Rect& dstRect, const RecordedOp& recordedOp) {
John Reck7df9ff22016-02-10 16:08:08 -0800159 return allocator.create_trivial<BakedOpState>(clip, dstRect, recordedOp);
Chris Craikb565df12015-10-05 13:00:52 -0700160 }
161
162 // computed state:
Chris Craikb87eadd2016-01-06 09:16:05 -0800163 ResolvedRenderState computedState;
Chris Craikb565df12015-10-05 13:00:52 -0700164
165 // simple state (straight pointer/value storage):
166 const float alpha;
167 const RoundRectClipState* roundRectClipState;
Chris Craikb565df12015-10-05 13:00:52 -0700168 const RecordedOp* op;
169
170private:
John Reck7df9ff22016-02-10 16:08:08 -0800171 friend class LinearAllocator;
172
Chris Craike4db79d2015-12-22 16:32:23 -0800173 BakedOpState(LinearAllocator& allocator, Snapshot& snapshot,
174 const RecordedOp& recordedOp, bool expandForStroke)
175 : computedState(allocator, snapshot, recordedOp, expandForStroke)
Chris Craikb565df12015-10-05 13:00:52 -0700176 , alpha(snapshot.alpha)
177 , roundRectClipState(snapshot.roundRectClipState)
Chris Craikb565df12015-10-05 13:00:52 -0700178 , op(&recordedOp) {}
Chris Craikd3daa312015-11-06 10:59:56 -0800179
Chris Craik4c3980b2016-03-15 14:20:18 -0700180 // TODO: fix this brittleness
181 BakedOpState(LinearAllocator& allocator, Snapshot& snapshot, const RecordedOp& recordedOp)
182 : computedState(allocator, snapshot, recordedOp.localMatrix, recordedOp.localClip)
183 , alpha(snapshot.alpha)
184 , roundRectClipState(snapshot.roundRectClipState)
185 , op(&recordedOp) {}
186
Chris Craike4db79d2015-12-22 16:32:23 -0800187 BakedOpState(LinearAllocator& allocator, Snapshot& snapshot, const ShadowOp* shadowOpPtr)
188 : computedState(allocator, snapshot)
Chris Craikd3daa312015-11-06 10:59:56 -0800189 , alpha(snapshot.alpha)
190 , roundRectClipState(snapshot.roundRectClipState)
Chris Craikd3daa312015-11-06 10:59:56 -0800191 , op(shadowOpPtr) {}
Chris Craikb87eadd2016-01-06 09:16:05 -0800192
Chris Craik4876de12016-02-25 16:54:08 -0800193 BakedOpState(const ClipRect* clipRect, const Rect& dstRect, const RecordedOp& recordedOp)
194 : computedState(clipRect, dstRect)
Chris Craikb87eadd2016-01-06 09:16:05 -0800195 , alpha(1.0f)
196 , roundRectClipState(nullptr)
Chris Craikb87eadd2016-01-06 09:16:05 -0800197 , op(&recordedOp) {}
Chris Craikb565df12015-10-05 13:00:52 -0700198};
199
200}; // namespace uirenderer
201}; // namespace android
202
203#endif // ANDROID_HWUI_BAKED_OP_STATE_H