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" |
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
222 kRGBA_8888_GrPixelConfig == srcTexture->config() || | 222 kRGBA_8888_GrPixelConfig == srcTexture->config() || |
223 kSRGBA_8888_GrPixelConfig == srcTexture->config() || | 223 kSRGBA_8888_GrPixelConfig == srcTexture->config() || |
224 kSBGRA_8888_GrPixelConfig == srcTexture->config() || | 224 kSBGRA_8888_GrPixelConfig == srcTexture->config() || |
225 kRGBA_half_GrPixelConfig == srcTexture->config() || | 225 kRGBA_half_GrPixelConfig == srcTexture->config() || |
226 kAlpha_8_GrPixelConfig == srcTexture->config()); | 226 kAlpha_8_GrPixelConfig == srcTexture->config()); |
227 | 227 |
228 const int width = dstBounds.width(); | 228 const int width = dstBounds.width(); |
229 const int height = dstBounds.height(); | 229 const int height = dstBounds.height(); |
230 const GrPixelConfig config = srcTexture->config(); | 230 const GrPixelConfig config = srcTexture->config(); |
231 | 231 |
232 sk_sp<GrRenderTargetContext> dstRenderTargetContext(context->makeRenderTarge
tContext( | 232 sk_sp<GrRenderTargetContext> dstRenderTargetContext(context->makeDeferredRen
derTargetContext( |
233 fit, width, height, config, colorSpace, 0, kDefault_GrSurfaceOrigin)); | 233 fit, width, height, config, colorSpace, 0, kDefault_GrSurfaceOrigin)); |
234 if (!dstRenderTargetContext) { | 234 if (!dstRenderTargetContext) { |
235 return nullptr; | 235 return nullptr; |
236 } | 236 } |
237 | 237 |
238 // For really small blurs (certainly no wider than 5x5 on desktop gpus) it i
s faster to just | 238 // For really small blurs (certainly no wider than 5x5 on desktop gpus) it i
s faster to just |
239 // launch a single non separable kernel vs two launches | 239 // launch a single non separable kernel vs two launches |
240 if (sigmaX > 0.0f && sigmaY > 0.0f && | 240 if (sigmaX > 0.0f && sigmaY > 0.0f && |
241 (2 * radiusX + 1) * (2 * radiusY + 1) <= MAX_KERNEL_SIZE) { | 241 (2 * radiusX + 1) * (2 * radiusY + 1) <= MAX_KERNEL_SIZE) { |
242 // We shouldn't be scaling because this is a small size blur | 242 // We shouldn't be scaling because this is a small size blur |
243 SkASSERT((1 == scaleFactorX) && (1 == scaleFactorY)); | 243 SkASSERT((1 == scaleFactorX) && (1 == scaleFactorY)); |
244 | 244 |
245 convolve_gaussian_2d(dstRenderTargetContext.get(), clip, localDstBounds,
srcOffset, | 245 convolve_gaussian_2d(dstRenderTargetContext.get(), clip, localDstBounds,
srcOffset, |
246 srcTexture.get(), radiusX, radiusY, sigmaX, sigmaY,
srcBounds); | 246 srcTexture.get(), radiusX, radiusY, sigmaX, sigmaY,
srcBounds); |
247 | 247 |
248 return dstRenderTargetContext; | 248 return dstRenderTargetContext; |
249 } | 249 } |
250 | 250 |
251 sk_sp<GrRenderTargetContext> tmpRenderTargetContext(context->makeRenderTarge
tContext( | 251 sk_sp<GrRenderTargetContext> tmpRenderTargetContext(context->makeDeferredRen
derTargetContext( |
252 fit, width, height, config, colorSpace, 0, kDefault_GrSurfaceOrigin)); | 252 fit, width, height, config, colorSpace, 0, kDefault_GrSurfaceOrigin)); |
253 if (!tmpRenderTargetContext) { | 253 if (!tmpRenderTargetContext) { |
254 return nullptr; | 254 return nullptr; |
255 } | 255 } |
256 | 256 |
257 sk_sp<GrRenderTargetContext> srcRenderTargetContext; | 257 sk_sp<GrRenderTargetContext> srcRenderTargetContext; |
258 | 258 |
259 SkASSERT(SkIsPow2(scaleFactorX) && SkIsPow2(scaleFactorY)); | 259 SkASSERT(SkIsPow2(scaleFactorX) && SkIsPow2(scaleFactorY)); |
260 | 260 |
261 for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) { | 261 for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) { |
262 GrPaint paint; | 262 GrPaint paint; |
263 paint.setGammaCorrect(dstRenderTargetContext->isGammaCorrect()); | 263 paint.setGammaCorrect(dstRenderTargetContext->isGammaCorrect()); |
| 264 // TODO: this matrix relies on the final instantiated size of the textur
e. This |
| 265 // will have to be deferred for TextureProxys |
264 SkMatrix matrix; | 266 SkMatrix matrix; |
265 matrix.setIDiv(srcTexture->width(), srcTexture->height()); | 267 matrix.setIDiv(srcTexture->width(), srcTexture->height()); |
266 SkIRect dstRect(srcRect); | 268 SkIRect dstRect(srcRect); |
267 if (srcBounds && i == 1) { | 269 if (srcBounds && i == 1) { |
268 SkRect domain; | 270 SkRect domain; |
269 matrix.mapRect(&domain, SkRect::Make(*srcBounds)); | 271 matrix.mapRect(&domain, SkRect::Make(*srcBounds)); |
270 domain.inset((i < scaleFactorX) ? SK_ScalarHalf / srcTexture->width(
) : 0.0f, | 272 domain.inset((i < scaleFactorX) ? SK_ScalarHalf / srcTexture->width(
) : 0.0f, |
271 (i < scaleFactorY) ? SK_ScalarHalf / srcTexture->height
() : 0.0f); | 273 (i < scaleFactorY) ? SK_ScalarHalf / srcTexture->height
() : 0.0f); |
272 sk_sp<GrFragmentProcessor> fp(GrTextureDomainEffect::Make( | 274 sk_sp<GrFragmentProcessor> fp(GrTextureDomainEffect::Make( |
273 srcTexture.get(), | 275 srcTexture.get(), |
(...skipping 11 matching lines...) Expand all Loading... |
285 } | 287 } |
286 paint.setPorterDuffXPFactory(SkBlendMode::kSrc); | 288 paint.setPorterDuffXPFactory(SkBlendMode::kSrc); |
287 shrink_irect_by_2(&dstRect, i < scaleFactorX, i < scaleFactorY); | 289 shrink_irect_by_2(&dstRect, i < scaleFactorX, i < scaleFactorY); |
288 | 290 |
289 dstRenderTargetContext->fillRectToRect(clip, paint, SkMatrix::I(), | 291 dstRenderTargetContext->fillRectToRect(clip, paint, SkMatrix::I(), |
290 SkRect::Make(dstRect), SkRect::Ma
ke(srcRect)); | 292 SkRect::Make(dstRect), SkRect::Ma
ke(srcRect)); |
291 | 293 |
292 srcRenderTargetContext = dstRenderTargetContext; | 294 srcRenderTargetContext = dstRenderTargetContext; |
293 srcRect = dstRect; | 295 srcRect = dstRect; |
294 srcTexture = srcRenderTargetContext->asTexture(); | 296 srcTexture = srcRenderTargetContext->asTexture(); |
| 297 if (!srcTexture) { |
| 298 return nullptr; |
| 299 } |
295 dstRenderTargetContext.swap(tmpRenderTargetContext); | 300 dstRenderTargetContext.swap(tmpRenderTargetContext); |
296 localSrcBounds = srcRect; | 301 localSrcBounds = srcRect; |
297 } | 302 } |
298 | 303 |
299 srcRect = localDstBounds; | 304 srcRect = localDstBounds; |
300 scale_irect_roundout(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY); | 305 scale_irect_roundout(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY); |
301 if (sigmaX > 0.0f) { | 306 if (sigmaX > 0.0f) { |
302 if (scaleFactorX > 1) { | 307 if (scaleFactorX > 1) { |
303 SkASSERT(srcRenderTargetContext); | 308 SkASSERT(srcRenderTargetContext); |
304 | 309 |
305 // Clear out a radius to the right of the srcRect to prevent the | 310 // Clear out a radius to the right of the srcRect to prevent the |
306 // X convolution from reading garbage. | 311 // X convolution from reading garbage. |
307 clearRect = SkIRect::MakeXYWH(srcRect.fRight, srcRect.fTop, | 312 clearRect = SkIRect::MakeXYWH(srcRect.fRight, srcRect.fTop, |
308 radiusX, srcRect.height()); | 313 radiusX, srcRect.height()); |
309 srcRenderTargetContext->clear(&clearRect, 0x0, false); | 314 srcRenderTargetContext->clear(&clearRect, 0x0, false); |
310 } | 315 } |
311 | 316 |
312 convolve_gaussian(dstRenderTargetContext.get(), clip, srcRect, | 317 convolve_gaussian(dstRenderTargetContext.get(), clip, srcRect, |
313 srcTexture.get(), Gr1DKernelEffect::kX_Direction, radi
usX, sigmaX, | 318 srcTexture.get(), Gr1DKernelEffect::kX_Direction, radi
usX, sigmaX, |
314 srcBounds, srcOffset); | 319 srcBounds, srcOffset); |
315 srcRenderTargetContext = dstRenderTargetContext; | 320 srcRenderTargetContext = dstRenderTargetContext; |
316 srcTexture = srcRenderTargetContext->asTexture(); | 321 srcTexture = srcRenderTargetContext->asTexture(); |
| 322 if (!srcTexture) { |
| 323 return nullptr; |
| 324 } |
317 srcRect.offsetTo(0, 0); | 325 srcRect.offsetTo(0, 0); |
318 dstRenderTargetContext.swap(tmpRenderTargetContext); | 326 dstRenderTargetContext.swap(tmpRenderTargetContext); |
319 localSrcBounds = srcRect; | 327 localSrcBounds = srcRect; |
320 srcOffset.set(0, 0); | 328 srcOffset.set(0, 0); |
321 } | 329 } |
322 | 330 |
323 if (sigmaY > 0.0f) { | 331 if (sigmaY > 0.0f) { |
324 if (scaleFactorY > 1 || sigmaX > 0.0f) { | 332 if (scaleFactorY > 1 || sigmaX > 0.0f) { |
325 SkASSERT(srcRenderTargetContext); | 333 SkASSERT(srcRenderTargetContext); |
326 | 334 |
(...skipping 16 matching lines...) Expand all Loading... |
343 SkASSERT(srcRenderTargetContext); | 351 SkASSERT(srcRenderTargetContext); |
344 srcTexture = nullptr; // we don't use this from here on out | 352 srcTexture = nullptr; // we don't use this from here on out |
345 | 353 |
346 if (scaleFactorX > 1 || scaleFactorY > 1) { | 354 if (scaleFactorX > 1 || scaleFactorY > 1) { |
347 // Clear one pixel to the right and below, to accommodate bilinear upsam
pling. | 355 // Clear one pixel to the right and below, to accommodate bilinear upsam
pling. |
348 clearRect = SkIRect::MakeXYWH(srcRect.fLeft, srcRect.fBottom, srcRect.wi
dth() + 1, 1); | 356 clearRect = SkIRect::MakeXYWH(srcRect.fLeft, srcRect.fBottom, srcRect.wi
dth() + 1, 1); |
349 srcRenderTargetContext->clear(&clearRect, 0x0, false); | 357 srcRenderTargetContext->clear(&clearRect, 0x0, false); |
350 clearRect = SkIRect::MakeXYWH(srcRect.fRight, srcRect.fTop, 1, srcRect.h
eight()); | 358 clearRect = SkIRect::MakeXYWH(srcRect.fRight, srcRect.fTop, 1, srcRect.h
eight()); |
351 srcRenderTargetContext->clear(&clearRect, 0x0, false); | 359 srcRenderTargetContext->clear(&clearRect, 0x0, false); |
352 | 360 |
353 SkMatrix matrix; | |
354 matrix.setIDiv(srcRenderTargetContext->width(), srcRenderTargetContext->
height()); | |
355 | |
356 GrPaint paint; | 361 GrPaint paint; |
357 paint.setGammaCorrect(dstRenderTargetContext->isGammaCorrect()); | 362 paint.setGammaCorrect(dstRenderTargetContext->isGammaCorrect()); |
358 // FIXME: this should be mitchell, not bilinear. | 363 // FIXME: this should be mitchell, not bilinear. |
359 GrSamplerParams params(SkShader::kClamp_TileMode, GrSamplerParams::kBile
rp_FilterMode); | 364 GrSamplerParams params(SkShader::kClamp_TileMode, GrSamplerParams::kBile
rp_FilterMode); |
360 sk_sp<GrTexture> tex(srcRenderTargetContext->asTexture()); | 365 sk_sp<GrTexture> tex(srcRenderTargetContext->asTexture()); |
| 366 if (!tex) { |
| 367 return nullptr; |
| 368 } |
| 369 |
| 370 // TODO: this matrix relies on the final instantiated size of the textur
e. This |
| 371 // will have to be deferred for TextureProxys |
| 372 SkMatrix matrix; |
| 373 matrix.setIDiv(tex->width(), tex->height()); |
| 374 |
361 paint.addColorTextureProcessor(tex.get(), nullptr, matrix, params); | 375 paint.addColorTextureProcessor(tex.get(), nullptr, matrix, params); |
362 paint.setPorterDuffXPFactory(SkBlendMode::kSrc); | 376 paint.setPorterDuffXPFactory(SkBlendMode::kSrc); |
363 | 377 |
364 SkIRect dstRect(srcRect); | 378 SkIRect dstRect(srcRect); |
365 scale_irect(&dstRect, scaleFactorX, scaleFactorY); | 379 scale_irect(&dstRect, scaleFactorX, scaleFactorY); |
366 | 380 |
367 dstRenderTargetContext->fillRectToRect(clip, paint, SkMatrix::I(), | 381 dstRenderTargetContext->fillRectToRect(clip, paint, SkMatrix::I(), |
368 SkRect::Make(dstRect), SkRect::Ma
ke(srcRect)); | 382 SkRect::Make(dstRect), SkRect::Ma
ke(srcRect)); |
369 | 383 |
370 srcRenderTargetContext = dstRenderTargetContext; | 384 srcRenderTargetContext = dstRenderTargetContext; |
371 srcRect = dstRect; | 385 srcRect = dstRect; |
372 dstRenderTargetContext.swap(tmpRenderTargetContext); | 386 dstRenderTargetContext.swap(tmpRenderTargetContext); |
373 } | 387 } |
374 | 388 |
375 return srcRenderTargetContext; | 389 return srcRenderTargetContext; |
376 } | 390 } |
377 | 391 |
378 } | 392 } |
379 | 393 |
380 #endif | 394 #endif |
381 | 395 |
OLD | NEW |