From 1191d203632e2954ce59163f87c9896b1c6ed40a Mon Sep 17 00:00:00 2001 From: Benjamin Franzke Date: Thu, 8 Sep 2011 08:03:34 +0200 Subject: [PATCH] st/egl: correctly return configs under wayland Handle "format" events and return configs for the supported formats. (Based on Chia-I Wu's patch) [olv: update and explain why PIPE_FORMAT_B8G8R8A8_UNORM should not be enabled without HAS_ARGB32] --- .../state_trackers/egl/wayland/native_drm.c | 25 ++++++++-- .../state_trackers/egl/wayland/native_shm.c | 37 +++++++++++++-- .../egl/wayland/native_wayland.c | 47 +++++++++++++------ .../egl/wayland/native_wayland.h | 12 ++++- 4 files changed, 98 insertions(+), 23 deletions(-) diff --git a/src/gallium/state_trackers/egl/wayland/native_drm.c b/src/gallium/state_trackers/egl/wayland/native_drm.c index 05c32f47734..9f6757b3c61 100644 --- a/src/gallium/state_trackers/egl/wayland/native_drm.c +++ b/src/gallium/state_trackers/egl/wayland/native_drm.c @@ -77,8 +77,8 @@ wayland_drm_display_destroy(struct native_display *ndpy) wl_drm_destroy(drmdpy->wl_drm); if (drmdpy->device_name) FREE(drmdpy->device_name); - if (drmdpy->base.config) - FREE(drmdpy->base.config); + if (drmdpy->base.configs) + FREE(drmdpy->base.configs); if (drmdpy->base.own_dpy) wl_display_destroy(drmdpy->base.dpy); @@ -97,7 +97,7 @@ wayland_create_drm_buffer(struct wayland_display *display, struct pipe_resource *resource; struct winsys_handle wsh; uint width, height; - uint32_t format; + enum wl_drm_format format; resource = resource_surface_get_single_resource(surface->rsurf, attachment); resource_surface_get_size(surface->rsurf, &width, &height); @@ -148,7 +148,19 @@ drm_handle_device(void *data, struct wl_drm *drm, const char *device) static void drm_handle_format(void *data, struct wl_drm *drm, uint32_t format) { - /* TODO */ + struct wayland_drm_display *drmdpy = data; + + switch (format) { + case WL_DRM_FORMAT_ARGB32: + drmdpy->base.formats |= HAS_ARGB32; + break; + case WL_DRM_FORMAT_PREMULTIPLIED_ARGB32: + drmdpy->base.formats |= HAS_PREMUL_ARGB32; + break; + case WL_DRM_FORMAT_XRGB32: + drmdpy->base.formats |= HAS_XRGB32; + break; + } } static void @@ -191,6 +203,11 @@ wayland_drm_display_init_screen(struct native_display *ndpy) if (!drmdpy->authenticated) return FALSE; + if (drmdpy->base.formats == 0) + wl_display_roundtrip(drmdpy->base.dpy); + if (drmdpy->base.formats == 0) + return FALSE; + drmdpy->base.base.screen = drmdpy->event_handler->new_drm_screen(&drmdpy->base.base, NULL, drmdpy->fd); diff --git a/src/gallium/state_trackers/egl/wayland/native_shm.c b/src/gallium/state_trackers/egl/wayland/native_shm.c index 598df9fe2ce..8a50915a9c6 100644 --- a/src/gallium/state_trackers/egl/wayland/native_shm.c +++ b/src/gallium/state_trackers/egl/wayland/native_shm.c @@ -63,8 +63,8 @@ wayland_shm_display_destroy(struct native_display *ndpy) { struct wayland_shm_display *shmdpy = wayland_shm_display(ndpy); - if (shmdpy->base.config) - FREE(shmdpy->base.config); + if (shmdpy->base.configs) + FREE(shmdpy->base.configs); if (shmdpy->base.own_dpy) wl_display_destroy(shmdpy->base.dpy); @@ -73,7 +73,6 @@ wayland_shm_display_destroy(struct native_display *ndpy) FREE(shmdpy); } - static struct wl_buffer * wayland_create_shm_buffer(struct wayland_display *display, struct wayland_surface *surface, @@ -84,7 +83,7 @@ wayland_create_shm_buffer(struct wayland_display *display, struct pipe_resource *resource; struct winsys_handle wsh; uint width, height; - uint32_t format; + enum wl_shm_format format; resource = resource_surface_get_single_resource(surface->rsurf, attachment); resource_surface_get_size(surface->rsurf, &width, &height); @@ -95,6 +94,7 @@ wayland_create_shm_buffer(struct wayland_display *display, switch (surface->color_format) { case PIPE_FORMAT_B8G8R8A8_UNORM: + /* assume premultiplied */ format = WL_SHM_FORMAT_PREMULTIPLIED_ARGB32; break; case PIPE_FORMAT_B8G8R8X8_UNORM: @@ -110,6 +110,28 @@ wayland_create_shm_buffer(struct wayland_display *display, wsh.stride, format); } +static void +shm_handle_format(void *data, struct wl_shm *shm, uint32_t format) +{ + struct wayland_shm_display *shmdpy = data; + + switch (format) { + case WL_SHM_FORMAT_ARGB32: + shmdpy->base.formats |= HAS_ARGB32; + break; + case WL_SHM_FORMAT_PREMULTIPLIED_ARGB32: + shmdpy->base.formats |= HAS_PREMUL_ARGB32; + break; + case WL_SHM_FORMAT_XRGB32: + shmdpy->base.formats |= HAS_XRGB32; + break; + } +} + +static const struct wl_shm_listener shm_listener = { + shm_handle_format +}; + static boolean wayland_shm_display_init_screen(struct native_display *ndpy) { @@ -128,6 +150,13 @@ wayland_shm_display_init_screen(struct native_display *ndpy) if (!shmdpy->wl_shm) return FALSE; + wl_shm_add_listener(shmdpy->wl_shm, &shm_listener, shmdpy); + + if (shmdpy->base.formats == 0) + wl_display_roundtrip(shmdpy->base.dpy); + if (shmdpy->base.formats == 0) + return FALSE; + winsys = wayland_create_sw_winsys(shmdpy->base.dpy); if (!winsys) return FALSE; diff --git a/src/gallium/state_trackers/egl/wayland/native_wayland.c b/src/gallium/state_trackers/egl/wayland/native_wayland.c index 29c9b46d612..7273d0ef9a7 100644 --- a/src/gallium/state_trackers/egl/wayland/native_wayland.c +++ b/src/gallium/state_trackers/egl/wayland/native_wayland.c @@ -37,40 +37,59 @@ static const struct native_event_handler *wayland_event_handler; +const static struct { + enum pipe_format format; + enum wayland_format_flag flag; +} wayland_formats[] = { + /* + * HAS_PREMUL_ARGB32 is ignored here. For the case that HAS_PREMUL_ARGB32 + * is set but HAS_ARGB32 isn't, we should not claim + * PIPE_FORMAT_B8G8R8A8_UNORM support because we will not be able to present + * a surface with non-premultiplied alpha. + */ + { PIPE_FORMAT_B8G8R8A8_UNORM, HAS_ARGB32 }, + { PIPE_FORMAT_B8G8R8X8_UNORM, HAS_XRGB32 }, +}; + static const struct native_config ** -wayland_display_get_configs (struct native_display *ndpy, int *num_configs) +wayland_display_get_configs(struct native_display *ndpy, int *num_configs) { struct wayland_display *display = wayland_display(ndpy); const struct native_config **configs; int i; - if (!display->config) { + if (!display->configs) { struct native_config *nconf; - display->config = CALLOC(2, sizeof(*display->config)); - if (!display->config) + + display->num_configs = 0; + display->configs = CALLOC(Elements(wayland_formats), + sizeof(*display->configs)); + if (!display->configs) return NULL; - for (i = 0; i < 2; ++i) { - nconf = &display->config[i].base; - + for (i = 0; i < Elements(wayland_formats); ++i) { + if (!(display->formats & wayland_formats[i].flag)) + continue; + + nconf = &display->configs[display->num_configs].base; nconf->buffer_mask = (1 << NATIVE_ATTACHMENT_FRONT_LEFT) | (1 << NATIVE_ATTACHMENT_BACK_LEFT); nconf->window_bit = TRUE; nconf->pixmap_bit = TRUE; + + nconf->color_format = wayland_formats[i].format; + display->num_configs++; } - - display->config[0].base.color_format = PIPE_FORMAT_B8G8R8A8_UNORM; - display->config[1].base.color_format = PIPE_FORMAT_B8G8R8X8_UNORM; } - configs = MALLOC(2 * sizeof(*configs)); + configs = MALLOC(display->num_configs * sizeof(*configs)); if (configs) { - configs[0] = &display->config[0].base; - configs[1] = &display->config[1].base; + for (i = 0; i < display->num_configs; ++i) + configs[i] = &display->configs[i].base; if (num_configs) - *num_configs = 2; + *num_configs = display->num_configs; } return configs; diff --git a/src/gallium/state_trackers/egl/wayland/native_wayland.h b/src/gallium/state_trackers/egl/wayland/native_wayland.h index 5390f2f08c9..0350a958154 100644 --- a/src/gallium/state_trackers/egl/wayland/native_wayland.h +++ b/src/gallium/state_trackers/egl/wayland/native_wayland.h @@ -36,12 +36,22 @@ struct wayland_surface; +enum wayland_format_flag { + HAS_ARGB32 = (1 << 0), + HAS_PREMUL_ARGB32 = (1 << 1), + HAS_XRGB32 = (1 << 2) +}; + struct wayland_display { struct native_display base; - struct wayland_config *config; struct wl_display *dpy; boolean own_dpy; + /* supported formats */ + uint32_t formats; + + struct wayland_config *configs; + int num_configs; struct wl_buffer *(*create_buffer)(struct wayland_display *display, struct wayland_surface *surface, -- 2.30.2