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