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 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel