/*
 * Copyright 2023 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "src/gpu/ganesh/image/GrImageUtils.h"

#include "include/core/SkAlphaType.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkColorSpace.h"
#include "include/core/SkImage.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkPixmap.h"
#include "include/core/SkRect.h"
#include "include/core/SkSamplingOptions.h"
#include "include/core/SkSize.h"
#include "include/core/SkSurface.h"
#include "include/core/SkTypes.h"
#include "include/core/SkYUVAInfo.h"
#include "include/core/SkYUVAPixmaps.h"
#include "include/gpu/GpuTypes.h"
#include "include/gpu/ganesh/GrBackendSurface.h"
#include "include/gpu/ganesh/GrContextOptions.h"
#include "include/gpu/ganesh/GrRecordingContext.h"
#include "include/gpu/ganesh/GrTypes.h"
#include "include/gpu/ganesh/SkSurfaceGanesh.h"
#include "include/private/SkIDChangeListener.h"
#include "include/private/base/SkMutex.h"
#include "include/private/gpu/ganesh/GrImageContext.h"
#include "include/private/gpu/ganesh/GrTextureGenerator.h"
#include "include/private/gpu/ganesh/GrTypesPriv.h"
#include "src/core/SkBlurEngine.h"
#include "src/core/SkCachedData.h"
#include "src/core/SkImageFilterCache.h"
#include "src/core/SkImageFilterTypes.h"
#include "src/core/SkSamplingPriv.h"
#include "src/gpu/ResourceKey.h"
#include "src/gpu/SkBackingFit.h"
#include "src/gpu/Swizzle.h"
#include "src/gpu/ganesh/Device.h"
#include "src/gpu/ganesh/GrCaps.h"
#include "src/gpu/ganesh/GrColorSpaceXform.h"
#include "src/gpu/ganesh/GrFragmentProcessor.h"
#include "src/gpu/ganesh/GrImageInfo.h"
#include "src/gpu/ganesh/GrProxyProvider.h"
#include "src/gpu/ganesh/GrRecordingContextPriv.h"
#include "src/gpu/ganesh/GrSamplerState.h"
#include "src/gpu/ganesh/GrSurfaceProxy.h"
#include "src/gpu/ganesh/GrSurfaceProxyView.h"
#include "src/gpu/ganesh/GrTextureProxy.h"
#include "src/gpu/ganesh/GrThreadSafeCache.h"
#include "src/gpu/ganesh/GrYUVATextureProxies.h"
#include "src/gpu/ganesh/SkGr.h"
#include "src/gpu/ganesh/SurfaceFillContext.h"
#include "src/gpu/ganesh/effects/GrBicubicEffect.h"
#include "src/gpu/ganesh/effects/GrTextureEffect.h"
#include "src/gpu/ganesh/effects/GrYUVtoRGBEffect.h"
#include "src/gpu/ganesh/image/SkImage_Ganesh.h"
#include "src/gpu/ganesh/image/SkImage_GaneshBase.h"
#include "src/gpu/ganesh/image/SkImage_RasterPinnable.h"
#include "src/gpu/ganesh/image/SkSpecialImage_Ganesh.h"
#include "src/image/SkImage_Base.h"
#include "src/image/SkImage_Lazy.h"
#include "src/image/SkImage_Picture.h"
#include "src/image/SkImage_Raster.h"

#include <string_view>
#include <utility>

class SkDevice;
class SkMatrix;
class SkSurfaceProps;
enum SkColorType : int;

#if defined(SK_USE_LEGACY_BLUR_GANESH)
#include "include/core/SkPoint.h"
#include "include/core/SkScalar.h"
#include "src/core/SkSpecialImage.h"
#include "src/gpu/ganesh/GrBlurUtils.h"
#include "src/gpu/ganesh/SurfaceDrawContext.h"
#else
class SkSpecialImage;
#endif

namespace skgpu::ganesh {

GrSurfaceProxyView CopyView(GrRecordingContext* context,
                            GrSurfaceProxyView src,
                            skgpu::Mipmapped mipmapped,
                            GrImageTexGenPolicy policy,
                            std::string_view label) {
    skgpu::Budgeted budgeted = policy == GrImageTexGenPolicy::kNew_Uncached_Budgeted
                                       ? skgpu::Budgeted::kYes
                                       : skgpu::Budgeted::kNo;
    return GrSurfaceProxyView::Copy(context,
                                    std::move(src),
                                    mipmapped,
                                    SkBackingFit::kExact,
                                    budgeted,
                                    /*label=*/label);
}

