/*
 * 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 "GrShaderVar.h"
#include "GrShaderCaps.h"

static const char* type_modifier_string(GrShaderVar::TypeModifier t) {
    switch (t) {
        case GrShaderVar::kNone_TypeModifier: return "";
        case GrShaderVar::kIn_TypeModifier: return "in";
        case GrShaderVar::kInOut_TypeModifier: return "inout";
        case GrShaderVar::kOut_TypeModifier: return "out";
        case GrShaderVar::kUniform_TypeModifier: return "uniform";
    }
    SK_ABORT("Unknown shader variable type modifier.");
    return "";
}

void GrShaderVar::setImageStorageFormat(GrImageStorageFormat format) {
    const char* formatStr = nullptr;
    switch (format) {
        case GrImageStorageFormat::kRGBA8:
            formatStr = "rgba8";
            break;
        case GrImageStorageFormat::kRGBA8i:
            formatStr = "rgba8i";
            break;
        case GrImageStorageFormat::kRGBA16f:
            formatStr = "rgba16f";
            break;
        case GrImageStorageFormat::kRGBA32f:
            formatStr = "rgba32f";
            break;
    }
    this->addLayoutQualifier(formatStr);
    SkASSERT(formatStr);
}

void GrShaderVar::setMemoryModel(GrSLMemoryModel model) {
    switch (model) {
        case GrSLMemoryModel::kNone:
            return;
        case GrSLMemoryModel::kCoherent:
            this->addModifier("coherent");
            return;
        case GrSLMemoryModel::kVolatile:
            this->addModifier("volatile");
            return;
    }
    SK_ABORT("Unknown memory model.");
}

void GrShaderVar::setRestrict(GrSLRestrict restrict) {
    switch (restrict) {
        case GrSLRestrict::kNo:
            return;
        case GrSLRestrict::kYes:
            this->addModifier("restrict");
            return;
    }
    SK_ABORT("Unknown restrict.");
}

void GrShaderVar::setIOType(GrIOType ioType) {
    switch (ioType) {
        case kRW_GrIOType:
            return;
        case kRead_GrIOType:
            this->addModifier("readonly");
            return;
        case kWrite_GrIOType:
            this->addModifier("writeonly");
            return;
    }
    SK_ABORT("Unknown io type.");
}

void GrShaderVar::appendDecl(const GrShaderCaps* shaderCaps, SkString* out) const {
    SkASSERT(kDefault_GrSLPrecision == fPrecision || GrSLTypeAcceptsPrecision(fType));
    SkString layout = fLayoutQualifier;
    if (!fLayoutQualifier.isEmpty()) {
        out->appendf("layout(%s) ", fLayoutQualifier.c_str());
    }
    out->append(fExtraModifiers);
    if (this->getTypeModifier() != kNone_TypeModifier) {
        out->append(type_modifier_string(this->getTypeModifier()));
        out->append(" ");
    }
    GrSLType effectiveType = this->getType();
    if (shaderCaps->usesPrecisionModifiers() && GrSLTypeAcceptsPrecision(effectiveType)) {
        // Desktop GLSL has added precision qualifiers but they don't do anything.
        out->appendf("%s ", GrGLSLPrecisionString(fPrecision));
    }
    if (this->isArray()) {
        if (this->isUnsizedArray()) {
            out->appendf("%s %s[]",
                         GrGLSLTypeString(shaderCaps, effectiveType),
                         this->getName().c_str());
        } else {
            SkASSERT(this->getArrayCount() > 0);
            out->appendf("%s %s[%d]",
                         GrGLSLTypeString(shaderCaps, effectiveType),
                         this->getName().c_str(),
                         this->getArrayCount());
        }
    } else {
        out->appendf("%s %s",
                     GrGLSLTypeString(shaderCaps, effectiveType),
                     this->getName().c_str());
    }
}
