| Name |
| |
| MESA_platform_gbm |
| |
| Name Strings |
| |
| EGL_MESA_platform_gbm |
| |
| Contributors |
| |
| Chad Versace <chad.versace@intel.com> |
| Kristian Høgsberg <krh@bitplanet.org> |
| |
| Contacts |
| |
| Chad Versace <chad.versace@intel.com> |
| |
| Status |
| |
| Complete |
| |
| Version |
| |
| Version 7, 2016/01/04 |
| |
| Number |
| |
| EGL Extension #62 |
| |
| Extension Type |
| |
| EGL client extension |
| |
| Dependencies |
| |
| Requires EGL_EXT_client_extensions to query its existence without |
| a display. |
| |
| Requires EGL_EXT_platform_base. |
| |
| This extension is written against the wording of version 7 of the |
| EGL_EXT_platform_base specification. |
| |
| Overview |
| |
| This extension defines how to create EGL resources from native GBM |
| resources using the functions defined by EGL_EXT_platform_base. (GBM is |
| a Generic Buffer Manager for Linux). |
| |
| New Types |
| |
| None |
| |
| New Procedures and Functions |
| |
| None |
| |
| New Tokens |
| |
| Accepted as the <platform> argument of eglGetPlatformDisplayEXT: |
| |
| EGL_PLATFORM_GBM_MESA 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 eglGetPlatformDisplayEXT with |
| <platform> set to EGL_PLATFORM_GBM_MESA. The <native_display> parameter |
| specifies the GBM device to use and must either point to a `struct |
| gbm_device` or be NULL. If <native_display> is NULL, 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 |
| eglCreatePlatformWindowSurfaceEXT 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 eglCreatePlatformPixmapSurfaceEXT with a <dpy> that |
| belongs to the GBM platform. Any such call fails and generates |
| EGL_BAD_PARAMETER. |
| |
| Issues |
| |
| 1. Should this extension permit NULL as input to eglGetPlatformDisplayEXT? |
| |
| RESOLUTION: Yes. When given NULL, eglGetPlatformDisplayEXT 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_MESA_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_MESA_platform_gbm |
| const char *client_extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); |
| |
| if (!client_extensions) { |
| // EGL_EXT_client_extensions is unsupported. |
| abort(); |
| } |
| if (!strstr(client_extensions, "EGL_MESA_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_MESA_platform_gbm |
| dpy.egl = eglGetPlatformDisplayEXT(EGL_PLATFORM_GBM_MESA, 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_MESA_platform_gbm |
| window.egl = eglCreatePlatformWindowSurfaceEXT(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 8, 2018-05-25 (Krzysztof Kosiński) |
| - Corrected EGL_DEFAULT_DISPLAY to NULL. The second argument to |
| eglGetPlatformDisplayEXT has type void*, while EGL_DEFAULT_DISPLAY has |
| type EGLNativeDisplayType, which is not guaranteed to be convertible |
| to void* - it could be int, long or intptr_t. |
| |
| Version 7, 2016-01-04 (Jon Leech) |
| - Free config memory allocated in sample code (Public Bug 1445). |
| |
| Version 6, 2014-02-12 (Chad Versace) |
| - Change resolution of issue #1 from "no" to "yes". Now |
| eglGetPlatformDisplayEXT accepts EGL_DEFAULT_DISPLAY for GBM. |
| |
| Version 5, 2013-010-15 (Chad Versace) |
| - Specify that EGL_NATIVE_VISUAL_ID is a GBM color format. |
| - Require for eglCreatePlatformWindowSurfaceEXT that the GBM color |
| format not differ between the EGLConfig and gbm_surface. (Suggested |
| by Kristian). |
| - Update example code to find matching EGL_NATIVE_VISUAL_ID. |
| |
| Version 4, 2013-09-13 (Chad Versace) |
| - Update the text and example code to wording of version 7 of |
| EGL_EXT_platform_base spec. |
| - Add section "Extension Type". |
| - Resolve issue #1 to "No". |
| - Add issue #2. |
| |
| Version 3, 2013-04-26 (Chad Versace) |
| - Add missing MESA suffix to new token. |
| |
| Version 2, 2013-04-23 (Chad Versace) |
| - Add issue #1 regarding EGL_DEFAULT_DISPLAY. |
| |
| Version 1, 2013.03.24 (Chad Versace) |
| - First draft |