blob: aa4c27fd4a463f44a218d18ef07c5553b17c7b0f [file] [log] [blame]
// Copyright 2017 The Cobalt 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.
#include "cobalt/renderer/rasterizer/egl/shader_program.h"
#include <GLES2/gl2.h>
#include "base/logging.h"
#include "cobalt/renderer/backend/egl/utils.h"
namespace cobalt {
namespace renderer {
namespace rasterizer {
namespace egl {
namespace {
void CompileShader(GLuint handle, const GLchar* source) {
GLint source_length = strlen(source);
GL_CALL(glShaderSource(handle, 1, &source, &source_length));
GL_CALL(glCompileShader(handle));
GLint compiled = GL_FALSE;
GL_CALL(glGetShaderiv(handle, GL_COMPILE_STATUS, &compiled));
if (compiled != GL_TRUE) {
GLchar log[2048] = {0};
glGetShaderInfoLog(handle, arraysize(log) - 1, NULL, log);
DLOG(ERROR) << "shader compile error:\n" << log;
DLOG(ERROR) << "shader source:\n" << source;
}
DCHECK(compiled == GL_TRUE);
}
} // namespace
ShaderProgramBase::ShaderProgramBase() : handle_(0) {}
ShaderProgramBase::~ShaderProgramBase() { DCHECK_EQ(handle_, 0); }
void ShaderProgramBase::Create(ShaderBase* vertex_shader,
ShaderBase* fragment_shader) {
handle_ = glCreateProgram();
GLuint vertex_shader_handle = glCreateShader(GL_VERTEX_SHADER);
CompileShader(vertex_shader_handle, vertex_shader->GetSource());
GL_CALL(glAttachShader(handle_, vertex_shader_handle));
GLuint fragment_shader_handle = glCreateShader(GL_FRAGMENT_SHADER);
CompileShader(fragment_shader_handle, fragment_shader->GetSource());
GL_CALL(glAttachShader(handle_, fragment_shader_handle));
vertex_shader->InitializePreLink(handle_);
fragment_shader->InitializePreLink(handle_);
GL_CALL(glLinkProgram(handle_));
GLint linked = GL_FALSE;
GL_CALL(glGetProgramiv(handle_, GL_LINK_STATUS, &linked));
if (linked != GL_TRUE) {
GLchar log[2048] = {0};
glGetProgramInfoLog(handle_, arraysize(log) - 1, NULL, log);
DLOG(ERROR) << "shader link error:\n" << log;
DLOG(ERROR) << "vertex source:\n" << vertex_shader->GetSource();
DLOG(ERROR) << "fragment source:\n" << fragment_shader->GetSource();
}
DCHECK(linked == GL_TRUE);
vertex_shader->InitializePostLink(handle_);
fragment_shader->InitializePostLink(handle_);
GL_CALL(glUseProgram(handle_));
vertex_shader->InitializePostUse();
fragment_shader->InitializePostUse();
GL_CALL(glDeleteShader(vertex_shader_handle));
GL_CALL(glDeleteShader(fragment_shader_handle));
}
void ShaderProgramBase::Destroy(ShaderBase* vertex_shader,
ShaderBase* fragment_shader) {
DCHECK_NE(handle_, 0);
GL_CALL(glDeleteProgram(handle_));
handle_ = 0;
}
} // namespace egl
} // namespace rasterizer
} // namespace renderer
} // namespace cobalt