OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkGpuDevice.h" | 8 #include "SkGpuDevice.h" |
9 | 9 |
10 #include "GrBlurUtils.h" | 10 #include "GrBlurUtils.h" |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
45 const GrFragmentProcessor* fpSeries[] = { shaderFP, textureFP }; | 45 const GrFragmentProcessor* fpSeries[] = { shaderFP, textureFP }; |
46 return GrFragmentProcessor::RunInSeries(fpSeries, 2); | 46 return GrFragmentProcessor::RunInSeries(fpSeries, 2); |
47 } else { | 47 } else { |
48 return GrFragmentProcessor::MulOutputByInputUnpremulColor(textureFP)
; | 48 return GrFragmentProcessor::MulOutputByInputUnpremulColor(textureFP)
; |
49 } | 49 } |
50 } else { | 50 } else { |
51 return GrFragmentProcessor::MulOutputByInputAlpha(textureFP); | 51 return GrFragmentProcessor::MulOutputByInputAlpha(textureFP); |
52 } | 52 } |
53 } | 53 } |
54 | 54 |
55 void SkGpuDevice::drawTextureAdjuster(GrTextureAdjuster* adjuster, | 55 ////////////////////////////////////////////////////////////////////////////// |
| 56 // Helper functions for dropping src rect constraint in bilerp mode. |
| 57 |
| 58 static const SkScalar kColorBleedTolerance = 0.001f; |
| 59 |
| 60 static bool has_aligned_samples(const SkRect& srcRect, const SkRect& transformed
Rect) { |
| 61 // detect pixel disalignment |
| 62 if (SkScalarAbs(SkScalarFraction(transformedRect.left())) < kColorBleedToler
ance && |
| 63 SkScalarAbs(SkScalarFraction(transformedRect.top())) < kColorBleedTolera
nce && |
| 64 SkScalarAbs(transformedRect.width() - srcRect.width()) < kColorBleedTole
rance && |
| 65 SkScalarAbs(transformedRect.height() - srcRect.height()) < kColorBleedTo
lerance) { |
| 66 return true; |
| 67 } |
| 68 return false; |
| 69 } |
| 70 |
| 71 static bool may_color_bleed(const SkRect& srcRect, |
| 72 const SkRect& transformedRect, |
| 73 const SkMatrix& m, |
| 74 bool isMSAA) { |
| 75 // Only gets called if has_aligned_samples returned false. |
| 76 // So we can assume that sampling is axis aligned but not texel aligned. |
| 77 SkASSERT(!has_aligned_samples(srcRect, transformedRect)); |
| 78 SkRect innerSrcRect(srcRect), innerTransformedRect, outerTransformedRect(tra
nsformedRect); |
| 79 if (isMSAA) { |
| 80 innerSrcRect.inset(SK_Scalar1, SK_Scalar1); |
| 81 } else { |
| 82 innerSrcRect.inset(SK_ScalarHalf, SK_ScalarHalf); |
| 83 } |
| 84 m.mapRect(&innerTransformedRect, innerSrcRect); |
| 85 |
| 86 // The gap between outerTransformedRect and innerTransformedRect |
| 87 // represents the projection of the source border area, which is |
| 88 // problematic for color bleeding. We must check whether any |
| 89 // destination pixels sample the border area. |
| 90 outerTransformedRect.inset(kColorBleedTolerance, kColorBleedTolerance); |
| 91 innerTransformedRect.outset(kColorBleedTolerance, kColorBleedTolerance); |
| 92 SkIRect outer, inner; |
| 93 outerTransformedRect.round(&outer); |
| 94 innerTransformedRect.round(&inner); |
| 95 // If the inner and outer rects round to the same result, it means the |
| 96 // border does not overlap any pixel centers. Yay! |
| 97 return inner != outer; |
| 98 } |
| 99 |
| 100 static bool can_ignore_bilerp_constraint(const GrTextureProducer& producer, |
| 101 const SkRect& srcRect, |
| 102 const SkMatrix& srcRectToDeviceSpace, |
| 103 bool isMSAA) { |
| 104 if (srcRectToDeviceSpace.rectStaysRect()) { |
| 105 // sampling is axis-aligned |
| 106 SkRect transformedRect; |
| 107 srcRectToDeviceSpace.mapRect(&transformedRect, srcRect); |
| 108 |
| 109 if (has_aligned_samples(srcRect, transformedRect) || |
| 110 !may_color_bleed(srcRect, transformedRect, srcRectToDeviceSpace, isM
SAA)) { |
| 111 return true; |
| 112 } |
| 113 } |
| 114 return false; |
| 115 } |
| 116 |
| 117 ////////////////////////////////////////////////////////////////////////////// |
| 118 |
| 119 void SkGpuDevice::drawTextureProducer(GrTextureProducer* producer, |
56 bool alphaOnly, | 120 bool alphaOnly, |
57 const SkRect* srcRect, | 121 const SkRect* srcRect, |
58 const SkRect* dstRect, | 122 const SkRect* dstRect, |
59 SkCanvas::SrcRectConstraint constraint, | 123 SkCanvas::SrcRectConstraint constraint, |
60 const SkMatrix& viewMatrix, | 124 const SkMatrix& viewMatrix, |
61 const GrClip& clip, | 125 const GrClip& clip, |
62 const SkPaint& paint) { | 126 const SkPaint& paint) { |
63 // Figure out the actual dst and src rect by clipping the src rect to the bo
unds of the | 127 // Figure out the actual dst and src rect by clipping the src rect to the bo
unds of the |
64 // adjuster. If the src rect is clipped then the dst rect must be recomputed
. Also determine | 128 // adjuster. If the src rect is clipped then the dst rect must be recomputed
. Also determine |
65 // the matrix that maps the src rect to the dst rect. | 129 // the matrix that maps the src rect to the dst rect. |
66 SkRect clippedSrcRect; | 130 SkRect clippedSrcRect; |
67 SkRect clippedDstRect; | 131 SkRect clippedDstRect; |
68 const SkRect srcBounds = SkRect::MakeIWH(adjuster->width(), adjuster->height
()); | 132 const SkRect srcBounds = SkRect::MakeIWH(producer->width(), producer->height
()); |
69 SkMatrix srcToDstMatrix; | 133 SkMatrix srcToDstMatrix; |
70 if (srcRect) { | 134 if (srcRect) { |
71 if (!dstRect) { | 135 if (!dstRect) { |
72 dstRect = &srcBounds; | 136 dstRect = &srcBounds; |
73 } | 137 } |
74 if (!srcBounds.contains(*srcRect)) { | 138 if (!srcBounds.contains(*srcRect)) { |
75 clippedSrcRect = *srcRect; | 139 clippedSrcRect = *srcRect; |
76 if (!clippedSrcRect.intersect(srcBounds)) { | 140 if (!clippedSrcRect.intersect(srcBounds)) { |
77 return; | 141 return; |
78 } | 142 } |
(...skipping 14 matching lines...) Expand all Loading... |
93 clippedDstRect = *dstRect; | 157 clippedDstRect = *dstRect; |
94 if (!srcToDstMatrix.setRectToRect(srcBounds, *dstRect, SkMatrix::kFi
ll_ScaleToFit)) { | 158 if (!srcToDstMatrix.setRectToRect(srcBounds, *dstRect, SkMatrix::kFi
ll_ScaleToFit)) { |
95 return; | 159 return; |
96 } | 160 } |
97 } else { | 161 } else { |
98 clippedDstRect = srcBounds; | 162 clippedDstRect = srcBounds; |
99 srcToDstMatrix.reset(); | 163 srcToDstMatrix.reset(); |
100 } | 164 } |
101 } | 165 } |
102 | 166 |
103 this->drawTextureAdjusterImpl(adjuster, alphaOnly, clippedSrcRect, clippedDs
tRect, constraint, | 167 this->drawTextureProducerImpl(producer, alphaOnly, clippedSrcRect, clippedDs
tRect, constraint, |
104 viewMatrix, srcToDstMatrix, clip, paint); | 168 viewMatrix, srcToDstMatrix, clip, paint); |
105 } | 169 } |
106 | 170 |
107 void SkGpuDevice::drawTextureAdjusterImpl(GrTextureAdjuster* adjuster, | 171 void SkGpuDevice::drawTextureProducerImpl(GrTextureProducer* producer, |
108 bool alphaTexture, | 172 bool alphaTexture, |
109 const SkRect& clippedSrcRect, | 173 const SkRect& clippedSrcRect, |
110 const SkRect& clippedDstRect, | 174 const SkRect& clippedDstRect, |
111 SkCanvas::SrcRectConstraint constraint
, | 175 SkCanvas::SrcRectConstraint constraint
, |
112 const SkMatrix& viewMatrix, | 176 const SkMatrix& viewMatrix, |
113 const SkMatrix& srcToDstMatrix, | 177 const SkMatrix& srcToDstMatrix, |
114 const GrClip& clip, | 178 const GrClip& clip, |
115 const SkPaint& paint) { | 179 const SkPaint& paint) { |
116 // Specifying the texture coords as local coordinates is an attempt to enabl
e more batching | 180 // Specifying the texture coords as local coordinates is an attempt to enabl
e more batching |
117 // by not baking anything about the srcRect, dstRect, or viewMatrix, into th
e texture FP. In | 181 // by not baking anything about the srcRect, dstRect, or viewMatrix, into th
e texture FP. In |
(...skipping 16 matching lines...) Expand all Loading... |
134 constraintMode = GrTextureAdjuster::kNo_FilterConstraint; | 198 constraintMode = GrTextureAdjuster::kNo_FilterConstraint; |
135 } else { | 199 } else { |
136 constraintMode = GrTextureAdjuster::kYes_FilterConstraint; | 200 constraintMode = GrTextureAdjuster::kYes_FilterConstraint; |
137 } | 201 } |
138 | 202 |
139 // If we have to outset for AA then we will generate texture coords outside
the src rect. The | 203 // If we have to outset for AA then we will generate texture coords outside
the src rect. The |
140 // same happens for any mask filter that extends the bounds rendered in the
dst. | 204 // same happens for any mask filter that extends the bounds rendered in the
dst. |
141 // This is conservative as a mask filter does not have to expand the bounds
rendered. | 205 // This is conservative as a mask filter does not have to expand the bounds
rendered. |
142 bool coordsAllInsideSrcRect = !paint.isAntiAlias() && !mf; | 206 bool coordsAllInsideSrcRect = !paint.isAntiAlias() && !mf; |
143 | 207 |
| 208 // Check for optimization to drop the src rect constraint when on bilerp. |
| 209 if (filterMode && GrTextureParams::kBilerp_FilterMode == *filterMode && |
| 210 GrTextureAdjuster::kYes_FilterConstraint == constraintMode && coordsAllI
nsideSrcRect) { |
| 211 SkMatrix combinedMatrix; |
| 212 combinedMatrix.setConcat(viewMatrix, srcToDstMatrix); |
| 213 if (can_ignore_bilerp_constraint(*producer, clippedSrcRect, combinedMatr
ix, |
| 214 fRenderTarget->isUnifiedMultisampled())
) { |
| 215 constraintMode = GrTextureAdjuster::kNo_FilterConstraint; |
| 216 } |
| 217 } |
| 218 |
144 const SkMatrix* textureMatrix; | 219 const SkMatrix* textureMatrix; |
145 SkMatrix tempMatrix; | 220 SkMatrix tempMatrix; |
146 if (canUseTextureCoordsAsLocalCoords) { | 221 if (canUseTextureCoordsAsLocalCoords) { |
147 textureMatrix = &SkMatrix::I(); | 222 textureMatrix = &SkMatrix::I(); |
148 } else { | 223 } else { |
149 if (!srcToDstMatrix.invert(&tempMatrix)) { | 224 if (!srcToDstMatrix.invert(&tempMatrix)) { |
150 return; | 225 return; |
151 } | 226 } |
152 textureMatrix = &tempMatrix; | 227 textureMatrix = &tempMatrix; |
153 } | 228 } |
154 SkAutoTUnref<const GrFragmentProcessor> fp(adjuster->createFragmentProcessor
( | 229 SkAutoTUnref<const GrFragmentProcessor> fp(producer->createFragmentProcessor
( |
155 *textureMatrix, clippedSrcRect, constraintMode, coordsAllInsideSrcRect,
filterMode)); | 230 *textureMatrix, clippedSrcRect, constraintMode, coordsAllInsideSrcRect,
filterMode)); |
156 if (!fp) { | 231 if (!fp) { |
157 return; | 232 return; |
158 } | 233 } |
159 fp.reset(mix_texture_fp_with_paint_color_and_shader(fp, alphaTexture, this->
context(), | 234 fp.reset(mix_texture_fp_with_paint_color_and_shader(fp, alphaTexture, this->
context(), |
160 viewMatrix, paint)); | 235 viewMatrix, paint)); |
161 GrPaint grPaint; | 236 GrPaint grPaint; |
162 if (!SkPaintToGrPaintReplaceShader(fContext, paint, fp, &grPaint)) { | 237 if (!SkPaintToGrPaintReplaceShader(fContext, paint, fp, &grPaint)) { |
163 return; | 238 return; |
164 } | 239 } |
(...skipping 20 matching lines...) Expand all Loading... |
185 rec, | 260 rec, |
186 rrect)) { | 261 rrect)) { |
187 return; | 262 return; |
188 } | 263 } |
189 SkPath rectPath; | 264 SkPath rectPath; |
190 rectPath.addRect(clippedDstRect); | 265 rectPath.addRect(clippedDstRect); |
191 GrBlurUtils::drawPathWithMaskFilter(this->context(), fDrawContext, fRenderTa
rget, fClip, | 266 GrBlurUtils::drawPathWithMaskFilter(this->context(), fDrawContext, fRenderTa
rget, fClip, |
192 rectPath, &grPaint, viewMatrix, mf, pain
t.getPathEffect(), | 267 rectPath, &grPaint, viewMatrix, mf, pain
t.getPathEffect(), |
193 GrStrokeInfo::FillInfo()); | 268 GrStrokeInfo::FillInfo()); |
194 } | 269 } |
OLD | NEW |