12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2011 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/output/program_binding.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/debug/trace_event.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/output/geometry_binding.h" 9a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "gpu/command_buffer/client/gles2_interface.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 11a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)using gpu::gles2::GLES2Interface; 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace cc { 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ProgramBindingBase::ProgramBindingBase() 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : program_(0), 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) vertex_shader_id_(0), 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) fragment_shader_id_(0), 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) initialized_(false) {} 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ProgramBindingBase::~ProgramBindingBase() { 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If you hit these asserts, you initialized but forgot to call Cleanup(). 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!program_); 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!vertex_shader_id_); 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!fragment_shader_id_); 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!initialized_); 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 29a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool ProgramBindingBase::Init(GLES2Interface* context, 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& vertex_shader, 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& fragment_shader) { 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TRACE_EVENT0("cc", "ProgramBindingBase::init"); 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) vertex_shader_id_ = LoadShader(context, GL_VERTEX_SHADER, vertex_shader); 34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!vertex_shader_id_) 35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) fragment_shader_id_ = 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LoadShader(context, GL_FRAGMENT_SHADER, fragment_shader); 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!fragment_shader_id_) { 40a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) context->DeleteShader(vertex_shader_id_); 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) vertex_shader_id_ = 0; 42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) program_ = 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateShaderProgram(context, vertex_shader_id_, fragment_shader_id_); 47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return !!program_; 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 50a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool ProgramBindingBase::Link(GLES2Interface* context) { 51a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) context->LinkProgram(program_); 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CleanupShaders(context); 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!program_) 54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifndef NDEBUG 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int linked = 0; 57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) context->GetProgramiv(program_, GL_LINK_STATUS, &linked); 58a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!linked) 59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return true; 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 64a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ProgramBindingBase::Cleanup(GLES2Interface* context) { 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) initialized_ = false; 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!program_) 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(context); 70a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) context->DeleteProgram(program_); 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) program_ = 0; 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CleanupShaders(context); 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 76a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)unsigned ProgramBindingBase::LoadShader(GLES2Interface* context, 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unsigned type, 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& shader_source) { 79a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) unsigned shader = context->CreateShader(type); 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!shader) 81a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return 0u; 82a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 83a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const char* shader_source_str[] = { shader_source.data() }; 84a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int shader_length[] = { static_cast<int>(shader_source.length()) }; 85a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) context->ShaderSource( 86a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) shader, 1, 87a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) shader_source_str, 88a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) shader_length); 89a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) context->CompileShader(shader); 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifndef NDEBUG 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int compiled = 0; 92a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) context->GetShaderiv(shader, GL_COMPILE_STATUS, &compiled); 93a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!compiled) 94a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return 0u; 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return shader; 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 99a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)unsigned ProgramBindingBase::CreateShaderProgram(GLES2Interface* context, 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unsigned vertex_shader, 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unsigned fragment_shader) { 102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) unsigned program_object = context->CreateProgram(); 103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!program_object) 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 0; 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 106a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) context->AttachShader(program_object, vertex_shader); 107a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) context->AttachShader(program_object, fragment_shader); 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Bind the common attrib locations. 110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) context->BindAttribLocation( 111a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) program_object, GeometryBinding::PositionAttribLocation(), "a_position"); 112a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) context->BindAttribLocation( 113a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) program_object, GeometryBinding::TexCoordAttribLocation(), "a_texCoord"); 114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) context->BindAttribLocation(program_object, 115a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) GeometryBinding::TriangleIndexAttribLocation(), 116a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "a_index"); 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return program_object; 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 121a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ProgramBindingBase::CleanupShaders(GLES2Interface* context) { 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (vertex_shader_id_) { 123a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) context->DeleteShader(vertex_shader_id_); 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) vertex_shader_id_ = 0; 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (fragment_shader_id_) { 127a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) context->DeleteShader(fragment_shader_id_); 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) fragment_shader_id_ = 0; 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace cc 133