void report_gles_attributes()

in tools/gpu-dump.c [285:445]


void report_gles_attributes(void) {
	void* libEGL = NULL;
	EGLConfig* configs = NULL;
	EGLDisplay display = EGL_NO_DISPLAY;
	EGLSurface surface = EGL_NO_SURFACE;
	EGLContext context = EGL_NO_CONTEXT;
	EGLBoolean egl_init_status = EGL_FALSE;
	EGLBoolean egl_make_current_status = EGL_FALSE;
	EGLBoolean egl_status;

	libEGL = dlopen("libEGL.so", RTLD_LAZY | RTLD_LOCAL);

	display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
	if (display == EGL_NO_DISPLAY) {
		fprintf(stderr, "failed to get default EGL display\n");
		goto cleanup;
	}

	EGLint egl_major = 0, egl_minor = 0;
	egl_init_status = eglInitialize(display, &egl_major, &egl_minor);
	if (egl_init_status != EGL_TRUE) {
		fprintf(stderr, "failed to initialize EGL display connection\n");
		goto cleanup;
	}
	printf("initialized display connection with EGL %d.%d\n", (int) egl_major, (int) egl_minor);

	EGLint configs_count = 0;
	egl_status = eglGetConfigs(display, NULL, 0, &configs_count);
	if (egl_status != EGL_TRUE) {
		fprintf(stderr, "failed to get the number of EGL frame buffer configurations\n");
		goto cleanup;
	}

	configs = (EGLConfig*) malloc(configs_count * sizeof(EGLConfig));
	if (configs == NULL) {
		fprintf(stderr, "failed to allocate %zu bytes for %d frame buffer configurations\n",
			configs_count * sizeof(EGLConfig), configs_count);
		goto cleanup;
	}

	egl_status = eglGetConfigs(display, configs, configs_count, &configs_count);
	if (egl_status != EGL_TRUE || configs_count == 0) {
		fprintf(stderr, "failed to get EGL frame buffer configurations\n");
		goto cleanup;
	}

	printf("EGL framebuffer configurations:\n");
	for (EGLint i = 0; i < configs_count; i++) {
		printf("\tConfiguration #%d:\n", (int) i);
		for (size_t n = 0; n < COUNT_OF(egl_config_attributes); n++) {
			EGLint value = 0;
			egl_status = eglGetConfigAttrib(display, configs[i], egl_config_attributes[n].id, &value);
			if (egl_config_attributes[n].cardinality == 0) {
				printf("\t\t%s: %d\n", egl_config_attributes[n].name, (int) value);
			} else if (egl_config_attributes[n].cardinality > 0) {
				/* Enumeration */
				bool known_value = false;
				for (size_t k = 0; k < (size_t) egl_config_attributes[n].cardinality; k++) {
					if (egl_config_attributes[n].values[k].id == value) {
						printf("\t\t%s: %s\n", egl_config_attributes[n].name, egl_config_attributes[n].values[k].name);
						known_value = true;
						break;
					}
				}
				if (!known_value) {
					printf("\t\t%s: unknown (%d)\n", egl_config_attributes[n].name, value);
				}
			} else {
				/* Bitfield */
				printf("\t\t%s: ", egl_config_attributes[n].name);
				if (value == 0) {
					printf("none\n");
				} else {
					for (size_t k = 0; k < (size_t) -egl_config_attributes[n].cardinality; k++) {
						if (egl_config_attributes[n].values[k].id & value) {
							value &= ~egl_config_attributes[n].values[k].id;
							if (value != 0) {
								printf("%s | ", egl_config_attributes[n].values[k].name);
							} else {
								printf("%s\n", egl_config_attributes[n].values[k].name);
							}
						}
					}
					if (value != 0) {
						printf("0x%08X\n", (int) value);
					}
				}
			}
		}
	}

	EGLint const config_attributes[] = {
		EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE,
		EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
		EGL_CONFORMANT, EGL_OPENGL_ES2_BIT,
		EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
		EGL_NONE,
	};
	EGLConfig config = NULL;
	EGLint config_count = 0;
	egl_status = eglChooseConfig(display, config_attributes, &config, 1, &config_count);
	if (egl_status != EGL_TRUE || config_count == 0 || config == NULL) {
		fprintf(stderr, "failed to find EGL frame buffer configuration that match required attributes\n");
		goto cleanup;
	}

	EGLint const surface_attributes[] = {
		EGL_HEIGHT, 1,
		EGL_WIDTH, 1,
		EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
		EGL_TEXTURE_TARGET, EGL_TEXTURE_2D,
		EGL_NONE,
	};
	surface = eglCreatePbufferSurface(display, config, surface_attributes);
	if (surface == EGL_NO_SURFACE) {
		fprintf(stderr, "failed to create PBuffer surface\n");
		goto cleanup;
	}

	EGLint const context_attributes[] = {
		EGL_CONTEXT_CLIENT_VERSION, 2,
		EGL_NONE,
	};
	context = eglCreateContext(display, config, EGL_NO_CONTEXT, context_attributes);
	if (context == EGL_NO_CONTEXT) {
		fprintf(stderr, "failed to create OpenGL ES context\n");
		goto cleanup;
	}

	egl_make_current_status = eglMakeCurrent(display, surface, surface, context);
	if (egl_make_current_status != EGL_TRUE) {
		fprintf(stderr, "failed to attach OpenGL ES rendering context\n");
		goto cleanup;
	}

	printf("OpenGL ES Attributes:\n");
	printf("\t%s: \"%s\"\n", "GL_VENDOR", glGetString(GL_VENDOR));
	printf("\t%s: \"%s\"\n", "GL_RENDERER", glGetString(GL_RENDERER));
	printf("\t%s: \"%s\"\n", "GL_VERSION", glGetString(GL_VERSION));
	printf("\t%s: \"%s\"\n", "GL_SHADING_LANGUAGE_VERSION", glGetString(GL_SHADING_LANGUAGE_VERSION));
	printf("\t%s: \"%s\"\n", "GL_EXTENSIONS", glGetString(GL_EXTENSIONS));

cleanup:
	if (egl_make_current_status == EGL_TRUE) {
		eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
	}
	if (context != EGL_NO_CONTEXT) {
		eglDestroyContext(display, context);
	}
	if (surface != EGL_NO_SURFACE) {
		eglDestroySurface(display, surface);
	}
	if (egl_init_status == EGL_TRUE) {
		eglTerminate(display);
	}
	free(configs);

	if (libEGL != NULL) {
		dlclose(libEGL);
	}
}