OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 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 "SkGpuBlurUtils.h" | 8 #include "SkGpuBlurUtils.h" |
9 | 9 |
10 #include "SkRect.h" | 10 #include "SkRect.h" |
11 | 11 |
12 #if SK_SUPPORT_GPU | 12 #if SK_SUPPORT_GPU |
13 #include "effects/GrConvolutionEffect.h" | 13 #include "effects/GrConvolutionEffect.h" |
14 #include "effects/GrMatrixConvolutionEffect.h" | 14 #include "effects/GrMatrixConvolutionEffect.h" |
15 #include "GrContext.h" | 15 #include "GrContext.h" |
16 #include "GrCaps.h" | 16 #include "GrCaps.h" |
17 #include "GrDrawContext.h" | 17 #include "GrDrawContext.h" |
18 #endif | |
19 | |
20 namespace SkGpuBlurUtils { | |
21 | |
22 #if SK_SUPPORT_GPU | |
23 | 18 |
24 #define MAX_BLUR_SIGMA 4.0f | 19 #define MAX_BLUR_SIGMA 4.0f |
25 | 20 |
26 static void scale_rect(SkRect* rect, float xScale, float yScale) { | 21 static void scale_irect_roundout(SkIRect* rect, float xScale, float yScale) { |
27 rect->fLeft = SkScalarMul(rect->fLeft, xScale); | 22 rect->fLeft = SkScalarFloorToInt(SkScalarMul(rect->fLeft, xScale)); |
28 rect->fTop = SkScalarMul(rect->fTop, yScale); | 23 rect->fTop = SkScalarFloorToInt(SkScalarMul(rect->fTop, yScale)); |
29 rect->fRight = SkScalarMul(rect->fRight, xScale); | 24 rect->fRight = SkScalarCeilToInt(SkScalarMul(rect->fRight, xScale)); |
30 rect->fBottom = SkScalarMul(rect->fBottom, yScale); | 25 rect->fBottom = SkScalarCeilToInt(SkScalarMul(rect->fBottom, yScale)); |
| 26 } |
| 27 |
| 28 static void scale_irect(SkIRect* rect, int xScale, int yScale) { |
| 29 rect->fLeft *= xScale; |
| 30 rect->fTop *= yScale; |
| 31 rect->fRight *= xScale; |
| 32 rect->fBottom *= yScale; |
| 33 } |
| 34 |
| 35 #ifdef SK_DEBUG |
| 36 static inline int is_even(int x) { return !(x & 1); } |
| 37 #endif |
| 38 |
| 39 static void shrink_irect_by_2(SkIRect* rect, bool xAxis, bool yAxis) { |
| 40 if (xAxis) { |
| 41 SkASSERT(is_even(rect->fLeft) && is_even(rect->fRight)); |
| 42 rect->fLeft /= 2; |
| 43 rect->fRight /= 2; |
| 44 } |
| 45 if (yAxis) { |
| 46 SkASSERT(is_even(rect->fTop) && is_even(rect->fBottom)); |
| 47 rect->fTop /= 2; |
| 48 rect->fBottom /= 2; |
| 49 } |
31 } | 50 } |
32 | 51 |
33 static float adjust_sigma(float sigma, int maxTextureSize, int *scaleFactor, int
*radius) { | 52 static float adjust_sigma(float sigma, int maxTextureSize, int *scaleFactor, int
*radius) { |
34 *scaleFactor = 1; | 53 *scaleFactor = 1; |
35 while (sigma > MAX_BLUR_SIGMA) { | 54 while (sigma > MAX_BLUR_SIGMA) { |
36 *scaleFactor *= 2; | 55 *scaleFactor *= 2; |
37 sigma *= 0.5f; | 56 sigma *= 0.5f; |
38 if (*scaleFactor > maxTextureSize) { | 57 if (*scaleFactor > maxTextureSize) { |
39 *scaleFactor = maxTextureSize; | 58 *scaleFactor = maxTextureSize; |
40 sigma = MAX_BLUR_SIGMA; | 59 sigma = MAX_BLUR_SIGMA; |
41 } | 60 } |
42 } | 61 } |
43 *radius = static_cast<int>(ceilf(sigma * 3.0f)); | 62 *radius = static_cast<int>(ceilf(sigma * 3.0f)); |
44 SkASSERT(*radius <= GrConvolutionEffect::kMaxKernelRadius); | 63 SkASSERT(*radius <= GrConvolutionEffect::kMaxKernelRadius); |
45 return sigma; | 64 return sigma; |
46 } | 65 } |
47 | 66 |
48 static void convolve_gaussian_1d(GrDrawContext* drawContext, | 67 static void convolve_gaussian_1d(GrDrawContext* drawContext, |
49 const GrClip& clip, | 68 const GrClip& clip, |
50 const SkRect& dstRect, | 69 const SkIRect& dstRect, |
51 const SkPoint& srcOffset, | 70 const SkIPoint& srcOffset, |
52 GrTexture* texture, | 71 GrTexture* texture, |
53 Gr1DKernelEffect::Direction direction, | 72 Gr1DKernelEffect::Direction direction, |
54 int radius, | 73 int radius, |
55 float sigma, | 74 float sigma, |
56 bool useBounds, | 75 bool useBounds, |
57 float bounds[2]) { | 76 float bounds[2]) { |
58 GrPaint paint; | 77 GrPaint paint; |
59 paint.setGammaCorrect(drawContext->isGammaCorrect()); | 78 paint.setGammaCorrect(drawContext->isGammaCorrect()); |
60 SkAutoTUnref<GrFragmentProcessor> conv(GrConvolutionEffect::CreateGaussian( | 79 SkAutoTUnref<GrFragmentProcessor> conv(GrConvolutionEffect::CreateGaussian( |
61 texture, direction, radius, sigma, useBounds, bounds)); | 80 texture, direction, radius, sigma, useBounds, bounds)); |
62 paint.addColorFragmentProcessor(conv); | 81 paint.addColorFragmentProcessor(conv); |
63 paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); | 82 paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); |
64 SkMatrix localMatrix = SkMatrix::MakeTrans(-srcOffset.x(), -srcOffset.y()); | 83 SkMatrix localMatrix = SkMatrix::MakeTrans(-SkIntToScalar(srcOffset.x()), |
65 drawContext->fillRectWithLocalMatrix(clip, paint, SkMatrix::I(), dstRect, lo
calMatrix); | 84 -SkIntToScalar(srcOffset.y())); |
| 85 drawContext->fillRectWithLocalMatrix(clip, paint, SkMatrix::I(), |
| 86 SkRect::Make(dstRect), localMatrix); |
66 } | 87 } |
67 | 88 |
68 static void convolve_gaussian_2d(GrDrawContext* drawContext, | 89 static void convolve_gaussian_2d(GrDrawContext* drawContext, |
69 const GrClip& clip, | 90 const GrClip& clip, |
70 const SkRect& dstRect, | 91 const SkIRect& dstRect, |
71 const SkPoint& srcOffset, | 92 const SkIPoint& srcOffset, |
72 GrTexture* texture, | 93 GrTexture* texture, |
73 int radiusX, | 94 int radiusX, |
74 int radiusY, | 95 int radiusY, |
75 SkScalar sigmaX, | 96 SkScalar sigmaX, |
76 SkScalar sigmaY, | 97 SkScalar sigmaY, |
77 const SkRect* srcBounds) { | 98 const SkIRect* srcBounds) { |
78 SkMatrix localMatrix = SkMatrix::MakeTrans(-srcOffset.x(), -srcOffset.y()); | 99 SkMatrix localMatrix = SkMatrix::MakeTrans(-SkIntToScalar(srcOffset.x()), |
| 100 -SkIntToScalar(srcOffset.y())); |
79 SkISize size = SkISize::Make(2 * radiusX + 1, 2 * radiusY + 1); | 101 SkISize size = SkISize::Make(2 * radiusX + 1, 2 * radiusY + 1); |
80 SkIPoint kernelOffset = SkIPoint::Make(radiusX, radiusY); | 102 SkIPoint kernelOffset = SkIPoint::Make(radiusX, radiusY); |
81 GrPaint paint; | 103 GrPaint paint; |
82 paint.setGammaCorrect(drawContext->isGammaCorrect()); | 104 paint.setGammaCorrect(drawContext->isGammaCorrect()); |
83 SkIRect bounds; | 105 SkIRect bounds = srcBounds ? *srcBounds : SkIRect::EmptyIRect(); |
84 if (srcBounds) { | |
85 srcBounds->roundOut(&bounds); | |
86 } else { | |
87 bounds.setEmpty(); | |
88 } | |
89 | 106 |
90 SkAutoTUnref<GrFragmentProcessor> conv(GrMatrixConvolutionEffect::CreateGaus
sian( | 107 SkAutoTUnref<GrFragmentProcessor> conv(GrMatrixConvolutionEffect::CreateGaus
sian( |
91 texture, bounds, size, 1.0, 0.0, kernelOffset, | 108 texture, bounds, size, 1.0, 0.0, kernelOffset, |
92 srcBounds ? GrTextureDomain::kDecal_Mode : GrTextureDomain::kIgnore_
Mode, | 109 srcBounds ? GrTextureDomain::kDecal_Mode : GrTextureDomain::kIgnore_
Mode, |
93 true, sigmaX, sigmaY)); | 110 true, sigmaX, sigmaY)); |
94 paint.addColorFragmentProcessor(conv); | 111 paint.addColorFragmentProcessor(conv); |
95 paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); | 112 paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); |
96 drawContext->fillRectWithLocalMatrix(clip, paint, SkMatrix::I(), dstRect, lo
calMatrix); | 113 drawContext->fillRectWithLocalMatrix(clip, paint, SkMatrix::I(), |
| 114 SkRect::Make(dstRect), localMatrix); |
97 } | 115 } |
98 | 116 |
99 static void convolve_gaussian(GrDrawContext* drawContext, | 117 static void convolve_gaussian(GrDrawContext* drawContext, |
100 const GrClip& clip, | 118 const GrClip& clip, |
101 const SkRect& srcRect, | 119 const SkIRect& srcRect, |
102 GrTexture* texture, | 120 GrTexture* texture, |
103 Gr1DKernelEffect::Direction direction, | 121 Gr1DKernelEffect::Direction direction, |
104 int radius, | 122 int radius, |
105 float sigma, | 123 float sigma, |
106 const SkRect* srcBounds, | 124 const SkIRect* srcBounds, |
107 const SkPoint& srcOffset) { | 125 const SkIPoint& srcOffset) { |
108 float bounds[2] = { 0.0f, 1.0f }; | 126 float bounds[2] = { 0.0f, 1.0f }; |
109 SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height()); | 127 SkIRect dstRect = SkIRect::MakeWH(srcRect.width(), srcRect.height()); |
110 if (!srcBounds) { | 128 if (!srcBounds) { |
111 convolve_gaussian_1d(drawContext, clip, dstRect, srcOffset, texture, | 129 convolve_gaussian_1d(drawContext, clip, dstRect, srcOffset, texture, |
112 direction, radius, sigma, false, bounds); | 130 direction, radius, sigma, false, bounds); |
113 return; | 131 return; |
114 } | 132 } |
115 SkRect midRect = *srcBounds, leftRect, rightRect; | 133 SkIRect midRect = *srcBounds, leftRect, rightRect; |
116 midRect.offset(srcOffset); | 134 midRect.offset(srcOffset); |
117 SkIRect topRect, bottomRect; | 135 SkIRect topRect, bottomRect; |
118 SkScalar rad = SkIntToScalar(radius); | |
119 if (direction == Gr1DKernelEffect::kX_Direction) { | 136 if (direction == Gr1DKernelEffect::kX_Direction) { |
120 bounds[0] = SkScalarToFloat(srcBounds->left()) / texture->width(); | 137 bounds[0] = SkIntToFloat(srcBounds->left()) / texture->width(); |
121 bounds[1] = SkScalarToFloat(srcBounds->right()) / texture->width(); | 138 bounds[1] = SkIntToFloat(srcBounds->right()) / texture->width(); |
122 SkRect::MakeLTRB(0, 0, dstRect.right(), midRect.top()).roundOut(&topRect
); | 139 topRect = SkIRect::MakeLTRB(0, 0, dstRect.right(), midRect.top()); |
123 SkRect::MakeLTRB(0, midRect.bottom(), dstRect.right(), dstRect.bottom()) | 140 bottomRect = SkIRect::MakeLTRB(0, midRect.bottom(), dstRect.right(), dst
Rect.bottom()); |
124 .roundOut(&bottomRect); | 141 midRect.inset(radius, 0); |
125 midRect.inset(rad, 0); | 142 leftRect = SkIRect::MakeLTRB(0, midRect.top(), midRect.left(), midRect.b
ottom()); |
126 leftRect = SkRect::MakeLTRB(0, midRect.top(), midRect.left(), midRect.bo
ttom()); | |
127 rightRect = | 143 rightRect = |
128 SkRect::MakeLTRB(midRect.right(), midRect.top(), dstRect.width(), mi
dRect.bottom()); | 144 SkIRect::MakeLTRB(midRect.right(), midRect.top(), dstRect.width(), m
idRect.bottom()); |
129 dstRect.fTop = midRect.top(); | 145 dstRect.fTop = midRect.top(); |
130 dstRect.fBottom = midRect.bottom(); | 146 dstRect.fBottom = midRect.bottom(); |
131 } else { | 147 } else { |
132 bounds[0] = SkScalarToFloat(srcBounds->top()) / texture->height(); | 148 bounds[0] = SkIntToFloat(srcBounds->top()) / texture->height(); |
133 bounds[1] = SkScalarToFloat(srcBounds->bottom()) / texture->height(); | 149 bounds[1] = SkIntToFloat(srcBounds->bottom()) / texture->height(); |
134 SkRect::MakeLTRB(0, 0, midRect.left(), dstRect.bottom()).roundOut(&topRe
ct); | 150 topRect = SkIRect::MakeLTRB(0, 0, midRect.left(), dstRect.bottom()); |
135 SkRect::MakeLTRB(midRect.right(), 0, dstRect.right(), dstRect.bottom()) | 151 bottomRect = SkIRect::MakeLTRB(midRect.right(), 0, dstRect.right(), dstR
ect.bottom()); |
136 .roundOut(&bottomRect);; | 152 midRect.inset(0, radius); |
137 midRect.inset(0, rad); | 153 leftRect = SkIRect::MakeLTRB(midRect.left(), 0, midRect.right(), midRect
.top()); |
138 leftRect = SkRect::MakeLTRB(midRect.left(), 0, midRect.right(), midRect.
top()); | |
139 rightRect = | 154 rightRect = |
140 SkRect::MakeLTRB(midRect.left(), midRect.bottom(), midRect.right(),
dstRect.height()); | 155 SkIRect::MakeLTRB(midRect.left(), midRect.bottom(), midRect.right(),
dstRect.height()); |
141 dstRect.fLeft = midRect.left(); | 156 dstRect.fLeft = midRect.left(); |
142 dstRect.fRight = midRect.right(); | 157 dstRect.fRight = midRect.right(); |
143 } | 158 } |
144 if (!topRect.isEmpty()) { | 159 if (!topRect.isEmpty()) { |
145 drawContext->clear(&topRect, 0, false); | 160 drawContext->clear(&topRect, 0, false); |
146 } | 161 } |
147 | 162 |
148 if (!bottomRect.isEmpty()) { | 163 if (!bottomRect.isEmpty()) { |
149 drawContext->clear(&bottomRect, 0, false); | 164 drawContext->clear(&bottomRect, 0, false); |
150 } | 165 } |
151 if (midRect.isEmpty()) { | 166 if (midRect.isEmpty()) { |
152 // Blur radius covers srcBounds; use bounds over entire draw | 167 // Blur radius covers srcBounds; use bounds over entire draw |
153 convolve_gaussian_1d(drawContext, clip, dstRect, srcOffset, texture, | 168 convolve_gaussian_1d(drawContext, clip, dstRect, srcOffset, texture, |
154 direction, radius, sigma, true, bounds); | 169 direction, radius, sigma, true, bounds); |
155 } else { | 170 } else { |
156 // Draw right and left margins with bounds; middle without. | 171 // Draw right and left margins with bounds; middle without. |
157 convolve_gaussian_1d(drawContext, clip, leftRect, srcOffset, texture, | 172 convolve_gaussian_1d(drawContext, clip, leftRect, srcOffset, texture, |
158 direction, radius, sigma, true, bounds); | 173 direction, radius, sigma, true, bounds); |
159 convolve_gaussian_1d(drawContext, clip, rightRect, srcOffset, texture, | 174 convolve_gaussian_1d(drawContext, clip, rightRect, srcOffset, texture, |
160 direction, radius, sigma, true, bounds); | 175 direction, radius, sigma, true, bounds); |
161 convolve_gaussian_1d(drawContext, clip, midRect, srcOffset, texture, | 176 convolve_gaussian_1d(drawContext, clip, midRect, srcOffset, texture, |
162 direction, radius, sigma, false, bounds); | 177 direction, radius, sigma, false, bounds); |
163 } | 178 } |
164 } | 179 } |
165 | 180 |
| 181 namespace SkGpuBlurUtils { |
| 182 |
166 sk_sp<GrDrawContext> GaussianBlur(GrContext* context, | 183 sk_sp<GrDrawContext> GaussianBlur(GrContext* context, |
167 GrTexture* srcTexture, | 184 GrTexture* srcTexture, |
168 bool gammaCorrect, | 185 bool gammaCorrect, |
169 const SkRect& dstBounds, | 186 const SkIRect& dstBounds, |
170 const SkRect* srcBounds, | 187 const SkIRect* srcBounds, |
171 float sigmaX, | 188 float sigmaX, |
172 float sigmaY) { | 189 float sigmaY) { |
173 SkASSERT(context); | 190 SkASSERT(context); |
174 SkIRect clearRect; | 191 SkIRect clearRect; |
175 int scaleFactorX, radiusX; | 192 int scaleFactorX, radiusX; |
176 int scaleFactorY, radiusY; | 193 int scaleFactorY, radiusY; |
177 int maxTextureSize = context->caps()->maxTextureSize(); | 194 int maxTextureSize = context->caps()->maxTextureSize(); |
178 sigmaX = adjust_sigma(sigmaX, maxTextureSize, &scaleFactorX, &radiusX); | 195 sigmaX = adjust_sigma(sigmaX, maxTextureSize, &scaleFactorX, &radiusX); |
179 sigmaY = adjust_sigma(sigmaY, maxTextureSize, &scaleFactorY, &radiusY); | 196 sigmaY = adjust_sigma(sigmaY, maxTextureSize, &scaleFactorY, &radiusY); |
| 197 SkASSERT(sigmaX || sigmaY); |
180 | 198 |
181 SkPoint srcOffset = SkPoint::Make(-dstBounds.x(), -dstBounds.y()); | 199 SkIPoint srcOffset = SkIPoint::Make(-dstBounds.x(), -dstBounds.y()); |
182 SkRect localDstBounds = SkRect::MakeWH(dstBounds.width(), dstBounds.height()
); | 200 SkIRect localDstBounds = SkIRect::MakeWH(dstBounds.width(), dstBounds.height
()); |
183 SkRect localSrcBounds; | 201 SkIRect localSrcBounds; |
184 SkRect srcRect; | 202 SkIRect srcRect; |
185 if (srcBounds) { | 203 if (srcBounds) { |
186 srcRect = localSrcBounds = *srcBounds; | 204 srcRect = localSrcBounds = *srcBounds; |
187 srcRect.offset(srcOffset); | 205 srcRect.offset(srcOffset); |
188 srcBounds = &localSrcBounds; | 206 srcBounds = &localSrcBounds; |
189 } else { | 207 } else { |
190 srcRect = localDstBounds; | 208 srcRect = localDstBounds; |
191 } | 209 } |
192 | 210 |
193 scale_rect(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY); | 211 scale_irect_roundout(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY); |
194 srcRect.roundOut(&srcRect); | 212 scale_irect(&srcRect, scaleFactorX, scaleFactorY); |
195 scale_rect(&srcRect, static_cast<float>(scaleFactorX), | |
196 static_cast<float>(scaleFactorY)); | |
197 | 213 |
198 // setup new clip | 214 // setup new clip |
199 GrClip clip(localDstBounds); | 215 GrClip clip(localDstBounds); |
200 | 216 |
201 SkASSERT(kBGRA_8888_GrPixelConfig == srcTexture->config() || | 217 SkASSERT(kBGRA_8888_GrPixelConfig == srcTexture->config() || |
202 kRGBA_8888_GrPixelConfig == srcTexture->config() || | 218 kRGBA_8888_GrPixelConfig == srcTexture->config() || |
203 kSRGBA_8888_GrPixelConfig == srcTexture->config() || | 219 kSRGBA_8888_GrPixelConfig == srcTexture->config() || |
204 kSBGRA_8888_GrPixelConfig == srcTexture->config() || | 220 kSBGRA_8888_GrPixelConfig == srcTexture->config() || |
205 kAlpha_8_GrPixelConfig == srcTexture->config()); | 221 kAlpha_8_GrPixelConfig == srcTexture->config()); |
206 | 222 |
207 const int width = SkScalarFloorToInt(dstBounds.width()); | 223 const int width = dstBounds.width(); |
208 const int height = SkScalarFloorToInt(dstBounds.height()); | 224 const int height = dstBounds.height(); |
209 const GrPixelConfig config = srcTexture->config(); | 225 const GrPixelConfig config = srcTexture->config(); |
210 | 226 |
211 const SkSurfaceProps props(gammaCorrect ? SkSurfaceProps::kGammaCorrect_Flag
: 0, | 227 const SkSurfaceProps props(gammaCorrect ? SkSurfaceProps::kGammaCorrect_Flag
: 0, |
212 SkSurfaceProps::kLegacyFontHost_InitType); | 228 SkSurfaceProps::kLegacyFontHost_InitType); |
213 | 229 |
214 sk_sp<GrDrawContext> dstDrawContext(context->newDrawContext(SkBackingFit::kA
pprox, | 230 sk_sp<GrDrawContext> dstDrawContext(context->newDrawContext(SkBackingFit::kA
pprox, |
215 width, height, c
onfig, | 231 width, height, c
onfig, |
216 0, kDefault_GrSu
rfaceOrigin, | 232 0, kDefault_GrSu
rfaceOrigin, |
217 &props)); | 233 &props)); |
218 if (!dstDrawContext) { | 234 if (!dstDrawContext) { |
(...skipping 16 matching lines...) Expand all Loading... |
235 sk_sp<GrDrawContext> tmpDrawContext(context->newDrawContext(SkBackingFit::kA
pprox, | 251 sk_sp<GrDrawContext> tmpDrawContext(context->newDrawContext(SkBackingFit::kA
pprox, |
236 width, height, c
onfig, | 252 width, height, c
onfig, |
237 0, kDefault_GrSu
rfaceOrigin, | 253 0, kDefault_GrSu
rfaceOrigin, |
238 &props)); | 254 &props)); |
239 if (!tmpDrawContext) { | 255 if (!tmpDrawContext) { |
240 return nullptr; | 256 return nullptr; |
241 } | 257 } |
242 | 258 |
243 sk_sp<GrDrawContext> srcDrawContext; | 259 sk_sp<GrDrawContext> srcDrawContext; |
244 | 260 |
| 261 SkASSERT(SkIsPow2(scaleFactorX) && SkIsPow2(scaleFactorY)); |
| 262 |
245 for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) { | 263 for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) { |
246 GrPaint paint; | 264 GrPaint paint; |
247 paint.setGammaCorrect(gammaCorrect); | 265 paint.setGammaCorrect(gammaCorrect); |
248 SkMatrix matrix; | 266 SkMatrix matrix; |
249 matrix.setIDiv(srcTexture->width(), srcTexture->height()); | 267 matrix.setIDiv(srcTexture->width(), srcTexture->height()); |
250 SkRect dstRect(srcRect); | 268 SkIRect dstRect(srcRect); |
251 if (srcBounds && i == 1) { | 269 if (srcBounds && i == 1) { |
252 SkRect domain; | 270 SkRect domain; |
253 matrix.mapRect(&domain, *srcBounds); | 271 matrix.mapRect(&domain, SkRect::Make(*srcBounds)); |
254 domain.inset((i < scaleFactorX) ? SK_ScalarHalf / srcTexture->width(
) : 0.0f, | 272 domain.inset((i < scaleFactorX) ? SK_ScalarHalf / srcTexture->width(
) : 0.0f, |
255 (i < scaleFactorY) ? SK_ScalarHalf / srcTexture->height
() : 0.0f); | 273 (i < scaleFactorY) ? SK_ScalarHalf / srcTexture->height
() : 0.0f); |
256 sk_sp<const GrFragmentProcessor> fp(GrTextureDomainEffect::Create( | 274 sk_sp<const GrFragmentProcessor> fp(GrTextureDomainEffect::Create( |
257 srcTexture, | 275 srcTexture, |
258 matrix, | 276 matrix, |
259 domain, | 277 domain, |
260 GrTextureDomain::kDecal_
Mode, | 278 GrTextureDomain::kDecal_
Mode, |
261 GrTextureParams::kBilerp
_FilterMode)); | 279 GrTextureParams::kBilerp
_FilterMode)); |
262 paint.addColorFragmentProcessor(fp.get()); | 280 paint.addColorFragmentProcessor(fp.get()); |
263 srcRect.offset(-srcOffset); | 281 srcRect.offset(-srcOffset); |
264 srcOffset.set(0, 0); | 282 srcOffset.set(0, 0); |
265 } else { | 283 } else { |
266 GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::k
Bilerp_FilterMode); | 284 GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::k
Bilerp_FilterMode); |
267 paint.addColorTextureProcessor(srcTexture, matrix, params); | 285 paint.addColorTextureProcessor(srcTexture, matrix, params); |
268 } | 286 } |
269 paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); | 287 paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); |
270 scale_rect(&dstRect, i < scaleFactorX ? 0.5f : 1.0f, | 288 shrink_irect_by_2(&dstRect, i < scaleFactorX, i < scaleFactorY); |
271 i < scaleFactorY ? 0.5f : 1.0f); | |
272 | 289 |
273 dstDrawContext->fillRectToRect(clip, paint, SkMatrix::I(), dstRect, srcR
ect); | 290 dstDrawContext->fillRectToRect(clip, paint, SkMatrix::I(), |
| 291 SkRect::Make(dstRect), SkRect::Make(srcRe
ct)); |
274 | 292 |
275 srcDrawContext = dstDrawContext; | 293 srcDrawContext = dstDrawContext; |
276 srcRect = dstRect; | 294 srcRect = dstRect; |
277 srcTexture = srcDrawContext->asTexture().release(); | 295 srcTexture = srcDrawContext->asTexture().release(); |
278 SkTSwap(dstDrawContext, tmpDrawContext); | 296 SkTSwap(dstDrawContext, tmpDrawContext); |
279 localSrcBounds = srcRect; | 297 localSrcBounds = srcRect; |
280 } | 298 } |
281 | 299 |
282 srcRect = localDstBounds; | 300 srcRect = localDstBounds; |
283 | 301 scale_irect_roundout(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY); |
284 scale_rect(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY); | |
285 srcRect.roundOut(&srcRect); | |
286 SkIRect srcIRect = srcRect.roundOut(); | |
287 if (sigmaX > 0.0f) { | 302 if (sigmaX > 0.0f) { |
288 if (scaleFactorX > 1) { | 303 if (scaleFactorX > 1) { |
289 SkASSERT(srcDrawContext); | 304 SkASSERT(srcDrawContext); |
290 | 305 |
291 // Clear out a radius to the right of the srcRect to prevent the | 306 // Clear out a radius to the right of the srcRect to prevent the |
292 // X convolution from reading garbage. | 307 // X convolution from reading garbage. |
293 clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop, | 308 clearRect = SkIRect::MakeXYWH(srcRect.fRight, srcRect.fTop, |
294 radiusX, srcIRect.height()); | 309 radiusX, srcRect.height()); |
295 srcDrawContext->clear(&clearRect, 0x0, false); | 310 srcDrawContext->clear(&clearRect, 0x0, false); |
296 } | 311 } |
297 | 312 |
298 convolve_gaussian(dstDrawContext.get(), clip, srcRect, | 313 convolve_gaussian(dstDrawContext.get(), clip, srcRect, |
299 srcTexture, Gr1DKernelEffect::kX_Direction, radiusX, s
igmaX, | 314 srcTexture, Gr1DKernelEffect::kX_Direction, radiusX, s
igmaX, |
300 srcBounds, srcOffset); | 315 srcBounds, srcOffset); |
301 srcDrawContext = dstDrawContext; | 316 srcDrawContext = dstDrawContext; |
302 srcTexture = srcDrawContext->asTexture().release(); | 317 srcTexture = srcDrawContext->asTexture().release(); |
303 srcRect.offsetTo(0, 0); | 318 srcRect.offsetTo(0, 0); |
304 SkTSwap(dstDrawContext, tmpDrawContext); | 319 SkTSwap(dstDrawContext, tmpDrawContext); |
305 localSrcBounds = srcRect; | 320 localSrcBounds = srcRect; |
306 srcOffset.set(0, 0); | 321 srcOffset.set(0, 0); |
307 } | 322 } |
308 | 323 |
309 if (sigmaY > 0.0f) { | 324 if (sigmaY > 0.0f) { |
310 if (scaleFactorY > 1 || sigmaX > 0.0f) { | 325 if (scaleFactorY > 1 || sigmaX > 0.0f) { |
311 SkASSERT(srcDrawContext); | 326 SkASSERT(srcDrawContext); |
312 | 327 |
313 // Clear out a radius below the srcRect to prevent the Y | 328 // Clear out a radius below the srcRect to prevent the Y |
314 // convolution from reading garbage. | 329 // convolution from reading garbage. |
315 clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom, | 330 clearRect = SkIRect::MakeXYWH(srcRect.fLeft, srcRect.fBottom, |
316 srcIRect.width(), radiusY); | 331 srcRect.width(), radiusY); |
317 srcDrawContext->clear(&clearRect, 0x0, false); | 332 srcDrawContext->clear(&clearRect, 0x0, false); |
318 } | 333 } |
319 | 334 |
320 convolve_gaussian(dstDrawContext.get(), clip, srcRect, | 335 convolve_gaussian(dstDrawContext.get(), clip, srcRect, |
321 srcTexture, Gr1DKernelEffect::kY_Direction, radiusY, s
igmaY, | 336 srcTexture, Gr1DKernelEffect::kY_Direction, radiusY, s
igmaY, |
322 srcBounds, srcOffset); | 337 srcBounds, srcOffset); |
323 | 338 |
324 srcDrawContext = dstDrawContext; | 339 srcDrawContext = dstDrawContext; |
325 srcRect.offsetTo(0, 0); | 340 srcRect.offsetTo(0, 0); |
326 SkTSwap(dstDrawContext, tmpDrawContext); | 341 SkTSwap(dstDrawContext, tmpDrawContext); |
327 } | 342 } |
328 | 343 |
329 SkASSERT(srcDrawContext); | 344 SkASSERT(srcDrawContext); |
330 srcTexture = nullptr; // we don't use this from here on out | 345 srcTexture = nullptr; // we don't use this from here on out |
331 srcIRect = srcRect.roundOut(); | |
332 | 346 |
333 if (scaleFactorX > 1 || scaleFactorY > 1) { | 347 if (scaleFactorX > 1 || scaleFactorY > 1) { |
334 // Clear one pixel to the right and below, to accommodate bilinear upsam
pling. | 348 // Clear one pixel to the right and below, to accommodate bilinear upsam
pling. |
335 clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom, srcIRect
.width() + 1, 1); | 349 clearRect = SkIRect::MakeXYWH(srcRect.fLeft, srcRect.fBottom, srcRect.wi
dth() + 1, 1); |
336 srcDrawContext->clear(&clearRect, 0x0, false); | 350 srcDrawContext->clear(&clearRect, 0x0, false); |
337 clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop, 1, srcIRec
t.height()); | 351 clearRect = SkIRect::MakeXYWH(srcRect.fRight, srcRect.fTop, 1, srcRect.h
eight()); |
338 srcDrawContext->clear(&clearRect, 0x0, false); | 352 srcDrawContext->clear(&clearRect, 0x0, false); |
339 | 353 |
340 SkMatrix matrix; | 354 SkMatrix matrix; |
341 matrix.setIDiv(srcDrawContext->width(), srcDrawContext->height()); | 355 matrix.setIDiv(srcDrawContext->width(), srcDrawContext->height()); |
342 | 356 |
343 GrPaint paint; | 357 GrPaint paint; |
344 paint.setGammaCorrect(gammaCorrect); | 358 paint.setGammaCorrect(gammaCorrect); |
345 // FIXME: this should be mitchell, not bilinear. | 359 // FIXME: this should be mitchell, not bilinear. |
346 GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBile
rp_FilterMode); | 360 GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBile
rp_FilterMode); |
347 paint.addColorTextureProcessor(srcDrawContext->asTexture().release(), ma
trix, params); | 361 paint.addColorTextureProcessor(srcDrawContext->asTexture().release(), ma
trix, params); |
348 paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); | 362 paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); |
349 | 363 |
350 SkRect dstRect(srcRect); | 364 SkIRect dstRect(srcRect); |
351 scale_rect(&dstRect, (float) scaleFactorX, (float) scaleFactorY); | 365 scale_irect(&dstRect, scaleFactorX, scaleFactorY); |
352 | 366 |
353 dstDrawContext->fillRectToRect(clip, paint, SkMatrix::I(), dstRect, srcR
ect); | 367 dstDrawContext->fillRectToRect(clip, paint, SkMatrix::I(), |
| 368 SkRect::Make(dstRect), SkRect::Make(srcRe
ct)); |
354 | 369 |
355 srcDrawContext = dstDrawContext; | 370 srcDrawContext = dstDrawContext; |
356 srcRect = dstRect; | 371 srcRect = dstRect; |
357 SkTSwap(dstDrawContext, tmpDrawContext); | 372 SkTSwap(dstDrawContext, tmpDrawContext); |
358 } | 373 } |
359 | 374 |
360 return srcDrawContext; | 375 return srcDrawContext; |
361 } | 376 } |
| 377 |
| 378 } |
| 379 |
362 #endif | 380 #endif |
363 | 381 |
364 } | |
OLD | NEW |