On Tue, Mar 27, 2018 at 7:45 PM, Daniel Stone <dan...@fooishbar.org> wrote:
> Hi Ilia,
>
> On 14 March 2018 at 19:02, Ilia Mirkin <imir...@alum.mit.edu> wrote:
>> On Tue, Mar 13, 2018 at 5:30 AM, Daniel Stone <dan...@fooishbar.org> wrote:
>>> On 12 March 2018 at 20:45, Mario Kleiner <mario.kleiner...@gmail.com> wrote:
>>>> This way the wayland server can signal support for these formats
>>>> to wayland EGL clients. This is currently used by nouveau for 10
>>>> bpc support.
>>>>
>>>> Tested with glmark2-wayland and glmark2-es2-wayland under weston
>>>> to now expose 10 bpc EGL configs under nouveau.
>>>
>>> Do we need a way to ensure that the backend driver does actually
>>> support BGR for texturing? AFAIK, if a client happens to select a BGR
>>> config on other drivers now - using a compositor which does not
>>> implement wl_drm - this will break for them.
>>
>> I think in practice, every hw driver can support both for texturing if
>> it can support one, since swizzles are always possible (due to
>> ARB_texture_swizzle).
>>
>> In practice at least nouveau prior to Mario's patches only supported
>> it one way. I just checked r600, radeonsi, i965 and freedreno, and
>> they appear to support both for texturing. I think that covers the
>> majority of the likely 10bpc users.
>
> Fair enough. My only remaining issue - and there's nothing the patch
> can really do about it - is a bit of a crapshoot. wayland-drm has no
> hint that the underlying KMS device prefers ABGR to ARGB, and clients
> have no way of determining the channel order even if they did want to
> hardcode it for a specific usecase. So nothing in here really
> guarantees that we'll get scanout. But, that being said, this seems
> harmless enough, so this patch is:
> Reviewed-by: Daniel Stone <dani...@collabora.com>
>
> Cheers,
> Daniel

Agreed. It doesn't seem to hurt, but isn't guaranteed to work in all
cases, at least not for prime renderoffload.

While it did work on single-gpu combos, and when testing prime
renderoffload from amd to nouveau, and from nouveau to amd, and intel
to amd, it didn't work on the prime combo intel as wayland server gpu,
nouveau as renderoffload client gpu, although in principle intel hw
does support sampling that format, according to the format table in
the i965 driver. The driver doesn't expose it though. So the common
"Optimus" Intel igpu + NVidia dgpu case doesn't work atm.

Until last wednesday i've worked on some patch that may get around
that, then i got sidetracked by new dri3.2 problems and other things.
Testing on the half-finished patch doesn't look too bad, but i'm not
yet sure if it will work out or run into other obstacles

The idea is that in the wayland server part, we can figure out which
gpu driver is associated with the dri2_dpy, and from there get to the
dri_configs exposed by the driver for rendering, assuming that if a
driver can render to a format, it will also be able to sample from it
for compositing - and ideally scan out from it if it's our lucky day.

On the wayland-client side, the code that generates eglconfigs from
supported visuals and driver dri_configs does this:

1. Build the list of eglconfigs like now in the wayland client egl code.

2. Check if there are dri_config formats supported by the client
driver that didn't get assigned in step 1 because the wayland server
doesn't support them for import. If so, check if there is a fallback
format supported by the server, e.g., for abgr2101010 the fallback
would be argb2101010. If that's the case, add the format to the list
of eglconfigs, as if it would be natively supported.

3. In the get_back_bo path, detect if we deal with the fallback case
from 2. If so, assign the fallback format for creation of the
linear_copy buffer. This way the actual back buffer used for rendering
has the format supported by the client driver, e.g., abgr2101010 for
nouveau, but the linear_copy buffer has the format of the server
driver, e.g., argb2101010 for intel. The blitImage detiling blit used
for prime renderoffload will then not only convert the tiled
renderbuffer into a linear buffer for import by the server, but also
perform a pixelformat conversion to what the server gpu supports.

This does at least work for "Optimus" with Intel gpu assigned to
weston, exporting argb2101010 as supported format, and nouveau
assigned to the wayland client, which then renders abgr2101010 but
converts to argb2101010 during the blitImage detiling blit. The nice
thing here is that for fullscreen wl_surfaces/buffers it allows the
wayland server to directly pageflip the wl_buffer to the scanout, as
it is in the optimal format for the server gpu.