std::tuple<GrSurfaceProxyView, GrColorType> RasterAsView(GrRecordingContext* rContext,
                                                         const SkImage_Raster* raster,
                                                         skgpu::Mipmapped mipmapped,
                                                         GrImageTexGenPolicy policy) {
    if (policy == GrImageTexGenPolicy::kDraw) {
        // If the draw doesn't require mipmaps but this SkImage has them go ahead and make a
        // mipmapped texture. There are three reasons for this:
        // 1) Avoiding another texture creation if a later draw requires mipmaps.
        // 2) Ensuring we upload the bitmap's levels instead of generating on the GPU from the base.
        if (raster->hasMipmaps()) {
            mipmapped = skgpu::Mipmapped::kYes;
        }
        return GrMakeCachedBitmapProxyView(rContext,
                                           raster->bitmap(),
                                           /*label=*/"TextureForImageRasterWithPolicyEqualKDraw",
                                           mipmapped);
    }
    auto budgeted = (policy == GrImageTexGenPolicy::kNew_Uncached_Unbudgeted)
                            ? skgpu::Budgeted::kNo
                            : skgpu::Budgeted::kYes;
    return GrMakeUncachedBitmapProxyView(
            rContext, raster->bitmap(), mipmapped, SkBackingFit::kExact, budgeted);
}

// Returns the GrColorType to use with the GrTextureProxy returned from lockTextureProxy. This
// may be different from the color type on the image in the case where we need up upload CPU
// data to a texture but the GPU doesn't support the format of CPU data. In this case we convert
// the data to RGBA_8888 unorm on the CPU then upload that.
GrColorType ColorTypeOfLockTextureProxy(const GrCaps* caps, SkColorType sct) {
    GrColorType ct = SkColorTypeToGrColorType(sct);
    GrBackendFormat format = caps->getDefaultBackendFormat(ct, GrRenderable::kNo);
    if (!format.isValid()) {
        ct = GrColorType::kRGBA_8888;
    }
    return ct;
}

static GrSurfaceOrigin get_origin(const SkImage_Lazy* img) {
    SkASSERT(img->generator());
    if (!img->generator()->isTextureGenerator()) {
        return kTopLeft_GrSurfaceOrigin;
    }
    // origin should be thread safe
    return static_cast<const GrTextureGenerator*>(img->generator()->fGenerator.get())->origin();
}


static GrSurfaceProxyView texture_proxy_view_from_planes(GrRecordingContext* ctx,
                                                         const SkImage_Lazy* img,
                                                         skgpu::Budgeted budgeted) {
    auto supportedDataTypes = SupportedTextureFormats(*ctx);
    SkYUVAPixmaps yuvaPixmaps;
    sk_sp<SkCachedData> dataStorage = img->getPlanes(supportedDataTypes, &yuvaPixmaps);
    if (!dataStorage) {
        return {};
    }

    GrSurfaceProxyView views[SkYUVAInfo::kMaxPlanes];
    GrColorType pixmapColorTypes[SkYUVAInfo::kMaxPlanes];
    for (int i = 0; i < yuvaPixmaps.numPlanes(); ++i) {
        // If the sizes of the components are not all the same we choose to create exact-match
        // textures for the smaller ones rather than add a texture domain to the draw.
        // TODO: revisit this decision to improve texture reuse?
        SkBackingFit fit = yuvaPixmaps.plane(i).dimensions() == img->dimensions()
                                   ? SkBackingFit::kApprox
                                   : SkBackingFit::kExact;

        // We grab a ref to cached yuv data. When the SkBitmap we create below goes away it will
        // call releaseProc which will release this ref.
        // DDL TODO: Currently we end up creating a lazy proxy that will hold onto a ref to the
        // SkImage in its lambda. This means that we'll keep the ref on the YUV data around for the
        // life time of the proxy and not just upload. For non-DDL draws we should look into
        // releasing this SkImage after uploads (by deleting the lambda after instantiation).
        auto releaseProc = [](void*, void* data) {
            auto cachedData = static_cast<SkCachedData*>(data);
            SkASSERT(cachedData);
            cachedData->unref();
        };
        SkBitmap bitmap;
        bitmap.installPixels(yuvaPixmaps.plane(i).info(),
                             yuvaPixmaps.plane(i).writable_addr(),
                             yuvaPixmaps.plane(i).rowBytes(),
                             releaseProc,
                             SkRef(dataStorage.get()));
        bitmap.setImmutable();

        std::tie(views[i], std::ignore) =
                GrMakeUncachedBitmapProxyView(ctx, bitmap, skgpu::Mipmapped::kNo, fit);
        if (!views[i]) {
            return {};
        }
        pixmapColorTypes[i] = SkColorTypeToGrColorType(bitmap.colorType());
    }

    // TODO: investigate preallocating mip maps here
    GrImageInfo info(SkColorTypeToGrColorType(img->colorType()),
                     kPremul_SkAlphaType,
                     /*color space*/ nullptr,
                     img->dimensions());

    auto sfc = ctx->priv().makeSFC(info,
                                   "ImageLazy_TextureProxyViewFromPlanes",
                                   SkBackingFit::kExact,
                                   1,
                                   skgpu::Mipmapped::kNo,
                                   GrProtected::kNo,
                                   kTopLeft_GrSurfaceOrigin,
                                   budgeted);
    if (!sfc) {
        return {};
    }

    GrYUVATextureProxies yuvaProxies(yuvaPixmaps.yuvaInfo(), views, pixmapColorTypes);
    SkAssertResult(yuvaProxies.isValid());

    std::unique_ptr<GrFragmentProcessor> fp = GrYUVtoRGBEffect::Make(
            yuvaProxies,
            GrSamplerState::Filter::kNearest,
            *ctx->priv().caps());

    // The pixels after yuv->rgb will be in the generator's color space.
    // If onMakeColorTypeAndColorSpace has been called then this will not match this image's
    // color space. To correct this, apply a color space conversion from the generator's color
    // space to this image's color space.
    SkColorSpace* srcColorSpace = img->generator()->getInfo().colorSpace();
    SkColorSpace* dstColorSpace = img->colorSpace();

    // If the caller expects the pixels in a different color space than the one from the image,
    // apply a color conversion to do this.
    fp = GrColorSpaceXformEffect::Make(std::move(fp),
                                       srcColorSpace, kOpaque_SkAlphaType,
                                       dstColorSpace, kOpaque_SkAlphaType);
    sfc->fillWithFP(std::move(fp));

    return sfc->readSurfaceView();
}

static GrSurfaceProxyView generate_picture_texture(GrRecordingContext* ctx,
                                                   const SkImage_Picture* img,
                                                   skgpu::Mipmapped mipmapped,
                                                   GrImageTexGenPolicy texGenPolicy) {
    SkASSERT(ctx);
    SkASSERT(img);

    skgpu::Budgeted budgeted = texGenPolicy == GrImageTexGenPolicy::kNew_Uncached_Unbudgeted
                                       ? skgpu::Budgeted::kNo
                                       : skgpu::Budgeted::kYes;
    auto surface = SkSurfaces::RenderTarget(ctx,
                                            budgeted,
                                            img->imageInfo(),
                                            0,
                                            kTopLeft_GrSurfaceOrigin,
                                            img->props(),
                                            mipmapped == skgpu::Mipmapped::kYes);
    if (!surface) {
        return {};
    }

    img->replay(surface->getCanvas());

    sk_sp<SkImage> image(surface->makeImageSnapshot());
    if (!image) {
        return {};
    }

    auto [view, ct] = AsView(ctx, image, mipmapped);
    SkASSERT(view);
    SkASSERT(mipmapped == skgpu::Mipmapped::kNo ||
             view.asTextureProxy()->mipmapped() == skgpu::Mipmapped::kYes);
    return view;
}

