102f4aeb0Sopenharmony_ciName
202f4aeb0Sopenharmony_ci
302f4aeb0Sopenharmony_ci    KHR_platform_gbm
402f4aeb0Sopenharmony_ci
502f4aeb0Sopenharmony_ciName Strings
602f4aeb0Sopenharmony_ci
702f4aeb0Sopenharmony_ci    EGL_KHR_platform_gbm
802f4aeb0Sopenharmony_ci
902f4aeb0Sopenharmony_ciContributors
1002f4aeb0Sopenharmony_ci
1102f4aeb0Sopenharmony_ci    Chad Versace <chad.versace@intel.com>
1202f4aeb0Sopenharmony_ci    Jon Leech (oddhack 'at' sonic.net)
1302f4aeb0Sopenharmony_ci    Kristian Høgsberg <krh@bitplanet.org>
1402f4aeb0Sopenharmony_ci
1502f4aeb0Sopenharmony_ciContacts
1602f4aeb0Sopenharmony_ci
1702f4aeb0Sopenharmony_ci    Chad Versace <chad.versace@intel.com>
1802f4aeb0Sopenharmony_ci
1902f4aeb0Sopenharmony_ciStatus
2002f4aeb0Sopenharmony_ci
2102f4aeb0Sopenharmony_ci    Complete.
2202f4aeb0Sopenharmony_ci    Approved by the EGL Working Group on January 31, 2014.
2302f4aeb0Sopenharmony_ci    Ratified by the Khronos Board of Promoters on March 14, 2014.
2402f4aeb0Sopenharmony_ci
2502f4aeb0Sopenharmony_ciVersion
2602f4aeb0Sopenharmony_ci
2702f4aeb0Sopenharmony_ci    Version 3, 2016/01/04
2802f4aeb0Sopenharmony_ci
2902f4aeb0Sopenharmony_ciNumber
3002f4aeb0Sopenharmony_ci
3102f4aeb0Sopenharmony_ci    EGL Extension #69
3202f4aeb0Sopenharmony_ci
3302f4aeb0Sopenharmony_ciExtension Type
3402f4aeb0Sopenharmony_ci
3502f4aeb0Sopenharmony_ci    EGL client extension
3602f4aeb0Sopenharmony_ci
3702f4aeb0Sopenharmony_ciDependencies
3802f4aeb0Sopenharmony_ci
3902f4aeb0Sopenharmony_ci    EGL 1.5 is required.
4002f4aeb0Sopenharmony_ci
4102f4aeb0Sopenharmony_ci    This extension is written against the EGL 1.5 Specification (draft
4202f4aeb0Sopenharmony_ci    20140122).
4302f4aeb0Sopenharmony_ci
4402f4aeb0Sopenharmony_ciOverview
4502f4aeb0Sopenharmony_ci
4602f4aeb0Sopenharmony_ci    This extension defines how to create EGL resources from native GBM
4702f4aeb0Sopenharmony_ci    resources using the EGL 1.5 platform functionality (GBM is a Generic
4802f4aeb0Sopenharmony_ci    Buffer Manager for Linux).
4902f4aeb0Sopenharmony_ci
5002f4aeb0Sopenharmony_ciNew Types
5102f4aeb0Sopenharmony_ci
5202f4aeb0Sopenharmony_ci    None
5302f4aeb0Sopenharmony_ci
5402f4aeb0Sopenharmony_ciNew Procedures and Functions
5502f4aeb0Sopenharmony_ci
5602f4aeb0Sopenharmony_ci    None
5702f4aeb0Sopenharmony_ci
5802f4aeb0Sopenharmony_ciNew Tokens
5902f4aeb0Sopenharmony_ci
6002f4aeb0Sopenharmony_ci    Accepted as the <platform> argument of eglGetPlatformDisplay:
6102f4aeb0Sopenharmony_ci
6202f4aeb0Sopenharmony_ci        EGL_PLATFORM_GBM_KHR                     0x31D7
6302f4aeb0Sopenharmony_ci
6402f4aeb0Sopenharmony_ciAdditions to the EGL Specification
6502f4aeb0Sopenharmony_ci
6602f4aeb0Sopenharmony_ci    None.
6702f4aeb0Sopenharmony_ci
6802f4aeb0Sopenharmony_ciNew Behavior
6902f4aeb0Sopenharmony_ci
7002f4aeb0Sopenharmony_ci    To determine if the EGL implementation supports this extension, clients
7102f4aeb0Sopenharmony_ci    should query the EGL_EXTENSIONS string of EGL_NO_DISPLAY.
7202f4aeb0Sopenharmony_ci
7302f4aeb0Sopenharmony_ci    To obtain an EGLDisplay from an GBM device, call eglGetPlatformDisplay with
7402f4aeb0Sopenharmony_ci    <platform> set to EGL_PLATFORM_GBM_KHR. The <native_display> parameter
7502f4aeb0Sopenharmony_ci    specifies the GBM device to use and must either point to a `struct
7602f4aeb0Sopenharmony_ci    gbm_device` or be EGL_DEFAULT_DISPLAY. If <native_display> is
7702f4aeb0Sopenharmony_ci    EGL_DEFAULT_DISPLAY, then the resultant EGLDisplay will be backed by some
7802f4aeb0Sopenharmony_ci    implementation-chosen GBM device.
7902f4aeb0Sopenharmony_ci
8002f4aeb0Sopenharmony_ci    For each EGLConfig that belongs to the GBM platform, the
8102f4aeb0Sopenharmony_ci    EGL_NATIVE_VISUAL_ID attribute is a GBM color format, such as
8202f4aeb0Sopenharmony_ci    GBM_FORMAT_XRGB8888.
8302f4aeb0Sopenharmony_ci
8402f4aeb0Sopenharmony_ci    To obtain a rendering surface from a GBM surface, call
8502f4aeb0Sopenharmony_ci    eglCreatePlatformWindowSurface with a <dpy> that belongs to the GBM
8602f4aeb0Sopenharmony_ci    platform and a <native_window> that points to a `struct gbm_surface`.  If
8702f4aeb0Sopenharmony_ci    <native_window> was created without the GBM_BO_USE_RENDERING flag, or if
8802f4aeb0Sopenharmony_ci    the color format of <native_window> differs from the EGL_NATIVE_VISUAL_ID
8902f4aeb0Sopenharmony_ci    of <config>, then the function fails and generates EGL_BAD_MATCH.
9002f4aeb0Sopenharmony_ci
9102f4aeb0Sopenharmony_ci    It is not valid to call eglCreatePlatformPixmapSurface with a <dpy> that
9202f4aeb0Sopenharmony_ci    belongs to the GBM platform. Any such call fails and generates
9302f4aeb0Sopenharmony_ci    an EGL_BAD_PARAMETER error.
9402f4aeb0Sopenharmony_ci
9502f4aeb0Sopenharmony_ciIssues
9602f4aeb0Sopenharmony_ci
9702f4aeb0Sopenharmony_ci    1. Should this extension permit EGL_DEFAULT_DISPLAY as input to
9802f4aeb0Sopenharmony_ci       eglGetPlatformDisplay?
9902f4aeb0Sopenharmony_ci
10002f4aeb0Sopenharmony_ci       RESOLUTION: Yes. When given EGL_DEFAULT_DISPLAY, eglGetPlatformDisplay
10102f4aeb0Sopenharmony_ci       returns an EGLDisplay backed by an implementation-chosen GBM device.
10202f4aeb0Sopenharmony_ci
10302f4aeb0Sopenharmony_ciExample Code
10402f4aeb0Sopenharmony_ci
10502f4aeb0Sopenharmony_ci    // This example program creates an EGL surface from a GBM surface.
10602f4aeb0Sopenharmony_ci    //
10702f4aeb0Sopenharmony_ci    // If the macro EGL_KHR_platform_gbm is defined, then the program
10802f4aeb0Sopenharmony_ci    // creates the surfaces using the methods defined in this specification.
10902f4aeb0Sopenharmony_ci    // Otherwise, it uses the methods defined by the EGL 1.4 specification.
11002f4aeb0Sopenharmony_ci    //
11102f4aeb0Sopenharmony_ci    // Compile with `cc -std=c99 example.c -lgbm -lEGL`.
11202f4aeb0Sopenharmony_ci
11302f4aeb0Sopenharmony_ci    #include <stdlib.h>
11402f4aeb0Sopenharmony_ci    #include <string.h>
11502f4aeb0Sopenharmony_ci
11602f4aeb0Sopenharmony_ci    #include <sys/types.h>
11702f4aeb0Sopenharmony_ci    #include <sys/stat.h>
11802f4aeb0Sopenharmony_ci    #include <fcntl.h>
11902f4aeb0Sopenharmony_ci
12002f4aeb0Sopenharmony_ci    #include <EGL/egl.h>
12102f4aeb0Sopenharmony_ci    #include <gbm.h>
12202f4aeb0Sopenharmony_ci
12302f4aeb0Sopenharmony_ci    struct my_display {
12402f4aeb0Sopenharmony_ci        struct gbm_device *gbm;
12502f4aeb0Sopenharmony_ci        EGLDisplay egl;
12602f4aeb0Sopenharmony_ci    };
12702f4aeb0Sopenharmony_ci
12802f4aeb0Sopenharmony_ci    struct my_config {
12902f4aeb0Sopenharmony_ci        struct my_display dpy;
13002f4aeb0Sopenharmony_ci        EGLConfig egl;
13102f4aeb0Sopenharmony_ci    };
13202f4aeb0Sopenharmony_ci
13302f4aeb0Sopenharmony_ci    struct my_window {
13402f4aeb0Sopenharmony_ci        struct my_config config;
13502f4aeb0Sopenharmony_ci        struct gbm_surface *gbm;
13602f4aeb0Sopenharmony_ci        EGLSurface egl;
13702f4aeb0Sopenharmony_ci    };
13802f4aeb0Sopenharmony_ci
13902f4aeb0Sopenharmony_ci    static void
14002f4aeb0Sopenharmony_ci    check_extensions(void)
14102f4aeb0Sopenharmony_ci    {
14202f4aeb0Sopenharmony_ci    #ifdef EGL_KHR_platform_gbm
14302f4aeb0Sopenharmony_ci        const char *client_extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
14402f4aeb0Sopenharmony_ci
14502f4aeb0Sopenharmony_ci        if (!client_extensions) {
14602f4aeb0Sopenharmony_ci            // No client extensions string available
14702f4aeb0Sopenharmony_ci            abort();
14802f4aeb0Sopenharmony_ci        }
14902f4aeb0Sopenharmony_ci        if (!strstr(client_extensions, "EGL_KHR_platform_gbm")) {
15002f4aeb0Sopenharmony_ci            abort();
15102f4aeb0Sopenharmony_ci        }
15202f4aeb0Sopenharmony_ci    #endif
15302f4aeb0Sopenharmony_ci    }
15402f4aeb0Sopenharmony_ci
15502f4aeb0Sopenharmony_ci    static struct my_display
15602f4aeb0Sopenharmony_ci    get_display(void)
15702f4aeb0Sopenharmony_ci    {
15802f4aeb0Sopenharmony_ci        struct my_display dpy;
15902f4aeb0Sopenharmony_ci
16002f4aeb0Sopenharmony_ci        int fd = open("/dev/dri/card0", O_RDWR | FD_CLOEXEC);
16102f4aeb0Sopenharmony_ci        if (fd < 0) {
16202f4aeb0Sopenharmony_ci            abort();
16302f4aeb0Sopenharmony_ci        }
16402f4aeb0Sopenharmony_ci
16502f4aeb0Sopenharmony_ci        dpy.gbm = gbm_create_device(fd);
16602f4aeb0Sopenharmony_ci        if (!dpy.gbm) {
16702f4aeb0Sopenharmony_ci            abort();
16802f4aeb0Sopenharmony_ci        }
16902f4aeb0Sopenharmony_ci
17002f4aeb0Sopenharmony_ci
17102f4aeb0Sopenharmony_ci    #ifdef EGL_KHR_platform_gbm
17202f4aeb0Sopenharmony_ci        dpy.egl = eglGetPlatformDisplay(EGL_PLATFORM_GBM_KHR, dpy.gbm, NULL);
17302f4aeb0Sopenharmony_ci    #else
17402f4aeb0Sopenharmony_ci        dpy.egl = eglGetDisplay(dpy.gbm);
17502f4aeb0Sopenharmony_ci    #endif
17602f4aeb0Sopenharmony_ci
17702f4aeb0Sopenharmony_ci        if (dpy.egl == EGL_NO_DISPLAY) {
17802f4aeb0Sopenharmony_ci            abort();
17902f4aeb0Sopenharmony_ci        }
18002f4aeb0Sopenharmony_ci
18102f4aeb0Sopenharmony_ci        EGLint major, minor;
18202f4aeb0Sopenharmony_ci        if (!eglInitialize(dpy.egl, &major, &minor)) {
18302f4aeb0Sopenharmony_ci            abort();
18402f4aeb0Sopenharmony_ci        }
18502f4aeb0Sopenharmony_ci
18602f4aeb0Sopenharmony_ci        return dpy;
18702f4aeb0Sopenharmony_ci    }
18802f4aeb0Sopenharmony_ci
18902f4aeb0Sopenharmony_ci    static struct my_config
19002f4aeb0Sopenharmony_ci    get_config(struct my_display dpy)
19102f4aeb0Sopenharmony_ci    {
19202f4aeb0Sopenharmony_ci        struct my_config config = {
19302f4aeb0Sopenharmony_ci            .dpy = dpy,
19402f4aeb0Sopenharmony_ci        };
19502f4aeb0Sopenharmony_ci
19602f4aeb0Sopenharmony_ci        EGLint egl_config_attribs[] = {
19702f4aeb0Sopenharmony_ci            EGL_BUFFER_SIZE,        32,
19802f4aeb0Sopenharmony_ci            EGL_DEPTH_SIZE,         EGL_DONT_CARE,
19902f4aeb0Sopenharmony_ci            EGL_STENCIL_SIZE,       EGL_DONT_CARE,
20002f4aeb0Sopenharmony_ci            EGL_RENDERABLE_TYPE,    EGL_OPENGL_ES2_BIT,
20102f4aeb0Sopenharmony_ci            EGL_SURFACE_TYPE,       EGL_WINDOW_BIT,
20202f4aeb0Sopenharmony_ci            EGL_NONE,
20302f4aeb0Sopenharmony_ci        };
20402f4aeb0Sopenharmony_ci
20502f4aeb0Sopenharmony_ci        EGLint num_configs;
20602f4aeb0Sopenharmony_ci        if (!eglGetConfigs(dpy.egl, NULL, 0, &num_configs)) {
20702f4aeb0Sopenharmony_ci            abort();
20802f4aeb0Sopenharmony_ci        }
20902f4aeb0Sopenharmony_ci
21002f4aeb0Sopenharmony_ci        EGLConfig *configs = malloc(num_configs * sizeof(EGLConfig));
21102f4aeb0Sopenharmony_ci        if (!eglChooseConfig(dpy.egl, egl_config_attribs,
21202f4aeb0Sopenharmony_ci                             configs, num_configs, &num_configs)) {
21302f4aeb0Sopenharmony_ci            abort();
21402f4aeb0Sopenharmony_ci        }
21502f4aeb0Sopenharmony_ci        if (num_configs == 0) {
21602f4aeb0Sopenharmony_ci            abort();
21702f4aeb0Sopenharmony_ci        }
21802f4aeb0Sopenharmony_ci
21902f4aeb0Sopenharmony_ci        // Find a config whose native visual ID is the desired GBM format.
22002f4aeb0Sopenharmony_ci        for (int i = 0; i < num_configs; ++i) {
22102f4aeb0Sopenharmony_ci            EGLint gbm_format;
22202f4aeb0Sopenharmony_ci
22302f4aeb0Sopenharmony_ci            if (!eglGetConfigAttrib(dpy.egl, configs[i],
22402f4aeb0Sopenharmony_ci                                    EGL_NATIVE_VISUAL_ID, &gbm_format)) {
22502f4aeb0Sopenharmony_ci                abort();
22602f4aeb0Sopenharmony_ci            }
22702f4aeb0Sopenharmony_ci
22802f4aeb0Sopenharmony_ci            if (gbm_format == GBM_FORMAT_XRGB8888) {
22902f4aeb0Sopenharmony_ci                config.egl = configs[i];
23002f4aeb0Sopenharmony_ci                free(configs);
23102f4aeb0Sopenharmony_ci                return config;
23202f4aeb0Sopenharmony_ci            }
23302f4aeb0Sopenharmony_ci        }
23402f4aeb0Sopenharmony_ci
23502f4aeb0Sopenharmony_ci        // Failed to find a config with matching GBM format.
23602f4aeb0Sopenharmony_ci        abort();
23702f4aeb0Sopenharmony_ci    }
23802f4aeb0Sopenharmony_ci
23902f4aeb0Sopenharmony_ci    static struct my_window
24002f4aeb0Sopenharmony_ci    get_window(struct my_config config)
24102f4aeb0Sopenharmony_ci    {
24202f4aeb0Sopenharmony_ci        struct my_window window = {
24302f4aeb0Sopenharmony_ci            .config = config,
24402f4aeb0Sopenharmony_ci        };
24502f4aeb0Sopenharmony_ci
24602f4aeb0Sopenharmony_ci        window.gbm = gbm_surface_create(config.dpy.gbm,
24702f4aeb0Sopenharmony_ci                                        256, 256,
24802f4aeb0Sopenharmony_ci                                        GBM_FORMAT_XRGB8888,
24902f4aeb0Sopenharmony_ci                                        GBM_BO_USE_RENDERING);
25002f4aeb0Sopenharmony_ci        if (!window.gbm) {
25102f4aeb0Sopenharmony_ci            abort();
25202f4aeb0Sopenharmony_ci        }
25302f4aeb0Sopenharmony_ci
25402f4aeb0Sopenharmony_ci    #ifdef EGL_KHR_platform_gbm
25502f4aeb0Sopenharmony_ci        window.egl = eglCreatePlatformWindowSurface(config.dpy.egl,
25602f4aeb0Sopenharmony_ci                                                    config.egl,
25702f4aeb0Sopenharmony_ci                                                    window.gbm,
25802f4aeb0Sopenharmony_ci                                                    NULL);
25902f4aeb0Sopenharmony_ci    #else
26002f4aeb0Sopenharmony_ci        window.egl = eglCreateWindowSurface(config.dpy.egl,
26102f4aeb0Sopenharmony_ci                                            config.egl,
26202f4aeb0Sopenharmony_ci                                            window.gbm,
26302f4aeb0Sopenharmony_ci                                            NULL);
26402f4aeb0Sopenharmony_ci    #endif
26502f4aeb0Sopenharmony_ci
26602f4aeb0Sopenharmony_ci        if (window.egl == EGL_NO_SURFACE) {
26702f4aeb0Sopenharmony_ci            abort();
26802f4aeb0Sopenharmony_ci        }
26902f4aeb0Sopenharmony_ci
27002f4aeb0Sopenharmony_ci        return window;
27102f4aeb0Sopenharmony_ci    }
27202f4aeb0Sopenharmony_ci
27302f4aeb0Sopenharmony_ci    int
27402f4aeb0Sopenharmony_ci    main(void)
27502f4aeb0Sopenharmony_ci    {
27602f4aeb0Sopenharmony_ci        check_extensions();
27702f4aeb0Sopenharmony_ci
27802f4aeb0Sopenharmony_ci        struct my_display dpy = get_display();
27902f4aeb0Sopenharmony_ci        struct my_config config = get_config(dpy);
28002f4aeb0Sopenharmony_ci        struct my_window window = get_window(config);
28102f4aeb0Sopenharmony_ci
28202f4aeb0Sopenharmony_ci        return 0;
28302f4aeb0Sopenharmony_ci    }
28402f4aeb0Sopenharmony_ci
28502f4aeb0Sopenharmony_ciRevision History
28602f4aeb0Sopenharmony_ci
28702f4aeb0Sopenharmony_ci    Version 3, 2016-01-04 (Jon Leech)
28802f4aeb0Sopenharmony_ci        - Free config memory allocated in sample code (Public Bug 1445).
28902f4aeb0Sopenharmony_ci
29002f4aeb0Sopenharmony_ci    Version 2, 2014/02/12 (Chad Versace)
29102f4aeb0Sopenharmony_ci        - Change resolution of issue #1 from "no" to "yes". Now
29202f4aeb0Sopenharmony_ci          eglGetPlatformDisplay accepts EGL_DEFAULT_DISPLAY for GBM.
29302f4aeb0Sopenharmony_ci
29402f4aeb0Sopenharmony_ci    Version 1, 2014/01/22 (Jon Leech)
29502f4aeb0Sopenharmony_ci        - Promote EGL_MESA_platform_gbm to KHR to go with EGL 1.5.
296