[PATCH mesa 1/3] wayland: Keep track of the formats in a sorted array instead of flags

Neil Roberts neil at linux.intel.com
Thu Feb 6 05:58:29 PST 2014


In order to support YUV formats in CreateWaylandBufferFromImageWL we need to
be able to check whether the compositor supports a larger number of formats so
storing them in flags is a bit awkard. Instead all of the formats are now
stored in a sorted array using wl_array. A binary search is used to check for
the format.
---
 src/egl/drivers/dri2/egl_dri2.h         |  2 +-
 src/egl/drivers/dri2/platform_wayland.c | 85 ++++++++++++++++++++++++---------
 2 files changed, 64 insertions(+), 23 deletions(-)

diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
index dfc5927..3f90582 100644
--- a/src/egl/drivers/dri2/egl_dri2.h
+++ b/src/egl/drivers/dri2/egl_dri2.h
@@ -131,7 +131,7 @@ struct dri2_egl_display
    struct wl_drm            *wl_drm;
    struct wl_event_queue    *wl_queue;
    int			     authenticated;
-   int			     formats;
+   struct wl_array           formats;
    uint32_t                  capabilities;
 #endif
 
diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c
index 50750a9..089ed62 100644
--- a/src/egl/drivers/dri2/platform_wayland.c
+++ b/src/egl/drivers/dri2/platform_wayland.c
@@ -41,12 +41,6 @@
 #include <wayland-client.h>
 #include "wayland-drm-client-protocol.h"
 
-enum wl_drm_format_flags {
-   HAS_ARGB8888 = 1,
-   HAS_XRGB8888 = 2,
-   HAS_RGB565 = 4,
-};
-
 static void
 sync_callback(void *data, struct wl_callback *callback, uint32_t serial)
 {
@@ -679,6 +673,31 @@ dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
    return dri2_swap_buffers_with_damage (drv, disp, draw, NULL, 0);
 }
 
+static EGLBoolean
+dri2_can_handle_format(struct dri2_egl_display *dri2_dpy,
+                       enum wl_drm_format format)
+{
+   const enum wl_drm_format *formats;
+   int min, mid, max;
+
+   /* Binary search for the format */
+   min = 0;
+   max = dri2_dpy->formats.size / sizeof (enum wl_drm_format);
+   formats = dri2_dpy->formats.data;
+
+   while (max > min) {
+      mid = (max + min) / 2;
+      if (formats[mid] < format)
+         min = mid + 1;
+      else if (formats[mid] > format)
+         max = mid;
+      else
+         return EGL_TRUE;
+   }
+
+   return EGL_FALSE;
+}
+
 static struct wl_buffer *
 dri2_create_wayland_buffer_from_image_wl(_EGLDriver *drv,
                                          _EGLDisplay *disp,
@@ -695,12 +714,12 @@ dri2_create_wayland_buffer_from_image_wl(_EGLDriver *drv,
 
    switch (format) {
    case __DRI_IMAGE_FORMAT_ARGB8888:
-      if (!(dri2_dpy->formats & HAS_ARGB8888))
+      if (!dri2_can_handle_format(dri2_dpy, WL_DRM_FORMAT_ARGB8888))
          goto bad_format;
       wl_format = WL_DRM_FORMAT_ARGB8888;
       break;
    case __DRI_IMAGE_FORMAT_XRGB8888:
-      if (!(dri2_dpy->formats & HAS_XRGB8888))
+      if (!dri2_can_handle_format(dri2_dpy, WL_DRM_FORMAT_XRGB8888))
          goto bad_format;
       wl_format = WL_DRM_FORMAT_XRGB8888;
       break;
@@ -794,6 +813,7 @@ dri2_terminate(_EGLDriver *drv, _EGLDisplay *disp)
    wl_drm_destroy(dri2_dpy->wl_drm);
    if (dri2_dpy->own_device)
       wl_display_disconnect(dri2_dpy->wl_dpy);
+   wl_array_release(&dri2_dpy->formats);
    free(dri2_dpy);
    disp->DriverData = NULL;
 
@@ -834,18 +854,36 @@ static void
 drm_handle_format(void *data, struct wl_drm *drm, uint32_t format)
 {
    struct dri2_egl_display *dri2_dpy = data;
-
-   switch (format) {
-   case WL_DRM_FORMAT_ARGB8888:
-      dri2_dpy->formats |= HAS_ARGB8888;
-      break;
-   case WL_DRM_FORMAT_XRGB8888:
-      dri2_dpy->formats |= HAS_XRGB8888;
-      break;
-   case WL_DRM_FORMAT_RGB565:
-      dri2_dpy->formats |= HAS_RGB565;
-      break;
+   enum wl_drm_format *formats = dri2_dpy->formats.data;
+   int n_formats;
+   int min, mid, max;
+
+   n_formats = dri2_dpy->formats.size / sizeof (enum wl_drm_format);
+
+   /* Search for the insert position to keep the format array sorted */
+   min = 0;
+   max = n_formats;
+
+   while (max > min) {
+      mid = (max + min) / 2;
+      if (formats[mid] < format)
+         min = mid + 1;
+      else if (formats[mid] > format)
+         max = mid;
+      else
+         return;
    }
+
+   if (wl_array_add(&dri2_dpy->formats, sizeof (enum wl_drm_format)) == NULL)
+      return;
+
+   formats = dri2_dpy->formats.data;
+
+   /* Move the subsequent formats out of the way */
+   memmove(formats + min + 1,
+           formats + min,
+           (n_formats - min) * sizeof *formats);
+   formats[min] = format;
 }
 
 static void
@@ -980,6 +1018,8 @@ dri2_initialize_wayland(_EGLDriver *drv, _EGLDisplay *disp)
    if (!dri2_dpy)
       return _eglError(EGL_BAD_ALLOC, "eglInitialize");
 
+   wl_array_init(&dri2_dpy->formats);
+
    disp->DriverData = (void *) dri2_dpy;
    if (disp->PlatformDisplay == NULL) {
       dri2_dpy->wl_dpy = wl_display_connect(NULL);
@@ -1050,11 +1090,11 @@ dri2_initialize_wayland(_EGLDriver *drv, _EGLDisplay *disp)
    types = EGL_WINDOW_BIT;
    for (i = 0; dri2_dpy->driver_configs[i]; i++) {
       config = dri2_dpy->driver_configs[i];
-      if (dri2_dpy->formats & HAS_XRGB8888)
+      if (dri2_can_handle_format(dri2_dpy, WL_DRM_FORMAT_XRGB8888))
 	 dri2_add_config(disp, config, i + 1, types, NULL, rgb_masks);
-      if (dri2_dpy->formats & HAS_ARGB8888)
+      if (dri2_can_handle_format(dri2_dpy, WL_DRM_FORMAT_ARGB8888))
 	 dri2_add_config(disp, config, i + 1, types, NULL, argb_masks);
-      if (dri2_dpy->formats & HAS_RGB565)
+      if (dri2_can_handle_format(dri2_dpy, WL_DRM_FORMAT_RGB565))
         dri2_add_config(disp, config, i + 1, types, NULL, rgb565_masks);
    }
 
@@ -1081,6 +1121,7 @@ dri2_initialize_wayland(_EGLDriver *drv, _EGLDisplay *disp)
    free(dri2_dpy->device_name);
    wl_drm_destroy(dri2_dpy->wl_drm);
  cleanup_dpy:
+   wl_array_release(&dri2_dpy->formats);
    free(dri2_dpy);
    
    return EGL_FALSE;
-- 
1.8.5.3



More information about the wayland-devel mailing list