// Returns the texture proxy. We will always cache the generated texture on success.
// We have 4 ways to try to return a texture (in sorted order)
//
// 1. Check the cache for a pre-existing one
// 2. Ask the generator to natively create one
// 3. Ask the generator to return YUV planes, which the GPU can convert
// 4. Ask the generator to return RGB(A) data, which the GPU can convert
GrSurfaceProxyView LockTextureProxyView(GrRecordingContext* rContext,
                                        const SkImage_Lazy* img,
                                        GrImageTexGenPolicy texGenPolicy,
                                        skgpu::Mipmapped mipmapped) {
    skgpu::UniqueKey key;
    if (texGenPolicy == GrImageTexGenPolicy::kDraw) {
        GrMakeKeyFromImageID(&key, img->uniqueID(), SkIRect::MakeSize(img->dimensions()));
    }

    const GrCaps* caps = rContext->priv().caps();
    GrProxyProvider* proxyProvider = rContext->priv().proxyProvider();

    auto installKey = [&](const GrSurfaceProxyView& view) {
        SkASSERT(view && view.asTextureProxy());
        if (key.isValid()) {
            auto listener = GrMakeUniqueKeyInvalidationListener(&key, rContext->priv().contextID());
            img->addUniqueIDListener(std::move(listener));
            proxyProvider->assignUniqueKeyToProxy(key, view.asTextureProxy());
        }
    };

    auto ct = ColorTypeOfLockTextureProxy(caps, img->colorType());

    // 1. Check the cache for a pre-existing one.
    if (key.isValid()) {
        auto proxy = proxyProvider->findOrCreateProxyByUniqueKey(key);
        if (proxy) {
            skgpu::Swizzle swizzle = caps->getReadSwizzle(proxy->backendFormat(), ct);
            GrSurfaceOrigin origin = get_origin(img);
            GrSurfaceProxyView view(std::move(proxy), origin, swizzle);
            if (mipmapped == skgpu::Mipmapped::kNo ||
                view.asTextureProxy()->mipmapped() == skgpu::Mipmapped::kYes) {
                return view;
            } else {
                // We need a mipped proxy, but we found a cached proxy that wasn't mipped. Thus we
                // generate a new mipped surface and copy the original proxy into the base layer. We
                // will then let the gpu generate the rest of the mips.
                auto mippedView = GrCopyBaseMipMapToView(rContext, view);
                if (!mippedView) {
                    // We failed to make a mipped proxy with the base copied into it. This could
                    // have been from failure to make the proxy or failure to do the copy. Thus we
                    // will fall back to just using the non mipped proxy; See skbug.com/7094.
                    return view;
                }
                proxyProvider->removeUniqueKeyFromProxy(view.asTextureProxy());
                installKey(mippedView);
                return mippedView;
            }
        }
    }

    // 2. Ask the generator to natively create one (if it knows how)
    {
        if (img->type() == SkImage_Base::Type::kLazyPicture) {
            if (auto view = generate_picture_texture(rContext,
                                                     static_cast<const SkImage_Picture*>(img),
                                                     mipmapped,
                                                     texGenPolicy)) {
                installKey(view);
                return view;
            }
            // The fallback for this would be to generate a bitmap, but some picture-backed
            // images can only be played back on the GPU.
            return {};
        } else if (img->generator()->isTextureGenerator()) {
            auto sharedGenerator = img->generator();
            SkAutoMutexExclusive mutex(sharedGenerator->fMutex);
            auto textureGen = static_cast<GrTextureGenerator*>(sharedGenerator->fGenerator.get());
            if (auto view = textureGen->generateTexture(rContext,
                                                        img->imageInfo(),
                                                        mipmapped,
                                                        texGenPolicy)) {
                installKey(view);
                return view;
            }
        }
    }

    // 3. Ask the generator to return YUV planes, which the GPU can convert. If we will be mipping
    //    the texture we skip this step so the CPU generate non-planar MIP maps for us.
    if (mipmapped == skgpu::Mipmapped::kNo &&
        !rContext->priv().options().fDisableGpuYUVConversion) {
        // TODO: Update to create the mipped surface in the textureProxyViewFromPlanes generator and
        //  draw the base layer directly into the mipped surface.
        skgpu::Budgeted budgeted = texGenPolicy == GrImageTexGenPolicy::kNew_Uncached_Unbudgeted
                                           ? skgpu::Budgeted::kNo
                                           : skgpu::Budgeted::kYes;
        auto view = texture_proxy_view_from_planes(rContext, img, budgeted);
        if (view) {
            installKey(view);
            return view;
        }
    }

    // 4. Ask the generator to return a bitmap, which the GPU can convert.
    auto hint = texGenPolicy == GrImageTexGenPolicy::kDraw ? SkImage::CachingHint::kAllow_CachingHint
                                                           : SkImage::CachingHint::kDisallow_CachingHint;
    if (SkBitmap bitmap; img->getROPixels(nullptr, &bitmap, hint)) {
        // We always make an uncached bitmap here because we will cache it based on passed in policy
        // with *our* key, not a key derived from bitmap. We're just making the proxy here.
        auto budgeted = texGenPolicy == GrImageTexGenPolicy::kNew_Uncached_Unbudgeted
                                ? skgpu::Budgeted::kNo
                                : skgpu::Budgeted::kYes;
        auto view = std::get<0>(GrMakeUncachedBitmapProxyView(rContext,
                                                              bitmap,
                                                              mipmapped,
                                                              SkBackingFit::kExact,
                                                              budgeted));
        if (view) {
            installKey(view);
            return view;
        }
    }

    return {};
}

static std::tuple<GrSurfaceProxyView, GrColorType> lazy_as_view(GrRecordingContext* context,
                                                                const SkImage_Lazy* img,
                                                                skgpu::Mipmapped mipmapped,
                                                                GrImageTexGenPolicy policy) {
    GrColorType ct = ColorTypeOfLockTextureProxy(context->priv().caps(), img->colorType());
    return {LockTextureProxyView(context, img, policy, mipmapped), ct};
}

