/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "base/logging.h"

#include "core/geometry.h"
#include "core/gl_buffer_interface.h"
#include "core/gl_env.h"
#include "core/gl_frame.h"
#include "core/shader_program.h"
#include "core/vertex_frame.h"

#include <string>
#include <sstream>
#include <vector>

namespace android {
namespace filterfw {

static const char* s_default_vertex_shader_source_ =
  "attribute vec4 a_position;\n"
  "attribute vec2 a_texcoord;\n"
  "varying vec2 v_texcoord;\n"
  "void main() {\n"
  "  gl_Position = a_position;\n"
  "  v_texcoord = a_texcoord;\n"
  "}\n";

// Helper Functions ////////////////////////////////////////////////////////////
// Maps coordinates x,y in the unit rectangle over to the quadrangle specified
// by the four points in b. The result coordinates are written to xt and yt.
static void GetTileCoords(const float* b, float x, float y, float* xt, float* yt) {
  const float w0 =  (1.0f - x) * (1.0f - y);
  const float w1 =  x * (1.0f - y);
  const float w2 =  (1.0f - x) * y;
  const float w3 =  x * y;

  *xt = w0 * b[0] + w1 * b[2] + w2 * b[4] + w3 * b[6];
  *yt = w0 * b[1] + w1 * b[3] + w2 * b[5] + w3 * b[7];
}

// VertexAttrib implementation /////////////////////////////////////////////////
ShaderProgram::VertexAttrib::VertexAttrib()
  : is_const(true),
    index(-1),
    normalized(false),
    stride(0),
    components(0),
    offset(0),
    type(GL_FLOAT),
    vbo(0),
    values(NULL),
    owned_data(NULL) {
}

// ShaderProgram implementation ////////////////////////////////////////////////
ShaderProgram::ShaderProgram(GLEnv* gl_env, const std::string& fragment_shader)
  : fragment_shader_source_(fragment_shader),
    vertex_shader_source_(s_default_vertex_shader_source_),
    fragment_shader_(0),
    vertex_shader_(0),
    program_(0),
    gl_env_(gl_env),
    base_texture_unit_(GL_TEXTURE0),
    source_coords_(NULL),
    target_coords_(NULL),
    manage_coordinates_(false),
    tile_x_count_(1),
    tile_y_count_(1),
    vertex_count_(4),
    draw_mode_(GL_TRIANGLE_STRIP),
    clears_(false),
    blending_(false),
    sfactor_(GL_SRC_ALPHA),
    dfactor_(GL_ONE_MINUS_SRC_ALPHA) {
  SetDefaultCoords();
}

ShaderProgram::ShaderProgram(GLEnv* gl_env,
                             const std::string& vertex_shader,
                             const std::string& fragment_shader)
  : fragment_shader_source_(fragment_shader),
    vertex_shader_source_(vertex_shader),
    fragment_shader_(0),
    vertex_shader_(0),
    program_(0),
    gl_env_(gl_env),
    base_texture_unit_(GL_TEXTURE0),
    source_coords_(NULL),
    target_coords_(NULL),
    manage_coordinates_(false),
    tile_x_count_(1),
    tile_y_count_(1),
    vertex_count_(4),
    draw_mode_(GL_TRIANGLE_STRIP),
    clears_(false),
    blending_(false),
    sfactor_(GL_SRC_ALPHA),
    dfactor_(GL_ONE_MINUS_SRC_ALPHA) {
  SetDefaultCoords();
}

ShaderProgram::~ShaderProgram() {
  // Delete our vertex data
  delete[] source_coords_;
  delete[] target_coords_;

  // Delete any owned attribute data
  VertexAttribMap::const_iterator iter;
  for (iter = attrib_values_.begin(); iter != attrib_values_.end(); ++iter) {
    const VertexAttrib& attrib = iter->second;
    if (attrib.owned_data)
      delete[] attrib.owned_data;
  }
}

void ShaderProgram::SetDefaultCoords() {
  if (!source_coords_)
    source_coords_ = new float[8];
  if (!target_coords_)
    target_coords_ = new float[8];

  source_coords_[0] = 0.0f;
  source_coords_[1] = 0.0f;
  source_coords_[2] = 1.0f;
  source_coords_[3] = 0.0f;
  source_coords_[4] = 0.0f;
  source_coords_[5] = 1.0f;
  source_coords_[6] = 1.0f;
  source_coords_[7] = 1.0f;

  target_coords_[0] = -1.0f;
  target_coords_[1] = -1.0f;
  target_coords_[2] =  1.0f;
  target_coords_[3] = -1.0f;
  target_coords_[4] = -1.0f;
  target_coords_[5] =  1.0f;
  target_coords_[6] =  1.0f;
  target_coords_[7] =  1.0f;

}

ShaderProgram* ShaderProgram::CreateIdentity(GLEnv* gl_env) {
  const char* s_id_fragment_shader =
    "precision mediump float;\n"
    "uniform sampler2D tex_sampler_0;\n"
    "varying vec2 v_texcoord;\n"
    "void main() {\n"
    "  gl_FragColor = texture2D(tex_sampler_0, v_texcoord);\n"
    "}\n";
  ShaderProgram* result = new ShaderProgram(gl_env, s_id_fragment_shader);
  result->CompileAndLink();
  return result;
}

bool ShaderProgram::IsVarValid(ProgramVar var) {
  return var != -1;
}

bool ShaderProgram::Process(const std::vector<const GLTextureHandle*>& input,
                            GLFrameBufferHandle* output) {
  // TODO: This can be optimized: If the input and output are the same, as in
  // the last iteration (typical of a multi-pass filter), a lot of this setup
  // may be skipped.

  // Abort if program did not successfully compile and link
  if (!IsExecutable()) {
    ALOGE("ShaderProgram: unexecutable program!");
    return false;
  }

  // Focus the FBO of the output
  if (!output->FocusFrameBuffer()) {
    ALOGE("Unable to focus frame buffer");
    return false;
  }

  // Get all required textures
  std::vector<GLuint> textures;
  std::vector<GLenum> targets;
  for (unsigned i = 0; i < input.size(); ++i) {
    // Get the current input frame and make sure it is a GL frame
    if (input[i]) {
      // Get the texture bound to that frame
      const GLuint tex_id = input[i]->GetTextureId();
      const GLenum target = input[i]->GetTextureTarget();
      if (tex_id == 0) {
        ALOGE("ShaderProgram: invalid texture id at input: %d!", i);
        return false;
      }
      textures.push_back(tex_id);
      targets.push_back(target);
    }
  }

  // And render!
  if (!RenderFrame(textures, targets)) {
    ALOGE("Unable to render frame");
    return false;
  }
  return true;
}

bool ShaderProgram::Process(const std::vector<const GLFrame*>& input, GLFrame* output) {
  std::vector<const GLTextureHandle*> textures(input.size());
  std::copy(input.begin(), input.end(), textures.begin());
  return Process(textures, output);
}

void ShaderProgram::SetSourceRect(float x, float y, float width, float height) {
  Quad quad(Point(x,          y),
            Point(x + width,  y),
            Point(x,          y + height),
            Point(x + width,  y + height));
  SetSourceRegion(quad);
}

void ShaderProgram::SetSourceRegion(const Quad& quad) {
  int index = 0;
  for (int i = 0; i < 4; ++i, index += 2) {
    source_coords_[index]   = quad.point(i).x();
    source_coords_[index+1] = quad.point(i).y();
  }
}

void ShaderProgram::SetTargetRect(float x, float y, float width, float height) {
  Quad quad(Point(x,          y),
            Point(x + width,  y),
            Point(x,          y + height),
            Point(x + width,  y + height));
  SetTargetRegion(quad);
}

void ShaderProgram::SetTargetRegion(const Quad& quad) {
  int index = 0;
  for (int i = 0; i < 4; ++i, index += 2) {
    target_coords_[index]   = (quad.point(i).x() * 2.0) - 1.0;
    target_coords_[index+1] = (quad.point(i).y() * 2.0) - 1.0;
  }
}

bool ShaderProgram::CompileAndLink() {
  // Make sure we haven't compiled and linked already
  if (vertex_shader_ != 0 || fragment_shader_ != 0 || program_ != 0) {
    ALOGE("Attempting to re-compile shaders!");
    return false;
  }

  // Compile vertex shader
  vertex_shader_ = CompileShader(GL_VERTEX_SHADER,
                                 vertex_shader_source_.c_str());
  if (!vertex_shader_) {
    ALOGE("Shader compilation failed!");
    return false;
  }

  // Compile fragment shader
  fragment_shader_ = CompileShader(GL_FRAGMENT_SHADER,
                                   fragment_shader_source_.c_str());
  if (!fragment_shader_)
    return false;

  // Link
  GLuint shaders[2] = { vertex_shader_, fragment_shader_ };
  program_ = LinkProgram(shaders, 2);

  // Scan for all uniforms in the program
  ScanUniforms();

  // Check if we manage all coordinates
  if (program_ != 0) {
    ProgramVar tex_coord_attr = glGetAttribLocation(program_, TexCoordAttributeName().c_str());
    ProgramVar pos_coord_attr = glGetAttribLocation(program_, PositionAttributeName().c_str());
    manage_coordinates_ = (tex_coord_attr >= 0 && pos_coord_attr >= 0);
  } else {
    ALOGE("Could not link shader program!");
    return false;
  }

  return true;
}

GLuint ShaderProgram::CompileShader(GLenum shader_type, const char* source) {
  LOG_FRAME("Compiling source:\n[%s]", source);

  // Create shader
  GLuint shader = glCreateShader(shader_type);
  if (shader) {
    // Compile source
    glShaderSource(shader, 1, &source, NULL);
    glCompileShader(shader);

    // Check for compilation errors
    GLint compiled = 0;
    glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
    if (!compiled) {
      // Log the compilation error messages
      ALOGE("Problem compiling shader! Source:");
      ALOGE("%s", source);
      std::string src(source);
      size_t cur_pos = 0;
      size_t next_pos = 0;
      size_t line_number = 1;
      while ( (next_pos = src.find_first_of('\n', cur_pos)) != std::string::npos) {
        ALOGE("%03zd : %s", line_number, src.substr(cur_pos, next_pos-cur_pos).c_str());
        cur_pos = next_pos + 1;
        line_number++;
      }
      ALOGE("%03zu : %s", line_number, src.substr(cur_pos, next_pos-cur_pos).c_str());

      GLint log_length = 0;
      glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length);
      if (log_length) {
        char* error_log = new char[log_length];
        if (error_log) {
          glGetShaderInfoLog(shader, log_length, NULL, error_log);
          ALOGE("Shader compilation error %d:\n%s\n", shader_type, error_log);
          delete[] error_log;
        }
      }
      glDeleteShader(shader);
      shader = 0;
    }
  }
  return shader;
}

GLuint ShaderProgram::LinkProgram(GLuint* shaders, GLuint count) {
  GLuint program = glCreateProgram();
  if (program) {
    // Attach all compiled shaders
    for (GLuint i = 0; i < count; ++i) {
      glAttachShader(program, shaders[i]);
      if (GLEnv::CheckGLError("glAttachShader")) return 0;
    }

    // Link
    glLinkProgram(program);

    // Check for linking errors
    GLint linked = 0;
    glGetProgramiv(program, GL_LINK_STATUS, &linked);
    if (linked != GL_TRUE) {
      // Log the linker error messages
      GLint log_length = 0;
      glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length);
      if (log_length) {
        char* error_log = new char[log_length];
        if (error_log) {
          glGetProgramInfoLog(program, log_length, NULL, error_log);
          ALOGE("Program Linker Error:\n%s\n", error_log);
          delete[] error_log;
        }
      }
      glDeleteProgram(program);
      program = 0;
    }
  }
  return program;
}

