blob: 5422ceafdcbae267ddd461c0dddb632071115659 [file] [log] [blame]
// 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;
}