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