blob: 1654eb8f02e4dbd6b069e6b0ad7e6678c562bbe4 [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;
106 // Bounds of the clipping area, used to define the scissor, and define which
107 // portion of the stencil is updated/used
108 Rect rect;
Chris Craik02806282016-03-11 19:16:21 -0800109
110 void dump() const;
Chris Craike4db79d2015-12-22 16:32:23 -0800111};
112
113struct ClipRect : ClipBase {
114 ClipRect(const Rect& rect)
115 : ClipBase(rect) {}
116};
117
118struct ClipRectList : ClipBase {
119 ClipRectList(const RectangleList& rectList)
120 : ClipBase(ClipMode::RectangleList)
121 , rectList(rectList) {}
122 RectangleList rectList;
123};
124
125struct ClipRegion : ClipBase {
126 ClipRegion(const SkRegion& region)
127 : ClipBase(ClipMode::Region)
128 , region(region) {}
129 ClipRegion()
130 : ClipBase(ClipMode::Region) {}
131 SkRegion region;
132};
133
134class ClipArea {
Rob Tsuk487a92c2015-01-06 13:22:54 -0800135public:
136 ClipArea();
137
138 void setViewportDimensions(int width, int height);
139
140 bool isEmpty() const {
141 return mClipRect.isEmpty();
142 }
143
144 void setEmpty();
145 void setClip(float left, float top, float right, float bottom);
Chris Craik4d3e7042015-08-20 12:54:25 -0700146 void clipRectWithTransform(const Rect& r, const mat4* transform,
147 SkRegion::Op op);
148 void clipRegion(const SkRegion& region, SkRegion::Op op);
149 void clipPathWithTransform(const SkPath& path, const mat4* transform,
Rob Tsuk487a92c2015-01-06 13:22:54 -0800150 SkRegion::Op op);
151
152 const Rect& getClipRect() const {
153 return mClipRect;
154 }
155
156 const SkRegion& getClipRegion() const {
157 return mClipRegion;
158 }
159
160 const RectangleList& getRectangleList() const {
161 return mRectangleList;
162 }
163
164 bool isRegion() const {
Chris Craike4db79d2015-12-22 16:32:23 -0800165 return ClipMode::Region == mMode;
Rob Tsuk487a92c2015-01-06 13:22:54 -0800166 }
167
168 bool isSimple() const {
Chris Craike4db79d2015-12-22 16:32:23 -0800169 return mMode == ClipMode::Rectangle;
Rob Tsuk487a92c2015-01-06 13:22:54 -0800170 }
171
172 bool isRectangleList() const {
Chris Craike4db79d2015-12-22 16:32:23 -0800173 return mMode == ClipMode::RectangleList;
Rob Tsuk487a92c2015-01-06 13:22:54 -0800174 }
175
Chris Craike4db79d2015-12-22 16:32:23 -0800176 const ClipBase* serializeClip(LinearAllocator& allocator);
177 const ClipBase* serializeIntersectedClip(LinearAllocator& allocator,
178 const ClipBase* recordedClip, const Matrix4& recordedClipTransform);
179 void applyClip(const ClipBase* recordedClip, const Matrix4& recordedClipTransform);
180
Rob Tsuk487a92c2015-01-06 13:22:54 -0800181private:
182 void enterRectangleMode();
Chris Craik4d3e7042015-08-20 12:54:25 -0700183 void rectangleModeClipRectWithTransform(const Rect& r, const mat4* transform, SkRegion::Op op);
Rob Tsuk487a92c2015-01-06 13:22:54 -0800184
185 void enterRectangleListMode();
Chris Craik4d3e7042015-08-20 12:54:25 -0700186 void rectangleListModeClipRectWithTransform(const Rect& r,
Rob Tsuk487a92c2015-01-06 13:22:54 -0800187 const mat4* transform, SkRegion::Op op);
188
189 void enterRegionModeFromRectangleMode();
190 void enterRegionModeFromRectangleListMode();
191 void enterRegionMode();
Chris Craik4d3e7042015-08-20 12:54:25 -0700192 void regionModeClipRectWithTransform(const Rect& r, const mat4* transform,
Rob Tsuk487a92c2015-01-06 13:22:54 -0800193 SkRegion::Op op);
Rob Tsuk487a92c2015-01-06 13:22:54 -0800194
195 void ensureClipRegion();
Tom Hudsone30b53c2015-03-30 15:59:02 -0400196 void onClipRegionUpdated();
Rob Tsuk487a92c2015-01-06 13:22:54 -0800197
Chris Craike4db79d2015-12-22 16:32:23 -0800198 // Called by every state modifying public method.
199 void onClipUpdated() {
200 mPostViewportClipObserved = true;
201 mLastSerialization = nullptr;
202 mLastResolutionResult = nullptr;
203 }
204
Rob Tsuk487a92c2015-01-06 13:22:54 -0800205 SkRegion createViewportRegion() {
206 return SkRegion(mViewportBounds.toSkIRect());
207 }
208
209 void regionFromPath(const SkPath& path, SkRegion& pathAsRegion) {
Chris Craik8ce8f3f2015-07-16 13:07:45 -0700210 // TODO: this should not mask every path to the viewport - this makes it impossible to use
211 // paths to clip to larger areas (which is valid e.g. with SkRegion::kReplace_Op)
Rob Tsuk487a92c2015-01-06 13:22:54 -0800212 pathAsRegion.setPath(path, createViewportRegion());
213 }
214
Chris Craike4db79d2015-12-22 16:32:23 -0800215 ClipMode mMode;
216 bool mPostViewportClipObserved = false;
217
218 /**
219 * If mLastSerialization is non-null, it represents an already serialized copy
220 * of the current clip state. If null, it has not been computed.
221 */
222 const ClipBase* mLastSerialization = nullptr;
223
224 /**
225 * This pair of pointers is a single entry cache of most recently seen
226 */
227 const ClipBase* mLastResolutionResult = nullptr;
228 const ClipBase* mLastResolutionClip = nullptr;
229 Matrix4 mLastResolutionTransform;
230
Rob Tsuk487a92c2015-01-06 13:22:54 -0800231 Rect mViewportBounds;
232 Rect mClipRect;
233 SkRegion mClipRegion;
234 RectangleList mRectangleList;
235};
236
237} /* namespace uirenderer */
238} /* namespace android */
239
240#endif /* CLIPAREA_H_ */