This source file includes following definitions.
- initialized_
- Init
- Link
- Cleanup
- LoadShader
- CreateShaderProgram
- CleanupShaders
#include "cc/output/program_binding.h"
#include "base/debug/trace_event.h"
#include "cc/output/geometry_binding.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "third_party/khronos/GLES2/gl2.h"
using gpu::gles2::GLES2Interface;
namespace cc {
ProgramBindingBase::ProgramBindingBase()
: program_(0),
vertex_shader_id_(0),
fragment_shader_id_(0),
initialized_(false) {}
ProgramBindingBase::~ProgramBindingBase() {
DCHECK(!program_);
DCHECK(!vertex_shader_id_);
DCHECK(!fragment_shader_id_);
DCHECK(!initialized_);
}
bool ProgramBindingBase::Init(GLES2Interface* context,
const std::string& vertex_shader,
const std::string& fragment_shader) {
TRACE_EVENT0("cc", "ProgramBindingBase::init");
vertex_shader_id_ = LoadShader(context, GL_VERTEX_SHADER, vertex_shader);
if (!vertex_shader_id_)
return false;
fragment_shader_id_ =
LoadShader(context, GL_FRAGMENT_SHADER, fragment_shader);
if (!fragment_shader_id_) {
context->DeleteShader(vertex_shader_id_);
vertex_shader_id_ = 0;
return false;
}
program_ =
CreateShaderProgram(context, vertex_shader_id_, fragment_shader_id_);
return !!program_;
}
bool ProgramBindingBase::Link(GLES2Interface* context) {
context->LinkProgram(program_);
CleanupShaders(context);
if (!program_)
return false;
#ifndef NDEBUG
int linked = 0;
context->GetProgramiv(program_, GL_LINK_STATUS, &linked);
if (!linked)
return false;
#endif
return true;
}
void ProgramBindingBase::Cleanup(GLES2Interface* context) {
initialized_ = false;
if (!program_)
return;
DCHECK(context);
context->DeleteProgram(program_);
program_ = 0;
CleanupShaders(context);
}
unsigned ProgramBindingBase::LoadShader(GLES2Interface* context,
unsigned type,
const std::string& shader_source) {
unsigned shader = context->CreateShader(type);
if (!shader)
return 0u;
const char* shader_source_str[] = { shader_source.data() };
int shader_length[] = { static_cast<int>(shader_source.length()) };
context->ShaderSource(
shader, 1,
shader_source_str,
shader_length);
context->CompileShader(shader);
#ifndef NDEBUG
int compiled = 0;
context->GetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
if (!compiled)
return 0u;
#endif
return shader;
}
unsigned ProgramBindingBase::CreateShaderProgram(GLES2Interface* context,
unsigned vertex_shader,
unsigned fragment_shader) {
unsigned program_object = context->CreateProgram();
if (!program_object)
return 0;
context->AttachShader(program_object, vertex_shader);
context->AttachShader(program_object, fragment_shader);
context->BindAttribLocation(
program_object, GeometryBinding::PositionAttribLocation(), "a_position");
context->BindAttribLocation(
program_object, GeometryBinding::TexCoordAttribLocation(), "a_texCoord");
context->BindAttribLocation(program_object,
GeometryBinding::TriangleIndexAttribLocation(),
"a_index");
return program_object;
}
void ProgramBindingBase::CleanupShaders(GLES2Interface* context) {
if (vertex_shader_id_) {
context->DeleteShader(vertex_shader_id_);
vertex_shader_id_ = 0;
}
if (fragment_shader_id_) {
context->DeleteShader(fragment_shader_id_);
fragment_shader_id_ = 0;
}
}
}