// based on // https://www.khronos.org/registry/EGL/extensions/MESA/EGL_MESA_platform_gbm.txt #include #include #include #include #include #include #include #include #include #include #include struct my_display { struct gbm_device *gbm; EGLDisplay egl; }; struct my_config { struct my_display dpy; EGLConfig egl; }; struct my_window { struct my_config config; struct gbm_surface *gbm; EGLSurface egl; }; PFNEGLGETPLATFORMDISPLAYEXTPROC getPlatformDisplayEXT; PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC createPlatformWindowSurfaceEXT; static void check_extensions(void) { const char *client_extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); if (!client_extensions) { abort(); } if (!strstr(client_extensions, "EGL_MESA_platform_gbm")) { abort(); } if (!strstr(client_extensions, "EGL_EXT_platform_base")) { abort(); } getPlatformDisplayEXT = (void *) eglGetProcAddress("eglGetPlatformDisplayEXT"); createPlatformWindowSurfaceEXT = (void *) eglGetProcAddress("eglCreatePlatformWindowSurfaceEXT"); } static struct my_display get_display(void) { struct my_display dpy; EGLint major, minor; int fd = open("/dev/dri/card0", O_RDWR | FD_CLOEXEC); if (fd < 0) abort(); dpy.gbm = gbm_create_device(fd); if (!dpy.gbm) abort(); dpy.egl = getPlatformDisplayEXT(EGL_PLATFORM_GBM_MESA, dpy.gbm, NULL); if (dpy.egl == EGL_NO_DISPLAY) abort(); if (eglInitialize(dpy.egl, &major, &minor)) printf ("EGL %d.%d\n", major, minor); else abort(); return dpy; } static struct my_config get_config(struct my_display dpy) { struct my_config config = { .dpy = dpy, }; EGLint egl_config_attribs[] = { EGL_BUFFER_SIZE, 32, EGL_DEPTH_SIZE, EGL_DONT_CARE, EGL_STENCIL_SIZE, EGL_DONT_CARE, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_NONE, }; EGLint num_configs; if (!eglGetConfigs(dpy.egl, NULL, 0, &num_configs)) abort(); EGLConfig *configs = malloc(num_configs * sizeof(EGLConfig)); if (!eglChooseConfig(dpy.egl, egl_config_attribs, configs, num_configs, &num_configs)) { abort(); } if (num_configs == 0) abort(); for (int i = 0; i < num_configs; ++i) { EGLint gbm_format; struct gbm_format_name_desc desc; if (!eglGetConfigAttrib(dpy.egl, configs[i], EGL_NATIVE_VISUAL_ID, &gbm_format)) { abort(); } printf ("found gbm_format: %s\n", gbm_format_get_name (gbm_format, &desc)); if (gbm_format == GBM_FORMAT_ARGB8888) { config.egl = configs[i]; free(configs); return config; } } // no egl config matching gbm format abort(); } static struct my_window get_window(struct my_config config) { struct my_window window = { .config = config, }; window.gbm = gbm_surface_create(config.dpy.gbm, 256, 256, GBM_FORMAT_XRGB8888, GBM_BO_USE_RENDERING); if (!window.gbm) abort(); window.egl = createPlatformWindowSurfaceEXT(config.dpy.egl, config.egl, window.gbm, NULL); if (window.egl == EGL_NO_SURFACE) abort(); return window; } int main(void) { check_extensions(); struct my_display dpy = get_display(); struct my_config config = get_config(dpy); struct my_window window = get_window(config); EGLContext context; context = eglCreateContext(dpy.egl, config.egl, EGL_NO_CONTEXT, NULL); eglMakeCurrent(dpy.egl, window.egl, window.egl, context); /* just so we have some gles symbols too */ glClearColor(1.0, 1.0, 1.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); glFlush(); return EXIT_SUCCESS; }