| Index: src/effects/SkXfermodeImageFilter.cpp
|
| diff --git a/src/effects/SkXfermodeImageFilter.cpp b/src/effects/SkXfermodeImageFilter.cpp
|
| index 330f8391528328c8b00be2eec2c0172bd6c550ee..af58a644eeeb5e57efbe80111569418d6ffeae07 100644
|
| --- a/src/effects/SkXfermodeImageFilter.cpp
|
| +++ b/src/effects/SkXfermodeImageFilter.cpp
|
| @@ -6,10 +6,12 @@
|
| */
|
|
|
| #include "SkXfermodeImageFilter.h"
|
| +
|
| #include "SkCanvas.h"
|
| -#include "SkDevice.h"
|
| #include "SkColorPriv.h"
|
| #include "SkReadBuffer.h"
|
| +#include "SkSpecialImage.h"
|
| +#include "SkSpecialSurface.h"
|
| #include "SkWriteBuffer.h"
|
| #include "SkXfermode.h"
|
| #if SK_SUPPORT_GPU
|
| @@ -35,14 +37,13 @@ SkXfermodeImageFilter::SkXfermodeImageFilter(sk_sp<SkXfermode> mode,
|
| sk_sp<SkImageFilter> inputs[2],
|
| const CropRect* cropRect)
|
| : INHERITED(inputs, 2, cropRect)
|
| - , fMode(std::move(mode))
|
| -{}
|
| + , fMode(std::move(mode)) {
|
| +}
|
|
|
| sk_sp<SkFlattenable> SkXfermodeImageFilter::CreateProc(SkReadBuffer& buffer) {
|
| SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 2);
|
| sk_sp<SkXfermode> mode(buffer.readXfermode());
|
| - return Make(std::move(mode), common.getInput(0), common.getInput(1),
|
| - &common.cropRect());
|
| + return Make(std::move(mode), common.getInput(0), common.getInput(1), &common.cropRect());
|
| }
|
|
|
| void SkXfermodeImageFilter::flatten(SkWriteBuffer& buffer) const {
|
| @@ -50,51 +51,83 @@ void SkXfermodeImageFilter::flatten(SkWriteBuffer& buffer) const {
|
| buffer.writeFlattenable(fMode.get());
|
| }
|
|
|
| -bool SkXfermodeImageFilter::onFilterImageDeprecated(Proxy* proxy,
|
| - const SkBitmap& src,
|
| - const Context& ctx,
|
| - SkBitmap* dst,
|
| - SkIPoint* offset) const {
|
| - SkBitmap background = src, foreground = src;
|
| +sk_sp<SkSpecialImage> SkXfermodeImageFilter::onFilterImage(SkSpecialImage* source,
|
| + const Context& ctx,
|
| + SkIPoint* offset) const {
|
| SkIPoint backgroundOffset = SkIPoint::Make(0, 0);
|
| - if (!this->filterInputDeprecated(0, proxy, src, ctx, &background, &backgroundOffset)) {
|
| - background.reset();
|
| - }
|
| + sk_sp<SkSpecialImage> background(this->filterInput(0, source, ctx, &backgroundOffset));
|
| +
|
| SkIPoint foregroundOffset = SkIPoint::Make(0, 0);
|
| - if (!this->filterInputDeprecated(1, proxy, src, ctx, &foreground, &foregroundOffset)) {
|
| - foreground.reset();
|
| + sk_sp<SkSpecialImage> foreground(this->filterInput(1, source, ctx, &foregroundOffset));
|
| +
|
| + SkIRect foregroundBounds = SkIRect::EmptyIRect();
|
| + if (foreground) {
|
| + foregroundBounds = SkIRect::MakeXYWH(foregroundOffset.x(), foregroundOffset.y(),
|
| + foreground->width(), foreground->height());
|
| }
|
|
|
| - SkIRect foregroundBounds = foreground.bounds();
|
| - foregroundBounds.offset(foregroundOffset);
|
| - SkIRect srcBounds = background.bounds();
|
| - srcBounds.offset(backgroundOffset);
|
| + SkIRect srcBounds = SkIRect::EmptyIRect();
|
| + if (background) {
|
| + srcBounds = SkIRect::MakeXYWH(backgroundOffset.x(), backgroundOffset.y(),
|
| + background->width(), background->height());
|
| + }
|
| +
|
| srcBounds.join(foregroundBounds);
|
| + if (srcBounds.isEmpty()) {
|
| + return nullptr;
|
| + }
|
| +
|
| SkIRect bounds;
|
| if (!this->applyCropRect(ctx, srcBounds, &bounds)) {
|
| - return false;
|
| + return nullptr;
|
| + }
|
| +
|
| + offset->fX = bounds.left();
|
| + offset->fY = bounds.top();
|
| +
|
| +#if SK_SUPPORT_GPU
|
| + if (source->isTextureBacked()) {
|
| + return this->filterImageGPU(source,
|
| + background, backgroundOffset,
|
| + foreground, foregroundOffset,
|
| + bounds);
|
| }
|
| +#endif
|
|
|
| - SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height()));
|
| - if (nullptr == device.get()) {
|
| - return false;
|
| + const SkImageInfo info = SkImageInfo::MakeN32(bounds.width(), bounds.height(),
|
| + kPremul_SkAlphaType);
|
| + sk_sp<SkSpecialSurface> surf(source->makeSurface(info));
|
| + if (!surf) {
|
| + return nullptr;
|
| }
|
| - SkCanvas canvas(device);
|
| - canvas.translate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top()));
|
| +
|
| + SkCanvas* canvas = surf->getCanvas();
|
| + SkASSERT(canvas);
|
| +
|
| + canvas->translate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top()));
|
| +
|
| SkPaint paint;
|
| paint.setXfermodeMode(SkXfermode::kSrc_Mode);
|
| - canvas.drawBitmap(background, SkIntToScalar(backgroundOffset.fX),
|
| - SkIntToScalar(backgroundOffset.fY), &paint);
|
| +
|
| + if (background) {
|
| + background->draw(canvas,
|
| + SkIntToScalar(backgroundOffset.fX), SkIntToScalar(backgroundOffset.fY),
|
| + &paint);
|
| + }
|
| +
|
| paint.setXfermode(fMode);
|
| - canvas.drawBitmap(foreground, SkIntToScalar(foregroundOffset.fX),
|
| - SkIntToScalar(foregroundOffset.fY), &paint);
|
| - canvas.clipRect(SkRect::Make(foregroundBounds), SkRegion::kDifference_Op);
|
| +
|
| + if (foreground) {
|
| + foreground->draw(canvas,
|
| + SkIntToScalar(foregroundOffset.fX), SkIntToScalar(foregroundOffset.fY),
|
| + &paint);
|
| + }
|
| +
|
| + canvas->clipRect(SkRect::Make(foregroundBounds), SkRegion::kDifference_Op);
|
| paint.setColor(SK_ColorTRANSPARENT);
|
| - canvas.drawPaint(paint);
|
| - *dst = device->accessBitmap(false);
|
| - offset->fX = bounds.left();
|
| - offset->fY = bounds.top();
|
| - return true;
|
| + canvas->drawPaint(paint);
|
| +
|
| + return surf->makeImageSnapshot();
|
| }
|
|
|
| #ifndef SK_IGNORE_TO_STRING
|
| @@ -121,46 +154,26 @@ void SkXfermodeImageFilter::toString(SkString* str) const {
|
|
|
| #if SK_SUPPORT_GPU
|
|
|
| -bool SkXfermodeImageFilter::canFilterImageGPU() const {
|
| - return !this->cropRectIsSet();
|
| -}
|
| -
|
| #include "SkXfermode_proccoeff.h"
|
|
|
| -bool SkXfermodeImageFilter::filterImageGPUDeprecated(Proxy* proxy,
|
| - const SkBitmap& src,
|
| - const Context& ctx,
|
| - SkBitmap* result,
|
| - SkIPoint* offset) const {
|
| - GrContext* context = nullptr;
|
| - SkBitmap background = src;
|
| - SkIPoint backgroundOffset = SkIPoint::Make(0, 0);
|
| - if (!this->filterInputGPUDeprecated(0, proxy, src, ctx, &background, &backgroundOffset)) {
|
| - background.reset();
|
| - }
|
| - GrTexture* backgroundTex = background.getTexture();
|
| - if (backgroundTex) {
|
| - context = backgroundTex->getContext();
|
| - }
|
| +sk_sp<SkSpecialImage> SkXfermodeImageFilter::filterImageGPU(SkSpecialImage* source,
|
| + sk_sp<SkSpecialImage> background,
|
| + const SkIPoint& backgroundOffset,
|
| + sk_sp<SkSpecialImage> foreground,
|
| + const SkIPoint& foregroundOffset,
|
| + const SkIRect& bounds) const {
|
| + SkASSERT(source->isTextureBacked());
|
|
|
| - SkBitmap foreground = src;
|
| - SkIPoint foregroundOffset = SkIPoint::Make(0, 0);
|
| - if (!this->filterInputGPUDeprecated(1, proxy, src, ctx, &foreground, &foregroundOffset)) {
|
| - foreground.reset();
|
| - }
|
| - GrTexture* foregroundTex = foreground.getTexture();
|
| - if (foregroundTex) {
|
| - context = foregroundTex->getContext();
|
| - }
|
| + GrContext* context = source->getContext();
|
|
|
| - if (!context) {
|
| - return false;
|
| + sk_sp<GrTexture> backgroundTex, foregroundTex;
|
| +
|
| + if (background) {
|
| + backgroundTex.reset(background->asTextureRef(context));
|
| }
|
|
|
| - SkIRect bounds = background.bounds().makeOffset(backgroundOffset.x(), backgroundOffset.y());
|
| - bounds.join(foreground.bounds().makeOffset(foregroundOffset.x(), foregroundOffset.y()));
|
| - if (bounds.isEmpty()) {
|
| - return false;
|
| + if (foreground) {
|
| + foregroundTex.reset(foreground->asTextureRef(context));
|
| }
|
|
|
| GrSurfaceDesc desc;
|
| @@ -170,7 +183,7 @@ bool SkXfermodeImageFilter::filterImageGPUDeprecated(Proxy* proxy,
|
| desc.fConfig = kSkia8888_GrPixelConfig;
|
| SkAutoTUnref<GrTexture> dst(context->textureProvider()->createApproxTexture(desc));
|
| if (!dst) {
|
| - return false;
|
| + return nullptr;
|
| }
|
|
|
| GrPaint paint;
|
| @@ -183,8 +196,9 @@ bool SkXfermodeImageFilter::filterImageGPUDeprecated(Proxy* proxy,
|
| backgroundMatrix.preTranslate(SkIntToScalar(-backgroundOffset.fX),
|
| SkIntToScalar(-backgroundOffset.fY));
|
| bgFP.reset(GrTextureDomainEffect::Create(
|
| - backgroundTex, backgroundMatrix,
|
| - GrTextureDomain::MakeTexelDomain(backgroundTex, background.bounds()),
|
| + backgroundTex.get(), backgroundMatrix,
|
| + GrTextureDomain::MakeTexelDomain(backgroundTex.get(),
|
| + background->subset()),
|
| GrTextureDomain::kDecal_Mode,
|
| GrTextureParams::kNone_FilterMode));
|
| } else {
|
| @@ -201,8 +215,9 @@ bool SkXfermodeImageFilter::filterImageGPUDeprecated(Proxy* proxy,
|
| SkAutoTUnref<const GrFragmentProcessor> foregroundFP;
|
|
|
| foregroundFP.reset(GrTextureDomainEffect::Create(
|
| - foregroundTex, foregroundMatrix,
|
| - GrTextureDomain::MakeTexelDomain(foregroundTex, foreground.bounds()),
|
| + foregroundTex.get(), foregroundMatrix,
|
| + GrTextureDomain::MakeTexelDomain(foregroundTex.get(),
|
| + foreground->subset()),
|
| GrTextureDomain::kDecal_Mode,
|
| GrTextureParams::kNone_FilterMode));
|
|
|
| @@ -235,17 +250,17 @@ bool SkXfermodeImageFilter::filterImageGPUDeprecated(Proxy* proxy,
|
|
|
| SkAutoTUnref<GrDrawContext> drawContext(context->drawContext(dst->asRenderTarget()));
|
| if (!drawContext) {
|
| - return false;
|
| + return nullptr;
|
| }
|
|
|
| SkMatrix matrix;
|
| matrix.setTranslate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top()));
|
| drawContext->drawRect(GrClip::WideOpen(), paint, matrix, SkRect::Make(bounds));
|
|
|
| - offset->fX = bounds.left();
|
| - offset->fY = bounds.top();
|
| - GrWrapTextureInBitmap(dst, bounds.width(), bounds.height(), false, result);
|
| - return true;
|
| + return SkSpecialImage::MakeFromGpu(source->internal_getProxy(),
|
| + SkIRect::MakeWH(bounds.width(), bounds.height()),
|
| + kNeedNewImageUniqueID_SpecialImage,
|
| + dst.get());
|
| }
|
|
|
| #endif
|
|
|