OPENGL: Unify shader implementation for GL and GLES2.
This commit is contained in:
parent
fc52f73050
commit
8a3eecb73a
6 changed files with 59 additions and 238 deletions
|
@ -68,166 +68,39 @@ const char *const g_defaultFragmentShaderGLES2 =
|
|||
"}\n";
|
||||
#endif
|
||||
|
||||
#if !USE_FORCED_GLES2
|
||||
|
||||
ShaderARB::ShaderARB(const Common::String &vertex, const Common::String &fragment)
|
||||
: Shader(vertex, fragment), _program(0), _projectionLocation(-1), _textureLocation(-1) {
|
||||
Shader::Shader(const Common::String &vertex, const Common::String &fragment)
|
||||
: _vertex(vertex), _fragment(fragment), _program(0), _projectionLocation(-1), _textureLocation(-1) {
|
||||
}
|
||||
|
||||
ShaderARB::~ShaderARB() {
|
||||
Shader::~Shader() {
|
||||
// According to extension specification glDeleteObjectARB silently ignores
|
||||
// 0. However, with nVidia drivers this can cause GL_INVALID_VALUE, thus
|
||||
// we do not call it with 0 as parameter to avoid warnings.
|
||||
if (_program) {
|
||||
GL_CALL_SAFE(glDeleteObjectARB, (_program));
|
||||
GL_CALL_SAFE(glDeleteProgram, (_program));
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderARB::destroy() {
|
||||
void Shader::destroy() {
|
||||
// According to extension specification glDeleteObjectARB silently ignores
|
||||
// 0. However, with nVidia drivers this can cause GL_INVALID_VALUE, thus
|
||||
// we do not call it with 0 as parameter to avoid warnings.
|
||||
if (_program) {
|
||||
GL_CALL(glDeleteObjectARB(_program));
|
||||
GL_CALL(glDeleteProgram(_program));
|
||||
_program = 0;
|
||||
}
|
||||
_program = 0;
|
||||
}
|
||||
|
||||
bool ShaderARB::recreate() {
|
||||
bool Shader::recreate() {
|
||||
// Make sure any old programs are destroyed properly.
|
||||
destroy();
|
||||
|
||||
GLhandleARB vertexShader = compileShader(_vertex.c_str(), GL_VERTEX_SHADER_ARB);
|
||||
GLshader vertexShader = compileShader(_vertex.c_str(), GL_VERTEX_SHADER);
|
||||
if (!vertexShader) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GLhandleARB fragmentShader = compileShader(_fragment.c_str(), GL_FRAGMENT_SHADER_ARB);
|
||||
if (!fragmentShader) {
|
||||
GL_CALL(glDeleteObjectARB(vertexShader));
|
||||
return false;
|
||||
}
|
||||
|
||||
GL_ASSIGN(_program, glCreateProgramObjectARB());
|
||||
if (!_program) {
|
||||
GL_CALL(glDeleteObjectARB(vertexShader));
|
||||
GL_CALL(glDeleteObjectARB(fragmentShader));
|
||||
return false;
|
||||
}
|
||||
|
||||
GL_CALL(glAttachObjectARB(_program, vertexShader));
|
||||
GL_CALL(glAttachObjectARB(_program, fragmentShader));
|
||||
|
||||
GL_CALL(glBindAttribLocationARB(_program, kPositionAttribLocation, "position"));
|
||||
GL_CALL(glBindAttribLocationARB(_program, kTexCoordAttribLocation, "texCoordIn"));
|
||||
GL_CALL(glBindAttribLocationARB(_program, kColorAttribLocation, "blendColorIn"));
|
||||
|
||||
GL_CALL(glLinkProgramARB(_program));
|
||||
|
||||
GL_CALL(glDetachObjectARB(_program, fragmentShader));
|
||||
GL_CALL(glDeleteObjectARB(fragmentShader));
|
||||
|
||||
GL_CALL(glDetachObjectARB(_program, vertexShader));
|
||||
GL_CALL(glDeleteObjectARB(vertexShader));
|
||||
|
||||
GLint result;
|
||||
GL_CALL(glGetObjectParameterivARB(_program, GL_OBJECT_LINK_STATUS_ARB, &result));
|
||||
if (result == GL_FALSE) {
|
||||
GLint logSize;
|
||||
GL_CALL(glGetObjectParameterivARB(_program, GL_OBJECT_INFO_LOG_LENGTH_ARB, &logSize));
|
||||
|
||||
GLchar *log = new GLchar[logSize];
|
||||
GL_CALL(glGetInfoLogARB(_program, logSize, nullptr, log));
|
||||
warning("Could not link shader: \"%s\"", log);
|
||||
delete[] log;
|
||||
|
||||
destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
GL_ASSIGN(_projectionLocation, glGetUniformLocationARB(_program, "projection"));
|
||||
if (_projectionLocation == -1) {
|
||||
warning("Shader misses \"projection\" uniform.");
|
||||
destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
GL_ASSIGN(_textureLocation, glGetUniformLocationARB(_program, "texture"));
|
||||
if (_textureLocation == -1) {
|
||||
warning("Shader misses \"texture\" uniform.");
|
||||
destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ShaderARB::activate(const GLfloat *projectionMatrix) {
|
||||
// Activate program.
|
||||
GL_CALL(glUseProgramObjectARB(_program));
|
||||
|
||||
// Set projection matrix.
|
||||
GL_CALL(glUniformMatrix4fv(_projectionLocation, 1, GL_FALSE, projectionMatrix));
|
||||
|
||||
// We always use texture unit 0.
|
||||
GL_CALL(glUniform1i(_textureLocation, 0));
|
||||
}
|
||||
|
||||
GLhandleARB ShaderARB::compileShader(const char *source, GLenum shaderType) {
|
||||
GLuint handle;
|
||||
GL_ASSIGN(handle, glCreateShaderObjectARB(shaderType));
|
||||
if (!handle) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
GL_CALL(glShaderSourceARB(handle, 1, &source, nullptr));
|
||||
GL_CALL(glCompileShaderARB(handle));
|
||||
|
||||
GLint result;
|
||||
GL_CALL(glGetObjectParameterivARB(handle, GL_OBJECT_COMPILE_STATUS_ARB, &result));
|
||||
if (result == GL_FALSE) {
|
||||
GLint logSize;
|
||||
GL_CALL(glGetObjectParameterivARB(handle, GL_OBJECT_INFO_LOG_LENGTH_ARB, &logSize));
|
||||
|
||||
GLchar *log = new GLchar[logSize];
|
||||
GL_CALL(glGetInfoLogARB(handle, logSize, nullptr, log));
|
||||
warning("Could not compile shader \"%s\": \"%s\"", source, log);
|
||||
delete[] log;
|
||||
|
||||
GL_CALL(glDeleteObjectARB(handle));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
#endif // !USE_FORCED_GLES2
|
||||
|
||||
#if !USE_FORCED_GL
|
||||
|
||||
ShaderGLES2::ShaderGLES2(const Common::String &vertex, const Common::String &fragment)
|
||||
: Shader(vertex, fragment), _program(0), _projectionLocation(-1), _textureLocation(-1) {
|
||||
}
|
||||
|
||||
ShaderGLES2::~ShaderGLES2() {
|
||||
GL_CALL_SAFE(glDeleteProgram, (_program));
|
||||
}
|
||||
|
||||
void ShaderGLES2::destroy() {
|
||||
GL_CALL(glDeleteProgram(_program));
|
||||
_program = 0;
|
||||
}
|
||||
|
||||
bool ShaderGLES2::recreate() {
|
||||
// Make sure any old programs are destroyed properly.
|
||||
destroy();
|
||||
|
||||
GLuint vertexShader = compileShader(_vertex.c_str(), GL_VERTEX_SHADER);
|
||||
if (!vertexShader) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GLuint fragmentShader = compileShader(_fragment.c_str(), GL_FRAGMENT_SHADER);
|
||||
GLshader fragmentShader = compileShader(_fragment.c_str(), GL_FRAGMENT_SHADER);
|
||||
if (!fragmentShader) {
|
||||
GL_CALL(glDeleteShader(vertexShader));
|
||||
return false;
|
||||
|
@ -287,7 +160,7 @@ bool ShaderGLES2::recreate() {
|
|||
return true;
|
||||
}
|
||||
|
||||
void ShaderGLES2::activate(const GLfloat *projectionMatrix) {
|
||||
void Shader::activate(const GLfloat *projectionMatrix) {
|
||||
// Activate program.
|
||||
GL_CALL(glUseProgram(_program));
|
||||
|
||||
|
@ -298,8 +171,8 @@ void ShaderGLES2::activate(const GLfloat *projectionMatrix) {
|
|||
GL_CALL(glUniform1i(_textureLocation, 0));
|
||||
}
|
||||
|
||||
GLuint ShaderGLES2::compileShader(const char *source, GLenum shaderType) {
|
||||
GLuint handle;
|
||||
GLshader Shader::compileShader(const char *source, GLenum shaderType) {
|
||||
GLshader handle;
|
||||
GL_ASSIGN(handle, glCreateShader(shaderType));
|
||||
if (!handle) {
|
||||
return 0;
|
||||
|
@ -326,8 +199,6 @@ GLuint ShaderGLES2::compileShader(const char *source, GLenum shaderType) {
|
|||
return handle;
|
||||
}
|
||||
|
||||
#endif // !!USE_FORCED_GL
|
||||
|
||||
} // End of namespace OpenGL
|
||||
|
||||
#endif // !USE_FORCED_GLES
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue