[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