void ShaderProgram::ScanUniforms() {
  int uniform_count;
  int buffer_size;
  GLenum type;
  GLint capacity;
  glGetProgramiv(program_, GL_ACTIVE_UNIFORMS, &uniform_count);
  glGetProgramiv(program_, GL_ACTIVE_UNIFORM_MAX_LENGTH, &buffer_size);
  std::vector<GLchar> name(buffer_size);
  for (int i = 0; i < uniform_count; ++i) {
    glGetActiveUniform(program_, i, buffer_size, NULL, &capacity, &type, &name[0]);
    ProgramVar uniform_id = glGetUniformLocation(program_, &name[0]);
    uniform_indices_[uniform_id] = i;
  }
}

bool ShaderProgram::PushCoords(ProgramVar attr, float* coords) {
  // If the shader does not define these, we simply ignore the coordinates, and assume that the
  // user is managing coordinates.
  if (attr >= 0) {
    const uint8_t* data = reinterpret_cast<const uint8_t*>(coords);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glVertexAttribPointer(attr, 2, GL_FLOAT, false, 2 * sizeof(float), data);
    glEnableVertexAttribArray(attr);
    return !GLEnv::CheckGLError("Pushing vertex coordinates");
  }
  return true;
}

bool ShaderProgram::PushSourceCoords(float* coords) {
  ProgramVar tex_coord_attr = glGetAttribLocation(program_, TexCoordAttributeName().c_str());
  return PushCoords(tex_coord_attr, coords);
}

