/*
 * 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/GrTextureProducer.h"

#include "include/private/GrRecordingContext.h"
#include "src/core/SkMipMap.h"
#include "src/core/SkRectPriv.h"
#include "src/gpu/GrClip.h"
#include "src/gpu/GrContextPriv.h"
#include "src/gpu/GrProxyProvider.h"
#include "src/gpu/GrRecordingContextPriv.h"
#include "src/gpu/GrRenderTargetContext.h"
#include "src/gpu/GrTextureProxy.h"
#include "src/gpu/SkGr.h"
#include "src/gpu/effects/GrBicubicEffect.h"
#include "src/gpu/effects/GrTextureEffect.h"

/** Determines whether a texture domain is necessary and if so what domain to use. There are two
 *  rectangles to consider:
 *  - The first is the content area specified by the texture adjuster (i.e., textureContentArea).
 *    We can *never* allow filtering to cause bleed of pixels outside this rectangle.
 *  - The second rectangle is the constraint rectangle (i.e., constraintRect), which is known to
 *    be contained by the content area. The filterConstraint specifies whether we are allowed to
 *    bleed across this rect.
 *
 *  We want to avoid using a domain if possible. We consider the above rectangles, the filter type,
 *  and whether the coords generated by the draw would all fall within the constraint rect. If the
 *  latter is true we only need to consider whether the filter would extend beyond the rects.
 */
GrTextureProducer::DomainMode GrTextureProducer::DetermineDomainMode(
        const SkRect& constraintRect,
        FilterConstraint filterConstraint,
        bool coordsLimitedToConstraintRect,
        GrSurfaceProxy* proxy,
        const GrSamplerState::Filter* filterModeOrNullForBicubic,
        SkRect* domainRect) {
    const SkIRect proxyBounds = SkIRect::MakeSize(proxy->dimensions());

    SkASSERT(proxyBounds.contains(constraintRect));

    const bool proxyIsExact = proxy->isFunctionallyExact();

    // If the constraint rectangle contains the whole proxy then no need for a domain.
    if (constraintRect.contains(proxyBounds) && proxyIsExact) {
        return kNoDomain_DomainMode;
    }

    bool restrictFilterToRect = (filterConstraint == GrTextureProducer::kYes_FilterConstraint);

    // If we can filter outside the constraint rect, and there is no non-content area of the
    // proxy, and we aren't going to generate sample coords outside the constraint rect then we
    // don't need a domain.
    if (!restrictFilterToRect && proxyIsExact && coordsLimitedToConstraintRect) {
        return kNoDomain_DomainMode;
    }

    // Get the domain inset based on sampling mode (or bail if mipped). This is used
    // to evaluate whether we will read outside a non-exact proxy's dimensions.
    // TODO: Let GrTextureEffect handle this.
    SkScalar filterHalfWidth = 0.f;
    if (filterModeOrNullForBicubic) {
        switch (*filterModeOrNullForBicubic) {
            case GrSamplerState::Filter::kNearest:
                if (coordsLimitedToConstraintRect) {
                    return kNoDomain_DomainMode;
                } else {
                    filterHalfWidth = 0.f;
                }
                break;
            case GrSamplerState::Filter::kBilerp:
                filterHalfWidth = .5f;
                break;
            case GrSamplerState::Filter::kMipMap:
                if (restrictFilterToRect || !proxyIsExact) {
                    // No domain can save us here.
                    return kTightCopy_DomainMode;
                }
                return kNoDomain_DomainMode;
        }
    } else {
        // bicubic does nearest filtering internally.
        filterHalfWidth = 1.5f;
    }

    if (restrictFilterToRect) {
        *domainRect = constraintRect;
    } else if (!proxyIsExact) {
        // If we got here then: proxy is not exact, the coords are limited to the
        // constraint rect, and we're allowed to filter across the constraint rect boundary. So
        // we check whether the filter would reach across the edge of the proxy.
        // We will only set the sides that are required.

        *domainRect = SkRectPriv::MakeLargest();
        if (coordsLimitedToConstraintRect) {
            // We may be able to use the fact that the texture coords are limited to the constraint
            // rect in order to avoid having to add a domain.
            bool needContentAreaConstraint = false;
            if (proxyBounds.fRight - filterHalfWidth < constraintRect.fRight) {
                domainRect->fRight = proxyBounds.fRight;
                needContentAreaConstraint = true;
            }
            if (proxyBounds.fBottom - filterHalfWidth < constraintRect.fBottom) {
                domainRect->fBottom = proxyBounds.fBottom;
                needContentAreaConstraint = true;
            }
            if (!needContentAreaConstraint) {
                return kNoDomain_DomainMode;
            }
        }
    } else {
        return kNoDomain_DomainMode;
    }

    if (!filterModeOrNullForBicubic) {
        // Bicubic doesn't yet rely on GrTextureEffect to do this insetting.
        domainRect->inset(0.5f, 0.5f);
        if (domainRect->fLeft > domainRect->fRight) {
            domainRect->fLeft = domainRect->fRight =
                    SkScalarAve(domainRect->fLeft, domainRect->fRight);
        }
        if (domainRect->fTop > domainRect->fBottom) {
            domainRect->fTop = domainRect->fBottom =
                    SkScalarAve(domainRect->fTop, domainRect->fBottom);
        }
    }

    return kDomain_DomainMode;
}

