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