/* * Copyright 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ //-------------------------------------------------------------------------------- // GLContext.cpp //-------------------------------------------------------------------------------- //-------------------------------------------------------------------------------- // includes //-------------------------------------------------------------------------------- #include #include "GLContext.h" #include "gl3stub.h" //-------------------------------------------------------------------------------- // eGLContext //-------------------------------------------------------------------------------- //-------------------------------------------------------------------------------- // Ctor //-------------------------------------------------------------------------------- GLContext::GLContext() : _display(EGL_NO_DISPLAY), _surface(EGL_NO_SURFACE), _context(EGL_NO_CONTEXT), _iWidth( 0 ), _iHeight( 0 ), _bES3Support( false ), _bEGLContextInitialized( false ), _bGLESInitialized( false ) { } void GLContext::initGLES() { if( _bGLESInitialized ) return; // //Initialize OpenGL ES 3 if available // const char* versionStr = (const char*)glGetString(GL_VERSION); if (strstr(versionStr, "OpenGL ES 3.") && gl3stubInit()) { _bES3Support = true; _fGLVersion = 3.0f; } else { _fGLVersion = 2.0f; } _bGLESInitialized = true; } //-------------------------------------------------------------------------------- // Dtor //-------------------------------------------------------------------------------- GLContext::~GLContext() { terminate(); } bool GLContext::init( ANativeWindow* window ) { if( _bEGLContextInitialized ) return true; // //Initialize EGL // _window = window; initEGLSurface(); initEGLContext(); initGLES(); _bEGLContextInitialized = true; return true; } bool GLContext::initEGLSurface() { _display = eglGetDisplay( EGL_DEFAULT_DISPLAY ); eglInitialize( _display, 0, 0 ); /* * Here specify the attributes of the desired configuration. * Below, we select an EGLConfig with at least 8 bits per color * component compatible with on-screen windows */ const EGLint attribs[] = { EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, //Request opengl ES2.0 EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_RED_SIZE, 8, EGL_DEPTH_SIZE, 24, EGL_NONE }; _iColorSize = 8; _iDepthSize = 24; EGLint numConfigs; eglChooseConfig( _display, attribs, &_config, 1, &numConfigs ); if( !numConfigs ) { //Fall back to 16bit depth buffer const EGLint attribs[] = { EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, //Request opengl ES2.0 EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_RED_SIZE, 8, EGL_DEPTH_SIZE, 16, EGL_NONE }; eglChooseConfig( _display, attribs, &_config, 1, &numConfigs ); _iDepthSize = 16; } if ( !numConfigs ) { LOGW("Unable to retrieve EGL config"); return false; } _surface = eglCreateWindowSurface( _display, _config, _window, NULL ); eglQuerySurface(_display, _surface, EGL_WIDTH, &_iWidth); eglQuerySurface(_display, _surface, EGL_HEIGHT, &_iHeight); /* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is * guaranteed to be accepted by ANativeWindow_setBuffersGeometry(). * As soon as we picked a EGLConfig, we can safely reconfigure the * ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. */ EGLint format; eglGetConfigAttrib(_display, _config, EGL_NATIVE_VISUAL_ID, &format); ANativeWindow_setBuffersGeometry( _window, 0, 0, format); return true; } bool GLContext::initEGLContext() { const EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, //Request opengl ES2.0 EGL_NONE }; _context = eglCreateContext( _display, _config, NULL, contextAttribs ); if( eglMakeCurrent(_display, _surface, _surface, _context) == EGL_FALSE ) { LOGW("Unable to eglMakeCurrent"); return false; } _bContextValid = true; return true; } EGLint GLContext::swap() { bool b = eglSwapBuffers( _display, _surface); if( !b ) { EGLint err = eglGetError(); if( err == EGL_BAD_SURFACE ) { //Recreate surface initEGLSurface(); } else if( err == EGL_CONTEXT_LOST || err == EGL_BAD_CONTEXT ) { //Context has been lost!! _bContextValid = false; terminate(); initEGLContext(); } return err; } return EGL_SUCCESS; } void GLContext::terminate() { if( _display != EGL_NO_DISPLAY ) { eglMakeCurrent( _display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT ); if ( _context != EGL_NO_CONTEXT ) { eglDestroyContext( _display, _context ); } if( _surface != EGL_NO_SURFACE ) { eglDestroySurface( _display, _surface ); } eglTerminate( _display ); } _display = EGL_NO_DISPLAY; _context = EGL_NO_CONTEXT; _surface = EGL_NO_SURFACE; _bContextValid = false; } EGLint GLContext::resume(ANativeWindow* window) { if( _bEGLContextInitialized == false ) { init( window ); return EGL_SUCCESS; } int32_t iOriginalWidth = _iWidth; int32_t iOriginalHeight = _iHeight; //Create surface _window = window; _surface = eglCreateWindowSurface( _display, _config, _window, NULL ); eglQuerySurface(_display, _surface, EGL_WIDTH, &_iWidth); eglQuerySurface(_display, _surface, EGL_HEIGHT, &_iHeight); if( _iWidth != iOriginalWidth || _iHeight != iOriginalHeight ) { //Screen resized LOGI("Screen resized"); } if( eglMakeCurrent(_display, _surface, _surface, _context) == EGL_TRUE ) return EGL_SUCCESS; EGLint err = eglGetError(); LOGW("Unable to eglMakeCurrent %d", err); if( err == EGL_CONTEXT_LOST ) { //Recreate context LOGI("Re-creating egl context"); initEGLContext(); } else { //Recreate surface terminate(); initEGLSurface(); initEGLContext(); } return err; } void GLContext::suspend() { if( _surface != EGL_NO_SURFACE ) { eglDestroySurface( _display, _surface ); _surface = EGL_NO_SURFACE; } } bool GLContext::invalidate() { terminate(); _bEGLContextInitialized = false; return true; } bool GLContext::checkExtension( const char* extension ) { if( extension == NULL ) return false; std::string extensions = std::string( (char*)glGetString(GL_EXTENSIONS) ); std::string str = std::string( extension ); str.append( " " ); size_t pos = 0; if( extensions.find( extension, pos ) != std::string::npos ) { return true; } return false; }