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/gl_env.h" 2065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn#include "core/gl_frame.h" 2165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn#include "core/shader_program.h" 2265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 2365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn#include <vector> 2465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 2565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennnamespace android { 2665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennnamespace filterfw { 2765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 2865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennstatic const int kIdentityShaderKey = 1; 2965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 3065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn// 3165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn// A GLFrame stores pixel data on the GPU. It uses two kinds of GL data 3265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn// containers for this: Textures and Frame Buffer Objects (FBOs). Textures are 3365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn// used whenever pixel data needs to be read into a shader or the host program, 3465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn// and when pixel data is uploaded to a GLFrame. The FBO is used as a rendering 3565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn// target for shaders. 3665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn// 3765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 3865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius RennGLFrame::GLFrame(GLEnv* gl_env) 3965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn : gl_env_(gl_env), 4065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn width_(0), 4165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn height_(0), 4265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn vp_x_(0), 4365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn vp_y_(0), 4465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn vp_width_(0), 4565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn vp_height_(0), 4665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn texture_id_(0), 4765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn fbo_id_(0), 4865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn texture_target_(GL_TEXTURE_2D), 4965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn texture_state_(kStateUninitialized), 5065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn fbo_state_(kStateUninitialized), 5165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn owns_texture_(false), 5265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn owns_fbo_(false) { 5365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn SetDefaultTexParameters(); 5465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 5565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 5665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool GLFrame::Init(int width, int height) { 5765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Make sure we haven't been initialized already 5865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (width_ == 0 && height_ == 0) { 5965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn InitDimensions(width, height); 6065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return true; 6165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 6265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 6365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 6465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 6565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool GLFrame::InitWithTexture(GLint texture_id, int width, int height) { 6665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn texture_id_ = texture_id; 6765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn texture_state_ = glIsTexture(texture_id) ? kStateComplete : kStateGenerated; 6865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn InitDimensions(width, height); 6965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return true; 7065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 7165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 7265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool GLFrame::InitWithFbo(GLint fbo_id, int width, int height) { 7365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn fbo_id_ = fbo_id; 7465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn fbo_state_ = glIsFramebuffer(fbo_id) ? kStateComplete : kStateGenerated; 7565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn texture_state_ = kStateUnmanaged; 7665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn InitDimensions(width, height); 7765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return true; 7865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 7965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 8065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool GLFrame::InitWithExternalTexture() { 8165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn texture_target_ = GL_TEXTURE_EXTERNAL_OES; 8265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn width_ = 0; 8365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn height_ = 0; 8465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return GenerateTextureName(); 8565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 8665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 8765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennvoid GLFrame::InitDimensions(int width, int height) { 8865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn width_ = width; 8965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn height_ = height; 9065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn vp_width_ = width; 9165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn vp_height_ = height; 9265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 9365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 9465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius RennGLFrame::~GLFrame() { 9565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Delete texture 9665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (owns_texture_) { 9765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Bind FBO so that texture is unbound from it during deletion 9865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (fbo_state_ == kStateComplete) { 9965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glBindFramebuffer(GL_FRAMEBUFFER, fbo_id_); 10065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 10165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glDeleteTextures(1, &texture_id_); 10265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 10365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 10465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Delete FBO 10565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (owns_fbo_) { 10665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glDeleteFramebuffers(1, &fbo_id_); 10765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 10865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 10965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 11065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool GLFrame::GenerateMipMap() { 11165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (FocusTexture()) { 11265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glGenerateMipmap(GL_TEXTURE_2D); 11365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return !GLEnv::CheckGLError("Generating MipMap!"); 11465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 11565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 11665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 11765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 11865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool GLFrame::SetTextureParameter(GLenum pname, GLint value) { 11965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (value != tex_params_[pname]) { 12065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (FocusTexture()) { 12165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glTexParameteri(GL_TEXTURE_2D, pname, value); 12265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!GLEnv::CheckGLError("Setting texture parameter!")) { 12365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn tex_params_[pname] = value; 12465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return true; 12565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 12665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 12765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else { 12865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return true; 12965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 13065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 13165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 13265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 13365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool GLFrame::UpdateTexParameters() { 13465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, tex_params_[GL_TEXTURE_MAG_FILTER]); 13565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, tex_params_[GL_TEXTURE_MIN_FILTER]); 13665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, tex_params_[GL_TEXTURE_WRAP_S]); 13765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, tex_params_[GL_TEXTURE_WRAP_T]); 13865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return !GLEnv::CheckGLError("Resetting texture parameters!"); 13965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 14065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 14165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool GLFrame::TexParametersModifed() { 14265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return tex_params_[GL_TEXTURE_MAG_FILTER] != GL_LINEAR 14365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn || tex_params_[GL_TEXTURE_MIN_FILTER] != GL_LINEAR 14465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn || tex_params_[GL_TEXTURE_WRAP_S] != GL_CLAMP_TO_EDGE 14565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn || tex_params_[GL_TEXTURE_WRAP_T] != GL_CLAMP_TO_EDGE; 14665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 14765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 14865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennvoid GLFrame::SetDefaultTexParameters() { 14965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn tex_params_[GL_TEXTURE_MAG_FILTER] = GL_LINEAR; 15065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn tex_params_[GL_TEXTURE_MIN_FILTER] = GL_LINEAR; 15165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn tex_params_[GL_TEXTURE_WRAP_S] = GL_CLAMP_TO_EDGE; 15265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn tex_params_[GL_TEXTURE_WRAP_T] = GL_CLAMP_TO_EDGE; 15365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 15465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 15565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool GLFrame::ResetTexParameters() { 15665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (TexParametersModifed()) { 15765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (BindTexture()) { 15865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn SetDefaultTexParameters(); 15965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return UpdateTexParameters(); 16065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 16165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 16265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 16365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return true; 16465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 16565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 16665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool GLFrame::CopyDataTo(uint8_t* buffer, int size) { 16765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return (size >= Size()) 16865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ? CopyPixelsTo(buffer) 16965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn : false; 17065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 17165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 17265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool GLFrame::CopyPixelsTo(uint8_t* buffer) { 17365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Use one of the pixel reading methods below, ordered from most 17465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // efficient to least efficient. 17565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (fbo_state_ == kStateComplete) 17665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return ReadFboPixels(buffer); 17765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn else if (texture_state_ == kStateComplete) 17865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return ReadTexturePixels(buffer); 17965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn else 18065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 18165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 18265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 18365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool GLFrame::WriteData(const uint8_t* data, int data_size) { 18465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return (data_size == Size()) ? UploadTexturePixels(data) : false; 18565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 18665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 18765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool GLFrame::SetViewport(int x, int y, int width, int height) { 18865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn vp_x_ = x; 18965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn vp_y_ = y; 19065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn vp_width_ = width; 19165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn vp_height_ = height; 19265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return true; 19365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 19465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 19565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius RennGLFrame* GLFrame::Clone() const { 19665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GLFrame* target = new GLFrame(gl_env_); 19765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn target->Init(width_, height_); 19865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn target->CopyPixelsFrom(this); 19965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return target; 20065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 20165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 20265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool GLFrame::CopyPixelsFrom(const GLFrame* frame) { 20365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (frame == this) { 20465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return true; 20565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else if (frame && frame->width_ == width_ && frame->height_ == height_) { 20665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn std::vector<const GLFrame*> sources; 20765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn sources.push_back(frame); 20865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GetIdentity()->Process(sources, this); 20965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return true; 21065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 21165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 21265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 21365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 21465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennint GLFrame::Size() const { 21565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return width_ * height_ * 4; 21665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 21765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 21865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius RennShaderProgram* GLFrame::GetIdentity() const { 21965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ShaderProgram* stored_shader = gl_env_->ShaderWithKey(kIdentityShaderKey); 22065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!stored_shader) { 22165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn stored_shader = ShaderProgram::CreateIdentity(gl_env_); 22265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn gl_env_->AttachShader(kIdentityShaderKey, stored_shader); 22365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 22465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return stored_shader; 22565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 22665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 22765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool GLFrame::BindFrameBuffer() const { 22865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Bind the FBO 22965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glBindFramebuffer(GL_FRAMEBUFFER, fbo_id_); 23065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (GLEnv::CheckGLError("FBO Binding")) return false; 23165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 23265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Set viewport 23365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glViewport(vp_x_, vp_y_, vp_width_, vp_height_); 23465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (GLEnv::CheckGLError("ViewPort Setup")) return false; 23565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 23665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return true; 23765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 23865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 23965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool GLFrame::FocusFrameBuffer() { 24065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Create texture backing if necessary 24165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (texture_state_ == kStateUninitialized) { 24265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!GenerateTextureName()) 24365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 24465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 24565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 24665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Create and bind FBO to texture if necessary 24765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (fbo_state_ != kStateComplete) { 24865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!GenerateFboName() || !AttachTextureToFbo()) 24965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 25065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 25165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 25265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // And bind it. 25365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return BindFrameBuffer(); 25465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 25565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 25665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool GLFrame::BindTexture() const { 25765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glBindTexture(GL_TEXTURE_2D, texture_id_); 25865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return !GLEnv::CheckGLError("Texture Binding"); 25965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 26065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 26165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius RennGLuint GLFrame::GetTextureId() const { 26265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return texture_id_; 26365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 26465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 26565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn// Returns the held FBO id. Only call this if the GLFrame holds an FBO. You 26665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn// can check this by calling HoldsFbo(). 26765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius RennGLuint GLFrame::GetFboId() const { 26865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return fbo_id_; 26965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 27065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 27165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool GLFrame::FocusTexture() { 27265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Make sure we have a texture 27365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!GenerateTextureName()) 27465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 27565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 27665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Bind the texture 27765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!BindTexture()) 27865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 27965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 28065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return !GLEnv::CheckGLError("Texture Binding"); 28165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 28265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 28365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool GLFrame::GenerateTextureName() { 28465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (texture_state_ == kStateUninitialized) { 28565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Make sure texture not in use already 28665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (glIsTexture(texture_id_)) { 28765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ALOGE("GLFrame: Cannot generate texture id %d, as it is in use already!", texture_id_); 28865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 28965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 29065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 29165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Generate the texture 29265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glGenTextures (1, &texture_id_); 29365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (GLEnv::CheckGLError("Texture Generation")) 29465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 29565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn texture_state_ = kStateGenerated; 29665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn owns_texture_ = true; 29765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 29865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 29965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return true; 30065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 30165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 30265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool GLFrame::AllocateTexture() { 30365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Allocate or re-allocate (if texture was deleted externally). 30465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (texture_state_ == kStateGenerated || TextureWasDeleted()) { 30565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn LOG_FRAME("GLFrame: Allocating texture: %d", texture_id_); 30665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glBindTexture(GL_TEXTURE_2D, texture_id_); 30765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glTexImage2D(GL_TEXTURE_2D, 30865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 0, 30965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GL_RGBA, 31065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn width_, 31165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn height_, 31265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 0, 31365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GL_RGBA, 31465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GL_UNSIGNED_BYTE, 31565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn NULL); 31665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!GLEnv::CheckGLError("Texture Allocation")) { 31765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn UpdateTexParameters(); 31865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn texture_state_ = kStateComplete; 31965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 32065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 32165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return texture_state_ == kStateComplete; 32265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 32365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 32465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool GLFrame::TextureWasDeleted() const { 32565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return texture_state_ == kStateComplete && !glIsTexture(texture_id_); 32665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 32765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 32865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool GLFrame::GenerateFboName() { 32965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (fbo_state_ == kStateUninitialized) { 33065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Make sure FBO not in use already 33165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (glIsFramebuffer(fbo_id_)) { 33265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ALOGE("GLFrame: Cannot generate FBO id %d, as it is in use already!", fbo_id_); 33365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 33465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 33565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 33665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Create FBO 33765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glGenFramebuffers(1, &fbo_id_); 33865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (GLEnv::CheckGLError("FBO Generation")) 33965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 34065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn fbo_state_ = kStateGenerated; 34165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn owns_fbo_ = true; 34265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 34365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 34465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return true; 34565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 34665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 34765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool GLFrame::ReadFboPixels(uint8_t* pixels) const { 34865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (fbo_state_ == kStateComplete) { 34965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn BindFrameBuffer(); 35065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glReadPixels(0, 35165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 0, 35265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn width_, 35365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn height_, 35465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GL_RGBA, 35565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GL_UNSIGNED_BYTE, 35665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn pixels); 35765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return !GLEnv::CheckGLError("FBO Pixel Readout"); 35865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 35965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 36065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 36165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 36265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool GLFrame::ReadTexturePixels(uint8_t* pixels) const { 36365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Read pixels from texture if we do not have an FBO 36465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // NOTE: OpenGL ES does NOT support glGetTexImage() for reading out texture 36565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // data. The only way for us to get texture data is to create a new FBO and 36665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // render the current texture frame into it. As this is quite inefficient, 36765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // and unnecessary (this can only happen if the user is reading out data 36865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // that was just set, and not run through a filter), we warn the user about 36965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // this here. 37065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ALOGW("Warning: Reading pixel data from unfiltered GL frame. This is highly " 37165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn "inefficient. Please consider using your original pixel buffer " 37265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn "instead!"); 37365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 37465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Create source frame set (unfortunately this requires an ugly const-cast, 37565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // as we need to wrap ourselves in a frame-set. Still, as this set is used 37665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // as input only, we are certain we will not be modified). 37765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn std::vector<const GLFrame*> sources; 37865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn sources.push_back(this); 37965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 38065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Create target frame 38165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GLFrame target(gl_env_); 38265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn target.Init(width_, height_); 38365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 38465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Render the texture to the target 38565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GetIdentity()->Process(sources, &target); 38665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 38765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Get the pixel data 38865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return target.ReadFboPixels(pixels); 38965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 39065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 39165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool GLFrame::AttachTextureToFbo() { 39265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Check FBO and texture state. We do not do anything if we are not managing the texture. 39365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (fbo_state_ == kStateComplete || texture_state_ == kStateUnmanaged) { 39465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return true; 39565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else if (fbo_state_ != kStateGenerated) { 39665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn ALOGE("Attempting to attach texture to FBO with no FBO in place!"); 39765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 39865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 39965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 40065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // If texture has been generated, make sure it is allocated. 40165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!AllocateTexture()) 40265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 40365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 40465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Bind the frame buffer, and check if we it is already bound 40565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glBindFramebuffer(GL_FRAMEBUFFER, fbo_id_); 40665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 40765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Bind the texture to the frame buffer 40865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn LOG_FRAME("Attaching tex %d w %d h %d to fbo %d", texture_id_, width_, height_, fbo_id_); 40965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glFramebufferTexture2D(GL_FRAMEBUFFER, 41065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GL_COLOR_ATTACHMENT0, 41165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GL_TEXTURE_2D, 41265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn texture_id_, 41365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 0); 41465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 41565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Cleanup 41665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glBindTexture(GL_TEXTURE_2D, 0); 41765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glBindFramebuffer(GL_FRAMEBUFFER, 0); 41865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 41965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (GLEnv::CheckGLError("Texture Binding to FBO")) 42065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 42165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn else 42265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn fbo_state_ = kStateComplete; 42365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 42465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return true; 42565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 42665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 42765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool GLFrame::ReattachTextureToFbo() { 42865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return (fbo_state_ == kStateGenerated) ? AttachTextureToFbo() : true; 42965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 43065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 43165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool GLFrame::DetachTextureFromFbo() { 43265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (fbo_state_ == kStateComplete && texture_state_ == kStateComplete) { 43365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn LOG_FRAME("Detaching tex %d w %d h %d from fbo %d", texture_id_, width_, height_, fbo_id_); 43465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glBindFramebuffer(GL_FRAMEBUFFER, fbo_id_); 43565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glFramebufferTexture2D(GL_FRAMEBUFFER, 43665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GL_COLOR_ATTACHMENT0, 43765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GL_TEXTURE_2D, 43865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 0, 43965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 0); 44065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (GLEnv::CheckGLError("Detaching texture to FBO")) 44165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 44265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn else 44365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn fbo_state_ = kStateGenerated; 44465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 44565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return true; 44665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 44765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 44865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool GLFrame::UploadTexturePixels(const uint8_t* pixels) { 44965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Bind the texture object 45065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn FocusTexture(); 45165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 45265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Load mipmap level 0 45365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 45465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); 45565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 45665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Set the user specified texture parameters 45765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn UpdateTexParameters(); 45865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 45965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (GLEnv::CheckGLError("Texture Pixel Upload")) 46065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return false; 46165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 46265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn texture_state_ = kStateComplete; 46365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return true; 46465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 46565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 46665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} // namespace filterfw 46765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} // namespace android 468