/*
 * Copyright 2011 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/gl/GrGLProgram.h"

#include "src/gpu/GrFragmentProcessor.h"
#include "src/gpu/GrGeometryProcessor.h"
#include "src/gpu/GrPipeline.h"
#include "src/gpu/GrProcessor.h"
#include "src/gpu/GrProgramInfo.h"
#include "src/gpu/GrTexture.h"
#include "src/gpu/GrXferProcessor.h"
#include "src/gpu/effects/GrTextureEffect.h"
#include "src/gpu/gl/GrGLBuffer.h"
#include "src/gpu/gl/GrGLGpu.h"
#include "src/sksl/SkSLCompiler.h"

#define GL_CALL(X) GR_GL_CALL(fGpu->glInterface(), X)
#define GL_CALL_RET(R, X) GR_GL_CALL_RET(fGpu->glInterface(), R, X)

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

sk_sp<GrGLProgram> GrGLProgram::Make(
        GrGLGpu* gpu,
        const GrGLSLBuiltinUniformHandles& builtinUniforms,
        GrGLuint programID,
        const UniformInfoArray& uniforms,
        const UniformInfoArray& textureSamplers,
        std::unique_ptr<GrGeometryProcessor::ProgramImpl> gpImpl,
        std::unique_ptr<GrXferProcessor::ProgramImpl> xpImpl,
        std::vector<std::unique_ptr<GrFragmentProcessor::ProgramImpl>> fpImpls,
        std::unique_ptr<Attribute[]> attributes,
        int vertexAttributeCnt,
        int instanceAttributeCnt,
        int vertexStride,
        int instanceStride) {
    sk_sp<GrGLProgram> program(new GrGLProgram(gpu,
                                               builtinUniforms,
                                               programID,
                                               uniforms,
                                               textureSamplers,
                                               std::move(gpImpl),
                                               std::move(xpImpl),
                                               std::move(fpImpls),
                                               std::move(attributes),
                                               vertexAttributeCnt,
                                               instanceAttributeCnt,
                                               vertexStride,
                                               instanceStride));
    // Assign texture units to sampler uniforms one time up front.
    gpu->flushProgram(program);
    program->fProgramDataManager.setSamplerUniforms(textureSamplers, 0);
    return program;
}

GrGLProgram::GrGLProgram(GrGLGpu* gpu,
                         const GrGLSLBuiltinUniformHandles& builtinUniforms,
                         GrGLuint programID,
                         const UniformInfoArray& uniforms,
                         const UniformInfoArray& textureSamplers,
                         std::unique_ptr<GrGeometryProcessor::ProgramImpl> gpImpl,
                         std::unique_ptr<GrXferProcessor::ProgramImpl> xpImpl,
                         std::vector<std::unique_ptr<GrFragmentProcessor::ProgramImpl>> fpImpls,
                         std::unique_ptr<Attribute[]> attributes,
                         int vertexAttributeCnt,
                         int instanceAttributeCnt,
                         int vertexStride,
                         int instanceStride)
        : fBuiltinUniformHandles(builtinUniforms)
        , fProgramID(programID)
        , fGPImpl(std::move(gpImpl))
        , fXPImpl(std::move(xpImpl))
        , fFPImpls(std::move(fpImpls))
        , fAttributes(std::move(attributes))
        , fVertexAttributeCnt(vertexAttributeCnt)
        , fInstanceAttributeCnt(instanceAttributeCnt)
        , fVertexStride(vertexStride)
        , fInstanceStride(instanceStride)
        , fGpu(gpu)
        , fProgramDataManager(gpu, uniforms)
        , fNumTextureSamplers(textureSamplers.count()) {}

GrGLProgram::~GrGLProgram() {
    if (fProgramID) {
        GL_CALL(DeleteProgram(fProgramID));
    }
}

void GrGLProgram::abandon() {
    fProgramID = 0;
}

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

void GrGLProgram::updateUniforms(const GrRenderTarget* renderTarget,
                                 const GrProgramInfo& programInfo) {
    this->setRenderTargetState(renderTarget, programInfo.origin(), programInfo.geomProc());

    // we set the uniforms for installed processors in a generic way, but subclasses of GLProgram
    // determine how to set coord transforms

    // We must bind to texture units in the same order in which we set the uniforms in
    // GrGLProgramDataManager. That is, we bind textures for processors in this order:
    // primProc, fragProcs, XP.
    fGPImpl->setData(fProgramDataManager, *fGpu->caps()->shaderCaps(), programInfo.geomProc());

    for (int i = 0; i < programInfo.pipeline().numFragmentProcessors(); ++i) {
        const auto& fp = programInfo.pipeline().getFragmentProcessor(i);
        fp.visitWithImpls([&](const GrFragmentProcessor& fp,
                              GrFragmentProcessor::ProgramImpl& impl) {
            impl.setData(fProgramDataManager, fp);
        }, *fFPImpls[i]);
    }

    programInfo.pipeline().setDstTextureUniforms(fProgramDataManager, &fBuiltinUniformHandles);
    fXPImpl->setData(fProgramDataManager, programInfo.pipeline().getXferProcessor());
}

void GrGLProgram::bindTextures(const GrGeometryProcessor& geomProc,
                               const GrSurfaceProxy* const geomProcTextures[],
                               const GrPipeline& pipeline) {
    // Bind textures from the geometry processor.
    for (int i = 0; i < geomProc.numTextureSamplers(); ++i) {
        SkASSERT(geomProcTextures[i]->asTextureProxy());
        auto* overrideTexture = static_cast<GrGLTexture*>(geomProcTextures[i]->peekTexture());
        fGpu->bindTexture(i, geomProc.textureSampler(i).samplerState(),
                          geomProc.textureSampler(i).swizzle(), overrideTexture);
    }
    int nextTexSamplerIdx = geomProc.numTextureSamplers();
    // Bind texture from the destination proxy view.
    GrTexture* dstTexture = pipeline.peekDstTexture();
    if (dstTexture) {
        fGpu->bindTexture(nextTexSamplerIdx++, GrSamplerState::Filter::kNearest,
                          pipeline.dstProxyView().swizzle(), static_cast<GrGLTexture*>(dstTexture));
    }
    // Bind textures from all of the fragment processors.
    pipeline.visitTextureEffects([&](const GrTextureEffect& te) {
        GrSamplerState samplerState = te.samplerState();
        GrSwizzle swizzle = te.view().swizzle();
        auto* texture = static_cast<GrGLTexture*>(te.texture());
        fGpu->bindTexture(nextTexSamplerIdx++, samplerState, swizzle, texture);
    });

    SkASSERT(nextTexSamplerIdx == fNumTextureSamplers);
}

void GrGLProgram::setRenderTargetState(const GrRenderTarget* rt,
                                       GrSurfaceOrigin origin,
                                       const GrGeometryProcessor& geomProc) {
    // Set RT adjustment and RT flip
    SkISize dimensions = rt->dimensions();
    if (fRenderTargetState.fRenderTargetOrigin != origin ||
        fRenderTargetState.fRenderTargetSize != dimensions) {
        fRenderTargetState.fRenderTargetSize = dimensions;
        fRenderTargetState.fRenderTargetOrigin = origin;

        // The client will mark a swap buffer as kBottomLeft when making a SkSurface because
        // GL's framebuffer space has (0, 0) at the bottom left. In NDC (-1, -1) is also the
        // bottom left. However, Skia's device coords has (0, 0) at the top left, so a flip is
        // required when the origin is kBottomLeft.
        bool flip = (origin == kBottomLeft_GrSurfaceOrigin);
        std::array<float, 4> v = SkSL::Compiler::GetRTAdjustVector(dimensions, flip);
        fProgramDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, v.data());
        if (fBuiltinUniformHandles.fRTFlipUni.isValid()) {
            std::array<float, 2> d = SkSL::Compiler::GetRTFlipVector(dimensions.height(), flip);
            fProgramDataManager.set2fv(fBuiltinUniformHandles.fRTFlipUni, 1, d.data());
        }
    }
}
