| 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 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 64 } | 64 } |
| 65 | 65 |
| 66 static void convolve_gaussian_2d(GrDrawContext* drawContext, | 66 static void convolve_gaussian_2d(GrDrawContext* drawContext, |
| 67 const GrClip& clip, | 67 const GrClip& clip, |
| 68 const SkRect& srcRect, | 68 const SkRect& srcRect, |
| 69 GrTexture* texture, | 69 GrTexture* texture, |
| 70 int radiusX, | 70 int radiusX, |
| 71 int radiusY, | 71 int radiusY, |
| 72 SkScalar sigmaX, | 72 SkScalar sigmaX, |
| 73 SkScalar sigmaY, | 73 SkScalar sigmaY, |
| 74 bool useBounds, | 74 const SkRect* srcBounds) { |
| 75 SkIRect bounds) { | |
| 76 SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height()); | 75 SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height()); |
| 77 SkMatrix localMatrix = SkMatrix::MakeTrans(srcRect.x(), srcRect.y()); | 76 SkMatrix localMatrix = SkMatrix::MakeTrans(srcRect.x(), srcRect.y()); |
| 78 SkISize size = SkISize::Make(2 * radiusX + 1, 2 * radiusY + 1); | 77 SkISize size = SkISize::Make(2 * radiusX + 1, 2 * radiusY + 1); |
| 79 SkIPoint kernelOffset = SkIPoint::Make(radiusX, radiusY); | 78 SkIPoint kernelOffset = SkIPoint::Make(radiusX, radiusY); |
| 80 GrPaint paint; | 79 GrPaint paint; |
| 80 SkIRect bounds; |
| 81 if (srcBounds) { |
| 82 srcBounds->roundOut(&bounds); |
| 83 } else { |
| 84 bounds.setEmpty(); |
| 85 } |
| 86 |
| 81 SkAutoTUnref<GrFragmentProcessor> conv(GrMatrixConvolutionEffect::CreateGaus
sian( | 87 SkAutoTUnref<GrFragmentProcessor> conv(GrMatrixConvolutionEffect::CreateGaus
sian( |
| 82 texture, bounds, size, 1.0, 0.0, kernelOffset, | 88 texture, bounds, size, 1.0, 0.0, kernelOffset, |
| 83 useBounds ? GrTextureDomain::kClamp_Mode : GrTextureDomain::kIgnore_
Mode, | 89 srcBounds ? GrTextureDomain::kDecal_Mode : GrTextureDomain::kIgnore_
Mode, |
| 84 true, sigmaX, sigmaY)); | 90 true, sigmaX, sigmaY)); |
| 85 paint.addColorFragmentProcessor(conv); | 91 paint.addColorFragmentProcessor(conv); |
| 86 drawContext->fillRectWithLocalMatrix(clip, paint, SkMatrix::I(), dstRect, lo
calMatrix); | 92 drawContext->fillRectWithLocalMatrix(clip, paint, SkMatrix::I(), dstRect, lo
calMatrix); |
| 87 } | 93 } |
| 88 | 94 |
| 89 static void convolve_gaussian(GrDrawContext* drawContext, | 95 static void convolve_gaussian(GrDrawContext* drawContext, |
| 90 const GrClip& clip, | 96 const GrClip& clip, |
| 91 const SkRect& srcRect, | 97 const SkRect& srcRect, |
| 92 GrTexture* texture, | 98 GrTexture* texture, |
| 93 Gr1DKernelEffect::Direction direction, | 99 Gr1DKernelEffect::Direction direction, |
| 94 int radius, | 100 int radius, |
| 95 float sigma, | 101 float sigma, |
| 96 bool cropToSrcRect) { | 102 const SkRect* srcBounds, |
| 103 const SkPoint& srcOffset) { |
| 97 float bounds[2] = { 0.0f, 1.0f }; | 104 float bounds[2] = { 0.0f, 1.0f }; |
| 98 SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height()); | 105 SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height()); |
| 99 SkPoint srcOffset = SkPoint::Make(srcRect.x(), srcRect.y()); | 106 if (!srcBounds) { |
| 100 if (!cropToSrcRect) { | |
| 101 convolve_gaussian_1d(drawContext, clip, dstRect, srcOffset, texture, | 107 convolve_gaussian_1d(drawContext, clip, dstRect, srcOffset, texture, |
| 102 direction, radius, sigma, false, bounds); | 108 direction, radius, sigma, false, bounds); |
| 103 return; | 109 return; |
| 104 } | 110 } |
| 105 SkRect lowerDstRect = dstRect; | 111 SkRect midRect = *srcBounds, leftRect, rightRect; |
| 106 SkRect middleDstRect = dstRect; | 112 midRect.offset(srcOffset); |
| 107 SkRect upperDstRect = dstRect; | 113 SkIRect topRect, bottomRect; |
| 108 SkScalar size; | |
| 109 SkScalar rad = SkIntToScalar(radius); | 114 SkScalar rad = SkIntToScalar(radius); |
| 110 if (direction == Gr1DKernelEffect::kX_Direction) { | 115 if (direction == Gr1DKernelEffect::kX_Direction) { |
| 111 bounds[0] = SkScalarToFloat(srcRect.left()) / texture->width(); | 116 bounds[0] = SkScalarToFloat(srcBounds->left()) / texture->width(); |
| 112 bounds[1] = SkScalarToFloat(srcRect.right()) / texture->width(); | 117 bounds[1] = SkScalarToFloat(srcBounds->right()) / texture->width(); |
| 113 size = dstRect.width(); | 118 SkRect::MakeLTRB(0, 0, dstRect.right(), midRect.top()).roundOut(&topRect
); |
| 114 lowerDstRect.fRight = dstRect.left() + rad; | 119 SkRect::MakeLTRB(0, midRect.bottom(), dstRect.right(), dstRect.bottom()) |
| 115 upperDstRect.fLeft = dstRect.right() - rad; | 120 .roundOut(&bottomRect); |
| 116 middleDstRect.inset(rad, 0); | 121 midRect.inset(rad, 0); |
| 122 leftRect = SkRect::MakeLTRB(0, midRect.top(), midRect.left(), midRect.bo
ttom()); |
| 123 rightRect = |
| 124 SkRect::MakeLTRB(midRect.right(), midRect.top(), dstRect.width(), mi
dRect.bottom()); |
| 125 dstRect.fTop = midRect.top(); |
| 126 dstRect.fBottom = midRect.bottom(); |
| 117 } else { | 127 } else { |
| 118 bounds[0] = SkScalarToFloat(srcRect.top()) / texture->height(); | 128 bounds[0] = SkScalarToFloat(srcBounds->top()) / texture->height(); |
| 119 bounds[1] = SkScalarToFloat(srcRect.bottom()) / texture->height(); | 129 bounds[1] = SkScalarToFloat(srcBounds->bottom()) / texture->height(); |
| 120 size = dstRect.height(); | 130 SkRect::MakeLTRB(0, 0, midRect.left(), dstRect.bottom()).roundOut(&topRe
ct); |
| 121 lowerDstRect.fBottom = dstRect.top() + rad; | 131 SkRect::MakeLTRB(midRect.right(), 0, dstRect.right(), dstRect.bottom()) |
| 122 upperDstRect.fTop = dstRect.bottom() - rad; | 132 .roundOut(&bottomRect);; |
| 123 middleDstRect.inset(0, rad); | 133 midRect.inset(0, rad); |
| 134 leftRect = SkRect::MakeLTRB(midRect.left(), 0, midRect.right(), midRect.
top()); |
| 135 rightRect = |
| 136 SkRect::MakeLTRB(midRect.left(), midRect.bottom(), midRect.right(),
dstRect.height()); |
| 137 dstRect.fLeft = midRect.left(); |
| 138 dstRect.fRight = midRect.right(); |
| 124 } | 139 } |
| 125 if (radius >= size * SK_ScalarHalf) { | 140 if (!topRect.isEmpty()) { |
| 126 // Blur radius covers srcRect; use bounds over entire draw | 141 drawContext->clear(&topRect, 0, false); |
| 127 convolve_gaussian_1d(drawContext, clip, dstRect, srcOffset, texture, | 142 } |
| 143 |
| 144 if (!bottomRect.isEmpty()) { |
| 145 drawContext->clear(&bottomRect, 0, false); |
| 146 } |
| 147 if (midRect.isEmpty()) { |
| 148 // Blur radius covers srcBounds; use bounds over entire draw |
| 149 convolve_gaussian_1d(drawContext, clip, dstRect, -srcOffset, texture, |
| 128 direction, radius, sigma, true, bounds); | 150 direction, radius, sigma, true, bounds); |
| 129 } else { | 151 } else { |
| 130 // Draw upper and lower margins with bounds; middle without. | 152 // Draw right and left margins with bounds; middle without. |
| 131 convolve_gaussian_1d(drawContext, clip, lowerDstRect, srcOffset, texture
, | 153 convolve_gaussian_1d(drawContext, clip, leftRect, -srcOffset, texture, |
| 132 direction, radius, sigma, true, bounds); | 154 direction, radius, sigma, true, bounds); |
| 133 convolve_gaussian_1d(drawContext, clip, upperDstRect, srcOffset, texture
, | 155 convolve_gaussian_1d(drawContext, clip, rightRect, -srcOffset, texture, |
| 134 direction, radius, sigma, true, bounds); | 156 direction, radius, sigma, true, bounds); |
| 135 convolve_gaussian_1d(drawContext, clip, middleDstRect, srcOffset, textur
e, | 157 convolve_gaussian_1d(drawContext, clip, midRect, -srcOffset, texture, |
| 136 direction, radius, sigma, false, bounds); | 158 direction, radius, sigma, false, bounds); |
| 137 } | 159 } |
| 138 } | 160 } |
| 139 | 161 |
| 140 GrTexture* GaussianBlur(GrContext* context, | 162 GrTexture* GaussianBlur(GrContext* context, |
| 141 GrTexture* srcTexture, | 163 GrTexture* srcTexture, |
| 142 bool canClobberSrc, | 164 bool canClobberSrc, |
| 143 const SkRect& rect, | 165 const SkRect& dstBounds, |
| 144 bool cropToRect, | 166 const SkRect* srcBounds, |
| 145 float sigmaX, | 167 float sigmaX, |
| 146 float sigmaY, | 168 float sigmaY, |
| 147 GrTextureProvider::SizeConstraint constraint) { | 169 GrTextureProvider::SizeConstraint constraint) { |
| 148 SkASSERT(context); | 170 SkASSERT(context); |
| 149 | |
| 150 SkIRect clearRect; | 171 SkIRect clearRect; |
| 151 int scaleFactorX, radiusX; | 172 int scaleFactorX, radiusX; |
| 152 int scaleFactorY, radiusY; | 173 int scaleFactorY, radiusY; |
| 153 int maxTextureSize = context->caps()->maxTextureSize(); | 174 int maxTextureSize = context->caps()->maxTextureSize(); |
| 154 sigmaX = adjust_sigma(sigmaX, maxTextureSize, &scaleFactorX, &radiusX); | 175 sigmaX = adjust_sigma(sigmaX, maxTextureSize, &scaleFactorX, &radiusX); |
| 155 sigmaY = adjust_sigma(sigmaY, maxTextureSize, &scaleFactorY, &radiusY); | 176 sigmaY = adjust_sigma(sigmaY, maxTextureSize, &scaleFactorY, &radiusY); |
| 156 | 177 |
| 157 SkRect srcRect(rect); | 178 SkPoint srcOffset = SkPoint::Make(-dstBounds.x(), -dstBounds.y()); |
| 179 SkRect localDstBounds = SkRect::MakeWH(dstBounds.width(), dstBounds.height()
); |
| 180 SkRect localSrcBounds; |
| 181 SkRect srcRect; |
| 182 if (srcBounds) { |
| 183 srcRect = localSrcBounds = *srcBounds; |
| 184 srcRect.offset(srcOffset); |
| 185 srcBounds = &localSrcBounds; |
| 186 } else { |
| 187 srcRect = localDstBounds; |
| 188 } |
| 189 |
| 158 scale_rect(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY); | 190 scale_rect(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY); |
| 159 srcRect.roundOut(&srcRect); | 191 srcRect.roundOut(&srcRect); |
| 160 scale_rect(&srcRect, static_cast<float>(scaleFactorX), | 192 scale_rect(&srcRect, static_cast<float>(scaleFactorX), |
| 161 static_cast<float>(scaleFactorY)); | 193 static_cast<float>(scaleFactorY)); |
| 162 | 194 |
| 163 // setup new clip | 195 // setup new clip |
| 164 GrClip clip(SkRect::MakeWH(srcRect.width(), srcRect.height())); | 196 GrClip clip(localDstBounds); |
| 165 | 197 |
| 166 SkASSERT(kBGRA_8888_GrPixelConfig == srcTexture->config() || | 198 SkASSERT(kBGRA_8888_GrPixelConfig == srcTexture->config() || |
| 167 kRGBA_8888_GrPixelConfig == srcTexture->config() || | 199 kRGBA_8888_GrPixelConfig == srcTexture->config() || |
| 168 kAlpha_8_GrPixelConfig == srcTexture->config()); | 200 kAlpha_8_GrPixelConfig == srcTexture->config()); |
| 169 | 201 |
| 170 GrSurfaceDesc desc; | 202 GrSurfaceDesc desc; |
| 171 desc.fFlags = kRenderTarget_GrSurfaceFlag; | 203 desc.fFlags = kRenderTarget_GrSurfaceFlag; |
| 172 desc.fWidth = SkScalarFloorToInt(srcRect.width()); | 204 desc.fWidth = SkScalarFloorToInt(dstBounds.width()); |
| 173 desc.fHeight = SkScalarFloorToInt(srcRect.height()); | 205 desc.fHeight = SkScalarFloorToInt(dstBounds.height()); |
| 174 desc.fConfig = srcTexture->config(); | 206 desc.fConfig = srcTexture->config(); |
| 175 | 207 |
| 176 GrTexture* dstTexture; | 208 GrTexture* dstTexture; |
| 177 GrTexture* tempTexture; | 209 GrTexture* tempTexture; |
| 178 SkAutoTUnref<GrTexture> temp1, temp2; | 210 SkAutoTUnref<GrTexture> temp1, temp2; |
| 179 | 211 |
| 180 temp1.reset(context->textureProvider()->createTexture(desc, constraint)); | 212 temp1.reset(context->textureProvider()->createTexture(desc, constraint)); |
| 181 dstTexture = temp1.get(); | 213 dstTexture = temp1.get(); |
| 182 if (canClobberSrc) { | 214 if (canClobberSrc) { |
| 183 tempTexture = srcTexture; | 215 tempTexture = srcTexture; |
| 184 } else { | 216 } else { |
| 185 temp2.reset(context->textureProvider()->createTexture(desc, constraint))
; | 217 temp2.reset(context->textureProvider()->createTexture(desc, constraint))
; |
| 186 tempTexture = temp2.get(); | 218 tempTexture = temp2.get(); |
| 187 } | 219 } |
| 188 | 220 |
| 189 if (nullptr == dstTexture || nullptr == tempTexture) { | 221 if (nullptr == dstTexture || nullptr == tempTexture) { |
| 190 return nullptr; | 222 return nullptr; |
| 191 } | 223 } |
| 192 | 224 |
| 193 SkAutoTUnref<GrDrawContext> srcDrawContext; | 225 SkAutoTUnref<GrDrawContext> srcDrawContext; |
| 194 | 226 |
| 195 for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) { | 227 for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) { |
| 196 GrPaint paint; | 228 GrPaint paint; |
| 197 SkMatrix matrix; | 229 SkMatrix matrix; |
| 198 matrix.setIDiv(srcTexture->width(), srcTexture->height()); | 230 matrix.setIDiv(srcTexture->width(), srcTexture->height()); |
| 199 SkRect dstRect(srcRect); | 231 SkRect dstRect(srcRect); |
| 200 if (cropToRect && i == 1) { | 232 if (srcBounds && i == 1) { |
| 201 dstRect.offset(-dstRect.fLeft, -dstRect.fTop); | |
| 202 SkRect domain; | 233 SkRect domain; |
| 203 matrix.mapRect(&domain, rect); | 234 matrix.mapRect(&domain, *srcBounds); |
| 204 domain.inset(i < scaleFactorX ? SK_ScalarHalf / srcTexture->width()
: 0.0f, | 235 domain.inset((i < scaleFactorX) ? SK_ScalarHalf / srcTexture->width(
) : 0.0f, |
| 205 i < scaleFactorY ? SK_ScalarHalf / srcTexture->height()
: 0.0f); | 236 (i < scaleFactorY) ? SK_ScalarHalf / srcTexture->height
() : 0.0f); |
| 206 SkAutoTUnref<const GrFragmentProcessor> fp(GrTextureDomainEffect::Cr
eate( | 237 SkAutoTUnref<const GrFragmentProcessor> fp(GrTextureDomainEffect::Cr
eate( |
| 207 srcTexture, | 238 srcTexture, |
| 208 matrix, | 239 matrix, |
| 209 domain, | 240 domain, |
| 210 GrTextureDomain::kDecal_Mode, | 241 GrTextureDomain::kDecal_Mode, |
| 211 GrTextureParams::kBilerp_FilterMode)); | 242 GrTextureParams::kBilerp_FilterMode)); |
| 212 paint.addColorFragmentProcessor(fp); | 243 paint.addColorFragmentProcessor(fp); |
| 244 srcRect.offset(-srcOffset); |
| 245 srcOffset.set(0, 0); |
| 213 } else { | 246 } else { |
| 214 GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::k
Bilerp_FilterMode); | 247 GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::k
Bilerp_FilterMode); |
| 215 paint.addColorTextureProcessor(srcTexture, matrix, params); | 248 paint.addColorTextureProcessor(srcTexture, matrix, params); |
| 216 } | 249 } |
| 217 scale_rect(&dstRect, i < scaleFactorX ? 0.5f : 1.0f, | 250 scale_rect(&dstRect, i < scaleFactorX ? 0.5f : 1.0f, |
| 218 i < scaleFactorY ? 0.5f : 1.0f); | 251 i < scaleFactorY ? 0.5f : 1.0f); |
| 219 | 252 |
| 220 SkAutoTUnref<GrDrawContext> dstDrawContext( | 253 SkAutoTUnref<GrDrawContext> dstDrawContext( |
| 221 context->drawContext(dstTexture->as
RenderTarget())); | 254 context->drawContext(dstTexture->as
RenderTarget())); |
| 222 if (!dstDrawContext) { | 255 if (!dstDrawContext) { |
| 223 return nullptr; | 256 return nullptr; |
| 224 } | 257 } |
| 225 dstDrawContext->fillRectToRect(clip, paint, SkMatrix::I(), dstRect, srcR
ect); | 258 dstDrawContext->fillRectToRect(clip, paint, SkMatrix::I(), dstRect, srcR
ect); |
| 226 | 259 |
| 227 srcDrawContext.swap(dstDrawContext); | 260 srcDrawContext.swap(dstDrawContext); |
| 228 srcRect = dstRect; | 261 srcRect = dstRect; |
| 229 srcTexture = dstTexture; | 262 srcTexture = dstTexture; |
| 230 SkTSwap(dstTexture, tempTexture); | 263 SkTSwap(dstTexture, tempTexture); |
| 264 localSrcBounds = srcRect; |
| 231 } | 265 } |
| 232 | 266 |
| 233 const SkIRect srcIRect = srcRect.roundOut(); | |
| 234 | |
| 235 // For really small blurs (certainly no wider than 5x5 on desktop gpus) it i
s faster to just | 267 // For really small blurs (certainly no wider than 5x5 on desktop gpus) it i
s faster to just |
| 236 // launch a single non separable kernel vs two launches | 268 // launch a single non separable kernel vs two launches |
| 237 if (sigmaX > 0.0f && sigmaY > 0.0f && | 269 if (sigmaX > 0.0f && sigmaY > 0.0f && |
| 238 (2 * radiusX + 1) * (2 * radiusY + 1) <= MAX_KERNEL_SIZE) { | 270 (2 * radiusX + 1) * (2 * radiusY + 1) <= MAX_KERNEL_SIZE) { |
| 239 // We shouldn't be scaling because this is a small size blur | 271 // We shouldn't be scaling because this is a small size blur |
| 240 SkASSERT((1 == scaleFactorX) && (1 == scaleFactorY)); | 272 SkASSERT((1 == scaleFactorX) && (1 == scaleFactorY)); |
| 241 | 273 |
| 242 SkAutoTUnref<GrDrawContext> dstDrawContext( | 274 SkAutoTUnref<GrDrawContext> dstDrawContext( |
| 243 context->drawContext(dstTexture->as
RenderTarget())); | 275 context->drawContext(dstTexture->as
RenderTarget())); |
| 244 if (!dstDrawContext) { | 276 if (!dstDrawContext) { |
| 245 return nullptr; | 277 return nullptr; |
| 246 } | 278 } |
| 247 convolve_gaussian_2d(dstDrawContext, clip, srcRect, | 279 convolve_gaussian_2d(dstDrawContext, clip, srcRect, |
| 248 srcTexture, radiusX, radiusY, sigmaX, sigmaY, cropT
oRect, srcIRect); | 280 srcTexture, radiusX, radiusY, sigmaX, sigmaY, srcBo
unds); |
| 249 | 281 |
| 250 srcDrawContext.swap(dstDrawContext); | 282 srcDrawContext.swap(dstDrawContext); |
| 251 srcRect.offsetTo(0, 0); | 283 srcRect.offsetTo(0, 0); |
| 252 srcTexture = dstTexture; | 284 srcTexture = dstTexture; |
| 253 SkTSwap(dstTexture, tempTexture); | 285 SkTSwap(dstTexture, tempTexture); |
| 254 | 286 |
| 255 } else { | 287 } else { |
| 288 srcRect = localDstBounds; |
| 289 scale_rect(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY); |
| 290 srcRect.roundOut(&srcRect); |
| 291 const SkIRect srcIRect = srcRect.roundOut(); |
| 256 if (sigmaX > 0.0f) { | 292 if (sigmaX > 0.0f) { |
| 257 if (scaleFactorX > 1) { | 293 if (scaleFactorX > 1) { |
| 258 // TODO: if we pass in the source draw context we don't need thi
s here | 294 // TODO: if we pass in the source draw context we don't need thi
s here |
| 259 if (!srcDrawContext) { | 295 if (!srcDrawContext) { |
| 260 srcDrawContext.reset(context->drawContext(srcTexture->asRend
erTarget())); | 296 srcDrawContext.reset(context->drawContext(srcTexture->asRend
erTarget())); |
| 261 if (!srcDrawContext) { | 297 if (!srcDrawContext) { |
| 262 return nullptr; | 298 return nullptr; |
| 263 } | 299 } |
| 264 } | 300 } |
| 265 | 301 |
| 266 // Clear out a radius to the right of the srcRect to prevent the | 302 // Clear out a radius to the right of the srcRect to prevent the |
| 267 // X convolution from reading garbage. | 303 // X convolution from reading garbage. |
| 268 clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop, | 304 clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop, |
| 269 radiusX, srcIRect.height()); | 305 radiusX, srcIRect.height()); |
| 270 srcDrawContext->clear(&clearRect, 0x0, false); | 306 srcDrawContext->clear(&clearRect, 0x0, false); |
| 271 } | 307 } |
| 272 | 308 |
| 273 SkAutoTUnref<GrDrawContext> dstDrawContext( | 309 SkAutoTUnref<GrDrawContext> dstDrawContext( |
| 274 context->drawContext(dstTexture->as
RenderTarget())); | 310 context->drawContext(dstTexture->as
RenderTarget())); |
| 275 if (!dstDrawContext) { | 311 if (!dstDrawContext) { |
| 276 return nullptr; | 312 return nullptr; |
| 277 } | 313 } |
| 278 convolve_gaussian(dstDrawContext, clip, srcRect, | 314 convolve_gaussian(dstDrawContext, clip, srcRect, |
| 279 srcTexture, Gr1DKernelEffect::kX_Direction, radius
X, sigmaX, | 315 srcTexture, Gr1DKernelEffect::kX_Direction, radius
X, sigmaX, |
| 280 cropToRect); | 316 srcBounds, srcOffset); |
| 281 | |
| 282 srcDrawContext.swap(dstDrawContext); | 317 srcDrawContext.swap(dstDrawContext); |
| 283 srcTexture = dstTexture; | 318 srcTexture = dstTexture; |
| 284 srcRect.offsetTo(0, 0); | 319 srcRect.offsetTo(0, 0); |
| 285 SkTSwap(dstTexture, tempTexture); | 320 SkTSwap(dstTexture, tempTexture); |
| 321 localSrcBounds = srcRect; |
| 322 srcOffset.set(0, 0); |
| 286 } | 323 } |
| 287 | 324 |
| 288 if (sigmaY > 0.0f) { | 325 if (sigmaY > 0.0f) { |
| 289 if (scaleFactorY > 1 || sigmaX > 0.0f) { | 326 if (scaleFactorY > 1 || sigmaX > 0.0f) { |
| 290 // TODO: if we pass in the source draw context we don't need thi
s here | 327 // TODO: if we pass in the source draw context we don't need thi
s here |
| 291 if (!srcDrawContext) { | 328 if (!srcDrawContext) { |
| 292 srcDrawContext.reset(context->drawContext(srcTexture->asRend
erTarget())); | 329 srcDrawContext.reset(context->drawContext(srcTexture->asRend
erTarget())); |
| 293 if (!srcDrawContext) { | 330 if (!srcDrawContext) { |
| 294 return nullptr; | 331 return nullptr; |
| 295 } | 332 } |
| 296 } | 333 } |
| 297 | 334 |
| 298 // Clear out a radius below the srcRect to prevent the Y | 335 // Clear out a radius below the srcRect to prevent the Y |
| 299 // convolution from reading garbage. | 336 // convolution from reading garbage. |
| 300 clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom, | 337 clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom, |
| 301 srcIRect.width(), radiusY); | 338 srcIRect.width(), radiusY); |
| 302 srcDrawContext->clear(&clearRect, 0x0, false); | 339 srcDrawContext->clear(&clearRect, 0x0, false); |
| 303 } | 340 } |
| 304 | 341 |
| 305 SkAutoTUnref<GrDrawContext> dstDrawContext( | 342 SkAutoTUnref<GrDrawContext> dstDrawContext( |
| 306 context->drawContext(dstTexture->
asRenderTarget())); | 343 context->drawContext(dstTexture->
asRenderTarget())); |
| 307 if (!dstDrawContext) { | 344 if (!dstDrawContext) { |
| 308 return nullptr; | 345 return nullptr; |
| 309 } | 346 } |
| 310 convolve_gaussian(dstDrawContext, clip, srcRect, | 347 convolve_gaussian(dstDrawContext, clip, srcRect, |
| 311 srcTexture, Gr1DKernelEffect::kY_Direction, radius
Y, sigmaY, | 348 srcTexture, Gr1DKernelEffect::kY_Direction, radius
Y, sigmaY, |
| 312 cropToRect); | 349 srcBounds, srcOffset); |
| 313 | 350 |
| 314 srcDrawContext.swap(dstDrawContext); | 351 srcDrawContext.swap(dstDrawContext); |
| 315 srcTexture = dstTexture; | 352 srcTexture = dstTexture; |
| 316 srcRect.offsetTo(0, 0); | 353 srcRect.offsetTo(0, 0); |
| 317 SkTSwap(dstTexture, tempTexture); | 354 SkTSwap(dstTexture, tempTexture); |
| 318 } | 355 } |
| 319 } | 356 } |
| 357 const SkIRect srcIRect = srcRect.roundOut(); |
| 320 | 358 |
| 321 if (scaleFactorX > 1 || scaleFactorY > 1) { | 359 if (scaleFactorX > 1 || scaleFactorY > 1) { |
| 322 SkASSERT(srcDrawContext); | 360 SkASSERT(srcDrawContext); |
| 323 | 361 |
| 324 // Clear one pixel to the right and below, to accommodate bilinear | 362 // Clear one pixel to the right and below, to accommodate bilinear |
| 325 // upsampling. | 363 // upsampling. |
| 326 clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom, | 364 clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom, |
| 327 srcIRect.width() + 1, 1); | 365 srcIRect.width() + 1, 1); |
| 328 srcDrawContext->clear(&clearRect, 0x0, false); | 366 srcDrawContext->clear(&clearRect, 0x0, false); |
| 329 clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop, | 367 clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop, |
| (...skipping 21 matching lines...) Expand all Loading... |
| 351 srcRect = dstRect; | 389 srcRect = dstRect; |
| 352 srcTexture = dstTexture; | 390 srcTexture = dstTexture; |
| 353 SkTSwap(dstTexture, tempTexture); | 391 SkTSwap(dstTexture, tempTexture); |
| 354 } | 392 } |
| 355 | 393 |
| 356 return SkRef(srcTexture); | 394 return SkRef(srcTexture); |
| 357 } | 395 } |
| 358 #endif | 396 #endif |
| 359 | 397 |
| 360 } | 398 } |
| OLD | NEW |