Name KHR_platform_x11 Name Strings EGL_KHR_platform_x11 Contributors Chad Versace James Jones Jon Leech (oddhack 'at' sonic.net) Contacts Chad Versace Status Complete. Approved by the EGL Working Group on January 31, 2014. Ratified by the Khronos Board of Promoters on March 14, 2014. Version Version 3, 2014/02/18 Number EGL Extension #71 Extension Type EGL client extension Dependencies EGL 1.5 is required. This extension is written against the EGL 1.5 Specification (draft 20140122). Overview This extension defines how to create EGL resources from native X11 resources using the EGL 1.5 platform functionality. This extension only defines how to create EGL resources from Xlib resources. It does not define how to do so from xcb resources. All X11 types discussed here are defined by the header `Xlib.h`. New Types None New Procedures and Functions None New Tokens Accepted as the argument of eglGetPlatformDisplay: EGL_PLATFORM_X11_KHR 0x31D5 Accepted as an attribute name in the argument of eglGetPlatformDisplay: EGL_PLATFORM_X11_SCREEN_KHR 0x31D6 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. On the X11 platform, an EGLDisplay refers to a specific X11 screen rather than an X11 display connection. This is the case because separate X11 screens, even when belonging to the same X11 display connection, may reside on different GPUs and/or be driven by different drivers. Therefore, different X11 screens may have different EGL capabilities. To obtain an EGLDisplay backed by an X11 screen, call eglGetPlatformDisplay with set to EGL_PLATFORM_X11_KHR. The parameter specifies the X11 display connection to use, and must either point to a valid X11 `Display` or be EGL_DEFAULT_DISPLAY. If is EGL_DEFAULT_DISPLAY, then EGL will create [1] a connection to the default X11 display. The environment variable DISPLAY determines the default X11 display as described in the manual page for XOpenDisplay(3). The value of attribute EGL_PLATFORM_X11_SCREEN_KHR specifies the X11 screen to use. If the attribute is omitted from , then the display connection's default screen is used. Otherwise, the attribute's value must be a valid screen on the display connection. If the attribute's value is not a valid screen, then an EGL_BAD_ATTRIBUTE error is generated. [fn1] The method by which EGL creates a connection to the default X11 display is an internal implementation detail. The implementation may use XOpenDisplay, xcb_connect, or any other method. To obtain an on-screen rendering surface from an X11 Window, call eglCreatePlatformWindowSurface with a that belongs to X11 and a that points to an X11 Window. To obtain an offscreen rendering surface from an X11 Pixmap, call eglCreatePlatformPixmapSurface with a that belongs to X11 and a that points to an X11 Pixmap. Issues 1. Should this extension permit EGL_DEFAULT_DISPLAY as input to eglGetPlatformDisplay()? RESOLVED. Yes. When given EGL_DEFAULT_DISPLAY, eglGetPlatformDisplay returns an EGLDisplay backed by the default X11 display. 2. When given EGL_DEFAULT_DISPLAY, does eglGetPlatformDisplay reuse an existing X11 display connection or create a new one? RESOLVED. eglGetPlatformDisplay creates a new connection because the alternative is infeasible. EGL cannot reliably detect if the client process already has a X11 display connection. Example Code // This example program creates two EGL surfaces: one from an X11 Window // and the other from an X11 Pixmap. // // If the macro USE_EGL_KHR_PLATFORM_X11 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 -lX11 -lEGL`. #include #include #include #include struct my_display { Display *x11; EGLDisplay egl; }; struct my_config { struct my_display dpy; XVisualInfo *x11; Colormap colormap; EGLConfig egl; }; struct my_window { struct my_config config; Window x11; EGLSurface egl; }; struct my_pixmap { struct my_config config; Pixmap x11; EGLSurface egl; }; static void check_extensions(void) { #ifdef USE_EGL_KHR_PLATFORM_X11 const char *client_extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); if (!client_extensions) { // No client extensions string available abort(); } if (!strstr(client_extensions, "EGL_KHR_platform_x11")) { abort(); } #endif } static struct my_display get_display(void) { struct my_display dpy; dpy.x11 = XOpenDisplay(NULL); if (!dpy.x11) { abort(); } #ifdef USE_EGL_KHR_PLATFORM_X11 dpy.egl = eglGetPlatformDisplay(EGL_PLATFORM_X11_KHR, dpy.x11, NULL); #else dpy.egl = eglGetDisplay(dpy.x11); #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_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8, 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_PIXMAP_BIT, EGL_NONE, }; EGLint num_configs; if (!eglChooseConfig(dpy.egl, egl_config_attribs, &config.egl, 1, &num_configs)) { abort(); } if (num_configs == 0) { abort(); } XVisualInfo x11_visual_info_template; if (!eglGetConfigAttrib(dpy.egl, config.egl, EGL_NATIVE_VISUAL_ID, (EGLint*) &x11_visual_info_template.visualid)) { abort(); } int num_visuals; config.x11 = XGetVisualInfo(dpy.x11, VisualIDMask, &x11_visual_info_template, &num_visuals); if (!config.x11) { abort(); } config.colormap = XCreateColormap(dpy.x11, RootWindow(dpy.x11, 0), config.x11->visual, AllocNone); if (config.colormap == None) { abort(); } return config; } static struct my_window get_window(struct my_config config) { XSetWindowAttributes attr; unsigned long mask; struct my_window window = { .config = config, }; attr.colormap = config.colormap; mask = CWColormap; window.x11 = XCreateWindow(config.dpy.x11, DefaultRootWindow(config.dpy.x11), // parent 0, 0, // x, y 256, 256, // width, height 0, // border_width config.x11->depth, InputOutput, // class config.x11->visual, mask, // valuemask &attr); // attributes if (!window.x11) { abort(); } #ifdef USE_EGL_KHR_PLATFORM_X11 window.egl = eglCreatePlatformWindowSurface(config.dpy.egl, config.egl, &window.x11, NULL); #else window.egl = eglCreateWindowSurface(config.dpy.egl, config.egl, window.x11, NULL); #endif if (window.egl == EGL_NO_SURFACE) { abort(); } return window; } static struct my_pixmap get_pixmap(struct my_config config) { struct my_pixmap pixmap = { .config = config, }; pixmap.x11 = XCreatePixmap(config.dpy.x11, DefaultRootWindow(config.dpy.x11), 256, 256, // width, height config.x11->depth); if (!pixmap.x11) { abort(); } #ifdef USE_EGL_KHR_PLATFORM_X11 pixmap.egl = eglCreatePlatformPixmapSurface(config.dpy.egl, config.egl, &pixmap.x11, NULL); #else pixmap.egl = eglCreatePixmapSurface(config.dpy.egl, config.egl, pixmap.x11, NULL); #endif if (pixmap.egl == EGL_NO_SURFACE) { abort(); } return pixmap; } 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); struct my_pixmap pixmap = get_pixmap(config); return 0; } Revision History Version 3, 2014/02/18 (Chad Versace) - Update text to reflect resolution of issue #1. State that may be EGL_DEFAULT_DISPLAY. - Explain in more detail how EGL connects to the default X11 display. - Add and resolve issue #2. Version 2, 2014/02/11 (Chad Versace) - Fix 2nd argument to XCreatePixmap in example code. Version 1, 2014/01/22 (Jon Leech) - Promote EGL_EXT_platform_x11 to KHR to go with EGL 1.5.