summaryrefslogtreecommitdiffstats
path: root/media/mca/filterfw/native/core/gl_env.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'media/mca/filterfw/native/core/gl_env.cpp')
-rw-r--r--media/mca/filterfw/native/core/gl_env.cpp408
1 files changed, 408 insertions, 0 deletions
diff --git a/media/mca/filterfw/native/core/gl_env.cpp b/media/mca/filterfw/native/core/gl_env.cpp
new file mode 100644
index 0000000..738b8e0
--- /dev/null
+++ b/media/mca/filterfw/native/core/gl_env.cpp
@@ -0,0 +1,408 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+// #define LOG_NDEBUG 0
+
+#include "base/logging.h"
+#include "base/utilities.h"
+#include "core/gl_env.h"
+#include "core/shader_program.h"
+#include "core/vertex_frame.h"
+#include "system/window.h"
+
+#include <map>
+#include <string>
+#include <EGL/eglext.h>
+
+namespace android {
+namespace filterfw {
+
+GLEnv::GLEnv()
+ : display_(EGL_NO_DISPLAY),
+ context_id_(0),
+ surface_id_(0),
+ max_surface_id_(0),
+ created_context_(false),
+ created_surface_(false),
+ initialized_(false) {
+}
+
+GLEnv::~GLEnv() {
+ // Destroy surfaces
+ for (std::map<int, SurfaceWindowPair>::iterator it = surfaces_.begin();
+ it != surfaces_.end();
+ ++it) {
+ if (it->first != 0 || created_surface_) {
+ eglDestroySurface(display(), it->second.first);
+ if (it->second.second) {
+ it->second.second->Destroy();
+ delete it->second.second;
+ }
+ }
+ }
+
+ // Destroy contexts
+ for (std::map<int, EGLContext>::iterator it = contexts_.begin();
+ it != contexts_.end();
+ ++it) {
+ if (it->first != 0 || created_context_)
+ eglDestroyContext(display(), it->second);
+ }
+
+ // Destroy attached shaders and frames
+ STLDeleteValues(&attached_shaders_);
+ STLDeleteValues(&attached_vframes_);
+
+ // Destroy display
+ if (initialized_)
+ eglTerminate(display());
+
+ // Log error if this did not work
+ if (CheckEGLError("TearDown!"))
+ ALOGE("GLEnv: Error tearing down GL Environment!");
+}
+
+bool GLEnv::IsInitialized() const {
+ return (contexts_.size() > 0 &&
+ surfaces_.size() > 0 &&
+ display_ != EGL_NO_DISPLAY);
+}
+
+bool GLEnv::Deactivate() {
+ eglMakeCurrent(display(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ return !CheckEGLError("eglMakeCurrent");
+}
+
+bool GLEnv::Activate() {
+ ALOGV("Activate()");
+ if (display() != eglGetCurrentDisplay() ||
+ context() != eglGetCurrentContext() ||
+ surface() != eglGetCurrentSurface(EGL_DRAW)) {
+ // Make sure we are initialized
+ if (context() == EGL_NO_CONTEXT || surface() == EGL_NO_SURFACE)
+ return false;
+
+ // Make our context current
+ ALOGV("eglMakeCurrent");
+ eglMakeCurrent(display(), surface(), surface(), context());
+
+ return !CheckEGLMakeCurrentError();
+ }
+ return true;
+}
+
+bool GLEnv::SwapBuffers() {
+ const bool result = eglSwapBuffers(display(), surface()) == EGL_TRUE;
+ return !CheckEGLError("eglSwapBuffers") && result;
+}
+
+bool GLEnv::InitWithCurrentContext() {
+ if (IsInitialized())
+ return true;
+
+ display_ = eglGetCurrentDisplay();
+ contexts_[0] = eglGetCurrentContext();
+ surfaces_[0] = SurfaceWindowPair(eglGetCurrentSurface(EGL_DRAW), NULL);
+
+ return (context() != EGL_NO_CONTEXT) &&
+ (display() != EGL_NO_DISPLAY) &&
+ (surface() != EGL_NO_SURFACE);
+}
+
+bool GLEnv::InitWithNewContext() {
+ if (IsInitialized()) {
+ ALOGE("GLEnv: Attempting to reinitialize environment!");
+ return false;
+ }
+
+ display_ = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ if (CheckEGLError("eglGetDisplay")) return false;
+
+ EGLint majorVersion;
+ EGLint minorVersion;
+ eglInitialize(display(), &majorVersion, &minorVersion);
+ if (CheckEGLError("eglInitialize")) return false;
+ initialized_ = true;
+
+ // Configure context/surface
+ EGLConfig config;
+ EGLint numConfigs = -1;
+
+ // TODO(renn): Do we need the window bit here?
+ // TODO: Currently choosing the config that includes all
+ // This is not needed if the encoding is not being used
+ EGLint configAttribs[] = {
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_RECORDABLE_ANDROID, EGL_TRUE,
+ EGL_NONE
+ };
+
+ eglChooseConfig(display(), configAttribs, &config, 1, &numConfigs);
+ if (numConfigs < 1) {
+ ALOGE("GLEnv::Init: No suitable EGL configuration found!");
+ return false;
+ }
+
+ // Create dummy surface using a SurfaceTexture
+ surfaceTexture_ = new SurfaceTexture(0);
+ window_ = new SurfaceTextureClient(static_cast<sp<ISurfaceTexture> >(
+ surfaceTexture_->getBufferQueue()));
+
+ surfaces_[0] = SurfaceWindowPair(eglCreateWindowSurface(display(), config, window_.get(), NULL), NULL);
+ if (CheckEGLError("eglCreateWindowSurface")) return false;
+
+ // Create context
+ EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
+ contexts_[0] = eglCreateContext(display(),
+ config,
+ EGL_NO_CONTEXT,
+ context_attribs);
+ if (CheckEGLError("eglCreateContext")) return false;
+
+ created_context_ = created_surface_ = true;
+
+ return true;
+}
+
+bool GLEnv::IsActive() const {
+ ALOGV("IsActive()");
+ return context() == eglGetCurrentContext()
+ && display() == eglGetCurrentDisplay()
+ && surface() == eglGetCurrentSurface(EGL_DRAW);
+}
+
+bool GLEnv::IsContextActive() const {
+ return context() == eglGetCurrentContext();
+}
+
+bool GLEnv::IsAnyContextActive() {
+ return eglGetCurrentContext() != EGL_NO_CONTEXT;
+}
+
+int GLEnv::AddWindowSurface(const EGLSurface& surface, WindowHandle* window_handle) {
+ const int id = ++max_surface_id_;
+ surfaces_[id] = SurfaceWindowPair(surface, window_handle);
+ return id;
+}
+
+int GLEnv::AddSurface(const EGLSurface& surface) {
+ return AddWindowSurface(surface, NULL);
+}
+
+bool GLEnv::SwitchToSurfaceId(int surface_id) {
+ ALOGV("SwitchToSurfaceId");
+ if (surface_id_ != surface_id) {
+ const SurfaceWindowPair* surface = FindOrNull(surfaces_, surface_id);
+ if (surface) {
+ bool wasActive = IsActive();
+ surface_id_ = surface_id;
+ return wasActive ? Activate() : true;
+ }
+ return false;
+ }
+ return true;
+}
+
+bool GLEnv::ReleaseSurfaceId(int surface_id) {
+ if (surface_id > 0) {
+ const SurfaceWindowPair* surface_window_pair = FindOrNull(surfaces_, surface_id);
+ if (surface_window_pair) {
+ if (surface_id_ == surface_id)
+ SwitchToSurfaceId(0);
+ eglDestroySurface(display(), surface_window_pair->first);
+ if (surface_window_pair->second) {
+ surface_window_pair->second->Destroy();
+ delete surface_window_pair->second;
+ }
+ surfaces_.erase(surface_id);
+ return true;
+ }
+ }
+ return false;
+}
+
+bool GLEnv::SetSurfaceTimestamp(int64_t timestamp) {
+ if (surface_id_ > 0) {
+ const SurfaceWindowPair* surface_window_pair = FindOrNull(surfaces_,
+ surface_id_);
+ if (surface_window_pair) {
+ ANativeWindow *window = static_cast<ANativeWindow*>(
+ surface_window_pair->second->InternalHandle());
+ native_window_set_buffers_timestamp(window, timestamp);
+ return true;
+ }
+ }
+ return false;
+}
+
+int GLEnv::FindSurfaceIdForWindow(const WindowHandle* window_handle) {
+ for (std::map<int, SurfaceWindowPair>::iterator it = surfaces_.begin();
+ it != surfaces_.end();
+ ++it) {
+ const WindowHandle* my_handle = it->second.second;
+ if (my_handle && my_handle->Equals(window_handle)) {
+ return it->first;
+ }
+ }
+ return -1;
+}
+
+
+int GLEnv::AddContext(const EGLContext& context) {
+ const int id = contexts_.size();
+ contexts_[id] = context;
+ return id;
+}
+
+bool GLEnv::SwitchToContextId(int context_id) {
+ const EGLContext* context = FindOrNull(contexts_, context_id);
+ if (context) {
+ if (context_id_ != context_id) {
+ context_id_ = context_id;
+ return Activate();
+ }
+ return true;
+ }
+ return false;
+}
+
+void GLEnv::ReleaseContextId(int context_id) {
+ if (context_id > 0) {
+ const EGLContext* context = FindOrNull(contexts_, context_id);
+ if (context) {
+ contexts_.erase(context_id);
+ if (context_id_ == context_id && IsActive())
+ SwitchToContextId(0);
+ eglDestroyContext(display(), *context);
+ }
+ }
+}
+
+bool GLEnv::CheckGLError(const std::string& op) {
+ bool err = false;
+ for (GLint error = glGetError(); error; error = glGetError()) {
+ ALOGE("GL Error: Operation '%s' caused GL error (0x%x)\n",
+ op.c_str(),
+ error);
+ err = true;
+ }
+ return err;
+}
+
+bool GLEnv::CheckEGLError(const std::string& op) {
+ bool err = false;
+ for (EGLint error = eglGetError();
+ error != EGL_SUCCESS;
+ error = eglGetError()) {
+ ALOGE("EGL Error: Operation '%s' caused EGL error (0x%x)\n",
+ op.c_str(),
+ error);
+ err = true;
+ }
+ return err;
+}
+
+bool GLEnv::CheckEGLMakeCurrentError() {
+ bool err = false;
+ for (EGLint error = eglGetError();
+ error != EGL_SUCCESS;
+ error = eglGetError()) {
+ switch (error) {
+ case EGL_BAD_DISPLAY:
+ ALOGE("EGL Error: Attempting to activate context with bad display!");
+ break;
+ case EGL_BAD_SURFACE:
+ ALOGE("EGL Error: Attempting to activate context with bad surface!");
+ break;
+ case EGL_BAD_ACCESS:
+ ALOGE("EGL Error: Attempting to activate context, which is "
+ "already active in another thread!");
+ break;
+ default:
+ ALOGE("EGL Error: Making EGL rendering context current caused "
+ "error: 0x%x\n", error);
+ }
+ err = true;
+ }
+ return err;
+}
+
+GLuint GLEnv::GetCurrentProgram() {
+ GLint result;
+ glGetIntegerv(GL_CURRENT_PROGRAM, &result);
+ ALOG_ASSERT(result >= 0);
+ return static_cast<GLuint>(result);
+}
+
+EGLDisplay GLEnv::GetCurrentDisplay() {
+ return eglGetCurrentDisplay();
+}
+
+int GLEnv::NumberOfComponents(GLenum type) {
+ switch (type) {
+ case GL_BOOL:
+ case GL_FLOAT:
+ case GL_INT:
+ return 1;
+ case GL_BOOL_VEC2:
+ case GL_FLOAT_VEC2:
+ case GL_INT_VEC2:
+ return 2;
+ case GL_INT_VEC3:
+ case GL_FLOAT_VEC3:
+ case GL_BOOL_VEC3:
+ return 3;
+ case GL_BOOL_VEC4:
+ case GL_FLOAT_VEC4:
+ case GL_INT_VEC4:
+ case GL_FLOAT_MAT2:
+ return 4;
+ case GL_FLOAT_MAT3:
+ return 9;
+ case GL_FLOAT_MAT4:
+ return 16;
+ default:
+ return 0;
+ }
+}
+
+void GLEnv::AttachShader(int key, ShaderProgram* shader) {
+ ShaderProgram* existingShader = ShaderWithKey(key);
+ if (existingShader)
+ delete existingShader;
+ attached_shaders_[key] = shader;
+}
+
+void GLEnv::AttachVertexFrame(int key, VertexFrame* frame) {
+ VertexFrame* existingFrame = VertexFrameWithKey(key);
+ if (existingFrame)
+ delete existingFrame;
+ attached_vframes_[key] = frame;
+}
+
+ShaderProgram* GLEnv::ShaderWithKey(int key) {
+ return FindPtrOrNull(attached_shaders_, key);
+}
+
+VertexFrame* GLEnv::VertexFrameWithKey(int key) {
+ return FindPtrOrNull(attached_vframes_, key);
+}
+
+} // namespace filterfw
+} // namespace android