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 |