diff --git a/lib/irrlicht/source/Irrlicht/CContextEGL.cpp b/lib/irrlicht/source/Irrlicht/CContextEGL.cpp index 05fbfb93b..ac7fe8a6f 100644 --- a/lib/irrlicht/source/Irrlicht/CContextEGL.cpp +++ b/lib/irrlicht/source/Irrlicht/CContextEGL.cpp @@ -6,376 +6,566 @@ // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in Irrlicht.h -#include "CContextEGL.h" -#include "os.h" -#include "fast_atof.h" - -#if defined(_IRR_COMPILE_WITH_ANDROID_DEVICE_) -#include "android_native_app_glue.h" -#endif +#include "IrrCompileConfig.h" #if defined(_IRR_COMPILE_WITH_EGL_) -namespace irr -{ -namespace video -{ - -ContextEGL::ContextEGL(const SIrrlichtCreationParameters& params, - const SExposedVideoData& data) -{ - EglDisplay = EGL_NO_DISPLAY; - EglSurface = EGL_NO_SURFACE; - EglContext = EGL_NO_CONTEXT; - EglConfig = 0; - EglWindow = 0; - EGLVersionMajor = 1; - EGLVersionMinor = 0; - IsCoreContext = true; - -#if defined(_IRR_COMPILE_WITH_WINDOWS_DEVICE_) - HDc = 0; -#endif - -#if defined(_IRR_COMPILE_WITH_WINDOWS_DEVICE_) - EglWindow = (NativeWindowType)data.OpenGLWin32.HWnd; - HDc = GetDC((HWND)EglWindow); - EglDisplay = eglGetDisplay((NativeDisplayType)HDc); -#elif defined(_IRR_COMPILE_WITH_X11_DEVICE_) - EglWindow = (NativeWindowType)data.OpenGLLinux.X11Window; - EglDisplay = eglGetDisplay((NativeDisplayType)data.OpenGLLinux.X11Display); -#elif defined(_IRR_COMPILE_WITH_ANDROID_DEVICE_) - EglWindow = ((struct android_app *)(params.PrivateData))->window; - EglDisplay = EGL_NO_DISPLAY; +#include +#include +#include +#include + +#ifdef _IRR_COMPILE_WITH_ANDROID_DEVICE_ +#include #endif - if (EglDisplay == EGL_NO_DISPLAY) - { - os::Printer::log("Getting EGL display."); - EglDisplay = eglGetDisplay((NativeDisplayType) EGL_DEFAULT_DISPLAY); - } - - if (EglDisplay == EGL_NO_DISPLAY) - { - os::Printer::log("Could not get EGL display."); - } +#include "CContextEGL.h" +#include "os.h" - if (!eglInitialize(EglDisplay, &EGLVersionMajor, &EGLVersionMinor)) - { - os::Printer::log("Could not initialize EGL display."); - } - else - { - char text[64]; - sprintf(text, "EglDisplay initialized. Egl version %d.%d\n", EGLVersionMajor, EGLVersionMinor); - os::Printer::log(text); - } - - EGLint EglOpenGLBIT = 0; +using namespace irr; - // We need proper OpenGL BIT. - switch (params.DriverType) - { - case EDT_OGLES2: - EglOpenGLBIT = EGL_OPENGL_ES2_BIT; - break; - default: - break; - } - - EGLint Attribs[] = - { - EGL_RED_SIZE, 8, - EGL_GREEN_SIZE, 8, - EGL_BLUE_SIZE, 8, - EGL_ALPHA_SIZE, params.WithAlphaChannel ? 1:0, - EGL_BUFFER_SIZE, params.Bits, - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, - EGL_DEPTH_SIZE, params.ZBufferBits, - EGL_STENCIL_SIZE, params.Stencilbuffer, - EGL_SAMPLE_BUFFERS, params.AntiAlias ? 1:0, - EGL_SAMPLES, params.AntiAlias, - EGL_RENDERABLE_TYPE, EglOpenGLBIT, - EGL_NONE, 0 - }; - - EglConfig = 0; - EGLint NumConfigs = 0; - u32 Steps = 5; - - // Choose the best EGL config. - while (!eglChooseConfig(EglDisplay, Attribs, &EglConfig, 1, &NumConfigs) || !NumConfigs) - { - switch (Steps) - { - case 5: // samples - if (Attribs[19] > 2) - --Attribs[19]; - else - { - Attribs[17] = 0; - Attribs[19] = 0; - --Steps; - } - break; - case 4: // alpha - if (Attribs[7]) - { - Attribs[7] = 0; - - if (params.AntiAlias) - { - Attribs[17] = 1; - Attribs[19] = params.AntiAlias; - Steps = 5; - } - } - else - --Steps; - break; - case 3: // stencil - if (Attribs[15]) - { - Attribs[15] = 0; - - if (params.AntiAlias) - { - Attribs[17] = 1; - Attribs[19] = params.AntiAlias; - Steps = 5; - } - } - else - --Steps; - break; - case 2: // depth size - if (Attribs[13] > 16) - { - Attribs[13] -= 8; - } - else - --Steps; - break; - case 1: // buffer size - if (Attribs[9] > 16) - { - Attribs[9] -= 8; - } - else - --Steps; - break; - default: - os::Printer::log("Could not get config for EGL display."); - return; - } - } - - if (params.AntiAlias && !Attribs[17]) - os::Printer::log("No multisampling."); - - if (params.WithAlphaChannel && !Attribs[7]) - os::Printer::log("No alpha."); - - if (params.Stencilbuffer && !Attribs[15]) - os::Printer::log("No stencil buffer."); - - if (params.ZBufferBits > Attribs[13]) - os::Printer::log("No full depth buffer."); - - if (params.Bits > Attribs[9]) - os::Printer::log("No full color buffer."); - - #if defined(_IRR_COMPILE_WITH_ANDROID_DEVICE_) - /* 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(EglDisplay, EglConfig, EGL_NATIVE_VISUAL_ID, &format); - - ANativeWindow_setBuffersGeometry(EglWindow, 0, 0, format); - #endif - - os::Printer::log(" Creating EglSurface with nativeWindow..."); - EglSurface = eglCreateWindowSurface(EglDisplay, EglConfig, EglWindow, NULL); - - if (EGL_NO_SURFACE == EglSurface) - { - os::Printer::log("FAILED"); - os::Printer::log("Creating EglSurface without nativeWindows..."); - EglSurface = eglCreateWindowSurface(EglDisplay, EglConfig, 0, NULL); - } - - if (EGL_NO_SURFACE == EglSurface) - { - os::Printer::log("FAILED"); - os::Printer::log("Could not create surface for EGL display."); - } - - eglBindAPI(EGL_OPENGL_ES_API); - - os::Printer::log("Creating EglContext..."); - - if (!params.ForceLegacyDevice) - { - os::Printer::log("Trying to create Context for OpenGL ES3."); - EGLint contextAttrib[] = - { - EGL_CONTEXT_CLIENT_VERSION, 3, - EGL_NONE, 0 - }; - - EglContext = eglCreateContext(EglDisplay, EglConfig, EGL_NO_CONTEXT, contextAttrib); - } - - if (EGL_NO_CONTEXT == EglContext) - { - os::Printer::log("Trying to create Context for OpenGL ES2."); - EGLint contextAttrib[] = - { - EGL_CONTEXT_CLIENT_VERSION, 2, - EGL_NONE, 0 - }; - - EglContext = eglCreateContext(EglDisplay, EglConfig, EGL_NO_CONTEXT, contextAttrib); - IsCoreContext = false; - } - - eglMakeCurrent(EglDisplay, EglSurface, EglSurface, EglContext); - if (testEGLError()) - { - os::Printer::log("Could not make Context current for EGL display."); - } - - // set vsync - if (params.Vsync) - eglSwapInterval(EglDisplay, 1); - - os::Printer::log(eglQueryString(EglDisplay, EGL_CLIENT_APIS)); +ContextManagerEGL::ContextManagerEGL() +{ + m_egl_window = 0; + m_egl_display = EGL_NO_DISPLAY; + m_egl_surface = EGL_NO_SURFACE; + m_egl_context = EGL_NO_CONTEXT; + m_egl_config = 0; + m_egl_version = 0; + m_is_legacy_device = false; + m_initialized = false; + + memset(&m_creation_params, 0, sizeof(ContextEGLParams)); } -ContextEGL::~ContextEGL() +ContextManagerEGL::~ContextManagerEGL() { - eglMakeCurrent(EglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + close(); +} - if (EglContext != EGL_NO_CONTEXT) - { - eglDestroyContext(EglDisplay, EglContext); - EglContext = EGL_NO_CONTEXT; - } - if (EglSurface != EGL_NO_SURFACE) - { - eglDestroySurface(EglDisplay, EglSurface); - EglSurface = EGL_NO_SURFACE; - } +bool ContextManagerEGL::init(const ContextEGLParams& params) +{ + if (m_initialized) + return false; - if (EglDisplay != EGL_NO_DISPLAY) - { - eglTerminate(EglDisplay); - EglDisplay = EGL_NO_DISPLAY; - } + m_creation_params = params; + m_egl_window = m_creation_params.window; -#if defined(_IRR_COMPILE_WITH_WINDOWS_DEVICE_) - if (HDc) - ReleaseDC((HWND)EglWindow, HDc); + bool success = initDisplay(); + + if (!success) + { + os::Printer::log("Error: Could not initialize EGL display.\n"); + close(); + return false; + } + + bool has_minimum_requirements = false; + + if (m_creation_params.opengl_api == CEGL_API_OPENGL) + { + if (hasEGLExtension("EGL_KHR_create_context") || m_egl_version >= 150) + { + has_minimum_requirements = true; + eglBindAPI(EGL_OPENGL_API); + } + } + else if (m_creation_params.opengl_api == CEGL_API_OPENGL_ES) + { + if (m_egl_version >= 130) + { + has_minimum_requirements = true; + eglBindAPI(EGL_OPENGL_ES_API); + } + } + + if (!has_minimum_requirements) + { + os::Printer::log("Error: EGL version is too old.\n"); + close(); + return false; + } + + success = chooseConfig(); + + if (!success) + { + os::Printer::log("Error: Couldn't get EGL config.\n"); + close(); + return false; + } + + success = createSurface(); + + if (!success) + { + os::Printer::log("Error: Couldn't create EGL surface.\n"); + close(); + return false; + } + + success = createContext(); + + if (!success) + { + os::Printer::log("Error: Couldn't create OpenGL context.\n"); + close(); + return false; + } + + success = eglMakeCurrent(m_egl_display, m_egl_surface, m_egl_surface, + m_egl_context); + + if (!success) + { + checkEGLError(); + os::Printer::log("Error: Couldn't make context current for EGL display.\n"); + close(); + return false; + } + + eglSwapInterval(m_egl_display, m_creation_params.vsync_enabled ? 1 : 0); + + m_initialized = true; + return true; +} + + +bool ContextManagerEGL::initDisplay() +{ + NativeDisplayType display = (NativeDisplayType)(m_creation_params.display); + +#ifdef _IRR_COMPILE_WITH_ANDROID_DEVICE_ + display = EGL_DEFAULT_DISPLAY; #endif -} + if (display != EGL_DEFAULT_DISPLAY) + { + m_egl_display = eglGetDisplay(display); + } -bool ContextEGL::swapBuffers() -{ - eglSwapBuffers(EglDisplay, EglSurface); - EGLint g = eglGetError(); - - return g == EGL_SUCCESS; -} + if (m_egl_display == EGL_NO_DISPLAY) + { + m_egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + } + if (m_egl_display == EGL_NO_DISPLAY) + { + return false; + } -void ContextEGL::reloadEGLSurface(void* window) -{ - os::Printer::log("Reload EGL surface."); + int egl_version_major = 0; + int egl_version_minor = 0; - #if defined(_IRR_COMPILE_WITH_ANDROID_DEVICE_) - EglWindow = (ANativeWindow*)window; - #endif + bool success = eglInitialize(m_egl_display, &egl_version_major, + &egl_version_minor); - if (!EglWindow) - os::Printer::log("Invalid EGL window."); - - eglMakeCurrent(EglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - - eglDestroySurface(EglDisplay, EglSurface); - - EglSurface = eglCreateWindowSurface(EglDisplay, EglConfig, EglWindow, 0); - - if (EGL_NO_SURFACE == EglSurface) - os::Printer::log("Could not create EGL surface."); - - eglMakeCurrent(EglDisplay, EglSurface, EglSurface, EglContext); -} - - -bool ContextEGL::testEGLError() -{ -#if defined(_DEBUG) - EGLint g = eglGetError(); - switch (g) + if (success) { - case EGL_SUCCESS: - return false; - case EGL_NOT_INITIALIZED : - os::Printer::log("Not Initialized", ELL_ERROR); - break; - case EGL_BAD_ACCESS: - os::Printer::log("Bad Access", ELL_ERROR); - break; - case EGL_BAD_ALLOC: - os::Printer::log("Bad Alloc", ELL_ERROR); - break; - case EGL_BAD_ATTRIBUTE: - os::Printer::log("Bad Attribute", ELL_ERROR); - break; - case EGL_BAD_CONTEXT: - os::Printer::log("Bad Context", ELL_ERROR); - break; - case EGL_BAD_CONFIG: - os::Printer::log("Bad Config", ELL_ERROR); - break; - case EGL_BAD_CURRENT_SURFACE: - os::Printer::log("Bad Current Surface", ELL_ERROR); - break; - case EGL_BAD_DISPLAY: - os::Printer::log("Bad Display", ELL_ERROR); - break; - case EGL_BAD_SURFACE: - os::Printer::log("Bad Surface", ELL_ERROR); - break; - case EGL_BAD_MATCH: - os::Printer::log("Bad Match", ELL_ERROR); - break; - case EGL_BAD_PARAMETER: - os::Printer::log("Bad Parameter", ELL_ERROR); - break; - case EGL_BAD_NATIVE_PIXMAP: - os::Printer::log("Bad Native Pixmap", ELL_ERROR); - break; - case EGL_BAD_NATIVE_WINDOW: - os::Printer::log("Bad Native Window", ELL_ERROR); - break; - case EGL_CONTEXT_LOST: - os::Printer::log("Context Lost", ELL_ERROR); - break; - }; - return true; -#else - return false; + m_egl_version = 100 * egl_version_major + 10 * egl_version_minor; + } + + return success; +} + + +bool ContextManagerEGL::chooseConfig() +{ + std::vector config_attribs; + config_attribs.push_back(EGL_RED_SIZE); + config_attribs.push_back(8); + config_attribs.push_back(EGL_GREEN_SIZE); + config_attribs.push_back(8); + config_attribs.push_back(EGL_BLUE_SIZE); + config_attribs.push_back(8); + config_attribs.push_back(EGL_ALPHA_SIZE); + config_attribs.push_back(m_creation_params.with_alpha_channel ? 8 : 0); + // config_attribs.push_back(EGL_BUFFER_SIZE); + // config_attribs.push_back(24); + config_attribs.push_back(EGL_DEPTH_SIZE); + config_attribs.push_back(16); + // config_attribs.push_back(EGL_STENCIL_SIZE); + // config_attribs.push_back(stencil_buffer); + // config_attribs.push_back(EGL_SAMPLE_BUFFERS); + // config_attribs.push_back(antialias ? 1 : 0); + // config_attribs.push_back(EGL_SAMPLES); + // config_attribs.push_back(antialias); + + if (m_creation_params.opengl_api == CEGL_API_OPENGL) + { + config_attribs.push_back(EGL_RENDERABLE_TYPE); + config_attribs.push_back(EGL_OPENGL_BIT); + } + else if (m_creation_params.opengl_api == CEGL_API_OPENGL_ES) + { + config_attribs.push_back(EGL_RENDERABLE_TYPE); + config_attribs.push_back(EGL_OPENGL_ES2_BIT); + } + + if (m_creation_params.surface_type == CEGL_SURFACE_WINDOW) + { + config_attribs.push_back(EGL_SURFACE_TYPE); + config_attribs.push_back(EGL_WINDOW_BIT); + } + else if (m_creation_params.surface_type == CEGL_SURFACE_PBUFFER) + { + config_attribs.push_back(EGL_SURFACE_TYPE); + config_attribs.push_back(EGL_PBUFFER_BIT); + } + + config_attribs.push_back(EGL_NONE); + config_attribs.push_back(0); + + EGLint num_configs = 0; + + bool success = eglChooseConfig(m_egl_display, &config_attribs[0], + &m_egl_config, 1, &num_configs); + + if (!success || num_configs == 0) + { + return false; + } + +#ifdef _IRR_COMPILE_WITH_ANDROID_DEVICE_ + EGLint format = 0; + eglGetConfigAttrib(m_egl_display, m_egl_config, EGL_NATIVE_VISUAL_ID, + &format); + ANativeWindow_setBuffersGeometry(m_egl_window, 0, 0, format); #endif + + return true; } + +bool ContextManagerEGL::createSurface() +{ + if (m_creation_params.surface_type == CEGL_SURFACE_WINDOW) + { + if (m_egl_surface == EGL_NO_SURFACE) + { + m_egl_surface = eglCreateWindowSurface(m_egl_display, m_egl_config, + m_egl_window, NULL); + } + + if (m_egl_surface == EGL_NO_SURFACE) + { + m_egl_surface = eglCreateWindowSurface(m_egl_display, m_egl_config, + 0, NULL); + } + } + else if (m_creation_params.surface_type == CEGL_SURFACE_PBUFFER) + { + if (m_egl_surface == EGL_NO_SURFACE) + { + std::vector pbuffer_attribs; + pbuffer_attribs.push_back(EGL_WIDTH); + pbuffer_attribs.push_back(m_creation_params.pbuffer_width); + pbuffer_attribs.push_back(EGL_HEIGHT); + pbuffer_attribs.push_back(m_creation_params.pbuffer_height); + pbuffer_attribs.push_back(EGL_NONE); + pbuffer_attribs.push_back(0); + + m_egl_surface = eglCreatePbufferSurface(m_egl_display, + m_egl_config, + &pbuffer_attribs[0]); + } + + if (m_egl_surface == EGL_NO_SURFACE) + { + std::vector pbuffer_attribs; + pbuffer_attribs.push_back(EGL_WIDTH); + pbuffer_attribs.push_back(m_creation_params.pbuffer_width); + pbuffer_attribs.push_back(EGL_HEIGHT); + pbuffer_attribs.push_back(m_creation_params.pbuffer_height); + pbuffer_attribs.push_back(EGL_LARGEST_PBUFFER); + pbuffer_attribs.push_back(EGL_TRUE); + pbuffer_attribs.push_back(EGL_NONE); + pbuffer_attribs.push_back(0); + + m_egl_surface = eglCreatePbufferSurface(m_egl_display, + m_egl_config, + &pbuffer_attribs[0]); + } + } + + return m_egl_surface != EGL_NO_SURFACE; } + +bool ContextManagerEGL::createContext() +{ + m_is_legacy_device = false; + + if (m_creation_params.opengl_api == CEGL_API_OPENGL_ES) + { + if (!m_creation_params.force_legacy_device) + { + if (m_egl_context == EGL_NO_CONTEXT) + { + std::vector context_attribs; + context_attribs.push_back(EGL_CONTEXT_CLIENT_VERSION); + context_attribs.push_back(3); + context_attribs.push_back(EGL_NONE); + context_attribs.push_back(0); + + m_egl_context = eglCreateContext(m_egl_display, + m_egl_config, + EGL_NO_CONTEXT, + &context_attribs[0]); + } + } + + if (m_egl_context == EGL_NO_CONTEXT) + { + m_is_legacy_device = true; + + std::vector context_attribs; + context_attribs.push_back(EGL_CONTEXT_CLIENT_VERSION); + context_attribs.push_back(2); + context_attribs.push_back(EGL_NONE); + context_attribs.push_back(0); + + m_egl_context = eglCreateContext(m_egl_display, + m_egl_config, + EGL_NO_CONTEXT, + &context_attribs[0]); + } + } + else if (m_creation_params.opengl_api == CEGL_API_OPENGL) + { + if (!m_creation_params.force_legacy_device) + { + if (m_egl_context == EGL_NO_CONTEXT) + { + std::vector context_attribs; + context_attribs.push_back(EGL_CONTEXT_MAJOR_VERSION_KHR); + context_attribs.push_back(4); + context_attribs.push_back(EGL_CONTEXT_MINOR_VERSION_KHR); + context_attribs.push_back(3); + context_attribs.push_back(EGL_NONE); + context_attribs.push_back(0); + + m_egl_context = eglCreateContext(m_egl_display, + m_egl_config, + EGL_NO_CONTEXT, + &context_attribs[0]); + } + + if (m_egl_context == EGL_NO_CONTEXT) + { + std::vector context_attribs; + context_attribs.push_back(EGL_CONTEXT_MAJOR_VERSION_KHR); + context_attribs.push_back(3); + context_attribs.push_back(EGL_CONTEXT_MINOR_VERSION_KHR); + context_attribs.push_back(3); + context_attribs.push_back(EGL_NONE); + context_attribs.push_back(0); + + m_egl_context = eglCreateContext(m_egl_display, + m_egl_config, + EGL_NO_CONTEXT, + &context_attribs[0]); + } + + if (m_egl_context == EGL_NO_CONTEXT) + { + std::vector context_attribs; + context_attribs.push_back(EGL_CONTEXT_MAJOR_VERSION_KHR); + context_attribs.push_back(3); + context_attribs.push_back(EGL_CONTEXT_MINOR_VERSION_KHR); + context_attribs.push_back(1); + context_attribs.push_back(EGL_NONE); + context_attribs.push_back(0); + + m_egl_context = eglCreateContext(m_egl_display, + m_egl_config, + EGL_NO_CONTEXT, + &context_attribs[0]); + } + } + + if (m_egl_context == EGL_NO_CONTEXT) + { + m_is_legacy_device = true; + + std::vector context_attribs; + context_attribs.push_back(EGL_CONTEXT_MAJOR_VERSION_KHR); + context_attribs.push_back(2); + context_attribs.push_back(EGL_CONTEXT_MINOR_VERSION_KHR); + context_attribs.push_back(1); + context_attribs.push_back(EGL_NONE); + context_attribs.push_back(0); + + m_egl_context = eglCreateContext(m_egl_display, + m_egl_config, + EGL_NO_CONTEXT, + &context_attribs[0]); + } + } + + return m_egl_context != EGL_NO_CONTEXT; +} + + +void ContextManagerEGL::close() +{ + eglMakeCurrent(m_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, + EGL_NO_CONTEXT); + + if (m_egl_context != EGL_NO_CONTEXT) + { + eglDestroyContext(m_egl_display, m_egl_context); + m_egl_context = EGL_NO_CONTEXT; + } + + if (m_egl_surface != EGL_NO_SURFACE) + { + eglDestroySurface(m_egl_display, m_egl_surface); + m_egl_surface = EGL_NO_SURFACE; + } + + if (m_egl_display != EGL_NO_DISPLAY) + { + eglTerminate(m_egl_display); + m_egl_display = EGL_NO_DISPLAY; + } +} + + +bool ContextManagerEGL::swapBuffers() +{ + bool success = eglSwapBuffers(m_egl_display, m_egl_surface); + +#ifdef DEBUG + if (!success) + { + eglGetError(); + } +#endif + + return success; +} + + +void ContextManagerEGL::reloadEGLSurface(void* window) +{ +#ifdef _IRR_COMPILE_WITH_ANDROID_DEVICE_ + m_egl_window = (ANativeWindow*)window; + + if (!m_egl_window) + { + os::Printer::log("Error: Invalid EGL window.\n"); + } +#endif + + eglMakeCurrent(m_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, + EGL_NO_CONTEXT); + + eglDestroySurface(m_egl_display, m_egl_surface); + m_egl_surface = EGL_NO_SURFACE; + + bool success = createSurface(); + + if (!success) + { + os::Printer::log("Error: Could not create EGL surface."); + } + + success = eglMakeCurrent(m_egl_display, m_egl_surface, m_egl_surface, + m_egl_context); + + if (!success) + { + checkEGLError(); + os::Printer::log("Error: Couldn't make context current for EGL display.\n"); + } +} + + +bool ContextManagerEGL::getSurfaceDimensions(int* width, int* height) +{ + if (!eglQuerySurface(m_egl_display, m_egl_surface, EGL_WIDTH, width)) + return false; + + if (!eglQuerySurface(m_egl_display, m_egl_surface, EGL_HEIGHT, height)) + return false; + + return true; +} + + +bool ContextManagerEGL::hasEGLExtension(const char* extension) +{ + const char* extensions = eglQueryString(m_egl_display, EGL_EXTENSIONS); + + if (extensions && strstr(extensions, extension) != NULL) + { + return true; + } + + return false; +} + + +bool ContextManagerEGL::checkEGLError() +{ + bool result = true; + + switch (eglGetError()) + { + case EGL_SUCCESS: + result = false; + break; + case EGL_NOT_INITIALIZED: + os::Printer::log("Error: EGL_NOT_INITIALIZED\n"); + break; + case EGL_BAD_ACCESS: + os::Printer::log("Error: EGL_BAD_ACCESS\n"); + break; + case EGL_BAD_ALLOC: + os::Printer::log("Error: EGL_BAD_ALLOC\n"); + break; + case EGL_BAD_ATTRIBUTE: + os::Printer::log("Error: EGL_BAD_ATTRIBUTE\n"); + break; + case EGL_BAD_CONTEXT: + os::Printer::log("Error: EGL_BAD_CONTEXT\n"); + break; + case EGL_BAD_CONFIG: + os::Printer::log("Error: EGL_BAD_CONFIG\n"); + break; + case EGL_BAD_CURRENT_SURFACE: + os::Printer::log("Error: EGL_BAD_CURRENT_SURFACE\n"); + break; + case EGL_BAD_DISPLAY: + os::Printer::log("Error: EGL_BAD_DISPLAY\n"); + break; + case EGL_BAD_SURFACE: + os::Printer::log("Error: EGL_BAD_SURFACE\n"); + break; + case EGL_BAD_MATCH: + os::Printer::log("Error: EGL_BAD_MATCH\n"); + break; + case EGL_BAD_PARAMETER: + os::Printer::log("Error: EGL_BAD_PARAMETER\n"); + break; + case EGL_BAD_NATIVE_PIXMAP: + os::Printer::log("Error: EGL_BAD_NATIVE_PIXMAP\n"); + break; + case EGL_BAD_NATIVE_WINDOW: + os::Printer::log("Error: EGL_BAD_NATIVE_WINDOW\n"); + break; + case EGL_CONTEXT_LOST: + os::Printer::log("Error: EGL_CONTEXT_LOST\n"); + break; + default: + os::Printer::log("Error: Unknown EGL error.\n"); + break; + }; + + return result; } #endif diff --git a/lib/irrlicht/source/Irrlicht/CContextEGL.h b/lib/irrlicht/source/Irrlicht/CContextEGL.h index a7cbe1b42..beae64d47 100644 --- a/lib/irrlicht/source/Irrlicht/CContextEGL.h +++ b/lib/irrlicht/source/Irrlicht/CContextEGL.h @@ -6,71 +6,75 @@ // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in Irrlicht.h -#ifndef __C_CONTEXT_EGL_H_INCLUDED__ -#define __C_CONTEXT_EGL_H_INCLUDED__ +#ifndef CONTEXT_EGL_HPP +#define CONTEXT_EGL_HPP #include "IrrCompileConfig.h" #if defined(_IRR_COMPILE_WITH_EGL_) -#include "SIrrCreationParameters.h" -#include "SExposedVideoData.h" - -#if defined(_IRR_COMPILE_WITH_ANDROID_DEVICE_) #include -#else -#include -#include -#endif +#include -#if defined(_IRR_WINDOWS_API_) -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#include -#endif - -#ifdef _MSC_VER -#pragma comment(lib, "libEGL.lib") -#endif - - -namespace irr +enum ContextEGLOpenGLAPI { -namespace video -{ - -class ContextEGL -{ -private: - NativeWindowType EglWindow; - void* EglDisplay; - void* EglSurface; - void* EglContext; - EGLConfig EglConfig; - int EGLVersionMajor; - int EGLVersionMinor; - -#ifdef _IRR_COMPILE_WITH_WINDOWS_DEVICE_ - HDC HDc; -#endif - - bool IsCoreContext; - - bool testEGLError(); - -public: - ContextEGL(const SIrrlichtCreationParameters& params, - const SExposedVideoData& data); - ~ContextEGL(); - - void reloadEGLSurface(void* window); - bool swapBuffers(); - bool isCoreContext() {return IsCoreContext;} + CEGL_API_OPENGL, + CEGL_API_OPENGL_ES }; -} -} +enum ContextEGLSurfaceType +{ + CEGL_SURFACE_WINDOW, + CEGL_SURFACE_PBUFFER +}; + +struct ContextEGLParams +{ + ContextEGLOpenGLAPI opengl_api; + ContextEGLSurfaceType surface_type; + EGLNativeWindowType window; + EGLNativeDisplayType display; + bool force_legacy_device; + bool with_alpha_channel; + bool vsync_enabled; + int pbuffer_width; + int pbuffer_height; +}; + + +class ContextManagerEGL +{ +private: + NativeWindowType m_egl_window; + EGLDisplay m_egl_display; + EGLSurface m_egl_surface; + EGLContext m_egl_context; + EGLConfig m_egl_config; + + ContextEGLParams m_creation_params; + bool m_is_legacy_device; + bool m_initialized; + int m_egl_version; + + bool initDisplay(); + bool chooseConfig(); + bool createSurface(); + bool createContext(); + bool hasEGLExtension(const char* extension); + bool checkEGLError(); + +public: + ContextManagerEGL(); + ~ContextManagerEGL(); + + bool init(const ContextEGLParams& params); + void close(); + + void reloadEGLSurface(void* window); + bool swapBuffers(); + bool isLegacyDevice() {return m_is_legacy_device;} + bool getSurfaceDimensions(int* width, int* height); +}; #endif diff --git a/lib/irrlicht/source/Irrlicht/COGLES2Driver.cpp b/lib/irrlicht/source/Irrlicht/COGLES2Driver.cpp index 68d3c1cf6..16991fd95 100644 --- a/lib/irrlicht/source/Irrlicht/COGLES2Driver.cpp +++ b/lib/irrlicht/source/Irrlicht/COGLES2Driver.cpp @@ -51,6 +51,9 @@ namespace video , ViewFramebuffer(0) , ViewRenderbuffer(0) , ViewDepthRenderbuffer(0) +#endif +#if defined(_IRR_COMPILE_WITH_WINDOWS_DEVICE_) + , HDc(0) #endif , Params(params) { @@ -60,10 +63,38 @@ namespace video ExposedData = data; #if defined(_IRR_COMPILE_WITH_EGL_) - EglContext = new ContextEGL(params, data); - useCoreContext = EglContext->isCoreContext(); + EglContext = new ContextManagerEGL(); + + ContextEGLParams egl_params; + egl_params.opengl_api = CEGL_API_OPENGL_ES; + egl_params.surface_type = CEGL_SURFACE_WINDOW; + egl_params.force_legacy_device = Params.ForceLegacyDevice; + egl_params.with_alpha_channel = Params.WithAlphaChannel; + egl_params.vsync_enabled = Params.Vsync; + +#if defined(_IRR_COMPILE_WITH_WINDOWS_DEVICE_) + egl_params.window = (EGLNativeWindowType)(data.OpenGLWin32.HWnd); + HDc = GetDC(data.OpenGLWin32.HWnd); + egl_params.display = (NativeDisplayType)(HDc); +#elif defined(_IRR_COMPILE_WITH_X11_DEVICE_) + egl_params.window = data.OpenGLLinux.X11Window; + egl_params.display = (EGLNativeDisplayType)(data.OpenGLLinux.X11Display); +#elif defined(_IRR_COMPILE_WITH_ANDROID_DEVICE_) + egl_params.window = ((struct android_app *)(params.PrivateData))->window; + egl_params.display = NULL; +#endif + + EglContext->init(egl_params); + useCoreContext = !EglContext->isLegacyDevice(); genericDriverInit(params.WindowSize, params.Stencilbuffer); + +#ifdef _IRR_COMPILE_WITH_ANDROID_DEVICE_ + int width = 0; + int height = 0; + EglContext->getSurfaceDimensions(&width, &height); + CNullDriver::ScreenSize = core::dimension2d(width, height); +#endif #elif defined(_IRR_COMPILE_WITH_IPHONE_DEVICE_) Device = device; @@ -115,6 +146,11 @@ namespace video #if defined(_IRR_COMPILE_WITH_EGL_) delete EglContext; + +#if defined(_IRR_COMPILE_WITH_WINDOWS_DEVICE_) + if (HDc) + ReleaseDC((ExposedData.OpenGLWin32.HWnd, HDc); +#endif #elif defined(_IRR_COMPILE_WITH_IPHONE_DEVICE_) diff --git a/lib/irrlicht/source/Irrlicht/COGLES2Driver.h b/lib/irrlicht/source/Irrlicht/COGLES2Driver.h index 328b13189..007dc2dbc 100644 --- a/lib/irrlicht/source/Irrlicht/COGLES2Driver.h +++ b/lib/irrlicht/source/Irrlicht/COGLES2Driver.h @@ -38,6 +38,8 @@ #endif #include "COGLES2ExtensionHandler.h" +class ContextManagerEGL; + namespace irr { namespace video @@ -48,7 +50,6 @@ namespace video class COGLES2Renderer2D; class COGLES2NormalMapRenderer; class COGLES2ParallaxMapRenderer; - class ContextEGL; class COGLES2Driver : public CNullDriver, public IMaterialRendererServices, public COGLES2ExtensionHandler { @@ -371,7 +372,7 @@ namespace video COGLES2CallBridge* getBridgeCalls() const; #if defined(_IRR_COMPILE_WITH_EGL_) - ContextEGL* getEGLContext() {return EglContext;} + ContextManagerEGL* getEGLContext() {return EglContext;} #endif private: @@ -458,7 +459,7 @@ namespace video COGLES2Renderer2D* MaterialRenderer2D; #if defined(_IRR_COMPILE_WITH_EGL_) - ContextEGL* EglContext; + ContextManagerEGL* EglContext; #endif #if defined(_IRR_COMPILE_WITH_IPHONE_DEVICE_) CIrrDeviceIPhone* Device; @@ -466,6 +467,9 @@ namespace video GLuint ViewRenderbuffer; GLuint ViewDepthRenderbuffer; #endif +#ifdef _IRR_COMPILE_WITH_WINDOWS_DEVICE_ + HDC HDc; +#endif SIrrlichtCreationParameters Params; };