bool ShaderProgram::PushTargetCoords(float* coords) {
  ProgramVar pos_coord_attr = glGetAttribLocation(program_, PositionAttributeName().c_str());
  return PushCoords(pos_coord_attr, coords);
}

std::string ShaderProgram::InputTextureUniformName(int index) {
  std::stringstream tex_name;
  tex_name << "tex_sampler_" << index;
  return tex_name.str();
}

bool ShaderProgram::BindInputTextures(const std::vector<GLuint>& textures,
                                      const std::vector<GLenum>& targets) {
  for (unsigned i = 0; i < textures.size(); ++i) {
    // Activate texture unit i
    glActiveTexture(BaseTextureUnit() + i);
    if (GLEnv::CheckGLError("Activating Texture Unit"))
      return false;

    // Bind our texture
    glBindTexture(targets[i], textures[i]);
    LOG_FRAME("Binding texture %d", textures[i]);
    if (GLEnv::CheckGLError("Binding Texture"))
      return false;

    // Set the texture handle in the shader to unit i
    ProgramVar tex_var = GetUniform(InputTextureUniformName(i));
    if (tex_var >= 0) {
      glUniform1i(tex_var, i);
    } else {
      ALOGE("ShaderProgram: Shader does not seem to support %zd number of "
           "inputs! Missing uniform 'tex_sampler_%d'!", textures.size(), i);
      return false;
    }

    if (GLEnv::CheckGLError("Texture Variable Binding"))
      return false;
  }

  return true;
}

