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