std::tuple<GrSurfaceProxyView, GrColorType> AsView(GrRecordingContext* rContext,
                                                   const SkImage* img,
                                                   skgpu::Mipmapped mipmapped,
                                                   GrImageTexGenPolicy policy) {
    SkASSERT(img);
    if (!rContext) {
        return {};
    }
    if (!rContext->priv().caps()->mipmapSupport() || img->dimensions().area() <= 1) {
        mipmapped = skgpu::Mipmapped::kNo;
    }

    auto ib = static_cast<const SkImage_Base*>(img);
    if (ib->type() == SkImage_Base::Type::kRaster) {
        return skgpu::ganesh::RasterAsView(
                    rContext, static_cast<const SkImage_Raster*>(ib), mipmapped, policy);
    } else if (ib->type() == SkImage_Base::Type::kRasterPinnable) {
        auto rp = static_cast<const SkImage_RasterPinnable*>(img);
        return rp->asView(rContext, mipmapped, policy);
    } else if (ib->isGaneshBacked()) {
        auto gb = static_cast<const SkImage_GaneshBase*>(img);
        return gb->asView(rContext, mipmapped, policy);
    } else if (ib->isLazyGenerated()) {
        return lazy_as_view(rContext, static_cast<const SkImage_Lazy*>(ib), mipmapped, policy);
    }

    SkDEBUGFAIL("Unsupported image type to make a View");
    return {};
}

static std::unique_ptr<GrFragmentProcessor> make_fp_from_view(GrRecordingContext* rContext,
                                                              GrSurfaceProxyView view,
                                                              SkAlphaType at,
                                                              SkSamplingOptions sampling,
                                                              const SkTileMode tileModes[2],
                                                              const SkMatrix& m,
                                                              const SkRect* subset,
                                                              const SkRect* domain) {
    if (!view) {
        return nullptr;
    }
    const GrCaps& caps = *rContext->priv().caps();
    auto wmx = SkTileModeToWrapMode(tileModes[0]);
    auto wmy = SkTileModeToWrapMode(tileModes[1]);
    if (sampling.useCubic) {
        if (subset) {
            if (domain) {
                return GrBicubicEffect::MakeSubset(std::move(view),
                                                   at,
                                                   m,
                                                   wmx,
                                                   wmy,
                                                   *subset,
                                                   *domain,
                                                   sampling.cubic,
                                                   GrBicubicEffect::Direction::kXY,
                                                   *rContext->priv().caps());
            }
            return GrBicubicEffect::MakeSubset(std::move(view),
                                               at,
                                               m,
                                               wmx,
                                               wmy,
                                               *subset,
                                               sampling.cubic,
                                               GrBicubicEffect::Direction::kXY,
                                               *rContext->priv().caps());
        }
        return GrBicubicEffect::Make(std::move(view),
                                     at,
                                     m,
                                     wmx,
                                     wmy,
                                     sampling.cubic,
                                     GrBicubicEffect::Direction::kXY,
                                     *rContext->priv().caps());
    }
    if (sampling.isAniso()) {
        if (!rContext->priv().caps()->anisoSupport()) {
            // Fallback to linear
            sampling = SkSamplingPriv::AnisoFallback(view.mipmapped() == skgpu::Mipmapped::kYes);
        }
    } else if (view.mipmapped() == skgpu::Mipmapped::kNo) {
        sampling = SkSamplingOptions(sampling.filter);
    }
    GrSamplerState sampler;
    if (sampling.isAniso()) {
        sampler = GrSamplerState::Aniso(wmx, wmy, sampling.maxAniso, view.mipmapped());
    } else {
        sampler = GrSamplerState(wmx, wmy, sampling.filter, sampling.mipmap);
    }
    if (subset) {
        if (domain) {
            return GrTextureEffect::MakeSubset(
                    std::move(view), at, m, sampler, *subset, *domain, caps);
        }
        return GrTextureEffect::MakeSubset(std::move(view), at, m, sampler, *subset, caps);
    } else {
        return GrTextureEffect::Make(std::move(view), at, m, sampler, caps);
    }
}

std::unique_ptr<GrFragmentProcessor> raster_as_fp(GrRecordingContext* rContext,
                                                  const SkImage_Raster* img,
                                                  SkSamplingOptions sampling,
                                                  const SkTileMode tileModes[2],
                                                  const SkMatrix& m,
                                                  const SkRect* subset,
                                                  const SkRect* domain) {
    auto mm =
            sampling.mipmap == SkMipmapMode::kNone ? skgpu::Mipmapped::kNo : skgpu::Mipmapped::kYes;
    return make_fp_from_view(rContext,
                             std::get<0>(AsView(rContext, img, mm)),
                             img->alphaType(),
                             sampling,
                             tileModes,
                             m,
                             subset,
                             domain);
}