bool ShaderProgram::UseProgram() {
  if (GLEnv::GetCurrentProgram() != program_) {
    LOG_FRAME("Using program %d", program_);
    glUseProgram(program_);
    return !GLEnv::CheckGLError("Use Program");
  }
  return true;
}

bool ShaderProgram::RenderFrame(const std::vector<GLuint>& textures,
                                const std::vector<GLenum>& targets) {
  // Make sure we have enough texture units to accomodate the textures
  if (textures.size() > static_cast<unsigned>(MaxTextureUnits())) {
    ALOGE("ShaderProgram: Number of input textures is unsupported on this "
         "platform!");
    return false;
  }

  // Prepare to render
  if (!BeginDraw()) {
    ALOGE("ShaderProgram: couldn't initialize gl for drawing!");
    return false;
  }

  // Bind input textures
  if (!BindInputTextures(textures, targets)) {
    ALOGE("BindInputTextures failed");
    return false;
  }

  if (LOG_EVERY_FRAME) {
    int fbo, program, buffer;
    glGetIntegerv(GL_FRAMEBUFFER_BINDING, &fbo);
    glGetIntegerv(GL_CURRENT_PROGRAM, &program);
    glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &buffer);
    ALOGV("RenderFrame: fbo %d prog %d buff %d", fbo, program, buffer);
  }

  // Render!
  const bool requestTile = (tile_x_count_ != 1 || tile_y_count_ != 1);
  const bool success = (!requestTile || !manage_coordinates_  || vertex_count_ != 4)
      ? Draw()
      : DrawTiled();

  // Pop vertex attributes
  PopAttributes();

  return success && !GLEnv::CheckGLError("Rendering");
}

bool ShaderProgram::Draw() {
  if (PushSourceCoords(source_coords_) && PushTargetCoords(target_coords_)) {
    glDrawArrays(draw_mode_, 0, vertex_count_);
    return true;
  }
  return false;
}

bool ShaderProgram::DrawTiled() {
  // Target coordinate step size
  float s[8];
  float t[8];

  // Step sizes
  const float xs = 1.0f / static_cast<float>(tile_x_count_);
  const float ys = 1.0f / static_cast<float>(tile_y_count_);

  // Tile drawing loop
  for (int i = 0; i < tile_x_count_; ++i) {
    for (int j = 0; j < tile_y_count_; ++j) {
      // Current coordinates in unit rectangle
      const float x = i / static_cast<float>(tile_x_count_);
      const float y = j / static_cast<float>(tile_y_count_);

      // Source coords
      GetTileCoords(source_coords_, x, y, &s[0], &s[1]);
      GetTileCoords(source_coords_, x + xs, y, &s[2], &s[3]);
      GetTileCoords(source_coords_, x, y + ys, &s[4], &s[5]);
      GetTileCoords(source_coords_, x + xs, y + ys, &s[6], &s[7]);

      // Target coords
      GetTileCoords(target_coords_, x, y, &t[0], &t[1]);
      GetTileCoords(target_coords_, x + xs, y, &t[2], &t[3]);
      GetTileCoords(target_coords_, x, y + ys, &t[4], &t[5]);
      GetTileCoords(target_coords_, x + xs, y + ys, &t[6], &t[7]);

      if (PushSourceCoords(s) && PushTargetCoords(t)) {
        glDrawArrays(draw_mode_, 0, vertex_count_);
        Yield();
      } else {
        return false;
      }
    }
  }
  return true;
}

