Chromium Code Reviews| 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 int shiftPerPixel = SkColorTypeBytesPerPixel(src.colorType()) >> 1; | |
| 49 procX(src.addr32(bounds.left(), bounds.top()), dst->getAddr32(0, 0), | |
| 45 radiusX, bounds.width(), bounds.height(), | 50 radiusX, bounds.width(), bounds.height(), |
| 46 src.rowBytesAsPixels(), dst->rowBytesAsPixels()); | 51 src.rowBytes() >> shiftPerPixel, dst->rowBytesAsPixels()); |
| 47 } | 52 } |
| 48 | 53 |
| 49 static void callProcY(SkMorphologyImageFilter::Proc procY, const SkBitmap& src, SkBitmap* dst, int radiusY, const SkIRect& bounds) | 54 static void call_proc_Y(SkMorphologyImageFilter::Proc procY, |
| 50 { | 55 const SkPMColor* src, int srcRowBytesAsPixels, SkBitmap* dst, |
| 51 procY(src.getAddr32(bounds.left(), bounds.top()), dst->getAddr32(0, 0), | 56 int radiusY, const SkIRect& bounds) { |
| 57 procY(src, dst->getAddr32(0, 0), | |
| 52 radiusY, bounds.height(), bounds.width(), | 58 radiusY, bounds.height(), bounds.width(), |
| 53 src.rowBytesAsPixels(), dst->rowBytesAsPixels()); | 59 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 } | 60 } |
| 144 | 61 |
| 145 SkRect SkMorphologyImageFilter::computeFastBounds(const SkRect& src) const { | 62 SkRect SkMorphologyImageFilter::computeFastBounds(const SkRect& src) const { |
| 146 SkRect bounds = this->getInput(0) ? this->getInput(0)->computeFastBounds(src ) : src; | 63 SkRect bounds = this->getInput(0) ? this->getInput(0)->computeFastBounds(src ) : src; |
| 147 bounds.outset(SkIntToScalar(fRadius.width()), SkIntToScalar(fRadius.height() )); | 64 bounds.outset(SkIntToScalar(fRadius.width()), SkIntToScalar(fRadius.height() )); |
| 148 return bounds; | 65 return bounds; |
| 149 } | 66 } |
| 150 | 67 |
| 151 SkIRect SkMorphologyImageFilter::onFilterNodeBounds(const SkIRect& src, const Sk Matrix& ctm, | 68 SkIRect SkMorphologyImageFilter::onFilterNodeBounds(const SkIRect& src, const Sk Matrix& ctm, |
| 152 MapDirection) const { | 69 MapDirection) const { |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 377 } | 294 } |
| 378 } | 295 } |
| 379 | 296 |
| 380 /////////////////////////////////////////////////////////////////////////////// | 297 /////////////////////////////////////////////////////////////////////////////// |
| 381 | 298 |
| 382 GrMorphologyEffect::GrMorphologyEffect(GrTexture* texture, | 299 GrMorphologyEffect::GrMorphologyEffect(GrTexture* texture, |
| 383 Direction direction, | 300 Direction direction, |
| 384 int radius, | 301 int radius, |
| 385 MorphologyType type) | 302 MorphologyType type) |
| 386 : INHERITED(texture, direction, radius) | 303 : INHERITED(texture, direction, radius) |
| 387 , fType(type), fUseRange(false) { | 304 , fType(type) |
| 305 , fUseRange(false) { | |
| 388 this->initClassID<GrMorphologyEffect>(); | 306 this->initClassID<GrMorphologyEffect>(); |
| 389 } | 307 } |
| 390 | 308 |
| 391 GrMorphologyEffect::GrMorphologyEffect(GrTexture* texture, | 309 GrMorphologyEffect::GrMorphologyEffect(GrTexture* texture, |
| 392 Direction direction, | 310 Direction direction, |
| 393 int radius, | 311 int radius, |
| 394 MorphologyType type, | 312 MorphologyType type, |
| 395 float range[2]) | 313 float range[2]) |
| 396 : INHERITED(texture, direction, radius) | 314 : INHERITED(texture, direction, radius) |
| 397 , fType(type), fUseRange(true) { | 315 , fType(type) |
| 316 , fUseRange(true) { | |
| 398 this->initClassID<GrMorphologyEffect>(); | 317 this->initClassID<GrMorphologyEffect>(); |
| 399 fRange[0] = range[0]; | 318 fRange[0] = range[0]; |
| 400 fRange[1] = range[1]; | 319 fRange[1] = range[1]; |
| 401 } | 320 } |
| 402 | 321 |
| 403 GrMorphologyEffect::~GrMorphologyEffect() { | 322 GrMorphologyEffect::~GrMorphologyEffect() { |
| 404 } | 323 } |
| 405 | 324 |
| 406 void GrMorphologyEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps, | 325 void GrMorphologyEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps, |
| 407 GrProcessorKeyBuilder* b) const { | 326 GrProcessorKeyBuilder* b) const { |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 434 GrProcessorUnitTest::kAlphaTextureIdx; | 353 GrProcessorUnitTest::kAlphaTextureIdx; |
| 435 Direction dir = d->fRandom->nextBool() ? kX_Direction : kY_Direction; | 354 Direction dir = d->fRandom->nextBool() ? kX_Direction : kY_Direction; |
| 436 static const int kMaxRadius = 10; | 355 static const int kMaxRadius = 10; |
| 437 int radius = d->fRandom->nextRangeU(1, kMaxRadius); | 356 int radius = d->fRandom->nextRangeU(1, kMaxRadius); |
| 438 MorphologyType type = d->fRandom->nextBool() ? GrMorphologyEffect::kErode_Mo rphologyType : | 357 MorphologyType type = d->fRandom->nextBool() ? GrMorphologyEffect::kErode_Mo rphologyType : |
| 439 GrMorphologyEffect::kDilate_Morph ologyType; | 358 GrMorphologyEffect::kDilate_Morph ologyType; |
| 440 | 359 |
| 441 return GrMorphologyEffect::Create(d->fTextures[texIdx], dir, radius, type); | 360 return GrMorphologyEffect::Create(d->fTextures[texIdx], dir, radius, type); |
| 442 } | 361 } |
| 443 | 362 |
| 444 namespace { | |
| 445 | 363 |
| 446 | 364 static void apply_morphology_rect(GrDrawContext* drawContext, |
| 447 void apply_morphology_rect(GrDrawContext* drawContext, | 365 const GrClip& clip, |
| 448 const GrClip& clip, | 366 GrTexture* texture, |
| 449 GrTexture* texture, | 367 const SkIRect& srcRect, |
| 450 const SkIRect& srcRect, | 368 const SkIRect& dstRect, |
| 451 const SkIRect& dstRect, | 369 int radius, |
| 452 int radius, | 370 GrMorphologyEffect::MorphologyType morphType, |
| 453 GrMorphologyEffect::MorphologyType morphType, | 371 float bounds[2], |
| 454 float bounds[2], | 372 Gr1DKernelEffect::Direction direction) { |
| 455 Gr1DKernelEffect::Direction direction) { | |
| 456 GrPaint paint; | 373 GrPaint paint; |
| 457 paint.addColorFragmentProcessor(GrMorphologyEffect::Create(texture, | 374 paint.addColorFragmentProcessor(GrMorphologyEffect::Create(texture, |
| 458 direction, | 375 direction, |
| 459 radius, | 376 radius, |
| 460 morphType, | 377 morphType, |
| 461 bounds))->unref() ; | 378 bounds))->unref() ; |
| 462 paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); | 379 paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); |
| 463 drawContext->fillRectToRect(clip, paint, SkMatrix::I(), SkRect::Make(dstRect ), | 380 drawContext->fillRectToRect(clip, paint, SkMatrix::I(), SkRect::Make(dstRect ), |
| 464 SkRect::Make(srcRect)); | 381 SkRect::Make(srcRect)); |
| 465 } | 382 } |
| 466 | 383 |
| 467 void apply_morphology_rect_no_bounds(GrDrawContext* drawContext, | 384 static void apply_morphology_rect_no_bounds(GrDrawContext* drawContext, |
| 468 const GrClip& clip, | 385 const GrClip& clip, |
| 469 GrTexture* texture, | 386 GrTexture* texture, |
| 470 const SkIRect& srcRect, | 387 const SkIRect& srcRect, |
| 471 const SkIRect& dstRect, | 388 const SkIRect& dstRect, |
| 472 int radius, | 389 int radius, |
| 473 GrMorphologyEffect::MorphologyType morphTyp e, | 390 GrMorphologyEffect::MorphologyType m orphType, |
| 474 Gr1DKernelEffect::Direction direction) { | 391 Gr1DKernelEffect::Direction directio n) { |
| 475 GrPaint paint; | 392 GrPaint paint; |
| 476 paint.addColorFragmentProcessor(GrMorphologyEffect::Create(texture, | 393 paint.addColorFragmentProcessor(GrMorphologyEffect::Create(texture, |
| 477 direction, | 394 direction, |
| 478 radius, | 395 radius, |
| 479 morphType))->unre f(); | 396 morphType))->unre f(); |
| 480 paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); | 397 paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); |
| 481 drawContext->fillRectToRect(clip, paint, SkMatrix::I(), SkRect::Make(dstRect ), | 398 drawContext->fillRectToRect(clip, paint, SkMatrix::I(), SkRect::Make(dstRect ), |
| 482 SkRect::Make(srcRect)); | 399 SkRect::Make(srcRect)); |
| 483 } | 400 } |
| 484 | 401 |
| 485 void apply_morphology_pass(GrDrawContext* drawContext, | 402 static void apply_morphology_pass(GrDrawContext* drawContext, |
| 486 const GrClip& clip, | 403 const GrClip& clip, |
| 487 GrTexture* texture, | 404 GrTexture* texture, |
| 488 const SkIRect& srcRect, | 405 const SkIRect& srcRect, |
| 489 const SkIRect& dstRect, | 406 const SkIRect& dstRect, |
| 490 int radius, | 407 int radius, |
| 491 GrMorphologyEffect::MorphologyType morphType, | 408 GrMorphologyEffect::MorphologyType morphType, |
| 492 Gr1DKernelEffect::Direction direction) { | 409 Gr1DKernelEffect::Direction direction) { |
| 493 float bounds[2] = { 0.0f, 1.0f }; | 410 float bounds[2] = { 0.0f, 1.0f }; |
| 494 SkIRect lowerSrcRect = srcRect, lowerDstRect = dstRect; | 411 SkIRect lowerSrcRect = srcRect, lowerDstRect = dstRect; |
| 495 SkIRect middleSrcRect = srcRect, middleDstRect = dstRect; | 412 SkIRect middleSrcRect = srcRect, middleDstRect = dstRect; |
| 496 SkIRect upperSrcRect = srcRect, upperDstRect = dstRect; | 413 SkIRect upperSrcRect = srcRect, upperDstRect = dstRect; |
| 497 if (direction == Gr1DKernelEffect::kX_Direction) { | 414 if (direction == Gr1DKernelEffect::kX_Direction) { |
| 498 bounds[0] = (SkIntToScalar(srcRect.left()) + 0.5f) / texture->width(); | 415 bounds[0] = (SkIntToScalar(srcRect.left()) + 0.5f) / texture->width(); |
| 499 bounds[1] = (SkIntToScalar(srcRect.right()) - 0.5f) / texture->width(); | 416 bounds[1] = (SkIntToScalar(srcRect.right()) - 0.5f) / texture->width(); |
| 500 lowerSrcRect.fRight = srcRect.left() + radius; | 417 lowerSrcRect.fRight = srcRect.left() + radius; |
| 501 lowerDstRect.fRight = dstRect.left() + radius; | 418 lowerDstRect.fRight = dstRect.left() + radius; |
| 502 upperSrcRect.fLeft = srcRect.right() - radius; | 419 upperSrcRect.fLeft = srcRect.right() - radius; |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 521 // Draw upper and lower margins with bounds; middle without. | 438 // Draw upper and lower margins with bounds; middle without. |
| 522 apply_morphology_rect(drawContext, clip, texture, lowerSrcRect, lowerDst Rect, radius, | 439 apply_morphology_rect(drawContext, clip, texture, lowerSrcRect, lowerDst Rect, radius, |
| 523 morphType, bounds, direction); | 440 morphType, bounds, direction); |
| 524 apply_morphology_rect(drawContext, clip, texture, upperSrcRect, upperDst Rect, radius, | 441 apply_morphology_rect(drawContext, clip, texture, upperSrcRect, upperDst Rect, radius, |
| 525 morphType, bounds, direction); | 442 morphType, bounds, direction); |
| 526 apply_morphology_rect_no_bounds(drawContext, clip, texture, middleSrcRec t, middleDstRect, | 443 apply_morphology_rect_no_bounds(drawContext, clip, texture, middleSrcRec t, middleDstRect, |
| 527 radius, morphType, direction); | 444 radius, morphType, direction); |
| 528 } | 445 } |
| 529 } | 446 } |
| 530 | 447 |
| 531 bool apply_morphology(const SkBitmap& input, | 448 static sk_sp<SkSpecialImage> apply_morphology(SkSpecialImage* input, |
| 532 const SkIRect& rect, | 449 const SkIRect& rect, |
| 533 GrMorphologyEffect::MorphologyType morphType, | 450 GrMorphologyEffect::MorphologyType morphType, |
| 534 SkISize radius, | 451 SkISize radius) { |
| 535 SkBitmap* dst) { | 452 SkAutoTUnref<GrTexture> srcTexture(SkRef(input->peekTexture())); |
| 536 SkAutoTUnref<GrTexture> srcTexture(SkRef(input.getTexture())); | |
| 537 SkASSERT(srcTexture); | 453 SkASSERT(srcTexture); |
| 538 GrContext* context = srcTexture->getContext(); | 454 GrContext* context = srcTexture->getContext(); |
| 539 | 455 |
| 540 // setup new clip | 456 // setup new clip |
| 541 GrClip clip(SkRect::MakeWH(SkIntToScalar(srcTexture->width()), | 457 GrClip clip(SkRect::MakeWH(SkIntToScalar(srcTexture->width()), |
| 542 SkIntToScalar(srcTexture->height()))); | 458 SkIntToScalar(srcTexture->height()))); |
| 543 | 459 |
| 544 SkIRect dstRect = SkIRect::MakeWH(rect.width(), rect.height()); | 460 SkIRect dstRect = SkIRect::MakeWH(rect.width(), rect.height()); |
| 545 GrSurfaceDesc desc; | 461 GrSurfaceDesc desc; |
| 546 desc.fFlags = kRenderTarget_GrSurfaceFlag; | 462 desc.fFlags = kRenderTarget_GrSurfaceFlag; |
| 547 desc.fWidth = rect.width(); | 463 desc.fWidth = rect.width(); |
| 548 desc.fHeight = rect.height(); | 464 desc.fHeight = rect.height(); |
| 549 desc.fConfig = kSkia8888_GrPixelConfig; | 465 desc.fConfig = kSkia8888_GrPixelConfig; |
| 550 SkIRect srcRect = rect; | 466 SkIRect srcRect = rect; |
| 551 | 467 |
| 468 SkASSERT(radius.width() > 0 || radius.height() > 0); | |
| 469 | |
| 552 if (radius.fWidth > 0) { | 470 if (radius.fWidth > 0) { |
| 553 GrTexture* scratch = context->textureProvider()->createApproxTexture(des c); | 471 GrTexture* scratch = context->textureProvider()->createApproxTexture(des c); |
| 554 if (nullptr == scratch) { | 472 if (!scratch) { |
| 555 return false; | 473 return nullptr; |
| 556 } | 474 } |
| 557 SkAutoTUnref<GrDrawContext> dstDrawContext( | 475 SkAutoTUnref<GrDrawContext> dstDrawContext( |
| 558 context->drawContext(scratch->as RenderTarget())); | 476 context->drawContext(scratch->as RenderTarget())); |
| 559 if (!dstDrawContext) { | 477 if (!dstDrawContext) { |
| 560 return false; | 478 return nullptr; |
| 561 } | 479 } |
| 562 | 480 |
| 563 apply_morphology_pass(dstDrawContext, clip, srcTexture, | 481 apply_morphology_pass(dstDrawContext, clip, srcTexture, |
| 564 srcRect, dstRect, radius.fWidth, morphType, | 482 srcRect, dstRect, radius.fWidth, morphType, |
| 565 Gr1DKernelEffect::kX_Direction); | 483 Gr1DKernelEffect::kX_Direction); |
| 566 SkIRect clearRect = SkIRect::MakeXYWH(dstRect.fLeft, dstRect.fBottom, | 484 SkIRect clearRect = SkIRect::MakeXYWH(dstRect.fLeft, dstRect.fBottom, |
| 567 dstRect.width(), radius.fHeight); | 485 dstRect.width(), radius.fHeight); |
| 568 GrColor clearColor = GrMorphologyEffect::kErode_MorphologyType == morphT ype ? | 486 GrColor clearColor = GrMorphologyEffect::kErode_MorphologyType == morphT ype ? |
| 569 SK_ColorWHITE : | 487 SK_ColorWHITE : |
| 570 SK_ColorTRANSPARENT; | 488 SK_ColorTRANSPARENT; |
| 571 dstDrawContext->clear(&clearRect, clearColor, false); | 489 dstDrawContext->clear(&clearRect, clearColor, false); |
| 572 | 490 |
| 573 srcTexture.reset(scratch); | 491 srcTexture.reset(scratch); |
| 574 srcRect = dstRect; | 492 srcRect = dstRect; |
| 575 } | 493 } |
| 576 if (radius.fHeight > 0) { | 494 if (radius.fHeight > 0) { |
| 577 GrTexture* scratch = context->textureProvider()->createApproxTexture(des c); | 495 GrTexture* scratch = context->textureProvider()->createApproxTexture(des c); |
| 578 if (nullptr == scratch) { | 496 if (!scratch) { |
| 579 return false; | 497 return nullptr; |
| 580 } | 498 } |
| 581 SkAutoTUnref<GrDrawContext> dstDrawContext( | 499 SkAutoTUnref<GrDrawContext> dstDrawContext( |
| 582 context->drawContext(scratch->as RenderTarget())); | 500 context->drawContext(scratch->as RenderTarget())); |
| 583 if (!dstDrawContext) { | 501 if (!dstDrawContext) { |
| 584 return false; | 502 return nullptr; |
| 585 } | 503 } |
| 586 | 504 |
| 587 apply_morphology_pass(dstDrawContext, clip, srcTexture, | 505 apply_morphology_pass(dstDrawContext, clip, srcTexture, |
| 588 srcRect, dstRect, radius.fHeight, morphType, | 506 srcRect, dstRect, radius.fHeight, morphType, |
| 589 Gr1DKernelEffect::kY_Direction); | 507 Gr1DKernelEffect::kY_Direction); |
| 590 | 508 |
| 591 srcTexture.reset(scratch); | 509 srcTexture.reset(scratch); |
| 592 } | 510 } |
| 593 GrWrapTextureInBitmap(srcTexture, rect.width(), rect.height(), false, dst); | 511 |
| 594 return true; | 512 return SkSpecialImage::MakeFromGpu(input->internal_getProxy(), |
| 513 SkIRect::MakeWH(rect.width(), rect.height ()), | |
| 514 kNeedNewImageUniqueID_SpecialImage, | |
| 515 srcTexture); | |
| 595 } | 516 } |
| 517 #endif | |
| 596 | 518 |
| 597 }; | 519 sk_sp<SkSpecialImage> SkMorphologyImageFilter::filterImageGeneric(bool dilate, |
| 520 SkSpecialImage * source, | |
| 521 const Context& ctx, | |
| 522 SkIPoint* offs et) const { | |
| 523 SkIPoint inputOffset = SkIPoint::Make(0, 0); | |
| 524 sk_sp<SkSpecialImage> input(this->filterInput(0, source, ctx, &inputOffset)) ; | |
| 525 if (!input) { | |
| 526 return nullptr; | |
| 527 } | |
| 598 | 528 |
| 599 bool SkMorphologyImageFilter::filterImageGPUGeneric(bool dilate, | 529 SkIRect bounds; |
| 600 Proxy* proxy, | 530 input = this->applyCropRect(this->mapContext(ctx), input.get(), &inputOffset , &bounds); |
| 601 const SkBitmap& src, | 531 if (!input) { |
| 602 const Context& ctx, | 532 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 } | 533 } |
| 610 SkIRect bounds; | 534 |
| 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()), | 535 SkVector radius = SkVector::Make(SkIntToScalar(this->radius().width()), |
| 616 SkIntToScalar(this->radius().height())); | 536 SkIntToScalar(this->radius().height())); |
| 617 ctx.ctm().mapVectors(&radius, 1); | 537 ctx.ctm().mapVectors(&radius, 1); |
| 618 int width = SkScalarFloorToInt(radius.fX); | 538 int width = SkScalarFloorToInt(radius.fX); |
| 619 int height = SkScalarFloorToInt(radius.fY); | 539 int height = SkScalarFloorToInt(radius.fY); |
| 620 | 540 |
| 621 if (width < 0 || height < 0) { | 541 if (width < 0 || height < 0) { |
| 622 return false; | 542 return nullptr; |
| 623 } | 543 } |
| 624 | 544 |
| 625 SkIRect srcBounds = bounds; | 545 SkIRect srcBounds = bounds; |
| 626 srcBounds.offset(-srcOffset); | 546 srcBounds.offset(-inputOffset); |
| 627 if (width == 0 && height == 0) { | 547 |
| 628 input.extractSubset(result, srcBounds); | 548 if (0 == width && 0 == height) { |
| 629 offset->fX = bounds.left(); | 549 offset->fX = bounds.left(); |
| 630 offset->fY = bounds.top(); | 550 offset->fY = bounds.top(); |
| 631 return true; | 551 return input->makeSubset(srcBounds); |
| 632 } | 552 } |
| 633 | 553 |
| 634 GrMorphologyEffect::MorphologyType type = dilate ? GrMorphologyEffect::kDila te_MorphologyType | 554 #if SK_SUPPORT_GPU |
| 635 : GrMorphologyEffect::kErod e_MorphologyType; | 555 if (input->peekTexture()) { |
| 636 if (!apply_morphology(input, srcBounds, type, SkISize::Make(width, height), result)) { | 556 auto type = dilate ? GrMorphologyEffect::kDilate_MorphologyType |
| 637 return false; | 557 : GrMorphologyEffect::kErode_MorphologyType; |
| 558 sk_sp<SkSpecialImage> result(apply_morphology(input.get(), srcBounds, ty pe, | |
| 559 SkISize::Make(width, heigh t))); | |
| 560 if (result) { | |
| 561 offset->fX = bounds.left(); | |
| 562 offset->fY = bounds.top(); | |
| 563 } | |
| 564 return result; | |
| 565 } | |
| 566 #endif | |
| 567 | |
| 568 SkPixmap inputPixmap; | |
| 569 | |
| 570 if (!input->peekPixels(&inputPixmap)) { | |
| 571 return nullptr; | |
| 572 } | |
| 573 | |
| 574 if (inputPixmap.colorType() != kN32_SkColorType) { | |
| 575 return nullptr; | |
| 576 } | |
| 577 | |
| 578 SkImageInfo info = SkImageInfo::Make(bounds.width(), bounds.height(), | |
| 579 inputPixmap.colorType(), inputPixmap.al phaType()); | |
| 580 | |
| 581 SkBitmap dst; | |
| 582 if (!dst.tryAllocPixels(info)) { | |
| 583 return nullptr; | |
| 584 } | |
| 585 | |
| 586 SkAutoLockPixels dstLock(dst); | |
| 587 | |
| 588 SkMorphologyImageFilter::Proc procX, procY; | |
| 589 | |
| 590 if (dilate) { | |
| 591 procX = SkOpts::dilate_x; | |
| 592 procY = SkOpts::dilate_y; | |
| 593 } else { | |
| 594 procX = SkOpts::erode_x; | |
| 595 procY = SkOpts::erode_y; | |
| 596 } | |
| 597 | |
| 598 if (width > 0 && height > 0) { | |
| 599 SkBitmap tmp; | |
| 600 if (!tmp.tryAllocPixels(info)) { | |
| 601 return nullptr; | |
| 602 } | |
| 603 | |
| 604 SkAutoLockPixels tmpLock(tmp); | |
| 605 | |
| 606 call_proc_X(procX, inputPixmap, &tmp, width, srcBounds); | |
| 607 SkIRect tmpBounds = SkIRect::MakeWH(srcBounds.width(), srcBounds.height( )); | |
| 608 call_proc_Y(procY, | |
| 609 tmp.getAddr32(tmpBounds.left(), tmpBounds.top()), tmp.rowByt esAsPixels(), | |
| 610 &dst, height, tmpBounds); | |
| 611 } else if (width > 0) { | |
| 612 call_proc_X(procX, inputPixmap, &dst, width, srcBounds); | |
| 613 } else if (height > 0) { | |
| 614 int shiftPerPixel = SkColorTypeBytesPerPixel(inputPixmap.colorType()) >> 1; | |
|
Stephen White
2016/03/24 15:16:34
As a side note, could we have SkPixmap::getRowByte
robertphillips
2016/03/24 18:08:13
Done.
| |
| 615 call_proc_Y(procY, | |
| 616 inputPixmap.addr32(srcBounds.left(), srcBounds.top()), | |
| 617 inputPixmap.rowBytes() >> shiftPerPixel, | |
| 618 &dst, height, srcBounds); | |
| 638 } | 619 } |
| 639 offset->fX = bounds.left(); | 620 offset->fX = bounds.left(); |
| 640 offset->fY = bounds.top(); | 621 offset->fY = bounds.top(); |
| 641 return true; | 622 |
| 623 return SkSpecialImage::MakeFromRaster(source->internal_getProxy(), | |
| 624 SkIRect::MakeWH(bounds.width(), bounds .height()), | |
|
Stephen White
2016/03/24 14:57:02
Not new to this patch, but could we make the subse
robertphillips
2016/03/24 18:08:13
Acknowledged.
| |
| 625 dst); | |
| 642 } | 626 } |
| 643 | 627 |
| 644 bool SkDilateImageFilter::filterImageGPUDeprecated(Proxy* proxy, const SkBitmap& src, | 628 sk_sp<SkSpecialImage> SkDilateImageFilter::onFilterImage(SkSpecialImage* source, const Context& ctx, |
| 645 const Context& ctx, | 629 SkIPoint* offset) const { |
| 646 SkBitmap* result, SkIPoint* o ffset) const { | 630 return this->filterImageGeneric(true, source, ctx, offset); |
|
Stephen White
2016/03/24 14:57:03
Not new to this patch, but we should probably repl
robertphillips
2016/03/24 18:08:13
Let me do that in a follow up CL. I think this CL
| |
| 647 return this->filterImageGPUGeneric(true, proxy, src, ctx, result, offset); | |
| 648 } | 631 } |
| 649 | 632 |
| 650 bool SkErodeImageFilter::filterImageGPUDeprecated(Proxy* proxy, const SkBitmap& src, | 633 sk_sp<SkSpecialImage> SkErodeImageFilter::onFilterImage(SkSpecialImage* source, const Context& ctx, |
| 651 const Context& ctx, | 634 SkIPoint* offset) const { |
| 652 SkBitmap* result, SkIPoint* of fset) const { | 635 return this->filterImageGeneric(false, source, ctx, offset); |
| 653 return this->filterImageGPUGeneric(false, proxy, src, ctx, result, offset); | |
| 654 } | 636 } |
| 655 | 637 |
| 656 #endif | |
| OLD | NEW |