| Name |
| |
| KHR_platform_x11 |
| |
| Name Strings |
| |
| EGL_KHR_platform_x11 |
| |
| Contributors |
| |
| Chad Versace <chad.versace@intel.com> |
| James Jones <jajones@nvidia.com> |
| Jon Leech (oddhack 'at' sonic.net) |
| |
| Contacts |
| |
| Chad Versace <chad.versace@intel.com> |
| |
| 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 <platform> argument of eglGetPlatformDisplay: |
| |
| EGL_PLATFORM_X11_KHR 0x31D5 |
| |
| Accepted as an attribute name in the <attrib_list> 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 <platform> set to EGL_PLATFORM_X11_KHR. The <native_display> parameter |
| specifies the X11 display connection to use, and must either point to |
| a valid X11 `Display` or be EGL_DEFAULT_DISPLAY. If <native_display> 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 <attrib_list>, 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 <dpy> that belongs to X11 and |
| a <native_window> that points to an X11 Window. |
| |
| To obtain an offscreen rendering surface from an X11 Pixmap, call |
| eglCreatePlatformPixmapSurface with a <dpy> that belongs to X11 and |
| a <native_pixmap> 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 <stdlib.h> |
| #include <string.h> |
| |
| #include <EGL/egl.h> |
| #include <X11/Xlib.h> |
| |
| 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 |
| <native_display> 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. |