• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1Name
2
3    MESA_platform_gbm
4
5Name Strings
6
7    EGL_MESA_platform_gbm
8
9Contributors
10
11    Chad Versace <chad.versace@intel.com>
12    Kristian Høgsberg <krh@bitplanet.org>
13
14Contacts
15
16    Chad Versace <chad.versace@intel.com>
17
18Status
19
20    Complete
21
22Version
23
24    Version 7, 2016/01/04
25
26Number
27
28    EGL Extension #62
29
30Extension Type
31
32    EGL client extension
33
34Dependencies
35
36    Requires EGL_EXT_client_extensions to query its existence without
37    a display.
38
39    Requires EGL_EXT_platform_base.
40
41    This extension is written against the wording of version 7 of the
42    EGL_EXT_platform_base specification.
43
44Overview
45
46    This extension defines how to create EGL resources from native GBM
47    resources using the functions defined by EGL_EXT_platform_base. (GBM is
48    a Generic Buffer Manager for Linux).
49
50New Types
51
52    None
53
54New Procedures and Functions
55
56    None
57
58New Tokens
59
60    Accepted as the <platform> argument of eglGetPlatformDisplayEXT:
61
62        EGL_PLATFORM_GBM_MESA                    0x31D7
63
64Additions to the EGL Specification
65
66    None.
67
68New Behavior
69
70    To determine if the EGL implementation supports this extension, clients
71    should query the EGL_EXTENSIONS string of EGL_NO_DISPLAY.
72
73    To obtain an EGLDisplay from an GBM device, call eglGetPlatformDisplayEXT with
74    <platform> set to EGL_PLATFORM_GBM_MESA. The <native_display> parameter
75    specifies the GBM device to use and must either point to a `struct
76    gbm_device` or be NULL. If <native_display> is NULL, then the resultant
77    EGLDisplay will be backed by some implementation-chosen GBM device.
78
79    For each EGLConfig that belongs to the GBM platform, the
80    EGL_NATIVE_VISUAL_ID attribute is a GBM color format, such as
81    GBM_FORMAT_XRGB8888.
82
83    To obtain a rendering surface from a GBM surface, call
84    eglCreatePlatformWindowSurfaceEXT with a <dpy> that belongs to the GBM
85    platform and a <native_window> that points to a `struct gbm_surface`.  If
86    <native_window> was created without the GBM_BO_USE_RENDERING flag, or if
87    the color format of <native_window> differs from the EGL_NATIVE_VISUAL_ID
88    of <config>, then the function fails and generates EGL_BAD_MATCH.
89
90    It is not valid to call eglCreatePlatformPixmapSurfaceEXT with a <dpy> that
91    belongs to the GBM platform. Any such call fails and generates
92    EGL_BAD_PARAMETER.
93
94Issues
95
96    1. Should this extension permit NULL as input to eglGetPlatformDisplayEXT?
97
98       RESOLUTION: Yes. When given NULL, eglGetPlatformDisplayEXT returns an
99       EGLDisplay backed by an implementation-chosen GBM device.
100
101Example Code
102
103    // This example program creates an EGL surface from a GBM surface.
104    //
105    // If the macro EGL_MESA_platform_gbm is defined, then the program
106    // creates the surfaces using the methods defined in this specification.
107    // Otherwise, it uses the methods defined by the EGL 1.4 specification.
108    //
109    // Compile with `cc -std=c99 example.c -lgbm -lEGL`.
110
111    #include <stdlib.h>
112    #include <string.h>
113
114    #include <sys/types.h>
115    #include <sys/stat.h>
116    #include <fcntl.h>
117
118    #include <EGL/egl.h>
119    #include <gbm.h>
120
121    struct my_display {
122        struct gbm_device *gbm;
123        EGLDisplay egl;
124    };
125
126    struct my_config {
127        struct my_display dpy;
128        EGLConfig egl;
129    };
130
131    struct my_window {
132        struct my_config config;
133        struct gbm_surface *gbm;
134        EGLSurface egl;
135    };
136
137    static void
138    check_extensions(void)
139    {
140    #ifdef EGL_MESA_platform_gbm
141        const char *client_extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
142
143        if (!client_extensions) {
144            // EGL_EXT_client_extensions is unsupported.
145            abort();
146        }
147        if (!strstr(client_extensions, "EGL_MESA_platform_gbm")) {
148            abort();
149        }
150    #endif
151    }
152
153    static struct my_display
154    get_display(void)
155    {
156        struct my_display dpy;
157
158        int fd = open("/dev/dri/card0", O_RDWR | FD_CLOEXEC);
159        if (fd < 0) {
160            abort();
161        }
162
163        dpy.gbm = gbm_create_device(fd);
164        if (!dpy.gbm) {
165            abort();
166        }
167
168
169    #ifdef EGL_MESA_platform_gbm
170        dpy.egl = eglGetPlatformDisplayEXT(EGL_PLATFORM_GBM_MESA, dpy.gbm, NULL);
171    #else
172        dpy.egl = eglGetDisplay(dpy.gbm);
173    #endif
174
175        if (dpy.egl == EGL_NO_DISPLAY) {
176            abort();
177        }
178
179        EGLint major, minor;
180        if (!eglInitialize(dpy.egl, &major, &minor)) {
181            abort();
182        }
183
184        return dpy;
185    }
186
187    static struct my_config
188    get_config(struct my_display dpy)
189    {
190        struct my_config config = {
191            .dpy = dpy,
192        };
193
194        EGLint egl_config_attribs[] = {
195            EGL_BUFFER_SIZE,        32,
196            EGL_DEPTH_SIZE,         EGL_DONT_CARE,
197            EGL_STENCIL_SIZE,       EGL_DONT_CARE,
198            EGL_RENDERABLE_TYPE,    EGL_OPENGL_ES2_BIT,
199            EGL_SURFACE_TYPE,       EGL_WINDOW_BIT,
200            EGL_NONE,
201        };
202
203        EGLint num_configs;
204        if (!eglGetConfigs(dpy.egl, NULL, 0, &num_configs)) {
205            abort();
206        }
207
208        EGLConfig *configs = malloc(num_configs * sizeof(EGLConfig));
209        if (!eglChooseConfig(dpy.egl, egl_config_attribs,
210                             configs, num_configs, &num_configs)) {
211            abort();
212        }
213        if (num_configs == 0) {
214            abort();
215        }
216
217        // Find a config whose native visual ID is the desired GBM format.
218        for (int i = 0; i < num_configs; ++i) {
219            EGLint gbm_format;
220
221            if (!eglGetConfigAttrib(dpy.egl, configs[i],
222                                    EGL_NATIVE_VISUAL_ID, &gbm_format)) {
223                abort();
224            }
225
226            if (gbm_format == GBM_FORMAT_XRGB8888) {
227                config.egl = configs[i];
228                free(configs);
229                return config;
230            }
231        }
232
233        // Failed to find a config with matching GBM format.
234        abort();
235    }
236
237    static struct my_window
238    get_window(struct my_config config)
239    {
240        struct my_window window = {
241            .config = config,
242        };
243
244        window.gbm = gbm_surface_create(config.dpy.gbm,
245                                        256, 256,
246                                        GBM_FORMAT_XRGB8888,
247                                        GBM_BO_USE_RENDERING);
248        if (!window.gbm) {
249            abort();
250        }
251
252    #ifdef EGL_MESA_platform_gbm
253        window.egl = eglCreatePlatformWindowSurfaceEXT(config.dpy.egl,
254                                                       config.egl,
255                                                       window.gbm,
256                                                       NULL);
257    #else
258        window.egl = eglCreateWindowSurface(config.dpy.egl,
259                                            config.egl,
260                                            window.gbm,
261                                            NULL);
262    #endif
263
264        if (window.egl == EGL_NO_SURFACE) {
265            abort();
266        }
267
268        return window;
269    }
270
271    int
272    main(void)
273    {
274        check_extensions();
275
276        struct my_display dpy = get_display();
277        struct my_config config = get_config(dpy);
278        struct my_window window = get_window(config);
279
280        return 0;
281    }
282
283Revision History
284
285    Version 8, 2018-05-25 (Krzysztof Kosiński)
286        - Corrected EGL_DEFAULT_DISPLAY to NULL. The second argument to
287          eglGetPlatformDisplayEXT has type void*, while EGL_DEFAULT_DISPLAY has
288          type EGLNativeDisplayType, which is not guaranteed to be convertible
289          to void* - it could be int, long or intptr_t.
290
291    Version 7, 2016-01-04 (Jon Leech)
292        - Free config memory allocated in sample code (Public Bug 1445).
293
294    Version 6, 2014-02-12 (Chad Versace)
295        - Change resolution of issue #1 from "no" to "yes". Now
296          eglGetPlatformDisplayEXT accepts EGL_DEFAULT_DISPLAY for GBM.
297
298    Version 5, 2013-010-15 (Chad Versace)
299        - Specify that EGL_NATIVE_VISUAL_ID is a GBM color format.
300        - Require for eglCreatePlatformWindowSurfaceEXT that the GBM color
301          format not differ between the EGLConfig and gbm_surface. (Suggested
302          by Kristian).
303        - Update example code to find matching EGL_NATIVE_VISUAL_ID.
304
305    Version 4, 2013-09-13 (Chad Versace)
306        - Update the text and example code to wording of version 7 of
307          EGL_EXT_platform_base spec.
308        - Add section "Extension Type".
309        - Resolve issue #1 to "No".
310        - Add issue #2.
311
312    Version 3, 2013-04-26 (Chad Versace)
313        - Add missing MESA suffix to new token.
314
315    Version 2, 2013-04-23 (Chad Versace)
316        - Add issue #1 regarding EGL_DEFAULT_DISPLAY.
317
318    Version 1, 2013.03.24 (Chad Versace)
319        - First draft
320