void ShaderProgram::Yield() {
  glFinish();
}

bool ShaderProgram::BeginDraw() {
  // Activate shader program
  if (!UseProgram())
    return false;

  // Push vertex attributes
  PushAttributes();

  // Clear output, if requested
  if (clears_) {
    glClearColor(clear_color_.red,
                 clear_color_.green,
                 clear_color_.blue,
                 clear_color_.alpha);
    glClear(GL_COLOR_BUFFER_BIT);
  }

  // Enable/Disable blending
  if (blending_) {
    glEnable(GL_BLEND);
    glBlendFunc(sfactor_, dfactor_);
  } else glDisable(GL_BLEND);

  return true;
}

int ShaderProgram::MaxVaryingCount() {
  GLint result;
  glGetIntegerv(GL_MAX_VARYING_VECTORS, &result);
  return result;
}

int ShaderProgram::MaxTextureUnits() {
  return GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS - 1;
}

void ShaderProgram::SetDrawMode(GLenum mode) {
  draw_mode_ = mode;
}

void ShaderProgram::SetClearsOutput(bool clears) {
  clears_ = clears;
}

void ShaderProgram::SetClearColor(float red, float green, float blue, float alpha) {
  clear_color_.red = red;
  clear_color_.green = green;
  clear_color_.blue = blue;
  clear_color_.alpha = alpha;
}

void ShaderProgram::SetTileCounts(int x_count, int y_count) {
  tile_x_count_ = x_count;
  tile_y_count_ = y_count;
}

// Variable Value Setting Helpers //////////////////////////////////////////////
bool ShaderProgram::CheckValueCount(const std::string& var_type,
                                    const std::string& var_name,
                                    int expected_count,
                                    int components,
                                    int value_size) {
  if (expected_count != (value_size / components)) {
    ALOGE("Shader Program: %s Value Error (%s): Expected value length %d "
         "(%d components), but received length of %d (%d components)!",
         var_type.c_str(), var_name.c_str(),
         expected_count, components * expected_count,
         value_size / components, value_size);
    return false;
  }
  return true;
}

bool ShaderProgram::CheckValueMult(const std::string& var_type,
                                   const std::string& var_name,
                                   int components,
                                   int value_size) {
  if (value_size % components != 0) {
    ALOGE("Shader Program: %s Value Error (%s): Value must be multiple of %d, "
         "but %d elements were passed!", var_type.c_str(), var_name.c_str(),
         components, value_size);
    return false;
  }
  return true;
}

bool ShaderProgram::CheckVarValid(ProgramVar var) {
  if (!IsVarValid(var)) {
    ALOGE("Shader Program: Attempting to access invalid variable!");
    return false;
  }
  return true;
}

// Uniforms ////////////////////////////////////////////////////////////////////
bool ShaderProgram::CheckUniformValid(ProgramVar var) {
  if (!IsVarValid(var) || uniform_indices_.find(var) == uniform_indices_.end()) {
    ALOGE("Shader Program: Attempting to access unknown uniform %d!", var);
    return false;
  }
  return true;
}

int ShaderProgram::MaxUniformCount() {
  // Here we return the minimum of the max uniform count for fragment and vertex
  // shaders.
  GLint count1, count2;
  glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &count1);
  glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &count2);
  return count1 < count2 ? count1 : count2;
}

ProgramVar ShaderProgram::GetUniform(const std::string& name) const {
  if (!IsExecutable()) {
    ALOGE("ShaderProgram: Error: Must link program before querying uniforms!");
    return -1;
  }
  return glGetUniformLocation(program_, name.c_str());
}

bool ShaderProgram::SetUniformValue(ProgramVar var, int value) {
  if (!CheckVarValid(var))
    return false;

  // Uniforms are local to the currently used program.
  if (UseProgram()) {
    glUniform1i(var, value);
    return !GLEnv::CheckGLError("Set Uniform Value (int)");
  }
  return false;
}

