gl_frame.cpp revision e9912de34684f1b8deaf36bcf77686152d33765d
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 2830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// 2930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// A GLFrame stores pixel data on the GPU. It uses two kinds of GL data 3030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// containers for this: Textures and Frame Buffer Objects (FBOs). Textures are 3130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// used whenever pixel data needs to be read into a shader or the host program, 3230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// and when pixel data is uploaded to a GLFrame. The FBO is used as a rendering 3330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// target for shaders. 3430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// 3530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 3630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo CarceroniGLFrame::GLFrame() 3730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni : width_(0), 3830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni height_(0), 3930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni vp_x_(0), 4030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni vp_y_(0), 4130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni vp_width_(0), 4230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni vp_height_(0), 4330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni texture_id_(0), 4430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni fbo_id_(0), 4530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni texture_target_(GL_TEXTURE_2D), 4630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni texture_state_(kStateUninitialized), 4730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni fbo_state_(kStateUninitialized), 4830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni owns_(false), 4930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni identity_cache_(NULL) { 5030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 5130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 5230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::Init(int width, int height) { 5330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Make sure we haven't been initialized already 5430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (width_ == 0 && height_ == 0) { 5530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni InitDimensions(width, height); 5630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni owns_ = true; 5730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 5830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 5930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 6030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 6130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 6230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::InitWithTexture(GLint texture_id, int width, int height, bool owns, bool create_tex) { 6330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni texture_id_ = texture_id; 6430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni texture_state_ = create_tex ? kStateGenerated : kStateAllocated; 6530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni InitDimensions(width, height); 6630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni owns_ = owns; 6730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 6830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 6930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 7030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::InitWithFbo(GLint fbo_id, int width, int height, bool owns, bool create_fbo) { 7130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni fbo_id_ = fbo_id; 7230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni fbo_state_ = create_fbo ? kStateGenerated : kStateBound; 7330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni InitDimensions(width, height); 7430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni owns_ = owns; 7530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 7630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 7730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 7830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::InitWithExternalTexture() { 7930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni texture_target_ = GL_TEXTURE_EXTERNAL_OES; 8030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni width_ = 0; 8130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni height_ = 0; 8230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni owns_ = true; 8330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return CreateTexture(); 8430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 8530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 8630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronivoid GLFrame::InitDimensions(int width, int height) { 8730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni width_ = width; 8830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni height_ = height; 8930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni vp_width_ = width; 9030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni vp_height_ = height; 9130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 9230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 9330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo CarceroniGLFrame::~GLFrame() { 9430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni LOGV("Deleting texture %d and fbo %d", texture_id_, fbo_id_); 9530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (owns_) { 9630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glDeleteTextures(1, &texture_id_); 9730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glDeleteFramebuffers(1, &fbo_id_); 9830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 9930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni delete identity_cache_; 10030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 10130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 10230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::GenerateMipMap() { 10330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (BindTexture()) { 10430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glGenerateMipmap(GL_TEXTURE_2D); 10530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glTexParameteri(GL_TEXTURE_2D, 10630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni GL_TEXTURE_MIN_FILTER, 10730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni GL_LINEAR_MIPMAP_NEAREST); 10830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return !GLEnv::CheckGLError("Generating MipMap!"); 10930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 11030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 11130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 11230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 11330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::SetTextureParameter(GLenum pname, GLint value) { 11430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (BindTexture()) { 11530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glTexParameteri(GL_TEXTURE_2D, pname, value); 11630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return !GLEnv::CheckGLError("Setting texture parameter!"); 11730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 11830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 11930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 12030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 121e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvalabool GLFrame::CopyDataTo(uint8_t* buffer, int size) { 12230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return (size >= Size()) 12330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni ? CopyPixelsTo(buffer) 12430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni : false; 12530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 12630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 127e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvalabool GLFrame::CopyPixelsTo(uint8_t* buffer) { 12830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (texture_state_ == kStateAllocated) 12930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return ReadTexturePixels(buffer); 13030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni else if (fbo_state_ == kStateBound) 13130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return ReadFboPixels(buffer); 13230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni else 13330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 13430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 13530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 136e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvalabool GLFrame::WriteData(const uint8_t* data, int data_size) { 13730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return (data_size == Size()) ? UploadTexturePixels(data) : false; 13830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 13930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 14030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::SetViewport(int x, int y, int width, int height) { 14130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni vp_x_ = x; 14230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni vp_y_ = y; 14330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni vp_width_ = width; 14430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni vp_height_ = height; 14530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 14630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 14730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 14830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo CarceroniGLFrame* GLFrame::Clone() const { 14930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni GLFrame* target = new GLFrame(); 15030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni target->Init(width_, height_); 15130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni target->CopyPixelsFrom(this); 15230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return target; 15330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 15430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 15530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::CopyPixelsFrom(const GLFrame* frame) { 15630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (frame == this) { 15730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 15830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } else if (frame && frame->width_ == width_ && frame->height_ == height_) { 159e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvala std::vector<const GLFrame*> sources; 16030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni sources.push_back(frame); 16130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni GetIdentity()->Process(sources, this); 16230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 16330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 16430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 16530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 16630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 16730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniint GLFrame::Size() const { 16830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return width_ * height_ * 4; 16930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 17030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 17130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo CarceroniShaderProgram* GLFrame::GetIdentity() const { 17230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (!identity_cache_) 17330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni identity_cache_ = ShaderProgram::CreateIdentity(); 17430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return identity_cache_; 17530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 17630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 17730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::BindFrameBuffer() const { 17830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Bind the FBO 17930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glBindFramebuffer(GL_FRAMEBUFFER, fbo_id_); 18030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (GLEnv::CheckGLError("FBO Binding")) return false; 18130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 18230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Set viewport 18330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glViewport(vp_x_, vp_y_, vp_width_, vp_height_); 18430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (GLEnv::CheckGLError("ViewPort Setup")) return false; 18530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 18630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 18730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 18830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 18930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::FocusFrameBuffer() { 19030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Create texture backing if necessary 19130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (texture_state_ == kStateUninitialized) { 19230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (!CreateTexture()) 19330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 19430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 19530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 19630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Create and bind FBO to texture if necessary 19730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (fbo_state_ != kStateBound) { 19830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (!CreateFBO() || !BindTextureToFBO()) 19930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 20030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 20130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 20230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // And bind it. 20330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return BindFrameBuffer(); 20430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 20530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 20630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::BindTexture() const { 20730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glBindTexture(GL_TEXTURE_2D, texture_id_); 20830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return !GLEnv::CheckGLError("Texture Binding"); 20930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 21030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 21130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo CarceroniGLuint GLFrame::GetTextureId() const { 21230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return texture_id_; 21330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 21430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 21530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// Returns the held FBO id. Only call this if the GLFrame holds an FBO. You 21630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// can check this by calling HoldsFbo(). 21730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo CarceroniGLuint GLFrame::GetFboId() const { 21830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return fbo_id_; 21930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 22030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 22130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::FocusTexture() { 22230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Make sure we have a texture 22330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (!CreateTexture()) 22430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 22530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 22630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Bind the texture 22730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (!BindTexture()) 22830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 22930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 23030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return !GLEnv::CheckGLError("Texture Binding"); 23130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 23230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 23330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::CreateTexture() { 23430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (texture_state_ == kStateUninitialized) { 23530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Make sure texture not in use already 23630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (glIsTexture(texture_id_)) { 23730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni LOGE("GLFrame: Cannot generate texture id %d, as it is in use already!", texture_id_); 23830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 23930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 24030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 24130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Generate the texture 24230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glGenTextures (1, &texture_id_); 24330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (GLEnv::CheckGLError("Texture Generation")) 24430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 24530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni texture_state_ = kStateGenerated; 24630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 24730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 24830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 24930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 25030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 25130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::CreateFBO() { 25230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (fbo_state_ == kStateUninitialized) { 25330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Make sure FBO not in use already 25430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (glIsFramebuffer(fbo_id_)) { 25530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni LOGE("GLFrame: Cannot generate FBO id %d, as it is in use already!", fbo_id_); 25630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 25730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 25830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 25930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Create FBO 26030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glGenFramebuffers(1, &fbo_id_); 26130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (GLEnv::CheckGLError("FBO Generation")) 26230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 26330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni fbo_state_ = kStateGenerated; 26430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 26530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 26630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 26730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 26830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 269e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvalabool GLFrame::ReadFboPixels(uint8_t* pixels) const { 27030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (fbo_state_ == kStateBound) { 27130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni BindFrameBuffer(); 27230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glReadPixels(0, 27330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 0, 27430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni width_, 27530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni height_, 27630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni GL_RGBA, 27730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni GL_UNSIGNED_BYTE, 27830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni pixels); 27930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return !GLEnv::CheckGLError("FBO Pixel Readout"); 28030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 28130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 28230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 28330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 284e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvalabool GLFrame::ReadTexturePixels(uint8_t* pixels) const { 28530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Read pixels from texture if we do not have an FBO 28630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // NOTE: OpenGL ES does NOT support glGetTexImage() for reading out texture 28730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // data. The only way for us to get texture data is to create a new FBO and 28830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // render the current texture frame into it. As this is quite inefficient, 28930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // and unnecessary (this can only happen if the user is reading out data 29030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // that was just set, and not run through a filter), we warn the user about 29130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // this here. 29230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni LOGW("Warning: Reading pixel data from unfiltered GL frame. This is highly " 29330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni "inefficient. Please consider using your original pixel buffer " 29430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni "instead!"); 29530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 29630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Create source frame set (unfortunately this requires an ugly const-cast, 29730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // as we need to wrap ourselves in a frame-set. Still, as this set is used 29830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // as input only, we are certain we will not be modified). 299e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvala std::vector<const GLFrame*> sources; 30030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni sources.push_back(this); 30130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 30230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Create target frame 30330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni GLFrame target; 30430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni target.Init(width_, height_); 30530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 30630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Render the texture to the target 30730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni GetIdentity()->Process(sources, &target); 30830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 30930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Get the pixel data 31030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return target.ReadFboPixels(pixels); 31130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 31230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 31330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool GLFrame::BindTextureToFBO() { 31430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Check if we are already bound 31530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (texture_state_ == kStateBound && fbo_state_ == kStateBound) 31630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 31730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 31830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Otherwise check if the texture and fbo states are acceptable 31930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // TODO: Is it okay to bind an FBO to a texture that has been allocated with pixels??? 32030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (texture_state_ != kStateGenerated 32130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni && texture_state_ != kStateAllocated 32230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni && fbo_state_ != kStateGenerated) 32330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 32430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 32530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Bind the frame buffer, and check if we it is already bound 32630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glBindFramebuffer(GL_FRAMEBUFFER, fbo_id_); 32730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { 32830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Bind texture 32930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glBindTexture(GL_TEXTURE_2D, texture_id_); 33030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 33130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Set the texture format 33230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glTexImage2D(GL_TEXTURE_2D, 33330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 0, 33430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni GL_RGBA, 33530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni width_, 33630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni height_, 33730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 0, 33830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni GL_RGBA, 33930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni GL_UNSIGNED_BYTE, 34030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni NULL); 34130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); 34230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); 34330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 34430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Bind the texture to the frame buffer 34530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni LOG_FRAME("Binding tex %d w %d h %d to fbo %d", texture_id_, width_, height_, fbo_id_); 34630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glFramebufferTexture2D(GL_FRAMEBUFFER, 34730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni GL_COLOR_ATTACHMENT0, 34830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni GL_TEXTURE_2D, 34930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni texture_id_, 35030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 0); 35130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 35230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 35330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Cleanup 35430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glBindTexture(GL_TEXTURE_2D, 0); 35530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glBindFramebuffer(GL_FRAMEBUFFER, 0); 35630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 35730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (GLEnv::CheckGLError("Texture Binding to FBO")) 35830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 35930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 36030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni texture_state_ = fbo_state_ = kStateBound; 36130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 36230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 36330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 364e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvalabool GLFrame::UploadTexturePixels(const uint8_t* pixels) { 36530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (fbo_state_ == kStateBound) { 36630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Get rid of FBO 36730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // TODO: Is this necessary? Can we just leave the FBO? 36830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glDeleteFramebuffers(1, &fbo_id_); 36930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni fbo_state_ = kStateUninitialized; 37030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (GLEnv::CheckGLError("Releasing FBO")) 37130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 37230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni } 37330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 37430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Bind the texture object 37530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni FocusTexture(); 37630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 37730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Load mipmap level 0 37830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 37930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); 38030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 38130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni // Set the filtering mode 38230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 38330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 38430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 38530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni if (GLEnv::CheckGLError("Texture Pixel Upload")) 38630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return false; 38730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 38830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni texture_state_ = kStateAllocated; 38930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni return true; 39030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} 39130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni 39230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} // namespace filterfw 39330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni} // namespace android 394