blob: a7a11801cfe23e92dc51ad4d84019b4c03aac8b3 [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
John Reck1bcacfd2017-11-03 10:12:19 -070042 const Rect& getBounds() const { return mBounds; }
Rob Tsuk487a92c2015-01-06 13:22:54 -080043
44 Rect transformedBounds() const {
45 Rect transformedBounds(transformAndCalculateBounds(mBounds, mTransform));
46 return transformedBounds;
47 }
48
John Reck1bcacfd2017-11-03 10:12:19 -070049 const Matrix4& getTransform() const { return mTransform; }
Rob Tsuk487a92c2015-01-06 13:22:54 -080050
Chris Craike4db79d2015-12-22 16:32:23 -080051 void transform(const Matrix4& transform) {
52 Matrix4 t;
53 t.loadMultiply(transform, mTransform);
54 mTransform = t;
55 }
56
Rob Tsuk487a92c2015-01-06 13:22:54 -080057private:
58 Rect mBounds;
59 Matrix4 mTransform;
60};
61
62class RectangleList {
63public:
64 RectangleList();
65
66 bool isEmpty() const;
67 int getTransformedRectanglesCount() const;
68 const TransformedRectangle& getTransformedRectangle(int i) const;
69
70 void setEmpty();
71 void set(const Rect& bounds, const Matrix4& transform);
72 bool intersectWith(const Rect& bounds, const Matrix4& transform);
Chris Craike4db79d2015-12-22 16:32:23 -080073 void transform(const Matrix4& transform);
Rob Tsuk487a92c2015-01-06 13:22:54 -080074
75 SkRegion convertToRegion(const SkRegion& clip) const;
76 Rect calculateBounds() const;
77
John Reck1bcacfd2017-11-03 10:12:19 -070078 enum { kMaxTransformedRectangles = 5 };
Rob Tsuk487a92c2015-01-06 13:22:54 -080079
Chris Craike4db79d2015-12-22 16:32:23 -080080private:
Rob Tsuk487a92c2015-01-06 13:22:54 -080081 int mTransformedRectanglesCount;
82 TransformedRectangle mTransformedRectangles[kMaxTransformedRectangles];
83};
84
Chris Craike4db79d2015-12-22 16:32:23 -080085enum class ClipMode {
86 Rectangle,
87 RectangleList,
Chris Craik4d3e7042015-08-20 12:54:25 -070088
Chris Craike4db79d2015-12-22 16:32:23 -080089 // region and path - intersected. if either is empty, don't use
90 Region
91};
92
93struct ClipBase {
John Reck1bcacfd2017-11-03 10:12:19 -070094 explicit ClipBase(ClipMode mode) : mode(mode) {}
95 explicit ClipBase(const Rect& rect) : mode(ClipMode::Rectangle), rect(rect) {}
Chris Craike4db79d2015-12-22 16:32:23 -080096 const ClipMode mode;
Chris Craik04d46eb2016-04-07 13:51:07 -070097 bool intersectWithRoot = false;
Chris Craike4db79d2015-12-22 16:32:23 -080098 // Bounds of the clipping area, used to define the scissor, and define which
99 // portion of the stencil is updated/used
100 Rect rect;
Chris Craik02806282016-03-11 19:16:21 -0800101
102 void dump() const;
Chris Craike4db79d2015-12-22 16:32:23 -0800103};
104
105struct ClipRect : ClipBase {
John Reck1bcacfd2017-11-03 10:12:19 -0700106 explicit ClipRect(const Rect& rect) : ClipBase(rect) {}
Chris Craike4db79d2015-12-22 16:32:23 -0800107};
108
109struct ClipRectList : ClipBase {
Chih-Hung Hsieha619ec72016-08-29 14:52:43 -0700110 explicit ClipRectList(const RectangleList& rectList)
John Reck1bcacfd2017-11-03 10:12:19 -0700111 : ClipBase(ClipMode::RectangleList), rectList(rectList) {}
Chris Craike4db79d2015-12-22 16:32:23 -0800112 RectangleList rectList;
113};
114
115struct ClipRegion : ClipBase {
John Reck1bcacfd2017-11-03 10:12:19 -0700116 explicit ClipRegion(const SkRegion& region) : ClipBase(ClipMode::Region), region(region) {}
117 ClipRegion() : ClipBase(ClipMode::Region) {}
Chris Craike4db79d2015-12-22 16:32:23 -0800118 SkRegion region;
119};
120
121class ClipArea {
Rob Tsuk487a92c2015-01-06 13:22:54 -0800122public:
123 ClipArea();
124
125 void setViewportDimensions(int width, int height);
126
John Reck1bcacfd2017-11-03 10:12:19 -0700127 bool isEmpty() const { return mClipRect.isEmpty(); }
Rob Tsuk487a92c2015-01-06 13:22:54 -0800128
129 void setEmpty();
130 void setClip(float left, float top, float right, float bottom);
John Reck1bcacfd2017-11-03 10:12:19 -0700131 void clipRectWithTransform(const Rect& r, const mat4* transform, SkRegion::Op op);
132 void clipPathWithTransform(const SkPath& path, const mat4* transform, SkRegion::Op op);
Rob Tsuk487a92c2015-01-06 13:22:54 -0800133
John Reck1bcacfd2017-11-03 10:12:19 -0700134 const Rect& getClipRect() const { return mClipRect; }
Rob Tsuk487a92c2015-01-06 13:22:54 -0800135
John Reck1bcacfd2017-11-03 10:12:19 -0700136 const SkRegion& getClipRegion() const { return mClipRegion; }
Rob Tsuk487a92c2015-01-06 13:22:54 -0800137
John Reck1bcacfd2017-11-03 10:12:19 -0700138 const RectangleList& getRectangleList() const { return mRectangleList; }
Rob Tsuk487a92c2015-01-06 13:22:54 -0800139
John Reck1bcacfd2017-11-03 10:12:19 -0700140 bool isRegion() const { return ClipMode::Region == mMode; }
Rob Tsuk487a92c2015-01-06 13:22:54 -0800141
John Reck1bcacfd2017-11-03 10:12:19 -0700142 bool isSimple() const { return mMode == ClipMode::Rectangle; }
Rob Tsuk487a92c2015-01-06 13:22:54 -0800143
John Reck1bcacfd2017-11-03 10:12:19 -0700144 bool isRectangleList() const { return mMode == ClipMode::RectangleList; }
Rob Tsuk487a92c2015-01-06 13:22:54 -0800145
Chris Craik04d46eb2016-04-07 13:51:07 -0700146 WARN_UNUSED_RESULT const ClipBase* serializeClip(LinearAllocator& allocator);
John Reck1bcacfd2017-11-03 10:12:19 -0700147 WARN_UNUSED_RESULT const ClipBase* serializeIntersectedClip(
148 LinearAllocator& allocator, const ClipBase* recordedClip,
149 const Matrix4& recordedClipTransform);
Chris Craike4db79d2015-12-22 16:32:23 -0800150 void applyClip(const ClipBase* recordedClip, const Matrix4& recordedClipTransform);
151
Chris Craik82457c52016-06-29 16:22:27 -0700152 static void applyTransformToRegion(const Matrix4& transform, SkRegion* region);
153
Rob Tsuk487a92c2015-01-06 13:22:54 -0800154private:
155 void enterRectangleMode();
Chris Craik4d3e7042015-08-20 12:54:25 -0700156 void rectangleModeClipRectWithTransform(const Rect& r, const mat4* transform, SkRegion::Op op);
Rob Tsuk487a92c2015-01-06 13:22:54 -0800157
158 void enterRectangleListMode();
John Reck1bcacfd2017-11-03 10:12:19 -0700159 void rectangleListModeClipRectWithTransform(const Rect& r, const mat4* transform,
160 SkRegion::Op op);
Rob Tsuk487a92c2015-01-06 13:22:54 -0800161
162 void enterRegionModeFromRectangleMode();
163 void enterRegionModeFromRectangleListMode();
164 void enterRegionMode();
John Reck1bcacfd2017-11-03 10:12:19 -0700165 void regionModeClipRectWithTransform(const Rect& r, const mat4* transform, SkRegion::Op op);
Rob Tsuk487a92c2015-01-06 13:22:54 -0800166
Derek Sollenbergerb29b16e2017-01-04 14:57:43 -0500167 void clipRegion(const SkRegion& region, SkRegion::Op op);
Rob Tsuk487a92c2015-01-06 13:22:54 -0800168 void ensureClipRegion();
Tom Hudsone30b53c2015-03-30 15:59:02 -0400169 void onClipRegionUpdated();
Rob Tsuk487a92c2015-01-06 13:22:54 -0800170
Chris Craike4db79d2015-12-22 16:32:23 -0800171 // Called by every state modifying public method.
172 void onClipUpdated() {
173 mPostViewportClipObserved = true;
174 mLastSerialization = nullptr;
175 mLastResolutionResult = nullptr;
176 }
177
John Reck1bcacfd2017-11-03 10:12:19 -0700178 SkRegion createViewportRegion() { return SkRegion(mViewportBounds.toSkIRect()); }
Rob Tsuk487a92c2015-01-06 13:22:54 -0800179
180 void regionFromPath(const SkPath& path, SkRegion& pathAsRegion) {
Chris Craik8ce8f3f2015-07-16 13:07:45 -0700181 // TODO: this should not mask every path to the viewport - this makes it impossible to use
182 // paths to clip to larger areas (which is valid e.g. with SkRegion::kReplace_Op)
Rob Tsuk487a92c2015-01-06 13:22:54 -0800183 pathAsRegion.setPath(path, createViewportRegion());
184 }
185
Chris Craike4db79d2015-12-22 16:32:23 -0800186 ClipMode mMode;
187 bool mPostViewportClipObserved = false;
Chris Craik04d46eb2016-04-07 13:51:07 -0700188 bool mReplaceOpObserved = false;
Chris Craike4db79d2015-12-22 16:32:23 -0800189
190 /**
191 * If mLastSerialization is non-null, it represents an already serialized copy
192 * of the current clip state. If null, it has not been computed.
193 */
194 const ClipBase* mLastSerialization = nullptr;
195
196 /**
197 * This pair of pointers is a single entry cache of most recently seen
198 */
199 const ClipBase* mLastResolutionResult = nullptr;
200 const ClipBase* mLastResolutionClip = nullptr;
201 Matrix4 mLastResolutionTransform;
202
Rob Tsuk487a92c2015-01-06 13:22:54 -0800203 Rect mViewportBounds;
204 Rect mClipRect;
205 SkRegion mClipRegion;
206 RectangleList mRectangleList;
207};
208
209} /* namespace uirenderer */
210} /* namespace android */
211
212#endif /* CLIPAREA_H_ */