// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Shader.cpp: Implements the Shader class and its  derived classes
// VertexShader and FragmentShader. Implements GL shader objects and related
// functionality. [OpenGL ES 2.0.24] section 2.10 page 24 and section 3.8 page 84.

#include "Shader.h"

#include "main.h"
#include "utilities.h"

#include <string>
#include <algorithm>

namespace es2
{
std::mutex Shader::mutex;
bool Shader::compilerInitialized = false;

Shader::Shader(ResourceManager *manager, GLuint handle) : mHandle(handle), mResourceManager(manager)
{
	mSource = nullptr;

	clear();

	mRefCount = 0;
	mDeleteStatus = false;
}

Shader::~Shader()
{
	delete[] mSource;
}

GLuint Shader::getName() const
{
	return mHandle;
}

void Shader::setSource(GLsizei count, const char *const *string, const GLint *length)
{
	delete[] mSource;
	int totalLength = 0;

	for(int i = 0; i < count; i++)
	{
		if(length && length[i] >= 0)
		{
			totalLength += length[i];
		}
		else
		{
			totalLength += (int)strlen(string[i]);
		}
	}

	mSource = new char[totalLength + 1];
	char *code = mSource;

	for(int i = 0; i < count; i++)
	{
		int stringLength;

		if(length && length[i] >= 0)
		{
			stringLength = length[i];
		}
		else
		{
			stringLength = (int)strlen(string[i]);
		}

		strncpy(code, string[i], stringLength);
		code += stringLength;
	}

	mSource[totalLength] = '\0';
}

size_t Shader::getInfoLogLength() const
{
	if(infoLog.empty())
	{
		return 0;
	}
	else
	{
	   return infoLog.size() + 1;
	}
}

void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLogOut)
{
	int index = 0;

	if(bufSize > 0)
	{
		if(!infoLog.empty())
		{
			index = std::min(bufSize - 1, (GLsizei)infoLog.size());
			memcpy(infoLogOut, infoLog.c_str(), index);
		}

		infoLogOut[index] = '\0';
	}

	if(length)
	{
		*length = index;
	}
}

size_t Shader::getSourceLength() const
{
	if(!mSource)
	{
		return 0;
	}
	else
	{
	   return strlen(mSource) + 1;
	}
}

void Shader::getSource(GLsizei bufSize, GLsizei *length, char *source)
{
	int index = 0;

	if(bufSize > 0)
	{
		if(mSource)
		{
			index = std::min(bufSize - 1, (int)strlen(mSource));
			memcpy(source, mSource, index);
		}

		source[index] = '\0';
	}

	if(length)
	{
		*length = index;
	}
}

TranslatorASM *Shader::createCompiler(GLenum shaderType)
{
	if(!compilerInitialized)
	{
		compilerInitialized = InitCompilerGlobals();

		if(!compilerInitialized)
		{
			infoLog += "GLSL compiler failed to initialize.\n";

			return nullptr;
		}
	}

	TranslatorASM *assembler = new TranslatorASM(this, shaderType);

	ShBuiltInResources resources;
	resources.MaxVertexAttribs = MAX_VERTEX_ATTRIBS;
	resources.MaxVertexUniformVectors = MAX_VERTEX_UNIFORM_VECTORS;
	resources.MaxVaryingVectors = MAX_VARYING_VECTORS;
	resources.MaxVertexTextureImageUnits = MAX_VERTEX_TEXTURE_IMAGE_UNITS;
	resources.MaxCombinedTextureImageUnits = MAX_COMBINED_TEXTURE_IMAGE_UNITS;
	resources.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
	resources.MaxFragmentUniformVectors = MAX_FRAGMENT_UNIFORM_VECTORS;
	resources.MaxDrawBuffers = MAX_DRAW_BUFFERS;
	resources.MaxVertexOutputVectors = MAX_VERTEX_OUTPUT_VECTORS;
	resources.MaxFragmentInputVectors = MAX_FRAGMENT_INPUT_VECTORS;
	resources.MinProgramTexelOffset = MIN_PROGRAM_TEXEL_OFFSET;
	resources.MaxProgramTexelOffset = MAX_PROGRAM_TEXEL_OFFSET;
	resources.OES_standard_derivatives = 1;
	resources.OES_fragment_precision_high = 1;
	resources.OES_EGL_image_external = 1;
	resources.OES_EGL_image_external_essl3 = 1;
	resources.EXT_draw_buffers = 1;
	resources.ARB_texture_rectangle = 1;
	resources.MaxCallStackDepth = MAX_SHADER_CALL_STACK_SIZE;
	assembler->Init(resources);

	return assembler;
}

void Shader::clear()
{
	infoLog.clear();

	varyings.clear();
	activeUniforms.clear();
	activeAttributes.clear();
}

void Shader::compile()
{
	// Our version of glslang is not thread safe.
	std::lock_guard<std::mutex> lock(mutex);

	clear();

	createShader();
	TranslatorASM *compiler = createCompiler(getType());

	if(!compiler)
	{
		deleteShader();

		return;
	}

	// Ensure we don't pass a nullptr source to the compiler
	const char *source = "\0";
	if(mSource)
	{
		source = mSource;
	}

	bool success = compiler->compile(&source, 1, SH_OBJECT_CODE);

	if(false)
	{
		static int serial = 1;

		if(false)
		{
			char buffer[256];
			sprintf(buffer, "shader-input-%d-%d.txt", getName(), serial);
			FILE *file = fopen(buffer, "wt");
			fprintf(file, "%s", mSource);
			fclose(file);
		}

		getShader()->print("shader-output-%d-%d.txt", getName(), serial);

		serial++;
	}

	shaderVersion = compiler->getShaderVersion();
	infoLog += compiler->getInfoSink().info.c_str();

	if(!success)
	{
		deleteShader();

		TRACE("\n%s", infoLog.c_str());
	}

	delete compiler;
}

bool Shader::isCompiled()
{
	return getShader() != 0;
}

void Shader::addRef()
{
	mRefCount++;
}

void Shader::release()
{
	mRefCount--;

	if(mRefCount == 0 && mDeleteStatus)
	{
		mResourceManager->deleteShader(mHandle);
	}
}

unsigned int Shader::getRefCount() const
{
	return mRefCount;
}

bool Shader::isFlaggedForDeletion() const
{
	return mDeleteStatus;
}

void Shader::flagForDeletion()
{
	mDeleteStatus = true;
}

void Shader::releaseCompiler()
{
	// Our version of glslang is not thread safe.
	std::lock_guard<std::mutex> lock(mutex);

	FreeCompilerGlobals();
	compilerInitialized = false;
}

// true if varying x has a higher priority in packing than y
bool Shader::compareVarying(const glsl::Varying &x, const glsl::Varying &y)
{
	if(x.type == y.type)
	{
		return x.size() > y.size();
	}

	switch(x.type)
	{
	case GL_FLOAT_MAT4: return true;
	case GL_FLOAT_MAT2:
		switch(y.type)
		{
		case GL_FLOAT_MAT4: return false;
		case GL_FLOAT_MAT2: return true;
		case GL_FLOAT_VEC4: return true;
		case GL_FLOAT_MAT3: return true;
		case GL_FLOAT_VEC3: return true;
		case GL_FLOAT_VEC2: return true;
		case GL_FLOAT:      return true;
		default: UNREACHABLE(y.type);
		}
		break;
	case GL_FLOAT_VEC4:
		switch(y.type)
		{
		case GL_FLOAT_MAT4: return false;
		case GL_FLOAT_MAT2: return false;
		case GL_FLOAT_VEC4: return true;
		case GL_FLOAT_MAT3: return true;
		case GL_FLOAT_VEC3: return true;
		case GL_FLOAT_VEC2: return true;
		case GL_FLOAT:      return true;
		default: UNREACHABLE(y.type);
		}
		break;
	case GL_FLOAT_MAT3:
		switch(y.type)
		{
		case GL_FLOAT_MAT4: return false;
		case GL_FLOAT_MAT2: return false;
		case GL_FLOAT_VEC4: return false;
		case GL_FLOAT_MAT3: return true;
		case GL_FLOAT_VEC3: return true;
		case GL_FLOAT_VEC2: return true;
		case GL_FLOAT:      return true;
		default: UNREACHABLE(y.type);
		}
		break;
	case GL_FLOAT_VEC3:
		switch(y.type)
		{
		case GL_FLOAT_MAT4: return false;
		case GL_FLOAT_MAT2: return false;
		case GL_FLOAT_VEC4: return false;
		case GL_FLOAT_MAT3: return false;
		case GL_FLOAT_VEC3: return true;
		case GL_FLOAT_VEC2: return true;
		case GL_FLOAT:      return true;
		default: UNREACHABLE(y.type);
		}
		break;
	case GL_FLOAT_VEC2:
		switch(y.type)
		{
		case GL_FLOAT_MAT4: return false;
		case GL_FLOAT_MAT2: return false;
		case GL_FLOAT_VEC4: return false;
		case GL_FLOAT_MAT3: return false;
		case GL_FLOAT_VEC3: return false;
		case GL_FLOAT_VEC2: return true;
		case GL_FLOAT:      return true;
		default: UNREACHABLE(y.type);
		}
		break;
	case GL_FLOAT: return false;
	default: UNREACHABLE(x.type);
	}

	return false;
}

VertexShader::VertexShader(ResourceManager *manager, GLuint handle) : Shader(manager, handle)
{
	vertexShader = 0;
}

VertexShader::~VertexShader()
{
	delete vertexShader;
}

GLenum VertexShader::getType() const
{
	return GL_VERTEX_SHADER;
}

int VertexShader::getSemanticIndex(const std::string &attributeName) const
{
	if(!attributeName.empty())
	{
		for(const auto &attribute : activeAttributes)
		{
			if(attribute.name == attributeName)
			{
				return attribute.registerIndex;
			}
		}
	}

	return -1;
}

sw::Shader *VertexShader::getShader() const
{
	return vertexShader;
}

sw::VertexShader *VertexShader::getVertexShader() const
{
	return vertexShader;
}

void VertexShader::createShader()
{
	delete vertexShader;
	vertexShader = new sw::VertexShader();
}

void VertexShader::deleteShader()
{
	delete vertexShader;
	vertexShader = nullptr;
}

FragmentShader::FragmentShader(ResourceManager *manager, GLuint handle) : Shader(manager, handle)
{
	pixelShader = 0;
}

FragmentShader::~FragmentShader()
{
	delete pixelShader;
}

GLenum FragmentShader::getType() const
{
	return GL_FRAGMENT_SHADER;
}

sw::Shader *FragmentShader::getShader() const
{
	return pixelShader;
}

sw::PixelShader *FragmentShader::getPixelShader() const
{
	return pixelShader;
}

void FragmentShader::createShader()
{
	delete pixelShader;
	pixelShader = new sw::PixelShader();
}

void FragmentShader::deleteShader()
{
	delete pixelShader;
	pixelShader = nullptr;
}

}
