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