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