| 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 |