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