| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2012 The Android Open Source Project | 2 * Copyright 2012 The Android Open Source Project |
| 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 "SkMorphologyImageFilter.h" | 8 #include "SkMorphologyImageFilter.h" |
| 9 |
| 9 #include "SkBitmap.h" | 10 #include "SkBitmap.h" |
| 10 #include "SkColorPriv.h" | 11 #include "SkColorPriv.h" |
| 11 #include "SkDevice.h" | |
| 12 #include "SkOpts.h" | 12 #include "SkOpts.h" |
| 13 #include "SkReadBuffer.h" | 13 #include "SkReadBuffer.h" |
| 14 #include "SkRect.h" | 14 #include "SkRect.h" |
| 15 #include "SkSpecialImage.h" |
| 15 #include "SkWriteBuffer.h" | 16 #include "SkWriteBuffer.h" |
| 17 |
| 16 #if SK_SUPPORT_GPU | 18 #if SK_SUPPORT_GPU |
| 17 #include "GrContext.h" | 19 #include "GrContext.h" |
| 18 #include "GrDrawContext.h" | 20 #include "GrDrawContext.h" |
| 19 #include "GrInvariantOutput.h" | 21 #include "GrInvariantOutput.h" |
| 20 #include "GrTexture.h" | 22 #include "GrTexture.h" |
| 21 #include "SkGr.h" | 23 #include "SkGr.h" |
| 22 #include "effects/Gr1DKernelEffect.h" | 24 #include "effects/Gr1DKernelEffect.h" |
| 23 #include "glsl/GrGLSLFragmentProcessor.h" | 25 #include "glsl/GrGLSLFragmentProcessor.h" |
| 24 #include "glsl/GrGLSLFragmentShaderBuilder.h" | 26 #include "glsl/GrGLSLFragmentShaderBuilder.h" |
| 25 #include "glsl/GrGLSLProgramDataManager.h" | 27 #include "glsl/GrGLSLProgramDataManager.h" |
| 26 #include "glsl/GrGLSLUniformHandler.h" | 28 #include "glsl/GrGLSLUniformHandler.h" |
| 27 #endif | 29 #endif |
| 28 | 30 |
| 29 SkMorphologyImageFilter::SkMorphologyImageFilter(int radiusX, | 31 SkMorphologyImageFilter::SkMorphologyImageFilter(int radiusX, |
| 30 int radiusY, | 32 int radiusY, |
| 31 SkImageFilter* input, | 33 SkImageFilter* input, |
| 32 const CropRect* cropRect) | 34 const CropRect* cropRect) |
| 33 : INHERITED(1, &input, cropRect), fRadius(SkISize::Make(radiusX, radiusY)) { | 35 : INHERITED(1, &input, cropRect) |
| 36 , fRadius(SkISize::Make(radiusX, radiusY)) { |
| 34 } | 37 } |
| 35 | 38 |
| 36 void SkMorphologyImageFilter::flatten(SkWriteBuffer& buffer) const { | 39 void SkMorphologyImageFilter::flatten(SkWriteBuffer& buffer) const { |
| 37 this->INHERITED::flatten(buffer); | 40 this->INHERITED::flatten(buffer); |
| 38 buffer.writeInt(fRadius.fWidth); | 41 buffer.writeInt(fRadius.fWidth); |
| 39 buffer.writeInt(fRadius.fHeight); | 42 buffer.writeInt(fRadius.fHeight); |
| 40 } | 43 } |
| 41 | 44 |
| 42 static void callProcX(SkMorphologyImageFilter::Proc procX, const SkBitmap& src,
SkBitmap* dst, int radiusX, const SkIRect& bounds) | 45 static void call_proc_X(SkMorphologyImageFilter::Proc procX, |
| 43 { | 46 const SkPixmap& src, SkBitmap* dst, |
| 44 procX(src.getAddr32(bounds.left(), bounds.top()), dst->getAddr32(0, 0), | 47 int radiusX, const SkIRect& bounds) { |
| 48 procX(src.addr32(bounds.left(), bounds.top()), dst->getAddr32(0, 0), |
| 45 radiusX, bounds.width(), bounds.height(), | 49 radiusX, bounds.width(), bounds.height(), |
| 46 src.rowBytesAsPixels(), dst->rowBytesAsPixels()); | 50 src.rowBytesAsPixels(), dst->rowBytesAsPixels()); |
| 47 } | 51 } |
| 48 | 52 |
| 49 static void callProcY(SkMorphologyImageFilter::Proc procY, const SkBitmap& src,
SkBitmap* dst, int radiusY, const SkIRect& bounds) | 53 static void call_proc_Y(SkMorphologyImageFilter::Proc procY, |
| 50 { | 54 const SkPMColor* src, int srcRowBytesAsPixels, SkBitmap*
dst, |
| 51 procY(src.getAddr32(bounds.left(), bounds.top()), dst->getAddr32(0, 0), | 55 int radiusY, const SkIRect& bounds) { |
| 56 procY(src, dst->getAddr32(0, 0), |
| 52 radiusY, bounds.height(), bounds.width(), | 57 radiusY, bounds.height(), bounds.width(), |
| 53 src.rowBytesAsPixels(), dst->rowBytesAsPixels()); | 58 srcRowBytesAsPixels, dst->rowBytesAsPixels()); |
| 54 } | |
| 55 | |
| 56 bool SkMorphologyImageFilter::filterImageGeneric(SkMorphologyImageFilter::Proc p
rocX, | |
| 57 SkMorphologyImageFilter::Proc p
rocY, | |
| 58 Proxy* proxy, | |
| 59 const SkBitmap& source, | |
| 60 const Context& ctx, | |
| 61 SkBitmap* dst, | |
| 62 SkIPoint* offset) const { | |
| 63 SkBitmap src = source; | |
| 64 SkIPoint srcOffset = SkIPoint::Make(0, 0); | |
| 65 if (!this->filterInputDeprecated(0, proxy, source, ctx, &src, &srcOffset)) { | |
| 66 return false; | |
| 67 } | |
| 68 | |
| 69 if (src.colorType() != kN32_SkColorType) { | |
| 70 return false; | |
| 71 } | |
| 72 | |
| 73 SkIRect bounds; | |
| 74 if (!this->applyCropRectDeprecated(this->mapContext(ctx), proxy, src, &srcOf
fset, | |
| 75 &bounds, &src)) { | |
| 76 return false; | |
| 77 } | |
| 78 | |
| 79 SkAutoLockPixels alp(src); | |
| 80 if (!src.getPixels()) { | |
| 81 return false; | |
| 82 } | |
| 83 | |
| 84 SkVector radius = SkVector::Make(SkIntToScalar(this->radius().width()), | |
| 85 SkIntToScalar(this->radius().height())); | |
| 86 ctx.ctm().mapVectors(&radius, 1); | |
| 87 int width = SkScalarFloorToInt(radius.fX); | |
| 88 int height = SkScalarFloorToInt(radius.fY); | |
| 89 | |
| 90 if (width < 0 || height < 0) { | |
| 91 return false; | |
| 92 } | |
| 93 | |
| 94 SkIRect srcBounds = bounds; | |
| 95 srcBounds.offset(-srcOffset); | |
| 96 | |
| 97 if (width == 0 && height == 0) { | |
| 98 src.extractSubset(dst, srcBounds); | |
| 99 offset->fX = bounds.left(); | |
| 100 offset->fY = bounds.top(); | |
| 101 return true; | |
| 102 } | |
| 103 | |
| 104 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds
.height())); | |
| 105 if (!device) { | |
| 106 return false; | |
| 107 } | |
| 108 *dst = device->accessBitmap(false); | |
| 109 SkAutoLockPixels alp_dst(*dst); | |
| 110 | |
| 111 if (width > 0 && height > 0) { | |
| 112 SkAutoTUnref<SkBaseDevice> tempDevice(proxy->createDevice(dst->width(),
dst->height())); | |
| 113 if (!tempDevice) { | |
| 114 return false; | |
| 115 } | |
| 116 SkBitmap temp = tempDevice->accessBitmap(false); | |
| 117 SkAutoLockPixels alp_temp(temp); | |
| 118 callProcX(procX, src, &temp, width, srcBounds); | |
| 119 SkIRect tmpBounds = SkIRect::MakeWH(srcBounds.width(), srcBounds.height(
)); | |
| 120 callProcY(procY, temp, dst, height, tmpBounds); | |
| 121 } else if (width > 0) { | |
| 122 callProcX(procX, src, dst, width, srcBounds); | |
| 123 } else if (height > 0) { | |
| 124 callProcY(procY, src, dst, height, srcBounds); | |
| 125 } | |
| 126 offset->fX = bounds.left(); | |
| 127 offset->fY = bounds.top(); | |
| 128 return true; | |
| 129 } | |
| 130 | |
| 131 bool SkErodeImageFilter::onFilterImageDeprecated(Proxy* proxy, | |
| 132 const SkBitmap& source, const C
ontext& ctx, | |
| 133 SkBitmap* dst, SkIPoint* offset
) const { | |
| 134 return this->filterImageGeneric(SkOpts::erode_x, SkOpts::erode_y, | |
| 135 proxy, source, ctx, dst, offset); | |
| 136 } | |
| 137 | |
| 138 bool SkDilateImageFilter::onFilterImageDeprecated(Proxy* proxy, | |
| 139 const SkBitmap& source, const
Context& ctx, | |
| 140 SkBitmap* dst, SkIPoint* offse
t) const { | |
| 141 return this->filterImageGeneric(SkOpts::dilate_x, SkOpts::dilate_y, | |
| 142 proxy, source, ctx, dst, offset); | |
| 143 } | 59 } |
| 144 | 60 |
| 145 SkRect SkMorphologyImageFilter::computeFastBounds(const SkRect& src) const { | 61 SkRect SkMorphologyImageFilter::computeFastBounds(const SkRect& src) const { |
| 146 SkRect bounds = this->getInput(0) ? this->getInput(0)->computeFastBounds(src
) : src; | 62 SkRect bounds = this->getInput(0) ? this->getInput(0)->computeFastBounds(src
) : src; |
| 147 bounds.outset(SkIntToScalar(fRadius.width()), SkIntToScalar(fRadius.height()
)); | 63 bounds.outset(SkIntToScalar(fRadius.width()), SkIntToScalar(fRadius.height()
)); |
| 148 return bounds; | 64 return bounds; |
| 149 } | 65 } |
| 150 | 66 |
| 151 SkIRect SkMorphologyImageFilter::onFilterNodeBounds(const SkIRect& src, const Sk
Matrix& ctm, | 67 SkIRect SkMorphologyImageFilter::onFilterNodeBounds(const SkIRect& src, const Sk
Matrix& ctm, |
| 152 MapDirection) const { | 68 MapDirection) const { |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 377 } | 293 } |
| 378 } | 294 } |
| 379 | 295 |
| 380 /////////////////////////////////////////////////////////////////////////////// | 296 /////////////////////////////////////////////////////////////////////////////// |
| 381 | 297 |
| 382 GrMorphologyEffect::GrMorphologyEffect(GrTexture* texture, | 298 GrMorphologyEffect::GrMorphologyEffect(GrTexture* texture, |
| 383 Direction direction, | 299 Direction direction, |
| 384 int radius, | 300 int radius, |
| 385 MorphologyType type) | 301 MorphologyType type) |
| 386 : INHERITED(texture, direction, radius) | 302 : INHERITED(texture, direction, radius) |
| 387 , fType(type), fUseRange(false) { | 303 , fType(type) |
| 304 , fUseRange(false) { |
| 388 this->initClassID<GrMorphologyEffect>(); | 305 this->initClassID<GrMorphologyEffect>(); |
| 389 } | 306 } |
| 390 | 307 |
| 391 GrMorphologyEffect::GrMorphologyEffect(GrTexture* texture, | 308 GrMorphologyEffect::GrMorphologyEffect(GrTexture* texture, |
| 392 Direction direction, | 309 Direction direction, |
| 393 int radius, | 310 int radius, |
| 394 MorphologyType type, | 311 MorphologyType type, |
| 395 float range[2]) | 312 float range[2]) |
| 396 : INHERITED(texture, direction, radius) | 313 : INHERITED(texture, direction, radius) |
| 397 , fType(type), fUseRange(true) { | 314 , fType(type) |
| 315 , fUseRange(true) { |
| 398 this->initClassID<GrMorphologyEffect>(); | 316 this->initClassID<GrMorphologyEffect>(); |
| 399 fRange[0] = range[0]; | 317 fRange[0] = range[0]; |
| 400 fRange[1] = range[1]; | 318 fRange[1] = range[1]; |
| 401 } | 319 } |
| 402 | 320 |
| 403 GrMorphologyEffect::~GrMorphologyEffect() { | 321 GrMorphologyEffect::~GrMorphologyEffect() { |
| 404 } | 322 } |
| 405 | 323 |
| 406 void GrMorphologyEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps, | 324 void GrMorphologyEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps, |
| 407 GrProcessorKeyBuilder* b) const { | 325 GrProcessorKeyBuilder* b) const { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 434 GrProcessorUnitTest::kAlphaTextureIdx; | 352 GrProcessorUnitTest::kAlphaTextureIdx; |
| 435 Direction dir = d->fRandom->nextBool() ? kX_Direction : kY_Direction; | 353 Direction dir = d->fRandom->nextBool() ? kX_Direction : kY_Direction; |
| 436 static const int kMaxRadius = 10; | 354 static const int kMaxRadius = 10; |
| 437 int radius = d->fRandom->nextRangeU(1, kMaxRadius); | 355 int radius = d->fRandom->nextRangeU(1, kMaxRadius); |
| 438 MorphologyType type = d->fRandom->nextBool() ? GrMorphologyEffect::kErode_Mo
rphologyType : | 356 MorphologyType type = d->fRandom->nextBool() ? GrMorphologyEffect::kErode_Mo
rphologyType : |
| 439 GrMorphologyEffect::kDilate_Morph
ologyType; | 357 GrMorphologyEffect::kDilate_Morph
ologyType; |
| 440 | 358 |
| 441 return GrMorphologyEffect::Create(d->fTextures[texIdx], dir, radius, type); | 359 return GrMorphologyEffect::Create(d->fTextures[texIdx], dir, radius, type); |
| 442 } | 360 } |
| 443 | 361 |
| 444 namespace { | |
| 445 | 362 |
| 446 | 363 static void apply_morphology_rect(GrDrawContext* drawContext, |
| 447 void apply_morphology_rect(GrDrawContext* drawContext, | 364 const GrClip& clip, |
| 448 const GrClip& clip, | 365 GrTexture* texture, |
| 449 GrTexture* texture, | 366 const SkIRect& srcRect, |
| 450 const SkIRect& srcRect, | 367 const SkIRect& dstRect, |
| 451 const SkIRect& dstRect, | 368 int radius, |
| 452 int radius, | 369 GrMorphologyEffect::MorphologyType morphType, |
| 453 GrMorphologyEffect::MorphologyType morphType, | 370 float bounds[2], |
| 454 float bounds[2], | 371 Gr1DKernelEffect::Direction direction) { |
| 455 Gr1DKernelEffect::Direction direction) { | |
| 456 GrPaint paint; | 372 GrPaint paint; |
| 457 paint.addColorFragmentProcessor(GrMorphologyEffect::Create(texture, | 373 paint.addColorFragmentProcessor(GrMorphologyEffect::Create(texture, |
| 458 direction, | 374 direction, |
| 459 radius, | 375 radius, |
| 460 morphType, | 376 morphType, |
| 461 bounds))->unref()
; | 377 bounds))->unref()
; |
| 462 paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); | 378 paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); |
| 463 drawContext->fillRectToRect(clip, paint, SkMatrix::I(), SkRect::Make(dstRect
), | 379 drawContext->fillRectToRect(clip, paint, SkMatrix::I(), SkRect::Make(dstRect
), |
| 464 SkRect::Make(srcRect)); | 380 SkRect::Make(srcRect)); |
| 465 } | 381 } |
| 466 | 382 |
| 467 void apply_morphology_rect_no_bounds(GrDrawContext* drawContext, | 383 static void apply_morphology_rect_no_bounds(GrDrawContext* drawContext, |
| 468 const GrClip& clip, | 384 const GrClip& clip, |
| 469 GrTexture* texture, | 385 GrTexture* texture, |
| 470 const SkIRect& srcRect, | 386 const SkIRect& srcRect, |
| 471 const SkIRect& dstRect, | 387 const SkIRect& dstRect, |
| 472 int radius, | 388 int radius, |
| 473 GrMorphologyEffect::MorphologyType morphTyp
e, | 389 GrMorphologyEffect::MorphologyType m
orphType, |
| 474 Gr1DKernelEffect::Direction direction) { | 390 Gr1DKernelEffect::Direction directio
n) { |
| 475 GrPaint paint; | 391 GrPaint paint; |
| 476 paint.addColorFragmentProcessor(GrMorphologyEffect::Create(texture, | 392 paint.addColorFragmentProcessor(GrMorphologyEffect::Create(texture, |
| 477 direction, | 393 direction, |
| 478 radius, | 394 radius, |
| 479 morphType))->unre
f(); | 395 morphType))->unre
f(); |
| 480 paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); | 396 paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); |
| 481 drawContext->fillRectToRect(clip, paint, SkMatrix::I(), SkRect::Make(dstRect
), | 397 drawContext->fillRectToRect(clip, paint, SkMatrix::I(), SkRect::Make(dstRect
), |
| 482 SkRect::Make(srcRect)); | 398 SkRect::Make(srcRect)); |
| 483 } | 399 } |
| 484 | 400 |
| 485 void apply_morphology_pass(GrDrawContext* drawContext, | 401 static void apply_morphology_pass(GrDrawContext* drawContext, |
| 486 const GrClip& clip, | 402 const GrClip& clip, |
| 487 GrTexture* texture, | 403 GrTexture* texture, |
| 488 const SkIRect& srcRect, | 404 const SkIRect& srcRect, |
| 489 const SkIRect& dstRect, | 405 const SkIRect& dstRect, |
| 490 int radius, | 406 int radius, |
| 491 GrMorphologyEffect::MorphologyType morphType, | 407 GrMorphologyEffect::MorphologyType morphType, |
| 492 Gr1DKernelEffect::Direction direction) { | 408 Gr1DKernelEffect::Direction direction) { |
| 493 float bounds[2] = { 0.0f, 1.0f }; | 409 float bounds[2] = { 0.0f, 1.0f }; |
| 494 SkIRect lowerSrcRect = srcRect, lowerDstRect = dstRect; | 410 SkIRect lowerSrcRect = srcRect, lowerDstRect = dstRect; |
| 495 SkIRect middleSrcRect = srcRect, middleDstRect = dstRect; | 411 SkIRect middleSrcRect = srcRect, middleDstRect = dstRect; |
| 496 SkIRect upperSrcRect = srcRect, upperDstRect = dstRect; | 412 SkIRect upperSrcRect = srcRect, upperDstRect = dstRect; |
| 497 if (direction == Gr1DKernelEffect::kX_Direction) { | 413 if (direction == Gr1DKernelEffect::kX_Direction) { |
| 498 bounds[0] = (SkIntToScalar(srcRect.left()) + 0.5f) / texture->width(); | 414 bounds[0] = (SkIntToScalar(srcRect.left()) + 0.5f) / texture->width(); |
| 499 bounds[1] = (SkIntToScalar(srcRect.right()) - 0.5f) / texture->width(); | 415 bounds[1] = (SkIntToScalar(srcRect.right()) - 0.5f) / texture->width(); |
| 500 lowerSrcRect.fRight = srcRect.left() + radius; | 416 lowerSrcRect.fRight = srcRect.left() + radius; |
| 501 lowerDstRect.fRight = dstRect.left() + radius; | 417 lowerDstRect.fRight = dstRect.left() + radius; |
| 502 upperSrcRect.fLeft = srcRect.right() - radius; | 418 upperSrcRect.fLeft = srcRect.right() - radius; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 521 // Draw upper and lower margins with bounds; middle without. | 437 // Draw upper and lower margins with bounds; middle without. |
| 522 apply_morphology_rect(drawContext, clip, texture, lowerSrcRect, lowerDst
Rect, radius, | 438 apply_morphology_rect(drawContext, clip, texture, lowerSrcRect, lowerDst
Rect, radius, |
| 523 morphType, bounds, direction); | 439 morphType, bounds, direction); |
| 524 apply_morphology_rect(drawContext, clip, texture, upperSrcRect, upperDst
Rect, radius, | 440 apply_morphology_rect(drawContext, clip, texture, upperSrcRect, upperDst
Rect, radius, |
| 525 morphType, bounds, direction); | 441 morphType, bounds, direction); |
| 526 apply_morphology_rect_no_bounds(drawContext, clip, texture, middleSrcRec
t, middleDstRect, | 442 apply_morphology_rect_no_bounds(drawContext, clip, texture, middleSrcRec
t, middleDstRect, |
| 527 radius, morphType, direction); | 443 radius, morphType, direction); |
| 528 } | 444 } |
| 529 } | 445 } |
| 530 | 446 |
| 531 bool apply_morphology(const SkBitmap& input, | 447 static sk_sp<SkSpecialImage> apply_morphology(SkSpecialImage* input, |
| 532 const SkIRect& rect, | 448 const SkIRect& rect, |
| 533 GrMorphologyEffect::MorphologyType morphType, | 449 GrMorphologyEffect::MorphologyType
morphType, |
| 534 SkISize radius, | 450 SkISize radius) { |
| 535 SkBitmap* dst) { | 451 SkAutoTUnref<GrTexture> srcTexture(SkRef(input->peekTexture())); |
| 536 SkAutoTUnref<GrTexture> srcTexture(SkRef(input.getTexture())); | |
| 537 SkASSERT(srcTexture); | 452 SkASSERT(srcTexture); |
| 538 GrContext* context = srcTexture->getContext(); | 453 GrContext* context = srcTexture->getContext(); |
| 539 | 454 |
| 540 // setup new clip | 455 // setup new clip |
| 541 GrClip clip(SkRect::MakeWH(SkIntToScalar(srcTexture->width()), | 456 GrClip clip(SkRect::MakeWH(SkIntToScalar(srcTexture->width()), |
| 542 SkIntToScalar(srcTexture->height()))); | 457 SkIntToScalar(srcTexture->height()))); |
| 543 | 458 |
| 544 SkIRect dstRect = SkIRect::MakeWH(rect.width(), rect.height()); | 459 SkIRect dstRect = SkIRect::MakeWH(rect.width(), rect.height()); |
| 545 GrSurfaceDesc desc; | 460 GrSurfaceDesc desc; |
| 546 desc.fFlags = kRenderTarget_GrSurfaceFlag; | 461 desc.fFlags = kRenderTarget_GrSurfaceFlag; |
| 547 desc.fWidth = rect.width(); | 462 desc.fWidth = rect.width(); |
| 548 desc.fHeight = rect.height(); | 463 desc.fHeight = rect.height(); |
| 549 desc.fConfig = kSkia8888_GrPixelConfig; | 464 desc.fConfig = kSkia8888_GrPixelConfig; |
| 550 SkIRect srcRect = rect; | 465 SkIRect srcRect = rect; |
| 551 | 466 |
| 467 SkASSERT(radius.width() > 0 || radius.height() > 0); |
| 468 |
| 552 if (radius.fWidth > 0) { | 469 if (radius.fWidth > 0) { |
| 553 GrTexture* scratch = context->textureProvider()->createApproxTexture(des
c); | 470 GrTexture* scratch = context->textureProvider()->createApproxTexture(des
c); |
| 554 if (nullptr == scratch) { | 471 if (!scratch) { |
| 555 return false; | 472 return nullptr; |
| 556 } | 473 } |
| 557 SkAutoTUnref<GrDrawContext> dstDrawContext( | 474 SkAutoTUnref<GrDrawContext> dstDrawContext( |
| 558 context->drawContext(scratch->as
RenderTarget())); | 475 context->drawContext(scratch->as
RenderTarget())); |
| 559 if (!dstDrawContext) { | 476 if (!dstDrawContext) { |
| 560 return false; | 477 return nullptr; |
| 561 } | 478 } |
| 562 | 479 |
| 563 apply_morphology_pass(dstDrawContext, clip, srcTexture, | 480 apply_morphology_pass(dstDrawContext, clip, srcTexture, |
| 564 srcRect, dstRect, radius.fWidth, morphType, | 481 srcRect, dstRect, radius.fWidth, morphType, |
| 565 Gr1DKernelEffect::kX_Direction); | 482 Gr1DKernelEffect::kX_Direction); |
| 566 SkIRect clearRect = SkIRect::MakeXYWH(dstRect.fLeft, dstRect.fBottom, | 483 SkIRect clearRect = SkIRect::MakeXYWH(dstRect.fLeft, dstRect.fBottom, |
| 567 dstRect.width(), radius.fHeight); | 484 dstRect.width(), radius.fHeight); |
| 568 GrColor clearColor = GrMorphologyEffect::kErode_MorphologyType == morphT
ype ? | 485 GrColor clearColor = GrMorphologyEffect::kErode_MorphologyType == morphT
ype ? |
| 569 SK_ColorWHITE : | 486 SK_ColorWHITE : |
| 570 SK_ColorTRANSPARENT; | 487 SK_ColorTRANSPARENT; |
| 571 dstDrawContext->clear(&clearRect, clearColor, false); | 488 dstDrawContext->clear(&clearRect, clearColor, false); |
| 572 | 489 |
| 573 srcTexture.reset(scratch); | 490 srcTexture.reset(scratch); |
| 574 srcRect = dstRect; | 491 srcRect = dstRect; |
| 575 } | 492 } |
| 576 if (radius.fHeight > 0) { | 493 if (radius.fHeight > 0) { |
| 577 GrTexture* scratch = context->textureProvider()->createApproxTexture(des
c); | 494 GrTexture* scratch = context->textureProvider()->createApproxTexture(des
c); |
| 578 if (nullptr == scratch) { | 495 if (!scratch) { |
| 579 return false; | 496 return nullptr; |
| 580 } | 497 } |
| 581 SkAutoTUnref<GrDrawContext> dstDrawContext( | 498 SkAutoTUnref<GrDrawContext> dstDrawContext( |
| 582 context->drawContext(scratch->as
RenderTarget())); | 499 context->drawContext(scratch->as
RenderTarget())); |
| 583 if (!dstDrawContext) { | 500 if (!dstDrawContext) { |
| 584 return false; | 501 return nullptr; |
| 585 } | 502 } |
| 586 | 503 |
| 587 apply_morphology_pass(dstDrawContext, clip, srcTexture, | 504 apply_morphology_pass(dstDrawContext, clip, srcTexture, |
| 588 srcRect, dstRect, radius.fHeight, morphType, | 505 srcRect, dstRect, radius.fHeight, morphType, |
| 589 Gr1DKernelEffect::kY_Direction); | 506 Gr1DKernelEffect::kY_Direction); |
| 590 | 507 |
| 591 srcTexture.reset(scratch); | 508 srcTexture.reset(scratch); |
| 592 } | 509 } |
| 593 GrWrapTextureInBitmap(srcTexture, rect.width(), rect.height(), false, dst); | 510 |
| 594 return true; | 511 return SkSpecialImage::MakeFromGpu(input->internal_getProxy(), |
| 512 SkIRect::MakeWH(rect.width(), rect.height
()), |
| 513 kNeedNewImageUniqueID_SpecialImage, |
| 514 srcTexture); |
| 595 } | 515 } |
| 516 #endif |
| 596 | 517 |
| 597 }; | 518 sk_sp<SkSpecialImage> SkMorphologyImageFilter::filterImageGeneric(bool dilate, |
| 519 SkSpecialImage
* source, |
| 520 const Context&
ctx, |
| 521 SkIPoint* offs
et) const { |
| 522 SkIPoint inputOffset = SkIPoint::Make(0, 0); |
| 523 sk_sp<SkSpecialImage> input(this->filterInput(0, source, ctx, &inputOffset))
; |
| 524 if (!input) { |
| 525 return nullptr; |
| 526 } |
| 598 | 527 |
| 599 bool SkMorphologyImageFilter::filterImageGPUGeneric(bool dilate, | 528 SkIRect bounds; |
| 600 Proxy* proxy, | 529 input = this->applyCropRect(this->mapContext(ctx), input.get(), &inputOffset
, &bounds); |
| 601 const SkBitmap& src, | 530 if (!input) { |
| 602 const Context& ctx, | 531 return nullptr; |
| 603 SkBitmap* result, | |
| 604 SkIPoint* offset) const { | |
| 605 SkBitmap input = src; | |
| 606 SkIPoint srcOffset = SkIPoint::Make(0, 0); | |
| 607 if (!this->filterInputGPUDeprecated(0, proxy, src, ctx, &input, &srcOffset))
{ | |
| 608 return false; | |
| 609 } | 532 } |
| 610 SkIRect bounds; | 533 |
| 611 if (!this->applyCropRectDeprecated(this->mapContext(ctx), proxy, input, &src
Offset, | |
| 612 &bounds, &input)) { | |
| 613 return false; | |
| 614 } | |
| 615 SkVector radius = SkVector::Make(SkIntToScalar(this->radius().width()), | 534 SkVector radius = SkVector::Make(SkIntToScalar(this->radius().width()), |
| 616 SkIntToScalar(this->radius().height())); | 535 SkIntToScalar(this->radius().height())); |
| 617 ctx.ctm().mapVectors(&radius, 1); | 536 ctx.ctm().mapVectors(&radius, 1); |
| 618 int width = SkScalarFloorToInt(radius.fX); | 537 int width = SkScalarFloorToInt(radius.fX); |
| 619 int height = SkScalarFloorToInt(radius.fY); | 538 int height = SkScalarFloorToInt(radius.fY); |
| 620 | 539 |
| 621 if (width < 0 || height < 0) { | 540 if (width < 0 || height < 0) { |
| 622 return false; | 541 return nullptr; |
| 623 } | 542 } |
| 624 | 543 |
| 625 SkIRect srcBounds = bounds; | 544 SkIRect srcBounds = bounds; |
| 626 srcBounds.offset(-srcOffset); | 545 srcBounds.offset(-inputOffset); |
| 627 if (width == 0 && height == 0) { | 546 |
| 628 input.extractSubset(result, srcBounds); | 547 if (0 == width && 0 == height) { |
| 629 offset->fX = bounds.left(); | 548 offset->fX = bounds.left(); |
| 630 offset->fY = bounds.top(); | 549 offset->fY = bounds.top(); |
| 631 return true; | 550 return input->makeSubset(srcBounds); |
| 632 } | 551 } |
| 633 | 552 |
| 634 GrMorphologyEffect::MorphologyType type = dilate ? GrMorphologyEffect::kDila
te_MorphologyType | 553 #if SK_SUPPORT_GPU |
| 635 : GrMorphologyEffect::kErod
e_MorphologyType; | 554 if (input->peekTexture()) { |
| 636 if (!apply_morphology(input, srcBounds, type, SkISize::Make(width, height),
result)) { | 555 auto type = dilate ? GrMorphologyEffect::kDilate_MorphologyType |
| 637 return false; | 556 : GrMorphologyEffect::kErode_MorphologyType; |
| 557 sk_sp<SkSpecialImage> result(apply_morphology(input.get(), srcBounds, ty
pe, |
| 558 SkISize::Make(width, heigh
t))); |
| 559 if (result) { |
| 560 offset->fX = bounds.left(); |
| 561 offset->fY = bounds.top(); |
| 562 } |
| 563 return result; |
| 564 } |
| 565 #endif |
| 566 |
| 567 SkPixmap inputPixmap; |
| 568 |
| 569 if (!input->peekPixels(&inputPixmap)) { |
| 570 return nullptr; |
| 571 } |
| 572 |
| 573 if (inputPixmap.colorType() != kN32_SkColorType) { |
| 574 return nullptr; |
| 575 } |
| 576 |
| 577 SkImageInfo info = SkImageInfo::Make(bounds.width(), bounds.height(), |
| 578 inputPixmap.colorType(), inputPixmap.al
phaType()); |
| 579 |
| 580 SkBitmap dst; |
| 581 if (!dst.tryAllocPixels(info)) { |
| 582 return nullptr; |
| 583 } |
| 584 |
| 585 SkAutoLockPixels dstLock(dst); |
| 586 |
| 587 SkMorphologyImageFilter::Proc procX, procY; |
| 588 |
| 589 if (dilate) { |
| 590 procX = SkOpts::dilate_x; |
| 591 procY = SkOpts::dilate_y; |
| 592 } else { |
| 593 procX = SkOpts::erode_x; |
| 594 procY = SkOpts::erode_y; |
| 595 } |
| 596 |
| 597 if (width > 0 && height > 0) { |
| 598 SkBitmap tmp; |
| 599 if (!tmp.tryAllocPixels(info)) { |
| 600 return nullptr; |
| 601 } |
| 602 |
| 603 SkAutoLockPixels tmpLock(tmp); |
| 604 |
| 605 call_proc_X(procX, inputPixmap, &tmp, width, srcBounds); |
| 606 SkIRect tmpBounds = SkIRect::MakeWH(srcBounds.width(), srcBounds.height(
)); |
| 607 call_proc_Y(procY, |
| 608 tmp.getAddr32(tmpBounds.left(), tmpBounds.top()), tmp.rowByt
esAsPixels(), |
| 609 &dst, height, tmpBounds); |
| 610 } else if (width > 0) { |
| 611 call_proc_X(procX, inputPixmap, &dst, width, srcBounds); |
| 612 } else if (height > 0) { |
| 613 call_proc_Y(procY, |
| 614 inputPixmap.addr32(srcBounds.left(), srcBounds.top()), |
| 615 inputPixmap.rowBytesAsPixels(), |
| 616 &dst, height, srcBounds); |
| 638 } | 617 } |
| 639 offset->fX = bounds.left(); | 618 offset->fX = bounds.left(); |
| 640 offset->fY = bounds.top(); | 619 offset->fY = bounds.top(); |
| 641 return true; | 620 |
| 621 return SkSpecialImage::MakeFromRaster(source->internal_getProxy(), |
| 622 SkIRect::MakeWH(bounds.width(), bounds
.height()), |
| 623 dst); |
| 642 } | 624 } |
| 643 | 625 |
| 644 bool SkDilateImageFilter::filterImageGPUDeprecated(Proxy* proxy, const SkBitmap&
src, | 626 sk_sp<SkSpecialImage> SkDilateImageFilter::onFilterImage(SkSpecialImage* source,
const Context& ctx, |
| 645 const Context& ctx, | 627 SkIPoint* offset) const
{ |
| 646 SkBitmap* result, SkIPoint* o
ffset) const { | 628 return this->filterImageGeneric(true, source, ctx, offset); |
| 647 return this->filterImageGPUGeneric(true, proxy, src, ctx, result, offset); | |
| 648 } | 629 } |
| 649 | 630 |
| 650 bool SkErodeImageFilter::filterImageGPUDeprecated(Proxy* proxy, const SkBitmap&
src, | 631 sk_sp<SkSpecialImage> SkErodeImageFilter::onFilterImage(SkSpecialImage* source,
const Context& ctx, |
| 651 const Context& ctx, | 632 SkIPoint* offset) const
{ |
| 652 SkBitmap* result, SkIPoint* of
fset) const { | 633 return this->filterImageGeneric(false, source, ctx, offset); |
| 653 return this->filterImageGPUGeneric(false, proxy, src, ctx, result, offset); | |
| 654 } | 634 } |
| 655 | 635 |
| 656 #endif | |
| OLD | NEW |