gl_frame.cpp revision 92568796d043c794553e5bcaa797c906899e71f0
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) { 173776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn if (texture_state_ == kStateComplete) 17430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return ReadTexturePixels(buffer); 175776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn else if (fbo_state_ == kStateComplete) 17630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return ReadFboPixels(buffer); 17730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni else 17830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 17930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 18030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 181e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvalabool GLFrame::WriteData(const uint8_t* data, int data_size) { 18230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return (data_size == Size()) ? UploadTexturePixels(data) : false; 18330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 18430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 18530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::SetViewport(int x, int y, int width, int height) { 18630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni vp_x_ = x; 18730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni vp_y_ = y; 18830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni vp_width_ = width; 18930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni vp_height_ = height; 19030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 19130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 19230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 19330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo CarceroniGLFrame* GLFrame::Clone() const { 194511360e61650864ea22a171159efe073c80d0cdbMarius Renn GLFrame* target = new GLFrame(gl_env_); 19530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni target->Init(width_, height_); 19630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni target->CopyPixelsFrom(this); 19730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return target; 19830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 19930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 20030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::CopyPixelsFrom(const GLFrame* frame) { 20130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (frame == this) { 20230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 20330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } else if (frame && frame->width_ == width_ && frame->height_ == height_) { 204e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvala std::vector<const GLFrame*> sources; 20530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni sources.push_back(frame); 20630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni GetIdentity()->Process(sources, this); 20730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 20830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 20930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 21030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 21130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 21230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniint GLFrame::Size() const { 21330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return width_ * height_ * 4; 21430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 21530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 21630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo CarceroniShaderProgram* GLFrame::GetIdentity() const { 217511360e61650864ea22a171159efe073c80d0cdbMarius Renn ShaderProgram* stored_shader = gl_env_->ShaderWithKey(kIdentityShaderKey); 218511360e61650864ea22a171159efe073c80d0cdbMarius Renn if (!stored_shader) { 219511360e61650864ea22a171159efe073c80d0cdbMarius Renn stored_shader = ShaderProgram::CreateIdentity(gl_env_); 220511360e61650864ea22a171159efe073c80d0cdbMarius Renn gl_env_->AttachShader(kIdentityShaderKey, stored_shader); 221511360e61650864ea22a171159efe073c80d0cdbMarius Renn } 222511360e61650864ea22a171159efe073c80d0cdbMarius Renn return stored_shader; 22330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 22430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 22530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::BindFrameBuffer() const { 22630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Bind the FBO 22730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glBindFramebuffer(GL_FRAMEBUFFER, fbo_id_); 22830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (GLEnv::CheckGLError("FBO Binding")) return false; 22930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 23030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Set viewport 23130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glViewport(vp_x_, vp_y_, vp_width_, vp_height_); 23230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (GLEnv::CheckGLError("ViewPort Setup")) return false; 23330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 23430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 23530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 23630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 23730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::FocusFrameBuffer() { 23830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Create texture backing if necessary 23930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (texture_state_ == kStateUninitialized) { 24092568796d043c794553e5bcaa797c906899e71f0Marius Renn if (!GenerateTextureName()) 24130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 24230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 24330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 24430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Create and bind FBO to texture if necessary 245776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn if (fbo_state_ != kStateComplete) { 24692568796d043c794553e5bcaa797c906899e71f0Marius Renn if (!GenerateFboName() || !AttachTextureToFbo()) 24730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 24830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 24930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 25030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // And bind it. 25130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return BindFrameBuffer(); 25230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 25330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 25430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::BindTexture() const { 25530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glBindTexture(GL_TEXTURE_2D, texture_id_); 25630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return !GLEnv::CheckGLError("Texture Binding"); 25730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 25830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 25930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo CarceroniGLuint GLFrame::GetTextureId() const { 26030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return texture_id_; 26130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 26230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 26330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// Returns the held FBO id. Only call this if the GLFrame holds an FBO. You 26430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// can check this by calling HoldsFbo(). 26530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo CarceroniGLuint GLFrame::GetFboId() const { 26630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return fbo_id_; 26730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 26830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 26930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::FocusTexture() { 27030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Make sure we have a texture 27192568796d043c794553e5bcaa797c906899e71f0Marius Renn if (!GenerateTextureName()) 27230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 27330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 27430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Bind the texture 27530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (!BindTexture()) 27630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 27730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 27830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return !GLEnv::CheckGLError("Texture Binding"); 27930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 28030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 28192568796d043c794553e5bcaa797c906899e71f0Marius Rennbool GLFrame::GenerateTextureName() { 28230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (texture_state_ == kStateUninitialized) { 28330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Make sure texture not in use already 28430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (glIsTexture(texture_id_)) { 28530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni LOGE("GLFrame: Cannot generate texture id %d, as it is in use already!", texture_id_); 28630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 28730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 28830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 28930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Generate the texture 29030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glGenTextures (1, &texture_id_); 29130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (GLEnv::CheckGLError("Texture Generation")) 29230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 29330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni texture_state_ = kStateGenerated; 294776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn owns_texture_ = true; 29530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 29630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 29730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 29830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 29930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 30092568796d043c794553e5bcaa797c906899e71f0Marius Rennbool GLFrame::AllocateTexture() { 30192568796d043c794553e5bcaa797c906899e71f0Marius Renn // Allocate or re-allocate (if texture was deleted externally). 30292568796d043c794553e5bcaa797c906899e71f0Marius Renn if (texture_state_ == kStateGenerated || TextureWasDeleted()) { 30392568796d043c794553e5bcaa797c906899e71f0Marius Renn LOG_FRAME("GLFrame: Allocating texture: %d", texture_id_); 30492568796d043c794553e5bcaa797c906899e71f0Marius Renn glBindTexture(GL_TEXTURE_2D, texture_id_); 30592568796d043c794553e5bcaa797c906899e71f0Marius Renn glTexImage2D(GL_TEXTURE_2D, 30692568796d043c794553e5bcaa797c906899e71f0Marius Renn 0, 30792568796d043c794553e5bcaa797c906899e71f0Marius Renn GL_RGBA, 30892568796d043c794553e5bcaa797c906899e71f0Marius Renn width_, 30992568796d043c794553e5bcaa797c906899e71f0Marius Renn height_, 31092568796d043c794553e5bcaa797c906899e71f0Marius Renn 0, 31192568796d043c794553e5bcaa797c906899e71f0Marius Renn GL_RGBA, 31292568796d043c794553e5bcaa797c906899e71f0Marius Renn GL_UNSIGNED_BYTE, 31392568796d043c794553e5bcaa797c906899e71f0Marius Renn NULL); 31492568796d043c794553e5bcaa797c906899e71f0Marius Renn if (!GLEnv::CheckGLError("Texture Allocation")) { 31592568796d043c794553e5bcaa797c906899e71f0Marius Renn UpdateTexParameters(); 31692568796d043c794553e5bcaa797c906899e71f0Marius Renn texture_state_ = kStateComplete; 31792568796d043c794553e5bcaa797c906899e71f0Marius Renn } 31892568796d043c794553e5bcaa797c906899e71f0Marius Renn } 31992568796d043c794553e5bcaa797c906899e71f0Marius Renn return texture_state_ == kStateComplete; 32092568796d043c794553e5bcaa797c906899e71f0Marius Renn} 32192568796d043c794553e5bcaa797c906899e71f0Marius Renn 32292568796d043c794553e5bcaa797c906899e71f0Marius Rennbool GLFrame::TextureWasDeleted() const { 32392568796d043c794553e5bcaa797c906899e71f0Marius Renn return texture_state_ == kStateComplete && !glIsTexture(texture_id_); 32492568796d043c794553e5bcaa797c906899e71f0Marius Renn} 32592568796d043c794553e5bcaa797c906899e71f0Marius Renn 32692568796d043c794553e5bcaa797c906899e71f0Marius Rennbool GLFrame::GenerateFboName() { 32730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (fbo_state_ == kStateUninitialized) { 32830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Make sure FBO not in use already 32930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (glIsFramebuffer(fbo_id_)) { 33030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni LOGE("GLFrame: Cannot generate FBO id %d, as it is in use already!", fbo_id_); 33130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 33230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 33330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 33430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Create FBO 33530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glGenFramebuffers(1, &fbo_id_); 33630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (GLEnv::CheckGLError("FBO Generation")) 33730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 33830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni fbo_state_ = kStateGenerated; 339776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn owns_fbo_ = true; 34030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 34130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 34230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 34330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 34430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 345e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvalabool GLFrame::ReadFboPixels(uint8_t* pixels) const { 346776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn if (fbo_state_ == kStateComplete) { 34730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni BindFrameBuffer(); 34830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glReadPixels(0, 34930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 0, 35030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni width_, 35130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni height_, 35230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni GL_RGBA, 35330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni GL_UNSIGNED_BYTE, 35430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni pixels); 35530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return !GLEnv::CheckGLError("FBO Pixel Readout"); 35630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 35730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 35830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 35930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 360e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvalabool GLFrame::ReadTexturePixels(uint8_t* pixels) const { 36130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Read pixels from texture if we do not have an FBO 36230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // NOTE: OpenGL ES does NOT support glGetTexImage() for reading out texture 36330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // data. The only way for us to get texture data is to create a new FBO and 36430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // render the current texture frame into it. As this is quite inefficient, 36530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // and unnecessary (this can only happen if the user is reading out data 36630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // that was just set, and not run through a filter), we warn the user about 36730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // this here. 36830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni LOGW("Warning: Reading pixel data from unfiltered GL frame. This is highly " 36930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni "inefficient. Please consider using your original pixel buffer " 37030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni "instead!"); 37130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 37230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Create source frame set (unfortunately this requires an ugly const-cast, 37330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // as we need to wrap ourselves in a frame-set. Still, as this set is used 37430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // as input only, we are certain we will not be modified). 375e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvala std::vector<const GLFrame*> sources; 37630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni sources.push_back(this); 37730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 37830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Create target frame 379511360e61650864ea22a171159efe073c80d0cdbMarius Renn GLFrame target(gl_env_); 38030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni target.Init(width_, height_); 38130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 38230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Render the texture to the target 38330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni GetIdentity()->Process(sources, &target); 38430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 38530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Get the pixel data 38630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return target.ReadFboPixels(pixels); 38730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 38830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 38992568796d043c794553e5bcaa797c906899e71f0Marius Rennbool GLFrame::AttachTextureToFbo() { 39092568796d043c794553e5bcaa797c906899e71f0Marius Renn // Check FBO and texture state. We do not do anything if we are not managing the texture. 39192568796d043c794553e5bcaa797c906899e71f0Marius Renn if (fbo_state_ == kStateComplete || texture_state_ == kStateUnmanaged) { 39230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 39392568796d043c794553e5bcaa797c906899e71f0Marius Renn } else if (fbo_state_ != kStateGenerated) { 39492568796d043c794553e5bcaa797c906899e71f0Marius Renn LOGE("Attempting to attach texture to FBO with no FBO in place!"); 39592568796d043c794553e5bcaa797c906899e71f0Marius Renn return false; 39692568796d043c794553e5bcaa797c906899e71f0Marius Renn } 39730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 39892568796d043c794553e5bcaa797c906899e71f0Marius Renn // If texture has been generated, make sure it is allocated. 39992568796d043c794553e5bcaa797c906899e71f0Marius Renn if (!AllocateTexture()) 40030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 40130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 40230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Bind the frame buffer, and check if we it is already bound 40330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glBindFramebuffer(GL_FRAMEBUFFER, fbo_id_); 40430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 40592568796d043c794553e5bcaa797c906899e71f0Marius Renn // Bind the texture to the frame buffer 40692568796d043c794553e5bcaa797c906899e71f0Marius Renn LOG_FRAME("Attaching tex %d w %d h %d to fbo %d", texture_id_, width_, height_, fbo_id_); 40792568796d043c794553e5bcaa797c906899e71f0Marius Renn glFramebufferTexture2D(GL_FRAMEBUFFER, 40892568796d043c794553e5bcaa797c906899e71f0Marius Renn GL_COLOR_ATTACHMENT0, 40992568796d043c794553e5bcaa797c906899e71f0Marius Renn GL_TEXTURE_2D, 41092568796d043c794553e5bcaa797c906899e71f0Marius Renn texture_id_, 41192568796d043c794553e5bcaa797c906899e71f0Marius Renn 0); 41230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 41330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Cleanup 41430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glBindTexture(GL_TEXTURE_2D, 0); 41530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glBindFramebuffer(GL_FRAMEBUFFER, 0); 41630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 41730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (GLEnv::CheckGLError("Texture Binding to FBO")) 41830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 41992568796d043c794553e5bcaa797c906899e71f0Marius Renn else 42092568796d043c794553e5bcaa797c906899e71f0Marius Renn fbo_state_ = kStateComplete; 42130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 42292568796d043c794553e5bcaa797c906899e71f0Marius Renn return true; 42392568796d043c794553e5bcaa797c906899e71f0Marius Renn} 42492568796d043c794553e5bcaa797c906899e71f0Marius Renn 42592568796d043c794553e5bcaa797c906899e71f0Marius Rennbool GLFrame::ReattachTextureToFbo() { 42692568796d043c794553e5bcaa797c906899e71f0Marius Renn return (fbo_state_ == kStateGenerated) ? AttachTextureToFbo() : true; 42792568796d043c794553e5bcaa797c906899e71f0Marius Renn} 42892568796d043c794553e5bcaa797c906899e71f0Marius Renn 42992568796d043c794553e5bcaa797c906899e71f0Marius Rennbool GLFrame::DetachTextureFromFbo() { 43092568796d043c794553e5bcaa797c906899e71f0Marius Renn if (fbo_state_ == kStateComplete && texture_state_ == kStateComplete) { 43192568796d043c794553e5bcaa797c906899e71f0Marius Renn LOG_FRAME("Detaching tex %d w %d h %d from fbo %d", texture_id_, width_, height_, fbo_id_); 43292568796d043c794553e5bcaa797c906899e71f0Marius Renn glBindFramebuffer(GL_FRAMEBUFFER, fbo_id_); 43392568796d043c794553e5bcaa797c906899e71f0Marius Renn glFramebufferTexture2D(GL_FRAMEBUFFER, 43492568796d043c794553e5bcaa797c906899e71f0Marius Renn GL_COLOR_ATTACHMENT0, 43592568796d043c794553e5bcaa797c906899e71f0Marius Renn GL_TEXTURE_2D, 43692568796d043c794553e5bcaa797c906899e71f0Marius Renn 0, 43792568796d043c794553e5bcaa797c906899e71f0Marius Renn 0); 43892568796d043c794553e5bcaa797c906899e71f0Marius Renn if (GLEnv::CheckGLError("Detaching texture to FBO")) 43992568796d043c794553e5bcaa797c906899e71f0Marius Renn return false; 44092568796d043c794553e5bcaa797c906899e71f0Marius Renn else 44192568796d043c794553e5bcaa797c906899e71f0Marius Renn fbo_state_ = kStateGenerated; 44292568796d043c794553e5bcaa797c906899e71f0Marius Renn } 44330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 44430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 44530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 446e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvalabool GLFrame::UploadTexturePixels(const uint8_t* pixels) { 44730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Bind the texture object 44830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni FocusTexture(); 44930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 45030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Load mipmap level 0 45130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 45230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); 45330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 454f5ae8eafa7605c6593f62f873b62cb64a3254db3Marius Renn // Set the user specified texture parameters 455f5ae8eafa7605c6593f62f873b62cb64a3254db3Marius Renn UpdateTexParameters(); 45630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 45730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (GLEnv::CheckGLError("Texture Pixel Upload")) 45830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 45930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 460776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn texture_state_ = kStateComplete; 46130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 46230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 46330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 46430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} // namespace filterfw 46530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} // namespace android 466