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 31 namespace android { 32 namespace filterfw { 33 34 GLEnv::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 44 GLEnv::~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 79 bool GLEnv::IsInitialized() const { 80 return (contexts_.size() > 0 && 81 surfaces_.size() > 0 && 82 display_ != EGL_NO_DISPLAY); 83 } 84 85 bool GLEnv::Deactivate() { 86 eglMakeCurrent(display(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); 87 return !CheckEGLError("eglMakeCurrent"); 88 } 89 90 bool 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 108 bool GLEnv::SwapBuffers() { 109 const bool result = eglSwapBuffers(display(), surface()) == EGL_TRUE; 110 return !CheckEGLError("eglSwapBuffers") && result; 111 } 112 113 bool 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 126 bool 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, GLConsumer::TEXTURE_EXTERNAL, 169 true, false); 170 window_ = new Surface(producer); 171 172 surfaces_[0] = SurfaceWindowPair(eglCreateWindowSurface(display(), config, window_.get(), NULL), NULL); 173 if (CheckEGLError("eglCreateWindowSurface")) return false; 174 175 // Create context 176 EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; 177 contexts_[0] = eglCreateContext(display(), 178 config, 179 EGL_NO_CONTEXT, 180 context_attribs); 181 if (CheckEGLError("eglCreateContext")) return false; 182 183 created_context_ = created_surface_ = true; 184 185 return true; 186 } 187 188 bool GLEnv::IsActive() const { 189 ALOGV("IsActive()"); 190 return context() == eglGetCurrentContext() 191 && display() == eglGetCurrentDisplay() 192 && surface() == eglGetCurrentSurface(EGL_DRAW); 193 } 194 195 bool GLEnv::IsContextActive() const { 196 return context() == eglGetCurrentContext(); 197 } 198 199 bool GLEnv::IsAnyContextActive() { 200 return eglGetCurrentContext() != EGL_NO_CONTEXT; 201 } 202 203 int GLEnv::AddWindowSurface(const EGLSurface& surface, WindowHandle* window_handle) { 204 const int id = ++max_surface_id_; 205 surfaces_[id] = SurfaceWindowPair(surface, window_handle); 206 return id; 207 } 208 209 int GLEnv::AddSurface(const EGLSurface& surface) { 210 return AddWindowSurface(surface, NULL); 211 } 212 213 bool GLEnv::SwitchToSurfaceId(int surface_id) { 214 ALOGV("SwitchToSurfaceId"); 215 if (surface_id_ != surface_id) { 216 const SurfaceWindowPair* surface = FindOrNull(surfaces_, surface_id); 217 if (surface) { 218 bool wasActive = IsActive(); 219 surface_id_ = surface_id; 220 return wasActive ? Activate() : true; 221 } 222 return false; 223 } 224 return true; 225 } 226 227 bool GLEnv::ReleaseSurfaceId(int surface_id) { 228 if (surface_id > 0) { 229 const SurfaceWindowPair* surface_window_pair = FindOrNull(surfaces_, surface_id); 230 if (surface_window_pair) { 231 if (surface_id_ == surface_id) 232 SwitchToSurfaceId(0); 233 eglDestroySurface(display(), surface_window_pair->first); 234 if (surface_window_pair->second) { 235 surface_window_pair->second->Destroy(); 236 delete surface_window_pair->second; 237 } 238 surfaces_.erase(surface_id); 239 return true; 240 } 241 } 242 return false; 243 } 244 245 bool GLEnv::SetSurfaceTimestamp(int64_t timestamp) { 246 if (surface_id_ > 0) { 247 const SurfaceWindowPair* surface_window_pair = FindOrNull(surfaces_, 248 surface_id_); 249 if (surface_window_pair) { 250 ANativeWindow *window = static_cast<ANativeWindow*>( 251 surface_window_pair->second->InternalHandle()); 252 native_window_set_buffers_timestamp(window, timestamp); 253 return true; 254 } 255 } 256 return false; 257 } 258 259 int GLEnv::FindSurfaceIdForWindow(const WindowHandle* window_handle) { 260 for (std::map<int, SurfaceWindowPair>::iterator it = surfaces_.begin(); 261 it != surfaces_.end(); 262 ++it) { 263 const WindowHandle* my_handle = it->second.second; 264 if (my_handle && my_handle->Equals(window_handle)) { 265 return it->first; 266 } 267 } 268 return -1; 269 } 270 271 272 int GLEnv::AddContext(const EGLContext& context) { 273 const int id = contexts_.size(); 274 contexts_[id] = context; 275 return id; 276 } 277 278 bool GLEnv::SwitchToContextId(int context_id) { 279 const EGLContext* context = FindOrNull(contexts_, context_id); 280 if (context) { 281 if (context_id_ != context_id) { 282 context_id_ = context_id; 283 return Activate(); 284 } 285 return true; 286 } 287 return false; 288 } 289 290 void GLEnv::ReleaseContextId(int context_id) { 291 if (context_id > 0) { 292 const EGLContext* context = FindOrNull(contexts_, context_id); 293 if (context) { 294 contexts_.erase(context_id); 295 if (context_id_ == context_id && IsActive()) 296 SwitchToContextId(0); 297 eglDestroyContext(display(), *context); 298 } 299 } 300 } 301 302 bool GLEnv::CheckGLError(const std::string& op) { 303 bool err = false; 304 for (GLint error = glGetError(); error; error = glGetError()) { 305 ALOGE("GL Error: Operation '%s' caused GL error (0x%x)\n", 306 op.c_str(), 307 error); 308 err = true; 309 } 310 return err; 311 } 312 313 bool GLEnv::CheckEGLError(const std::string& op) { 314 bool err = false; 315 for (EGLint error = eglGetError(); 316 error != EGL_SUCCESS; 317 error = eglGetError()) { 318 ALOGE("EGL Error: Operation '%s' caused EGL error (0x%x)\n", 319 op.c_str(), 320 error); 321 err = true; 322 } 323 return err; 324 } 325 326 bool GLEnv::CheckEGLMakeCurrentError() { 327 bool err = false; 328 for (EGLint error = eglGetError(); 329 error != EGL_SUCCESS; 330 error = eglGetError()) { 331 switch (error) { 332 case EGL_BAD_DISPLAY: 333 ALOGE("EGL Error: Attempting to activate context with bad display!"); 334 break; 335 case EGL_BAD_SURFACE: 336 ALOGE("EGL Error: Attempting to activate context with bad surface!"); 337 break; 338 case EGL_BAD_ACCESS: 339 ALOGE("EGL Error: Attempting to activate context, which is " 340 "already active in another thread!"); 341 break; 342 default: 343 ALOGE("EGL Error: Making EGL rendering context current caused " 344 "error: 0x%x\n", error); 345 } 346 err = true; 347 } 348 return err; 349 } 350 351 GLuint GLEnv::GetCurrentProgram() { 352 GLint result; 353 glGetIntegerv(GL_CURRENT_PROGRAM, &result); 354 ALOG_ASSERT(result >= 0); 355 return static_cast<GLuint>(result); 356 } 357 358 EGLDisplay GLEnv::GetCurrentDisplay() { 359 return eglGetCurrentDisplay(); 360 } 361 362 int GLEnv::NumberOfComponents(GLenum type) { 363 switch (type) { 364 case GL_BOOL: 365 case GL_FLOAT: 366 case GL_INT: 367 return 1; 368 case GL_BOOL_VEC2: 369 case GL_FLOAT_VEC2: 370 case GL_INT_VEC2: 371 return 2; 372 case GL_INT_VEC3: 373 case GL_FLOAT_VEC3: 374 case GL_BOOL_VEC3: 375 return 3; 376 case GL_BOOL_VEC4: 377 case GL_FLOAT_VEC4: 378 case GL_INT_VEC4: 379 case GL_FLOAT_MAT2: 380 return 4; 381 case GL_FLOAT_MAT3: 382 return 9; 383 case GL_FLOAT_MAT4: 384 return 16; 385 default: 386 return 0; 387 } 388 } 389 390 void GLEnv::AttachShader(int key, ShaderProgram* shader) { 391 ShaderProgram* existingShader = ShaderWithKey(key); 392 if (existingShader) 393 delete existingShader; 394 attached_shaders_[key] = shader; 395 } 396 397 void GLEnv::AttachVertexFrame(int key, VertexFrame* frame) { 398 VertexFrame* existingFrame = VertexFrameWithKey(key); 399 if (existingFrame) 400 delete existingFrame; 401 attached_vframes_[key] = frame; 402 } 403 404 ShaderProgram* GLEnv::ShaderWithKey(int key) { 405 return FindPtrOrNull(attached_shaders_, key); 406 } 407 408 VertexFrame* GLEnv::VertexFrameWithKey(int key) { 409 return FindPtrOrNull(attached_vframes_, key); 410 } 411 412 } // namespace filterfw 413 } // namespace android 414