std::unique_ptr<GrFragmentProcessor> AsFragmentProcessor(GrRecordingContext* rContext,
                                                         const SkImage* img,
                                                         SkSamplingOptions sampling,
                                                         const SkTileMode tileModes[2],
                                                         const SkMatrix& m,
                                                         const SkRect* subset,
                                                         const SkRect* domain) {
    if (!rContext) {
        return {};
    }
    if (sampling.useCubic && !GrValidCubicResampler(sampling.cubic)) {
        return {};
    }
    if (sampling.mipmap != SkMipmapMode::kNone &&
        (!rContext->priv().caps()->mipmapSupport() || img->dimensions().area() <= 1)) {
        sampling = SkSamplingOptions(sampling.filter);
    }

    auto ib = static_cast<const SkImage_Base*>(img);
    if (ib->isRasterBacked()) {
        return raster_as_fp(rContext,
                            static_cast<const SkImage_Raster*>(ib),
                            sampling,
                            tileModes,
                            m,
                            subset,
                            domain);
    } else if (ib->isGaneshBacked()) {
        auto gb = static_cast<const SkImage_GaneshBase*>(img);
        return gb->asFragmentProcessor(rContext, sampling, tileModes, m, subset, domain);
    } else if (ib->isLazyGenerated()) {
        // TODO: If the CPU data is extracted as planes return a FP that reconstructs the image from
        // the planes.
        auto mm = sampling.mipmap == SkMipmapMode::kNone ? skgpu::Mipmapped::kNo : skgpu::Mipmapped::kYes;
        return MakeFragmentProcessorFromView(rContext,
                                             std::get<0>(AsView(rContext, img, mm)),
                                             img->alphaType(),
                                             sampling,
                                             tileModes,
                                             m,
                                             subset,
                                             domain);
    }

    SkDEBUGFAIL("Unsupported image type to make a FragmentProcessor");
    return {};
}

std::unique_ptr<GrFragmentProcessor> MakeFragmentProcessorFromView(
        GrRecordingContext* rContext,
        GrSurfaceProxyView view,
        SkAlphaType at,
        SkSamplingOptions sampling,
        const SkTileMode tileModes[2],
        const SkMatrix& m,
        const SkRect* subset,
        const SkRect* domain) {
    if (!view) {
        return nullptr;
    }
    const GrCaps& caps = *rContext->priv().caps();
    auto wmx = SkTileModeToWrapMode(tileModes[0]);
    auto wmy = SkTileModeToWrapMode(tileModes[1]);
    if (sampling.useCubic) {
        if (subset) {
            if (domain) {
                return GrBicubicEffect::MakeSubset(std::move(view),
                                                   at,
                                                   m,
                                                   wmx,
                                                   wmy,
                                                   *subset,
                                                   *domain,
                                                   sampling.cubic,
                                                   GrBicubicEffect::Direction::kXY,
                                                   *rContext->priv().caps());
            }
            return GrBicubicEffect::MakeSubset(std::move(view),
                                               at,
                                               m,
                                               wmx,
                                               wmy,
                                               *subset,
                                               sampling.cubic,
                                               GrBicubicEffect::Direction::kXY,
                                               *rContext->priv().caps());
        }
        return GrBicubicEffect::Make(std::move(view),
                                     at,
                                     m,
                                     wmx,
                                     wmy,
                                     sampling.cubic,
                                     GrBicubicEffect::Direction::kXY,
                                     *rContext->priv().caps());
    }
    if (sampling.isAniso()) {
        if (!rContext->priv().caps()->anisoSupport()) {
            // Fallback to linear
            sampling = SkSamplingPriv::AnisoFallback(view.mipmapped() == skgpu::Mipmapped::kYes);
        }
    } else if (view.mipmapped() == skgpu::Mipmapped::kNo) {
        sampling = SkSamplingOptions(sampling.filter);
    }
    GrSamplerState sampler;
    if (sampling.isAniso()) {
        sampler = GrSamplerState::Aniso(wmx, wmy, sampling.maxAniso, view.mipmapped());
    } else {
        sampler = GrSamplerState(wmx, wmy, sampling.filter, sampling.mipmap);
    }
    if (subset) {
        if (domain) {
            return GrTextureEffect::MakeSubset(std::move(view),
                                               at,
                                               m,
                                               sampler,
                                               *subset,
                                               *domain,
                                               caps);
        }
        return GrTextureEffect::MakeSubset(std::move(view),
                                           at,
                                           m,
                                           sampler,
                                           *subset,
                                           caps);
    } else {
        return GrTextureEffect::Make(std::move(view), at, m, sampler, caps);
    }
}

