// Copyright (c) 2010 The Chromium OS Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // To use runtime linking, uncomment the #define OPENGL_ES_IMPORT_FUNCTIONS, // and pass libGLESxx.so libEGLxx.so in the command line as input // parameters. // Otherwise, comment out #define OPENGL_ES_IMPORT_FUNCTIONS and pass no // parameters in the command line. #include <stdio.h> #include <EGL/egl.h> #include <GLES2/gl2.h> #include <X11/Xlib.h> #include <X11/Xutil.h> #define OPENGL_ES_IMPORT_FUNCTIONS #ifdef OPENGL_ES_IMPORT_FUNCTIONS #include <dlfcn.h> EGLDisplay (*FP_eglGetDisplay)(NativeDisplayType display) = NULL; EGLBoolean (*FP_eglInitialize)(EGLDisplay dpy, EGLint* major, EGLint* minor) = NULL; EGLBoolean (*FP_eglGetConfigs)(EGLDisplay dpy, EGLConfig* configs, EGLint config_size, EGLint* num_config) = NULL; EGLBoolean (*FP_eglChooseConfig)(EGLDisplay dpy, const EGLint* attrib_list, EGLConfig* configs, EGLint config_size, EGLint* num_config) = NULL; EGLContext (*FP_eglCreateContext)(EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint* attrib_list) = NULL; EGLBoolean (*FP_eglGetConfigAttrib)(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint* value) = NULL; EGLSurface (*FP_eglCreateWindowSurface)(EGLDisplay dpy, EGLConfig config, NativeWindowType window, const EGLint* attrib_list) = NULL; EGLBoolean (*FP_eglMakeCurrent)(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) = NULL; EGLBoolean (*FP_eglDestroyContext)(EGLDisplay dpy, EGLContext ctx) = NULL; EGLBoolean (*FP_eglDestroySurface)(EGLDisplay dpy, EGLSurface surface) = NULL; EGLBoolean (*FP_eglTerminate)(EGLDisplay dpy) = NULL; const char* (*FP_eglQueryString)(EGLDisplay dpy, EGLint name) = NULL; const GLubyte* (*FP_glGetString)(GLenum name) = NULL; #define eglGetDisplay FP_eglGetDisplay #define eglInitialize FP_eglInitialize #define eglGetConfigs FP_eglGetConfigs #define eglChooseConfig FP_eglChooseConfig #define eglCreateContext FP_eglCreateContext #define eglGetConfigAttrib FP_eglGetConfigAttrib #define eglCreateWindowSurface FP_eglCreateWindowSurface #define eglMakeCurrent FP_eglMakeCurrent #define eglDestroyContext FP_eglDestroyContext #define eglDestroySurface FP_eglDestroySurface #define eglTerminate FP_eglTerminate #define eglQueryString FP_eglQueryString #define glGetString FP_glGetString typedef EGLDisplay (*FT_eglGetDisplay)(NativeDisplayType); typedef EGLBoolean (*FT_eglInitialize)(EGLDisplay, EGLint*, EGLint*); typedef EGLBoolean (*FT_eglGetConfigs)(EGLDisplay, EGLConfig*, EGLint, EGLint*); typedef EGLBoolean (*FT_eglChooseConfig)(EGLDisplay, const EGLint*, EGLConfig*, EGLint, EGLint*); typedef EGLContext (*FT_eglCreateContext)(EGLDisplay, EGLConfig, EGLContext, const EGLint*); typedef EGLBoolean (*FT_eglGetConfigAttrib)(EGLDisplay, EGLConfig, EGLint, EGLint*); typedef EGLSurface (*FT_eglCreateWindowSurface)(EGLDisplay, EGLConfig, NativeWindowType, const EGLint*); typedef EGLBoolean (*FT_eglMakeCurrent)(EGLDisplay, EGLSurface, EGLSurface, EGLContext); typedef EGLBoolean (*FT_eglDestroyContext)(EGLDisplay, EGLContext); typedef EGLBoolean (*FT_eglDestroySurface)(EGLDisplay, EGLSurface); typedef EGLBoolean (*FT_eglTerminate)(EGLDisplay); typedef const char* (*FT_eglQueryString)(EGLDisplay, EGLint); typedef const GLubyte* (*FT_glGetString)(GLenum); bool LoadDLFunction(void** func_handle, const char* func_name, void* dl_handle) { *func_handle = dlsym(dl_handle, func_name); if (*func_handle == NULL) { printf("ERROR: fail to load %s\n", func_name); return false; } return true; } bool EntryImportGL(char* lib_gles, char* lib_egl, void** handle_gles, void** handle_egl) { *handle_gles = dlopen(lib_gles, RTLD_LAZY); if (*handle_gles == NULL) { printf("ERROR: %s\n", dlerror()); return false; } *handle_egl = dlopen(lib_egl, RTLD_LAZY); if (*handle_egl == NULL) { printf("ERROR: %s\n", dlerror()); return false; } bool rt = true; void* tmp; rt &= LoadDLFunction(&tmp, "eglGetDisplay", *handle_egl); FP_eglGetDisplay = reinterpret_cast<FT_eglGetDisplay>(tmp); rt &= LoadDLFunction(&tmp, "eglInitialize", *handle_egl); FP_eglInitialize = reinterpret_cast<FT_eglInitialize>(tmp); rt &= LoadDLFunction(&tmp, "eglGetConfigs", *handle_egl); FP_eglGetConfigs = reinterpret_cast<FT_eglGetConfigs>(tmp); rt &= LoadDLFunction(&tmp, "eglChooseConfig", *handle_egl); FP_eglChooseConfig = reinterpret_cast<FT_eglChooseConfig>(tmp); rt &= LoadDLFunction(&tmp, "eglCreateContext", *handle_egl); FP_eglCreateContext = reinterpret_cast<FT_eglCreateContext>(tmp); rt &= LoadDLFunction(&tmp, "eglGetConfigAttrib", *handle_egl); FP_eglGetConfigAttrib = reinterpret_cast<FT_eglGetConfigAttrib>(tmp); rt &= LoadDLFunction(&tmp, "eglCreateWindowSurface", *handle_egl); FP_eglCreateWindowSurface = reinterpret_cast<FT_eglCreateWindowSurface>(tmp); rt &= LoadDLFunction(&tmp, "eglMakeCurrent", *handle_egl); FP_eglMakeCurrent = reinterpret_cast<FT_eglMakeCurrent>(tmp); rt &= LoadDLFunction(&tmp, "eglDestroyContext", *handle_egl); FP_eglDestroyContext = reinterpret_cast<FT_eglDestroyContext>(tmp); rt &= LoadDLFunction(&tmp, "eglDestroySurface", *handle_egl); FP_eglDestroySurface = reinterpret_cast<FT_eglDestroySurface>(tmp); rt &= LoadDLFunction(&tmp, "eglTerminate", *handle_egl); FP_eglTerminate = reinterpret_cast<FT_eglTerminate>(tmp); rt &= LoadDLFunction(&tmp, "eglQueryString", *handle_egl); FP_eglQueryString = reinterpret_cast<FT_eglQueryString>(tmp); rt &= LoadDLFunction(&tmp, "glGetString", *handle_gles); FP_glGetString = reinterpret_cast<FT_glGetString>(tmp); return rt; } void ExitImportGL(void* handle_gles, void* handle_egl) { if (handle_gles != NULL) dlclose(handle_gles); if (handle_egl != NULL) dlclose(handle_egl); } #endif // OPENGL_ES_IMPORT_FUNCTIONS bool InitGraphics(Display** display, EGLDisplay* egl_display, EGLContext* egl_context, EGLSurface* egl_surface) { const int kWindowWidth = 100; const int kWindowHeight = 100; const EGLint config_attribs[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_NONE }; const EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; // XWindow init. *display = XOpenDisplay(NULL); if (*display == NULL) { printf("ERROR: XOpenDisplay failed\n"); return false; } int screen = XDefaultScreen(*display); Window window = XCreateSimpleWindow(*display, RootWindow(*display, screen), 0, 0, kWindowWidth, kWindowHeight, 0, 0, WhitePixel(*display, screen)); XMapWindow(*display, window); XSync(*display, True); // EGL init. *egl_display = eglGetDisplay((EGLNativeDisplayType)*display); EGLint no_major, no_minor; EGLBoolean rt_code = eglInitialize(*egl_display, &no_major, &no_minor); if (rt_code == EGL_FALSE) { printf("ERROR: eglInitialize failed\n"); return false; } // Print out version info. printf("EGL_VERSION = %d.%d\n", static_cast<int>(no_major), static_cast<int>(no_minor)); // Config. EGLint num_configs; EGLConfig egl_config; rt_code = eglChooseConfig(*egl_display, config_attribs, &egl_config, 1, &num_configs); if (rt_code == EGL_FALSE || num_configs != 1) { printf("ERROR: eglChooseConfig failed\n"); return false; } // Surface. *egl_surface = eglCreateWindowSurface(*egl_display, egl_config, (NativeWindowType)window, NULL); if (*egl_surface == EGL_NO_SURFACE) { printf("ERROR: eglCreateWindowSurface failed\n"); return false; } // Context. *egl_context = eglCreateContext(*egl_display, egl_config, EGL_NO_CONTEXT, context_attribs); if (*egl_context == EGL_NO_CONTEXT) { printf("ERROR: eglCreateContext failed\n"); return false; } // Make current. rt_code = eglMakeCurrent(*egl_display, *egl_surface, *egl_surface, *egl_context); if (rt_code == EGL_FALSE) { printf("ERROR: eglMakeCurrent failed\n"); return false; } return true; } void ExitGraphics(EGLDisplay egl_display, EGLContext egl_context, EGLSurface egl_surface) { if (egl_display != EGL_NO_DISPLAY) { eglMakeCurrent(egl_display, NULL, NULL, NULL); if (egl_context != EGL_NO_CONTEXT) eglDestroyContext(egl_display, egl_context); if (egl_surface != EGL_NO_SURFACE) eglDestroySurface(egl_display, egl_surface); eglTerminate(egl_display); } } bool GetGLESVersion() { const GLubyte* version_string = glGetString(GL_VERSION); if (version_string == NULL) { printf("ERROR: glGetString(GL_VERSION) failed\n"); return false; } printf("GLES_VERSION = %s\n", version_string); return true; } bool GetGLESExtensions() { const GLubyte* ext_string = glGetString(GL_EXTENSIONS); if (ext_string == NULL) { printf("ERROR: glGetString(GL_EXTENSIONS) failed\n"); return false; } printf("GLES_EXTENSIONS = %s\n", ext_string); return true; } bool GetEGLExtensions(EGLDisplay egl_display) { const char* ext_string = eglQueryString(egl_display, EGL_EXTENSIONS); if (ext_string == NULL) { printf("ERROR: eglQueryString(EGL_EXTENSIONS) failed\n"); return false; } printf("EGL_EXTENSIONS = %s\n", ext_string); return true; } bool GetXExtensions(Display* display) { int ext_num; char** ext_list = XListExtensions(display, &ext_num); printf("X_EXTENSIONS ="); for (int i = 0; i < ext_num; ++i) { printf(" %s", ext_list[i]); } printf("\n"); XFreeExtensionList(ext_list); return true; } int main(int argc, char* argv[]) { // Initialize graphics. Display* display; EGLDisplay egl_display = EGL_NO_DISPLAY; EGLContext egl_context = EGL_NO_CONTEXT; EGLSurface egl_surface = EGL_NO_SURFACE; bool rt_code = true; #ifdef OPENGL_ES_IMPORT_FUNCTIONS if (argc != 3) { printf("ERROR: Usage: gles_APICheck libGLESxx.so libEGLxx.so\n"); return 0; } void* handle_gles = NULL; void* handle_egl = NULL; rt_code = EntryImportGL(argv[1], argv[2], &handle_gles, &handle_egl); #endif // OPENGL_ES_IMPORT_FUNCTIONS // EGL version is printed out in InitGraphics if (rt_code) rt_code = InitGraphics(&display, &egl_display, &egl_context, &egl_surface); // Get GLES version. if (rt_code) rt_code = GetGLESVersion(); // Get GLES extentions. if (rt_code) rt_code = GetGLESExtensions(); // Get EGL extentions. if (rt_code) rt_code = GetEGLExtensions(egl_display); // Get X11 extensions. if (rt_code) rt_code = GetXExtensions(display); ExitGraphics(egl_display, egl_context, egl_surface); #ifdef OPENGL_ES_IMPORT_FUNCTIONS ExitImportGL(handle_gles, handle_egl); #endif // OPENGL_ES_IMPORT_FUNCTIONS printf("SUCCEED: run to the end\n"); return 0; }