blob: deb16b288ccb2edc3ea679054bb4a856fb430888 [file] [log] [blame]
//
// Copyright (c) 2002-2014 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.h: Defines the gl::Program class. Implements GL program objects
// and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28.
#ifndef LIBANGLE_PROGRAM_H_
#define LIBANGLE_PROGRAM_H_
#include "libANGLE/angletypes.h"
#include "libANGLE/Constants.h"
#include "libANGLE/Error.h"
#include "libANGLE/RefCountObject.h"
#include "common/angleutils.h"
#include <GLES2/gl2.h>
#include <GLSLANG/ShaderLang.h>
#include <vector>
#include <sstream>
#include <string>
#include <set>
namespace rx
{
class ImplFactory;
class ProgramImpl;
struct TranslatedAttribute;
}
namespace gl
{
struct Caps;
struct Data;
class ResourceManager;
class Shader;
class InfoLog;
class AttributeBindings;
class Buffer;
class Framebuffer;
struct UniformBlock;
struct LinkedUniform;
extern const char * const g_fakepath;
class AttributeBindings
{
public:
AttributeBindings();
~AttributeBindings();
void bindAttributeLocation(GLuint index, const char *name);
int getAttributeBinding(const std::string &name) const;
private:
std::set<std::string> mAttributeBinding[MAX_VERTEX_ATTRIBS];
};
class InfoLog : angle::NonCopyable
{
public:
InfoLog();
~InfoLog();
size_t getLength() const;
void getLog(GLsizei bufSize, GLsizei *length, char *infoLog);
void appendSanitized(const char *message);
void reset();
// This helper class ensures we append a newline after writing a line.
class StreamHelper : angle::NonCopyable
{
public:
StreamHelper(StreamHelper &&rhs)
: mStream(rhs.mStream)
{
rhs.mStream = nullptr;
}
StreamHelper &operator=(StreamHelper &&rhs)
{
std::swap(mStream, rhs.mStream);
return *this;
}
~StreamHelper()
{
// Write newline when destroyed on the stack
if (mStream)
{
(*mStream) << std::endl;
}
}
template <typename T>
StreamHelper &operator<<(const T &value)
{
(*mStream) << value;
return *this;
}
private:
friend class InfoLog;
StreamHelper(std::stringstream *stream)
: mStream(stream)
{
ASSERT(stream);
}
std::stringstream *mStream;
};
template <typename T>
StreamHelper operator<<(const T &value)
{
StreamHelper helper(&mStream);
helper << value;
return helper;
}
std::string str() const { return mStream.str(); }
private:
std::stringstream mStream;
};
// Struct used for correlating uniforms/elements of uniform arrays to handles
struct VariableLocation
{
VariableLocation();
VariableLocation(const std::string &name, unsigned int element, unsigned int index);
std::string name;
unsigned int element;
unsigned int index;
};
struct LinkedVarying
{
LinkedVarying();
LinkedVarying(const std::string &name, GLenum type, GLsizei size, const std::string &semanticName,
unsigned int semanticIndex, unsigned int semanticIndexCount);
// Original GL name
std::string name;
GLenum type;
GLsizei size;
// DirectX semantic information
std::string semanticName;
unsigned int semanticIndex;
unsigned int semanticIndexCount;
};
class Program : angle::NonCopyable
{
public:
class Data final : angle::NonCopyable
{
public:
Data();
~Data();
const Shader *getAttachedVertexShader() const { return mAttachedVertexShader; }
const Shader *getAttachedFragmentShader() const { return mAttachedFragmentShader; }
const std::vector<std::string> &getTransformFeedbackVaryingNames() const
{
return mTransformFeedbackVaryingNames;
}
GLint getTransformFeedbackBufferMode() const { return mTransformFeedbackBufferMode; }
GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const
{
ASSERT(uniformBlockIndex < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS);
return mUniformBlockBindings[uniformBlockIndex];
}
private:
friend class Program;
Shader *mAttachedFragmentShader;
Shader *mAttachedVertexShader;
std::vector<std::string> mTransformFeedbackVaryingNames;
std::vector<sh::Varying> mTransformFeedbackVaryingVars;
GLenum mTransformFeedbackBufferMode;
GLuint mUniformBlockBindings[IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS];
// TODO(jmadill): move more state into Data.
};
Program(rx::ImplFactory *factory, ResourceManager *manager, GLuint handle);
~Program();
GLuint id() const { return mHandle; }
rx::ProgramImpl *getImplementation() { return mProgram; }
const rx::ProgramImpl *getImplementation() const { return mProgram; }
bool attachShader(Shader *shader);
bool detachShader(Shader *shader);
int getAttachedShadersCount() const;
void bindAttributeLocation(GLuint index, const char *name);
Error link(const gl::Data &data);
bool isLinked();
Error loadBinary(GLenum binaryFormat, const void *binary, GLsizei length);
Error saveBinary(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length) const;
GLint getBinaryLength() const;
int getInfoLogLength() const;
void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog);
void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders);
GLuint getAttributeLocation(const std::string &name);
int getSemanticIndex(int attributeIndex) const;
const int *getSemanticIndexes() const;
void getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
GLint getActiveAttributeCount();
GLint getActiveAttributeMaxLength();
const std::vector<sh::Attribute> &getLinkedAttributes() const { return mLinkedAttributes; }
GLint getFragDataLocation(const std::string &name) const;
void getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
GLint getActiveUniformCount();
GLint getActiveUniformMaxLength();
GLint getActiveUniformi(GLuint index, GLenum pname) const;
bool isValidUniformLocation(GLint location) const;
LinkedUniform *getUniformByLocation(GLint location) const;
LinkedUniform *getUniformByName(const std::string &name) const;
GLint getUniformLocation(const std::string &name);
GLuint getUniformIndex(const std::string &name);
void setUniform1fv(GLint location, GLsizei count, const GLfloat *v);
void setUniform2fv(GLint location, GLsizei count, const GLfloat *v);
void setUniform3fv(GLint location, GLsizei count, const GLfloat *v);
void setUniform4fv(GLint location, GLsizei count, const GLfloat *v);
void setUniform1iv(GLint location, GLsizei count, const GLint *v);
void setUniform2iv(GLint location, GLsizei count, const GLint *v);
void setUniform3iv(GLint location, GLsizei count, const GLint *v);
void setUniform4iv(GLint location, GLsizei count, const GLint *v);
void setUniform1uiv(GLint location, GLsizei count, const GLuint *v);
void setUniform2uiv(GLint location, GLsizei count, const GLuint *v);
void setUniform3uiv(GLint location, GLsizei count, const GLuint *v);
void setUniform4uiv(GLint location, GLsizei count, const GLuint *v);
void setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
void setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
void setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
void setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
void setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
void setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
void setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
void setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
void getUniformfv(GLint location, GLfloat *params);
void getUniformiv(GLint location, GLint *params);
void getUniformuiv(GLint location, GLuint *params);
Error applyUniforms();
void getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const;
void getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GLint *params) const;
GLuint getActiveUniformBlockCount();
GLint getActiveUniformBlockMaxLength();
GLuint getUniformBlockIndex(const std::string &name);
void bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding);
GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const;
const UniformBlock *getUniformBlockByIndex(GLuint index) const;
void setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode);
void getTransformFeedbackVarying(GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) const;
GLsizei getTransformFeedbackVaryingCount() const;
GLsizei getTransformFeedbackVaryingMaxLength() const;
GLenum getTransformFeedbackBufferMode() const;
static bool linkValidateUniforms(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform);
static bool linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform);
void addRef();
void release();
unsigned int getRefCount() const;
void flagForDeletion();
bool isFlaggedForDeletion() const;
void validate(const Caps &caps);
bool validateSamplers(InfoLog *infoLog, const Caps &caps);
bool isValidated() const;
private:
void unlink(bool destroy = false);
void resetUniformBlockBindings();
bool linkAttributes(const gl::Data &data,
InfoLog &infoLog,
const AttributeBindings &attributeBindings,
const Shader *vertexShader);
bool linkUniformBlocks(InfoLog &infoLog, const Caps &caps);
static bool linkVaryings(InfoLog &infoLog,
const Shader *vertexShader,
const Shader *fragmentShader);
bool linkUniforms(gl::InfoLog &infoLog, const gl::Caps &caps) const;
bool areMatchingInterfaceBlocks(gl::InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock,
const sh::InterfaceBlock &fragmentInterfaceBlock);
static bool linkValidateVariablesBase(InfoLog &infoLog,
const std::string &variableName,
const sh::ShaderVariable &vertexVariable,
const sh::ShaderVariable &fragmentVariable,
bool validatePrecision);
static bool linkValidateVaryings(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying);
bool linkValidateTransformFeedback(InfoLog &infoLog,
const std::vector<const sh::Varying *> &linkedVaryings,
const Caps &caps) const;
void gatherTransformFeedbackVaryings(const std::vector<const sh::Varying *> &varyings);
bool assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex, const Caps &caps);
void defineOutputVariables(Shader *fragmentShader);
std::vector<const sh::Varying *> getMergedVaryings() const;
Data mData;
rx::ProgramImpl *mProgram;
std::vector<sh::Attribute> mLinkedAttributes;
std::map<int, VariableLocation> mOutputVariables;
bool mValidated;
AttributeBindings mAttributeBindings;
bool mLinked;
bool mDeleteStatus; // Flag to indicate that the program can be deleted when no longer in use
unsigned int mRefCount;
ResourceManager *mResourceManager;
const GLuint mHandle;
InfoLog mInfoLog;
};
}
#endif // LIBANGLE_PROGRAM_H_