130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni/* 230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * Copyright (C) 2011 The Android Open Source Project 330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * 430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * Licensed under the Apache License, Version 2.0 (the "License"); 530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * you may not use this file except in compliance with the License. 630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * You may obtain a copy of the License at 730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * 830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * http://www.apache.org/licenses/LICENSE-2.0 930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * 1030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * Unless required by applicable law or agreed to in writing, software 1130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * distributed under the License is distributed on an "AS IS" BASIS, 1230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * See the License for the specific language governing permissions and 1430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * limitations under the License. 1530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni */ 1630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 1730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni#include "base/logging.h" 1830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 1930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni#include "core/gl_env.h" 2030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni#include "core/gl_frame.h" 2130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni#include "core/shader_program.h" 2230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 23e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvala#include <vector> 24e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvala 2530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroninamespace android { 2630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroninamespace filterfw { 2730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 28511360e61650864ea22a171159efe073c80d0cdbMarius Rennstatic const int kIdentityShaderKey = 1; 29511360e61650864ea22a171159efe073c80d0cdbMarius Renn 3030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// 3130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// A GLFrame stores pixel data on the GPU. It uses two kinds of GL data 3230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// containers for this: Textures and Frame Buffer Objects (FBOs). Textures are 3330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// used whenever pixel data needs to be read into a shader or the host program, 3430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// and when pixel data is uploaded to a GLFrame. The FBO is used as a rendering 3530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// target for shaders. 3630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// 3730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 38511360e61650864ea22a171159efe073c80d0cdbMarius RennGLFrame::GLFrame(GLEnv* gl_env) 39511360e61650864ea22a171159efe073c80d0cdbMarius Renn : gl_env_(gl_env), 40511360e61650864ea22a171159efe073c80d0cdbMarius Renn width_(0), 4130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni height_(0), 4230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni vp_x_(0), 4330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni vp_y_(0), 4430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni vp_width_(0), 4530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni vp_height_(0), 4630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni texture_id_(0), 4730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni fbo_id_(0), 4830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni texture_target_(GL_TEXTURE_2D), 4930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni texture_state_(kStateUninitialized), 5030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni fbo_state_(kStateUninitialized), 51776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn owns_texture_(false), 52776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn owns_fbo_(false) { 53f5ae8eafa7605c6593f62f873b62cb64a3254db3Marius Renn SetDefaultTexParameters(); 5430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 5530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 5630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::Init(int width, int height) { 5730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Make sure we haven't been initialized already 5830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (width_ == 0 && height_ == 0) { 5930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni InitDimensions(width, height); 6030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 6130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 6230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 6330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 6430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 65776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Rennbool GLFrame::InitWithTexture(GLint texture_id, int width, int height) { 6630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni texture_id_ = texture_id; 67776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn texture_state_ = glIsTexture(texture_id) ? kStateComplete : kStateGenerated; 6830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni InitDimensions(width, height); 6930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 7030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 7130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 72776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Rennbool GLFrame::InitWithFbo(GLint fbo_id, int width, int height) { 7330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni fbo_id_ = fbo_id; 74776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn fbo_state_ = glIsFramebuffer(fbo_id) ? kStateComplete : kStateGenerated; 7592568796d043c794553e5bcaa797c906899e71f0Marius Renn texture_state_ = kStateUnmanaged; 7630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni InitDimensions(width, height); 7730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 7830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 7930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 8030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::InitWithExternalTexture() { 8130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni texture_target_ = GL_TEXTURE_EXTERNAL_OES; 8230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni width_ = 0; 8330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni height_ = 0; 8492568796d043c794553e5bcaa797c906899e71f0Marius Renn return GenerateTextureName(); 8530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 8630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 8730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronivoid GLFrame::InitDimensions(int width, int height) { 8830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni width_ = width; 8930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni height_ = height; 9030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni vp_width_ = width; 9130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni vp_height_ = height; 9230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 9330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 9430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo CarceroniGLFrame::~GLFrame() { 95776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn // Delete texture 96776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn if (owns_texture_) { 97776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn // Bind FBO so that texture is unbound from it during deletion 98776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn if (fbo_state_ == kStateComplete) { 99776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn glBindFramebuffer(GL_FRAMEBUFFER, fbo_id_); 100776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn } 101776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn glDeleteTextures(1, &texture_id_); 102776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn } 103776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn 104776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn // Delete FBO 105776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn if (owns_fbo_) { 106776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn glDeleteFramebuffers(1, &fbo_id_); 10730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 10830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 10930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 11030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::GenerateMipMap() { 111fb7c020acdd0fb38c9d2b6750d904b64cc78458dWei Hua if (FocusTexture()) { 11230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glGenerateMipmap(GL_TEXTURE_2D); 11330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return !GLEnv::CheckGLError("Generating MipMap!"); 11430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 11530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 11630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 11730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 11830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::SetTextureParameter(GLenum pname, GLint value) { 119f5ae8eafa7605c6593f62f873b62cb64a3254db3Marius Renn if (value != tex_params_[pname]) { 120f5ae8eafa7605c6593f62f873b62cb64a3254db3Marius Renn if (FocusTexture()) { 121f5ae8eafa7605c6593f62f873b62cb64a3254db3Marius Renn glTexParameteri(GL_TEXTURE_2D, pname, value); 122f5ae8eafa7605c6593f62f873b62cb64a3254db3Marius Renn if (!GLEnv::CheckGLError("Setting texture parameter!")) { 123f5ae8eafa7605c6593f62f873b62cb64a3254db3Marius Renn tex_params_[pname] = value; 124f5ae8eafa7605c6593f62f873b62cb64a3254db3Marius Renn return true; 125f5ae8eafa7605c6593f62f873b62cb64a3254db3Marius Renn } 126f5ae8eafa7605c6593f62f873b62cb64a3254db3Marius Renn } 127f5ae8eafa7605c6593f62f873b62cb64a3254db3Marius Renn } else { 128f5ae8eafa7605c6593f62f873b62cb64a3254db3Marius Renn return true; 12930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 13030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 13130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 13230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 133f5ae8eafa7605c6593f62f873b62cb64a3254db3Marius Rennbool GLFrame::UpdateTexParameters() { 134f5ae8eafa7605c6593f62f873b62cb64a3254db3Marius Renn glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, tex_params_[GL_TEXTURE_MAG_FILTER]); 135f5ae8eafa7605c6593f62f873b62cb64a3254db3Marius Renn glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, tex_params_[GL_TEXTURE_MIN_FILTER]); 136f5ae8eafa7605c6593f62f873b62cb64a3254db3Marius Renn glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, tex_params_[GL_TEXTURE_WRAP_S]); 137f5ae8eafa7605c6593f62f873b62cb64a3254db3Marius Renn glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, tex_params_[GL_TEXTURE_WRAP_T]); 138f5ae8eafa7605c6593f62f873b62cb64a3254db3Marius Renn return !GLEnv::CheckGLError("Resetting texture parameters!"); 139f5ae8eafa7605c6593f62f873b62cb64a3254db3Marius Renn} 140f5ae8eafa7605c6593f62f873b62cb64a3254db3Marius Renn 141f5ae8eafa7605c6593f62f873b62cb64a3254db3Marius Rennbool GLFrame::TexParametersModifed() { 142f5ae8eafa7605c6593f62f873b62cb64a3254db3Marius Renn return tex_params_[GL_TEXTURE_MAG_FILTER] != GL_LINEAR 143f5ae8eafa7605c6593f62f873b62cb64a3254db3Marius Renn || tex_params_[GL_TEXTURE_MIN_FILTER] != GL_LINEAR 144f5ae8eafa7605c6593f62f873b62cb64a3254db3Marius Renn || tex_params_[GL_TEXTURE_WRAP_S] != GL_CLAMP_TO_EDGE 145f5ae8eafa7605c6593f62f873b62cb64a3254db3Marius Renn || tex_params_[GL_TEXTURE_WRAP_T] != GL_CLAMP_TO_EDGE; 146f5ae8eafa7605c6593f62f873b62cb64a3254db3Marius Renn} 147f5ae8eafa7605c6593f62f873b62cb64a3254db3Marius Renn 148f5ae8eafa7605c6593f62f873b62cb64a3254db3Marius Rennvoid GLFrame::SetDefaultTexParameters() { 149f5ae8eafa7605c6593f62f873b62cb64a3254db3Marius Renn tex_params_[GL_TEXTURE_MAG_FILTER] = GL_LINEAR; 150f5ae8eafa7605c6593f62f873b62cb64a3254db3Marius Renn tex_params_[GL_TEXTURE_MIN_FILTER] = GL_LINEAR; 151f5ae8eafa7605c6593f62f873b62cb64a3254db3Marius Renn tex_params_[GL_TEXTURE_WRAP_S] = GL_CLAMP_TO_EDGE; 152f5ae8eafa7605c6593f62f873b62cb64a3254db3Marius Renn tex_params_[GL_TEXTURE_WRAP_T] = GL_CLAMP_TO_EDGE; 153f5ae8eafa7605c6593f62f873b62cb64a3254db3Marius Renn} 154f5ae8eafa7605c6593f62f873b62cb64a3254db3Marius Renn 155f5ae8eafa7605c6593f62f873b62cb64a3254db3Marius Rennbool GLFrame::ResetTexParameters() { 156f5ae8eafa7605c6593f62f873b62cb64a3254db3Marius Renn if (TexParametersModifed()) { 15733164fee278e106cc5d0493a1c184f208e9d273fMarius Renn if (BindTexture()) { 158f5ae8eafa7605c6593f62f873b62cb64a3254db3Marius Renn SetDefaultTexParameters(); 159f5ae8eafa7605c6593f62f873b62cb64a3254db3Marius Renn return UpdateTexParameters(); 16033164fee278e106cc5d0493a1c184f208e9d273fMarius Renn } 161f5ae8eafa7605c6593f62f873b62cb64a3254db3Marius Renn return false; 16233164fee278e106cc5d0493a1c184f208e9d273fMarius Renn } 163f5ae8eafa7605c6593f62f873b62cb64a3254db3Marius Renn return true; 16433164fee278e106cc5d0493a1c184f208e9d273fMarius Renn} 16533164fee278e106cc5d0493a1c184f208e9d273fMarius Renn 166e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvalabool GLFrame::CopyDataTo(uint8_t* buffer, int size) { 16730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return (size >= Size()) 16830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni ? CopyPixelsTo(buffer) 16930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni : false; 17030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 17130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 172e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvalabool GLFrame::CopyPixelsTo(uint8_t* buffer) { 17315ebdcc40023b94f8f7184b8c4ea47acc8d207c6Marius Renn // Use one of the pixel reading methods below, ordered from most 17415ebdcc40023b94f8f7184b8c4ea47acc8d207c6Marius Renn // efficient to least efficient. 17515ebdcc40023b94f8f7184b8c4ea47acc8d207c6Marius Renn if (fbo_state_ == kStateComplete) 17630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return ReadFboPixels(buffer); 17715ebdcc40023b94f8f7184b8c4ea47acc8d207c6Marius Renn else if (texture_state_ == kStateComplete) 17815ebdcc40023b94f8f7184b8c4ea47acc8d207c6Marius Renn return ReadTexturePixels(buffer); 17930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni else 18030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 18130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 18230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 183e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvalabool GLFrame::WriteData(const uint8_t* data, int data_size) { 18430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return (data_size == Size()) ? UploadTexturePixels(data) : false; 18530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 18630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 18730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::SetViewport(int x, int y, int width, int height) { 18830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni vp_x_ = x; 18930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni vp_y_ = y; 19030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni vp_width_ = width; 19130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni vp_height_ = height; 19230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 19330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 19430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 19530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo CarceroniGLFrame* GLFrame::Clone() const { 196511360e61650864ea22a171159efe073c80d0cdbMarius Renn GLFrame* target = new GLFrame(gl_env_); 19730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni target->Init(width_, height_); 19830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni target->CopyPixelsFrom(this); 19930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return target; 20030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 20130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 20230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::CopyPixelsFrom(const GLFrame* frame) { 20330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (frame == this) { 20430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 20530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } else if (frame && frame->width_ == width_ && frame->height_ == height_) { 206e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvala std::vector<const GLFrame*> sources; 20730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni sources.push_back(frame); 20830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni GetIdentity()->Process(sources, this); 20930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 21030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 21130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 21230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 21330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 21430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniint GLFrame::Size() const { 21530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return width_ * height_ * 4; 21630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 21730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 21830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo CarceroniShaderProgram* GLFrame::GetIdentity() const { 219511360e61650864ea22a171159efe073c80d0cdbMarius Renn ShaderProgram* stored_shader = gl_env_->ShaderWithKey(kIdentityShaderKey); 220511360e61650864ea22a171159efe073c80d0cdbMarius Renn if (!stored_shader) { 221511360e61650864ea22a171159efe073c80d0cdbMarius Renn stored_shader = ShaderProgram::CreateIdentity(gl_env_); 222511360e61650864ea22a171159efe073c80d0cdbMarius Renn gl_env_->AttachShader(kIdentityShaderKey, stored_shader); 223511360e61650864ea22a171159efe073c80d0cdbMarius Renn } 224511360e61650864ea22a171159efe073c80d0cdbMarius Renn return stored_shader; 22530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 22630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 22730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::BindFrameBuffer() const { 22830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Bind the FBO 22930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glBindFramebuffer(GL_FRAMEBUFFER, fbo_id_); 23030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (GLEnv::CheckGLError("FBO Binding")) return false; 23130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 23230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Set viewport 23330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glViewport(vp_x_, vp_y_, vp_width_, vp_height_); 23430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (GLEnv::CheckGLError("ViewPort Setup")) return false; 23530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 23630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 23730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 23830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 23930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::FocusFrameBuffer() { 24030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Create texture backing if necessary 24130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (texture_state_ == kStateUninitialized) { 24292568796d043c794553e5bcaa797c906899e71f0Marius Renn if (!GenerateTextureName()) 24330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 24430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 24530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 24630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Create and bind FBO to texture if necessary 247776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn if (fbo_state_ != kStateComplete) { 24892568796d043c794553e5bcaa797c906899e71f0Marius Renn if (!GenerateFboName() || !AttachTextureToFbo()) 24930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 25030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 25130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 25230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // And bind it. 25330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return BindFrameBuffer(); 25430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 25530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 25630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::BindTexture() const { 25730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glBindTexture(GL_TEXTURE_2D, texture_id_); 25830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return !GLEnv::CheckGLError("Texture Binding"); 25930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 26030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 26130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo CarceroniGLuint GLFrame::GetTextureId() const { 26230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return texture_id_; 26330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 26430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 26530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// Returns the held FBO id. Only call this if the GLFrame holds an FBO. You 26630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// can check this by calling HoldsFbo(). 26730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo CarceroniGLuint GLFrame::GetFboId() const { 26830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return fbo_id_; 26930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 27030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 27130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::FocusTexture() { 27230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Make sure we have a texture 27392568796d043c794553e5bcaa797c906899e71f0Marius Renn if (!GenerateTextureName()) 27430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 27530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 27630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Bind the texture 27730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (!BindTexture()) 27830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 27930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 28030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return !GLEnv::CheckGLError("Texture Binding"); 28130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 28230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 28392568796d043c794553e5bcaa797c906899e71f0Marius Rennbool GLFrame::GenerateTextureName() { 28430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (texture_state_ == kStateUninitialized) { 28530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Make sure texture not in use already 28630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (glIsTexture(texture_id_)) { 28730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni LOGE("GLFrame: Cannot generate texture id %d, as it is in use already!", texture_id_); 28830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 28930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 29030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 29130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Generate the texture 29230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glGenTextures (1, &texture_id_); 29330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (GLEnv::CheckGLError("Texture Generation")) 29430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 29530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni texture_state_ = kStateGenerated; 296776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn owns_texture_ = true; 29730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 29830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 29930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 30030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 30130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 30292568796d043c794553e5bcaa797c906899e71f0Marius Rennbool GLFrame::AllocateTexture() { 30392568796d043c794553e5bcaa797c906899e71f0Marius Renn // Allocate or re-allocate (if texture was deleted externally). 30492568796d043c794553e5bcaa797c906899e71f0Marius Renn if (texture_state_ == kStateGenerated || TextureWasDeleted()) { 30592568796d043c794553e5bcaa797c906899e71f0Marius Renn LOG_FRAME("GLFrame: Allocating texture: %d", texture_id_); 30692568796d043c794553e5bcaa797c906899e71f0Marius Renn glBindTexture(GL_TEXTURE_2D, texture_id_); 30792568796d043c794553e5bcaa797c906899e71f0Marius Renn glTexImage2D(GL_TEXTURE_2D, 30892568796d043c794553e5bcaa797c906899e71f0Marius Renn 0, 30992568796d043c794553e5bcaa797c906899e71f0Marius Renn GL_RGBA, 31092568796d043c794553e5bcaa797c906899e71f0Marius Renn width_, 31192568796d043c794553e5bcaa797c906899e71f0Marius Renn height_, 31292568796d043c794553e5bcaa797c906899e71f0Marius Renn 0, 31392568796d043c794553e5bcaa797c906899e71f0Marius Renn GL_RGBA, 31492568796d043c794553e5bcaa797c906899e71f0Marius Renn GL_UNSIGNED_BYTE, 31592568796d043c794553e5bcaa797c906899e71f0Marius Renn NULL); 31692568796d043c794553e5bcaa797c906899e71f0Marius Renn if (!GLEnv::CheckGLError("Texture Allocation")) { 31792568796d043c794553e5bcaa797c906899e71f0Marius Renn UpdateTexParameters(); 31892568796d043c794553e5bcaa797c906899e71f0Marius Renn texture_state_ = kStateComplete; 31992568796d043c794553e5bcaa797c906899e71f0Marius Renn } 32092568796d043c794553e5bcaa797c906899e71f0Marius Renn } 32192568796d043c794553e5bcaa797c906899e71f0Marius Renn return texture_state_ == kStateComplete; 32292568796d043c794553e5bcaa797c906899e71f0Marius Renn} 32392568796d043c794553e5bcaa797c906899e71f0Marius Renn 32492568796d043c794553e5bcaa797c906899e71f0Marius Rennbool GLFrame::TextureWasDeleted() const { 32592568796d043c794553e5bcaa797c906899e71f0Marius Renn return texture_state_ == kStateComplete && !glIsTexture(texture_id_); 32692568796d043c794553e5bcaa797c906899e71f0Marius Renn} 32792568796d043c794553e5bcaa797c906899e71f0Marius Renn 32892568796d043c794553e5bcaa797c906899e71f0Marius Rennbool GLFrame::GenerateFboName() { 32930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (fbo_state_ == kStateUninitialized) { 33030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Make sure FBO not in use already 33130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (glIsFramebuffer(fbo_id_)) { 33230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni LOGE("GLFrame: Cannot generate FBO id %d, as it is in use already!", fbo_id_); 33330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 33430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 33530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 33630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Create FBO 33730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glGenFramebuffers(1, &fbo_id_); 33830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (GLEnv::CheckGLError("FBO Generation")) 33930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 34030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni fbo_state_ = kStateGenerated; 341776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn owns_fbo_ = true; 34230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 34330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 34430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 34530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 34630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 347e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvalabool GLFrame::ReadFboPixels(uint8_t* pixels) const { 348776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn if (fbo_state_ == kStateComplete) { 34930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni BindFrameBuffer(); 35030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glReadPixels(0, 35130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 0, 35230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni width_, 35330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni height_, 35430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni GL_RGBA, 35530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni GL_UNSIGNED_BYTE, 35630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni pixels); 35730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return !GLEnv::CheckGLError("FBO Pixel Readout"); 35830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 35930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 36030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 36130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 362e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvalabool GLFrame::ReadTexturePixels(uint8_t* pixels) const { 36330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Read pixels from texture if we do not have an FBO 36430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // NOTE: OpenGL ES does NOT support glGetTexImage() for reading out texture 36530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // data. The only way for us to get texture data is to create a new FBO and 36630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // render the current texture frame into it. As this is quite inefficient, 36730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // and unnecessary (this can only happen if the user is reading out data 36830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // that was just set, and not run through a filter), we warn the user about 36930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // this here. 37030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni LOGW("Warning: Reading pixel data from unfiltered GL frame. This is highly " 37130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni "inefficient. Please consider using your original pixel buffer " 37230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni "instead!"); 37330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 37430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Create source frame set (unfortunately this requires an ugly const-cast, 37530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // as we need to wrap ourselves in a frame-set. Still, as this set is used 37630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // as input only, we are certain we will not be modified). 377e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvala std::vector<const GLFrame*> sources; 37830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni sources.push_back(this); 37930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 38030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Create target frame 381511360e61650864ea22a171159efe073c80d0cdbMarius Renn GLFrame target(gl_env_); 38230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni target.Init(width_, height_); 38330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 38430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Render the texture to the target 38530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni GetIdentity()->Process(sources, &target); 38630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 38730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Get the pixel data 38830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return target.ReadFboPixels(pixels); 38930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 39030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 39192568796d043c794553e5bcaa797c906899e71f0Marius Rennbool GLFrame::AttachTextureToFbo() { 39292568796d043c794553e5bcaa797c906899e71f0Marius Renn // Check FBO and texture state. We do not do anything if we are not managing the texture. 39392568796d043c794553e5bcaa797c906899e71f0Marius Renn if (fbo_state_ == kStateComplete || texture_state_ == kStateUnmanaged) { 39430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 39592568796d043c794553e5bcaa797c906899e71f0Marius Renn } else if (fbo_state_ != kStateGenerated) { 39692568796d043c794553e5bcaa797c906899e71f0Marius Renn LOGE("Attempting to attach texture to FBO with no FBO in place!"); 39792568796d043c794553e5bcaa797c906899e71f0Marius Renn return false; 39892568796d043c794553e5bcaa797c906899e71f0Marius Renn } 39930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 40092568796d043c794553e5bcaa797c906899e71f0Marius Renn // If texture has been generated, make sure it is allocated. 40192568796d043c794553e5bcaa797c906899e71f0Marius Renn if (!AllocateTexture()) 40230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 40330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 40430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Bind the frame buffer, and check if we it is already bound 40530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glBindFramebuffer(GL_FRAMEBUFFER, fbo_id_); 40630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 40792568796d043c794553e5bcaa797c906899e71f0Marius Renn // Bind the texture to the frame buffer 40892568796d043c794553e5bcaa797c906899e71f0Marius Renn LOG_FRAME("Attaching tex %d w %d h %d to fbo %d", texture_id_, width_, height_, fbo_id_); 40992568796d043c794553e5bcaa797c906899e71f0Marius Renn glFramebufferTexture2D(GL_FRAMEBUFFER, 41092568796d043c794553e5bcaa797c906899e71f0Marius Renn GL_COLOR_ATTACHMENT0, 41192568796d043c794553e5bcaa797c906899e71f0Marius Renn GL_TEXTURE_2D, 41292568796d043c794553e5bcaa797c906899e71f0Marius Renn texture_id_, 41392568796d043c794553e5bcaa797c906899e71f0Marius Renn 0); 41430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 41530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Cleanup 41630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glBindTexture(GL_TEXTURE_2D, 0); 41730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glBindFramebuffer(GL_FRAMEBUFFER, 0); 41830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 41930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (GLEnv::CheckGLError("Texture Binding to FBO")) 42030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 42192568796d043c794553e5bcaa797c906899e71f0Marius Renn else 42292568796d043c794553e5bcaa797c906899e71f0Marius Renn fbo_state_ = kStateComplete; 42330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 42492568796d043c794553e5bcaa797c906899e71f0Marius Renn return true; 42592568796d043c794553e5bcaa797c906899e71f0Marius Renn} 42692568796d043c794553e5bcaa797c906899e71f0Marius Renn 42792568796d043c794553e5bcaa797c906899e71f0Marius Rennbool GLFrame::ReattachTextureToFbo() { 42892568796d043c794553e5bcaa797c906899e71f0Marius Renn return (fbo_state_ == kStateGenerated) ? AttachTextureToFbo() : true; 42992568796d043c794553e5bcaa797c906899e71f0Marius Renn} 43092568796d043c794553e5bcaa797c906899e71f0Marius Renn 43192568796d043c794553e5bcaa797c906899e71f0Marius Rennbool GLFrame::DetachTextureFromFbo() { 43292568796d043c794553e5bcaa797c906899e71f0Marius Renn if (fbo_state_ == kStateComplete && texture_state_ == kStateComplete) { 43392568796d043c794553e5bcaa797c906899e71f0Marius Renn LOG_FRAME("Detaching tex %d w %d h %d from fbo %d", texture_id_, width_, height_, fbo_id_); 43492568796d043c794553e5bcaa797c906899e71f0Marius Renn glBindFramebuffer(GL_FRAMEBUFFER, fbo_id_); 43592568796d043c794553e5bcaa797c906899e71f0Marius Renn glFramebufferTexture2D(GL_FRAMEBUFFER, 43692568796d043c794553e5bcaa797c906899e71f0Marius Renn GL_COLOR_ATTACHMENT0, 43792568796d043c794553e5bcaa797c906899e71f0Marius Renn GL_TEXTURE_2D, 43892568796d043c794553e5bcaa797c906899e71f0Marius Renn 0, 43992568796d043c794553e5bcaa797c906899e71f0Marius Renn 0); 44092568796d043c794553e5bcaa797c906899e71f0Marius Renn if (GLEnv::CheckGLError("Detaching texture to FBO")) 44192568796d043c794553e5bcaa797c906899e71f0Marius Renn return false; 44292568796d043c794553e5bcaa797c906899e71f0Marius Renn else 44392568796d043c794553e5bcaa797c906899e71f0Marius Renn fbo_state_ = kStateGenerated; 44492568796d043c794553e5bcaa797c906899e71f0Marius Renn } 44530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 44630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 44730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 448e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvalabool GLFrame::UploadTexturePixels(const uint8_t* pixels) { 44930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Bind the texture object 45030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni FocusTexture(); 45130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 45230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Load mipmap level 0 45330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 45430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); 45530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 456f5ae8eafa7605c6593f62f873b62cb64a3254db3Marius Renn // Set the user specified texture parameters 457f5ae8eafa7605c6593f62f873b62cb64a3254db3Marius Renn UpdateTexParameters(); 45830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 45930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (GLEnv::CheckGLError("Texture Pixel Upload")) 46030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 46130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 462776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn texture_state_ = kStateComplete; 46330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 46430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 46530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 46630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} // namespace filterfw 46730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} // namespace android 468