1 /*
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 
25 namespace android {
26 namespace uirenderer {
27 
28 namespace 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 /**
41  * Holds a list of BakedOpStates of ops that can be drawn together
42  */
43 struct MergedBakedOpList {
44     const BakedOpState* const* states;
45     size_t count;
46     int clipSideFlags;
47     Rect clip;
48 };
49 
50 /**
51  * Holds the resolved clip, transform, and bounds of a recordedOp, when replayed with a snapshot
52  */
53 class ResolvedRenderState {
54 public:
55     ResolvedRenderState(LinearAllocator& allocator, Snapshot& snapshot,
56                         const RecordedOp& recordedOp, bool expandForStroke,
57                         bool expandForPathTexture);
58 
59     // Constructor for unbounded ops *with* transform/clip
60     ResolvedRenderState(LinearAllocator& allocator, Snapshot& snapshot,
61                         const Matrix4& localTransform, const ClipBase* localClip);
62 
63     // Constructor for unbounded ops without transform/clip (namely shadows)
64     ResolvedRenderState(LinearAllocator& allocator, Snapshot& snapshot);
65 
66     // Constructor for primitive ops provided clip, and no transform
67     ResolvedRenderState(const ClipRect* viewportRect, const Rect& dstRect);
68 
computeLocalSpaceClip()69     Rect computeLocalSpaceClip() const {
70         Matrix4 inverse;
71         inverse.loadInverse(transform);
72 
73         Rect outClip(clipRect());
74         inverse.mapRect(outClip);
75         return outClip;
76     }
77 
clipRect()78     const Rect& clipRect() const { return clipState->rect; }
79 
requiresClip()80     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
getClipIfNeeded()86     const ClipBase* getClipIfNeeded() const { return requiresClip() ? clipState : nullptr; }
87 
88     Matrix4 transform;
89     const ClipBase* clipState = nullptr;
90     Rect clippedBounds;
91     int clipSideFlags = 0;
92     const SkPath* localProjectionPathMask = nullptr;
93     bool opaqueOverClippedBounds = false;
94 };
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  */
101 class BakedOpState {
102 public:
103     static BakedOpState* tryConstruct(LinearAllocator& allocator, Snapshot& snapshot,
104                                       const RecordedOp& recordedOp);
105 
106     static BakedOpState* tryConstructUnbounded(LinearAllocator& allocator, Snapshot& snapshot,
107                                                const RecordedOp& recordedOp);
108 
109     enum class StrokeBehavior {
110         // stroking is forced, regardless of style on paint (such as for lines)
111         Forced,
112         // stroking is defined by style on paint
113         StyleDefined,
114     };
115 
116     static BakedOpState* tryStrokeableOpConstruct(LinearAllocator& allocator, Snapshot& snapshot,
117                                                   const RecordedOp& recordedOp,
118                                                   StrokeBehavior strokeBehavior,
119                                                   bool expandForPathTexture);
120 
121     static BakedOpState* tryShadowOpConstruct(LinearAllocator& allocator, Snapshot& snapshot,
122                                               const ShadowOp* shadowOpPtr);
123 
124     static BakedOpState* directConstruct(LinearAllocator& allocator, const ClipRect* clip,
125                                          const Rect& dstRect, const RecordedOp& recordedOp);
126 
127     // Set opaqueOverClippedBounds. If this method isn't called, the op is assumed translucent.
128     void setupOpacity(const SkPaint* paint);
129 
130     // computed state:
131     ResolvedRenderState computedState;
132 
133     // simple state (straight pointer/value storage):
134     const float alpha;
135     const RoundRectClipState* roundRectClipState;
136     const RecordedOp* op;
137 
138 private:
139     friend class LinearAllocator;
140 
BakedOpState(LinearAllocator & allocator,Snapshot & snapshot,const RecordedOp & recordedOp,bool expandForStroke,bool expandForPathTexture)141     BakedOpState(LinearAllocator& allocator, Snapshot& snapshot, const RecordedOp& recordedOp,
142                  bool expandForStroke, bool expandForPathTexture)
143             : computedState(allocator, snapshot, recordedOp, expandForStroke, expandForPathTexture)
144             , alpha(snapshot.alpha)
145             , roundRectClipState(snapshot.roundRectClipState)
146             , op(&recordedOp) {}
147 
148     // TODO: fix this brittleness
BakedOpState(LinearAllocator & allocator,Snapshot & snapshot,const RecordedOp & recordedOp)149     BakedOpState(LinearAllocator& allocator, Snapshot& snapshot, const RecordedOp& recordedOp)
150             : computedState(allocator, snapshot, recordedOp.localMatrix, recordedOp.localClip)
151             , alpha(snapshot.alpha)
152             , roundRectClipState(snapshot.roundRectClipState)
153             , op(&recordedOp) {}
154 
BakedOpState(LinearAllocator & allocator,Snapshot & snapshot,const ShadowOp * shadowOpPtr)155     BakedOpState(LinearAllocator& allocator, Snapshot& snapshot, const ShadowOp* shadowOpPtr)
156             : computedState(allocator, snapshot)
157             , alpha(snapshot.alpha)
158             , roundRectClipState(snapshot.roundRectClipState)
159             , op(shadowOpPtr) {}
160 
BakedOpState(const ClipRect * clipRect,const Rect & dstRect,const RecordedOp & recordedOp)161     BakedOpState(const ClipRect* clipRect, const Rect& dstRect, const RecordedOp& recordedOp)
162             : computedState(clipRect, dstRect)
163             , alpha(1.0f)
164             , roundRectClipState(nullptr)
165             , op(&recordedOp) {}
166 };
167 
168 };  // namespace uirenderer
169 };  // namespace android
170 
171 #endif  // ANDROID_HWUI_BAKED_OP_STATE_H
172