Attached the current diffs for reference. The client bit needs
cleanup, the server bit is only just enough so i could check with the
debugger attached if i can get to the needed info at all. Also in the
client, using dmabuf for import it totally untested, only the wl-drm
method.

-mario
diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c
index 7a32491974..32a8e53979 100644
--- a/src/egl/drivers/dri2/platform_wayland.c
+++ b/src/egl/drivers/dri2/platform_wayland.c
@@ -56,7 +56,7 @@
 #ifndef DRM_FORMAT_MOD_LINEAR
 #define DRM_FORMAT_MOD_LINEAR 0
 #endif
-
+#include <stdio.h>
 /*
  * The index of entries in this table is used as a bitmask in
  * dri2_dpy->formats, which tracks the formats supported by our server.
@@ -66,49 +66,50 @@ static const struct dri2_wl_visual {
    uint32_t wl_drm_format;
    uint32_t wl_shm_format;
    int dri_image_format;
+   int alt_dri_image_format;
    int bpp;
    unsigned int rgba_masks[4];
 } dri2_wl_visuals[] = {
    {
      "XRGB2101010",
      WL_DRM_FORMAT_XRGB2101010, WL_SHM_FORMAT_XRGB2101010,
-     __DRI_IMAGE_FORMAT_XRGB2101010, 32,
+     __DRI_IMAGE_FORMAT_XRGB2101010, __DRI_IMAGE_FORMAT_XBGR2101010, 32,
      { 0x3ff00000, 0x000ffc00, 0x000003ff, 0x00000000 }
    },
    {
      "ARGB2101010",
      WL_DRM_FORMAT_ARGB2101010, WL_SHM_FORMAT_ARGB2101010,
-     __DRI_IMAGE_FORMAT_ARGB2101010, 32,
+     __DRI_IMAGE_FORMAT_ARGB2101010, __DRI_IMAGE_FORMAT_ABGR2101010, 32,
      { 0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000 }
    },
    {
      "XBGR2101010",
      WL_DRM_FORMAT_XBGR2101010, WL_SHM_FORMAT_XBGR2101010,
-     __DRI_IMAGE_FORMAT_XBGR2101010, 32,
+     __DRI_IMAGE_FORMAT_XBGR2101010, __DRI_IMAGE_FORMAT_XRGB2101010, 32,
      { 0x000003ff, 0x000ffc00, 0x3ff00000, 0x00000000 }
    },
    {
      "ABGR2101010",
      WL_DRM_FORMAT_ABGR2101010, WL_SHM_FORMAT_ABGR2101010,
-     __DRI_IMAGE_FORMAT_ABGR2101010, 32,
+     __DRI_IMAGE_FORMAT_ABGR2101010, __DRI_IMAGE_FORMAT_ARGB2101010, 32,
      { 0x000003ff, 0x000ffc00, 0x3ff00000, 0xc0000000 }
    },
    {
      "XRGB8888",
      WL_DRM_FORMAT_XRGB8888, WL_SHM_FORMAT_XRGB8888,
-     __DRI_IMAGE_FORMAT_XRGB8888, 32,
+     __DRI_IMAGE_FORMAT_XRGB8888, __DRI_IMAGE_FORMAT_NONE, 32,
      { 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 }
    },
    {
      "ARGB8888",
      WL_DRM_FORMAT_ARGB8888, WL_SHM_FORMAT_ARGB8888,
-     __DRI_IMAGE_FORMAT_ARGB8888, 32,
+     __DRI_IMAGE_FORMAT_ARGB8888, __DRI_IMAGE_FORMAT_NONE, 32,
      { 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }
    },
    {
      "RGB565",
      WL_DRM_FORMAT_RGB565, WL_SHM_FORMAT_RGB565,
-     __DRI_IMAGE_FORMAT_RGB565, 16,
+     __DRI_IMAGE_FORMAT_RGB565, __DRI_IMAGE_FORMAT_NONE, 16,
      { 0xf800, 0x07e0, 0x001f, 0x0000 }
    },
 };
@@ -442,15 +443,32 @@ get_back_bo(struct dri2_egl_surface *dri2_surf)
    int use_flags;
    int visual_idx;
    unsigned int dri_image_format;
+   unsigned int linear_dri_image_format;
    uint64_t *modifiers;
    int num_modifiers;
 
    visual_idx = dri2_wl_visual_idx_from_fourcc(dri2_surf->format);
    assert(visual_idx != -1);
    dri_image_format = dri2_wl_visuals[visual_idx].dri_image_format;
+   linear_dri_image_format = dri_image_format;
    modifiers = u_vector_tail(&dri2_dpy->wl_modifiers[visual_idx]);
    num_modifiers = u_vector_length(&dri2_dpy->wl_modifiers[visual_idx]);
 
+   /* Substitute dri image format if server does not support original format */
+   if (!(dri2_dpy->formats & (1 << visual_idx)))
+      linear_dri_image_format = dri2_wl_visuals[visual_idx].alt_dri_image_format;
+
+   assert(linear_dri_image_format != __DRI_IMAGE_FORMAT_NONE);
+
+#if 0
+   if (linear_dri_image_format != dri_image_format) {
+      int j = dri2_wl_visual_idx_from_dri_image_format(linear_dri_image_format);
+      if (j == -1 || !(dri2_dpy->formats & (1 << j)))
+         printf("BAD remap of %s!!!\n", dri2_wl_visuals[visual_idx].format_name);
+      else
+         printf("GOOD remap of %s --> %s!\n", dri2_wl_visuals[visual_idx].format_name, dri2_wl_visuals[j].format_name);
+   }
+#endif
    /* There might be a buffer release already queued that wasn't processed */
    wl_display_dispatch_queue_pending(dri2_dpy->wl_dpy, dri2_surf->wl_queue);
 
