• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdbool.h>
4 #include <dlfcn.h>
5 
6 #include <EGL/egl.h>
7 #include <GLES2/gl2.h>
8 
9 
10 #define COUNT_OF(x) (sizeof(x) / sizeof(0[x]))
11 
12 
13 struct egl_enum_item {
14 	EGLint id;
15 	const char* name;
16 };
17 
18 struct egl_enum_item egl_enum_boolean[] = {
19 	{
20 		.id = EGL_TRUE,
21 		.name = "EGL_TRUE",
22 	},
23 	{
24 		.id = EGL_FALSE,
25 		.name = "EGL_FALSE",
26 	},
27 };
28 
29 struct egl_enum_item egl_enum_caveat[] = {
30 	{
31 		.id = EGL_NONE,
32 		.name = "EGL_NONE",
33 	},
34 	{
35 		.id = EGL_SLOW_CONFIG,
36 		.name = "EGL_SLOW_CONFIG",
37 	},
38 	{
39 		.id = EGL_NON_CONFORMANT_CONFIG,
40 		.name = "EGL_NON_CONFORMANT_CONFIG",
41 	},
42 };
43 
44 struct egl_enum_item egl_enum_transparency[] = {
45 	{
46 		.id = EGL_NONE,
47 		.name = "EGL_NONE",
48 	},
49 	{
50 		.id = EGL_TRANSPARENT_RGB,
51 		.name = "EGL_TRANSPARENT_RGB",
52 	},
53 };
54 
55 struct egl_enum_item egl_enum_color_buffer[] = {
56 	{
57 		.id = EGL_RGB_BUFFER,
58 		.name = "EGL_RGB_BUFFER",
59 	},
60 	{
61 		.id = EGL_LUMINANCE_BUFFER,
62 		.name = "EGL_LUMINANCE_BUFFER",
63 	},
64 };
65 
66 #ifndef EGL_OPENGL_ES3_BIT
67 	#define EGL_OPENGL_ES3_BIT 0x40
68 #endif
69 
70 struct egl_enum_item egl_enum_conformant[] = {
71 	{
72 		.id = EGL_OPENGL_BIT,
73 		.name = "EGL_OPENGL_BIT",
74 	},
75 	{
76 		.id = EGL_OPENGL_ES_BIT,
77 		.name = "EGL_OPENGL_ES_BIT",
78 	},
79 	{
80 		.id = EGL_OPENGL_ES2_BIT,
81 		.name = "EGL_OPENGL_ES2_BIT",
82 	},
83 	{
84 		.id = EGL_OPENGL_ES3_BIT,
85 		.name = "EGL_OPENGL_ES3_BIT",
86 	},
87 	{
88 		.id = EGL_OPENVG_BIT,
89 		.name = "EGL_OPENVG_BIT",
90 	},
91 };
92 
93 struct egl_enum_item egl_enum_surface_type[] = {
94 	{
95 		.id = EGL_PBUFFER_BIT,
96 		.name = "EGL_PBUFFER_BIT",
97 	},
98 	{
99 		.id = EGL_PIXMAP_BIT,
100 		.name = "EGL_PIXMAP_BIT",
101 	},
102 	{
103 		.id = EGL_WINDOW_BIT,
104 		.name = "EGL_WINDOW_BIT",
105 	},
106 	{
107 		.id = EGL_VG_COLORSPACE_LINEAR_BIT,
108 		.name = "EGL_VG_COLORSPACE_LINEAR_BIT",
109 	},
110 	{
111 		.id = EGL_VG_ALPHA_FORMAT_PRE_BIT,
112 		.name = "EGL_VG_ALPHA_FORMAT_PRE_BIT",
113 	},
114 	{
115 		.id = EGL_MULTISAMPLE_RESOLVE_BOX_BIT,
116 		.name = "EGL_MULTISAMPLE_RESOLVE_BOX_BIT",
117 	},
118 	{
119 		.id = EGL_SWAP_BEHAVIOR_PRESERVED_BIT,
120 		.name = "EGL_SWAP_BEHAVIOR_PRESERVED_BIT",
121 	},
122 };
123 
124 struct egl_enum_item egl_enum_renderable_type[] = {
125 	{
126 		.id = EGL_OPENGL_ES_BIT,
127 		.name = "EGL_OPENGL_ES_BIT",
128 	},
129 	{
130 		.id = EGL_OPENVG_BIT,
131 		.name = "EGL_OPENVG_BIT",
132 	},
133 	{
134 		.id = EGL_OPENGL_ES2_BIT,
135 		.name = "EGL_OPENGL_ES2_BIT",
136 	},
137 	{
138 		.id = EGL_OPENGL_BIT,
139 		.name = "EGL_OPENGL_BIT",
140 	},
141 	{
142 		.id = EGL_OPENGL_ES3_BIT,
143 		.name = "EGL_OPENGL_ES3_BIT",
144 	},
145 };
146 
147 struct egl_config_attribute {
148 	EGLint id;
149 	const char* name;
150 	int32_t cardinality;
151 	const struct egl_enum_item* values;
152 };
153 
154 struct egl_config_attribute egl_config_attributes[] = {
155 	{
156 		.id = EGL_CONFIG_ID,
157 		.name = "EGL_CONFIG_ID",
158 	},
159 	{
160 		.id = EGL_CONFIG_CAVEAT,
161 		.name = "EGL_CONFIG_CAVEAT",
162 		.cardinality = COUNT_OF(egl_enum_caveat),
163 		.values = egl_enum_caveat,
164 	},
165 	{
166 		.id = EGL_LUMINANCE_SIZE,
167 		.name = "EGL_LUMINANCE_SIZE",
168 	},
169 	{
170 		.id = EGL_RED_SIZE,
171 		.name = "EGL_RED_SIZE",
172 	},
173 	{
174 		.id = EGL_GREEN_SIZE,
175 		.name = "EGL_GREEN_SIZE",
176 	},
177 	{
178 		.id = EGL_BLUE_SIZE,
179 		.name = "EGL_BLUE_SIZE",
180 	},
181 	{
182 		.id = EGL_ALPHA_SIZE,
183 		.name = "EGL_ALPHA_SIZE",
184 	},
185 	{
186 		.id = EGL_DEPTH_SIZE,
187 		.name = "EGL_DEPTH_SIZE",
188 	},
189 	{
190 		.id = EGL_STENCIL_SIZE,
191 		.name = "EGL_STENCIL_SIZE",
192 	},
193 	{
194 		.id = EGL_ALPHA_MASK_SIZE,
195 		.name = "EGL_ALPHA_MASK_SIZE",
196 	},
197 	{
198 		.id = EGL_BIND_TO_TEXTURE_RGB,
199 		.name = "EGL_BIND_TO_TEXTURE_RGB",
200 		.cardinality = COUNT_OF(egl_enum_boolean),
201 		.values = egl_enum_boolean,
202 	},
203 	{
204 		.id = EGL_BIND_TO_TEXTURE_RGBA,
205 		.name = "EGL_BIND_TO_TEXTURE_RGBA",
206 		.cardinality = COUNT_OF(egl_enum_boolean),
207 		.values = egl_enum_boolean,
208 	},
209 	{
210 		.id = EGL_MAX_PBUFFER_WIDTH,
211 		.name = "EGL_MAX_PBUFFER_WIDTH",
212 	},
213 	{
214 		.id = EGL_MAX_PBUFFER_HEIGHT,
215 		.name = "EGL_MAX_PBUFFER_HEIGHT",
216 	},
217 	{
218 		.id = EGL_MAX_PBUFFER_PIXELS,
219 		.name = "EGL_MAX_PBUFFER_PIXELS",
220 	},
221 	{
222 		.id = EGL_TRANSPARENT_RED_VALUE,
223 		.name = "EGL_TRANSPARENT_RED_VALUE",
224 	},
225 	{
226 		.id = EGL_TRANSPARENT_GREEN_VALUE,
227 		.name = "EGL_TRANSPARENT_GREEN_VALUE",
228 	},
229 	{
230 		.id = EGL_TRANSPARENT_BLUE_VALUE,
231 		.name = "EGL_TRANSPARENT_BLUE_VALUE",
232 	},
233 	{
234 		.id = EGL_SAMPLE_BUFFERS,
235 		.name = "EGL_SAMPLE_BUFFERS",
236 	},
237 	{
238 		.id = EGL_SAMPLES,
239 		.name = "EGL_SAMPLES",
240 	},
241 	{
242 		.id = EGL_LEVEL,
243 		.name = "EGL_LEVEL",
244 	},
245 	{
246 		.id = EGL_MAX_SWAP_INTERVAL,
247 		.name = "EGL_MAX_SWAP_INTERVAL",
248 	},
249 	{
250 		.id = EGL_MIN_SWAP_INTERVAL,
251 		.name = "EGL_MIN_SWAP_INTERVAL",
252 	},
253 	{
254 		.id = EGL_SURFACE_TYPE,
255 		.name = "EGL_SURFACE_TYPE",
256 		.cardinality = -(int32_t) COUNT_OF(egl_enum_surface_type),
257 		.values = egl_enum_surface_type,
258 	},
259 	{
260 		.id = EGL_RENDERABLE_TYPE,
261 		.name = "EGL_RENDERABLE_TYPE",
262 		.cardinality = -(int32_t) COUNT_OF(egl_enum_renderable_type),
263 		.values = egl_enum_renderable_type,
264 	},
265 	{
266 		.id = EGL_CONFORMANT,
267 		.name = "EGL_CONFORMANT",
268 		.cardinality = -(int32_t) COUNT_OF(egl_enum_conformant),
269 		.values = egl_enum_conformant,
270 	},
271 	{
272 		.id = EGL_TRANSPARENT_TYPE,
273 		.name = "EGL_TRANSPARENT_TYPE",
274 		.cardinality = COUNT_OF(egl_enum_transparency),
275 		.values = egl_enum_transparency,
276 	},
277 	{
278 		.id = EGL_COLOR_BUFFER_TYPE,
279 		.name = "EGL_COLOR_BUFFER_TYPE",
280 		.cardinality = COUNT_OF(egl_enum_color_buffer),
281 		.values = egl_enum_color_buffer,
282 	},
283 };
284 
report_gles_attributes(void)285 void report_gles_attributes(void) {
286 	void* libEGL = NULL;
287 	EGLConfig* configs = NULL;
288 	EGLDisplay display = EGL_NO_DISPLAY;
289 	EGLSurface surface = EGL_NO_SURFACE;
290 	EGLContext context = EGL_NO_CONTEXT;
291 	EGLBoolean egl_init_status = EGL_FALSE;
292 	EGLBoolean egl_make_current_status = EGL_FALSE;
293 	EGLBoolean egl_status;
294 
295 	libEGL = dlopen("libEGL.so", RTLD_LAZY | RTLD_LOCAL);
296 
297 	display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
298 	if (display == EGL_NO_DISPLAY) {
299 		fprintf(stderr, "failed to get default EGL display\n");
300 		goto cleanup;
301 	}
302 
303 	EGLint egl_major = 0, egl_minor = 0;
304 	egl_init_status = eglInitialize(display, &egl_major, &egl_minor);
305 	if (egl_init_status != EGL_TRUE) {
306 		fprintf(stderr, "failed to initialize EGL display connection\n");
307 		goto cleanup;
308 	}
309 	printf("initialized display connection with EGL %d.%d\n", (int) egl_major, (int) egl_minor);
310 
311 	EGLint configs_count = 0;
312 	egl_status = eglGetConfigs(display, NULL, 0, &configs_count);
313 	if (egl_status != EGL_TRUE) {
314 		fprintf(stderr, "failed to get the number of EGL frame buffer configurations\n");
315 		goto cleanup;
316 	}
317 
318 	configs = (EGLConfig*) malloc(configs_count * sizeof(EGLConfig));
319 	if (configs == NULL) {
320 		fprintf(stderr, "failed to allocate %zu bytes for %d frame buffer configurations\n",
321 			configs_count * sizeof(EGLConfig), configs_count);
322 		goto cleanup;
323 	}
324 
325 	egl_status = eglGetConfigs(display, configs, configs_count, &configs_count);
326 	if (egl_status != EGL_TRUE || configs_count == 0) {
327 		fprintf(stderr, "failed to get EGL frame buffer configurations\n");
328 		goto cleanup;
329 	}
330 
331 	printf("EGL framebuffer configurations:\n");
332 	for (EGLint i = 0; i < configs_count; i++) {
333 		printf("\tConfiguration #%d:\n", (int) i);
334 		for (size_t n = 0; n < COUNT_OF(egl_config_attributes); n++) {
335 			EGLint value = 0;
336 			egl_status = eglGetConfigAttrib(display, configs[i], egl_config_attributes[n].id, &value);
337 			if (egl_config_attributes[n].cardinality == 0) {
338 				printf("\t\t%s: %d\n", egl_config_attributes[n].name, (int) value);
339 			} else if (egl_config_attributes[n].cardinality > 0) {
340 				/* Enumeration */
341 				bool known_value = false;
342 				for (size_t k = 0; k < (size_t) egl_config_attributes[n].cardinality; k++) {
343 					if (egl_config_attributes[n].values[k].id == value) {
344 						printf("\t\t%s: %s\n", egl_config_attributes[n].name, egl_config_attributes[n].values[k].name);
345 						known_value = true;
346 						break;
347 					}
348 				}
349 				if (!known_value) {
350 					printf("\t\t%s: unknown (%d)\n", egl_config_attributes[n].name, value);
351 				}
352 			} else {
353 				/* Bitfield */
354 				printf("\t\t%s: ", egl_config_attributes[n].name);
355 				if (value == 0) {
356 					printf("none\n");
357 				} else {
358 					for (size_t k = 0; k < (size_t) -egl_config_attributes[n].cardinality; k++) {
359 						if (egl_config_attributes[n].values[k].id & value) {
360 							value &= ~egl_config_attributes[n].values[k].id;
361 							if (value != 0) {
362 								printf("%s | ", egl_config_attributes[n].values[k].name);
363 							} else {
364 								printf("%s\n", egl_config_attributes[n].values[k].name);
365 							}
366 						}
367 					}
368 					if (value != 0) {
369 						printf("0x%08X\n", (int) value);
370 					}
371 				}
372 			}
373 		}
374 	}
375 
376 	EGLint const config_attributes[] = {
377 		EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE,
378 		EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
379 		EGL_CONFORMANT, EGL_OPENGL_ES2_BIT,
380 		EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
381 		EGL_NONE,
382 	};
383 	EGLConfig config = NULL;
384 	EGLint config_count = 0;
385 	egl_status = eglChooseConfig(display, config_attributes, &config, 1, &config_count);
386 	if (egl_status != EGL_TRUE || config_count == 0 || config == NULL) {
387 		fprintf(stderr, "failed to find EGL frame buffer configuration that match required attributes\n");
388 		goto cleanup;
389 	}
390 
391 	EGLint const surface_attributes[] = {
392 		EGL_HEIGHT, 1,
393 		EGL_WIDTH, 1,
394 		EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
395 		EGL_TEXTURE_TARGET, EGL_TEXTURE_2D,
396 		EGL_NONE,
397 	};
398 	surface = eglCreatePbufferSurface(display, config, surface_attributes);
399 	if (surface == EGL_NO_SURFACE) {
400 		fprintf(stderr, "failed to create PBuffer surface\n");
401 		goto cleanup;
402 	}
403 
404 	EGLint const context_attributes[] = {
405 		EGL_CONTEXT_CLIENT_VERSION, 2,
406 		EGL_NONE,
407 	};
408 	context = eglCreateContext(display, config, EGL_NO_CONTEXT, context_attributes);
409 	if (context == EGL_NO_CONTEXT) {
410 		fprintf(stderr, "failed to create OpenGL ES context\n");
411 		goto cleanup;
412 	}
413 
414 	egl_make_current_status = eglMakeCurrent(display, surface, surface, context);
415 	if (egl_make_current_status != EGL_TRUE) {
416 		fprintf(stderr, "failed to attach OpenGL ES rendering context\n");
417 		goto cleanup;
418 	}
419 
420 	printf("OpenGL ES Attributes:\n");
421 	printf("\t%s: \"%s\"\n", "GL_VENDOR", glGetString(GL_VENDOR));
422 	printf("\t%s: \"%s\"\n", "GL_RENDERER", glGetString(GL_RENDERER));
423 	printf("\t%s: \"%s\"\n", "GL_VERSION", glGetString(GL_VERSION));
424 	printf("\t%s: \"%s\"\n", "GL_SHADING_LANGUAGE_VERSION", glGetString(GL_SHADING_LANGUAGE_VERSION));
425 	printf("\t%s: \"%s\"\n", "GL_EXTENSIONS", glGetString(GL_EXTENSIONS));
426 
427 cleanup:
428 	if (egl_make_current_status == EGL_TRUE) {
429 		eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
430 	}
431 	if (context != EGL_NO_CONTEXT) {
432 		eglDestroyContext(display, context);
433 	}
434 	if (surface != EGL_NO_SURFACE) {
435 		eglDestroySurface(display, surface);
436 	}
437 	if (egl_init_status == EGL_TRUE) {
438 		eglTerminate(display);
439 	}
440 	free(configs);
441 
442 	if (libEGL != NULL) {
443 		dlclose(libEGL);
444 	}
445 }
446 
main(int argc,char ** argv)447 int main(int argc, char** argv) {
448 	report_gles_attributes();
449 	return 0;
450 }
451