/*
 * 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 "GrTextureAdjuster.h"
#include "GrColorSpaceXform.h"
#include "GrContext.h"
#include "GrContextPriv.h"
#include "GrGpu.h"
#include "GrProxyProvider.h"
#include "SkGr.h"

GrTextureAdjuster::GrTextureAdjuster(GrContext* context, sk_sp<GrTextureProxy> original,
                                     SkAlphaType alphaType,
                                     uint32_t uniqueID,
                                     SkColorSpace* cs)
    : INHERITED(context, original->width(), original->height(),
                GrPixelConfigIsAlphaOnly(original->config()))
    , fOriginal(std::move(original))
    , fAlphaType(alphaType)
    , fColorSpace(cs)
    , fUniqueID(uniqueID) {}

void GrTextureAdjuster::makeCopyKey(const CopyParams& params, GrUniqueKey* copyKey) {
    // Destination color space is irrelevant - we already have a texture so we're just sub-setting
    GrUniqueKey baseKey;
    GrMakeKeyFromImageID(&baseKey, fUniqueID, SkIRect::MakeWH(this->width(), this->height()));
    MakeCopyKeyFromOrigKey(baseKey, params, copyKey);
}

void GrTextureAdjuster::didCacheCopy(const GrUniqueKey& copyKey, uint32_t contextUniqueID) {
    // We don't currently have a mechanism for notifications on Images!
}

sk_sp<GrTextureProxy> GrTextureAdjuster::refTextureProxyCopy(const CopyParams& copyParams,
                                                             bool willBeMipped) {
    GrProxyProvider* proxyProvider = fContext->priv().proxyProvider();

    GrUniqueKey key;
    this->makeCopyKey(copyParams, &key);
    sk_sp<GrTextureProxy> cachedCopy;
    if (key.isValid()) {
        cachedCopy = proxyProvider->findOrCreateProxyByUniqueKey(key,
                                                                 this->originalProxy()->origin());
        if (cachedCopy && (!willBeMipped || GrMipMapped::kYes == cachedCopy->mipMapped())) {
            return cachedCopy;
        }
    }

    sk_sp<GrTextureProxy> proxy = this->originalProxyRef();

    sk_sp<GrTextureProxy> copy = CopyOnGpu(fContext, std::move(proxy), copyParams, willBeMipped);
    if (copy) {
        if (key.isValid()) {
            SkASSERT(copy->origin() == this->originalProxy()->origin());
            if (cachedCopy) {
                SkASSERT(GrMipMapped::kYes == copy->mipMapped() &&
                         GrMipMapped::kNo == cachedCopy->mipMapped());
                // If we had a cachedProxy, that means there already is a proxy in the cache which
                // matches the key, but it does not have mip levels and we require them. Thus we
                // must remove the unique key from that proxy.
                SkASSERT(cachedCopy->getUniqueKey() == key);
                proxyProvider->removeUniqueKeyFromProxy(cachedCopy.get());
            }
            proxyProvider->assignUniqueKeyToProxy(key, copy.get());
            this->didCacheCopy(key, proxyProvider->contextUniqueID());
        }
    }
    return copy;
}

sk_sp<GrTextureProxy> GrTextureAdjuster::onRefTextureProxyForParams(
        const GrSamplerState& params,
        bool willBeMipped,
        SkScalar scaleAdjust[2]) {
    sk_sp<GrTextureProxy> proxy = this->originalProxyRef();
    CopyParams copyParams;

    if (!fContext) {
        // The texture was abandoned.
        return nullptr;
    }

    SkASSERT(this->width() <= fContext->priv().caps()->maxTextureSize() &&
             this->height() <= fContext->priv().caps()->maxTextureSize());

    bool needsCopyForMipsOnly = false;
    if (!params.isRepeated() ||
        !GrGpu::IsACopyNeededForRepeatWrapMode(fContext->priv().caps(), proxy.get(),
                                               proxy->width(), proxy->height(), params.filter(),
                                               &copyParams, scaleAdjust)) {
        needsCopyForMipsOnly = GrGpu::IsACopyNeededForMips(fContext->priv().caps(),
                                                           proxy.get(), params.filter(),
                                                           &copyParams);
        if (!needsCopyForMipsOnly) {
            return proxy;
        }
    }

    sk_sp<GrTextureProxy> result = this->refTextureProxyCopy(copyParams, willBeMipped);
    if (!result && needsCopyForMipsOnly) {
        // If we were unable to make a copy and we only needed a copy for mips, then we will return
        // the source texture here and require that the GPU backend is able to fall back to using
        // bilerp if mips are required.
        return this->originalProxyRef();
    }
    return result;
}

std::unique_ptr<GrFragmentProcessor> GrTextureAdjuster::createFragmentProcessor(
        const SkMatrix& origTextureMatrix,
        const SkRect& constraintRect,
        FilterConstraint filterConstraint,
        bool coordsLimitedToConstraintRect,
        const GrSamplerState::Filter* filterOrNullForBicubic) {
    SkMatrix textureMatrix = origTextureMatrix;

    SkRect domain;
    GrSamplerState samplerState;
    if (filterOrNullForBicubic) {
        samplerState.setFilterMode(*filterOrNullForBicubic);
    }
    SkScalar scaleAdjust[2] = { 1.0f, 1.0f };
    sk_sp<GrTextureProxy> proxy(
            this->refTextureProxyForParams(samplerState, scaleAdjust));
    if (!proxy) {
        return nullptr;
    }
    // If we made a copy then we only copied the contentArea, in which case the new texture is all
    // content.
    if (proxy.get() != this->originalProxy()) {
        textureMatrix.postScale(scaleAdjust[0], scaleAdjust[1]);
    }

    DomainMode domainMode =
        DetermineDomainMode(constraintRect, filterConstraint, coordsLimitedToConstraintRect,
                            proxy.get(), filterOrNullForBicubic, &domain);
    if (kTightCopy_DomainMode == domainMode) {
        // TODO: Copy the texture and adjust the texture matrix (both parts need to consider
        // non-int constraint rect)
        // For now: treat as bilerp and ignore what goes on above level 0.

        // We only expect MIP maps to require a tight copy.
        SkASSERT(filterOrNullForBicubic &&
                 GrSamplerState::Filter::kMipMap == *filterOrNullForBicubic);
        static const GrSamplerState::Filter kBilerp = GrSamplerState::Filter::kBilerp;
        domainMode =
            DetermineDomainMode(constraintRect, filterConstraint, coordsLimitedToConstraintRect,
                                proxy.get(), &kBilerp, &domain);
        SkASSERT(kTightCopy_DomainMode != domainMode);
    }
    SkASSERT(kNoDomain_DomainMode == domainMode ||
             (domain.fLeft <= domain.fRight && domain.fTop <= domain.fBottom));
    return CreateFragmentProcessorForDomainAndFilter(std::move(proxy), textureMatrix, domainMode,
                                                     domain, filterOrNullForBicubic);
}