std::unique_ptr<GrFragmentProcessor> GrTextureProducer::createFragmentProcessorForSubsetAndFilter(
        GrSurfaceProxyView view,
        const SkMatrix& textureMatrix,
        DomainMode domainMode,
        const SkRect& domain,
        GrSamplerState::WrapMode wrapX,
        GrSamplerState::WrapMode wrapY,
        const GrSamplerState::Filter* filterOrNullForBicubic) {
    SkASSERT(kTightCopy_DomainMode != domainMode);
    SkASSERT(view.asTextureProxy());
    const auto& caps = *fContext->priv().caps();
    SkAlphaType srcAlphaType = this->alphaType();
    if (filterOrNullForBicubic) {
        GrSamplerState samplerState(wrapX, wrapY, *filterOrNullForBicubic);
        if (kNoDomain_DomainMode == domainMode) {
            return GrTextureEffect::Make(std::move(view), srcAlphaType, textureMatrix, samplerState,
                                         caps);
        }
        return GrTextureEffect::MakeSubset(std::move(view), srcAlphaType, textureMatrix,
                                           samplerState, domain, caps);
    } else {
        static constexpr auto kDir    = GrBicubicEffect::Direction::kXY;
        static constexpr auto kKernel = GrBicubicEffect::Kernel::kMitchell;
        const auto& caps = *fContext->priv().caps();
        if (kDomain_DomainMode == domainMode) {
            return GrBicubicEffect::MakeSubset(std::move(view), srcAlphaType, textureMatrix, wrapX,
                                               wrapY, domain, kKernel, kDir, caps);
        } else {
            return GrBicubicEffect::Make(std::move(view), srcAlphaType, textureMatrix, wrapX, wrapY,
                                         kKernel, kDir, caps);
        }
    }
}

GrSurfaceProxyView GrTextureProducer::view(GrMipMapped mipMapped) {
    const GrCaps* caps = this->context()->priv().caps();
    // Sanitize the MIP map request.
    if (mipMapped == GrMipMapped::kYes) {
        if ((this->width() == 1 && this->height() == 1) || !caps->mipMapSupport()) {
            mipMapped = GrMipMapped::kNo;
        }
    }
    auto result = this->onView(mipMapped);
    // Check to make sure if we requested MIPs that the returned texture has MIP maps or the format
    // is not copyable.
    SkASSERT(!result || mipMapped == GrMipMapped::kNo ||
             result.asTextureProxy()->mipMapped() == GrMipMapped::kYes ||
             !caps->isFormatCopyable(result.proxy()->backendFormat()));
    return result;
}

GrSurfaceProxyView GrTextureProducer::view(GrSamplerState::Filter filter) {
    auto mipMapped = filter == GrSamplerState::Filter::kMipMap ? GrMipMapped::kYes
                                                               : GrMipMapped::kNo;
    return this->view(mipMapped);
}
