st/egl: correctly return configs under wayland
authorBenjamin Franzke <benjaminfranzke@googlemail.com>
Thu, 8 Sep 2011 06:03:34 +0000 (08:03 +0200)
committerChia-I Wu <olv@lunarg.com>
Thu, 8 Sep 2011 08:05:40 +0000 (16:05 +0800)
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]

src/gallium/state_trackers/egl/wayland/native_drm.c
src/gallium/state_trackers/egl/wayland/native_shm.c
src/gallium/state_trackers/egl/wayland/native_wayland.c
src/gallium/state_trackers/egl/wayland/native_wayland.h

index 05c32f4773423e4f6a9aeecd3db8c1e024c77acd..9f6757b3c61f09cf629110dcc7d896815750fee2 100644 (file)
@@ -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);
index 598df9fe2ced20aa7ccca0290d7efa02c185c489..8a50915a9c6d9977d78df7a504a58db68f49834b 100644 (file)
@@ -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;
index 29c9b46d612eed386da49ebf429008ab7d9b9fc2..7273d0ef9a7a2f3f2a6f03e51ae1808acf487043 100644 (file)
 
 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;
index 5390f2f08c9790a041420fc1c8245ca4232f12b2..0350a958154b163623e161a0d0111662f4d32c28 100644 (file)
 
 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,