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