gl_frame.cpp revision 33164fee278e106cc5d0493a1c184f208e9d273f
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), 5133164fee278e106cc5d0493a1c184f208e9d273fMarius Renn tex_params_modified_(false), 52511360e61650864ea22a171159efe073c80d0cdbMarius Renn owns_(false) { 5330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 5430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 5530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::Init(int width, int height) { 5630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Make sure we haven't been initialized already 5730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (width_ == 0 && height_ == 0) { 5830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni InitDimensions(width, height); 5930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni owns_ = true; 6030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 6130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 6230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 6330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 6430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 6530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::InitWithTexture(GLint texture_id, int width, int height, bool owns, bool create_tex) { 6630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni texture_id_ = texture_id; 6730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni texture_state_ = create_tex ? kStateGenerated : kStateAllocated; 6830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni InitDimensions(width, height); 6930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni owns_ = owns; 7030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 7130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 7230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 7330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::InitWithFbo(GLint fbo_id, int width, int height, bool owns, bool create_fbo) { 7430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni fbo_id_ = fbo_id; 7530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni fbo_state_ = create_fbo ? kStateGenerated : kStateBound; 7630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni InitDimensions(width, height); 7730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni owns_ = owns; 7830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 7930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 8030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 8130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::InitWithExternalTexture() { 8230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni texture_target_ = GL_TEXTURE_EXTERNAL_OES; 8330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni width_ = 0; 8430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni height_ = 0; 8530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni owns_ = true; 8630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return CreateTexture(); 8730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 8830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 8930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronivoid GLFrame::InitDimensions(int width, int height) { 9030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni width_ = width; 9130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni height_ = height; 9230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni vp_width_ = width; 9330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni vp_height_ = height; 9430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 9530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 9630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo CarceroniGLFrame::~GLFrame() { 9730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni LOGV("Deleting texture %d and fbo %d", texture_id_, fbo_id_); 9830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (owns_) { 9930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glDeleteTextures(1, &texture_id_); 10030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glDeleteFramebuffers(1, &fbo_id_); 10130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 10230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 10330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 10430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::GenerateMipMap() { 105fb7c020acdd0fb38c9d2b6750d904b64cc78458dWei Hua if (FocusTexture()) { 10630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glGenerateMipmap(GL_TEXTURE_2D); 10730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return !GLEnv::CheckGLError("Generating MipMap!"); 10830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 10930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 11030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 11130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 11230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::SetTextureParameter(GLenum pname, GLint value) { 113fb7c020acdd0fb38c9d2b6750d904b64cc78458dWei Hua if (FocusTexture()) { 11430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glTexParameteri(GL_TEXTURE_2D, pname, value); 11533164fee278e106cc5d0493a1c184f208e9d273fMarius Renn tex_params_modified_ = true; 11630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return !GLEnv::CheckGLError("Setting texture parameter!"); 11730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 11830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 11930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 12030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 12133164fee278e106cc5d0493a1c184f208e9d273fMarius Rennbool GLFrame::ResetParameters() { 12233164fee278e106cc5d0493a1c184f208e9d273fMarius Renn if (tex_params_modified_) { 12333164fee278e106cc5d0493a1c184f208e9d273fMarius Renn if (BindTexture()) { 12433164fee278e106cc5d0493a1c184f208e9d273fMarius Renn // Set default parameter values 12533164fee278e106cc5d0493a1c184f208e9d273fMarius Renn glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 12633164fee278e106cc5d0493a1c184f208e9d273fMarius Renn glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR); 12733164fee278e106cc5d0493a1c184f208e9d273fMarius Renn glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 12833164fee278e106cc5d0493a1c184f208e9d273fMarius Renn glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 12933164fee278e106cc5d0493a1c184f208e9d273fMarius Renn tex_params_modified_ = false; 13033164fee278e106cc5d0493a1c184f208e9d273fMarius Renn } else { 13133164fee278e106cc5d0493a1c184f208e9d273fMarius Renn return false; 13233164fee278e106cc5d0493a1c184f208e9d273fMarius Renn } 13333164fee278e106cc5d0493a1c184f208e9d273fMarius Renn } 13433164fee278e106cc5d0493a1c184f208e9d273fMarius Renn return !GLEnv::CheckGLError("Resetting texture parameters!"); 13533164fee278e106cc5d0493a1c184f208e9d273fMarius Renn} 13633164fee278e106cc5d0493a1c184f208e9d273fMarius Renn 137e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvalabool GLFrame::CopyDataTo(uint8_t* buffer, int size) { 13830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return (size >= Size()) 13930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni ? CopyPixelsTo(buffer) 14030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni : false; 14130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 14230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 143e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvalabool GLFrame::CopyPixelsTo(uint8_t* buffer) { 14430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (texture_state_ == kStateAllocated) 14530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return ReadTexturePixels(buffer); 14630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni else if (fbo_state_ == kStateBound) 14730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return ReadFboPixels(buffer); 14830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni else 14930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 15030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 15130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 152e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvalabool GLFrame::WriteData(const uint8_t* data, int data_size) { 15330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return (data_size == Size()) ? UploadTexturePixels(data) : false; 15430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 15530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 15630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::SetViewport(int x, int y, int width, int height) { 15730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni vp_x_ = x; 15830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni vp_y_ = y; 15930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni vp_width_ = width; 16030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni vp_height_ = height; 16130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 16230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 16330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 16430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo CarceroniGLFrame* GLFrame::Clone() const { 165511360e61650864ea22a171159efe073c80d0cdbMarius Renn GLFrame* target = new GLFrame(gl_env_); 16630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni target->Init(width_, height_); 16730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni target->CopyPixelsFrom(this); 16830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return target; 16930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 17030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 17130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::CopyPixelsFrom(const GLFrame* frame) { 17230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (frame == this) { 17330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 17430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } else if (frame && frame->width_ == width_ && frame->height_ == height_) { 175e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvala std::vector<const GLFrame*> sources; 17630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni sources.push_back(frame); 17730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni GetIdentity()->Process(sources, this); 17830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 17930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 18030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 18130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 18230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 18330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniint GLFrame::Size() const { 18430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return width_ * height_ * 4; 18530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 18630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 18730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo CarceroniShaderProgram* GLFrame::GetIdentity() const { 188511360e61650864ea22a171159efe073c80d0cdbMarius Renn ShaderProgram* stored_shader = gl_env_->ShaderWithKey(kIdentityShaderKey); 189511360e61650864ea22a171159efe073c80d0cdbMarius Renn if (!stored_shader) { 190511360e61650864ea22a171159efe073c80d0cdbMarius Renn stored_shader = ShaderProgram::CreateIdentity(gl_env_); 191511360e61650864ea22a171159efe073c80d0cdbMarius Renn gl_env_->AttachShader(kIdentityShaderKey, stored_shader); 192511360e61650864ea22a171159efe073c80d0cdbMarius Renn } 193511360e61650864ea22a171159efe073c80d0cdbMarius Renn return stored_shader; 19430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 19530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 19630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::BindFrameBuffer() const { 19730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Bind the FBO 19830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glBindFramebuffer(GL_FRAMEBUFFER, fbo_id_); 19930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (GLEnv::CheckGLError("FBO Binding")) return false; 20030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 20130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Set viewport 20230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glViewport(vp_x_, vp_y_, vp_width_, vp_height_); 20330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (GLEnv::CheckGLError("ViewPort Setup")) return false; 20430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 20530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 20630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 20730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 20830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::FocusFrameBuffer() { 20930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Create texture backing if necessary 21030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (texture_state_ == kStateUninitialized) { 21130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (!CreateTexture()) 21230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 21330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 21430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 21530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Create and bind FBO to texture if necessary 21630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (fbo_state_ != kStateBound) { 21730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (!CreateFBO() || !BindTextureToFBO()) 21830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 21930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 22030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 22130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // And bind it. 22230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return BindFrameBuffer(); 22330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 22430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 22530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::BindTexture() const { 22630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glBindTexture(GL_TEXTURE_2D, texture_id_); 22730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return !GLEnv::CheckGLError("Texture Binding"); 22830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 22930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 23030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo CarceroniGLuint GLFrame::GetTextureId() const { 23130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return texture_id_; 23230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 23330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 23430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// Returns the held FBO id. Only call this if the GLFrame holds an FBO. You 23530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// can check this by calling HoldsFbo(). 23630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo CarceroniGLuint GLFrame::GetFboId() const { 23730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return fbo_id_; 23830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 23930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 24030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::FocusTexture() { 24130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Make sure we have a texture 24230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (!CreateTexture()) 24330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 24430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 24530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Bind the texture 24630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (!BindTexture()) 24730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 24830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 24930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return !GLEnv::CheckGLError("Texture Binding"); 25030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 25130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 25230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::CreateTexture() { 25330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (texture_state_ == kStateUninitialized) { 25430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Make sure texture not in use already 25530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (glIsTexture(texture_id_)) { 25630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni LOGE("GLFrame: Cannot generate texture id %d, as it is in use already!", texture_id_); 25730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 25830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 25930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 26030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Generate the texture 26130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glGenTextures (1, &texture_id_); 26230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (GLEnv::CheckGLError("Texture Generation")) 26330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 26430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni texture_state_ = kStateGenerated; 26530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 26630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 26730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 26830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 26930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 27030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::CreateFBO() { 27130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (fbo_state_ == kStateUninitialized) { 27230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Make sure FBO not in use already 27330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (glIsFramebuffer(fbo_id_)) { 27430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni LOGE("GLFrame: Cannot generate FBO id %d, as it is in use already!", fbo_id_); 27530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 27630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 27730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 27830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Create FBO 27930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glGenFramebuffers(1, &fbo_id_); 28030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (GLEnv::CheckGLError("FBO Generation")) 28130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 28230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni fbo_state_ = kStateGenerated; 28330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 28430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 28530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 28630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 28730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 288e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvalabool GLFrame::ReadFboPixels(uint8_t* pixels) const { 28930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (fbo_state_ == kStateBound) { 29030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni BindFrameBuffer(); 29130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glReadPixels(0, 29230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 0, 29330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni width_, 29430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni height_, 29530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni GL_RGBA, 29630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni GL_UNSIGNED_BYTE, 29730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni pixels); 29830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return !GLEnv::CheckGLError("FBO Pixel Readout"); 29930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 30030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 30130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 30230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 303e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvalabool GLFrame::ReadTexturePixels(uint8_t* pixels) const { 30430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Read pixels from texture if we do not have an FBO 30530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // NOTE: OpenGL ES does NOT support glGetTexImage() for reading out texture 30630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // data. The only way for us to get texture data is to create a new FBO and 30730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // render the current texture frame into it. As this is quite inefficient, 30830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // and unnecessary (this can only happen if the user is reading out data 30930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // that was just set, and not run through a filter), we warn the user about 31030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // this here. 31130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni LOGW("Warning: Reading pixel data from unfiltered GL frame. This is highly " 31230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni "inefficient. Please consider using your original pixel buffer " 31330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni "instead!"); 31430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 31530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Create source frame set (unfortunately this requires an ugly const-cast, 31630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // as we need to wrap ourselves in a frame-set. Still, as this set is used 31730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // as input only, we are certain we will not be modified). 318e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvala std::vector<const GLFrame*> sources; 31930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni sources.push_back(this); 32030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 32130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Create target frame 322511360e61650864ea22a171159efe073c80d0cdbMarius Renn GLFrame target(gl_env_); 32330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni target.Init(width_, height_); 32430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 32530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Render the texture to the target 32630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni GetIdentity()->Process(sources, &target); 32730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 32830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Get the pixel data 32930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return target.ReadFboPixels(pixels); 33030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 33130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 33230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::BindTextureToFBO() { 33330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Check if we are already bound 33430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (texture_state_ == kStateBound && fbo_state_ == kStateBound) 33530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 33630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 33730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Otherwise check if the texture and fbo states are acceptable 33830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (texture_state_ != kStateGenerated 33930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni && texture_state_ != kStateAllocated 34030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni && fbo_state_ != kStateGenerated) 34130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 34230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 34330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Bind the frame buffer, and check if we it is already bound 34430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glBindFramebuffer(GL_FRAMEBUFFER, fbo_id_); 34530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { 34630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Bind texture 34730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glBindTexture(GL_TEXTURE_2D, texture_id_); 34830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 34930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Set the texture format 35030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glTexImage2D(GL_TEXTURE_2D, 35130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 0, 35230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni GL_RGBA, 35330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni width_, 35430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni height_, 35530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 0, 35630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni GL_RGBA, 35730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni GL_UNSIGNED_BYTE, 35830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni NULL); 35930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); 36030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); 36130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 36230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Bind the texture to the frame buffer 36330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni LOG_FRAME("Binding tex %d w %d h %d to fbo %d", texture_id_, width_, height_, fbo_id_); 36430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glFramebufferTexture2D(GL_FRAMEBUFFER, 36530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni GL_COLOR_ATTACHMENT0, 36630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni GL_TEXTURE_2D, 36730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni texture_id_, 36830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 0); 36930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 37030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 37130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Cleanup 37230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glBindTexture(GL_TEXTURE_2D, 0); 37330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glBindFramebuffer(GL_FRAMEBUFFER, 0); 37430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 37530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (GLEnv::CheckGLError("Texture Binding to FBO")) 37630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 37730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 37830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni texture_state_ = fbo_state_ = kStateBound; 37930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 38030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 38130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 382e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvalabool GLFrame::UploadTexturePixels(const uint8_t* pixels) { 38330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Bind the texture object 38430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni FocusTexture(); 38530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 38630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Load mipmap level 0 38730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 38830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); 38930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 39030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Set the filtering mode 39130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 39230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 39330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 39430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (GLEnv::CheckGLError("Texture Pixel Upload")) 39530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 39630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 39730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni texture_state_ = kStateAllocated; 39830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 39930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 40030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 40130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} // namespace filterfw 40230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} // namespace android 403