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-09-13 09:58:52 -0700 |
commit | 385283fd82264ff1c6bbdc2bea7546cef5265261 (patch) | |
tree | e04793386872ff9e711831581b181bee639c3afb | |
parent | 1a91fcb0a9c29f07625805554dbe151254e62edb (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.c | 75 | ||||
-rw-r--r-- | src/waffle/gbm/gbm_context.c | 55 | ||||
-rw-r--r-- | src/waffle/gbm/gbm_display.c | 107 | ||||
-rw-r--r-- | src/waffle/gbm/gbm_platform.c | 51 | ||||
-rw-r--r-- | src/waffle/gbm/gbm_window.c | 71 |
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 = { |