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