Chromium Code Reviews| Index: src/gpu/SkGpuDevice.cpp |
| diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp |
| index 4af16109a4b6df1481c65ce98306277f732ce5ca..a767f4dfc34262fc71b728865a6d46ba03a8e66b 100644 |
| --- a/src/gpu/SkGpuDevice.cpp |
| +++ b/src/gpu/SkGpuDevice.cpp |
| @@ -1137,6 +1137,74 @@ static inline void clamped_outset_with_offset(SkIRect* iRect, |
| } |
| } |
| +static bool has_aligned_samples(const SkRect& srcRect, |
| + const SkRect& transformedRect) { |
| + // detect pixel disalignment |
| + if (SkScalarAbs(SkScalarRoundToScalar(transformedRect.left()) - |
| + transformedRect.left()) < COLOR_BLEED_TOLERANCE && |
| + SkScalarAbs(SkScalarRoundToScalar(transformedRect.top()) - |
| + transformedRect.top()) < COLOR_BLEED_TOLERANCE && |
| + SkScalarAbs(transformedRect.width() - srcRect.width()) < |
| + COLOR_BLEED_TOLERANCE && |
| + SkScalarAbs(transformedRect.height() - srcRect.height()) < |
| + COLOR_BLEED_TOLERANCE) { |
| + return true; |
| + } |
| + return false; |
| +} |
| + |
| +static bool may_color_bleed(const SkRect& srcRect, |
| + const SkRect& transformedRect, |
| + const SkMatrix& m) { |
| + // 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); |
| + 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(COLOR_BLEED_TOLERANCE, COLOR_BLEED_TOLERANCE); |
| + innerTransformedRect.outset(COLOR_BLEED_TOLERANCE, COLOR_BLEED_TOLERANCE); |
| + 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; |
| +} |
| + |
| +bool SkGpuDevice::needsTextureDomain(const SkBitmap& bitmap, |
| + const SkRect& srcRect, |
| + GrTextureParams ¶ms, |
| + bool bicubic) { |
| + bool needsTextureDomain = false; |
| + |
| + if (bicubic || params.filterMode() != GrTextureParams::kNone_FilterMode) { |
| + // Need texture domain if drawing a sub rect |
| + needsTextureDomain = srcRect.width() < bitmap.width() || |
| + srcRect.height() < bitmap.height(); |
| + if (!bicubic && needsTextureDomain && fContext->getMatrix().rectStaysRect()) { |
| + const SkMatrix& matrix = fContext->getMatrix(); |
|
bsalomon
2014/05/08 14:13:23
Is accessing the matrix the only reason why this i
|
| + // sampling is axis-aligned |
| + SkRect transformedRect; |
| + matrix.mapRect(&transformedRect, srcRect); |
| + |
| + if (has_aligned_samples(srcRect, transformedRect)) { |
| + params.setFilterMode(GrTextureParams::kNone_FilterMode); |
| + needsTextureDomain = false; |
| + } else { |
| + needsTextureDomain = may_color_bleed(srcRect, transformedRect, matrix); |
| + } |
| + } |
| + } |
| + return needsTextureDomain; |
| +} |
| + |
| void SkGpuDevice::drawBitmapCommon(const SkDraw& draw, |
| const SkBitmap& bitmap, |
| const SkRect* srcRectPtr, |
| @@ -1275,7 +1343,14 @@ void SkGpuDevice::drawBitmapCommon(const SkDraw& draw, |
| doBicubic); |
| } else { |
| // take the simple case |
| - this->internalDrawBitmap(bitmap, srcRect, params, paint, flags, doBicubic); |
| + bool needsTextureDomain = this->needsTextureDomain(bitmap, srcRect, params, doBicubic); |
| + this->internalDrawBitmap(bitmap, |
| + srcRect, |
| + params, |
| + paint, |
| + flags, |
| + doBicubic, |
| + needsTextureDomain); |
| } |
| } |
| @@ -1341,54 +1416,23 @@ void SkGpuDevice::drawTiledBitmap(const SkBitmap& bitmap, |
| if (bitmap.extractSubset(&tmpB, iTileR)) { |
| // now offset it to make it "local" to our tmp bitmap |
| tileR.offset(-offset.fX, -offset.fY); |
| - |
| - this->internalDrawBitmap(tmpB, tileR, params, paint, flags, bicubic); |
| + GrTextureParams paramsTemp = params; |
| + bool needsTextureDomain = this->needsTextureDomain(bitmap, |
| + srcRect, |
| + paramsTemp, |
| + bicubic); |
| + this->internalDrawBitmap(tmpB, |
| + tileR, |
| + paramsTemp, |
| + paint, |
| + flags, |
| + bicubic, |
| + needsTextureDomain); |
| } |
| } |
| } |
| } |
| -static bool has_aligned_samples(const SkRect& srcRect, |
| - const SkRect& transformedRect) { |
| - // detect pixel disalignment |
| - if (SkScalarAbs(SkScalarRoundToScalar(transformedRect.left()) - |
| - transformedRect.left()) < COLOR_BLEED_TOLERANCE && |
| - SkScalarAbs(SkScalarRoundToScalar(transformedRect.top()) - |
| - transformedRect.top()) < COLOR_BLEED_TOLERANCE && |
| - SkScalarAbs(transformedRect.width() - srcRect.width()) < |
| - COLOR_BLEED_TOLERANCE && |
| - SkScalarAbs(transformedRect.height() - srcRect.height()) < |
| - COLOR_BLEED_TOLERANCE) { |
| - return true; |
| - } |
| - return false; |
| -} |
| - |
| -static bool may_color_bleed(const SkRect& srcRect, |
| - const SkRect& transformedRect, |
| - const SkMatrix& m) { |
| - // 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); |
| - 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(COLOR_BLEED_TOLERANCE, COLOR_BLEED_TOLERANCE); |
| - innerTransformedRect.outset(COLOR_BLEED_TOLERANCE, COLOR_BLEED_TOLERANCE); |
| - 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; |
| -} |
| - |
| /* |
| * This is called by drawBitmap(), which has to handle images that may be too |
| @@ -1402,7 +1446,8 @@ void SkGpuDevice::internalDrawBitmap(const SkBitmap& bitmap, |
| const GrTextureParams& params, |
| const SkPaint& paint, |
| SkCanvas::DrawBitmapRectFlags flags, |
| - bool bicubic) { |
| + bool bicubic, |
| + bool needsTextureDomain) { |
| SkASSERT(bitmap.width() <= fContext->getMaxTextureSize() && |
| bitmap.height() <= fContext->getMaxTextureSize()); |
| @@ -1421,31 +1466,9 @@ void SkGpuDevice::internalDrawBitmap(const SkBitmap& bitmap, |
| SkScalarMul(srcRect.fRight, wInv), |
| SkScalarMul(srcRect.fBottom, hInv)); |
| - bool needsTextureDomain = false; |
| - if (!(flags & SkCanvas::kBleed_DrawBitmapRectFlag) && |
| - (bicubic || params.filterMode() != GrTextureParams::kNone_FilterMode)) { |
| - // Need texture domain if drawing a sub rect |
| - needsTextureDomain = srcRect.width() < bitmap.width() || |
| - srcRect.height() < bitmap.height(); |
| - if (!bicubic && needsTextureDomain && fContext->getMatrix().rectStaysRect()) { |
| - const SkMatrix& matrix = fContext->getMatrix(); |
| - // sampling is axis-aligned |
| - SkRect transformedRect; |
| - matrix.mapRect(&transformedRect, srcRect); |
| - |
| - if (has_aligned_samples(srcRect, transformedRect)) { |
| - // We could also turn off filtering here (but we already did a cache lookup with |
| - // params). |
| - needsTextureDomain = false; |
| - } else { |
| - needsTextureDomain = may_color_bleed(srcRect, transformedRect, matrix); |
| - } |
| - } |
| - } |
| - |
| SkRect textureDomain = SkRect::MakeEmpty(); |
| SkAutoTUnref<GrEffectRef> effect; |
| - if (needsTextureDomain) { |
| + if (needsTextureDomain && !(flags & SkCanvas::kBleed_DrawBitmapRectFlag)) { |
| // Use a constrained texture domain to avoid color bleeding |
| SkScalar left, top, right, bottom; |
| if (srcRect.width() > SK_Scalar1) { |