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