165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn/* 265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Copyright (C) 2011 The Android Open Source Project 365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * 465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Licensed under the Apache License, Version 2.0 (the "License"); 565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * you may not use this file except in compliance with the License. 665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * You may obtain a copy of the License at 765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * 865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * http://www.apache.org/licenses/LICENSE-2.0 965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * 1065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Unless required by applicable law or agreed to in writing, software 1165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * distributed under the License is distributed on an "AS IS" BASIS, 1265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * See the License for the specific language governing permissions and 1465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * limitations under the License. 1565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn */ 1665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 1765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn#include "base/logging.h" 1865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 1965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn#include "core/geometry.h" 2065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn#include "core/gl_buffer_interface.h" 2165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn#include "core/gl_env.h" 2265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn#include "core/gl_frame.h" 2365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn#include "core/shader_program.h" 2465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn#include "core/vertex_frame.h" 2565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 2665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn#include <string> 2765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn#include <sstream> 2865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn#include <vector> 2965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 3065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennnamespace android { 3165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennnamespace filterfw { 3265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 3365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn// VBO attachment keys 3465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennstatic const int kDefaultVboKey = 1; 3565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 3665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennstatic const char* s_default_vertex_shader_source_ = 3765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn "attribute vec4 a_position;\n" 3865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn "attribute vec2 a_texcoord;\n" 3965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn "varying vec2 v_texcoord;\n" 4065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn "void main() {\n" 4165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn " gl_Position = a_position;\n" 4265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn " v_texcoord = a_texcoord;\n" 4365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn "}\n"; 4465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 4565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn// Helper Functions //////////////////////////////////////////////////////////// 4665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn// Maps coordinates x,y in the unit rectangle over to the quadrangle specified 4765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn// by the four points in b. The result coordinates are written to xt and yt. 4865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennstatic void GetTileCoords(const float* b, float x, float y, float* xt, float* yt) { 4965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn const float w0 = (1.0f - x) * (1.0f - y); 5065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn const float w1 = x * (1.0f - y); 5165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn const float w2 = (1.0f - x) * y; 5265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn const float w3 = x * y; 5365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 5465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn *xt = w0 * b[0] + w1 * b[2] + w2 * b[4] + w3 * b[6]; 5565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn *yt = w0 * b[1] + w1 * b[3] + w2 * b[5] + w3 * b[7]; 5665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 5765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 5865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennstatic inline float AdjustRatio(float current, float next) { 5965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return (current + next) / 2.0; 6065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 6165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 6265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn// VertexAttrib implementation ///////////////////////////////////////////////// 6365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius RennShaderProgram::VertexAttrib::VertexAttrib() 6465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn : is_const(true), 6565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn index(-1), 6665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn normalized(false), 6765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn stride(0), 6865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn components(0), 6965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn offset(0), 7065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn type(GL_FLOAT), 7165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn vbo(0), 7265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn values(NULL), 7365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn owned_data(NULL) { 7465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 7565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 7665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn// ShaderProgram implementation //////////////////////////////////////////////// 7765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius RennShaderProgram::ShaderProgram(GLEnv* gl_env, const std::string& fragment_shader) 7865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn : fragment_shader_source_(fragment_shader), 7965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn vertex_shader_source_(s_default_vertex_shader_source_), 8065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn fragment_shader_(0), 8165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn vertex_shader_(0), 8265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn program_(0), 8365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn gl_env_(gl_env), 8465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn base_texture_unit_(GL_TEXTURE0), 8565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn source_coords_(NULL), 8665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn target_coords_(NULL), 8765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn manage_coordinates_(false), 8865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn tile_x_count_(1), 8965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn tile_y_count_(1), 9065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn vertex_count_(4), 9165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn draw_mode_(GL_TRIANGLE_STRIP), 9265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn clears_(false), 9365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn blending_(false), 9465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn sfactor_(GL_SRC_ALPHA), 9565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn dfactor_(GL_ONE_MINUS_SRC_ALPHA) { 9665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn SetDefaultCoords(); 9765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 9865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 9965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius RennShaderProgram::ShaderProgram(GLEnv* gl_env, 10065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn const std::string& vertex_shader, 10165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn const std::string& fragment_shader) 10265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn : fragment_shader_source_(fragment_shader), 10365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn vertex_shader_source_(vertex_shader), 10465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn fragment_shader_(0), 10565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn vertex_shader_(0), 10665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn program_(0), 10765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn gl_env_(gl_env), 10865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn base_texture_unit_(GL_TEXTURE0), 10965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn source_coords_(NULL), 11065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn target_coords_(NULL), 11165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn manage_coordinates_(false), 11265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn tile_x_count_(1), 11365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn tile_y_count_(1), 11465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn vertex_count_(4), 11565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn draw_mode_(GL_TRIANGLE_STRIP), 11665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn clears_(false), 11765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn blending_(false), 11865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn sfactor_(GL_SRC_ALPHA), 11965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn dfactor_(GL_ONE_MINUS_SRC_ALPHA) { 12065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn SetDefaultCoords(); 12165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 12265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 12365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius RennShaderProgram::~ShaderProgram() { 12465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Delete our vertex data 12565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn delete[] source_coords_; 12665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn delete[] target_coords_; 12765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 12865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Delete any owned attribute data 12965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn VertexAttribMap::const_iterator iter; 13065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn for (iter = attrib_values_.begin(); iter != attrib_values_.end(); ++iter) { 13165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn const VertexAttrib& attrib = iter->second; 13265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (attrib.owned_data) 13365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn delete[] attrib.owned_data; 13465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 13565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 13665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 13765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennvoid ShaderProgram::SetDefaultCoords() { 13865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!source_coords_) 13965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn source_coords_ = new float[8]; 14065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!target_coords_) 14165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn target_coords_ = new float[8]; 14265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 14365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn source_coords_[0] = 0.0f; 14465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn source_coords_[1] = 0.0f; 14565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn source_coords_[2] = 1.0f; 14665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn source_coords_[3] = 0.0f; 14765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn source_coords_[4] = 0.0f; 14865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn source_coords_[5] = 1.0f; 14965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn source_coords_[6] = 1.0f; 15065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn source_coords_[7] = 1.0f; 15165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 15265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn target_coords_[0] = -1.0f; 15365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn target_coords_[1] = -1.0f; 15465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn target_coords_[2] = 1.0f; 15565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn target_coords_[3] = -1.0f; 15665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn target_coords_[4] = -1.0f; 15765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn target_coords_[5] = 1.0f; 15865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn target_coords_[6] = 1.0f; 15965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn target_coords_[7] = 1.0f; 16065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 16165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 16265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 16365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius RennShaderProgram* ShaderProgram::CreateIdentity(GLEnv* gl_env) { 16465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn const char* s_id_fragment_shader = 16565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn "precision mediump float;\n" 16665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn "uniform sampler2D tex_sampler_0;\n" 16765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn "varying vec2 v_texcoord;\n" 16865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn "void main() {\n" 16965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn " gl_FragColor = texture2D(tex_sampler_0, v_texcoord);\n" 17065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn "}\n"; 17165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ShaderProgram* result = new ShaderProgram(gl_env, s_id_fragment_shader); 17265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn result->CompileAndLink(); 17365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return result; 17465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 17565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 17665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool ShaderProgram::IsVarValid(ProgramVar var) { 17765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return var != -1; 17865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 17965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 18065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool ShaderProgram::Process(const std::vector<const GLTextureHandle*>& input, 18165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GLFrameBufferHandle* output) { 18265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // TODO: This can be optimized: If the input and output are the same, as in 18365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // the last iteration (typical of a multi-pass filter), a lot of this setup 18465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // may be skipped. 18565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 18665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Abort if program did not successfully compile and link 18765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!IsExecutable()) { 18865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ALOGE("ShaderProgram: unexecutable program!"); 18965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 19065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 19165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 19265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Focus the FBO of the output 19365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!output->FocusFrameBuffer()) { 19465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ALOGE("Unable to focus frame buffer"); 19565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 19665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 19765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 19865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Get all required textures 19965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn std::vector<GLuint> textures; 20065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn std::vector<GLenum> targets; 20165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn for (unsigned i = 0; i < input.size(); ++i) { 20265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Get the current input frame and make sure it is a GL frame 20365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (input[i]) { 20465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Get the texture bound to that frame 20565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn const GLuint tex_id = input[i]->GetTextureId(); 20665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn const GLenum target = input[i]->GetTextureTarget(); 20765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (tex_id == 0) { 20865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ALOGE("ShaderProgram: invalid texture id at input: %d!", i); 20965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 21065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 21165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn textures.push_back(tex_id); 21265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn targets.push_back(target); 21365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 21465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 21565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 21665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // And render! 21765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!RenderFrame(textures, targets)) { 21865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ALOGE("Unable to render frame"); 21965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 22065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 22165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return true; 22265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 22365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 22465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool ShaderProgram::Process(const std::vector<const GLFrame*>& input, GLFrame* output) { 22565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn std::vector<const GLTextureHandle*> textures(input.size()); 22665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn std::copy(input.begin(), input.end(), textures.begin()); 22765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return Process(textures, output); 22865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 22965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 23065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennvoid ShaderProgram::SetSourceRect(float x, float y, float width, float height) { 23165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn Quad quad(Point(x, y), 23265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn Point(x + width, y), 23365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn Point(x, y + height), 23465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn Point(x + width, y + height)); 23565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn SetSourceRegion(quad); 23665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 23765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 23865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennvoid ShaderProgram::SetSourceRegion(const Quad& quad) { 23965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn int index = 0; 24065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn for (int i = 0; i < 4; ++i, index += 2) { 24165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn source_coords_[index] = quad.point(i).x(); 24265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn source_coords_[index+1] = quad.point(i).y(); 24365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 24465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 24565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 24665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennvoid ShaderProgram::SetTargetRect(float x, float y, float width, float height) { 24765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn Quad quad(Point(x, y), 24865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn Point(x + width, y), 24965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn Point(x, y + height), 25065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn Point(x + width, y + height)); 25165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn SetTargetRegion(quad); 25265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 25365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 25465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennvoid ShaderProgram::SetTargetRegion(const Quad& quad) { 25565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn int index = 0; 25665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn for (int i = 0; i < 4; ++i, index += 2) { 25765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn target_coords_[index] = (quad.point(i).x() * 2.0) - 1.0; 25865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn target_coords_[index+1] = (quad.point(i).y() * 2.0) - 1.0; 25965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 26065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 26165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 26265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool ShaderProgram::CompileAndLink() { 26365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Make sure we haven't compiled and linked already 26465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (vertex_shader_ != 0 || fragment_shader_ != 0 || program_ != 0) { 26565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ALOGE("Attempting to re-compile shaders!"); 26665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 26765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 26865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 26965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Compile vertex shader 27065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn vertex_shader_ = CompileShader(GL_VERTEX_SHADER, 27165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn vertex_shader_source_.c_str()); 27265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!vertex_shader_) { 27365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ALOGE("Shader compilation failed!"); 27465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 27565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 27665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 27765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Compile fragment shader 27865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn fragment_shader_ = CompileShader(GL_FRAGMENT_SHADER, 27965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn fragment_shader_source_.c_str()); 28065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!fragment_shader_) 28165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 28265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 28365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Link 28465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GLuint shaders[2] = { vertex_shader_, fragment_shader_ }; 28565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn program_ = LinkProgram(shaders, 2); 28665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 28765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Scan for all uniforms in the program 28865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ScanUniforms(); 28965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 29065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Check if we manage all coordinates 29165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (program_ != 0) { 29265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ProgramVar tex_coord_attr = glGetAttribLocation(program_, TexCoordAttributeName().c_str()); 29365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ProgramVar pos_coord_attr = glGetAttribLocation(program_, PositionAttributeName().c_str()); 29465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn manage_coordinates_ = (tex_coord_attr >= 0 && pos_coord_attr >= 0); 29565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else { 29665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ALOGE("Could not link shader program!"); 29765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 29865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 29965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 30065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return true; 30165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 30265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 30365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius RennGLuint ShaderProgram::CompileShader(GLenum shader_type, const char* source) { 30465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn LOG_FRAME("Compiling source:\n[%s]", source); 30565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 30665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Create shader 30765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GLuint shader = glCreateShader(shader_type); 30865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (shader) { 30965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Compile source 31065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glShaderSource(shader, 1, &source, NULL); 31165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glCompileShader(shader); 31265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 31365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Check for compilation errors 31465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GLint compiled = 0; 31565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); 31665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!compiled) { 31765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Log the compilation error messages 31865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ALOGE("Problem compiling shader! Source:"); 31965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ALOGE("%s", source); 32065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn std::string src(source); 32165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn unsigned int cur_pos = 0; 32265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn unsigned int next_pos = 0; 32365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn int line_number = 1; 32465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn while ( (next_pos = src.find_first_of('\n', cur_pos)) != std::string::npos) { 32565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ALOGE("%03d : %s", line_number, src.substr(cur_pos, next_pos-cur_pos).c_str()); 32665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn cur_pos = next_pos + 1; 32765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn line_number++; 32865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 32965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ALOGE("%03d : %s", line_number, src.substr(cur_pos, next_pos-cur_pos).c_str()); 33065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 33165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GLint log_length = 0; 33265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length); 33365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (log_length) { 33465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn char* error_log = new char[log_length]; 33565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (error_log) { 33665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glGetShaderInfoLog(shader, log_length, NULL, error_log); 33765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ALOGE("Shader compilation error %d:\n%s\n", shader_type, error_log); 33865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn delete[] error_log; 33965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 34065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 34165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glDeleteShader(shader); 34265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn shader = 0; 34365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 34465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 34565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return shader; 34665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 34765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 34865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius RennGLuint ShaderProgram::LinkProgram(GLuint* shaders, GLuint count) { 34965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GLuint program = glCreateProgram(); 35065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (program) { 35165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Attach all compiled shaders 35265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn for (GLuint i = 0; i < count; ++i) { 35365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glAttachShader(program, shaders[i]); 35465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (GLEnv::CheckGLError("glAttachShader")) return 0; 35565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 35665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 35765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Link 35865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glLinkProgram(program); 35965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 36065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Check for linking errors 36165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GLint linked = 0; 36265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glGetProgramiv(program, GL_LINK_STATUS, &linked); 36365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (linked != GL_TRUE) { 36465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Log the linker error messages 36565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GLint log_length = 0; 36665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length); 36765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (log_length) { 36865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn char* error_log = new char[log_length]; 36965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (error_log) { 37065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glGetProgramInfoLog(program, log_length, NULL, error_log); 37165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ALOGE("Program Linker Error:\n%s\n", error_log); 37265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn delete[] error_log; 37365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 37465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 37565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glDeleteProgram(program); 37665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn program = 0; 37765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 37865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 37965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return program; 38065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 38165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 38265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennvoid ShaderProgram::ScanUniforms() { 38365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn int uniform_count; 38465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn int buffer_size; 38565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GLenum type; 38665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GLint capacity; 38765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glGetProgramiv(program_, GL_ACTIVE_UNIFORMS, &uniform_count); 38865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glGetProgramiv(program_, GL_ACTIVE_UNIFORM_MAX_LENGTH, &buffer_size); 38965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn std::vector<GLchar> name(buffer_size); 39065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn for (int i = 0; i < uniform_count; ++i) { 39165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glGetActiveUniform(program_, i, buffer_size, NULL, &capacity, &type, &name[0]); 39265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ProgramVar uniform_id = glGetUniformLocation(program_, &name[0]); 39365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn uniform_indices_[uniform_id] = i; 39465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 39565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 39665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 39765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool ShaderProgram::PushCoords(ProgramVar attr, float* coords) { 39865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // If the shader does not define these, we simply ignore the coordinates, and assume that the 39965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // user is managing coordinates. 40065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (attr >= 0) { 40165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn const uint8_t* data = reinterpret_cast<const uint8_t*>(coords); 40265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glBindBuffer(GL_ARRAY_BUFFER, 0); 40365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glVertexAttribPointer(attr, 2, GL_FLOAT, false, 2 * sizeof(float), data); 40465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glEnableVertexAttribArray(attr); 40565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return !GLEnv::CheckGLError("Pushing vertex coordinates"); 40665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 40765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return true; 40865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 40965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 41065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool ShaderProgram::PushSourceCoords(float* coords) { 41165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ProgramVar tex_coord_attr = glGetAttribLocation(program_, TexCoordAttributeName().c_str()); 41265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return PushCoords(tex_coord_attr, coords); 41365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 41465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 41565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool ShaderProgram::PushTargetCoords(float* coords) { 41665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ProgramVar pos_coord_attr = glGetAttribLocation(program_, PositionAttributeName().c_str()); 41765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return PushCoords(pos_coord_attr, coords); 41865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 41965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 42065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennstd::string ShaderProgram::InputTextureUniformName(int index) { 42165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn std::stringstream tex_name; 42265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn tex_name << "tex_sampler_" << index; 42365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return tex_name.str(); 42465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 42565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 42665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool ShaderProgram::BindInputTextures(const std::vector<GLuint>& textures, 42765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn const std::vector<GLenum>& targets) { 42865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn for (unsigned i = 0; i < textures.size(); ++i) { 42965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Activate texture unit i 43065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glActiveTexture(BaseTextureUnit() + i); 43165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (GLEnv::CheckGLError("Activating Texture Unit")) 43265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 43365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 43465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Bind our texture 43565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glBindTexture(targets[i], textures[i]); 43665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn LOG_FRAME("Binding texture %d", textures[i]); 43765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (GLEnv::CheckGLError("Binding Texture")) 43865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 43965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 44065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Set the texture handle in the shader to unit i 44165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ProgramVar tex_var = GetUniform(InputTextureUniformName(i)); 44265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (tex_var >= 0) { 44365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glUniform1i(tex_var, i); 44465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else { 44565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ALOGE("ShaderProgram: Shader does not seem to support %d number of " 44665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn "inputs! Missing uniform 'tex_sampler_%d'!", textures.size(), i); 44765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 44865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 44965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 45065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (GLEnv::CheckGLError("Texture Variable Binding")) 45165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 45265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 45365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 45465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return true; 45565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 45665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 45765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool ShaderProgram::UseProgram() { 45865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (GLEnv::GetCurrentProgram() != program_) { 45965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn LOG_FRAME("Using program %d", program_); 46065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glUseProgram(program_); 46165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return !GLEnv::CheckGLError("Use Program"); 46265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 46365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return true; 46465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 46565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 46665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool ShaderProgram::RenderFrame(const std::vector<GLuint>& textures, 46765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn const std::vector<GLenum>& targets) { 46865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Make sure we have enough texture units to accomodate the textures 46965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (textures.size() > static_cast<unsigned>(MaxTextureUnits())) { 47065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ALOGE("ShaderProgram: Number of input textures is unsupported on this " 47165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn "platform!"); 47265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 47365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 47465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 47565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Prepare to render 47665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!BeginDraw()) { 47765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ALOGE("ShaderProgram: couldn't initialize gl for drawing!"); 47865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 47965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 48065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 48165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Bind input textures 48265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!BindInputTextures(textures, targets)) { 48365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ALOGE("BindInputTextures failed"); 48465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 48565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 48665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 48765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (LOG_EVERY_FRAME) { 48865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn int fbo, program, buffer; 48965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glGetIntegerv(GL_FRAMEBUFFER_BINDING, &fbo); 49065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glGetIntegerv(GL_CURRENT_PROGRAM, &program); 49165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &buffer); 49265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ALOGV("RenderFrame: fbo %d prog %d buff %d", fbo, program, buffer); 49365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 49465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 49565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Render! 49665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn const bool requestTile = (tile_x_count_ != 1 || tile_y_count_ != 1); 49765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn const bool success = (!requestTile || !manage_coordinates_ || vertex_count_ != 4) 49865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ? Draw() 49965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn : DrawTiled(); 50065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 50165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Pop vertex attributes 50265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn PopAttributes(); 50365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 50465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return success && !GLEnv::CheckGLError("Rendering"); 50565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 50665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 50765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool ShaderProgram::Draw() { 50865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (PushSourceCoords(source_coords_) && PushTargetCoords(target_coords_)) { 50965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glDrawArrays(draw_mode_, 0, vertex_count_); 51065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return true; 51165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 51265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 51365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 51465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 51565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool ShaderProgram::DrawTiled() { 51665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Target coordinate step size 51765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn float s[8]; 51865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn float t[8]; 51965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 52065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Step sizes 52165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn const float xs = 1.0f / static_cast<float>(tile_x_count_); 52265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn const float ys = 1.0f / static_cast<float>(tile_y_count_); 52365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 52465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Tile drawing loop 52565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn for (int i = 0; i < tile_x_count_; ++i) { 52665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn for (int j = 0; j < tile_y_count_; ++j) { 52765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Current coordinates in unit rectangle 52865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn const float x = i / static_cast<float>(tile_x_count_); 52965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn const float y = j / static_cast<float>(tile_y_count_); 53065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 53165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Source coords 53265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GetTileCoords(source_coords_, x, y, &s[0], &s[1]); 53365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GetTileCoords(source_coords_, x + xs, y, &s[2], &s[3]); 53465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GetTileCoords(source_coords_, x, y + ys, &s[4], &s[5]); 53565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GetTileCoords(source_coords_, x + xs, y + ys, &s[6], &s[7]); 53665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 53765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Target coords 53865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GetTileCoords(target_coords_, x, y, &t[0], &t[1]); 53965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GetTileCoords(target_coords_, x + xs, y, &t[2], &t[3]); 54065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GetTileCoords(target_coords_, x, y + ys, &t[4], &t[5]); 54165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GetTileCoords(target_coords_, x + xs, y + ys, &t[6], &t[7]); 54265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 54365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (PushSourceCoords(s) && PushTargetCoords(t)) { 54465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glDrawArrays(draw_mode_, 0, vertex_count_); 54565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn Yield(); 54665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else { 54765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 54865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 54965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 55065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 55165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return true; 55265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 55365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 55465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennvoid ShaderProgram::Yield() { 55565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glFinish(); 55665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 55765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 55865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool ShaderProgram::BeginDraw() { 55965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Activate shader program 56065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!UseProgram()) 56165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 56265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 56365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Push vertex attributes 56465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn PushAttributes(); 56565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 56665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Clear output, if requested 56765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (clears_) { 56865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glClearColor(clear_color_.red, 56965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn clear_color_.green, 57065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn clear_color_.blue, 57165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn clear_color_.alpha); 57265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glClear(GL_COLOR_BUFFER_BIT); 57365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 57465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 57565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Enable/Disable blending 57665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (blending_) { 57765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glEnable(GL_BLEND); 57865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glBlendFunc(sfactor_, dfactor_); 57965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else glDisable(GL_BLEND); 58065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 58165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return true; 58265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 58365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 58465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennint ShaderProgram::MaxVaryingCount() { 58565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GLint result; 58665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glGetIntegerv(GL_MAX_VARYING_VECTORS, &result); 58765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return result; 58865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 58965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 59065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennint ShaderProgram::MaxTextureUnits() { 59165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS - 1; 59265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 59365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 59465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennvoid ShaderProgram::SetDrawMode(GLenum mode) { 59565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn draw_mode_ = mode; 59665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 59765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 59865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennvoid ShaderProgram::SetClearsOutput(bool clears) { 59965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn clears_ = clears; 60065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 60165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 60265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennvoid ShaderProgram::SetClearColor(float red, float green, float blue, float alpha) { 60365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn clear_color_.red = red; 60465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn clear_color_.green = green; 60565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn clear_color_.blue = blue; 60665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn clear_color_.alpha = alpha; 60765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 60865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 60965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennvoid ShaderProgram::SetTileCounts(int x_count, int y_count) { 61065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn tile_x_count_ = x_count; 61165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn tile_y_count_ = y_count; 61265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 61365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 61465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn// Variable Value Setting Helpers ////////////////////////////////////////////// 61565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool ShaderProgram::CheckValueCount(const std::string& var_type, 61665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn const std::string& var_name, 61765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn int expected_count, 61865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn int components, 61965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn int value_size) { 62065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (expected_count != (value_size / components)) { 62165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ALOGE("Shader Program: %s Value Error (%s): Expected value length %d " 62265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn "(%d components), but received length of %d (%d components)!", 62365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn var_type.c_str(), var_name.c_str(), 62465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn expected_count, components * expected_count, 62565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn value_size / components, value_size); 62665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 62765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 62865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return true; 62965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 63065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 63165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool ShaderProgram::CheckValueMult(const std::string& var_type, 63265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn const std::string& var_name, 63365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn int components, 63465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn int value_size) { 63565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (value_size % components != 0) { 63665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ALOGE("Shader Program: %s Value Error (%s): Value must be multiple of %d, " 63765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn "but %d elements were passed!", var_type.c_str(), var_name.c_str(), 63865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn components, value_size); 63965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 64065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 64165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return true; 64265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 64365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 64465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool ShaderProgram::CheckVarValid(ProgramVar var) { 64565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!IsVarValid(var)) { 64665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ALOGE("Shader Program: Attempting to access invalid variable!"); 64765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 64865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 64965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return true; 65065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 65165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 65265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn// Uniforms //////////////////////////////////////////////////////////////////// 65365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool ShaderProgram::CheckUniformValid(ProgramVar var) { 65465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!IsVarValid(var) || uniform_indices_.find(var) == uniform_indices_.end()) { 65565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ALOGE("Shader Program: Attempting to access unknown uniform %d!", var); 65665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 65765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 65865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return true; 65965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 66065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 66165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennint ShaderProgram::MaxUniformCount() { 66265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Here we return the minimum of the max uniform count for fragment and vertex 66365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // shaders. 66465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GLint count1, count2; 66565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glGetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, &count1); 66665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &count2); 66765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return count1 < count2 ? count1 : count2; 66865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 66965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 67065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius RennProgramVar ShaderProgram::GetUniform(const std::string& name) const { 67165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!IsExecutable()) { 67265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ALOGE("ShaderProgram: Error: Must link program before querying uniforms!"); 67365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return -1; 67465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 67565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return glGetUniformLocation(program_, name.c_str()); 67665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 67765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 67865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool ShaderProgram::SetUniformValue(ProgramVar var, int value) { 67965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!CheckVarValid(var)) 68065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 68165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 68265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Uniforms are local to the currently used program. 68365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (UseProgram()) { 68465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glUniform1i(var, value); 68565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return !GLEnv::CheckGLError("Set Uniform Value (int)"); 68665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 68765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 68865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 68965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 69065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool ShaderProgram::SetUniformValue(ProgramVar var, float value) { 69165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!CheckVarValid(var)) 69265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 69365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 69465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Uniforms are local to the currently used program. 69565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (UseProgram()) { 69665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glUniform1f(var, value); 69765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return !GLEnv::CheckGLError("Set Uniform Value (float)"); 69865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 69965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 70065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 70165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 70265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool ShaderProgram::SetUniformValue(ProgramVar var, 70365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn const int* values, 70465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn int count) { 70565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!CheckUniformValid(var)) 70665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 70765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 70865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Make sure we have values at all 70965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (count == 0) 71065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 71165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 71265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Uniforms are local to the currently used program. 71365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (UseProgram()) { 71465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Get uniform information 71565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GLint capacity; 71665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GLenum type; 71765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn char name[128]; 71865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glGetActiveUniform(program_, IndexOfUniform(var), 128, NULL, &capacity, &type, name); 71965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 72065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Make sure passed values are compatible 72165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn const int components = GLEnv::NumberOfComponents(type); 72265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!CheckValueCount("Uniform (int)", name, capacity, components, count) 72365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn || !CheckValueMult ("Uniform (int)", name, components, count)) 72465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 72565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 72665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Set value based on type 72765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn const int n = count / components; 72865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn switch(type) { 72965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case GL_INT: 73065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glUniform1iv(var, n, values); 73165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn break; 73265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 73365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case GL_INT_VEC2: 73465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glUniform2iv(var, n, values); 73565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn break; 73665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 73765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case GL_INT_VEC3: 73865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glUniform3iv(var, n, values); 73965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn break; 74065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 74165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case GL_INT_VEC4: 74265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glUniform4iv(var, n, values); 74365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn break; 74465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 74565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn default: 74665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 74765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn }; 74865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return !GLEnv::CheckGLError("Set Uniform Value"); 74965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 75065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 75165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 75265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 75365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool ShaderProgram::SetUniformValue(ProgramVar var, 75465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn const float* values, 75565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn int count) { 75665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!CheckUniformValid(var)) 75765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 75865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 75965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Make sure we have values at all 76065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (count == 0) 76165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 76265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 76365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Uniforms are local to the currently used program. 76465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (UseProgram()) { 76565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Get uniform information 76665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GLint capacity; 76765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GLenum type; 76865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn char name[128]; 76965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glGetActiveUniform(program_, IndexOfUniform(var), 128, NULL, &capacity, &type, name); 77065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 77165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Make sure passed values are compatible 77265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn const int components = GLEnv::NumberOfComponents(type); 77365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!CheckValueCount("Uniform (float)", name, capacity, components, count) 77465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn || !CheckValueMult ("Uniform (float)", name, components, count)) 77565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 77665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 77765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Set value based on type 77865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn const int n = count / components; 77965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn switch(type) { 78065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case GL_FLOAT: 78165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glUniform1fv(var, n, values); 78265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn break; 78365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 78465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case GL_FLOAT_VEC2: 78565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glUniform2fv(var, n, values); 78665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn break; 78765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 78865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case GL_FLOAT_VEC3: 78965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glUniform3fv(var, n, values); 79065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn break; 79165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 79265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case GL_FLOAT_VEC4: 79365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glUniform4fv(var, n, values); 79465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn break; 79565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 79665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case GL_FLOAT_MAT2: 79765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glUniformMatrix2fv(var, n, GL_FALSE, values); 79865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn break; 79965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 80065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case GL_FLOAT_MAT3: 80165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glUniformMatrix3fv(var, n, GL_FALSE, values); 80265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn break; 80365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 80465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case GL_FLOAT_MAT4: 80565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glUniformMatrix4fv(var, n, GL_FALSE, values); 80665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn break; 80765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 80865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn default: 80965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 81065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn }; 81165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return !GLEnv::CheckGLError("Set Uniform Value"); 81265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 81365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 81465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 81565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 81665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool ShaderProgram::SetUniformValue(ProgramVar var, const std::vector<int>& values) { 81765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return SetUniformValue(var, &values[0], values.size()); 81865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 81965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 82065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool ShaderProgram::SetUniformValue(ProgramVar var, 82165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn const std::vector<float>& values) { 82265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return SetUniformValue(var, &values[0], values.size()); 82365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 82465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 82565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool ShaderProgram::SetUniformValue(const std::string& name, const Value& value) { 82665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (ValueIsFloat(value)) 82765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return SetUniformValue(GetUniform(name), GetFloatValue(value)); 82865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn else if (ValueIsInt(value)) 82965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return SetUniformValue(GetUniform(name), GetIntValue(value)); 83065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn else if (ValueIsFloatArray(value)) 83165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return SetUniformValue(GetUniform(name), GetFloatArrayValue(value), GetValueCount(value)); 83265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn else if (ValueIsIntArray(value)) 83365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return SetUniformValue(GetUniform(name), GetIntArrayValue(value), GetValueCount(value)); 83465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn else 83565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 83665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 83765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 83865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius RennValue ShaderProgram::GetUniformValue(const std::string& name) { 83965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ProgramVar var = GetUniform(name); 84065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (CheckUniformValid(var)) { 84165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Get uniform information 84265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GLint capacity; 84365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GLenum type; 84465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glGetActiveUniform(program_, IndexOfUniform(var), 0, NULL, &capacity, &type, NULL); 84565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!GLEnv::CheckGLError("Get Active Uniform")) { 84665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Get value based on type, and wrap in value object 84765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn switch(type) { 84865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case GL_INT: { 84965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn int value; 85065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glGetUniformiv(program_, var, &value); 85165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return !GLEnv::CheckGLError("GetVariableValue") ? MakeIntValue(value) 85265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn : MakeNullValue(); 85365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } break; 85465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 85565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case GL_INT_VEC2: { 85665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn int value[2]; 85765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glGetUniformiv(program_, var, &value[0]); 85865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return !GLEnv::CheckGLError("GetVariableValue") ? MakeIntArrayValue(value, 2) 85965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn : MakeNullValue(); 86065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } break; 86165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 86265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case GL_INT_VEC3: { 86365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn int value[3]; 86465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glGetUniformiv(program_, var, &value[0]); 86565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return !GLEnv::CheckGLError("GetVariableValue") ? MakeIntArrayValue(value, 3) 86665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn : MakeNullValue(); 86765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } break; 86865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 86965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case GL_INT_VEC4: { 87065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn int value[4]; 87165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glGetUniformiv(program_, var, &value[0]); 87265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return !GLEnv::CheckGLError("GetVariableValue") ? MakeIntArrayValue(value, 4) 87365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn : MakeNullValue(); 87465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } break; 87565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 87665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case GL_FLOAT: { 87765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn float value; 87865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glGetUniformfv(program_, var, &value); 87965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return !GLEnv::CheckGLError("GetVariableValue") ? MakeFloatValue(value) 88065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn : MakeNullValue(); 88165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } break; 88265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 88365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case GL_FLOAT_VEC2: { 88465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn float value[2]; 88565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glGetUniformfv(program_, var, &value[0]); 88665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return !GLEnv::CheckGLError("GetVariableValue") ? MakeFloatArrayValue(value, 2) 88765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn : MakeNullValue(); 88865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } break; 88965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 89065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case GL_FLOAT_VEC3: { 89165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn float value[3]; 89265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glGetUniformfv(program_, var, &value[0]); 89365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return !GLEnv::CheckGLError("GetVariableValue") ? MakeFloatArrayValue(value, 3) 89465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn : MakeNullValue(); 89565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } break; 89665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 89765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case GL_FLOAT_VEC4: { 89865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn float value[4]; 89965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glGetUniformfv(program_, var, &value[0]); 90065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return !GLEnv::CheckGLError("GetVariableValue") ? MakeFloatArrayValue(value, 4) 90165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn : MakeNullValue(); 90265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } break; 90365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 90465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case GL_FLOAT_MAT2: { 90565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn float value[4]; 90665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glGetUniformfv(program_, var, &value[0]); 90765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return !GLEnv::CheckGLError("GetVariableValue") ? MakeFloatArrayValue(value, 4) 90865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn : MakeNullValue(); 90965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } break; 91065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 91165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case GL_FLOAT_MAT3: { 91265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn float value[9]; 91365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glGetUniformfv(program_, var, &value[0]); 91465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return !GLEnv::CheckGLError("GetVariableValue") ? MakeFloatArrayValue(value, 9) 91565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn : MakeNullValue(); 91665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } break; 91765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 91865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case GL_FLOAT_MAT4: { 91965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn float value[16]; 92065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glGetUniformfv(program_, var, &value[0]); 92165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return !GLEnv::CheckGLError("GetVariableValue") ? MakeFloatArrayValue(value, 16) 92265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn : MakeNullValue(); 92365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } break; 92465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 92565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 92665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 92765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return MakeNullValue(); 92865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 92965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 93065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius RennGLuint ShaderProgram::IndexOfUniform(ProgramVar var) { 93165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return uniform_indices_[var]; 93265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 93365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 93465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn// Attributes ////////////////////////////////////////////////////////////////////////////////////// 93565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennint ShaderProgram::MaxAttributeCount() { 93665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GLint result; 93765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &result); 93865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return result; 93965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 94065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 94165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius RennProgramVar ShaderProgram::GetAttribute(const std::string& name) const { 94265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!IsExecutable()) { 94365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ALOGE("ShaderProgram: Error: Must link program before querying attributes!"); 94465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return -1; 94565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else if (name == PositionAttributeName() || name == TexCoordAttributeName()) { 94665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ALOGW("ShaderProgram: Attempting to overwrite internal vertex attribute '%s'!", name.c_str()); 94765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 94865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return glGetAttribLocation(program_, name.c_str()); 94965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 95065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 95165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool ShaderProgram::SetAttributeValues(ProgramVar var, 95265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn const VertexFrame* vbo, 95365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GLenum type, 95465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn int components, 95565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn int stride, 95665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn int offset, 95765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn bool normalize) { 95865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!CheckVarValid(var)) 95965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 96065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 96165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (vbo) { 96265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn VertexAttrib attrib; 96365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn attrib.is_const = false; 96465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn attrib.index = var; 96565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn attrib.components = components; 96665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn attrib.normalized = normalize; 96765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn attrib.stride = stride; 96865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn attrib.type = type; 96965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn attrib.vbo = vbo->GetVboId(); 97065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn attrib.offset = offset; 97165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 97265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return StoreAttribute(attrib); 97365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 97465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 97565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 97665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 97765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool ShaderProgram::SetAttributeValues(ProgramVar var, 97865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn const uint8_t* data, 97965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GLenum type, 98065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn int components, 98165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn int stride, 98265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn int offset, 98365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn bool normalize) { 98465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!CheckVarValid(var)) 98565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 98665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 98765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (data) { 98865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn VertexAttrib attrib; 98965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn attrib.is_const = false; 99065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn attrib.index = var; 99165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn attrib.components = components; 99265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn attrib.normalized = normalize; 99365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn attrib.stride = stride; 99465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn attrib.type = type; 99565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn attrib.values = data + offset; 99665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 99765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return StoreAttribute(attrib); 99865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 99965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 100065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 100165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 100265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool ShaderProgram::SetAttributeValues(ProgramVar var, 100365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn const std::vector<float>& data, 100465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn int components) { 100565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return SetAttributeValues(var, &data[0], data.size(), components); 100665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 100765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 100865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool ShaderProgram::SetAttributeValues(ProgramVar var, 100965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn const float* data, 101065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn int total, 101165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn int components) { 101265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!CheckVarValid(var)) 101365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 101465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 101565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Make sure the passed data vector has a valid size 101665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (total % components != 0) { 101765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ALOGE("ShaderProgram: Invalid attribute vector given! Specified a component " 101865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn "count of %d, but passed a non-multiple vector of size %d!", 101965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn components, total); 102065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 102165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 102265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 102365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Copy the data to a buffer we own 102465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn float* data_cpy = new float[total]; 102565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn memcpy(data_cpy, data, sizeof(float) * total); 102665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 102765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Store the attribute 102865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn VertexAttrib attrib; 102965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn attrib.is_const = false; 103065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn attrib.index = var; 103165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn attrib.components = components; 103265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn attrib.normalized = false; 103365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn attrib.stride = components * sizeof(float); 103465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn attrib.type = GL_FLOAT; 103565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn attrib.values = data_cpy; 103665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn attrib.owned_data = data_cpy; // Marks this for deletion later on 103765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 103865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return StoreAttribute(attrib); 103965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 104065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 104165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool ShaderProgram::StoreAttribute(VertexAttrib attrib) { 104265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (attrib.index >= 0) { 104365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn attrib_values_[attrib.index] = attrib; 104465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return true; 104565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 104665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 104765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 104865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 104965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool ShaderProgram::PushAttributes() { 105065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn for (VertexAttribMap::const_iterator iter = attrib_values_.begin(); 105165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn iter != attrib_values_.end(); 105265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ++iter) { 105365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn const VertexAttrib& attrib = iter->second; 105465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 105565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (attrib.is_const) { 105665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Set constant attribute values (must be specified as host values) 105765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!attrib.values) 105865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 105965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 106065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn const float* values = reinterpret_cast<const float*>(attrib.values); 106165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn switch (attrib.components) { 106265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case 1: glVertexAttrib1fv(attrib.index, values); break; 106365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case 2: glVertexAttrib2fv(attrib.index, values); break; 106465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case 3: glVertexAttrib3fv(attrib.index, values); break; 106565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn case 4: glVertexAttrib4fv(attrib.index, values); break; 106665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn default: return false; 106765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 106865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glDisableVertexAttribArray(attrib.index); 106965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else { 107065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Set per-vertex values 107165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (attrib.values) { 107265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Make sure no buffer is bound and set attribute 107365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glBindBuffer(GL_ARRAY_BUFFER, 0); 107465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 107565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glVertexAttribPointer(attrib.index, 107665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn attrib.components, 107765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn attrib.type, 107865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn attrib.normalized, 107965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn attrib.stride, 108065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn attrib.values); 108165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else if (attrib.vbo) { 108265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Bind VBO and set attribute 108365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glBindBuffer(GL_ARRAY_BUFFER, attrib.vbo); 108465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 108565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glVertexAttribPointer(attrib.index, 108665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn attrib.components, 108765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn attrib.type, 108865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn attrib.normalized, 108965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn attrib.stride, 109065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn reinterpret_cast<const void*>(attrib.offset)); 109165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else { 109265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 109365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 109465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glEnableVertexAttribArray(attrib.index); 109565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 109665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 109765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Make sure everything worked 109865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (GLEnv::CheckGLError("Pushing Vertex Attributes")) 109965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 110065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 110165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 110265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return true; 110365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 110465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 110565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool ShaderProgram::PopAttributes() { 110665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Disable vertex attributes 110765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn for (VertexAttribMap::const_iterator iter = attrib_values_.begin(); 110865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn iter != attrib_values_.end(); 110965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ++iter) { 111065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glDisableVertexAttribArray(iter->second.index); 111165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 111265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Unbind buffer: Very important as this greatly affects what glVertexAttribPointer does! 111365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glBindBuffer(GL_ARRAY_BUFFER, 0); 111465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return !GLEnv::CheckGLError("Popping Vertex Attributes"); 111565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 111665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 111765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennvoid ShaderProgram::SetVertexCount(int count) { 111865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn vertex_count_ = count; 111965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 112065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 112165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} // namespace filterfw 112265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} // namespace android 1123