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) { | |
bsalomon
2015/11/17 23:15:57
these functions are lifted and simplified from SkG
| |
61 // detect pixel disalignment | |
62 if (SkScalarAbs(SkScalarFraction(transformedRect.left())) < kColorBleedToler ance && | |
63 SkScalarAbs(SkScalarFraction(transformedRect.top())) < kColorBleedTolera nce && | |
bsalomon
2015/11/17 23:15:57
Changed this to use abs(fraction(x)) instead of ab
| |
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, | |
bsalomon
2015/11/17 23:15:57
this function is unchanged.
| |
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, | |
bsalomon
2015/11/17 23:15:57
was needs_texture_domain() in the original. That f
| |
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 |