Home | History | Annotate | Download | only in output
      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 
     11 using gpu::gles2::GLES2Interface;
     12 
     13 namespace cc {
     14 
     15 ProgramBindingBase::ProgramBindingBase()
     16     : program_(0),
     17       vertex_shader_id_(0),
     18       fragment_shader_id_(0),
     19       initialized_(false) {}
     20 
     21 ProgramBindingBase::~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 
     29 bool 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 
     50 bool 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 
     64 void 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 
     76 unsigned 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 
     99 unsigned 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 
    121 void 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