[waffle] [PATCH v4 4/4] gbm: initial functional gbm support
Jordan Justen
jordan.l.justen at intel.com
Mon Oct 1 10:14:34 PDT 2012
src/waffle/gbm is based on src/waffle/wayland, and then heavily
modified.
Tested as functional with: examples/gl_basic gbm gl|gles2
Signed-off-by: Ben Widawsky <ben at bwidawsk.net>
Signed-off-by: Jordan Justen <jordan.l.justen at intel.com>
---
src/waffle/gbm/gbm_config.c | 77 +++++++++++++++++++++++++++-
src/waffle/gbm/gbm_context.c | 55 +++++++++++++++++++-
src/waffle/gbm/gbm_display.c | 112 +++++++++++++++++++++++++++++++++++++++--
src/waffle/gbm/gbm_platform.c | 50 ++++++++++++++++--
src/waffle/gbm/gbm_window.c | 71 ++++++++++++++++++++++++--
5 files changed, 349 insertions(+), 16 deletions(-)
diff --git a/src/waffle/gbm/gbm_config.c b/src/waffle/gbm/gbm_config.c
index 4270b8a..ed6d6fc 100644
--- a/src/waffle/gbm/gbm_config.c
+++ b/src/waffle/gbm/gbm_config.c
@@ -45,7 +45,36 @@ static const struct wcore_config_vtbl gbm_config_wcore_vtbl;
static bool
gbm_config_destroy(struct wcore_config *wc_self)
{
- return false;
+ struct gbm_config *self = gbm_config(wc_self);
+ bool ok = true;
+
+ if (!self)
+ return ok;
+
+ ok &= wcore_config_teardown(wc_self);
+ free(self);
+ return ok;
+}
+
+static uint32_t
+get_gbm_format(const struct wcore_config_attrs *attrs)
+{
+ if (attrs->depth_size > 0 || attrs->stencil_size > 0) {
+ return 0;
+ }
+
+ if (attrs->red_size > 8 || attrs->blue_size > 8 ||
+ attrs->green_size > 8 || attrs->alpha_size > 8) {
+ return 0;
+ }
+
+ if (attrs->alpha_size > 0) {
+ return GBM_FORMAT_ABGR8888;
+ } else {
+ return GBM_FORMAT_XRGB8888;
+ }
+
+ return 0;
}
struct wcore_config*
@@ -53,13 +82,57 @@ gbm_config_choose(struct wcore_platform *wc_plat,
struct wcore_display *wc_dpy,
const struct wcore_config_attrs *attrs)
{
+ struct gbm_config *self;
+ struct gbm_display *dpy = gbm_display(wc_dpy);
+ bool ok = true;
+
+ self = wcore_calloc(sizeof(*self));
+ if (self == NULL)
+ return NULL;
+
+ ok = wcore_config_init(&self->wcore, wc_dpy);
+ if (!ok)
+ goto error;
+
+ self->gbm_format = get_gbm_format(attrs);
+ if (self->gbm_format == 0) {
+ wcore_errorf(WAFFLE_ERROR_UNSUPPORTED_ON_PLATFORM,
+ "gbm_config_choose: unsupported config");
+ goto error;
+ }
+
+ ok = egl_get_render_buffer_attrib(attrs, &self->egl_render_buffer);
+ if (!ok)
+ goto error;
+
+ self->egl = egl_choose_config(wc_plat, dpy->egl, attrs);
+ if (!self->egl)
+ goto error;
+
+ self->waffle_context_api = attrs->context_api;
+ self->wcore.vtbl = &gbm_config_wcore_vtbl;
+ return &self->wcore;
+
+error:
+ gbm_config_destroy(&self->wcore);
return NULL;
}
static union waffle_native_config*
gbm_config_get_native(struct wcore_config *wc_self)
{
- return NULL;
+ struct gbm_config *self = gbm_config(wc_self);
+ struct gbm_display *dpy = gbm_display(wc_self->display);
+ union waffle_native_config *n_config;
+
+ WCORE_CREATE_NATIVE_UNION(n_config, gbm);
+ if (n_config == NULL)
+ return NULL;
+
+ gbm_display_fill_native(dpy, &n_config->gbm->display);
+ n_config->gbm->egl_config = self->egl;
+
+ return n_config;
}
static const struct wcore_config_vtbl gbm_config_wcore_vtbl = {
diff --git a/src/waffle/gbm/gbm_context.c b/src/waffle/gbm/gbm_context.c
index f723a4f..35bbcb1 100644
--- a/src/waffle/gbm/gbm_context.c
+++ b/src/waffle/gbm/gbm_context.c
@@ -40,7 +40,19 @@ static const struct wcore_context_vtbl gbm_context_wcore_vtbl;
static bool
gbm_context_destroy(struct wcore_context *wc_self)
{
- return false;
+ struct gbm_context *self = gbm_context(wc_self);
+ bool ok = true;
+
+ if (!self)
+ return ok;
+
+ if (self->egl)
+ ok &= egl_destroy_context(gbm_display(wc_self->display)->egl,
+ self->egl);
+
+ ok &= wcore_context_teardown(wc_self);
+ free(self);
+ return ok;
}
struct wcore_context*
@@ -48,13 +60,52 @@ gbm_context_create(struct wcore_platform *wc_plat,
struct wcore_config *wc_config,
struct wcore_context *wc_share_ctx)
{
+ struct gbm_context *self;
+ struct gbm_config *config = gbm_config(wc_config);
+ struct gbm_context *share_ctx = gbm_context(wc_share_ctx);
+ struct gbm_display *dpy = gbm_display(wc_config->display);
+ bool ok = true;
+
+ self = wcore_calloc(sizeof(*self));
+ if (self == NULL)
+ return NULL;
+
+ ok = wcore_context_init(&self->wcore, wc_config);
+ if (!ok)
+ goto error;
+
+ self->egl = egl_create_context(dpy->egl,
+ config->egl,
+ share_ctx
+ ? share_ctx->egl
+ : NULL,
+ config->waffle_context_api);
+ if (!self->egl)
+ goto error;
+
+ self->wcore.vtbl = &gbm_context_wcore_vtbl;
+ return &self->wcore;
+
+error:
+ gbm_context_destroy(&self->wcore);
return NULL;
}
static union waffle_native_context*
gbm_context_get_native(struct wcore_context *wc_self)
{
- return NULL;
+ struct gbm_context *self = gbm_context(wc_self);
+ struct gbm_display *dpy = gbm_display(wc_self->display);
+ union waffle_native_context *n_ctx;
+
+ WCORE_CREATE_NATIVE_UNION(n_ctx, gbm);
+ if (n_ctx == NULL)
+ return NULL;
+
+ gbm_display_fill_native(dpy, &n_ctx->gbm->display);
+ n_ctx->gbm->egl_context = self->egl;
+
+ return n_ctx;
}
static const struct wcore_context_vtbl gbm_context_wcore_vtbl = {
diff --git a/src/waffle/gbm/gbm_display.c b/src/waffle/gbm/gbm_display.c
index a38f8a4..a623014 100644
--- a/src/waffle/gbm/gbm_display.c
+++ b/src/waffle/gbm/gbm_display.c
@@ -27,6 +27,7 @@
#define _GNU_SOURCE
#include <stdlib.h>
+#include <unistd.h>
#include <gbm.h>
#include <libudev.h>
@@ -47,13 +48,101 @@ static const struct wcore_display_vtbl gbm_display_wcore_vtbl;
static bool
gbm_display_destroy(struct wcore_display *wc_self)
{
- return false;
+ struct gbm_display *self = gbm_display(wc_self);
+ bool ok = true;
+ int fd;
+
+ if (!self)
+ return ok;
+
+ if (self->egl)
+ ok &= egl_terminate(self->egl);
+
+ if (self->gbm_device) {
+ fd = gbm_device_get_fd(self->gbm_device);
+ gbm_device_destroy(self->gbm_device);
+ close(fd);
+ }
+
+ ok &= wcore_display_teardown(&self->wcore);
+ free(self);
+ return ok;
+}
+
+static int
+gbm_get_fd(void)
+{
+ struct udev *ud;
+ struct udev_enumerate *en;
+ struct udev_list_entry *entry;
+ const char *path, *filename;
+ struct udev_device *device;
+ int fd;
+
+ ud = udev_new();
+ en = udev_enumerate_new(ud);
+ udev_enumerate_add_match_subsystem(en, "drm");
+ udev_enumerate_add_match_sysname(en, "card[0-9]*");
+ udev_enumerate_scan_devices(en);
+
+ udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(en)) {
+ path = udev_list_entry_get_name(entry);
+ device = udev_device_new_from_syspath(ud, path);
+ filename = udev_device_get_devnode(device);
+ fd = open(filename, O_RDWR | O_CLOEXEC);
+ udev_device_unref(device);
+ if (fd >= 0) {
+ return fd;
+ }
+ }
+
+ return -1;
}
struct wcore_display*
gbm_display_connect(struct wcore_platform *wc_plat,
const char *name)
{
+ struct gbm_display *self;
+ bool ok = true;
+ int fd;
+
+ self = wcore_calloc(sizeof(*self));
+ if (self == NULL)
+ return NULL;
+
+ ok = wcore_display_init(&self->wcore, wc_plat);
+ if (!ok)
+ goto error;
+
+ if (name != NULL) {
+ fd = open(name, O_RDWR | O_CLOEXEC);
+ } else {
+ fd = gbm_get_fd();
+ }
+
+ if (fd < 0) {
+ wcore_errorf(WAFFLE_ERROR_UNKNOWN, "open drm file for gbm failed");
+ goto error;
+ }
+
+ self->gbm_device = gbm_create_device(fd);
+ if (!self->gbm_device) {
+ wcore_errorf(WAFFLE_ERROR_UNKNOWN, "gbm_create_device failed");
+ goto error;
+ }
+
+ self->egl = gbm_egl_initialize(self->gbm_device);
+ if (!self->egl) {
+ wcore_errorf(WAFFLE_ERROR_UNKNOWN, "gbm_egl_initialize failed");
+ goto error;
+ }
+
+ self->wcore.vtbl = &gbm_display_wcore_vtbl;
+ return &self->wcore;
+
+error:
+ gbm_display_destroy(&self->wcore);
return NULL;
}
@@ -62,13 +151,30 @@ static bool
gbm_display_supports_context_api(struct wcore_display *wc_self,
int32_t waffle_context_api)
{
- return false;
+ return egl_supports_context_api(wc_self->platform, waffle_context_api);
+}
+
+void
+gbm_display_fill_native(struct gbm_display *self,
+ struct waffle_gbm_display *n_dpy)
+{
+ n_dpy->gbm_device = self->gbm_device;
+ n_dpy->egl_display = self->egl;
}
static union waffle_native_display*
gbm_display_get_native(struct wcore_display *wc_self)
{
- return NULL;
+ struct gbm_display *self = gbm_display(wc_self);
+ union waffle_native_display *n_dpy;
+
+ WCORE_CREATE_NATIVE_UNION(n_dpy, gbm);
+ if (n_dpy == NULL)
+ return NULL;
+
+ gbm_display_fill_native(self, n_dpy->gbm);
+
+ return n_dpy;
}
static const struct wcore_display_vtbl gbm_display_wcore_vtbl = {
diff --git a/src/waffle/gbm/gbm_platform.c b/src/waffle/gbm/gbm_platform.c
index fca6ab5..e4ba774 100644
--- a/src/waffle/gbm/gbm_platform.c
+++ b/src/waffle/gbm/gbm_platform.c
@@ -43,12 +43,47 @@ static const struct wcore_platform_vtbl gbm_platform_wcore_vtbl;
static bool
gbm_platform_destroy(struct wcore_platform *wc_self)
{
- return false;
+ struct gbm_platform *self = gbm_platform(wc_self);
+ bool ok = true;
+
+ if (!self)
+ return true;
+
+ unsetenv("EGL_PLATFORM");
+
+ if (self->linux)
+ ok &= linux_platform_destroy(self->linux);
+
+ ok &= wcore_platform_teardown(wc_self);
+ free(self);
+ return ok;
}
struct wcore_platform*
gbm_platform_create(void)
{
+ struct gbm_platform *self;
+ bool ok = true;
+
+ self = wcore_calloc(sizeof(*self));
+ if (self == NULL)
+ return NULL;
+
+ ok = wcore_platform_init(&self->wcore);
+ if (!ok)
+ goto error;
+
+ self->linux = linux_platform_create();
+ if (!self->linux)
+ goto error;
+
+ setenv("EGL_PLATFORM", "drm", true);
+
+ self->wcore.vtbl = &gbm_platform_wcore_vtbl;
+ return &self->wcore;
+
+error:
+ gbm_platform_destroy(&self->wcore);
return NULL;
}
@@ -58,21 +93,24 @@ gbm_platform_make_current(struct wcore_platform *wc_self,
struct wcore_window *wc_window,
struct wcore_context *wc_ctx)
{
- return false;
+ return egl_make_current(gbm_display(wc_dpy)->egl,
+ wc_window ? gbm_window(wc_window)->egl : NULL,
+ wc_ctx ? gbm_context(wc_ctx)->egl : NULL);
}
static void*
gbm_platform_get_proc_address(struct wcore_platform *wc_self,
const char *name)
{
- return NULL;
+ return eglGetProcAddress(name);
}
static bool
gbm_platform_dl_can_open(struct wcore_platform *wc_self,
int32_t waffle_dl)
{
- return false;
+ return linux_platform_dl_can_open(gbm_platform(wc_self)->linux,
+ waffle_dl);
}
static void*
@@ -80,7 +118,9 @@ gbm_platform_dl_sym(struct wcore_platform *wc_self,
int32_t waffle_dl,
const char *name)
{
- return NULL;
+ return linux_platform_dl_sym(gbm_platform(wc_self)->linux,
+ waffle_dl,
+ name);
}
static const struct wcore_platform_vtbl gbm_platform_wcore_vtbl = {
diff --git a/src/waffle/gbm/gbm_window.c b/src/waffle/gbm/gbm_window.c
index 588588b..c284a71 100644
--- a/src/waffle/gbm/gbm_window.c
+++ b/src/waffle/gbm/gbm_window.c
@@ -43,7 +43,21 @@ static const struct wcore_window_vtbl gbm_window_wcore_vtbl;
static bool
gbm_window_destroy(struct wcore_window *wc_self)
{
- return false;
+ struct gbm_window *self = gbm_window(wc_self);
+ struct gbm_display *dpy;
+ bool ok = true;
+
+ if (!self)
+ return ok;
+
+ dpy = gbm_display(wc_self->display);
+
+ if (self->egl)
+ ok &= egl_destroy_surface(dpy->egl, self->egl);
+
+ ok &= wcore_window_teardown(wc_self);
+ free(self);
+ return ok;
}
struct wcore_window*
@@ -52,6 +66,40 @@ gbm_window_create(struct wcore_platform *wc_plat,
int width,
int height)
{
+ struct gbm_window *self;
+ struct gbm_config *config = gbm_config(wc_config);
+ struct gbm_display *dpy = gbm_display(wc_config->display);
+ bool ok = true;
+
+ self = wcore_calloc(sizeof(*self));
+ if (self == NULL)
+ return NULL;
+
+ ok = wcore_window_init(&self->wcore, wc_config);
+ if (!ok)
+ goto error;
+
+ self->gbm_surface = gbm_surface_create(dpy->gbm_device, width, height,
+ config->gbm_format,
+ GBM_BO_USE_RENDERING);
+ if (!self->gbm_surface) {
+ wcore_errorf(WAFFLE_ERROR_UNKNOWN,
+ "gbm_surface_create failed");
+ goto error;
+ }
+
+ self->egl = gbm_egl_create_window_surface(dpy->egl,
+ config->egl,
+ self->gbm_surface,
+ config->egl_render_buffer);
+ if (!self->egl)
+ goto error;
+
+ self->wcore.vtbl = &gbm_window_wcore_vtbl;
+ return &self->wcore;
+
+error:
+ gbm_window_destroy(&self->wcore);
return NULL;
}
@@ -59,19 +107,34 @@ gbm_window_create(struct wcore_platform *wc_plat,
static bool
gbm_window_show(struct wcore_window *wc_self)
{
- return false;
+ return true;
}
static bool
gbm_window_swap_buffers(struct wcore_window *wc_self)
{
- return false;
+ struct gbm_window *self = gbm_window(wc_self);
+ struct gbm_display *dpy = gbm_display(wc_self->display);
+
+ return egl_swap_buffers(dpy->egl, self->egl);
}
static union waffle_native_window*
gbm_window_get_native(struct wcore_window *wc_self)
{
- return NULL;
+ struct gbm_window *self = gbm_window(wc_self);
+ struct gbm_display *dpy = gbm_display(wc_self->display);
+ union waffle_native_window *n_window;
+
+ WCORE_CREATE_NATIVE_UNION(n_window, gbm);
+ if (n_window == NULL)
+ return NULL;
+
+ gbm_display_fill_native(dpy, &n_window->gbm->display);
+ n_window->gbm->egl_surface = self->egl;
+ n_window->gbm->gbm_surface = self->gbm_surface;
+
+ return n_window;
}
static const struct wcore_window_vtbl gbm_window_wcore_vtbl = {
--
1.7.9.5
More information about the waffle
mailing list