summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/angle/src/libGLESv2/Program.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/angle/src/libGLESv2/Program.cpp')
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Program.cpp528
1 files changed, 528 insertions, 0 deletions
diff --git a/src/3rdparty/angle/src/libGLESv2/Program.cpp b/src/3rdparty/angle/src/libGLESv2/Program.cpp
new file mode 100644
index 0000000000..5f53a1f581
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/Program.cpp
@@ -0,0 +1,528 @@
+//
+// Copyright (c) 2002-2012 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.
+//
+
+// Program.cpp: Implements the gl::Program class. Implements GL program objects
+// and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28.
+
+#include "libGLESv2/Program.h"
+#include "libGLESv2/ProgramBinary.h"
+
+#include "common/debug.h"
+
+#include "libGLESv2/main.h"
+#include "libGLESv2/Shader.h"
+#include "libGLESv2/utilities.h"
+
+#include <string>
+
+namespace gl
+{
+const char * const g_fakepath = "C:\\fakepath";
+
+AttributeBindings::AttributeBindings()
+{
+}
+
+AttributeBindings::~AttributeBindings()
+{
+}
+
+InfoLog::InfoLog() : mInfoLog(NULL)
+{
+}
+
+InfoLog::~InfoLog()
+{
+ delete[] mInfoLog;
+}
+
+
+int InfoLog::getLength() const
+{
+ if (!mInfoLog)
+ {
+ return 0;
+ }
+ else
+ {
+ return strlen(mInfoLog) + 1;
+ }
+}
+
+void InfoLog::getLog(GLsizei bufSize, GLsizei *length, char *infoLog)
+{
+ int index = 0;
+
+ if (bufSize > 0)
+ {
+ if (mInfoLog)
+ {
+ index = std::min(bufSize - 1, (int)strlen(mInfoLog));
+ memcpy(infoLog, mInfoLog, index);
+ }
+
+ infoLog[index] = '\0';
+ }
+
+ if (length)
+ {
+ *length = index;
+ }
+}
+
+// append a santized message to the program info log.
+// The D3D compiler includes a fake file path in some of the warning or error
+// messages, so lets remove all occurrences of this fake file path from the log.
+void InfoLog::appendSanitized(const char *message)
+{
+ std::string msg(message);
+
+ size_t found;
+ do
+ {
+ found = msg.find(g_fakepath);
+ if (found != std::string::npos)
+ {
+ msg.erase(found, strlen(g_fakepath));
+ }
+ }
+ while (found != std::string::npos);
+
+ append("%s\n", msg.c_str());
+}
+
+void InfoLog::append(const char *format, ...)
+{
+ if (!format)
+ {
+ return;
+ }
+
+ char info[1024];
+
+ va_list vararg;
+ va_start(vararg, format);
+ vsnprintf(info, sizeof(info), format, vararg);
+ va_end(vararg);
+
+ size_t infoLength = strlen(info);
+
+ if (!mInfoLog)
+ {
+ mInfoLog = new char[infoLength + 1];
+ strcpy(mInfoLog, info);
+ }
+ else
+ {
+ size_t logLength = strlen(mInfoLog);
+ char *newLog = new char[logLength + infoLength + 1];
+ strcpy(newLog, mInfoLog);
+ strcpy(newLog + logLength, info);
+
+ delete[] mInfoLog;
+ mInfoLog = newLog;
+ }
+}
+
+void InfoLog::reset()
+{
+ if (mInfoLog)
+ {
+ delete [] mInfoLog;
+ mInfoLog = NULL;
+ }
+}
+
+Program::Program(ResourceManager *manager, GLuint handle) : mResourceManager(manager), mHandle(handle)
+{
+ mFragmentShader = NULL;
+ mVertexShader = NULL;
+ mProgramBinary.set(NULL);
+ mDeleteStatus = false;
+ mLinked = false;
+ mRefCount = 0;
+}
+
+Program::~Program()
+{
+ unlink(true);
+
+ if (mVertexShader != NULL)
+ {
+ mVertexShader->release();
+ }
+
+ if (mFragmentShader != NULL)
+ {
+ mFragmentShader->release();
+ }
+}
+
+bool Program::attachShader(Shader *shader)
+{
+ if (shader->getType() == GL_VERTEX_SHADER)
+ {
+ if (mVertexShader)
+ {
+ return false;
+ }
+
+ mVertexShader = (VertexShader*)shader;
+ mVertexShader->addRef();
+ }
+ else if (shader->getType() == GL_FRAGMENT_SHADER)
+ {
+ if (mFragmentShader)
+ {
+ return false;
+ }
+
+ mFragmentShader = (FragmentShader*)shader;
+ mFragmentShader->addRef();
+ }
+ else UNREACHABLE();
+
+ return true;
+}
+
+bool Program::detachShader(Shader *shader)
+{
+ if (shader->getType() == GL_VERTEX_SHADER)
+ {
+ if (mVertexShader != shader)
+ {
+ return false;
+ }
+
+ mVertexShader->release();
+ mVertexShader = NULL;
+ }
+ else if (shader->getType() == GL_FRAGMENT_SHADER)
+ {
+ if (mFragmentShader != shader)
+ {
+ return false;
+ }
+
+ mFragmentShader->release();
+ mFragmentShader = NULL;
+ }
+ else UNREACHABLE();
+
+ return true;
+}
+
+int Program::getAttachedShadersCount() const
+{
+ return (mVertexShader ? 1 : 0) + (mFragmentShader ? 1 : 0);
+}
+
+void AttributeBindings::bindAttributeLocation(GLuint index, const char *name)
+{
+ if (index < MAX_VERTEX_ATTRIBS)
+ {
+ for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+ {
+ mAttributeBinding[i].erase(name);
+ }
+
+ mAttributeBinding[index].insert(name);
+ }
+}
+
+void Program::bindAttributeLocation(GLuint index, const char *name)
+{
+ mAttributeBindings.bindAttributeLocation(index, name);
+}
+
+// Links the HLSL code of the vertex and pixel shader by matching up their varyings,
+// compiling them into binaries, determining the attribute mappings, and collecting
+// a list of uniforms
+bool Program::link()
+{
+ unlink(false);
+
+ mInfoLog.reset();
+
+ mProgramBinary.set(new ProgramBinary());
+ mLinked = mProgramBinary->link(mInfoLog, mAttributeBindings, mFragmentShader, mVertexShader);
+
+ return mLinked;
+}
+
+int AttributeBindings::getAttributeBinding(const std::string &name) const
+{
+ for (int location = 0; location < MAX_VERTEX_ATTRIBS; location++)
+ {
+ if (mAttributeBinding[location].find(name) != mAttributeBinding[location].end())
+ {
+ return location;
+ }
+ }
+
+ return -1;
+}
+
+// Returns the program object to an unlinked state, before re-linking, or at destruction
+void Program::unlink(bool destroy)
+{
+ if (destroy) // Object being destructed
+ {
+ if (mFragmentShader)
+ {
+ mFragmentShader->release();
+ mFragmentShader = NULL;
+ }
+
+ if (mVertexShader)
+ {
+ mVertexShader->release();
+ mVertexShader = NULL;
+ }
+ }
+
+ mProgramBinary.set(NULL);
+ mLinked = false;
+}
+
+bool Program::isLinked()
+{
+ return mLinked;
+}
+
+ProgramBinary* Program::getProgramBinary()
+{
+ return mProgramBinary.get();
+}
+
+bool Program::setProgramBinary(const void *binary, GLsizei length)
+{
+ unlink(false);
+
+ mInfoLog.reset();
+
+ mProgramBinary.set(new ProgramBinary());
+ mLinked = mProgramBinary->load(mInfoLog, binary, length);
+ if (!mLinked)
+ {
+ mProgramBinary.set(NULL);
+ }
+
+ return mLinked;
+}
+
+void Program::release()
+{
+ mRefCount--;
+
+ if (mRefCount == 0 && mDeleteStatus)
+ {
+ mResourceManager->deleteProgram(mHandle);
+ }
+}
+
+void Program::addRef()
+{
+ mRefCount++;
+}
+
+unsigned int Program::getRefCount() const
+{
+ return mRefCount;
+}
+
+GLint Program::getProgramBinaryLength() const
+{
+ ProgramBinary *programBinary = mProgramBinary.get();
+ if (programBinary)
+ {
+ return programBinary->getLength();
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+int Program::getInfoLogLength() const
+{
+ return mInfoLog.getLength();
+}
+
+void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog)
+{
+ return mInfoLog.getLog(bufSize, length, infoLog);
+}
+
+void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders)
+{
+ int total = 0;
+
+ if (mVertexShader)
+ {
+ if (total < maxCount)
+ {
+ shaders[total] = mVertexShader->getHandle();
+ }
+
+ total++;
+ }
+
+ if (mFragmentShader)
+ {
+ if (total < maxCount)
+ {
+ shaders[total] = mFragmentShader->getHandle();
+ }
+
+ total++;
+ }
+
+ if (count)
+ {
+ *count = total;
+ }
+}
+
+void Program::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
+{
+ ProgramBinary *programBinary = getProgramBinary();
+ if (programBinary)
+ {
+ programBinary->getActiveAttribute(index, bufsize, length, size, type, name);
+ }
+ else
+ {
+ if (bufsize > 0)
+ {
+ name[0] = '\0';
+ }
+
+ if (length)
+ {
+ *length = 0;
+ }
+
+ *type = GL_NONE;
+ *size = 1;
+ }
+}
+
+GLint Program::getActiveAttributeCount()
+{
+ ProgramBinary *programBinary = getProgramBinary();
+ if (programBinary)
+ {
+ return programBinary->getActiveAttributeCount();
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+GLint Program::getActiveAttributeMaxLength()
+{
+ ProgramBinary *programBinary = getProgramBinary();
+ if (programBinary)
+ {
+ return programBinary->getActiveAttributeMaxLength();
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+void Program::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
+{
+ ProgramBinary *programBinary = getProgramBinary();
+ if (programBinary)
+ {
+ return programBinary->getActiveUniform(index, bufsize, length, size, type, name);
+ }
+ else
+ {
+ if (bufsize > 0)
+ {
+ name[0] = '\0';
+ }
+
+ if (length)
+ {
+ *length = 0;
+ }
+
+ *size = 0;
+ *type = GL_NONE;
+ }
+}
+
+GLint Program::getActiveUniformCount()
+{
+ ProgramBinary *programBinary = getProgramBinary();
+ if (programBinary)
+ {
+ return programBinary->getActiveUniformCount();
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+GLint Program::getActiveUniformMaxLength()
+{
+ ProgramBinary *programBinary = getProgramBinary();
+ if (programBinary)
+ {
+ return programBinary->getActiveUniformMaxLength();
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+void Program::flagForDeletion()
+{
+ mDeleteStatus = true;
+}
+
+bool Program::isFlaggedForDeletion() const
+{
+ return mDeleteStatus;
+}
+
+void Program::validate()
+{
+ mInfoLog.reset();
+
+ ProgramBinary *programBinary = getProgramBinary();
+ if (isLinked() && programBinary)
+ {
+ programBinary->validate(mInfoLog);
+ }
+ else
+ {
+ mInfoLog.append("Program has not been successfully linked.");
+ }
+}
+
+bool Program::isValidated() const
+{
+ ProgramBinary *programBinary = mProgramBinary.get();
+ if (programBinary)
+ {
+ return programBinary->isValidated();
+ }
+ else
+ {
+ return false;
+ }
+}
+
+}