blob: a4c04e0b4117c2d533441ec8cf291fd658a99097 [file] [log] [blame]
Name
KHR_platform_gbm
Name Strings
EGL_KHR_platform_gbm
Contributors
Chad Versace <chad.versace@intel.com>
Jon Leech (oddhack 'at' sonic.net)
Kristian Høgsberg <krh@bitplanet.org>
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, 2016/01/04
Number
EGL Extension #69
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 GBM
resources using the EGL 1.5 platform functionality (GBM is a Generic
Buffer Manager for Linux).
New Types
None
New Procedures and Functions
None
New Tokens
Accepted as the <platform> argument of eglGetPlatformDisplay:
EGL_PLATFORM_GBM_KHR 0x31D7
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.
To obtain an EGLDisplay from an GBM device, call eglGetPlatformDisplay with
<platform> set to EGL_PLATFORM_GBM_KHR. The <native_display> parameter
specifies the GBM device to use and must either point to a `struct
gbm_device` or be EGL_DEFAULT_DISPLAY. If <native_display> is
EGL_DEFAULT_DISPLAY, then the resultant EGLDisplay will be backed by some
implementation-chosen GBM device.
For each EGLConfig that belongs to the GBM platform, the
EGL_NATIVE_VISUAL_ID attribute is a GBM color format, such as
GBM_FORMAT_XRGB8888.
To obtain a rendering surface from a GBM surface, call
eglCreatePlatformWindowSurface with a <dpy> that belongs to the GBM
platform and a <native_window> that points to a `struct gbm_surface`. If
<native_window> was created without the GBM_BO_USE_RENDERING flag, or if
the color format of <native_window> differs from the EGL_NATIVE_VISUAL_ID
of <config>, then the function fails and generates EGL_BAD_MATCH.
It is not valid to call eglCreatePlatformPixmapSurface with a <dpy> that
belongs to the GBM platform. Any such call fails and generates
an EGL_BAD_PARAMETER error.
Issues
1. Should this extension permit EGL_DEFAULT_DISPLAY as input to
eglGetPlatformDisplay?
RESOLUTION: Yes. When given EGL_DEFAULT_DISPLAY, eglGetPlatformDisplay
returns an EGLDisplay backed by an implementation-chosen GBM device.
Example Code
// This example program creates an EGL surface from a GBM surface.
//
// If the macro EGL_KHR_platform_gbm 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 -lgbm -lEGL`.
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <EGL/egl.h>
#include <gbm.h>
struct my_display {
struct gbm_device *gbm;
EGLDisplay egl;
};
struct my_config {
struct my_display dpy;
EGLConfig egl;
};
struct my_window {
struct my_config config;
struct gbm_surface *gbm;
EGLSurface egl;
};
static void
check_extensions(void)
{
#ifdef EGL_KHR_platform_gbm
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_gbm")) {
abort();
}
#endif
}
static struct my_display
get_display(void)
{
struct my_display dpy;
int fd = open("/dev/dri/card0", O_RDWR | FD_CLOEXEC);
if (fd < 0) {
abort();
}
dpy.gbm = gbm_create_device(fd);
if (!dpy.gbm) {
abort();
}
#ifdef EGL_KHR_platform_gbm
dpy.egl = eglGetPlatformDisplay(EGL_PLATFORM_GBM_KHR, dpy.gbm, NULL);
#else
dpy.egl = eglGetDisplay(dpy.gbm);
#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_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_NONE,
};
EGLint num_configs;
if (!eglGetConfigs(dpy.egl, NULL, 0, &num_configs)) {
abort();
}
EGLConfig *configs = malloc(num_configs * sizeof(EGLConfig));
if (!eglChooseConfig(dpy.egl, egl_config_attribs,
configs, num_configs, &num_configs)) {
abort();
}
if (num_configs == 0) {
abort();
}
// Find a config whose native visual ID is the desired GBM format.
for (int i = 0; i < num_configs; ++i) {
EGLint gbm_format;
if (!eglGetConfigAttrib(dpy.egl, configs[i],
EGL_NATIVE_VISUAL_ID, &gbm_format)) {
abort();
}
if (gbm_format == GBM_FORMAT_XRGB8888) {
config.egl = configs[i];
free(configs);
return config;
}
}
// Failed to find a config with matching GBM format.
abort();
}
static struct my_window
get_window(struct my_config config)
{
struct my_window window = {
.config = config,
};
window.gbm = gbm_surface_create(config.dpy.gbm,
256, 256,
GBM_FORMAT_XRGB8888,
GBM_BO_USE_RENDERING);
if (!window.gbm) {
abort();
}
#ifdef EGL_KHR_platform_gbm
window.egl = eglCreatePlatformWindowSurface(config.dpy.egl,
config.egl,
window.gbm,
NULL);
#else
window.egl = eglCreateWindowSurface(config.dpy.egl,
config.egl,
window.gbm,
NULL);
#endif
if (window.egl == EGL_NO_SURFACE) {
abort();
}
return window;
}
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);
return 0;
}
Revision History
Version 3, 2016-01-04 (Jon Leech)
- Free config memory allocated in sample code (Public Bug 1445).
Version 2, 2014/02/12 (Chad Versace)
- Change resolution of issue #1 from "no" to "yes". Now
eglGetPlatformDisplay accepts EGL_DEFAULT_DISPLAY for GBM.
Version 1, 2014/01/22 (Jon Leech)
- Promote EGL_MESA_platform_gbm to KHR to go with EGL 1.5.