GrSurfaceProxyView FindOrMakeCachedMipmappedView(GrRecordingContext* rContext,
                                                 GrSurfaceProxyView view,
                                                 uint32_t imageUniqueID) {
    SkASSERT(rContext);
    SkASSERT(imageUniqueID != SK_InvalidUniqueID);

    if (!view || view.proxy()->asTextureProxy()->mipmapped() == skgpu::Mipmapped::kYes) {
        return view;
    }
    GrProxyProvider* proxyProvider = rContext->priv().proxyProvider();

    skgpu::UniqueKey baseKey;
    GrMakeKeyFromImageID(&baseKey, imageUniqueID, SkIRect::MakeSize(view.dimensions()));
    SkASSERT(baseKey.isValid());
    skgpu::UniqueKey mipmappedKey;
    static const skgpu::UniqueKey::Domain kMipmappedDomain = skgpu::UniqueKey::GenerateDomain();
    {  // No extra values beyond the domain are required. Must name the var to please
       // clang-tidy.
        skgpu::UniqueKey::Builder b(&mipmappedKey, baseKey, kMipmappedDomain, 0);
    }
    SkASSERT(mipmappedKey.isValid());
    if (sk_sp<GrTextureProxy> cachedMippedView =
                proxyProvider->findOrCreateProxyByUniqueKey(mipmappedKey)) {
        return {std::move(cachedMippedView), view.origin(), view.swizzle()};
    }

    auto copy = GrCopyBaseMipMapToView(rContext, view);
    if (!copy) {
        return view;
    }
    // TODO: If we move listeners up from SkImage_Lazy to SkImage_Base then add one here.
    proxyProvider->assignUniqueKeyToProxy(mipmappedKey, copy.asTextureProxy());
    return copy;
}

using DataType = SkYUVAPixmapInfo::DataType;

SkYUVAPixmapInfo::SupportedDataTypes SupportedTextureFormats(const GrImageContext& context) {
    SkYUVAPixmapInfo::SupportedDataTypes dataTypes;
    const auto isValid = [&context](DataType dt, int n) {
        return context.defaultBackendFormat(SkYUVAPixmapInfo::DefaultColorTypeForDataType(dt, n),
                                            GrRenderable::kNo).isValid();
    };
     for (int n = 1; n <= 4; ++n) {
        if (isValid(DataType::kUnorm8, n)) {
            dataTypes.enableDataType(DataType::kUnorm8, n);
        }
        if (isValid(DataType::kUnorm16, n)) {
            dataTypes.enableDataType(DataType::kUnorm16, n);
        }
        if (isValid(DataType::kFloat16, n)) {
            dataTypes.enableDataType(DataType::kFloat16, n);
        }
        if (isValid(DataType::kUnorm10_Unorm2, n)) {
            dataTypes.enableDataType(DataType::kUnorm10_Unorm2, n);
        }
    }
     return dataTypes;
}

}  // namespace skgpu::ganesh

