Chromium Code Reviews| Index: src/gpu/SkGpuDevice_drawTexture.cpp |
| diff --git a/src/gpu/SkGpuDevice_drawTexture.cpp b/src/gpu/SkGpuDevice_drawTexture.cpp |
| index b41d69c6fd7aa5f690c18bb27fb4de2834235985..ccc9e2a2dd0da91dc8763c2fedee02d6e073b888 100644 |
| --- a/src/gpu/SkGpuDevice_drawTexture.cpp |
| +++ b/src/gpu/SkGpuDevice_drawTexture.cpp |
| @@ -52,7 +52,71 @@ static const GrFragmentProcessor* mix_texture_fp_with_paint_color_and_shader( |
| } |
| } |
| -void SkGpuDevice::drawTextureAdjuster(GrTextureAdjuster* adjuster, |
| +////////////////////////////////////////////////////////////////////////////// |
| +// Helper functions for dropping src rect constraint in bilerp mode. |
| + |
| +static const SkScalar kColorBleedTolerance = 0.001f; |
| + |
| +static bool has_aligned_samples(const SkRect& srcRect, const SkRect& transformedRect) { |
|
bsalomon
2015/11/17 23:15:57
these functions are lifted and simplified from SkG
|
| + // detect pixel disalignment |
| + if (SkScalarAbs(SkScalarFraction(transformedRect.left())) < kColorBleedTolerance && |
| + SkScalarAbs(SkScalarFraction(transformedRect.top())) < kColorBleedTolerance && |
|
bsalomon
2015/11/17 23:15:57
Changed this to use abs(fraction(x)) instead of ab
|
| + SkScalarAbs(transformedRect.width() - srcRect.width()) < kColorBleedTolerance && |
| + SkScalarAbs(transformedRect.height() - srcRect.height()) < kColorBleedTolerance) { |
| + return true; |
| + } |
| + return false; |
| +} |
| + |
| +static bool may_color_bleed(const SkRect& srcRect, |
|
bsalomon
2015/11/17 23:15:57
this function is unchanged.
|
| + const SkRect& transformedRect, |
| + const SkMatrix& m, |
| + bool isMSAA) { |
| + // Only gets called if has_aligned_samples returned false. |
| + // So we can assume that sampling is axis aligned but not texel aligned. |
| + SkASSERT(!has_aligned_samples(srcRect, transformedRect)); |
| + SkRect innerSrcRect(srcRect), innerTransformedRect, outerTransformedRect(transformedRect); |
| + if (isMSAA) { |
| + innerSrcRect.inset(SK_Scalar1, SK_Scalar1); |
| + } else { |
| + innerSrcRect.inset(SK_ScalarHalf, SK_ScalarHalf); |
| + } |
| + m.mapRect(&innerTransformedRect, innerSrcRect); |
| + |
| + // The gap between outerTransformedRect and innerTransformedRect |
| + // represents the projection of the source border area, which is |
| + // problematic for color bleeding. We must check whether any |
| + // destination pixels sample the border area. |
| + outerTransformedRect.inset(kColorBleedTolerance, kColorBleedTolerance); |
| + innerTransformedRect.outset(kColorBleedTolerance, kColorBleedTolerance); |
| + SkIRect outer, inner; |
| + outerTransformedRect.round(&outer); |
| + innerTransformedRect.round(&inner); |
| + // If the inner and outer rects round to the same result, it means the |
| + // border does not overlap any pixel centers. Yay! |
| + return inner != outer; |
| +} |
| + |
| +static bool can_ignore_bilerp_constraint(const GrTextureProducer& producer, |
|
bsalomon
2015/11/17 23:15:57
was needs_texture_domain() in the original. That f
|
| + const SkRect& srcRect, |
| + const SkMatrix& srcRectToDeviceSpace, |
| + bool isMSAA) { |
| + if (srcRectToDeviceSpace.rectStaysRect()) { |
| + // sampling is axis-aligned |
| + SkRect transformedRect; |
| + srcRectToDeviceSpace.mapRect(&transformedRect, srcRect); |
| + |
| + if (has_aligned_samples(srcRect, transformedRect) || |
| + !may_color_bleed(srcRect, transformedRect, srcRectToDeviceSpace, isMSAA)) { |
| + return true; |
| + } |
| + } |
| + return false; |
| +} |
| + |
| +////////////////////////////////////////////////////////////////////////////// |
| + |
| +void SkGpuDevice::drawTextureProducer(GrTextureProducer* producer, |
| bool alphaOnly, |
| const SkRect* srcRect, |
| const SkRect* dstRect, |
| @@ -65,7 +129,7 @@ void SkGpuDevice::drawTextureAdjuster(GrTextureAdjuster* adjuster, |
| // the matrix that maps the src rect to the dst rect. |
| SkRect clippedSrcRect; |
| SkRect clippedDstRect; |
| - const SkRect srcBounds = SkRect::MakeIWH(adjuster->width(), adjuster->height()); |
| + const SkRect srcBounds = SkRect::MakeIWH(producer->width(), producer->height()); |
| SkMatrix srcToDstMatrix; |
| if (srcRect) { |
| if (!dstRect) { |
| @@ -100,11 +164,11 @@ void SkGpuDevice::drawTextureAdjuster(GrTextureAdjuster* adjuster, |
| } |
| } |
| - this->drawTextureAdjusterImpl(adjuster, alphaOnly, clippedSrcRect, clippedDstRect, constraint, |
| + this->drawTextureProducerImpl(producer, alphaOnly, clippedSrcRect, clippedDstRect, constraint, |
| viewMatrix, srcToDstMatrix, clip, paint); |
| } |
| -void SkGpuDevice::drawTextureAdjusterImpl(GrTextureAdjuster* adjuster, |
| +void SkGpuDevice::drawTextureProducerImpl(GrTextureProducer* producer, |
| bool alphaTexture, |
| const SkRect& clippedSrcRect, |
| const SkRect& clippedDstRect, |
| @@ -141,6 +205,17 @@ void SkGpuDevice::drawTextureAdjusterImpl(GrTextureAdjuster* adjuster, |
| // This is conservative as a mask filter does not have to expand the bounds rendered. |
| bool coordsAllInsideSrcRect = !paint.isAntiAlias() && !mf; |
| + // Check for optimization to drop the src rect constraint when on bilerp. |
| + if (filterMode && GrTextureParams::kBilerp_FilterMode == *filterMode && |
| + GrTextureAdjuster::kYes_FilterConstraint == constraintMode && coordsAllInsideSrcRect) { |
| + SkMatrix combinedMatrix; |
| + combinedMatrix.setConcat(viewMatrix, srcToDstMatrix); |
| + if (can_ignore_bilerp_constraint(*producer, clippedSrcRect, combinedMatrix, |
| + fRenderTarget->isUnifiedMultisampled())) { |
| + constraintMode = GrTextureAdjuster::kNo_FilterConstraint; |
| + } |
| + } |
| + |
| const SkMatrix* textureMatrix; |
| SkMatrix tempMatrix; |
| if (canUseTextureCoordsAsLocalCoords) { |
| @@ -151,7 +226,7 @@ void SkGpuDevice::drawTextureAdjusterImpl(GrTextureAdjuster* adjuster, |
| } |
| textureMatrix = &tempMatrix; |
| } |
| - SkAutoTUnref<const GrFragmentProcessor> fp(adjuster->createFragmentProcessor( |
| + SkAutoTUnref<const GrFragmentProcessor> fp(producer->createFragmentProcessor( |
| *textureMatrix, clippedSrcRect, constraintMode, coordsAllInsideSrcRect, filterMode)); |
| if (!fp) { |
| return; |