static sk_sp<SkSpecialImage> apply_morphology(
                                          GrContext* context,
                                          SkSpecialImage* input,
                                          const SkIRect& rect,
                                          GrMorphologyEffect::Type morphType,
                                          SkISize radius,
                                          const SkImageFilter::OutputProperties& outputProperties) {
    sk_sp<GrTextureProxy> srcTexture(input->asTextureProxyRef(context));
    SkASSERT(srcTexture);
    sk_sp<SkColorSpace> colorSpace = sk_ref_sp(outputProperties.colorSpace());
    GrPixelConfig config = SkColorType2GrPixelConfig(outputProperties.colorType());

    // setup new clip
    const GrFixedClip clip(SkIRect::MakeWH(srcTexture->width(), srcTexture->height()));

    const SkIRect dstRect = SkIRect::MakeWH(rect.width(), rect.height());
    SkIRect srcRect = rect;

    SkASSERT(radius.width() > 0 || radius.height() > 0);

    if (radius.fWidth > 0) {
        sk_sp<GrRenderTargetContext> dstRTContext(
            context->contextPriv().makeDeferredRenderTargetContext(
                SkBackingFit::kApprox, rect.width(), rect.height(), config, colorSpace));
        if (!dstRTContext) {
            return nullptr;
        }

        apply_morphology_pass(dstRTContext.get(), clip, std::move(srcTexture), srcRect, dstRect,
                              radius.fWidth, morphType, GrMorphologyEffect::Direction::kX);
        SkIRect clearRect = SkIRect::MakeXYWH(dstRect.fLeft, dstRect.fBottom,
                                              dstRect.width(), radius.fHeight);
        GrColor clearColor =
                GrMorphologyEffect::Type::kErode == morphType ? SK_ColorWHITE : SK_ColorTRANSPARENT;
        dstRTContext->clear(&clearRect, clearColor, GrRenderTargetContext::CanClearFullscreen::kNo);

        srcTexture = dstRTContext->asTextureProxyRef();
        srcRect = dstRect;
    }
    if (radius.fHeight > 0) {
        sk_sp<GrRenderTargetContext> dstRTContext(
            context->contextPriv().makeDeferredRenderTargetContext(
                SkBackingFit::kApprox, rect.width(), rect.height(), config, colorSpace));
        if (!dstRTContext) {
            return nullptr;
        }

        apply_morphology_pass(dstRTContext.get(), clip, std::move(srcTexture), srcRect, dstRect,
                              radius.fHeight, morphType, GrMorphologyEffect::Direction::kY);

        srcTexture = dstRTContext->asTextureProxyRef();
    }

    return SkSpecialImage::MakeDeferredFromGpu(context,
                                               SkIRect::MakeWH(rect.width(), rect.height()),
                                               kNeedNewImageUniqueID_SpecialImage,
                                               std::move(srcTexture), std::move(colorSpace),
                                               &input->props());
}
Ejemplo n.º 2
0
static sk_sp<SkSpecialImage> apply_morphology(GrContext* context,
                                              SkSpecialImage* input,
                                              const SkIRect& rect,
                                              GrMorphologyEffect::MorphologyType morphType,
                                              SkISize radius) {
    SkAutoTUnref<GrTexture> srcTexture(input->asTextureRef(context));
    SkASSERT(srcTexture);

    // setup new clip
    GrClip clip(SkRect::MakeWH(SkIntToScalar(srcTexture->width()),
                               SkIntToScalar(srcTexture->height())));

    SkIRect dstRect = SkIRect::MakeWH(rect.width(), rect.height());
    GrSurfaceDesc desc;
    desc.fFlags = kRenderTarget_GrSurfaceFlag;
    desc.fWidth = rect.width();
    desc.fHeight = rect.height();
    desc.fConfig = kSkia8888_GrPixelConfig;
    SkIRect srcRect = rect;

    SkASSERT(radius.width() > 0 || radius.height() > 0);

    if (radius.fWidth > 0) {
        GrTexture* scratch = context->textureProvider()->createApproxTexture(desc);
        if (!scratch) {
            return nullptr;
        }
        SkAutoTUnref<GrDrawContext> dstDrawContext(
                                                context->drawContext(scratch->asRenderTarget()));
        if (!dstDrawContext) {
            return nullptr;
        }

        apply_morphology_pass(dstDrawContext, clip, srcTexture,
                              srcRect, dstRect, radius.fWidth, morphType,
                              Gr1DKernelEffect::kX_Direction);
        SkIRect clearRect = SkIRect::MakeXYWH(dstRect.fLeft, dstRect.fBottom,
                                              dstRect.width(), radius.fHeight);
        GrColor clearColor = GrMorphologyEffect::kErode_MorphologyType == morphType ?
                                SK_ColorWHITE :
                                SK_ColorTRANSPARENT;
        dstDrawContext->clear(&clearRect, clearColor, false);

        srcTexture.reset(scratch);
        srcRect = dstRect;
    }
    if (radius.fHeight > 0) {
        GrTexture* scratch = context->textureProvider()->createApproxTexture(desc);
        if (!scratch) {
            return nullptr;
        }
        SkAutoTUnref<GrDrawContext> dstDrawContext(
                                                context->drawContext(scratch->asRenderTarget()));
        if (!dstDrawContext) {
            return nullptr;
        }

        apply_morphology_pass(dstDrawContext, clip, srcTexture,
                              srcRect, dstRect, radius.fHeight, morphType,
                              Gr1DKernelEffect::kY_Direction);

        srcTexture.reset(scratch);
    }

    return SkSpecialImage::MakeFromGpu(input->internal_getProxy(),
                                       SkIRect::MakeWH(rect.width(), rect.height()),
                                       kNeedNewImageUniqueID_SpecialImage,
                                       srcTexture, &input->props());
}