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 |