Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Public Member Functions | Public Attributes | List of all members
skgpu::graphite::ClipStack::TransformedShape Struct Reference

Public Member Functions

bool intersects (const TransformedShape &) const
 
bool contains (const TransformedShape &) const
 

Public Attributes

const TransformfLocalToDevice
 
const ShapefShape
 
const RectfOuterBounds
 
const RectfInnerBounds
 
SkClipOp fOp
 
bool fContainsChecksOnlyBounds = false
 

Detailed Description

Definition at line 94 of file ClipStack_graphite.cpp.

Member Function Documentation

◆ contains()

bool skgpu::graphite::ClipStack::TransformedShape::contains ( const TransformedShape o) const

Definition at line 146 of file ClipStack_graphite.cpp.

146 {
147 if (fInnerBounds.contains(o.fOuterBounds)) {
148 return true;
149 }
150 // Skip more expensive contains() checks if configured not to, or if the extent of 'o' exceeds
151 // this shape's outer bounds. When that happens there must be some part of 'o' that cannot be
152 // contained in this shape.
153 if (fContainsChecksOnlyBounds || !fOuterBounds.contains(o.fOuterBounds)) {
154 return false;
155 }
156
158 return false; // don't do any more work
159 }
160
161 if (fLocalToDevice == o.fLocalToDevice) {
162 // Test the shapes directly against each other, with a special check for a rrect+rrect
163 // containment (a intersect b == a implies b contains a) and paths (same gen ID, or same
164 // path for small paths means they contain each other).
165 static constexpr int kMaxPathComparePoints = 16;
166 if (fShape.isRRect() && o.fShape.isRRect()) {
167 return SkRRectPriv::ConservativeIntersect(fShape.rrect(), o.fShape.rrect())
168 == o.fShape.rrect();
169 } else if (fShape.isPath() && o.fShape.isPath()) {
170 // TODO: Is this worth doing still if clips only cost as much as a single draw?
171 return (fShape.path().getGenerationID() == o.fShape.path().getGenerationID()) ||
172 (fShape.path().countPoints() <= kMaxPathComparePoints &&
173 fShape.path() == o.fShape.path());
174 } else {
175 return fShape.conservativeContains(o.fShape.bounds());
176 }
178 o.fLocalToDevice.type() <= Transform::Type::kRectStaysRect) {
179 // Optimize the common case where o's bounds can be mapped tightly into this coordinate
180 // space and then tested against our shape.
181 Rect localBounds = fLocalToDevice.inverseMapRect(
182 o.fLocalToDevice.mapRect(o.fShape.bounds()));
183 return fShape.conservativeContains(localBounds);
184 } else if (fShape.convex()) {
185 // Since this shape is convex, if all four corners of o's bounding box are inside it
186 // then the entirety of o is also guaranteed to be inside it.
187 SkV4 deviceQuad[4];
188 o.fLocalToDevice.mapPoints(o.fShape.bounds(), deviceQuad);
189 SkV4 localQuad[4];
190 fLocalToDevice.inverseMapPoints(deviceQuad, localQuad, 4);
191 for (int i = 0; i < 4; ++i) {
192 // TODO: Would be nice to make this consistent with how the GPU clips NDC w.
193 if (deviceQuad[i].w < SkPathPriv::kW0PlaneDistance ||
194 localQuad[i].w < SkPathPriv::kW0PlaneDistance) {
195 // Something in O actually projects behind the W = 0 plane and would be clipped
196 // to infinity, so it's extremely unlikely that this contains O.
197 return false;
198 }
199 if (!fShape.conservativeContains(skvx::float2::Load(localQuad + i) / localQuad[i].w)) {
200 return false;
201 }
202 }
203 return true;
204 }
205
206 // Else not an easily comparable pair of shapes so assume this doesn't contain O
207 return false;
208}
static constexpr SkScalar kW0PlaneDistance
Definition SkPathPriv.h:40
uint32_t getGenerationID() const
Definition SkPath.cpp:356
int countPoints() const
Definition SkPath.cpp:525
static SkRRect ConservativeIntersect(const SkRRect &a, const SkRRect &b)
Definition SkRRect.cpp:812
AI bool contains(Rect rect) const
Definition Rect.h:127
bool convex(bool simpleFill=true) const
Definition Shape.cpp:59
const SkPath & path() const
Definition Shape.h:107
const SkRRect & rrect() const
Definition Shape.h:106
bool isRRect() const
Definition Shape.h:62
bool conservativeContains(const Rect &rect) const
Definition Shape.cpp:37
bool isPath() const
Definition Shape.h:63
void inverseMapPoints(const SkV4 *deviceIn, SkV4 *localOut, int count) const
Rect inverseMapRect(const Rect &rect) const
TRect< Scalar > Rect
Definition rect.h:746
SkScalar w
Definition SkM44.h:98
static SKVX_ALWAYS_INLINE Vec Load(const void *ptr)
Definition SkVx.h:109

