Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6)

Side by Side Diff: src/effects/SkAlphaThresholdFilter.cpp

Issue 1879643003: Switch AlphaThresholdFilter over to new onFilterImage interface (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: clean up Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« include/core/SkImageFilter.h ('K') | « src/core/SkImageFilter.cpp ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2013 Google Inc. 2 * Copyright 2013 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkAlphaThresholdFilter.h" 8 #include "SkAlphaThresholdFilter.h"
9 9
10 #include "SkBitmap.h" 10 #include "SkBitmap.h"
11 #include "SkDevice.h"
12 #include "SkReadBuffer.h" 11 #include "SkReadBuffer.h"
12 #include "SkSpecialImage.h"
13 #include "SkWriteBuffer.h" 13 #include "SkWriteBuffer.h"
14 #include "SkRegion.h" 14 #include "SkRegion.h"
15 #if SK_SUPPORT_GPU 15 #if SK_SUPPORT_GPU
16 #include "GrDrawContext.h" 16 #include "GrDrawContext.h"
17 #endif 17 #endif
18 18
19 class SK_API SkAlphaThresholdFilterImpl : public SkImageFilter { 19 class SK_API SkAlphaThresholdFilterImpl : public SkImageFilter {
20 public: 20 public:
21 SkAlphaThresholdFilterImpl(const SkRegion& region, SkScalar innerThreshold, 21 SkAlphaThresholdFilterImpl(const SkRegion& region, SkScalar innerThreshold,
22 SkScalar outerThreshold, sk_sp<SkImageFilter> inp ut); 22 SkScalar outerThreshold, sk_sp<SkImageFilter> inp ut);
23 23
24 SK_TO_STRING_OVERRIDE() 24 SK_TO_STRING_OVERRIDE()
25 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkAlphaThresholdFilterIm pl) 25 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkAlphaThresholdFilterIm pl)
26 friend void SkAlphaThresholdFilter::InitializeFlattenables(); 26 friend void SkAlphaThresholdFilter::InitializeFlattenables();
27 27
28 protected: 28 protected:
29 void flatten(SkWriteBuffer&) const override; 29 void flatten(SkWriteBuffer&) const override;
30 30
31 bool onFilterImageDeprecated(Proxy*, const SkBitmap& src, const Context&, 31 sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,
32 SkBitmap* result, SkIPoint* offset) const overr ide; 32 SkIPoint* offset) const override;
33
33 #if SK_SUPPORT_GPU 34 #if SK_SUPPORT_GPU
34 bool asFragmentProcessor(GrFragmentProcessor**, GrTexture*, const SkMatrix&, 35 GrTexture* createMaskTexture(GrContext*, const SkMatrix&, const SkIRect& bou nds) const;
Stephen White 2016/04/11 20:48:20 Should this return an sk_sp<GrTexture> instead?
robertphillips 2016/04/12 15:36:39 Done.
35 const SkIRect& bounds) const override;
36 #endif 36 #endif
37 37
38 private: 38 private:
39 SkRegion fRegion; 39 SkRegion fRegion;
40 SkScalar fInnerThreshold; 40 SkScalar fInnerThreshold;
41 SkScalar fOuterThreshold; 41 SkScalar fOuterThreshold;
42 typedef SkImageFilter INHERITED; 42 typedef SkImageFilter INHERITED;
43 }; 43 };
44 44
45 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkAlphaThresholdFilter) 45 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkAlphaThresholdFilter)
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
278 SkScalar innerThreshold, 278 SkScalar innerThreshold,
279 SkScalar outerThreshold, 279 SkScalar outerThreshold,
280 sk_sp<SkImageFilter> inpu t) 280 sk_sp<SkImageFilter> inpu t)
281 : INHERITED(&input, 1, nullptr) 281 : INHERITED(&input, 1, nullptr)
282 , fRegion(region) 282 , fRegion(region)
283 , fInnerThreshold(innerThreshold) 283 , fInnerThreshold(innerThreshold)
284 , fOuterThreshold(outerThreshold) { 284 , fOuterThreshold(outerThreshold) {
285 } 285 }
286 286
287 #if SK_SUPPORT_GPU 287 #if SK_SUPPORT_GPU
288 bool SkAlphaThresholdFilterImpl::asFragmentProcessor(GrFragmentProcessor** fp, 288 GrTexture* SkAlphaThresholdFilterImpl::createMaskTexture(GrContext* context,
289 GrTexture* texture, 289 const SkMatrix& inMatri x,
290 const SkMatrix& inMatrix, 290 const SkIRect& bounds) const {
291 const SkIRect& bounds) cons t { 291 GrSurfaceDesc maskDesc;
292 if (fp) { 292 if (context->caps()->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) {
293 GrContext* context = texture->getContext(); 293 maskDesc.fConfig = kAlpha_8_GrPixelConfig;
294 GrSurfaceDesc maskDesc; 294 } else {
295 if (context->caps()->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) { 295 maskDesc.fConfig = kRGBA_8888_GrPixelConfig;
296 maskDesc.fConfig = kAlpha_8_GrPixelConfig; 296 }
297 } else { 297 maskDesc.fFlags = kRenderTarget_GrSurfaceFlag;
298 maskDesc.fConfig = kRGBA_8888_GrPixelConfig; 298 // Add one pixel of border to ensure that clamp mode will be all zeros
299 } 299 // the outside.
300 maskDesc.fFlags = kRenderTarget_GrSurfaceFlag; 300 maskDesc.fWidth = bounds.width();
301 // Add one pixel of border to ensure that clamp mode will be all zeros 301 maskDesc.fHeight = bounds.height();
302 // the outside. 302 SkAutoTUnref<GrTexture> maskTexture(context->textureProvider()->createApprox Texture(maskDesc));
303 maskDesc.fWidth = bounds.width(); 303 if (!maskTexture) {
304 maskDesc.fHeight = bounds.height(); 304 return nullptr;
305 SkAutoTUnref<GrTexture> maskTexture( 305 }
306 context->textureProvider()->createApproxTexture(maskDesc));
307 if (!maskTexture) {
308 return false;
309 }
310 306
311 SkAutoTUnref<GrDrawContext> drawContext( 307 SkAutoTUnref<GrDrawContext> drawContext(context->drawContext(maskTexture->as RenderTarget()));
312 context->drawContext(maskTexture->as RenderTarget())); 308 if (!drawContext) {
313 if (drawContext) { 309 return nullptr;
314 GrPaint grPaint; 310 }
315 grPaint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
316 SkRegion::Iterator iter(fRegion);
317 drawContext->clear(nullptr, 0x0, true);
318 311
319 GrClip clip(SkRect::Make(SkIRect::MakeWH(bounds.width(), bounds.heig ht()))); 312 GrPaint grPaint;
320 while (!iter.done()) { 313 grPaint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
321 SkRect rect = SkRect::Make(iter.rect()); 314 SkRegion::Iterator iter(fRegion);
322 drawContext->drawRect(clip, grPaint, inMatrix, rect); 315 drawContext->clear(nullptr, 0x0, true);
Stephen White 2016/04/11 20:48:20 Add a reference to the "clear may not be necessary
robertphillips 2016/04/12 15:36:39 This one is necessary since we don't know where th
Stephen White 2016/04/12 15:41:40 Good point. Perhaps we could do a pass unioning al
323 iter.next();
324 }
325 }
326 316
327 *fp = AlphaThresholdEffect::Create(texture, 317 GrClip clip(SkRect::Make(SkIRect::MakeWH(bounds.width(), bounds.height())));
328 maskTexture, 318 while (!iter.done()) {
329 fInnerThreshold, 319 SkRect rect = SkRect::Make(iter.rect());
330 fOuterThreshold, 320 drawContext->drawRect(clip, grPaint, inMatrix, rect);
331 bounds); 321 iter.next();
332 } 322 }
333 return true; 323
324 return maskTexture.release();
334 } 325 }
335 #endif 326 #endif
336 327
337 void SkAlphaThresholdFilterImpl::flatten(SkWriteBuffer& buffer) const { 328 void SkAlphaThresholdFilterImpl::flatten(SkWriteBuffer& buffer) const {
338 this->INHERITED::flatten(buffer); 329 this->INHERITED::flatten(buffer);
339 buffer.writeScalar(fInnerThreshold); 330 buffer.writeScalar(fInnerThreshold);
340 buffer.writeScalar(fOuterThreshold); 331 buffer.writeScalar(fOuterThreshold);
341 buffer.writeRegion(fRegion); 332 buffer.writeRegion(fRegion);
342 } 333 }
343 334
344 bool SkAlphaThresholdFilterImpl::onFilterImageDeprecated(Proxy* proxy, const SkB itmap& src, 335 sk_sp<SkSpecialImage> SkAlphaThresholdFilterImpl::onFilterImage(SkSpecialImage* source,
345 const Context& ctx, SkB itmap* dst, 336 const Context& c tx,
346 SkIPoint* offset) const { 337 SkIPoint* offset ) const {
338 SkIPoint inputOffset = SkIPoint::Make(0, 0);
339 sk_sp<SkSpecialImage> input(this->filterInput(0, source, ctx, &inputOffset)) ;
340 if (!input) {
341 return nullptr;
342 }
347 343
348 if (src.colorType() != kN32_SkColorType) { 344 const SkIRect inputBounds = SkIRect::MakeXYWH(inputOffset.x(), inputOffset.y (),
349 return false; 345 input->width(), input->height( ));
346
347 SkIRect bounds;
348 if (!this->applyCropRect(ctx, inputBounds, &bounds)) {
Stephen White 2016/04/11 20:48:20 Given that there's no create param to add a crop r
robertphillips 2016/04/12 15:36:39 applyCropRect also does interesting things with th
Stephen White 2016/04/12 15:41:39 Thanks!
349 return nullptr;
350 } 350 }
351 351
352 #if SK_SUPPORT_GPU
353 if (source->isTextureBacked()) {
354 GrContext* context = source->getContext();
355
356 sk_sp<GrTexture> inputTexture(input->asTextureRef(context));
357 if (!inputTexture) {
Stephen White 2016/04/11 20:48:20 Please assert this is non-null instead.
robertphillips 2016/04/12 15:36:39 Done.
358 return nullptr;
359 }
360
361 offset->fX = bounds.left();
362 offset->fY = bounds.top();
363
364 bounds.offset(-inputOffset);
365
366 SkMatrix matrix(ctx.ctm());
367 matrix.postTranslate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bound s.top()));
368
369 sk_sp<GrTexture> maskTexture(this->createMaskTexture(context, matrix, bo unds));
370 if (!maskTexture) {
371 return nullptr;
372 }
373
374 // SRGBTODO: handle sRGB here
Stephen White 2016/04/11 20:48:20 Is there a bug for that?
robertphillips 2016/04/12 15:36:39 This is Brian O.'s TODO. I believe he is just trac
Stephen White 2016/04/12 15:41:39 Acknowledged.
375 sk_sp<GrFragmentProcessor> fp(AlphaThresholdEffect::Create(inputTexture. get(),
376 maskTexture.g et(),
377 fInnerThresho ld,
378 fOuterThresho ld,
379 bounds));
380 if (!fp) {
381 return nullptr;
382 }
383
384 GrPaint paint;
385 paint.addColorFragmentProcessor(fp.get());
386 paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
387
388 GrSurfaceDesc desc;
389 desc.fFlags = kRenderTarget_GrSurfaceFlag;
390 desc.fWidth = bounds.width();
391 desc.fHeight = bounds.height();
392 desc.fConfig = kRGBA_8888_GrPixelConfig;
393
394 SkAutoTUnref<GrTexture> dst(context->textureProvider()->createApproxText ure(desc));
395 if (!dst) {
396 return nullptr;
397 }
398
399 SkAutoTUnref<GrDrawContext> drawContext(context->drawContext(dst->asRend erTarget()));
400 if (!drawContext) {
401 return nullptr;
402 }
403
404 SkRect srcRect = SkRect::Make(bounds);
405 SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
406 GrClip clip(dstRect);
407 drawContext->fillRectToRect(clip, paint, SkMatrix::I(), dstRect, srcRect );
408
409 return SkSpecialImage::MakeFromGpu(source->internal_getProxy(),
410 SkIRect::MakeWH(bounds.width(), bound s.height()),
411 kNeedNewImageUniqueID_SpecialImage,
412 dst);
Stephen White 2016/04/11 20:48:20 Kind of a shame the GPU code got so much longer in
robertphillips 2016/04/12 15:36:39 I've added a SkImageFilter::DrawWithFP helper func
Stephen White 2016/04/12 15:41:39 Acknowledged.
413 }
414 #endif
415
416 SkBitmap inputBM;
417
418 if (!input->getROPixels(&inputBM)) {
419 return nullptr;
420 }
421
422 if (inputBM.colorType() != kN32_SkColorType) {
423 return nullptr;
424 }
425
426 SkAutoLockPixels inputLock(inputBM);
427
428 if (!inputBM.getPixels() || inputBM.width() <= 0 || inputBM.height() <= 0) {
429 return nullptr;
430 }
431
432
352 SkMatrix localInverse; 433 SkMatrix localInverse;
353 if (!ctx.ctm().invert(&localInverse)) { 434 if (!ctx.ctm().invert(&localInverse)) {
354 return false; 435 return nullptr;
355 } 436 }
356 437
357 SkAutoLockPixels alp(src); 438 SkImageInfo info = SkImageInfo::MakeN32(bounds.width(), bounds.height(),
358 SkASSERT(src.getPixels()); 439 inputBM.alphaType());
359 if (!src.getPixels() || src.width() <= 0 || src.height() <= 0) { 440
360 return false; 441 SkBitmap dst;
442 if (!dst.tryAllocPixels(info)) {
443 return nullptr;
361 } 444 }
362 445
363 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(src.width(), src.heigh t())); 446 SkAutoLockPixels dstLock(dst);
364 if (!device) {
365 return false;
366 }
367 *dst = device->accessBitmap(false);
368 SkAutoLockPixels alp_dst(*dst);
369 447
370 U8CPU innerThreshold = (U8CPU)(fInnerThreshold * 0xFF); 448 U8CPU innerThreshold = (U8CPU)(fInnerThreshold * 0xFF);
371 U8CPU outerThreshold = (U8CPU)(fOuterThreshold * 0xFF); 449 U8CPU outerThreshold = (U8CPU)(fOuterThreshold * 0xFF);
372 SkColor* sptr = src.getAddr32(0, 0); 450 SkColor* dptr = dst.getAddr32(0, 0);
373 SkColor* dptr = dst->getAddr32(0, 0); 451 int dstWidth = dst.width(), dstHeight = dst.height();
374 int width = src.width(), height = src.height(); 452 for (int y = 0; y < dstHeight; ++y) {
375 for (int y = 0; y < height; ++y) { 453 const SkColor* sptr = inputBM.getAddr32(bounds.fLeft, bounds.fTop+y);
376 for (int x = 0; x < width; ++x) { 454
377 const SkColor& source = sptr[y * width + x]; 455 for (int x = 0; x < dstWidth; ++x) {
378 SkColor output_color(source); 456 const SkColor& source = sptr[x];
457 SkColor outputColor(source);
379 SkPoint position; 458 SkPoint position;
380 localInverse.mapXY((SkScalar)x, (SkScalar)y, &position); 459 localInverse.mapXY((SkScalar)x + bounds.fLeft, (SkScalar)y + bounds. fTop, &position);
381 if (fRegion.contains((int32_t)position.x(), (int32_t)position.y())) { 460 if (fRegion.contains((int32_t)position.x(), (int32_t)position.y())) {
382 if (SkColorGetA(source) < innerThreshold) { 461 if (SkColorGetA(source) < innerThreshold) {
383 U8CPU alpha = SkColorGetA(source); 462 U8CPU alpha = SkColorGetA(source);
384 if (alpha == 0) 463 if (alpha == 0) {
385 alpha = 1; 464 alpha = 1;
465 }
386 float scale = (float)innerThreshold / alpha; 466 float scale = (float)innerThreshold / alpha;
387 output_color = SkColorSetARGB(innerThreshold, 467 outputColor = SkColorSetARGB(innerThreshold,
388 (U8CPU)(SkColorGetR(source) * scale), 468 (U8CPU)(SkColorGetR(source) * scale),
389 (U8CPU)(SkColorGetG(source) * scale), 469 (U8CPU)(SkColorGetG(source) * scale),
390 (U8CPU)(SkColorGetB(source) * scale)); 470 (U8CPU)(SkColorGetB(source) * scale));
391 } 471 }
392 } else { 472 } else {
393 if (SkColorGetA(source) > outerThreshold) { 473 if (SkColorGetA(source) > outerThreshold) {
394 float scale = (float)outerThreshold / SkColorGetA(source); 474 float scale = (float)outerThreshold / SkColorGetA(source);
395 output_color = SkColorSetARGB(outerThreshold, 475 outputColor = SkColorSetARGB(outerThreshold,
396 (U8CPU)(SkColorGetR(source) * scale), 476 (U8CPU)(SkColorGetR(source) * scale),
397 (U8CPU)(SkColorGetG(source) * scale), 477 (U8CPU)(SkColorGetG(source) * scale),
398 (U8CPU)(SkColorGetB(source) * scale)); 478 (U8CPU)(SkColorGetB(source) * scale));
399 } 479 }
400 } 480 }
401 dptr[y * dst->width() + x] = output_color; 481 dptr[y * dstWidth + x] = outputColor;
402 } 482 }
403 } 483 }
404 484
405 return true; 485 offset->fX = bounds.left();
486 offset->fY = bounds.top();
487 return SkSpecialImage::MakeFromRaster(source->internal_getProxy(),
488 SkIRect::MakeWH(bounds.width(), bounds .height()),
489 dst);
406 } 490 }
407 491
408 #ifndef SK_IGNORE_TO_STRING 492 #ifndef SK_IGNORE_TO_STRING
409 void SkAlphaThresholdFilterImpl::toString(SkString* str) const { 493 void SkAlphaThresholdFilterImpl::toString(SkString* str) const {
410 str->appendf("SkAlphaThresholdImageFilter: ("); 494 str->appendf("SkAlphaThresholdImageFilter: (");
411 str->appendf("inner: %f outer: %f", fInnerThreshold, fOuterThreshold); 495 str->appendf("inner: %f outer: %f", fInnerThreshold, fOuterThreshold);
412 str->append(")"); 496 str->append(")");
413 } 497 }
414 #endif 498 #endif
OLDNEW
« include/core/SkImageFilter.h ('K') | « src/core/SkImageFilter.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698