SkCanvas::kStrict_SrcRectConstraint disables mipmapping.
The implementation is inconsistent across CPU and GPU. CPU currently always implements kStrict even when kFast is passed. For mipmapping this means computing a set of levels from the subset, which is an expensive. GPU limits the texture sampling coordinates to the subset in the base level. However, higher level mipmap pixels that map back to a footprint outside the subset are still sampled. So GPU pays a higher shader complexity cost without really providing the benefit of kStrict. We are adding anisotropic filtering, which will not work well with kStrict, and thus will also be disabled by kStrict. Must land after https://chromium-review.googlesource.com/c/chromium/src/+/3571661 Bug: skia:10481 Bug: skia:13078 Bug: skia:13036 Canary-Chromium-CL: 3571661 Change-Id: I011b8698a3f9fafa9b819486873c8ff54df6299e Reviewed-on: https://skia-review.googlesource.com/c/skia/+/527284 Reviewed-by: Michael Ludwig <michaelludwig@google.com> Commit-Queue: Brian Salomon <bsalomon@google.com>
This commit is contained in:
parent
44832b292d
commit
072e09b26d
@ -9,6 +9,13 @@ Milestone 102
|
|||||||
* GrContextOptions::fSharpenMipmappedTextures is removed. MIP LOD is now always
|
* GrContextOptions::fSharpenMipmappedTextures is removed. MIP LOD is now always
|
||||||
biased on the GPU backend. The CPU backend implementation is modified to match
|
biased on the GPU backend. The CPU backend implementation is modified to match
|
||||||
this behavior.
|
this behavior.
|
||||||
|
* Passing SkCanvas::kStrict_SrcRectConstraint disables mipmapping. The old behavior differed
|
||||||
|
between GPU and CPU. CPU always computed a new set of mipmap based on the subset. GPU restricted
|
||||||
|
the sampling coordinates to the subset in the base level but upper level pixels that map to
|
||||||
|
pixels outside the subset in the base level were still used. To get the previous CPU behavior
|
||||||
|
use SkImage::makeSubset() to make a subset image and draw that. The previous GPU behavior is
|
||||||
|
similar, though not exactly, equivalent to making a mipmapped image shader from the original
|
||||||
|
image and applying that to a rectangle.
|
||||||
|
|
||||||
* * *
|
* * *
|
||||||
|
|
||||||
|
@ -1445,6 +1445,7 @@ public:
|
|||||||
SrcRectConstraint controls the behavior at the edge of source SkRect,
|
SrcRectConstraint controls the behavior at the edge of source SkRect,
|
||||||
provided to drawImageRect() when there is any filtering. If kStrict is set,
|
provided to drawImageRect() when there is any filtering. If kStrict is set,
|
||||||
then extra code is used to ensure it nevers samples outside of the src-rect.
|
then extra code is used to ensure it nevers samples outside of the src-rect.
|
||||||
|
kStrict_SrcRectConstraint disables the use of mipmaps.
|
||||||
*/
|
*/
|
||||||
enum SrcRectConstraint {
|
enum SrcRectConstraint {
|
||||||
kStrict_SrcRectConstraint, //!< sample only inside bounds; slower
|
kStrict_SrcRectConstraint, //!< sample only inside bounds; slower
|
||||||
|
@ -2253,14 +2253,40 @@ void SkCanvas::onDrawImage2(const SkImage* image, SkScalar x, SkScalar y,
|
|||||||
auto layer = this->aboutToDraw(this, realPaint, &bounds);
|
auto layer = this->aboutToDraw(this, realPaint, &bounds);
|
||||||
if (layer) {
|
if (layer) {
|
||||||
this->topDevice()->drawImageRect(image, nullptr, bounds, sampling,
|
this->topDevice()->drawImageRect(image, nullptr, bounds, sampling,
|
||||||
layer->paint(), kStrict_SrcRectConstraint);
|
layer->paint(), kFast_SrcRectConstraint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static SkSamplingOptions clean_sampling_for_constraint(
|
||||||
|
const SkSamplingOptions& sampling,
|
||||||
|
SkCanvas::SrcRectConstraint constraint) {
|
||||||
|
#if !defined(SK_LEGACY_ALLOW_STRICT_CONSTRAINT_MIPMAPPING)
|
||||||
|
if (constraint == SkCanvas::kStrict_SrcRectConstraint &&
|
||||||
|
sampling.mipmap != SkMipmapMode::kNone) {
|
||||||
|
return SkSamplingOptions(sampling.filter);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return sampling;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SkCanvas::SrcRectConstraint clean_constraint_for_image_bounds(
|
||||||
|
SkCanvas::SrcRectConstraint constraint,
|
||||||
|
const SkRect& src,
|
||||||
|
const SkImage* image) {
|
||||||
|
#if defined(SK_DISABLE_STRICT_CONSTRAINT_FOR_ENTIRE_IMAGE)
|
||||||
|
if (constraint == SkCanvas::kStrict_SrcRectConstraint && src.contains(image->bounds())) {
|
||||||
|
return SkCanvas::kFast_SrcRectConstraint;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return constraint;
|
||||||
|
}
|
||||||
|
|
||||||
void SkCanvas::onDrawImageRect2(const SkImage* image, const SkRect& src, const SkRect& dst,
|
void SkCanvas::onDrawImageRect2(const SkImage* image, const SkRect& src, const SkRect& dst,
|
||||||
const SkSamplingOptions& sampling, const SkPaint* paint,
|
const SkSamplingOptions& sampling, const SkPaint* paint,
|
||||||
SrcRectConstraint constraint) {
|
SrcRectConstraint constraint) {
|
||||||
SkPaint realPaint = clean_paint_for_drawImage(paint);
|
SkPaint realPaint = clean_paint_for_drawImage(paint);
|
||||||
|
constraint = clean_constraint_for_image_bounds(constraint, src, image);
|
||||||
|
SkSamplingOptions realSampling = clean_sampling_for_constraint(sampling, constraint);
|
||||||
|
|
||||||
if (this->internalQuickReject(dst, realPaint)) {
|
if (this->internalQuickReject(dst, realPaint)) {
|
||||||
return;
|
return;
|
||||||
@ -2270,7 +2296,7 @@ void SkCanvas::onDrawImageRect2(const SkImage* image, const SkRect& src, const S
|
|||||||
image->isOpaque() ? kOpaque_ShaderOverrideOpacity
|
image->isOpaque() ? kOpaque_ShaderOverrideOpacity
|
||||||
: kNotOpaque_ShaderOverrideOpacity);
|
: kNotOpaque_ShaderOverrideOpacity);
|
||||||
if (layer) {
|
if (layer) {
|
||||||
this->topDevice()->drawImageRect(image, &src, dst, sampling, layer->paint(), constraint);
|
this->topDevice()->drawImageRect(image, &src, dst, realSampling, layer->paint(), constraint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2633,6 +2659,7 @@ void SkCanvas::onDrawEdgeAAImageSet2(const ImageSetEntry imageSet[], int count,
|
|||||||
}
|
}
|
||||||
|
|
||||||
SkPaint realPaint = clean_paint_for_drawImage(paint);
|
SkPaint realPaint = clean_paint_for_drawImage(paint);
|
||||||
|
SkSamplingOptions realSampling = clean_sampling_for_constraint(sampling, constraint);
|
||||||
|
|
||||||
// We could calculate the set's dstRect union to always check quickReject(), but we can't reject
|
// We could calculate the set's dstRect union to always check quickReject(), but we can't reject
|
||||||
// individual entries and Chromium's occlusion culling already makes it likely that at least one
|
// individual entries and Chromium's occlusion culling already makes it likely that at least one
|
||||||
@ -2662,8 +2689,8 @@ void SkCanvas::onDrawEdgeAAImageSet2(const ImageSetEntry imageSet[], int count,
|
|||||||
|
|
||||||
auto layer = this->aboutToDraw(this, realPaint, setBoundsValid ? &setBounds : nullptr);
|
auto layer = this->aboutToDraw(this, realPaint, setBoundsValid ? &setBounds : nullptr);
|
||||||
if (layer) {
|
if (layer) {
|
||||||
this->topDevice()->drawEdgeAAImageSet(imageSet, count, dstClips, preViewMatrices, sampling,
|
this->topDevice()->drawEdgeAAImageSet(imageSet, count, dstClips, preViewMatrices,
|
||||||
layer->paint(), constraint);
|
realSampling, layer->paint(), constraint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user