| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| #include <EGL/egl.h> |
| #include <EGL/eglplatform.h> |
|
|
| #include <stdlib.h> |
|
|
| #include "egl_setup.h" |
|
|
| |
| #define EGL_CONTEXT_MAJOR_VERSION_KHR 0x3098 |
| #define EGL_CONTEXT_MINOR_VERSION_KHR 0x30FB |
| #define EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR 0x30FD |
| #define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR 0x00000002 |
|
|
| #include <android/log.h> |
|
|
| #define EGLLOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, "egl_setup", __VA_ARGS__)) |
| #define EGLLOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "egl_setup", __VA_ARGS__)) |
| #define EGLLOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "egl_setup", __VA_ARGS__)) |
| #define EGLLOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "egl_setup", __VA_ARGS__)) |
|
|
| static EGLConfig GetBestConfigMatch(EGLDisplay display, EGLint renderable) { |
| EGLint count = 0; |
| if (!eglGetConfigs(display, NULL, 0, &count)) |
| { |
| EGLLOGE("defaultEGLChooser cannot query count of all configs"); |
| return 0; |
| } |
|
|
| EGLint numConfigs; |
|
|
| EGLLOGD("Config count = %d", count); |
|
|
| EGLConfig* configs = new EGLConfig[count]; |
| if (!eglGetConfigs(display, configs, count, &count)) |
| { |
| EGLLOGE("defaultEGLChooser cannot query all configs"); |
| return 0; |
| } |
|
|
| int bestMatch = 1<<30; |
| int bestIndex = -1; |
|
|
| int i; |
| for (i = 0; i < count; i++) |
| { |
| int match = 0; |
| EGLint surfaceType = 0; |
| EGLint blueBits = 0; |
| EGLint greenBits = 0; |
| EGLint redBits = 0; |
| EGLint alphaBits = 0; |
| EGLint depthBits = 0; |
| EGLint stencilBits = 0; |
| EGLint renderableFlags = 0; |
|
|
| eglGetConfigAttrib(display, configs[i], EGL_SURFACE_TYPE, &surfaceType); |
| eglGetConfigAttrib(display, configs[i], EGL_BLUE_SIZE, &blueBits); |
| eglGetConfigAttrib(display, configs[i], EGL_GREEN_SIZE, &greenBits); |
| eglGetConfigAttrib(display, configs[i], EGL_RED_SIZE, &redBits); |
| eglGetConfigAttrib(display, configs[i], EGL_ALPHA_SIZE, &alphaBits); |
| eglGetConfigAttrib(display, configs[i], EGL_DEPTH_SIZE, &depthBits); |
| eglGetConfigAttrib(display, configs[i], EGL_STENCIL_SIZE, &stencilBits); |
| eglGetConfigAttrib(display, configs[i], EGL_RENDERABLE_TYPE, &renderableFlags); |
| EGLLOGD("Config[%d]: R%dG%dB%dA%d D%dS%d Type=%04x Render=%04x", |
| i, redBits, greenBits, blueBits, alphaBits, depthBits, stencilBits, surfaceType, renderableFlags); |
|
|
| |
| |
| if ((surfaceType & EGL_WINDOW_BIT) == 0) |
| continue; |
| if ((renderableFlags & renderable) == 0) |
| continue; |
| if (depthBits < 16) |
| continue; |
| if ((redBits < 5) || (greenBits < 6) || (blueBits < 5)) |
| continue; |
|
|
| |
| int penalty = depthBits - 24; |
| match += penalty * penalty; |
| penalty = redBits - 8; |
| match += penalty * penalty; |
| penalty = greenBits - 8; |
| match += penalty * penalty; |
| penalty = blueBits - 8; |
| match += penalty * penalty; |
| penalty = alphaBits - 8; |
| match += penalty * penalty; |
| penalty = stencilBits - 8; |
| match += penalty * penalty; |
|
|
| |
| if ((match < bestMatch) || (bestIndex == -1)) { |
| bestMatch = match; |
| bestIndex = i; |
| EGLLOGD("Config[%d] is the new best config", i, configs[i]); |
| } |
| } |
|
|
| if (bestIndex < 0) |
| { |
| delete[] configs; |
| EGLLOGE("Fatal error! No valid configs were found!"); |
| return 0; |
| } |
|
|
| EGLConfig config = configs[bestIndex]; |
| delete[] configs; |
|
|
| return config; |
| } |
|
|
| const EGLCapabilities* EGLCapabilities::create() { |
| EGLCapabilities* caps = new EGLCapabilities; |
| EGLBoolean result = EGL_FALSE; |
|
|
| EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); |
|
|
| result = eglInitialize(display, 0, 0); |
| if (!result) { |
| delete caps; |
| return NULL; |
| } |
| |
| caps->m_esConfig = GetBestConfigMatch(display, EGL_OPENGL_ES2_BIT); |
|
|
| result = eglBindAPI(EGL_OPENGL_API); |
| if (result) { |
| caps->m_glConfig = GetBestConfigMatch(display, EGL_OPENGL_BIT); |
| } else { |
| caps->m_glConfig = 0; |
| } |
|
|
| result = eglBindAPI(EGL_OPENGL_ES_API); |
|
|
| return caps; |
| } |
| |
| EGLCapabilities::EGLCapabilities() { |
| m_esConfig = 0; |
| m_glConfig = 0; |
| } |
|
|
| EGLCapabilities::~EGLCapabilities() { |
| } |
|
|
| EGLInfo* EGLInfo::create(const EGLCapabilities& caps, unsigned int api, unsigned int minAPIVersion) { |
| EGLInfo* info = new EGLInfo; |
|
|
| info->m_api = api; |
| info->m_display = eglGetDisplay(EGL_DEFAULT_DISPLAY); |
|
|
| EGLBoolean result = eglInitialize(info->m_display, 0, 0); |
| if (!result) { |
| delete info; |
| return NULL; |
| } |
|
|
| if ((api == API_ES) && caps.isESCapable()) { |
| info->m_config = caps.m_esConfig; |
|
|
| EGLint contextAttrs[] = { EGL_CONTEXT_CLIENT_VERSION, minAPIVersion, |
| EGL_NONE }; |
|
|
| info->m_context = eglCreateContext(info->m_display, info->m_config, |
| NULL, contextAttrs); |
| if (info->m_context == EGL_NO_CONTEXT) { |
| delete info; |
| EGLLOGW("Failed to create context!"); |
| return NULL; |
| } |
| } else if ((api == API_GL) && caps.isGLCapable()) { |
| result = eglBindAPI(EGL_OPENGL_API); |
| if (!result) { |
| delete info; |
| EGLLOGW("Failed to bind GL API!"); |
| return NULL; |
| } |
|
|
| info->m_config = caps.m_glConfig; |
|
|
| EGLint contextAttrs[] = { EGL_CONTEXT_MAJOR_VERSION_KHR, minAPIVersion, |
| EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, |
| EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR, |
| EGL_NONE }; |
|
|
| info->m_context = eglCreateContext(info->m_display, info->m_config, |
| NULL, contextAttrs); |
| if (info->m_context == EGL_NO_CONTEXT) { |
| delete info; |
| EGLLOGW("Failed to create context!"); |
| return NULL; |
| } |
| } else { |
| delete info; |
| return NULL; |
| } |
|
|
| eglQueryContext(info->m_display, info->m_context, EGL_CONTEXT_CLIENT_VERSION, &info->m_apiVersion); |
|
|
| return info; |
| } |
|
|
| bool EGLInfo::createWindowSurface(ANativeWindow* window) { |
| |
| |
| |
| |
| EGLint format; |
| if (!eglGetConfigAttrib(m_display, m_config, EGL_NATIVE_VISUAL_ID, &format)) { |
| EGLLOGE("Fatal error! Failed to get config format!"); |
| return false; |
| } |
|
|
| ANativeWindow_setBuffersGeometry(window, 0, 0, format); |
| m_surface = eglCreateWindowSurface(m_display, m_config, window, NULL); |
|
|
| return m_surface != NULL; |
| } |
|
|
| EGLInfo::EGLInfo() { |
| m_display = EGL_NO_DISPLAY; |
| m_surface = EGL_NO_SURFACE; |
| m_context = EGL_NO_CONTEXT; |
| m_config = 0; |
| } |
|
|
| EGLInfo::~EGLInfo() { |
| eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); |
| if (m_context != EGL_NO_CONTEXT) { |
| eglDestroyContext(m_display, m_context); |
| } |
| if (m_surface != EGL_NO_SURFACE) { |
| eglDestroySurface(m_display, m_surface); |
| } |
| eglTerminate(m_display); |
| } |
|
|
|
|