diff options
author | Jordan Justen <jordan.l.justen@intel.com> | 2012-08-13 16:29:04 -0700 |
---|---|---|
committer | Jordan Justen <jordan.l.justen@intel.com> | 2012-10-01 10:00:52 -0700 |
commit | 1a10259861b160e8aacf0b864e2cf6f417c886d5 (patch) | |
tree | fb8666b61a62e45687693c56eff43de07101302f | |
parent | 98cec38029d2052dba48c5581de6d52a21caaa82 (diff) |
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.c | 77 | ||||
-rw-r--r-- | src/waffle/gbm/gbm_context.c | 55 | ||||
-rw-r--r-- | src/waffle/gbm/gbm_display.c | 112 | ||||
-rw-r--r-- | src/waffle/gbm/gbm_platform.c | 50 | ||||
-rw-r--r-- | 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 = { |