gl_env.cpp revision 52a9a10b6b8c7b7a9f97777541841b94d4fd9754
1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16// #define LOG_NDEBUG 0 17 18#include "base/logging.h" 19#include "base/utilities.h" 20#include "core/gl_env.h" 21#include "core/shader_program.h" 22#include "core/vertex_frame.h" 23#include "system/window.h" 24 25#include <map> 26#include <string> 27#include <EGL/eglext.h> 28 29namespace android { 30namespace filterfw { 31 32GLEnv::GLEnv() 33 : display_(EGL_NO_DISPLAY), 34 context_id_(0), 35 surface_id_(0), 36 max_surface_id_(0), 37 created_context_(false), 38 created_surface_(false), 39 initialized_(false) { 40} 41 42GLEnv::~GLEnv() { 43 // Destroy surfaces 44 for (std::map<int, SurfaceWindowPair>::iterator it = surfaces_.begin(); 45 it != surfaces_.end(); 46 ++it) { 47 if (it->first != 0 || created_surface_) { 48 eglDestroySurface(display(), it->second.first); 49 if (it->second.second) { 50 it->second.second->Destroy(); 51 delete it->second.second; 52 } 53 } 54 } 55 56 // Destroy contexts 57 for (std::map<int, EGLContext>::iterator it = contexts_.begin(); 58 it != contexts_.end(); 59 ++it) { 60 if (it->first != 0 || created_context_) 61 eglDestroyContext(display(), it->second); 62 } 63 64 // Destroy attached shaders and frames 65 STLDeleteValues(&attached_shaders_); 66 STLDeleteValues(&attached_vframes_); 67 68 // Destroy display 69 if (initialized_) 70 eglTerminate(display()); 71 72 // Log error if this did not work 73 if (CheckEGLError("TearDown!")) 74 ALOGE("GLEnv: Error tearing down GL Environment!"); 75} 76 77bool GLEnv::IsInitialized() const { 78 return (contexts_.size() > 0 && 79 surfaces_.size() > 0 && 80 display_ != EGL_NO_DISPLAY); 81} 82 83bool GLEnv::Deactivate() { 84 eglMakeCurrent(display(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 85 return !CheckEGLError("eglMakeCurrent"); 86} 87 88bool GLEnv::Activate() { 89 ALOGV("Activate()"); 90 if (display() != eglGetCurrentDisplay() || 91 context() != eglGetCurrentContext() || 92 surface() != eglGetCurrentSurface(EGL_DRAW)) { 93 // Make sure we are initialized 94 if (context() == EGL_NO_CONTEXT || surface() == EGL_NO_SURFACE) 95 return false; 96 97 // Make our context current 98 ALOGV("eglMakeCurrent"); 99 eglMakeCurrent(display(), surface(), surface(), context()); 100 101 return !CheckEGLMakeCurrentError(); 102 } 103 return true; 104} 105 106bool GLEnv::SwapBuffers() { 107 const bool result = eglSwapBuffers(display(), surface()) == EGL_TRUE; 108 return !CheckEGLError("eglSwapBuffers") && result; 109} 110 111bool GLEnv::InitWithCurrentContext() { 112 if (IsInitialized()) 113 return true; 114 115 display_ = eglGetCurrentDisplay(); 116 contexts_[0] = eglGetCurrentContext(); 117 surfaces_[0] = SurfaceWindowPair(eglGetCurrentSurface(EGL_DRAW), NULL); 118 119 return (context() != EGL_NO_CONTEXT) && 120 (display() != EGL_NO_DISPLAY) && 121 (surface() != EGL_NO_SURFACE); 122} 123 124bool GLEnv::InitWithNewContext() { 125 if (IsInitialized()) { 126 ALOGE("GLEnv: Attempting to reinitialize environment!"); 127 return false; 128 } 129 130 display_ = eglGetDisplay(EGL_DEFAULT_DISPLAY); 131 if (CheckEGLError("eglGetDisplay")) return false; 132 133 EGLint majorVersion; 134 EGLint minorVersion; 135 eglInitialize(display(), &majorVersion, &minorVersion); 136 if (CheckEGLError("eglInitialize")) return false; 137 initialized_ = true; 138 139 // Configure context/surface 140 EGLConfig config; 141 EGLint numConfigs = -1; 142 143 // TODO(renn): Do we need the window bit here? 144 // TODO: Currently choosing the config that includes all 145 // This is not needed if the encoding is not being used 146 EGLint configAttribs[] = { 147 EGL_SURFACE_TYPE, EGL_WINDOW_BIT, 148 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 149 EGL_RED_SIZE, 8, 150 EGL_GREEN_SIZE, 8, 151 EGL_BLUE_SIZE, 8, 152 EGL_RECORDABLE_ANDROID, EGL_TRUE, 153 EGL_NONE 154 }; 155 156 eglChooseConfig(display(), configAttribs, &config, 1, &numConfigs); 157 if (numConfigs < 1) { 158 ALOGE("GLEnv::Init: No suitable EGL configuration found!"); 159 return false; 160 } 161 162 // Create dummy surface using a GLConsumer 163 sp<BufferQueue> bq = new BufferQueue(); 164 surfaceTexture_ = new GLConsumer(bq, 0); 165 window_ = new Surface(static_cast<sp<IGraphicBufferProducer> >(bq)); 166 167 surfaces_[0] = SurfaceWindowPair(eglCreateWindowSurface(display(), config, window_.get(), NULL), NULL); 168 if (CheckEGLError("eglCreateWindowSurface")) return false; 169 170 // Create context 171 EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; 172 contexts_[0] = eglCreateContext(display(), 173 config, 174 EGL_NO_CONTEXT, 175 context_attribs); 176 if (CheckEGLError("eglCreateContext")) return false; 177 178 created_context_ = created_surface_ = true; 179 180 return true; 181} 182 183bool GLEnv::IsActive() const { 184 ALOGV("IsActive()"); 185 return context() == eglGetCurrentContext() 186 && display() == eglGetCurrentDisplay() 187 && surface() == eglGetCurrentSurface(EGL_DRAW); 188} 189 190bool GLEnv::IsContextActive() const { 191 return context() == eglGetCurrentContext(); 192} 193 194bool GLEnv::IsAnyContextActive() { 195 return eglGetCurrentContext() != EGL_NO_CONTEXT; 196} 197 198int GLEnv::AddWindowSurface(const EGLSurface& surface, WindowHandle* window_handle) { 199 const int id = ++max_surface_id_; 200 surfaces_[id] = SurfaceWindowPair(surface, window_handle); 201 return id; 202} 203 204int GLEnv::AddSurface(const EGLSurface& surface) { 205 return AddWindowSurface(surface, NULL); 206} 207 208bool GLEnv::SwitchToSurfaceId(int surface_id) { 209 ALOGV("SwitchToSurfaceId"); 210 if (surface_id_ != surface_id) { 211 const SurfaceWindowPair* surface = FindOrNull(surfaces_, surface_id); 212 if (surface) { 213 bool wasActive = IsActive(); 214 surface_id_ = surface_id; 215 return wasActive ? Activate() : true; 216 } 217 return false; 218 } 219 return true; 220} 221 222bool GLEnv::ReleaseSurfaceId(int surface_id) { 223 if (surface_id > 0) { 224 const SurfaceWindowPair* surface_window_pair = FindOrNull(surfaces_, surface_id); 225 if (surface_window_pair) { 226 if (surface_id_ == surface_id) 227 SwitchToSurfaceId(0); 228 eglDestroySurface(display(), surface_window_pair->first); 229 if (surface_window_pair->second) { 230 surface_window_pair->second->Destroy(); 231 delete surface_window_pair->second; 232 } 233 surfaces_.erase(surface_id); 234 return true; 235 } 236 } 237 return false; 238} 239 240bool GLEnv::SetSurfaceTimestamp(int64_t timestamp) { 241 if (surface_id_ > 0) { 242 const SurfaceWindowPair* surface_window_pair = FindOrNull(surfaces_, 243 surface_id_); 244 if (surface_window_pair) { 245 ANativeWindow *window = static_cast<ANativeWindow*>( 246 surface_window_pair->second->InternalHandle()); 247 native_window_set_buffers_timestamp(window, timestamp); 248 return true; 249 } 250 } 251 return false; 252} 253 254int GLEnv::FindSurfaceIdForWindow(const WindowHandle* window_handle) { 255 for (std::map<int, SurfaceWindowPair>::iterator it = surfaces_.begin(); 256 it != surfaces_.end(); 257 ++it) { 258 const WindowHandle* my_handle = it->second.second; 259 if (my_handle && my_handle->Equals(window_handle)) { 260 return it->first; 261 } 262 } 263 return -1; 264} 265 266 267int GLEnv::AddContext(const EGLContext& context) { 268 const int id = contexts_.size(); 269 contexts_[id] = context; 270 return id; 271} 272 273bool GLEnv::SwitchToContextId(int context_id) { 274 const EGLContext* context = FindOrNull(contexts_, context_id); 275 if (context) { 276 if (context_id_ != context_id) { 277 context_id_ = context_id; 278 return Activate(); 279 } 280 return true; 281 } 282 return false; 283} 284 285void GLEnv::ReleaseContextId(int context_id) { 286 if (context_id > 0) { 287 const EGLContext* context = FindOrNull(contexts_, context_id); 288 if (context) { 289 contexts_.erase(context_id); 290 if (context_id_ == context_id && IsActive()) 291 SwitchToContextId(0); 292 eglDestroyContext(display(), *context); 293 } 294 } 295} 296 297bool GLEnv::CheckGLError(const std::string& op) { 298 bool err = false; 299 for (GLint error = glGetError(); error; error = glGetError()) { 300 ALOGE("GL Error: Operation '%s' caused GL error (0x%x)\n", 301 op.c_str(), 302 error); 303 err = true; 304 } 305 return err; 306} 307 308bool GLEnv::CheckEGLError(const std::string& op) { 309 bool err = false; 310 for (EGLint error = eglGetError(); 311 error != EGL_SUCCESS; 312 error = eglGetError()) { 313 ALOGE("EGL Error: Operation '%s' caused EGL error (0x%x)\n", 314 op.c_str(), 315 error); 316 err = true; 317 } 318 return err; 319} 320 321bool GLEnv::CheckEGLMakeCurrentError() { 322 bool err = false; 323 for (EGLint error = eglGetError(); 324 error != EGL_SUCCESS; 325 error = eglGetError()) { 326 switch (error) { 327 case EGL_BAD_DISPLAY: 328 ALOGE("EGL Error: Attempting to activate context with bad display!"); 329 break; 330 case EGL_BAD_SURFACE: 331 ALOGE("EGL Error: Attempting to activate context with bad surface!"); 332 break; 333 case EGL_BAD_ACCESS: 334 ALOGE("EGL Error: Attempting to activate context, which is " 335 "already active in another thread!"); 336 break; 337 default: 338 ALOGE("EGL Error: Making EGL rendering context current caused " 339 "error: 0x%x\n", error); 340 } 341 err = true; 342 } 343 return err; 344} 345 346GLuint GLEnv::GetCurrentProgram() { 347 GLint result; 348 glGetIntegerv(GL_CURRENT_PROGRAM, &result); 349 ALOG_ASSERT(result >= 0); 350 return static_cast<GLuint>(result); 351} 352 353EGLDisplay GLEnv::GetCurrentDisplay() { 354 return eglGetCurrentDisplay(); 355} 356 357int GLEnv::NumberOfComponents(GLenum type) { 358 switch (type) { 359 case GL_BOOL: 360 case GL_FLOAT: 361 case GL_INT: 362 return 1; 363 case GL_BOOL_VEC2: 364 case GL_FLOAT_VEC2: 365 case GL_INT_VEC2: 366 return 2; 367 case GL_INT_VEC3: 368 case GL_FLOAT_VEC3: 369 case GL_BOOL_VEC3: 370 return 3; 371 case GL_BOOL_VEC4: 372 case GL_FLOAT_VEC4: 373 case GL_INT_VEC4: 374 case GL_FLOAT_MAT2: 375 return 4; 376 case GL_FLOAT_MAT3: 377 return 9; 378 case GL_FLOAT_MAT4: 379 return 16; 380 default: 381 return 0; 382 } 383} 384 385void GLEnv::AttachShader(int key, ShaderProgram* shader) { 386 ShaderProgram* existingShader = ShaderWithKey(key); 387 if (existingShader) 388 delete existingShader; 389 attached_shaders_[key] = shader; 390} 391 392void GLEnv::AttachVertexFrame(int key, VertexFrame* frame) { 393 VertexFrame* existingFrame = VertexFrameWithKey(key); 394 if (existingFrame) 395 delete existingFrame; 396 attached_vframes_[key] = frame; 397} 398 399ShaderProgram* GLEnv::ShaderWithKey(int key) { 400 return FindPtrOrNull(attached_shaders_, key); 401} 402 403VertexFrame* GLEnv::VertexFrameWithKey(int key) { 404 return FindPtrOrNull(attached_vframes_, key); 405} 406 407} // namespace filterfw 408} // namespace android 409