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 #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