bool ShaderProgram::SetUniformValue(ProgramVar var, float value) {
  if (!CheckVarValid(var))
    return false;

  // Uniforms are local to the currently used program.
  if (UseProgram()) {
    glUniform1f(var, value);
    return !GLEnv::CheckGLError("Set Uniform Value (float)");
  }
  return false;
}

bool ShaderProgram::SetUniformValue(ProgramVar var,
                                    const int* values,
                                    int count) {
  if (!CheckUniformValid(var))
    return false;

  // Make sure we have values at all
  if (count == 0)
    return false;

  // Uniforms are local to the currently used program.
  if (UseProgram()) {
    // Get uniform information
    GLint capacity;
    GLenum type;
    char name[128];
    glGetActiveUniform(program_, IndexOfUniform(var), 128, NULL, &capacity, &type, name);

    // Make sure passed values are compatible
    const int components = GLEnv::NumberOfComponents(type);
    if (!CheckValueCount("Uniform (int)", name, capacity, components, count)
    ||  !CheckValueMult ("Uniform (int)", name, components, count))
      return false;

    // Set value based on type
    const int n = count / components;
    switch(type) {
      case GL_INT:
        glUniform1iv(var, n, values);
        break;

      case GL_INT_VEC2:
        glUniform2iv(var, n, values);
        break;

      case GL_INT_VEC3:
        glUniform3iv(var, n, values);
        break;

      case GL_INT_VEC4:
        glUniform4iv(var, n, values);
        break;

      default:
        return false;
    };
    return !GLEnv::CheckGLError("Set Uniform Value");
  }
  return false;
}

bool ShaderProgram::SetUniformValue(ProgramVar var,
                                    const float* values,
                                    int count) {
  if (!CheckUniformValid(var))
    return false;

  // Make sure we have values at all
  if (count == 0)
    return false;

  // Uniforms are local to the currently used program.
  if (UseProgram()) {
    // Get uniform information
    GLint capacity;
    GLenum type;
    char name[128];
    glGetActiveUniform(program_, IndexOfUniform(var), 128, NULL, &capacity, &type, name);

    // Make sure passed values are compatible
    const int components = GLEnv::NumberOfComponents(type);
    if (!CheckValueCount("Uniform (float)", name, capacity, components, count)
    ||  !CheckValueMult ("Uniform (float)", name, components, count))
      return false;

    // Set value based on type
    const int n = count / components;
    switch(type) {
      case GL_FLOAT:
        glUniform1fv(var, n, values);
        break;

      case GL_FLOAT_VEC2:
        glUniform2fv(var, n, values);
        break;

      case GL_FLOAT_VEC3:
        glUniform3fv(var, n, values);
        break;

      case GL_FLOAT_VEC4:
        glUniform4fv(var, n, values);
        break;

      case GL_FLOAT_MAT2:
        glUniformMatrix2fv(var, n, GL_FALSE, values);
        break;

      case GL_FLOAT_MAT3:
        glUniformMatrix3fv(var, n, GL_FALSE, values);
        break;

      case GL_FLOAT_MAT4:
        glUniformMatrix4fv(var, n, GL_FALSE, values);
        break;

      default:
        return false;
    };
    return !GLEnv::CheckGLError("Set Uniform Value");
  }
  return false;
}

bool ShaderProgram::SetUniformValue(ProgramVar var, const std::vector<int>& values) {
  return SetUniformValue(var, &values[0], values.size());
}

bool ShaderProgram::SetUniformValue(ProgramVar var,
                                    const std::vector<float>& values) {
  return SetUniformValue(var, &values[0], values.size());
}

bool ShaderProgram::SetUniformValue(const std::string& name, const Value& value) {
  if (ValueIsFloat(value))
    return SetUniformValue(GetUniform(name), GetFloatValue(value));
  else if (ValueIsInt(value))
    return SetUniformValue(GetUniform(name), GetIntValue(value));
  else if (ValueIsFloatArray(value))
    return SetUniformValue(GetUniform(name), GetFloatArrayValue(value), GetValueCount(value));
  else if (ValueIsIntArray(value))
    return SetUniformValue(GetUniform(name), GetIntArrayValue(value), GetValueCount(value));
  else
    return false;
}

