• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1Name
2
3    KHR_platform_gbm
4
5Name Strings
6
7    EGL_KHR_platform_gbm
8
9Contributors
10
11    Chad Versace <chad.versace@intel.com>
12    Jon Leech (oddhack 'at' sonic.net)
13    Kristian Høgsberg <krh@bitplanet.org>
14
15Contacts
16
17    Chad Versace <chad.versace@intel.com>
18
19Status
20
21    Complete.
22    Approved by the EGL Working Group on January 31, 2014.
23    Ratified by the Khronos Board of Promoters on March 14, 2014.
24
25Version
26
27    Version 3, 2016/01/04
28
29Number
30
31    EGL Extension #69
32
33Extension Type
34
35    EGL client extension
36
37Dependencies
38
39    EGL 1.5 is required.
40
41    This extension is written against the EGL 1.5 Specification (draft
42    20140122).
43
44Overview
45
46    This extension defines how to create EGL resources from native GBM
47    resources using the EGL 1.5 platform functionality (GBM is a Generic
48    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 eglGetPlatformDisplay:
61
62        EGL_PLATFORM_GBM_KHR                     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 eglGetPlatformDisplay with
74    <platform> set to EGL_PLATFORM_GBM_KHR. The <native_display> parameter
75    specifies the GBM device to use and must either point to a `struct
76    gbm_device` or be EGL_DEFAULT_DISPLAY. If <native_display> is
77    EGL_DEFAULT_DISPLAY, then the resultant EGLDisplay will be backed by some
78    implementation-chosen GBM device.
79
80    For each EGLConfig that belongs to the GBM platform, the
81    EGL_NATIVE_VISUAL_ID attribute is a GBM color format, such as
82    GBM_FORMAT_XRGB8888.
83
84    To obtain a rendering surface from a GBM surface, call
85    eglCreatePlatformWindowSurface with a <dpy> that belongs to the GBM
86    platform and a <native_window> that points to a `struct gbm_surface`.  If
87    <native_window> was created without the GBM_BO_USE_RENDERING flag, or if
88    the color format of <native_window> differs from the EGL_NATIVE_VISUAL_ID
89    of <config>, then the function fails and generates EGL_BAD_MATCH.
90
91    It is not valid to call eglCreatePlatformPixmapSurface with a <dpy> that
92    belongs to the GBM platform. Any such call fails and generates
93    an EGL_BAD_PARAMETER error.
94
95Issues
96
97    1. Should this extension permit EGL_DEFAULT_DISPLAY as input to
98       eglGetPlatformDisplay?
99
100       RESOLUTION: Yes. When given EGL_DEFAULT_DISPLAY, eglGetPlatformDisplay
101       returns an EGLDisplay backed by an implementation-chosen GBM device.
102
103Example Code
104
105    // This example program creates an EGL surface from a GBM surface.
106    //
107    // If the macro EGL_KHR_platform_gbm is defined, then the program
108    // creates the surfaces using the methods defined in this specification.
109    // Otherwise, it uses the methods defined by the EGL 1.4 specification.
110    //
111    // Compile with `cc -std=c99 example.c -lgbm -lEGL`.
112
113    #include <stdlib.h>
114    #include <string.h>
115
116    #include <sys/types.h>
117    #include <sys/stat.h>
118    #include <fcntl.h>
119
120    #include <EGL/egl.h>
121    #include <gbm.h>
122
123    struct my_display {
124        struct gbm_device *gbm;
125        EGLDisplay egl;
126    };
127
128    struct my_config {
129        struct my_display dpy;
130        EGLConfig egl;
131    };
132
133    struct my_window {
134        struct my_config config;
135        struct gbm_surface *gbm;
136        EGLSurface egl;
137    };
138
139    static void
140    check_extensions(void)
141    {
142    #ifdef EGL_KHR_platform_gbm
143        const char *client_extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
144
145        if (!client_extensions) {
146            // No client extensions string available
147            abort();
148        }
149        if (!strstr(client_extensions, "EGL_KHR_platform_gbm")) {
150            abort();
151        }
152    #endif
153    }
154
155    static struct my_display
156    get_display(void)
157    {
158        struct my_display dpy;
159
160        int fd = open("/dev/dri/card0", O_RDWR | FD_CLOEXEC);
161        if (fd < 0) {
162            abort();
163        }
164
165        dpy.gbm = gbm_create_device(fd);
166        if (!dpy.gbm) {
167            abort();
168        }
169
170
171    #ifdef EGL_KHR_platform_gbm
172        dpy.egl = eglGetPlatformDisplay(EGL_PLATFORM_GBM_KHR, dpy.gbm, NULL);
173    #else
174        dpy.egl = eglGetDisplay(dpy.gbm);
175    #endif
176
177        if (dpy.egl == EGL_NO_DISPLAY) {
178            abort();
179        }
180
181        EGLint major, minor;
182        if (!eglInitialize(dpy.egl, &major, &minor)) {
183            abort();
184        }
185
186        return dpy;
187    }
188
189    static struct my_config
190    get_config(struct my_display dpy)
191    {
192        struct my_config config = {
193            .dpy = dpy,
194        };
195
196        EGLint egl_config_attribs[] = {
197            EGL_BUFFER_SIZE,        32,
198            EGL_DEPTH_SIZE,         EGL_DONT_CARE,
199            EGL_STENCIL_SIZE,       EGL_DONT_CARE,
200            EGL_RENDERABLE_TYPE,    EGL_OPENGL_ES2_BIT,
201            EGL_SURFACE_TYPE,       EGL_WINDOW_BIT,
202            EGL_NONE,
203        };
204
205        EGLint num_configs;
206        if (!eglGetConfigs(dpy.egl, NULL, 0, &num_configs)) {
207            abort();
208        }
209
210        EGLConfig *configs = malloc(num_configs * sizeof(EGLConfig));
211        if (!eglChooseConfig(dpy.egl, egl_config_attribs,
212                             configs, num_configs, &num_configs)) {
213            abort();
214        }
215        if (num_configs == 0) {
216            abort();
217        }
218
219        // Find a config whose native visual ID is the desired GBM format.
220        for (int i = 0; i < num_configs; ++i) {
221            EGLint gbm_format;
222
223            if (!eglGetConfigAttrib(dpy.egl, configs[i],
224                                    EGL_NATIVE_VISUAL_ID, &gbm_format)) {
225                abort();
226            }
227
228            if (gbm_format == GBM_FORMAT_XRGB8888) {
229                config.egl = configs[i];
230                free(configs);
231                return config;
232            }
233        }
234
235        // Failed to find a config with matching GBM format.
236        abort();
237    }
238
239    static struct my_window
240    get_window(struct my_config config)
241    {
242        struct my_window window = {
243            .config = config,
244        };
245
246        window.gbm = gbm_surface_create(config.dpy.gbm,
247                                        256, 256,
248                                        GBM_FORMAT_XRGB8888,
249                                        GBM_BO_USE_RENDERING);
250        if (!window.gbm) {
251            abort();
252        }
253
254    #ifdef EGL_KHR_platform_gbm
255        window.egl = eglCreatePlatformWindowSurface(config.dpy.egl,
256                                                    config.egl,
257                                                    window.gbm,
258                                                    NULL);
259    #else
260        window.egl = eglCreateWindowSurface(config.dpy.egl,
261                                            config.egl,
262                                            window.gbm,
263                                            NULL);
264    #endif
265
266        if (window.egl == EGL_NO_SURFACE) {
267            abort();
268        }
269
270        return window;
271    }
272
273    int
274    main(void)
275    {
276        check_extensions();
277
278        struct my_display dpy = get_display();
279        struct my_config config = get_config(dpy);
280        struct my_window window = get_window(config);
281
282        return 0;
283    }
284
285Revision History
286
287    Version 3, 2016-01-04 (Jon Leech)
288        - Free config memory allocated in sample code (Public Bug 1445).
289
290    Version 2, 2014/02/12 (Chad Versace)
291        - Change resolution of issue #1 from "no" to "yes". Now
292          eglGetPlatformDisplay accepts EGL_DEFAULT_DISPLAY for GBM.
293
294    Version 1, 2014/01/22 (Jon Leech)
295        - Promote EGL_MESA_platform_gbm to KHR to go with EGL 1.5.
296