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 58 // Constructor for unbounded ops *with* transform/clip 59 ResolvedRenderState(LinearAllocator& allocator, Snapshot& snapshot, 60 const Matrix4& localTransform, const ClipBase* localClip); 61 62 // Constructor for unbounded ops without transform/clip (namely shadows) 63 ResolvedRenderState(LinearAllocator& allocator, Snapshot& snapshot); 64 65 // Constructor for primitive ops provided clip, and no transform 66 ResolvedRenderState(const ClipRect* viewportRect, const Rect& dstRect); 67 computeLocalSpaceClip()68 Rect computeLocalSpaceClip() const { 69 Matrix4 inverse; 70 inverse.loadInverse(transform); 71 72 Rect outClip(clipRect()); 73 inverse.mapRect(outClip); 74 return outClip; 75 } 76 clipRect()77 const Rect& clipRect() const { 78 return clipState->rect; 79 } 80 requiresClip()81 bool requiresClip() const { 82 return clipSideFlags != OpClipSideFlags::None 83 || CC_UNLIKELY(clipState->mode != ClipMode::Rectangle); 84 } 85 86 // returns the clip if it's needed to draw the operation, otherwise nullptr getClipIfNeeded()87 const ClipBase* getClipIfNeeded() const { 88 return requiresClip() ? clipState : nullptr; 89 } 90 91 Matrix4 transform; 92 const ClipBase* clipState = nullptr; 93 Rect clippedBounds; 94 int clipSideFlags = 0; 95 const SkPath* localProjectionPathMask = nullptr; 96 bool opaqueOverClippedBounds = false; 97 }; 98 99 /** 100 * Self-contained op wrapper, containing all resolved state required to draw the op. 101 * 102 * Stashed pointers within all point to longer lived objects, with no ownership implied. 103 */ 104 class BakedOpState { 105 public: 106 static BakedOpState* tryConstruct(LinearAllocator& allocator, 107 Snapshot& snapshot, const RecordedOp& recordedOp); 108 109 static BakedOpState* tryConstructUnbounded(LinearAllocator& allocator, 110 Snapshot& snapshot, const RecordedOp& recordedOp); 111 112 enum class StrokeBehavior { 113 // stroking is forced, regardless of style on paint (such as for lines) 114 Forced, 115 // stroking is defined by style on paint 116 StyleDefined, 117 }; 118 119 static BakedOpState* tryStrokeableOpConstruct(LinearAllocator& allocator, 120 Snapshot& snapshot, const RecordedOp& recordedOp, StrokeBehavior strokeBehavior); 121 122 static BakedOpState* tryShadowOpConstruct(LinearAllocator& allocator, 123 Snapshot& snapshot, const ShadowOp* shadowOpPtr); 124 125 static BakedOpState* directConstruct(LinearAllocator& allocator, 126 const ClipRect* clip, const Rect& dstRect, const RecordedOp& recordedOp); 127 128 // Set opaqueOverClippedBounds. If this method isn't called, the op is assumed translucent. 129 void setupOpacity(const SkPaint* paint); 130 131 // computed state: 132 ResolvedRenderState computedState; 133 134 // simple state (straight pointer/value storage): 135 const float alpha; 136 const RoundRectClipState* roundRectClipState; 137 const RecordedOp* op; 138 139 private: 140 friend class LinearAllocator; 141 BakedOpState(LinearAllocator & allocator,Snapshot & snapshot,const RecordedOp & recordedOp,bool expandForStroke)142 BakedOpState(LinearAllocator& allocator, Snapshot& snapshot, 143 const RecordedOp& recordedOp, bool expandForStroke) 144 : computedState(allocator, snapshot, recordedOp, expandForStroke) 145 , alpha(snapshot.alpha) 146 , roundRectClipState(snapshot.roundRectClipState) 147 , op(&recordedOp) {} 148 149 // TODO: fix this brittleness BakedOpState(LinearAllocator & allocator,Snapshot & snapshot,const RecordedOp & recordedOp)150 BakedOpState(LinearAllocator& allocator, Snapshot& snapshot, const RecordedOp& recordedOp) 151 : computedState(allocator, snapshot, recordedOp.localMatrix, recordedOp.localClip) 152 , alpha(snapshot.alpha) 153 , roundRectClipState(snapshot.roundRectClipState) 154 , op(&recordedOp) {} 155 BakedOpState(LinearAllocator & allocator,Snapshot & snapshot,const ShadowOp * shadowOpPtr)156 BakedOpState(LinearAllocator& allocator, Snapshot& snapshot, const ShadowOp* shadowOpPtr) 157 : computedState(allocator, snapshot) 158 , alpha(snapshot.alpha) 159 , roundRectClipState(snapshot.roundRectClipState) 160 , op(shadowOpPtr) {} 161 BakedOpState(const ClipRect * clipRect,const Rect & dstRect,const RecordedOp & recordedOp)162 BakedOpState(const ClipRect* clipRect, const Rect& dstRect, const RecordedOp& recordedOp) 163 : computedState(clipRect, dstRect) 164 , alpha(1.0f) 165 , roundRectClipState(nullptr) 166 , op(&recordedOp) {} 167 }; 168 169 }; // namespace uirenderer 170 }; // namespace android 171 172 #endif // ANDROID_HWUI_BAKED_OP_STATE_H 173