Value ShaderProgram::GetUniformValue(const std::string& name) {
  ProgramVar var = GetUniform(name);
  if (CheckUniformValid(var)) {
    // Get uniform information
    GLint capacity;
    GLenum type;
    glGetActiveUniform(program_, IndexOfUniform(var), 0, NULL, &capacity, &type, NULL);
    if (!GLEnv::CheckGLError("Get Active Uniform")) {
      // Get value based on type, and wrap in value object
      switch(type) {
        case GL_INT: {
          int value;
          glGetUniformiv(program_, var, &value);
          return !GLEnv::CheckGLError("GetVariableValue") ? MakeIntValue(value)
                                                          : MakeNullValue();
        } break;

        case GL_INT_VEC2: {
          int value[2];
          glGetUniformiv(program_, var, &value[0]);
          return !GLEnv::CheckGLError("GetVariableValue") ? MakeIntArrayValue(value, 2)
                                                          : MakeNullValue();
        } break;

        case GL_INT_VEC3: {
          int value[3];
          glGetUniformiv(program_, var, &value[0]);
          return !GLEnv::CheckGLError("GetVariableValue") ? MakeIntArrayValue(value, 3)
                                                          : MakeNullValue();
        } break;

        case GL_INT_VEC4: {
          int value[4];
          glGetUniformiv(program_, var, &value[0]);
          return !GLEnv::CheckGLError("GetVariableValue") ? MakeIntArrayValue(value, 4)
                                                          : MakeNullValue();
        } break;

        case GL_FLOAT: {
          float value;
          glGetUniformfv(program_, var, &value);
          return !GLEnv::CheckGLError("GetVariableValue") ? MakeFloatValue(value)
                                                          : MakeNullValue();
        } break;

        case GL_FLOAT_VEC2: {
          float value[2];
          glGetUniformfv(program_, var, &value[0]);
          return !GLEnv::CheckGLError("GetVariableValue") ? MakeFloatArrayValue(value, 2)
                                                          : MakeNullValue();
        } break;

        case GL_FLOAT_VEC3: {
          float value[3];
          glGetUniformfv(program_, var, &value[0]);
          return !GLEnv::CheckGLError("GetVariableValue") ? MakeFloatArrayValue(value, 3)
                                                          : MakeNullValue();
        } break;

        case GL_FLOAT_VEC4: {
          float value[4];
          glGetUniformfv(program_, var, &value[0]);
          return !GLEnv::CheckGLError("GetVariableValue") ? MakeFloatArrayValue(value, 4)
                                                          : MakeNullValue();
        } break;

        case GL_FLOAT_MAT2: {
          float value[4];
          glGetUniformfv(program_, var, &value[0]);
          return !GLEnv::CheckGLError("GetVariableValue") ? MakeFloatArrayValue(value, 4)
                                                          : MakeNullValue();
        } break;

        case GL_FLOAT_MAT3: {
          float value[9];
          glGetUniformfv(program_, var, &value[0]);
          return !GLEnv::CheckGLError("GetVariableValue") ? MakeFloatArrayValue(value, 9)
                                                          : MakeNullValue();
        } break;

        case GL_FLOAT_MAT4: {
          float value[16];
          glGetUniformfv(program_, var, &value[0]);
          return !GLEnv::CheckGLError("GetVariableValue") ? MakeFloatArrayValue(value, 16)
                                                          : MakeNullValue();
        } break;
      }
    }
  }
  return MakeNullValue();
}

GLuint ShaderProgram::IndexOfUniform(ProgramVar var) {
  return uniform_indices_[var];
}

// Attributes //////////////////////////////////////////////////////////////////////////////////////
int ShaderProgram::MaxAttributeCount() {
  GLint result;
  glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &result);
  return result;
}

ProgramVar ShaderProgram::GetAttribute(const std::string& name) const {
  if (!IsExecutable()) {
    ALOGE("ShaderProgram: Error: Must link program before querying attributes!");
    return -1;
  } else if (name == PositionAttributeName() || name == TexCoordAttributeName()) {
    ALOGW("ShaderProgram: Attempting to overwrite internal vertex attribute '%s'!", name.c_str());
  }
  return glGetAttribLocation(program_, name.c_str());
}

bool ShaderProgram::SetAttributeValues(ProgramVar var,
                                       const VertexFrame* vbo,
                                       GLenum type,
                                       int components,
                                       int stride,
                                       int offset,
                                       bool normalize) {
  if (!CheckVarValid(var))
    return false;

  if (vbo) {
    VertexAttrib attrib;
    attrib.is_const = false;
    attrib.index = var;
    attrib.components = components;
    attrib.normalized = normalize;
    attrib.stride = stride;
    attrib.type = type;
    attrib.vbo = vbo->GetVboId();
    attrib.offset = offset;

    return StoreAttribute(attrib);
  }
  return false;
}

