1// Copyright 2011 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "cc/output/program_binding.h" 6 7#include "base/debug/trace_event.h" 8#include "cc/output/geometry_binding.h" 9#include "gpu/command_buffer/client/gles2_interface.h" 10 11using gpu::gles2::GLES2Interface; 12 13namespace cc { 14 15ProgramBindingBase::ProgramBindingBase() 16 : program_(0), 17 vertex_shader_id_(0), 18 fragment_shader_id_(0), 19 initialized_(false) {} 20 21ProgramBindingBase::~ProgramBindingBase() { 22 // If you hit these asserts, you initialized but forgot to call Cleanup(). 23 DCHECK(!program_); 24 DCHECK(!vertex_shader_id_); 25 DCHECK(!fragment_shader_id_); 26 DCHECK(!initialized_); 27} 28 29bool ProgramBindingBase::Init(GLES2Interface* context, 30 const std::string& vertex_shader, 31 const std::string& fragment_shader) { 32 TRACE_EVENT0("cc", "ProgramBindingBase::init"); 33 vertex_shader_id_ = LoadShader(context, GL_VERTEX_SHADER, vertex_shader); 34 if (!vertex_shader_id_) 35 return false; 36 37 fragment_shader_id_ = 38 LoadShader(context, GL_FRAGMENT_SHADER, fragment_shader); 39 if (!fragment_shader_id_) { 40 context->DeleteShader(vertex_shader_id_); 41 vertex_shader_id_ = 0; 42 return false; 43 } 44 45 program_ = 46 CreateShaderProgram(context, vertex_shader_id_, fragment_shader_id_); 47 return !!program_; 48} 49 50bool ProgramBindingBase::Link(GLES2Interface* context) { 51 context->LinkProgram(program_); 52 CleanupShaders(context); 53 if (!program_) 54 return false; 55#ifndef NDEBUG 56 int linked = 0; 57 context->GetProgramiv(program_, GL_LINK_STATUS, &linked); 58 if (!linked) 59 return false; 60#endif 61 return true; 62} 63 64void ProgramBindingBase::Cleanup(GLES2Interface* context) { 65 initialized_ = false; 66 if (!program_) 67 return; 68 69 DCHECK(context); 70 context->DeleteProgram(program_); 71 program_ = 0; 72 73 CleanupShaders(context); 74} 75 76unsigned ProgramBindingBase::LoadShader(GLES2Interface* context, 77 unsigned type, 78 const std::string& shader_source) { 79 unsigned shader = context->CreateShader(type); 80 if (!shader) 81 return 0u; 82 83 const char* shader_source_str[] = { shader_source.data() }; 84 int shader_length[] = { static_cast<int>(shader_source.length()) }; 85 context->ShaderSource( 86 shader, 1, 87 shader_source_str, 88 shader_length); 89 context->CompileShader(shader); 90#ifndef NDEBUG 91 int compiled = 0; 92 context->GetShaderiv(shader, GL_COMPILE_STATUS, &compiled); 93 if (!compiled) 94 return 0u; 95#endif 96 return shader; 97} 98 99unsigned ProgramBindingBase::CreateShaderProgram(GLES2Interface* context, 100 unsigned vertex_shader, 101 unsigned fragment_shader) { 102 unsigned program_object = context->CreateProgram(); 103 if (!program_object) 104 return 0; 105 106 context->AttachShader(program_object, vertex_shader); 107 context->AttachShader(program_object, fragment_shader); 108 109 // Bind the common attrib locations. 110 context->BindAttribLocation( 111 program_object, GeometryBinding::PositionAttribLocation(), "a_position"); 112 context->BindAttribLocation( 113 program_object, GeometryBinding::TexCoordAttribLocation(), "a_texCoord"); 114 context->BindAttribLocation(program_object, 115 GeometryBinding::TriangleIndexAttribLocation(), 116 "a_index"); 117 118 return program_object; 119} 120 121void ProgramBindingBase::CleanupShaders(GLES2Interface* context) { 122 if (vertex_shader_id_) { 123 context->DeleteShader(vertex_shader_id_); 124 vertex_shader_id_ = 0; 125 } 126 if (fragment_shader_id_) { 127 context->DeleteShader(fragment_shader_id_); 128 fragment_shader_id_ = 0; 129 } 130} 131 132} // namespace cc 133