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