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

#include "src/gpu/GrImageTextureMaker.h"

#include "src/gpu/GrColorSpaceXform.h"
#include "src/gpu/GrImageContextPriv.h"
#include "src/gpu/GrRecordingContextPriv.h"
#include "src/gpu/SkGr.h"
#include "src/gpu/effects/GrBicubicEffect.h"
#include "src/gpu/effects/GrYUVtoRGBEffect.h"
#include "src/image/SkImage_GpuYUVA.h"
#include "src/image/SkImage_Lazy.h"

static GrImageInfo get_image_info(GrRecordingContext* context, const SkImage* client) {
    SkASSERT(client->isLazyGenerated());
    const SkImage_Lazy* lazyImage = static_cast<const SkImage_Lazy*>(client);

    GrColorType ct = lazyImage->colorTypeOfLockTextureProxy(context->priv().caps());

    return {ct, client->alphaType(), client->refColorSpace(), client->dimensions()};
}

GrImageTextureMaker::GrImageTextureMaker(GrRecordingContext* context,
                                         const SkImage* client,
                                         GrImageTexGenPolicy texGenPolicy)
        : INHERITED(context, get_image_info(context, client))
        , fImage(static_cast<const SkImage_Lazy*>(client))
        , fTexGenPolicy(texGenPolicy) {
    SkASSERT(client->isLazyGenerated());
}

GrSurfaceProxyView GrImageTextureMaker::refOriginalTextureProxyView(GrMipmapped mipMapped) {
    return fImage->lockTextureProxyView(this->context(), fTexGenPolicy, mipMapped);
}

/////////////////////////////////////////////////////////////////////////////////////////////////

GrYUVAImageTextureMaker::GrYUVAImageTextureMaker(GrRecordingContext* context, const SkImage* client)
        : INHERITED(context, client->imageInfo())
        , fImage(static_cast<const SkImage_GpuYUVA*>(client)) {
    SkASSERT(as_IB(client)->isYUVA());
}

GrSurfaceProxyView GrYUVAImageTextureMaker::refOriginalTextureProxyView(GrMipmapped mipMapped) {
    if (mipMapped == GrMipmapped::kYes) {
        return fImage->refMippedView(this->context());
    } else {
        if (const GrSurfaceProxyView* view = fImage->view(this->context())) {
            return *view;
        } else {
            return {};
        }
    }
}

std::unique_ptr<GrFragmentProcessor> GrYUVAImageTextureMaker::createFragmentProcessor(
        const SkMatrix& textureMatrix,
        const SkRect* subset,
        const SkRect* domain,
        GrSamplerState samplerState) {
    // Check whether it's already been flattened.
    if (fImage->fRGBView.proxy()) {
        return this->INHERITED::createFragmentProcessor(textureMatrix, subset, domain,
                                                        samplerState);
    }

    // Check to see if the client has given us pre-mipped textures or we can generate them
    // If not disable mip mapping. Also disable when a subset is requested.
    if (samplerState.mipmapped() == GrMipmapped::kYes &&
        (subset || !fImage->setupMipmapsForPlanes(this->context()))) {
        samplerState.setMipmapMode(GrSamplerState::MipmapMode::kNone);
    }

    const auto& caps = *fImage->context()->priv().caps();
    auto fp = GrYUVtoRGBEffect::Make(fImage->fViews, fImage->fYUVALocations, fImage->fYUVColorSpace,
                                     samplerState, caps, textureMatrix, subset, domain);
    if (fImage->fFromColorSpace) {
        fp = GrColorSpaceXformEffect::Make(std::move(fp), fImage->fFromColorSpace.get(),
                                           fImage->alphaType(), fImage->colorSpace(),
                                           kPremul_SkAlphaType);
    }
    return fp;
}

std::unique_ptr<GrFragmentProcessor> GrYUVAImageTextureMaker::createBicubicFragmentProcessor(
        const SkMatrix& textureMatrix,
        const SkRect* subset,
        const SkRect* domain,
        GrSamplerState::WrapMode wrapX,
        GrSamplerState::WrapMode wrapY,
        SkImage::CubicResampler kernel) {
    const auto& caps = *fImage->context()->priv().caps();
    GrSamplerState samplerState(wrapX, wrapY, GrSamplerState::Filter::kNearest);
    auto fp = GrYUVtoRGBEffect::Make(fImage->fViews, fImage->fYUVALocations, fImage->fYUVColorSpace,
                                     samplerState, caps, SkMatrix::I(), subset, domain);
    fp = GrBicubicEffect::Make(std::move(fp),
                               fImage->alphaType(),
                               textureMatrix,
                               kernel /*GrBicubicEffect::gMitchell*/,
                               GrBicubicEffect::Direction::kXY);
    if (fImage->fFromColorSpace) {
        fp = GrColorSpaceXformEffect::Make(std::move(fp),
                                           fImage->fFromColorSpace.get(), fImage->alphaType(),
                                           fImage->colorSpace(), kPremul_SkAlphaType);
    }
    return fp;
}
