| Name |
| |
| KHR_platform_gbm |
| |
| Name Strings |
| |
| EGL_KHR_platform_gbm |
| |
| Contributors |
| |
| Chad Versace <chad.versace@intel.com> |
| Jon Leech (oddhack 'at' sonic.net) |
| Kristian Høgsberg <krh@bitplanet.org> |
| |
| Contacts |
| |
| Chad Versace <chad.versace@intel.com> |
| |
| Status |
| |
| Complete. |
| Approved by the EGL Working Group on January 31, 2014. |
| Ratified by the Khronos Board of Promoters on March 14, 2014. |
| |
| Version |
| |
| Version 3, 2016/01/04 |
| |
| Number |
| |
| EGL Extension #69 |
| |
| Extension Type |
| |
| EGL client extension |
| |
| Dependencies |
| |
| EGL 1.5 is required. |
| |
| This extension is written against the EGL 1.5 Specification (draft |
| 20140122). |
| |
| Overview |
| |
| This extension defines how to create EGL resources from native GBM |
| resources using the EGL 1.5 platform functionality (GBM is a Generic |
| Buffer Manager for Linux). |
| |
| New Types |
| |
| None |
| |
| New Procedures and Functions |
| |
| None |
| |
| New Tokens |
| |
| Accepted as the <platform> argument of eglGetPlatformDisplay: |
| |
| EGL_PLATFORM_GBM_KHR 0x31D7 |
| |
| Additions to the EGL Specification |
| |
| None. |
| |
| New Behavior |
| |
| To determine if the EGL implementation supports this extension, clients |
| should query the EGL_EXTENSIONS string of EGL_NO_DISPLAY. |
| |
| To obtain an EGLDisplay from an GBM device, call eglGetPlatformDisplay with |
| <platform> set to EGL_PLATFORM_GBM_KHR. The <native_display> parameter |
| specifies the GBM device to use and must either point to a `struct |
| gbm_device` or be EGL_DEFAULT_DISPLAY. If <native_display> is |
| EGL_DEFAULT_DISPLAY, then the resultant EGLDisplay will be backed by some |
| implementation-chosen GBM device. |
| |
| For each EGLConfig that belongs to the GBM platform, the |
| EGL_NATIVE_VISUAL_ID attribute is a GBM color format, such as |
| GBM_FORMAT_XRGB8888. |
| |
| To obtain a rendering surface from a GBM surface, call |
| eglCreatePlatformWindowSurface with a <dpy> that belongs to the GBM |
| platform and a <native_window> that points to a `struct gbm_surface`. If |
| <native_window> was created without the GBM_BO_USE_RENDERING flag, or if |
| the color format of <native_window> differs from the EGL_NATIVE_VISUAL_ID |
| of <config>, then the function fails and generates EGL_BAD_MATCH. |
| |
| It is not valid to call eglCreatePlatformPixmapSurface with a <dpy> that |
| belongs to the GBM platform. Any such call fails and generates |
| an EGL_BAD_PARAMETER error. |
| |
| Issues |
| |
| 1. Should this extension permit EGL_DEFAULT_DISPLAY as input to |
| eglGetPlatformDisplay? |
| |
| RESOLUTION: Yes. When given EGL_DEFAULT_DISPLAY, eglGetPlatformDisplay |
| returns an EGLDisplay backed by an implementation-chosen GBM device. |
| |
| Example Code |
| |
| // This example program creates an EGL surface from a GBM surface. |
| // |
| // If the macro EGL_KHR_platform_gbm is defined, then the program |
| // creates the surfaces using the methods defined in this specification. |
| // Otherwise, it uses the methods defined by the EGL 1.4 specification. |
| // |
| // Compile with `cc -std=c99 example.c -lgbm -lEGL`. |
| |
| #include <stdlib.h> |
| #include <string.h> |
| |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include <fcntl.h> |
| |
| #include <EGL/egl.h> |
| #include <gbm.h> |
| |
| 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; |
| }; |
| |
| static void |
| check_extensions(void) |
| { |
| #ifdef EGL_KHR_platform_gbm |
| const char *client_extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); |
| |
| if (!client_extensions) { |
| // No client extensions string available |
| abort(); |
| } |
| if (!strstr(client_extensions, "EGL_KHR_platform_gbm")) { |
| abort(); |
| } |
| #endif |
| } |
| |
| static struct my_display |
| get_display(void) |
| { |
| struct my_display dpy; |
| |
| int fd = open("/dev/dri/card0", O_RDWR | FD_CLOEXEC); |
| if (fd < 0) { |
| abort(); |
| } |
| |
| dpy.gbm = gbm_create_device(fd); |
| if (!dpy.gbm) { |
| abort(); |
| } |
| |
| |
| #ifdef EGL_KHR_platform_gbm |
| dpy.egl = eglGetPlatformDisplay(EGL_PLATFORM_GBM_KHR, dpy.gbm, NULL); |
| #else |
| dpy.egl = eglGetDisplay(dpy.gbm); |
| #endif |
| |
| if (dpy.egl == EGL_NO_DISPLAY) { |
| abort(); |
| } |
| |
| EGLint major, minor; |
| if (!eglInitialize(dpy.egl, &major, &minor)) { |
| 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(); |
| } |
| |
| // Find a config whose native visual ID is the desired GBM format. |
| for (int i = 0; i < num_configs; ++i) { |
| EGLint gbm_format; |
| |
| if (!eglGetConfigAttrib(dpy.egl, configs[i], |
| EGL_NATIVE_VISUAL_ID, &gbm_format)) { |
| abort(); |
| } |
| |
| if (gbm_format == GBM_FORMAT_XRGB8888) { |
| config.egl = configs[i]; |
| free(configs); |
| return config; |
| } |
| } |
| |
| // Failed to find a config with 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(); |
| } |
| |
| #ifdef EGL_KHR_platform_gbm |
| window.egl = eglCreatePlatformWindowSurface(config.dpy.egl, |
| config.egl, |
| window.gbm, |
| NULL); |
| #else |
| window.egl = eglCreateWindowSurface(config.dpy.egl, |
| config.egl, |
| window.gbm, |
| NULL); |
| #endif |
| |
| 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); |
| |
| return 0; |
| } |
| |
| Revision History |
| |
| Version 3, 2016-01-04 (Jon Leech) |
| - Free config memory allocated in sample code (Public Bug 1445). |
| |
| Version 2, 2014/02/12 (Chad Versace) |
| - Change resolution of issue #1 from "no" to "yes". Now |
| eglGetPlatformDisplay accepts EGL_DEFAULT_DISPLAY for GBM. |
| |
| Version 1, 2014/01/22 (Jon Leech) |
| - Promote EGL_MESA_platform_gbm to KHR to go with EGL 1.5. |