1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // To use runtime linking, uncomment the #define OPENGL_ES_IMPORT_FUNCTIONS,
6 // and pass libGLESxx.so libEGLxx.so in the command line as input
7 // parameters.
8 // Otherwise, comment out #define OPENGL_ES_IMPORT_FUNCTIONS and pass no
9 // parameters in the command line.
10
11 #include <stdio.h>
12
13 #include <EGL/egl.h>
14 #include <GLES2/gl2.h>
15
16 #include <X11/Xlib.h>
17 #include <X11/Xutil.h>
18
19 #define OPENGL_ES_IMPORT_FUNCTIONS
20
21 #ifdef OPENGL_ES_IMPORT_FUNCTIONS
22
23 #include <dlfcn.h>
24
25 EGLDisplay (*FP_eglGetDisplay)(NativeDisplayType display) = NULL;
26 EGLBoolean (*FP_eglInitialize)(EGLDisplay dpy,
27 EGLint* major,
28 EGLint* minor) = NULL;
29 EGLBoolean (*FP_eglGetConfigs)(EGLDisplay dpy,
30 EGLConfig* configs,
31 EGLint config_size,
32 EGLint* num_config) = NULL;
33 EGLBoolean (*FP_eglChooseConfig)(EGLDisplay dpy,
34 const EGLint* attrib_list,
35 EGLConfig* configs,
36 EGLint config_size,
37 EGLint* num_config) = NULL;
38 EGLContext (*FP_eglCreateContext)(EGLDisplay dpy,
39 EGLConfig config,
40 EGLContext share_list,
41 const EGLint* attrib_list) = NULL;
42 EGLBoolean (*FP_eglGetConfigAttrib)(EGLDisplay dpy,
43 EGLConfig config,
44 EGLint attribute,
45 EGLint* value) = NULL;
46 EGLSurface (*FP_eglCreateWindowSurface)(EGLDisplay dpy,
47 EGLConfig config,
48 NativeWindowType window,
49 const EGLint* attrib_list) = NULL;
50 EGLBoolean (*FP_eglMakeCurrent)(EGLDisplay dpy,
51 EGLSurface draw,
52 EGLSurface read,
53 EGLContext ctx) = NULL;
54 EGLBoolean (*FP_eglDestroyContext)(EGLDisplay dpy, EGLContext ctx) = NULL;
55 EGLBoolean (*FP_eglDestroySurface)(EGLDisplay dpy, EGLSurface surface) = NULL;
56 EGLBoolean (*FP_eglTerminate)(EGLDisplay dpy) = NULL;
57 const char* (*FP_eglQueryString)(EGLDisplay dpy, EGLint name) = NULL;
58 const GLubyte* (*FP_glGetString)(GLenum name) = NULL;
59
60 #define eglGetDisplay FP_eglGetDisplay
61 #define eglInitialize FP_eglInitialize
62 #define eglGetConfigs FP_eglGetConfigs
63 #define eglChooseConfig FP_eglChooseConfig
64 #define eglCreateContext FP_eglCreateContext
65 #define eglGetConfigAttrib FP_eglGetConfigAttrib
66 #define eglCreateWindowSurface FP_eglCreateWindowSurface
67 #define eglMakeCurrent FP_eglMakeCurrent
68 #define eglDestroyContext FP_eglDestroyContext
69 #define eglDestroySurface FP_eglDestroySurface
70 #define eglTerminate FP_eglTerminate
71 #define eglQueryString FP_eglQueryString
72 #define glGetString FP_glGetString
73
74 typedef EGLDisplay (*FT_eglGetDisplay)(NativeDisplayType);
75 typedef EGLBoolean (*FT_eglInitialize)(EGLDisplay, EGLint*, EGLint*);
76 typedef EGLBoolean (*FT_eglGetConfigs)(EGLDisplay, EGLConfig*,
77 EGLint, EGLint*);
78 typedef EGLBoolean (*FT_eglChooseConfig)(EGLDisplay, const EGLint*,
79 EGLConfig*, EGLint, EGLint*);
80 typedef EGLContext (*FT_eglCreateContext)(EGLDisplay, EGLConfig,
81 EGLContext, const EGLint*);
82 typedef EGLBoolean (*FT_eglGetConfigAttrib)(EGLDisplay, EGLConfig,
83 EGLint, EGLint*);
84 typedef EGLSurface (*FT_eglCreateWindowSurface)(EGLDisplay, EGLConfig,
85 NativeWindowType,
86 const EGLint*);
87 typedef EGLBoolean (*FT_eglMakeCurrent)(EGLDisplay, EGLSurface,
88 EGLSurface, EGLContext);
89 typedef EGLBoolean (*FT_eglDestroyContext)(EGLDisplay, EGLContext);
90 typedef EGLBoolean (*FT_eglDestroySurface)(EGLDisplay, EGLSurface);
91 typedef EGLBoolean (*FT_eglTerminate)(EGLDisplay);
92 typedef const char* (*FT_eglQueryString)(EGLDisplay, EGLint);
93 typedef const GLubyte* (*FT_glGetString)(GLenum);
94
LoadDLFunction(void ** func_handle,const char * func_name,void * dl_handle)95 bool LoadDLFunction(void** func_handle,
96 const char* func_name,
97 void* dl_handle) {
98 *func_handle = dlsym(dl_handle, func_name);
99 if (*func_handle == NULL) {
100 printf("ERROR: fail to load %s\n", func_name);
101 return false;
102 }
103 return true;
104 }
105
EntryImportGL(char * lib_gles,char * lib_egl,void ** handle_gles,void ** handle_egl)106 bool EntryImportGL(char* lib_gles, char* lib_egl,
107 void** handle_gles, void** handle_egl) {
108 *handle_gles = dlopen(lib_gles, RTLD_LAZY);
109 if (*handle_gles == NULL) {
110 printf("ERROR: %s\n", dlerror());
111 return false;
112 }
113 *handle_egl = dlopen(lib_egl, RTLD_LAZY);
114 if (*handle_egl == NULL) {
115 printf("ERROR: %s\n", dlerror());
116 return false;
117 }
118
119 bool rt = true;
120 void* tmp;
121 rt &= LoadDLFunction(&tmp, "eglGetDisplay", *handle_egl);
122 FP_eglGetDisplay = reinterpret_cast<FT_eglGetDisplay>(tmp);
123 rt &= LoadDLFunction(&tmp, "eglInitialize", *handle_egl);
124 FP_eglInitialize = reinterpret_cast<FT_eglInitialize>(tmp);
125 rt &= LoadDLFunction(&tmp, "eglGetConfigs", *handle_egl);
126 FP_eglGetConfigs = reinterpret_cast<FT_eglGetConfigs>(tmp);
127 rt &= LoadDLFunction(&tmp, "eglChooseConfig", *handle_egl);
128 FP_eglChooseConfig = reinterpret_cast<FT_eglChooseConfig>(tmp);
129 rt &= LoadDLFunction(&tmp, "eglCreateContext", *handle_egl);
130 FP_eglCreateContext = reinterpret_cast<FT_eglCreateContext>(tmp);
131 rt &= LoadDLFunction(&tmp, "eglGetConfigAttrib", *handle_egl);
132 FP_eglGetConfigAttrib = reinterpret_cast<FT_eglGetConfigAttrib>(tmp);
133 rt &= LoadDLFunction(&tmp, "eglCreateWindowSurface", *handle_egl);
134 FP_eglCreateWindowSurface = reinterpret_cast<FT_eglCreateWindowSurface>(tmp);
135 rt &= LoadDLFunction(&tmp, "eglMakeCurrent", *handle_egl);
136 FP_eglMakeCurrent = reinterpret_cast<FT_eglMakeCurrent>(tmp);
137 rt &= LoadDLFunction(&tmp, "eglDestroyContext", *handle_egl);
138 FP_eglDestroyContext = reinterpret_cast<FT_eglDestroyContext>(tmp);
139 rt &= LoadDLFunction(&tmp, "eglDestroySurface", *handle_egl);
140 FP_eglDestroySurface = reinterpret_cast<FT_eglDestroySurface>(tmp);
141 rt &= LoadDLFunction(&tmp, "eglTerminate", *handle_egl);
142 FP_eglTerminate = reinterpret_cast<FT_eglTerminate>(tmp);
143 rt &= LoadDLFunction(&tmp, "eglQueryString", *handle_egl);
144 FP_eglQueryString = reinterpret_cast<FT_eglQueryString>(tmp);
145 rt &= LoadDLFunction(&tmp, "glGetString", *handle_gles);
146 FP_glGetString = reinterpret_cast<FT_glGetString>(tmp);
147 return rt;
148 }
149
ExitImportGL(void * handle_gles,void * handle_egl)150 void ExitImportGL(void* handle_gles, void* handle_egl) {
151 if (handle_gles != NULL)
152 dlclose(handle_gles);
153 if (handle_egl != NULL)
154 dlclose(handle_egl);
155 }
156
157 #endif // OPENGL_ES_IMPORT_FUNCTIONS
158
InitGraphics(Display ** display,EGLDisplay * egl_display,EGLContext * egl_context,EGLSurface * egl_surface)159 bool InitGraphics(Display** display,
160 EGLDisplay* egl_display,
161 EGLContext* egl_context,
162 EGLSurface* egl_surface) {
163 const int kWindowWidth = 100;
164 const int kWindowHeight = 100;
165 const EGLint config_attribs[] = {
166 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
167 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
168 EGL_NONE
169 };
170 const EGLint context_attribs[] = {
171 EGL_CONTEXT_CLIENT_VERSION, 2,
172 EGL_NONE
173 };
174
175 // XWindow init.
176 *display = XOpenDisplay(NULL);
177 if (*display == NULL) {
178 printf("ERROR: XOpenDisplay failed\n");
179 return false;
180 }
181
182 int screen = XDefaultScreen(*display);
183 Window window = XCreateSimpleWindow(*display, RootWindow(*display, screen),
184 0, 0, kWindowWidth, kWindowHeight,
185 0, 0, WhitePixel(*display, screen));
186 XMapWindow(*display, window);
187 XSync(*display, True);
188
189 // EGL init.
190 *egl_display = eglGetDisplay((EGLNativeDisplayType)*display);
191 EGLint no_major, no_minor;
192 EGLBoolean rt_code = eglInitialize(*egl_display, &no_major, &no_minor);
193 if (rt_code == EGL_FALSE) {
194 printf("ERROR: eglInitialize failed\n");
195 return false;
196 }
197 // Print out version info.
198 printf("EGL_VERSION = %d.%d\n",
199 static_cast<int>(no_major),
200 static_cast<int>(no_minor));
201 // Config.
202 EGLint num_configs;
203 EGLConfig egl_config;
204 rt_code = eglChooseConfig(*egl_display, config_attribs,
205 &egl_config, 1, &num_configs);
206 if (rt_code == EGL_FALSE || num_configs != 1) {
207 printf("ERROR: eglChooseConfig failed\n");
208 return false;
209 }
210 // Surface.
211 *egl_surface = eglCreateWindowSurface(*egl_display, egl_config,
212 (NativeWindowType)window, NULL);
213 if (*egl_surface == EGL_NO_SURFACE) {
214 printf("ERROR: eglCreateWindowSurface failed\n");
215 return false;
216 }
217 // Context.
218 *egl_context = eglCreateContext(*egl_display, egl_config, EGL_NO_CONTEXT,
219 context_attribs);
220 if (*egl_context == EGL_NO_CONTEXT) {
221 printf("ERROR: eglCreateContext failed\n");
222 return false;
223 }
224 // Make current.
225 rt_code = eglMakeCurrent(*egl_display, *egl_surface,
226 *egl_surface, *egl_context);
227 if (rt_code == EGL_FALSE) {
228 printf("ERROR: eglMakeCurrent failed\n");
229 return false;
230 }
231 return true;
232 }
233
ExitGraphics(EGLDisplay egl_display,EGLContext egl_context,EGLSurface egl_surface)234 void ExitGraphics(EGLDisplay egl_display,
235 EGLContext egl_context,
236 EGLSurface egl_surface) {
237 if (egl_display != EGL_NO_DISPLAY) {
238 eglMakeCurrent(egl_display, NULL, NULL, NULL);
239 if (egl_context != EGL_NO_CONTEXT)
240 eglDestroyContext(egl_display, egl_context);
241 if (egl_surface != EGL_NO_SURFACE)
242 eglDestroySurface(egl_display, egl_surface);
243 eglTerminate(egl_display);
244 }
245 }
246
GetGLESVersion()247 bool GetGLESVersion() {
248 const GLubyte* version_string = glGetString(GL_VERSION);
249 if (version_string == NULL) {
250 printf("ERROR: glGetString(GL_VERSION) failed\n");
251 return false;
252 }
253 printf("GLES_VERSION = %s\n", version_string);
254 return true;
255 }
256
GetGLESExtensions()257 bool GetGLESExtensions() {
258 const GLubyte* ext_string = glGetString(GL_EXTENSIONS);
259 if (ext_string == NULL) {
260 printf("ERROR: glGetString(GL_EXTENSIONS) failed\n");
261 return false;
262 }
263 printf("GLES_EXTENSIONS = %s\n", ext_string);
264 return true;
265 }
266
GetEGLExtensions(EGLDisplay egl_display)267 bool GetEGLExtensions(EGLDisplay egl_display) {
268 const char* ext_string = eglQueryString(egl_display, EGL_EXTENSIONS);
269 if (ext_string == NULL) {
270 printf("ERROR: eglQueryString(EGL_EXTENSIONS) failed\n");
271 return false;
272 }
273 printf("EGL_EXTENSIONS = %s\n", ext_string);
274 return true;
275 }
276
GetXExtensions(Display * display)277 bool GetXExtensions(Display* display) {
278 int ext_num;
279 char** ext_list = XListExtensions(display, &ext_num);
280 printf("X_EXTENSIONS =");
281 for (int i = 0; i < ext_num; ++i) {
282 printf(" %s", ext_list[i]);
283 }
284 printf("\n");
285 XFreeExtensionList(ext_list);
286 return true;
287 }
288
main(int argc,char * argv[])289 int main(int argc, char* argv[]) {
290 // Initialize graphics.
291 Display* display;
292 EGLDisplay egl_display = EGL_NO_DISPLAY;
293 EGLContext egl_context = EGL_NO_CONTEXT;
294 EGLSurface egl_surface = EGL_NO_SURFACE;
295
296 bool rt_code = true;
297
298 #ifdef OPENGL_ES_IMPORT_FUNCTIONS
299 if (argc != 3) {
300 printf("ERROR: Usage: gles_APICheck libGLESxx.so libEGLxx.so\n");
301 return 0;
302 }
303 void* handle_gles = NULL;
304 void* handle_egl = NULL;
305 rt_code = EntryImportGL(argv[1], argv[2], &handle_gles, &handle_egl);
306 #endif // OPENGL_ES_IMPORT_FUNCTIONS
307
308 // EGL version is printed out in InitGraphics
309 if (rt_code)
310 rt_code = InitGraphics(&display, &egl_display,
311 &egl_context, &egl_surface);
312
313 // Get GLES version.
314 if (rt_code)
315 rt_code = GetGLESVersion();
316
317 // Get GLES extentions.
318 if (rt_code)
319 rt_code = GetGLESExtensions();
320
321 // Get EGL extentions.
322 if (rt_code)
323 rt_code = GetEGLExtensions(egl_display);
324
325 // Get X11 extensions.
326 if (rt_code)
327 rt_code = GetXExtensions(display);
328
329 ExitGraphics(egl_display, egl_context, egl_surface);
330 #ifdef OPENGL_ES_IMPORT_FUNCTIONS
331 ExitImportGL(handle_gles, handle_egl);
332 #endif // OPENGL_ES_IMPORT_FUNCTIONS
333 printf("SUCCEED: run to the end\n");
334 return 0;
335 }
336
337