blob: 53d9d03a3629453bb4f5c4157f4597765a667574 [file] [log] [blame]
Rob Tsuk487a92c2015-01-06 13:22:54 -08001/*
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#ifndef CLIPAREA_H
17#define CLIPAREA_H
18
Rob Tsuk487a92c2015-01-06 13:22:54 -080019#include "Matrix.h"
20#include "Rect.h"
21#include "utils/Pair.h"
22
Chris Craike4db79d2015-12-22 16:32:23 -080023#include <SkRegion.h>
24
Rob Tsuk487a92c2015-01-06 13:22:54 -080025namespace android {
26namespace uirenderer {
27
Chris Craike4db79d2015-12-22 16:32:23 -080028class LinearAllocator;
29
Rob Tsuk487a92c2015-01-06 13:22:54 -080030Rect transformAndCalculateBounds(const Rect& r, const Matrix4& transform);
31
32class TransformedRectangle {
33public:
34 TransformedRectangle();
35 TransformedRectangle(const Rect& bounds, const Matrix4& transform);
36
37 bool canSimplyIntersectWith(const TransformedRectangle& other) const;
Chris Craikac02eb92015-10-05 12:23:46 -070038 void intersectWith(const TransformedRectangle& other);
Rob Tsuk487a92c2015-01-06 13:22:54 -080039
40 bool isEmpty() const;
41
42 const Rect& getBounds() const {
43 return mBounds;
44 }
45
46 Rect transformedBounds() const {
47 Rect transformedBounds(transformAndCalculateBounds(mBounds, mTransform));
48 return transformedBounds;
49 }
50
51 const Matrix4& getTransform() const {
52 return mTransform;
53 }
54
Chris Craike4db79d2015-12-22 16:32:23 -080055 void transform(const Matrix4& transform) {
56 Matrix4 t;
57 t.loadMultiply(transform, mTransform);
58 mTransform = t;
59 }
60
Rob Tsuk487a92c2015-01-06 13:22:54 -080061private:
62 Rect mBounds;
63 Matrix4 mTransform;
64};
65
66class RectangleList {
67public:
68 RectangleList();
69
70 bool isEmpty() const;
71 int getTransformedRectanglesCount() const;
72 const TransformedRectangle& getTransformedRectangle(int i) const;
73
74 void setEmpty();
75 void set(const Rect& bounds, const Matrix4& transform);
76 bool intersectWith(const Rect& bounds, const Matrix4& transform);
Chris Craike4db79d2015-12-22 16:32:23 -080077 void transform(const Matrix4& transform);
Rob Tsuk487a92c2015-01-06 13:22:54 -080078
79 SkRegion convertToRegion(const SkRegion& clip) const;
80 Rect calculateBounds() const;
81
Rob Tsuk487a92c2015-01-06 13:22:54 -080082 enum {
83 kMaxTransformedRectangles = 5
84 };
85
Chris Craike4db79d2015-12-22 16:32:23 -080086private:
Rob Tsuk487a92c2015-01-06 13:22:54 -080087 int mTransformedRectanglesCount;
88 TransformedRectangle mTransformedRectangles[kMaxTransformedRectangles];
89};
90
Chris Craike4db79d2015-12-22 16:32:23 -080091enum class ClipMode {
92 Rectangle,
93 RectangleList,
Chris Craik4d3e7042015-08-20 12:54:25 -070094
Chris Craike4db79d2015-12-22 16:32:23 -080095 // region and path - intersected. if either is empty, don't use
96 Region
97};
98
99struct ClipBase {
100 ClipBase(ClipMode mode)
101 : mode(mode) {}
102 ClipBase(const Rect& rect)
103 : mode(ClipMode::Rectangle)
104 , rect(rect) {}
105 const ClipMode mode;
Chris Craik04d46eb2016-04-07 13:51:07 -0700106 bool intersectWithRoot = false;
Chris Craike4db79d2015-12-22 16:32:23 -0800107 // Bounds of the clipping area, used to define the scissor, and define which
108 // portion of the stencil is updated/used
109 Rect rect;
Chris Craik02806282016-03-11 19:16:21 -0800110
111 void dump() const;
Chris Craike4db79d2015-12-22 16:32:23 -0800112};
113
114struct ClipRect : ClipBase {
115 ClipRect(const Rect& rect)
116 : ClipBase(rect) {}
117};
118
119struct ClipRectList : ClipBase {
120 ClipRectList(const RectangleList& rectList)
121 : ClipBase(ClipMode::RectangleList)
122 , rectList(rectList) {}
123 RectangleList rectList;
124};
125
126struct ClipRegion : ClipBase {
127 ClipRegion(const SkRegion& region)
128 : ClipBase(ClipMode::Region)
129 , region(region) {}
130 ClipRegion()
131 : ClipBase(ClipMode::Region) {}
132 SkRegion region;
133};
134
135class ClipArea {
Rob Tsuk487a92c2015-01-06 13:22:54 -0800136public:
137 ClipArea();
138
139 void setViewportDimensions(int width, int height);
140
141 bool isEmpty() const {
142 return mClipRect.isEmpty();
143 }
144
145 void setEmpty();
146 void setClip(float left, float top, float right, float bottom);
Chris Craik4d3e7042015-08-20 12:54:25 -0700147 void clipRectWithTransform(const Rect& r, const mat4* transform,
148 SkRegion::Op op);
149 void clipRegion(const SkRegion& region, SkRegion::Op op);
150 void clipPathWithTransform(const SkPath& path, const mat4* transform,
Rob Tsuk487a92c2015-01-06 13:22:54 -0800151 SkRegion::Op op);
152
153 const Rect& getClipRect() const {
154 return mClipRect;
155 }
156
157 const SkRegion& getClipRegion() const {
158 return mClipRegion;
159 }
160
161 const RectangleList& getRectangleList() const {
162 return mRectangleList;
163 }
164
165 bool isRegion() const {
Chris Craike4db79d2015-12-22 16:32:23 -0800166 return ClipMode::Region == mMode;
Rob Tsuk487a92c2015-01-06 13:22:54 -0800167 }
168
169 bool isSimple() const {
Chris Craike4db79d2015-12-22 16:32:23 -0800170 return mMode == ClipMode::Rectangle;
Rob Tsuk487a92c2015-01-06 13:22:54 -0800171 }
172
173 bool isRectangleList() const {
Chris Craike4db79d2015-12-22 16:32:23 -0800174 return mMode == ClipMode::RectangleList;
Rob Tsuk487a92c2015-01-06 13:22:54 -0800175 }
176
Chris Craik04d46eb2016-04-07 13:51:07 -0700177 WARN_UNUSED_RESULT const ClipBase* serializeClip(LinearAllocator& allocator);
178 WARN_UNUSED_RESULT const ClipBase* serializeIntersectedClip(LinearAllocator& allocator,
Chris Craike4db79d2015-12-22 16:32:23 -0800179 const ClipBase* recordedClip, const Matrix4& recordedClipTransform);
180 void applyClip(const ClipBase* recordedClip, const Matrix4& recordedClipTransform);
181
Chris Craik82457c52016-06-29 16:22:27 -0700182 static void applyTransformToRegion(const Matrix4& transform, SkRegion* region);
183
Rob Tsuk487a92c2015-01-06 13:22:54 -0800184private:
185 void enterRectangleMode();
Chris Craik4d3e7042015-08-20 12:54:25 -0700186 void rectangleModeClipRectWithTransform(const Rect& r, const mat4* transform, SkRegion::Op op);
Rob Tsuk487a92c2015-01-06 13:22:54 -0800187
188 void enterRectangleListMode();
Chris Craik4d3e7042015-08-20 12:54:25 -0700189 void rectangleListModeClipRectWithTransform(const Rect& r,
Rob Tsuk487a92c2015-01-06 13:22:54 -0800190 const mat4* transform, SkRegion::Op op);
191
192 void enterRegionModeFromRectangleMode();
193 void enterRegionModeFromRectangleListMode();
194 void enterRegionMode();
Chris Craik4d3e7042015-08-20 12:54:25 -0700195 void regionModeClipRectWithTransform(const Rect& r, const mat4* transform,
Rob Tsuk487a92c2015-01-06 13:22:54 -0800196 SkRegion::Op op);
Rob Tsuk487a92c2015-01-06 13:22:54 -0800197
198 void ensureClipRegion();
Tom Hudsone30b53c2015-03-30 15:59:02 -0400199 void onClipRegionUpdated();
Rob Tsuk487a92c2015-01-06 13:22:54 -0800200
Chris Craike4db79d2015-12-22 16:32:23 -0800201 // Called by every state modifying public method.
202 void onClipUpdated() {
203 mPostViewportClipObserved = true;
204 mLastSerialization = nullptr;
205 mLastResolutionResult = nullptr;
206 }
207
Rob Tsuk487a92c2015-01-06 13:22:54 -0800208 SkRegion createViewportRegion() {
209 return SkRegion(mViewportBounds.toSkIRect());
210 }
211
212 void regionFromPath(const SkPath& path, SkRegion& pathAsRegion) {
Chris Craik8ce8f3f2015-07-16 13:07:45 -0700213 // TODO: this should not mask every path to the viewport - this makes it impossible to use
214 // paths to clip to larger areas (which is valid e.g. with SkRegion::kReplace_Op)
Rob Tsuk487a92c2015-01-06 13:22:54 -0800215 pathAsRegion.setPath(path, createViewportRegion());
216 }
217
Chris Craike4db79d2015-12-22 16:32:23 -0800218 ClipMode mMode;
219 bool mPostViewportClipObserved = false;
Chris Craik04d46eb2016-04-07 13:51:07 -0700220 bool mReplaceOpObserved = false;
Chris Craike4db79d2015-12-22 16:32:23 -0800221
222 /**
223 * If mLastSerialization is non-null, it represents an already serialized copy
224 * of the current clip state. If null, it has not been computed.
225 */
226 const ClipBase* mLastSerialization = nullptr;
227
228 /**
229 * This pair of pointers is a single entry cache of most recently seen
230 */
231 const ClipBase* mLastResolutionResult = nullptr;
232 const ClipBase* mLastResolutionClip = nullptr;
233 Matrix4 mLastResolutionTransform;
234
Rob Tsuk487a92c2015-01-06 13:22:54 -0800235 Rect mViewportBounds;
236 Rect mClipRect;
237 SkRegion mClipRegion;
238 RectangleList mRectangleList;
239};
240
241} /* namespace uirenderer */
242} /* namespace android */
243
244#endif /* CLIPAREA_H_ */