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