◆ intersects()

bool skgpu::graphite::ClipStack::TransformedShape::intersects ( const TransformedShape o) const

Definition at line 113 of file ClipStack_graphite.cpp.

113 {
114 if (!fOuterBounds.intersects(o.fOuterBounds)) {
115 return false;
116 }
117
119 o.fLocalToDevice.type() <= Transform::Type::kRectStaysRect) {
120 // The two shape's coordinate spaces are different but both rect-stays-rect or simpler.
121 // This means, though, that their outer bounds approximations are tight to their transormed
122 // shape bounds. There's no point to do further tests given that and that we already found
123 // that these outer bounds *do* intersect.
124 return true;
125 } else if (fLocalToDevice == o.fLocalToDevice) {
126 // Since the two shape's local coordinate spaces are the same, we can compare shape
127 // bounds directly for a more accurate intersection test. We intentionally do not go
128 // further and do shape-specific intersection tests since these could have unknown
129 // complexity (for paths) and limited utility (e.g. two round rects that are disjoint
130 // solely from their corner curves).
131 return fShape.bounds().intersects(o.fShape.bounds());
133 o.fLocalToDevice.type() != Transform::Type::kPerspective) {
134 // The shapes don't share the same coordinate system, and their approximate 'outer'
135 // bounds in device space could have substantial outsetting to contain the transformed
136 // shape (e.g. 45 degree rotation). Perform a more detailed check on their oriented
137 // bounding boxes.
138 return oriented_bbox_intersection(fShape.bounds(), fLocalToDevice,
139 o.fShape.bounds(), o.fLocalToDevice);
140 }
141 // Else multiple perspective transforms are involved, so assume intersection and allow the
142 // rasterizer to handle perspective clipping.
143 return true;
144}
AI bool intersects(ComplementRect comp) const
Definition Rect.h:126
Rect bounds() const
Definition Shape.cpp:69

Member Data Documentation

◆ fContainsChecksOnlyBounds

bool skgpu::graphite::ClipStack::TransformedShape::fContainsChecksOnlyBounds = false

Definition at line 107 of file ClipStack_graphite.cpp.

◆ fInnerBounds

const Rect& skgpu::graphite::ClipStack::TransformedShape::fInnerBounds

Definition at line 98 of file ClipStack_graphite.cpp.

◆ fLocalToDevice

const Transform& skgpu::graphite::ClipStack::TransformedShape::fLocalToDevice

Definition at line 95 of file ClipStack_graphite.cpp.

◆ fOp

SkClipOp skgpu::graphite::ClipStack::TransformedShape::fOp

Definition at line 100 of file ClipStack_graphite.cpp.

◆ fOuterBounds

const Rect& skgpu::graphite::ClipStack::TransformedShape::fOuterBounds

Definition at line 97 of file ClipStack_graphite.cpp.

◆ fShape

const Shape& skgpu::graphite::ClipStack::TransformedShape::fShape

Definition at line 96 of file ClipStack_graphite.cpp.


The documentation for this struct was generated from the following file: