Initial import from TransGaming
git-svn-id: https://angleproject.googlecode.com/svn/trunk@2 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/libGLESv2/Shader.cpp b/libGLESv2/Shader.cpp
new file mode 100644
index 0000000..4ee2ce2
--- /dev/null
+++ b/libGLESv2/Shader.cpp
@@ -0,0 +1,337 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Shader.cpp: Implements the gl::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 "Shaderlang.h"
+#include "debug.h"
+
+namespace gl
+{
+void *Shader::mFragmentCompiler = NULL;
+void *Shader::mVertexCompiler = NULL;
+
+Shader::Shader()
+{
+ mSource = NULL;
+ mHlsl = NULL;
+ mErrors = NULL;
+
+ // Perform a one-time initialization of the shader compiler (or after being destructed by releaseCompiler)
+ if (!mFragmentCompiler)
+ {
+ int result = ShInitialize();
+
+ if (result)
+ {
+ mFragmentCompiler = ShConstructCompiler(EShLangFragment, EDebugOpObjectCode);
+ mVertexCompiler = ShConstructCompiler(EShLangVertex, EDebugOpObjectCode);
+ }
+ }
+
+ mAttachCount = 0;
+ mDeleteStatus = false;
+}
+
+Shader::~Shader()
+{
+ delete[] mSource;
+ delete[] mHlsl;
+ delete[] mErrors;
+}
+
+void Shader::setSource(GLsizei count, const char **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';
+}
+
+bool Shader::isCompiled()
+{
+ return mHlsl != NULL;
+}
+
+const char *Shader::linkHLSL()
+{
+ return mHlsl;
+}
+
+void Shader::attach()
+{
+ mAttachCount++;
+}
+
+void Shader::detach()
+{
+ mAttachCount--;
+}
+
+bool Shader::isAttached() const
+{
+ return mAttachCount > 0;
+}
+
+bool Shader::isDeletable() const
+{
+ return mDeleteStatus == true && mAttachCount == 0;
+}
+
+void Shader::flagForDeletion()
+{
+ mDeleteStatus = true;
+}
+
+void Shader::releaseCompiler()
+{
+ ShDestruct(mFragmentCompiler);
+ ShDestruct(mVertexCompiler);
+
+ mFragmentCompiler = NULL;
+ mVertexCompiler = NULL;
+}
+
+void Shader::compileToHLSL(void *compiler)
+{
+ if (isCompiled() || !mSource)
+ {
+ return;
+ }
+
+ trace(mSource);
+
+ delete[] mErrors;
+ mErrors = NULL;
+
+ TBuiltInResource 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;
+
+ int result = ShCompile(compiler, &mSource, 1, EShOptNone, &resources, EDebugOpObjectCode);
+ const char *obj = ShGetObjectCode(compiler);
+ const char *info = ShGetInfoLog(compiler);
+
+ if (result)
+ {
+ mHlsl = new char[strlen(obj) + 1];
+ strcpy(mHlsl, obj);
+
+ trace(mHlsl);
+ }
+ else
+ {
+ mErrors = new char[strlen(info) + 1];
+ strcpy(mErrors, info);
+
+ trace(mErrors);
+ }
+}
+
+InputMapping::InputMapping()
+{
+ mAttribute = NULL;
+ mSemanticIndex = -1;
+}
+
+InputMapping::InputMapping(const char *attribute, int semanticIndex)
+{
+ mAttribute = new char[strlen(attribute) + 1];
+ strcpy(mAttribute, attribute);
+ mSemanticIndex = semanticIndex;
+}
+
+InputMapping &InputMapping::operator=(const InputMapping &inputMapping)
+{
+ delete[] mAttribute;
+
+ mAttribute = new char[strlen(inputMapping.mAttribute) + 1];
+ strcpy(mAttribute, inputMapping.mAttribute);
+ mSemanticIndex = inputMapping.mSemanticIndex;
+
+ return *this;
+}
+
+InputMapping::~InputMapping()
+{
+ delete[] mAttribute;
+}
+
+VertexShader::VertexShader()
+{
+}
+
+VertexShader::~VertexShader()
+{
+}
+
+GLenum VertexShader::getType()
+{
+ return GL_VERTEX_SHADER;
+}
+
+void VertexShader::compile()
+{
+ compileToHLSL(mVertexCompiler);
+ parseAttributes();
+}
+
+const char *VertexShader::linkHLSL(const char *pixelHLSL)
+{
+ if (mHlsl && pixelHLSL)
+ {
+ const char *input = strstr(pixelHLSL, "struct PS_INPUT");
+ char *output = strstr(mHlsl, "struct VS_OUTPUT");
+
+ while (*input != '}' && output)
+ {
+ char varyingName[100];
+ int semanticIndex;
+ int matches = sscanf(input, "%s : TEXCOORD%d;", varyingName, &semanticIndex);
+
+ if (matches == 2)
+ {
+ ASSERT(semanticIndex < 10 && semanticIndex < MAX_VARYING_VECTORS);
+ char *varying = strstr(output, varyingName);
+ varying = strstr(varying, " : TEXCOORD0;");
+
+ if (output)
+ {
+ varying[11] = '0' + semanticIndex;
+ }
+ else
+ {
+ return NULL;
+ }
+
+ input = strstr(input, ";");
+ }
+
+ input++;
+ }
+ }
+
+ return mHlsl;
+}
+
+const char *VertexShader::getAttributeName(unsigned int attributeIndex)
+{
+ if (attributeIndex < MAX_VERTEX_ATTRIBS)
+ {
+ return mInputMapping[attributeIndex].mAttribute;
+ }
+
+ return 0;
+}
+
+bool VertexShader::isActiveAttribute(const char *attributeName)
+{
+ return getInputMapping(attributeName) != -1;
+}
+
+int VertexShader::getInputMapping(const char *attributeName)
+{
+ if (attributeName)
+ {
+ for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
+ {
+ if (mInputMapping[index].mAttribute && strcmp(mInputMapping[index].mAttribute, attributeName) == 0)
+ {
+ return mInputMapping[index].mSemanticIndex;
+ }
+ }
+ }
+
+ return -1;
+}
+
+void VertexShader::parseAttributes()
+{
+ if (mHlsl)
+ {
+ const char *input = strstr(mHlsl, "struct VS_INPUT");
+
+ for (int attributeIndex = 0; *input != '}'; input++)
+ {
+ char attributeName[100];
+ int semanticIndex;
+
+ int matches = sscanf(input, "%s : TEXCOORD%d;", attributeName, &semanticIndex);
+
+ if (matches == 2)
+ {
+ ASSERT(attributeIndex < MAX_VERTEX_ATTRIBS);
+ mInputMapping[attributeIndex] = InputMapping(attributeName, semanticIndex);
+ attributeIndex++;
+
+ input = strstr(input, ";");
+ }
+ }
+ }
+}
+
+FragmentShader::FragmentShader()
+{
+}
+
+FragmentShader::~FragmentShader()
+{
+}
+
+GLenum FragmentShader::getType()
+{
+ return GL_FRAGMENT_SHADER;
+}
+
+void FragmentShader::compile()
+{
+ compileToHLSL(mFragmentCompiler);
+}
+}