namespace skif {

namespace {

class GaneshBackend :
        public Backend,
#if defined(SK_USE_LEGACY_BLUR_GANESH)
        private SkBlurEngine::Algorithm,
#else
        private SkShaderBlurAlgorithm,
#endif
        private SkBlurEngine {
public:

    GaneshBackend(sk_sp<GrRecordingContext> context,
                  GrSurfaceOrigin origin,
                  const SkSurfaceProps& surfaceProps,
                  SkColorType colorType)
            : Backend(SkImageFilterCache::Create(SkImageFilterCache::kDefaultTransientSize),
                      surfaceProps, colorType)
            , fContext(std::move(context))
            , fOrigin(origin) {}

    // Backend
    sk_sp<SkDevice> makeDevice(SkISize size,
                               sk_sp<SkColorSpace> colorSpace,
                               const SkSurfaceProps* props) const override {
        SkImageInfo imageInfo = SkImageInfo::Make(size,
                                                  this->colorType(),
                                                  kPremul_SkAlphaType,
                                                  std::move(colorSpace));

        return fContext->priv().createDevice(skgpu::Budgeted::kYes,
                                             imageInfo,
                                             SkBackingFit::kApprox,
                                             1,
                                             skgpu::Mipmapped::kNo,
                                             GrProtected::kNo,
                                             fOrigin,
                                             props ? *props : this->surfaceProps(),
                                             skgpu::ganesh::Device::InitContents::kUninit);
    }

    sk_sp<SkSpecialImage> makeImage(const SkIRect& subset, sk_sp<SkImage> image) const override {
        return SkSpecialImages::MakeFromTextureImage(
                fContext.get(), subset, image, this->surfaceProps());
    }

    sk_sp<SkImage> getCachedBitmap(const SkBitmap& data) const override {
        // This uses the thread safe cache (instead of GrMakeCachedBitmapProxyView) so that image
        // filters can be evaluated on other threads with DDLs.
        auto threadSafeCache = fContext->priv().threadSafeCache();

        skgpu::UniqueKey key;
        SkIRect subset = SkIRect::MakePtSize(data.pixelRefOrigin(), data.dimensions());
        GrMakeKeyFromImageID(&key, data.getGenerationID(), subset);

        auto view = threadSafeCache->find(key);
        if (!view) {
            view = std::get<0>(GrMakeUncachedBitmapProxyView(fContext.get(), data));
            if (!view) {
                return nullptr;
            }
            threadSafeCache->add(key, view);
        }

        return sk_make_sp<SkImage_Ganesh>(fContext,
                                          data.getGenerationID(),
                                          std::move(view),
                                          data.info().colorInfo());
    }

    const SkBlurEngine* getBlurEngine() const override { return this; }

    // SkBlurEngine
    const SkBlurEngine::Algorithm* findAlgorithm(SkSize sigma,
                                                 SkColorType colorType) const override {
        // GrBlurUtils supports all tile modes and color types
        return this;
    }

#if defined(SK_USE_LEGACY_BLUR_GANESH)
    // NOTE: When SK_USE_LEGACY_BLUR_GANESH is defined, `useLegacyFilterResultBlur()` returns true,
    // so FilterResult::blur() will resolve all tiling in the original image space before calling
    // into this function that routes to GrBlurUtils::GaussianBlur to perform the rescaling and
    // blurring. It is possible ot restore original GrBlurUtils performance by just having
    // `useLegacyFilterResultBlur()` return false but still reporting a max sigma of infinity and
    // advertising support for all tile modes.
    //
    // Since all clients are currently rebased on the intermediate "legacy" blur approach, the ideal
    // step would be to just migrate them to the SkShaderBlurAlgorithm variant instead of first
    // going back to pure GrBlurUtils. But if needed for cherry-picking to old releases, the
    // original GrBlurUtils behavior can be achieved quikly.

    // SkBlurEngine::Algorithm
    float maxSigma() const override {
        // GrBlurUtils handles resizing at the moment
        return SK_ScalarInfinity;
    }

    bool supportsOnlyDecalTiling() const override { return false; }

    sk_sp<SkSpecialImage> blur(SkSize sigma,
                               sk_sp<SkSpecialImage> input,
                               const SkIRect& srcRect,
                               SkTileMode tileMode,
                               const SkIRect& dstRect) const override {
        GrSurfaceProxyView inputView = SkSpecialImages::AsView(fContext.get(), input);
        if (!inputView.proxy()) {
            return nullptr;
        }
        SkASSERT(inputView.asTextureProxy());

        // Update srcRect and dstRect to be relative to the underlying texture proxy of 'input'.
        auto proxyOffset = input->subset().topLeft() - srcRect.topLeft();
        auto sdc = GrBlurUtils::GaussianBlur(
                fContext.get(),
                std::move(inputView),
                SkColorTypeToGrColorType(input->colorType()),
                input->alphaType(),
                sk_ref_sp(input->getColorSpace()),
                dstRect.makeOffset(proxyOffset),
                srcRect.makeOffset(proxyOffset),
                sigma.width(),
                sigma.height(),
                tileMode);
        if (!sdc) {
            return nullptr;
        }

        return SkSpecialImages::MakeDeferredFromGpu(fContext.get(),
                                                    SkIRect::MakeSize(dstRect.size()),
                                                    kNeedNewImageUniqueID_SpecialImage,
                                                    sdc->readSurfaceView(),
                                                    sdc->colorInfo(),
                                                    this->surfaceProps());
    }
#else
    bool useLegacyFilterResultBlur() const override { return false; }

    // SkShaderBlurAlgorithm
    sk_sp<SkDevice> makeDevice(const SkImageInfo& imageInfo) const override {
        return fContext->priv().createDevice(skgpu::Budgeted::kYes,
                                             imageInfo,
                                             SkBackingFit::kApprox,
                                             1,
                                             skgpu::Mipmapped::kNo,
                                             GrProtected::kNo,
                                             fOrigin,
                                             this->surfaceProps(),
                                             skgpu::ganesh::Device::InitContents::kUninit);
    }

#endif

private:
    sk_sp<GrRecordingContext> fContext;
    GrSurfaceOrigin fOrigin;
};

} // anonymous namespace

sk_sp<Backend> MakeGaneshBackend(sk_sp<GrRecordingContext> context,
                                 GrSurfaceOrigin origin,
                                 const SkSurfaceProps& surfaceProps,
                                 SkColorType colorType) {
    SkASSERT(context);
    return sk_make_sp<GaneshBackend>(std::move(context), origin, surfaceProps, colorType);
}

}  // namespace skif
