summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJordan Justen <jordan.l.justen@intel.com>2012-08-13 16:29:04 -0700
committerJordan Justen <jordan.l.justen@intel.com>2012-09-13 09:58:52 -0700
commit385283fd82264ff1c6bbdc2bea7546cef5265261 (patch)
treee04793386872ff9e711831581b181bee639c3afb
parent1a91fcb0a9c29f07625805554dbe151254e62edb (diff)
gbm: initial functional gbm supportgbm-v3
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@bwidawsk.net> Signed-off-by: Jordan Justen <jordan.l.justen@intel.com>
-rw-r--r--src/waffle/gbm/gbm_config.c75
-rw-r--r--src/waffle/gbm/gbm_context.c55
-rw-r--r--src/waffle/gbm/gbm_display.c107
-rw-r--r--src/waffle/gbm/gbm_platform.c51
-rw-r--r--src/waffle/gbm/gbm_window.c71
5 files changed, 343 insertions, 16 deletions
diff --git a/src/waffle/gbm/gbm_config.c b/src/waffle/gbm/gbm_config.c
index 4270b8a..9bb6b87 100644
--- a/src/waffle/gbm/gbm_config.c
+++ b/src/waffle/gbm/gbm_config.c
@@ -45,7 +45,34 @@ 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 != WAFFLE_DONT_CARE ||
+ attrs->stencil_size != WAFFLE_DONT_CARE) {
+ return 0;
+ }
+
+ if (attrs->red_size == 8 && attrs->blue_size == 8 && attrs->green_size == 8) {
+ if (attrs->alpha_size == WAFFLE_DONT_CARE) {
+ return GBM_FORMAT_XRGB8888;
+ } else if (attrs->alpha_size == 8) {
+ return GBM_FORMAT_ABGR8888;
+ }
+ }
+
+ return 0;
}
struct wcore_config*
@@ -53,13 +80,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);
+ struct waffle_gbm_config *n_config;
+
+ n_config = wcore_malloc(sizeof(*n_config));
+ if (n_config == NULL)
+ return NULL;
+
+ gbm_display_fill_native(dpy, &n_config->display);
+ n_config->egl_config = self->egl;
+
+ return (union waffle_native_config*) 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..be8dc93 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);
+ struct waffle_gbm_context *n_ctx;
+
+ n_ctx = wcore_malloc(sizeof(*n_ctx));
+ if (n_ctx == NULL)
+ return NULL;
+
+ gbm_display_fill_native(dpy, &n_ctx->display);
+ n_ctx->egl_context = self->egl;
+
+ return (union waffle_native_context*) 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..896b837 100644
--- a/src/waffle/gbm/gbm_display.c
+++ b/src/waffle/gbm/gbm_display.c
@@ -47,13 +47,97 @@ 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;
+
+ if (!self)
+ return ok;
+
+ if (self->egl)
+ ok &= egl_terminate(self->egl);
+
+ if (self->gbm_device)
+ gbm_device_destroy(self->gbm_device);
+
+ 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 +146,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);
+ struct waffle_gbm_display *n_dpy;
+
+ n_dpy = wcore_malloc(sizeof(*n_dpy));
+ if (n_dpy == NULL)
+ return NULL;
+
+ gbm_display_fill_native(self, n_dpy);
+
+ return (union waffle_native_display*) 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..c8f57e2 100644
--- a/src/waffle/gbm/gbm_platform.c
+++ b/src/waffle/gbm/gbm_platform.c
@@ -43,12 +43,48 @@ 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");
+ unsetenv("EGL_DRIVER");
+
+ 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 +94,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 +119,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..1f3679d 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);
+ struct waffle_gbm_window *n_window;
+
+ n_window = wcore_malloc(sizeof(*n_window));
+ if (n_window == NULL)
+ return NULL;
+
+ gbm_display_fill_native(dpy, &n_window->display);
+ n_window->egl_surface = self->egl;
+ n_window->gbm_surface = self->gbm_surface;
+
+ return (union waffle_native_window*) n_window;
}
static const struct wcore_window_vtbl gbm_window_wcore_vtbl = {