bool ShaderProgram::SetAttributeValues(ProgramVar var,
                                       const uint8_t* data,
                                       GLenum type,
                                       int components,
                                       int stride,
                                       int offset,
                                       bool normalize) {
  if (!CheckVarValid(var))
    return false;

  if (data) {
    VertexAttrib attrib;
    attrib.is_const = false;
    attrib.index = var;
    attrib.components = components;
    attrib.normalized = normalize;
    attrib.stride = stride;
    attrib.type = type;
    attrib.values = data + offset;

    return StoreAttribute(attrib);
  }
  return false;
}

bool ShaderProgram::SetAttributeValues(ProgramVar var,
                                       const std::vector<float>& data,
                                       int components) {
  return SetAttributeValues(var, &data[0], data.size(), components);
}

bool ShaderProgram::SetAttributeValues(ProgramVar var,
                                       const float* data,
                                       int total,
                                       int components) {
  if (!CheckVarValid(var))
    return false;

  // Make sure the passed data vector has a valid size
  if (total  % components != 0) {
    ALOGE("ShaderProgram: Invalid attribute vector given! Specified a component "
         "count of %d, but passed a non-multiple vector of size %d!",
         components, total);
    return false;
  }

  // Copy the data to a buffer we own
  float* data_cpy = new float[total];
  memcpy(data_cpy, data, sizeof(float) * total);

  // Store the attribute
  VertexAttrib attrib;
  attrib.is_const = false;
  attrib.index = var;
  attrib.components = components;
  attrib.normalized = false;
  attrib.stride = components * sizeof(float);
  attrib.type = GL_FLOAT;
  attrib.values = data_cpy;
  attrib.owned_data = data_cpy; // Marks this for deletion later on

  return StoreAttribute(attrib);
}

bool ShaderProgram::StoreAttribute(VertexAttrib attrib) {
  if (attrib.index >= 0) {
    attrib_values_[attrib.index] = attrib;
    return true;
  }
  return false;
}

bool ShaderProgram::PushAttributes() {
  for (VertexAttribMap::const_iterator iter = attrib_values_.begin();
       iter != attrib_values_.end();
       ++iter) {
    const VertexAttrib& attrib = iter->second;

    if (attrib.is_const) {
      // Set constant attribute values (must be specified as host values)
      if (!attrib.values)
        return false;

      const float* values = reinterpret_cast<const float*>(attrib.values);
      switch (attrib.components) {
        case 1: glVertexAttrib1fv(attrib.index, values); break;
        case 2: glVertexAttrib2fv(attrib.index, values); break;
        case 3: glVertexAttrib3fv(attrib.index, values); break;
        case 4: glVertexAttrib4fv(attrib.index, values); break;
        default: return false;
      }
      glDisableVertexAttribArray(attrib.index);
    } else {
      // Set per-vertex values
      if (attrib.values) {
        // Make sure no buffer is bound and set attribute
        glBindBuffer(GL_ARRAY_BUFFER, 0);

        glVertexAttribPointer(attrib.index,
                              attrib.components,
                              attrib.type,
                              attrib.normalized,
                              attrib.stride,
                              attrib.values);
      } else if (attrib.vbo) {
        // Bind VBO and set attribute
        glBindBuffer(GL_ARRAY_BUFFER, attrib.vbo);

        glVertexAttribPointer(attrib.index,
                              attrib.components,
                              attrib.type,
                              attrib.normalized,
                              attrib.stride,
                              reinterpret_cast<const void*>(attrib.offset));
      } else {
        return false;
      }
      glEnableVertexAttribArray(attrib.index);
    }

    // Make sure everything worked
    if (GLEnv::CheckGLError("Pushing Vertex Attributes"))
      return false;
  }

  return true;
}

bool ShaderProgram::PopAttributes() {
  // Disable vertex attributes
  for (VertexAttribMap::const_iterator iter = attrib_values_.begin();
       iter != attrib_values_.end();
       ++iter) {
    glDisableVertexAttribArray(iter->second.index);
  }
  // Unbind buffer: Very important as this greatly affects what glVertexAttribPointer does!
  glBindBuffer(GL_ARRAY_BUFFER, 0);
  return !GLEnv::CheckGLError("Popping Vertex Attributes");
}

void ShaderProgram::SetVertexCount(int count) {
  vertex_count_ = count;
}

} // namespace filterfw
} // namespace android
