egl/wayland-drm: Only announce formats via wl_drm which the driver supports.
authorMario Kleiner <mario.kleiner.de@gmail.com>
Wed, 13 Jun 2018 04:04:15 +0000 (06:04 +0200)
committerAdam Jackson <ajax@nwnk.net>
Tue, 29 Jan 2019 20:03:20 +0000 (20:03 +0000)
Check if a pixel format is supported by the Wayland servers gpu driver
before exposing it to the client via wl_drm, so we avoid reporting formats
to the client which the server gpu can't handle.

Restrict this reporting to the new color depth 30 formats for now, as the
ARGB/XRGB8888 and RGB565 formats are probably supported by every gpu under
the sun.

Atm. this is mostly useful to allow proper PRIME renderoffload for depth
30 formats on the typical Intel iGPU + NVidia dGPU "NVidia Optimus" laptop
combo.

Tested on Intel, AMD, NVidia with single-gpu setup and on a Intel + NVidia
Optimus setup.

Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.com>
Reviewed-by: Adam Jackson <ajax@redhat.com>
Reviewed-by: Daniel Stone <daniels@collabora.com>
src/egl/drivers/dri2/egl_dri2.c
src/egl/drivers/dri2/egl_dri2.h
src/egl/drivers/dri2/platform_wayland.c
src/egl/wayland/wayland-drm/wayland-drm.c
src/egl/wayland/wayland-drm/wayland-drm.h

index 892e32dd4e35e87927d9b3e504e7556e3e6de144..c98b9a5d18af532f05a13c544c29dfece0803517 100644 (file)
@@ -2797,7 +2797,8 @@ dri2_bind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp,
    const struct wayland_drm_callbacks wl_drm_callbacks = {
       .authenticate = (int(*)(void *, uint32_t)) dri2_dpy->vtbl->authenticate,
       .reference_buffer = dri2_wl_reference_buffer,
-      .release_buffer = dri2_wl_release_buffer
+      .release_buffer = dri2_wl_release_buffer,
+      .is_format_supported = dri2_wl_is_format_supported
    };
    int flags = 0;
    uint64_t cap;
index 726ba16ae61980d56c5a259c1a870c2087154f58..a9ddadf11b18cebc3164d1c70365a0d8aeb00fba 100644 (file)
@@ -458,6 +458,8 @@ EGLBoolean
 dri2_initialize_wayland(_EGLDriver *drv, _EGLDisplay *disp);
 void
 dri2_teardown_wayland(struct dri2_egl_display *dri2_dpy);
+bool
+dri2_wl_is_format_supported(void* user_data, uint32_t format);
 #else
 static inline EGLBoolean
 dri2_initialize_wayland(_EGLDriver *drv, _EGLDisplay *disp)
index 872e265f5097ae1445fe3b3cc433c9de0374db29..c3ca1b6f7bc12716619874db6aed0984cabf75b5 100644 (file)
@@ -174,6 +174,24 @@ dri2_wl_visual_idx_from_shm_format(uint32_t shm_format)
    return -1;
 }
 
+bool
+dri2_wl_is_format_supported(void* user_data, uint32_t format)
+{
+   _EGLDisplay *disp = (_EGLDisplay *) user_data;
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+   int j = dri2_wl_visual_idx_from_fourcc(format);
+
+   if (j == -1)
+      return false;
+
+   for (int i = 0; dri2_dpy->driver_configs[i]; i++)
+      if (j == dri2_wl_visual_idx_from_config(dri2_dpy,
+                                              dri2_dpy->driver_configs[i]))
+         return true;
+
+   return false;
+}
+
 static int
 roundtrip(struct dri2_egl_display *dri2_dpy)
 {
index 3c6696dbffb21a989597fc5b155358b4f97e0333..51cdd2cb845bcebc490e27297ab961c68c750a1b 100644 (file)
@@ -111,6 +111,8 @@ drm_create_buffer(struct wl_client *client, struct wl_resource *resource,
                  uint32_t stride, uint32_t format)
 {
         switch (format) {
+        case WL_DRM_FORMAT_ABGR2101010:
+        case WL_DRM_FORMAT_XBGR2101010:
         case WL_DRM_FORMAT_ARGB2101010:
         case WL_DRM_FORMAT_XRGB2101010:
         case WL_DRM_FORMAT_ARGB8888:
@@ -210,10 +212,31 @@ bind_drm(struct wl_client *client, void *data, uint32_t version, uint32_t id)
        wl_resource_set_implementation(resource, &drm_interface, data, NULL);
 
        wl_resource_post_event(resource, WL_DRM_DEVICE, drm->device_name);
-       wl_resource_post_event(resource, WL_DRM_FORMAT,
-                              WL_DRM_FORMAT_ARGB2101010);
-       wl_resource_post_event(resource, WL_DRM_FORMAT,
-                              WL_DRM_FORMAT_XRGB2101010);
+
+       if (drm->callbacks.is_format_supported(drm->user_data,
+                                              WL_DRM_FORMAT_ARGB2101010)) {
+               wl_resource_post_event(resource, WL_DRM_FORMAT,
+                                      WL_DRM_FORMAT_ARGB2101010);
+       }
+
+       if (drm->callbacks.is_format_supported(drm->user_data,
+                                              WL_DRM_FORMAT_XRGB2101010)) {
+               wl_resource_post_event(resource, WL_DRM_FORMAT,
+                                      WL_DRM_FORMAT_XRGB2101010);
+       }
+
+       if (drm->callbacks.is_format_supported(drm->user_data,
+                                              WL_DRM_FORMAT_ABGR2101010)) {
+               wl_resource_post_event(resource, WL_DRM_FORMAT,
+                                      WL_DRM_FORMAT_ABGR2101010);
+       }
+
+       if (drm->callbacks.is_format_supported(drm->user_data,
+                                              WL_DRM_FORMAT_XBGR2101010)) {
+               wl_resource_post_event(resource, WL_DRM_FORMAT,
+                                      WL_DRM_FORMAT_XBGR2101010);
+       }
+
        wl_resource_post_event(resource, WL_DRM_FORMAT,
                               WL_DRM_FORMAT_ARGB8888);
        wl_resource_post_event(resource, WL_DRM_FORMAT,
index 36e5bf042a7a9178f8146ef4ade9cf976610a16c..8b7fd3b0b64092fe3aec05c9cfeb5302ce70e6ca 100644 (file)
@@ -14,6 +14,8 @@ struct wayland_drm_callbacks {
                                  struct wl_drm_buffer *buffer);
 
        void (*release_buffer)(void *user_data, struct wl_drm_buffer *buffer);
+
+       bool (*is_format_supported)(void *user_data, uint32_t format);
 };