Handle non-finite quads in attemptQuadOptimization
Bug: chromium:977315 Change-Id: Ia5b734f5c0f0806af0f096de5add880a777c5c25 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/222793 Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Michael Ludwig <michaelludwig@google.com>
This commit is contained in:
parent
e505341a24
commit
ed71b7e779
@ -537,6 +537,21 @@ enum class GrRenderTargetContext::QuadOptimization {
|
|||||||
kCropped
|
kCropped
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static bool make_vertex_finite(float* value) {
|
||||||
|
if (SkScalarIsNaN(*value)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SkScalarIsFinite(*value)) {
|
||||||
|
// +/- infinity at this point. Don't use exactly SK_ScalarMax so that we have some precision
|
||||||
|
// left when calculating crops.
|
||||||
|
static constexpr float kNearInfinity = SK_ScalarMax / 4.f;
|
||||||
|
*value = *value < 0.f ? -kNearInfinity : kNearInfinity;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
GrRenderTargetContext::QuadOptimization GrRenderTargetContext::attemptQuadOptimization(
|
GrRenderTargetContext::QuadOptimization GrRenderTargetContext::attemptQuadOptimization(
|
||||||
const GrClip& clip, const SkPMColor4f* constColor,
|
const GrClip& clip, const SkPMColor4f* constColor,
|
||||||
const GrUserStencilSettings* stencilSettings, GrAA* aa, GrQuadAAFlags* edgeFlags,
|
const GrUserStencilSettings* stencilSettings, GrAA* aa, GrQuadAAFlags* edgeFlags,
|
||||||
@ -567,6 +582,25 @@ GrRenderTargetContext::QuadOptimization GrRenderTargetContext::attemptQuadOptimi
|
|||||||
if (constColor) {
|
if (constColor) {
|
||||||
// Don't bother updating local coordinates when the paint will ignore them anyways
|
// Don't bother updating local coordinates when the paint will ignore them anyways
|
||||||
localQuad = nullptr;
|
localQuad = nullptr;
|
||||||
|
// If the device quad is not finite, coerce into a finite quad. This is acceptable since it
|
||||||
|
// will be cropped to the finite 'clip' or render target and there is no local space mapping
|
||||||
|
if (!deviceQuad->isFinite()) {
|
||||||
|
for (int i = 0; i < 4; ++i) {
|
||||||
|
if (!make_vertex_finite(deviceQuad->xs() + i) ||
|
||||||
|
!make_vertex_finite(deviceQuad->ys() + i) ||
|
||||||
|
!make_vertex_finite(deviceQuad->ws() + i)) {
|
||||||
|
// Discard if we see a nan
|
||||||
|
return QuadOptimization::kDiscarded;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SkASSERT(deviceQuad->isFinite());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// CropToRect requires the quads to be finite. If they are not finite and we have local
|
||||||
|
// coordinates, the mapping from local space to device space is poorly defined so drop it
|
||||||
|
if (!deviceQuad->isFinite()) {
|
||||||
|
return QuadOptimization::kDiscarded;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the quad is entirely off screen, it doesn't matter what the clip does
|
// If the quad is entirely off screen, it doesn't matter what the clip does
|
||||||
|
@ -100,6 +100,18 @@ public:
|
|||||||
return {min(x), min(y), max(x), max(y)};
|
return {min(x), min(y), max(x), max(y)};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isFinite() const {
|
||||||
|
// If any coordinate is infinity or NaN, then multiplying it with 0 will make accum NaN
|
||||||
|
float accum = 0;
|
||||||
|
for (int i = 0; i < 4; ++i) {
|
||||||
|
accum *= fX[i];
|
||||||
|
accum *= fY[i];
|
||||||
|
accum *= fW[i];
|
||||||
|
}
|
||||||
|
SkASSERT(0 == accum || SkScalarIsNaN(accum));
|
||||||
|
return !SkScalarIsNaN(accum);
|
||||||
|
}
|
||||||
|
|
||||||
float x(int i) const { return fX[i]; }
|
float x(int i) const { return fX[i]; }
|
||||||
float y(int i) const { return fY[i]; }
|
float y(int i) const { return fY[i]; }
|
||||||
float w(int i) const { return fW[i]; }
|
float w(int i) const { return fW[i]; }
|
||||||
|
@ -198,6 +198,8 @@ void ResolveAAType(GrAAType requestedAAType, GrQuadAAFlags requestedEdgeFlags, c
|
|||||||
|
|
||||||
bool CropToRect(const SkRect& cropRect, GrAA cropAA, GrQuadAAFlags* edgeFlags, GrQuad* quad,
|
bool CropToRect(const SkRect& cropRect, GrAA cropAA, GrQuadAAFlags* edgeFlags, GrQuad* quad,
|
||||||
GrQuad* local) {
|
GrQuad* local) {
|
||||||
|
SkASSERT(quad->isFinite());
|
||||||
|
|
||||||
if (quad->quadType() == GrQuad::Type::kAxisAligned) {
|
if (quad->quadType() == GrQuad::Type::kAxisAligned) {
|
||||||
// crop_rect keeps the rectangles as rectangles, so there's no need to modify types
|
// crop_rect keeps the rectangles as rectangles, so there's no need to modify types
|
||||||
if (local) {
|
if (local) {
|
||||||
|
@ -25,7 +25,7 @@ namespace GrQuadUtils {
|
|||||||
* Crops quad to the provided device-space axis-aligned rectangle. If the intersection of this
|
* Crops quad to the provided device-space axis-aligned rectangle. If the intersection of this
|
||||||
* quad (projected) and cropRect results in a quadrilateral, this returns true. If not, this
|
* quad (projected) and cropRect results in a quadrilateral, this returns true. If not, this
|
||||||
* quad may be updated to be a smaller quad of the same type such that its intersection with
|
* quad may be updated to be a smaller quad of the same type such that its intersection with
|
||||||
* cropRect is visually the same.
|
* cropRect is visually the same. This function assumes that the 'quad' coordinates are finite.
|
||||||
*
|
*
|
||||||
* The provided edge flags are updated to reflect edges clipped by cropRect (toggling on or off
|
* The provided edge flags are updated to reflect edges clipped by cropRect (toggling on or off
|
||||||
* based on cropAA policy). If provided, the local coordinates will be updated to reflect the
|
* based on cropAA policy). If provided, the local coordinates will be updated to reflect the
|
||||||
|
Loading…
Reference in New Issue
Block a user