165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn/*
265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Copyright (C) 2011 The Android Open Source Project
365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn *
465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Licensed under the Apache License, Version 2.0 (the "License");
565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * you may not use this file except in compliance with the License.
665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * You may obtain a copy of the License at
765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn *
865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn *      http://www.apache.org/licenses/LICENSE-2.0
965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn *
1065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Unless required by applicable law or agreed to in writing, software
1165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * distributed under the License is distributed on an "AS IS" BASIS,
1265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * See the License for the specific language governing permissions and
1465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * limitations under the License.
1565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn */
1665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn// #define LOG_NDEBUG 0
1765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
1865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn#include "base/logging.h"
1965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn#include "base/utilities.h"
2065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn#include "core/gl_env.h"
2165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn#include "core/shader_program.h"
2265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn#include "core/vertex_frame.h"
2365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn#include "system/window.h"
2465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
2565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn#include <map>
2665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn#include <string>
2765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn#include <EGL/eglext.h>
2865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
29e3eae73abb5e429d9747f9c36ab025219e68bb26Mathias Agopian#include <gui/GLConsumer.h>
30e3eae73abb5e429d9747f9c36ab025219e68bb26Mathias Agopian
3165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennnamespace android {
3265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennnamespace filterfw {
3365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
3465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius RennGLEnv::GLEnv()
3565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  : display_(EGL_NO_DISPLAY),
3665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    context_id_(0),
3765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    surface_id_(0),
3865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    max_surface_id_(0),
3965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    created_context_(false),
4065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    created_surface_(false),
4165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    initialized_(false) {
4265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
4365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
4465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius RennGLEnv::~GLEnv() {
4565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  // Destroy surfaces
4665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  for (std::map<int, SurfaceWindowPair>::iterator it = surfaces_.begin();
4765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn       it != surfaces_.end();
4865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn       ++it) {
4965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    if (it->first != 0 || created_surface_) {
5065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      eglDestroySurface(display(), it->second.first);
5165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      if (it->second.second) {
5265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        it->second.second->Destroy();
5365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        delete it->second.second;
5465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      }
5565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
5665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  }
5765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
5865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  // Destroy contexts
5965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  for (std::map<int, EGLContext>::iterator it = contexts_.begin();
6065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn       it != contexts_.end();
6165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn       ++it) {
6265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    if (it->first != 0 || created_context_)
6365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      eglDestroyContext(display(), it->second);
6465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  }
6565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
6665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  // Destroy attached shaders and frames
6765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  STLDeleteValues(&attached_shaders_);
6865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  STLDeleteValues(&attached_vframes_);
6965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
7065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  // Destroy display
7165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  if (initialized_)
7265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    eglTerminate(display());
7365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
7465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  // Log error if this did not work
7565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  if (CheckEGLError("TearDown!"))
7665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    ALOGE("GLEnv: Error tearing down GL Environment!");
7765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
7865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
7965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool GLEnv::IsInitialized() const {
8065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return (contexts_.size() > 0 &&
8165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn          surfaces_.size() > 0 &&
8265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn          display_ != EGL_NO_DISPLAY);
8365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
8465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
8565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool GLEnv::Deactivate() {
8665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  eglMakeCurrent(display(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
8765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return !CheckEGLError("eglMakeCurrent");
8865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
8965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
9065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool GLEnv::Activate() {
9165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  ALOGV("Activate()");
9265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  if (display()   != eglGetCurrentDisplay() ||
9365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      context()   != eglGetCurrentContext() ||
9465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      surface()   != eglGetCurrentSurface(EGL_DRAW)) {
9565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    // Make sure we are initialized
9665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    if (context() == EGL_NO_CONTEXT || surface() == EGL_NO_SURFACE)
9765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      return false;
9865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
9965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    // Make our context current
10065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    ALOGV("eglMakeCurrent");
10165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    eglMakeCurrent(display(), surface(), surface(), context());
10265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
10365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    return !CheckEGLMakeCurrentError();
10465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  }
10565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return true;
10665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
10765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
10865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool GLEnv::SwapBuffers() {
10965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  const bool result = eglSwapBuffers(display(), surface()) == EGL_TRUE;
11065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return !CheckEGLError("eglSwapBuffers") && result;
11165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
11265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
11365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool GLEnv::InitWithCurrentContext() {
11465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  if (IsInitialized())
11565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    return true;
11665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
11765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  display_     = eglGetCurrentDisplay();
11865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  contexts_[0] = eglGetCurrentContext();
11965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  surfaces_[0] = SurfaceWindowPair(eglGetCurrentSurface(EGL_DRAW), NULL);
12065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
12165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return (context() != EGL_NO_CONTEXT) &&
12265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn         (display() != EGL_NO_DISPLAY) &&
12365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn         (surface() != EGL_NO_SURFACE);
12465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
12565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
12665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool GLEnv::InitWithNewContext() {
12765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  if (IsInitialized()) {
12865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    ALOGE("GLEnv: Attempting to reinitialize environment!");
12965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    return false;
13065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  }
13165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
13265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  display_ = eglGetDisplay(EGL_DEFAULT_DISPLAY);
13365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  if (CheckEGLError("eglGetDisplay")) return false;
13465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
13565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  EGLint majorVersion;
13665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  EGLint minorVersion;
13765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  eglInitialize(display(), &majorVersion, &minorVersion);
13865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  if (CheckEGLError("eglInitialize")) return false;
13965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  initialized_ = true;
14065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
14165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  // Configure context/surface
14265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  EGLConfig config;
14365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  EGLint numConfigs = -1;
14465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
14565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  // TODO(renn): Do we need the window bit here?
14665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  // TODO: Currently choosing the config that includes all
14765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  // This is not needed if the encoding is not being used
14865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  EGLint configAttribs[] = {
14965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
15065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
15165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    EGL_RED_SIZE, 8,
15265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    EGL_GREEN_SIZE, 8,
15365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    EGL_BLUE_SIZE, 8,
15465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    EGL_RECORDABLE_ANDROID, EGL_TRUE,
15565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    EGL_NONE
15665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  };
15765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
15865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  eglChooseConfig(display(), configAttribs, &config, 1, &numConfigs);
15965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  if (numConfigs < 1) {
16065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    ALOGE("GLEnv::Init: No suitable EGL configuration found!");
16165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    return false;
16265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  }
16365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
164d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden  // Create dummy surface using a GLConsumer
165526f21b2c68bc7a386b6f3bebe2df4ca86170a0bDan Stoza  sp<IGraphicBufferProducer> producer;
166526f21b2c68bc7a386b6f3bebe2df4ca86170a0bDan Stoza  sp<IGraphicBufferConsumer> consumer;
167526f21b2c68bc7a386b6f3bebe2df4ca86170a0bDan Stoza  BufferQueue::createBufferQueue(&producer, &consumer);
168ffdbe97f8e8e6381ab1c794c26386060acbc9bbeDan Stoza  surfaceTexture_ = new GLConsumer(consumer, 0, GLConsumer::TEXTURE_EXTERNAL,
169ffdbe97f8e8e6381ab1c794c26386060acbc9bbeDan Stoza          true, false);
170526f21b2c68bc7a386b6f3bebe2df4ca86170a0bDan Stoza  window_ = new Surface(producer);
17165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
17265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  surfaces_[0] = SurfaceWindowPair(eglCreateWindowSurface(display(), config, window_.get(), NULL), NULL);
17365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  if (CheckEGLError("eglCreateWindowSurface")) return false;
17465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
17565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  // Create context
17665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
17765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  contexts_[0] = eglCreateContext(display(),
17865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                  config,
17965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                  EGL_NO_CONTEXT,
18065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                  context_attribs);
18165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  if (CheckEGLError("eglCreateContext")) return false;
18265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
18365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  created_context_ = created_surface_ = true;
18465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
18565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return true;
18665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
18765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
18865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool GLEnv::IsActive() const {
18965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  ALOGV("IsActive()");
19065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return context() == eglGetCurrentContext()
19165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    &&   display() == eglGetCurrentDisplay()
19265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    &&   surface() == eglGetCurrentSurface(EGL_DRAW);
19365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
19465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
19565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool GLEnv::IsContextActive() const {
19665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return context() == eglGetCurrentContext();
19765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
19865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
19965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool GLEnv::IsAnyContextActive() {
20065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return eglGetCurrentContext() != EGL_NO_CONTEXT;
20165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
20265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
20365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennint GLEnv::AddWindowSurface(const EGLSurface& surface, WindowHandle* window_handle) {
20465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  const int id = ++max_surface_id_;
20565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  surfaces_[id] = SurfaceWindowPair(surface, window_handle);
20665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return id;
20765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
20865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
20965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennint GLEnv::AddSurface(const EGLSurface& surface) {
21065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return AddWindowSurface(surface, NULL);
21165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
21265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
21365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool GLEnv::SwitchToSurfaceId(int surface_id) {
21465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  ALOGV("SwitchToSurfaceId");
21565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  if (surface_id_ != surface_id) {
21665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    const SurfaceWindowPair* surface = FindOrNull(surfaces_, surface_id);
21765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    if (surface) {
21865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      bool wasActive = IsActive();
21965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      surface_id_ = surface_id;
22065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      return wasActive ? Activate() : true;
22165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
22265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    return false;
22365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  }
22465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return true;
22565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
22665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
22765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool GLEnv::ReleaseSurfaceId(int surface_id) {
22865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  if (surface_id > 0) {
22965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    const SurfaceWindowPair* surface_window_pair = FindOrNull(surfaces_, surface_id);
23065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    if (surface_window_pair) {
23165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      if (surface_id_ == surface_id)
23265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        SwitchToSurfaceId(0);
23365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      eglDestroySurface(display(), surface_window_pair->first);
23465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      if (surface_window_pair->second) {
23565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        surface_window_pair->second->Destroy();
23665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        delete surface_window_pair->second;
23765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      }
23865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      surfaces_.erase(surface_id);
23965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      return true;
24065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
24165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  }
24265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return false;
24365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
24465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
24565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool GLEnv::SetSurfaceTimestamp(int64_t timestamp) {
24665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  if (surface_id_ > 0) {
24765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    const SurfaceWindowPair* surface_window_pair = FindOrNull(surfaces_,
24865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            surface_id_);
24965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    if (surface_window_pair) {
25065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      ANativeWindow *window = static_cast<ANativeWindow*>(
25165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn              surface_window_pair->second->InternalHandle());
25265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      native_window_set_buffers_timestamp(window, timestamp);
25365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      return true;
25465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
25565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  }
25665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return false;
25765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
25865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
25965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennint GLEnv::FindSurfaceIdForWindow(const WindowHandle* window_handle) {
26065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  for (std::map<int, SurfaceWindowPair>::iterator it = surfaces_.begin();
26165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn       it != surfaces_.end();
26265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn       ++it) {
26365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    const WindowHandle* my_handle = it->second.second;
26465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    if (my_handle && my_handle->Equals(window_handle)) {
26565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      return it->first;
26665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
26765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  }
26865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return -1;
26965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
27065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
27165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
27265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennint GLEnv::AddContext(const EGLContext& context) {
27365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  const int id = contexts_.size();
27465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  contexts_[id] = context;
27565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return id;
27665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
27765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
27865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool GLEnv::SwitchToContextId(int context_id) {
27965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  const EGLContext* context = FindOrNull(contexts_, context_id);
28065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  if (context) {
28165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    if (context_id_ != context_id) {
28265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      context_id_ = context_id;
28365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      return Activate();
28465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
28565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    return true;
28665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  }
28765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return false;
28865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
28965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
29065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennvoid GLEnv::ReleaseContextId(int context_id) {
29165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  if (context_id > 0) {
29265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    const EGLContext* context = FindOrNull(contexts_, context_id);
29365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    if (context) {
29465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      contexts_.erase(context_id);
29565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      if (context_id_ == context_id && IsActive())
29665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        SwitchToContextId(0);
29765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      eglDestroyContext(display(), *context);
29865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
29965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  }
30065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
30165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
30265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool GLEnv::CheckGLError(const std::string& op) {
30365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  bool err = false;
30465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  for (GLint error = glGetError(); error; error = glGetError()) {
30565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    ALOGE("GL Error: Operation '%s' caused GL error (0x%x)\n",
30665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn         op.c_str(),
30765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn         error);
30865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    err = true;
30965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  }
31065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return err;
31165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
31265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
31365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool GLEnv::CheckEGLError(const std::string& op) {
31465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  bool err = false;
31565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  for (EGLint error = eglGetError();
31665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn       error != EGL_SUCCESS;
31765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn       error = eglGetError()) {
31865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    ALOGE("EGL Error: Operation '%s' caused EGL error (0x%x)\n",
31965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn         op.c_str(),
32065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn         error);
32165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    err = true;
32265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  }
32365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return err;
32465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
32565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
32665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennbool GLEnv::CheckEGLMakeCurrentError() {
32765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  bool err = false;
32865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  for (EGLint error = eglGetError();
32965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn       error != EGL_SUCCESS;
33065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn       error = eglGetError()) {
33165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    switch (error) {
33265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      case EGL_BAD_DISPLAY:
33365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        ALOGE("EGL Error: Attempting to activate context with bad display!");
33465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        break;
33565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      case EGL_BAD_SURFACE:
33665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        ALOGE("EGL Error: Attempting to activate context with bad surface!");
33765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        break;
33865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      case EGL_BAD_ACCESS:
33965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        ALOGE("EGL Error: Attempting to activate context, which is "
34065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn             "already active in another thread!");
34165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        break;
34265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      default:
34365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        ALOGE("EGL Error: Making EGL rendering context current caused "
34465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn             "error: 0x%x\n", error);
34565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
34665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    err = true;
34765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  }
34865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return err;
34965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
35065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
35165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius RennGLuint GLEnv::GetCurrentProgram() {
35265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  GLint result;
35365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  glGetIntegerv(GL_CURRENT_PROGRAM, &result);
35465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  ALOG_ASSERT(result >= 0);
35565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return static_cast<GLuint>(result);
35665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
35765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
35865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius RennEGLDisplay GLEnv::GetCurrentDisplay() {
35965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return eglGetCurrentDisplay();
36065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
36165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
36265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennint GLEnv::NumberOfComponents(GLenum type) {
36365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  switch (type) {
36465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    case GL_BOOL:
36565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    case GL_FLOAT:
36665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    case GL_INT:
36765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      return 1;
36865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    case GL_BOOL_VEC2:
36965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    case GL_FLOAT_VEC2:
37065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    case GL_INT_VEC2:
37165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      return 2;
37265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    case GL_INT_VEC3:
37365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    case GL_FLOAT_VEC3:
37465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    case GL_BOOL_VEC3:
37565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      return 3;
37665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    case GL_BOOL_VEC4:
37765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    case GL_FLOAT_VEC4:
37865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    case GL_INT_VEC4:
37965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    case GL_FLOAT_MAT2:
38065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      return 4;
38165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    case GL_FLOAT_MAT3:
38265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      return 9;
38365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    case GL_FLOAT_MAT4:
38465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      return 16;
38565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    default:
38665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn      return 0;
38765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  }
38865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
38965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
39065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennvoid GLEnv::AttachShader(int key, ShaderProgram* shader) {
39165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  ShaderProgram* existingShader = ShaderWithKey(key);
39265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  if (existingShader)
39365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    delete existingShader;
39465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  attached_shaders_[key] = shader;
39565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
39665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
39765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennvoid GLEnv::AttachVertexFrame(int key, VertexFrame* frame) {
39865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  VertexFrame* existingFrame = VertexFrameWithKey(key);
39965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  if (existingFrame)
40065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    delete existingFrame;
40165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  attached_vframes_[key] = frame;
40265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
40365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
40465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius RennShaderProgram* GLEnv::ShaderWithKey(int key) {
40565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return FindPtrOrNull(attached_shaders_, key);
40665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
40765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
40865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius RennVertexFrame* GLEnv::VertexFrameWithKey(int key) {
40965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn  return FindPtrOrNull(attached_vframes_, key);
41065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
41165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
41265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} // namespace filterfw
41365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} // namespace android
414