blob: 70b0484d36956e678a18faa1d212e1f48d162b34 [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 Craike4db79d2015-12-22 16:32:23 -080058 // Constructor for unbounded ops without transform/clip (namely shadows)
59 ResolvedRenderState(LinearAllocator& allocator, Snapshot& snapshot);
Chris Craikd3daa312015-11-06 10:59:56 -080060
Chris Craikb87eadd2016-01-06 09:16:05 -080061 // Constructor for primitive ops without clip or transform
62 // NOTE: these ops can't be queried for RT clip / local clip
63 ResolvedRenderState(const Rect& dstRect);
64
Chris Craikd7448e62015-12-15 10:34:36 -080065 Rect computeLocalSpaceClip() const {
66 Matrix4 inverse;
67 inverse.loadInverse(transform);
68
Chris Craike4db79d2015-12-22 16:32:23 -080069 Rect outClip(clipRect());
Chris Craikd7448e62015-12-15 10:34:36 -080070 inverse.mapRect(outClip);
71 return outClip;
72 }
73
Chris Craikb87eadd2016-01-06 09:16:05 -080074 // NOTE: Can only be used on clipped/snapshot based ops
Chris Craike4db79d2015-12-22 16:32:23 -080075 const Rect& clipRect() const {
76 return clipState->rect;
77 }
Chris Craikb87eadd2016-01-06 09:16:05 -080078
79 // NOTE: Can only be used on clipped/snapshot based ops
Chris Craike4db79d2015-12-22 16:32:23 -080080 bool requiresClip() const {
81 return clipSideFlags != OpClipSideFlags::None
82 || CC_UNLIKELY(clipState->mode != ClipMode::Rectangle);
83 }
84
85 // returns the clip if it's needed to draw the operation, otherwise nullptr
86 const ClipBase* getClipIfNeeded() const {
87 return requiresClip() ? clipState : nullptr;
88 }
Chris Craikb87eadd2016-01-06 09:16:05 -080089
90 Matrix4 transform;
Chris Craike4db79d2015-12-22 16:32:23 -080091 const ClipBase* clipState = nullptr;
Chris Craikb565df12015-10-05 13:00:52 -070092 Rect clippedBounds;
Chris Craikb87eadd2016-01-06 09:16:05 -080093 int clipSideFlags = 0;
Chris Craikb565df12015-10-05 13:00:52 -070094};
95
96/**
97 * Self-contained op wrapper, containing all resolved state required to draw the op.
98 *
99 * Stashed pointers within all point to longer lived objects, with no ownership implied.
100 */
101class BakedOpState {
102public:
103 static BakedOpState* tryConstruct(LinearAllocator& allocator,
Chris Craike4db79d2015-12-22 16:32:23 -0800104 Snapshot& snapshot, const RecordedOp& recordedOp) {
105 BakedOpState* bakedState = new (allocator) BakedOpState(
106 allocator, snapshot, recordedOp, false);
Chris Craik386aa032015-12-07 17:08:25 -0800107 if (bakedState->computedState.clippedBounds.isEmpty()) {
Chris Craikb565df12015-10-05 13:00:52 -0700108 // bounds are empty, so op is rejected
Chris Craik386aa032015-12-07 17:08:25 -0800109 allocator.rewindIfLastAlloc(bakedState);
Chris Craikb565df12015-10-05 13:00:52 -0700110 return nullptr;
111 }
Chris Craik386aa032015-12-07 17:08:25 -0800112 return bakedState;
113 }
114
115 enum class StrokeBehavior {
116 // stroking is forced, regardless of style on paint
117 Forced,
118 // stroking is defined by style on paint
119 StyleDefined,
120 };
121
122 static BakedOpState* tryStrokeableOpConstruct(LinearAllocator& allocator,
Chris Craike4db79d2015-12-22 16:32:23 -0800123 Snapshot& snapshot, const RecordedOp& recordedOp, StrokeBehavior strokeBehavior) {
Chris Craik386aa032015-12-07 17:08:25 -0800124 bool expandForStroke = (strokeBehavior == StrokeBehavior::StyleDefined)
125 ? (recordedOp.paint && recordedOp.paint->getStyle() != SkPaint::kFill_Style)
126 : true;
127
128 BakedOpState* bakedState = new (allocator) BakedOpState(
Chris Craike4db79d2015-12-22 16:32:23 -0800129 allocator, snapshot, recordedOp, expandForStroke);
Chris Craik386aa032015-12-07 17:08:25 -0800130 if (bakedState->computedState.clippedBounds.isEmpty()) {
131 // bounds are empty, so op is rejected
132 allocator.rewindIfLastAlloc(bakedState);
133 return nullptr;
134 }
135 return bakedState;
Chris Craikb565df12015-10-05 13:00:52 -0700136 }
137
Chris Craikd3daa312015-11-06 10:59:56 -0800138 static BakedOpState* tryShadowOpConstruct(LinearAllocator& allocator,
Chris Craike4db79d2015-12-22 16:32:23 -0800139 Snapshot& snapshot, const ShadowOp* shadowOpPtr) {
Chris Craikd3daa312015-11-06 10:59:56 -0800140 if (snapshot.getRenderTargetClip().isEmpty()) return nullptr;
141
142 // clip isn't empty, so construct the op
Chris Craike4db79d2015-12-22 16:32:23 -0800143 return new (allocator) BakedOpState(allocator, snapshot, shadowOpPtr);
Chris Craikd3daa312015-11-06 10:59:56 -0800144 }
145
Chris Craikb87eadd2016-01-06 09:16:05 -0800146 static BakedOpState* directConstruct(LinearAllocator& allocator,
147 const Rect& dstRect, const RecordedOp& recordedOp) {
148 return new (allocator) BakedOpState(dstRect, recordedOp);
149 }
150
Chris Craikb565df12015-10-05 13:00:52 -0700151 static void* operator new(size_t size, LinearAllocator& allocator) {
152 return allocator.alloc(size);
153 }
154
155 // computed state:
Chris Craikb87eadd2016-01-06 09:16:05 -0800156 ResolvedRenderState computedState;
Chris Craikb565df12015-10-05 13:00:52 -0700157
158 // simple state (straight pointer/value storage):
159 const float alpha;
160 const RoundRectClipState* roundRectClipState;
161 const ProjectionPathMask* projectionPathMask;
162 const RecordedOp* op;
163
164private:
Chris Craike4db79d2015-12-22 16:32:23 -0800165 BakedOpState(LinearAllocator& allocator, Snapshot& snapshot,
166 const RecordedOp& recordedOp, bool expandForStroke)
167 : computedState(allocator, snapshot, recordedOp, expandForStroke)
Chris Craikb565df12015-10-05 13:00:52 -0700168 , alpha(snapshot.alpha)
169 , roundRectClipState(snapshot.roundRectClipState)
170 , projectionPathMask(snapshot.projectionPathMask)
171 , op(&recordedOp) {}
Chris Craikd3daa312015-11-06 10:59:56 -0800172
Chris Craike4db79d2015-12-22 16:32:23 -0800173 BakedOpState(LinearAllocator& allocator, Snapshot& snapshot, const ShadowOp* shadowOpPtr)
174 : computedState(allocator, snapshot)
Chris Craikd3daa312015-11-06 10:59:56 -0800175 , alpha(snapshot.alpha)
176 , roundRectClipState(snapshot.roundRectClipState)
177 , projectionPathMask(snapshot.projectionPathMask)
178 , op(shadowOpPtr) {}
Chris Craikb87eadd2016-01-06 09:16:05 -0800179
180 BakedOpState(const Rect& dstRect, const RecordedOp& recordedOp)
181 : computedState(dstRect)
182 , alpha(1.0f)
183 , roundRectClipState(nullptr)
184 , projectionPathMask(nullptr)
185 , op(&recordedOp) {}
Chris Craikb565df12015-10-05 13:00:52 -0700186};
187
188}; // namespace uirenderer
189}; // namespace android
190
191#endif // ANDROID_HWUI_BAKED_OP_STATE_H