@@ -486,7 +504,8 @@ get_back_bo(struct dri2_egl_surface *dri2_surf)
    use_flags = __DRI_IMAGE_USE_SHARE | __DRI_IMAGE_USE_BACKBUFFER;
 
    if (dri2_dpy->is_different_gpu &&
-       dri2_surf->back->linear_copy == NULL) {
+   /*if ((dri2_dpy->is_different_gpu || linear_dri_image_format != dri_image_format) &&*/
+         dri2_surf->back->linear_copy == NULL) {
       /* The LINEAR modifier should be a perfect alias of the LINEAR use
        * flag; try the new interface first before the old, then fall back. */
       if (dri2_dpy->image->base.version >= 15 &&
@@ -497,7 +516,7 @@ get_back_bo(struct dri2_egl_surface *dri2_surf)
             dri2_dpy->image->createImageWithModifiers(dri2_dpy->dri_screen,
                                                       dri2_surf->base.Width,
                                                       dri2_surf->base.Height,
-                                                      dri_image_format,
+                                                      linear_dri_image_format,
                                                       &linear_mod,
                                                       1,
                                                       NULL);
@@ -506,7 +525,7 @@ get_back_bo(struct dri2_egl_surface *dri2_surf)
             dri2_dpy->image->createImage(dri2_dpy->dri_screen,
                                          dri2_surf->base.Width,
                                          dri2_surf->base.Height,
-                                         dri_image_format,
+                                         linear_dri_image_format,
                                          use_flags |
                                          __DRI_IMAGE_USE_LINEAR,
                                          NULL);
@@ -1168,7 +1187,7 @@ dmabuf_handle_modifier(void *data, struct zwp_linux_dmabuf_v1 *dmabuf,
    struct dri2_egl_display *dri2_dpy = data;
    int visual_idx = dri2_wl_visual_idx_from_fourcc(format);
    uint64_t *mod;
-
+return;
    if (visual_idx == -1)
       return;
 
@@ -1270,20 +1289,56 @@ dri2_wl_add_configs_for_visuals(_EGLDriver *drv, _EGLDisplay *disp)
    struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
    unsigned int format_count[ARRAY_SIZE(dri2_wl_visuals)] = { 0 };
    unsigned int count = 0;
+   bool assigned;
 
    for (unsigned i = 0; dri2_dpy->driver_configs[i]; i++) {
+      assigned = false;
+/*      printf("%i: Processing config %s\n", i, dri2_wl_visuals[dri2_wl_visual_idx_from_config(dri2_dpy, dri2_dpy->driver_configs[i])].format_name);*/
       for (unsigned j = 0; j < ARRAY_SIZE(dri2_wl_visuals); j++) {
          struct dri2_egl_config *dri2_conf;
 
          if (!(dri2_dpy->formats & (1 << j)))
             continue;
-
+/*         printf("%i,%i: Tryadding config %s\n", i, j, dri2_wl_visuals[dri2_wl_visual_idx_from_config(dri2_dpy, dri2_dpy->driver_configs[i])].format_name);*/
          dri2_conf = dri2_add_config(disp, dri2_dpy->driver_configs[i],
                count + 1, EGL_WINDOW_BIT, NULL, dri2_wl_visuals[j].rgba_masks);
          if (dri2_conf) {
             if (dri2_conf->base.ConfigID == count + 1)
                count++;
             format_count[j]++;
+            assigned = true;
+/*            printf("%i,%i: Added config %s\n", i, j, dri2_wl_visuals[dri2_wl_visual_idx_from_config(dri2_dpy, dri2_dpy->driver_configs[i])].format_name);*/
+         }
+      }
+
+      if (!assigned /*&& dri2_dpy->is_different_gpu */) {
+         struct dri2_egl_config *dri2_conf;
+         int alt_dri_image_format, j, k;
+
+         /* No match for config. Try if we can blitImage convert to a visual */
+         j = dri2_wl_visual_idx_from_config(dri2_dpy,
+                                            dri2_dpy->driver_configs[i]);
+
+         if (j == -1)
+            continue;
+/*         printf("Try mapping server unsupported %s\n", dri2_wl_visuals[j].format_name);*/
+         /* Find optimal target visual for blitImage conversion, if any. */
+         alt_dri_image_format = dri2_wl_visuals[j].alt_dri_image_format;
+         k = dri2_wl_visual_idx_from_dri_image_format(alt_dri_image_format);
+
+         if (k == -1 || !(dri2_dpy->formats & (1 << k)))
+            continue;
+         printf("Try replacement server supported %s\n", dri2_wl_visuals[k].format_name);
+
+         /* See if this one would work */
+         dri2_conf = dri2_add_config(disp, dri2_dpy->driver_configs[i],
+                                     count + 1, EGL_WINDOW_BIT, NULL,
+                                     dri2_wl_visuals[j].rgba_masks);
+         if (dri2_conf) {
+            if (dri2_conf->base.ConfigID == count + 1)
+               count++;
+            format_count[k]++;
+            printf("Mapped to format %s via blitImage conversion.\n", dri2_wl_visuals[k].format_name);
          }
       }
    }
diff --git a/src/egl/wayland/wayland-drm/wayland-drm.c b/src/egl/wayland/wayland-drm/wayland-drm.c
index fc91e13f79..d2f22f1fd5 100644
--- a/src/egl/wayland/wayland-drm/wayland-drm.c
+++ b/src/egl/wayland/wayland-drm/wayland-drm.c
@@ -214,14 +214,17 @@ 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);
+/*
 	wl_resource_post_event(resource, WL_DRM_FORMAT,
 			       WL_DRM_FORMAT_ABGR2101010);
 	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,
commit 1774e1497f879d84896656cfbae6fa4b528f07b8
Author: Mario Kleiner <mario.kleiner...@gmail.com>
Date:   Fri Mar 16 00:47:30 2018 +0100

    egl/wayland-drm: Wip for format suppported checks.
    
    Not for upstream yet!

diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
index 864f7eb0c6..c3a7aa8184 100644
--- a/src/egl/drivers/dri2/egl_dri2.c
+++ b/src/egl/drivers/dri2/egl_dri2.c
@@ -2757,6 +2757,16 @@ dri2_wl_release_buffer(void *user_data, struct wl_drm_buffer *buffer)
    dri2_dpy->image->destroyImage(buffer->driver_buffer);
 }
 
+static 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);
+   const __DRIconfig **driver_configs = dri2_dpy->driver_configs;
+
+   return false;
+}
+
 static EGLBoolean
 dri2_bind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp,
                              struct wl_display *wl_dpy)
@@ -2765,7 +2775,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;
diff --git a/src/egl/wayland/wayland-drm/wayland-drm.c b/src/egl/wayland/wayland-drm/wayland-drm.c
index 7d44d3821c..fc91e13f79 100644
--- a/src/egl/wayland/wayland-drm/wayland-drm.c
+++ b/src/egl/wayland/wayland-drm/wayland-drm.c
@@ -209,6 +209,8 @@ bind_drm(struct wl_client *client, void *data, uint32_t version, uint32_t id)
 		return;
 	}
 
+	drm->callbacks.is_format_supported(drm->user_data, WL_DRM_FORMAT_ARGB2101010);
+
 	wl_resource_set_implementation(resource, &drm_interface, data, NULL);
 
 	wl_resource_post_event(resource, WL_DRM_DEVICE, drm->device_name);
diff --git a/src/egl/wayland/wayland-drm/wayland-drm.h b/src/egl/wayland/wayland-drm/wayland-drm.h
index 36e5bf042a..9d9dec32aa 100644
--- a/src/egl/wayland/wayland-drm/wayland-drm.h
+++ b/src/egl/wayland/wayland-drm/wayland-drm.h
@@ -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);
 };
 
 
_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to