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