<div dir="ltr">Hi Mario<div><br></div><div>Can you explain how I can test this? I'll test it out on an Intel+AMD system</div><div><br></div><div>Cheers</div><div><br></div><div>Mike</div></div><br><div class="gmail_quote"><div dir="ltr">On Wed, 23 May 2018 at 05:51 Mario Kleiner <<a href="mailto:mario.kleiner.de@gmail.com">mario.kleiner.de@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">On Mon, May 21, 2018 at 4:42 PM, Eric Engestrom<br>
<<a href="mailto:eric.engestrom@intel.com" target="_blank">eric.engestrom@intel.com</a>> wrote:<br>
> On Saturday, 2018-05-19 05:32:41 +0200, Mario Kleiner wrote:<br>
>> Support PRIME render offload between a Wayland server gpu and a Wayland<br>
>> client gpu with different channel ordering for their color formats,<br>
>> e.g., between Intel drivers which currently only support ARGB2101010<br>
>> and XRGB2101010 import/display and nouveau which only supports ABGR2101010<br>
>> rendering and display on nv-50 and later.<br>
>><br>
>> In the wl_visuals table, we also store for each format an alternate<br>
>> sibling format which stores colors at the same precision, but with<br>
>> different channel ordering, e.g., ARGB2101010 <-> ABGR2101010.<br>
>><br>
>> If a given client-gpu renderable format is not supported by the server<br>
>> for import, but the alternate format is supported by the server, expose<br>
>> the client-gpu renderable format as a valid EGLConfig to the client. At<br>
>> eglSwapBuffers time, during the blitImage() detiling blit from the client<br>
>> backbuffer to the linear buffer, the client format is converted to the<br>
>> server supported format. As we have to do a copy for PRIME anyway,<br>
>> this channel swizzling conversion comes essentially for free.<br>
>><br>
>> Note that even if a server gpu in principle does support sampling<br>
>> from the clients native format, this conversion will be a performance<br>
>> advantage if it allows to convert to the servers preferred format<br>
>> for direct scanout, as the Wayland compositor may then be able to<br>
>> directly page-flip a fullscreen client wl_buffer onto the primary<br>
>> plane, or onto a hardware overlay plane, avoiding an extra data copy<br>
>> for desktop composition.<br>
>><br>
>> Tested so far under Weston with: nouveau single-gpu, Intel single-gpu,<br>
>> AMD single-gpu, "Optimus" Intel server iGPU for display + NVidia<br>
>> client dGPU for rendering.<br>
>><br>
>> Signed-off-by: Mario Kleiner <<a href="mailto:mario.kleiner.de@gmail.com" target="_blank">mario.kleiner.de@gmail.com</a>><br>
>> Cc: Daniel Stone <<a href="mailto:daniels@collabora.com" target="_blank">daniels@collabora.com</a>><br>
>> ---<br>
>>  src/egl/drivers/dri2/platform_wayland.c | 67 ++++++++++++++++++++++++++++-----<br>
>>  1 file changed, 58 insertions(+), 9 deletions(-)<br>
>><br>
>> diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c<br>
>> index 89a7f90118..fb364a6233 100644<br>
>> --- a/src/egl/drivers/dri2/platform_wayland.c<br>
>> +++ b/src/egl/drivers/dri2/platform_wayland.c<br>
>> @@ -68,49 +68,50 @@ static const struct dri2_wl_visual {<br>
>>     uint32_t wl_drm_format;<br>
>>     uint32_t wl_shm_format;<br>
>>     int dri_image_format;<br>
>> +   int alt_dri_image_format;<br>
><br>
<br>
Thanks for the review.<br>
<br>
> A comment here wouldn't hurt, to explain what this "alt" is to someone<br>
> who sees the code after it landed :)<br>
><br>
<br>
Will do, although i usually feel a bit guilty that my patches usually<br>
suffer from over-commenting and essay length commit messages :)<br>
<br>
>>     int bpp;<br>
>>     unsigned int rgba_masks[4];<br>
>>  } dri2_wl_visuals[] = {<br>
>>     {<br>
>>       "XRGB2101010",<br>
>>       WL_DRM_FORMAT_XRGB2101010, WL_SHM_FORMAT_XRGB2101010,<br>
>> -     __DRI_IMAGE_FORMAT_XRGB2101010, 32,<br>
>> +     __DRI_IMAGE_FORMAT_XRGB2101010, __DRI_IMAGE_FORMAT_XBGR2101010, 32,<br>
>>       { 0x3ff00000, 0x000ffc00, 0x000003ff, 0x00000000 }<br>
>>     },<br>
>>     {<br>
>>       "ARGB2101010",<br>
>>       WL_DRM_FORMAT_ARGB2101010, WL_SHM_FORMAT_ARGB2101010,<br>
>> -     __DRI_IMAGE_FORMAT_ARGB2101010, 32,<br>
>> +     __DRI_IMAGE_FORMAT_ARGB2101010, __DRI_IMAGE_FORMAT_ABGR2101010, 32,<br>
>>       { 0x3ff00000, 0x000ffc00, 0x000003ff, 0xc0000000 }<br>
>>     },<br>
>>     {<br>
>>       "XBGR2101010",<br>
>>       WL_DRM_FORMAT_XBGR2101010, WL_SHM_FORMAT_XBGR2101010,<br>
>> -     __DRI_IMAGE_FORMAT_XBGR2101010, 32,<br>
>> +     __DRI_IMAGE_FORMAT_XBGR2101010, __DRI_IMAGE_FORMAT_XRGB2101010, 32,<br>
>>       { 0x000003ff, 0x000ffc00, 0x3ff00000, 0x00000000 }<br>
>>     },<br>
>>     {<br>
>>       "ABGR2101010",<br>
>>       WL_DRM_FORMAT_ABGR2101010, WL_SHM_FORMAT_ABGR2101010,<br>
>> -     __DRI_IMAGE_FORMAT_ABGR2101010, 32,<br>
>> +     __DRI_IMAGE_FORMAT_ABGR2101010, __DRI_IMAGE_FORMAT_ARGB2101010, 32,<br>
>>       { 0x000003ff, 0x000ffc00, 0x3ff00000, 0xc0000000 }<br>
>>     },<br>
>>     {<br>
>>       "XRGB8888",<br>
>>       WL_DRM_FORMAT_XRGB8888, WL_SHM_FORMAT_XRGB8888,<br>
>> -     __DRI_IMAGE_FORMAT_XRGB8888, 32,<br>
>> +     __DRI_IMAGE_FORMAT_XRGB8888, __DRI_IMAGE_FORMAT_NONE, 32,<br>
>>       { 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 }<br>
>>     },<br>
>>     {<br>
>>       "ARGB8888",<br>
>>       WL_DRM_FORMAT_ARGB8888, WL_SHM_FORMAT_ARGB8888,<br>
>> -     __DRI_IMAGE_FORMAT_ARGB8888, 32,<br>
>> +     __DRI_IMAGE_FORMAT_ARGB8888, __DRI_IMAGE_FORMAT_NONE, 32,<br>
>>       { 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }<br>
>>     },<br>
>>     {<br>
>>       "RGB565",<br>
>>       WL_DRM_FORMAT_RGB565, WL_SHM_FORMAT_RGB565,<br>
>> -     __DRI_IMAGE_FORMAT_RGB565, 16,<br>
>> +     __DRI_IMAGE_FORMAT_RGB565, __DRI_IMAGE_FORMAT_NONE, 16,<br>
>>       { 0xf800, 0x07e0, 0x001f, 0x0000 }<br>
>>     },<br>
>>  };<br>
>> @@ -450,15 +451,23 @@ get_back_bo(struct dri2_egl_surface *dri2_surf)<br>
>>     int use_flags;<br>
>>     int visual_idx;<br>
>>     unsigned int dri_image_format;<br>
>> +   unsigned int linear_dri_image_format;<br>
>>     uint64_t *modifiers;<br>
>>     int num_modifiers;<br>
>><br>
>>     visual_idx = dri2_wl_visual_idx_from_fourcc(dri2_surf->format);<br>
>>     assert(visual_idx != -1);<br>
>>     dri_image_format = dri2_wl_visuals[visual_idx].dri_image_format;<br>
>> +   linear_dri_image_format = dri_image_format;<br>
>>     modifiers = u_vector_tail(&dri2_dpy->wl_modifiers[visual_idx]);<br>
>>     num_modifiers = u_vector_length(&dri2_dpy->wl_modifiers[visual_idx]);<br>
>><br>
>> +   /* Substitute dri image format if server does not support original format */<br>
>> +   if (!(dri2_dpy->formats & (1 << visual_idx)))<br>
>> +      linear_dri_image_format = dri2_wl_visuals[visual_idx].alt_dri_image_format;<br>
><br>
> Could we test that the substitution would actually work better before<br>
> doing it?<br>
><br>
<br>
We test that, but already in dri2_wl_add_configs_for_visuals() below.<br>
The only way to get to the if statement (ie. visual_idx != -1) and<br>
then have it trigger the linear_dri_image_format substitution is if<br>
the new hunk of code in dri2_wl_add_configs_for_visuals() found out<br>
that the substitution is necessary, possible and valid. A EGLconfig<br>
can support the client format with the given visual_idx if either the<br>
wayland-server supports it (so the above if statement will skip the<br>
substitution), or if the server doesn't support it, but does support<br>
sampling/displaying the substituted format, according to the checks<br>
done in dri2_wl_add_configs_for_visuals before adding the EGLconfig to<br>
the list of client configs.<br>
<br>
I could add a test to document this, which would be redundant though.<br>
Or maybe a code comment? Or maybe the test in an assert() to document<br>
that that test should always succeed in the absence of bugs in the<br>
code?<br>
<br>
>> +<br>
>> +   assert(linear_dri_image_format != __DRI_IMAGE_FORMAT_NONE);<br>
>> +<br>
>>     /* There might be a buffer release already queued that wasn't processed */<br>
>>     wl_display_dispatch_queue_pending(dri2_dpy->wl_dpy, dri2_surf->wl_queue);<br>
>><br>
>> @@ -505,7 +514,7 @@ get_back_bo(struct dri2_egl_surface *dri2_surf)<br>
>>              dri2_dpy->image->createImageWithModifiers(dri2_dpy->dri_screen,<br>
>>                                                        dri2_surf->base.Width,<br>
>>                                                        dri2_surf->base.Height,<br>
>> -                                                      dri_image_format,<br>
>> +                                                      linear_dri_image_format,<br>
>>                                                        &linear_mod,<br>
>>                                                        1,<br>
>>                                                        NULL);<br>
>> @@ -514,7 +523,7 @@ get_back_bo(struct dri2_egl_surface *dri2_surf)<br>
>>              dri2_dpy->image->createImage(dri2_dpy->dri_screen,<br>
>>                                           dri2_surf->base.Width,<br>
>>                                           dri2_surf->base.Height,<br>
>> -                                         dri_image_format,<br>
>> +                                         linear_dri_image_format,<br>
>>                                           use_flags |<br>
>>                                           __DRI_IMAGE_USE_LINEAR,<br>
>>                                           NULL);<br>
>> @@ -1278,8 +1287,11 @@ dri2_wl_add_configs_for_visuals(_EGLDriver *drv, _EGLDisplay *disp)<br>
>>     struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);<br>
>>     unsigned int format_count[ARRAY_SIZE(dri2_wl_visuals)] = { 0 };<br>
>>     unsigned int count = 0;<br>
>> +   bool assigned;<br>
>><br>
>>     for (unsigned i = 0; dri2_dpy->driver_configs[i]; i++) {<br>
>> +      assigned = false;<br>
>> +<br>
>>        for (unsigned j = 0; j < ARRAY_SIZE(dri2_wl_visuals); j++) {<br>
>>           struct dri2_egl_config *dri2_conf;<br>
>><br>
>> @@ -1292,6 +1304,43 @@ dri2_wl_add_configs_for_visuals(_EGLDriver *drv, _EGLDisplay *disp)<br>
>>              if (dri2_conf->base.ConfigID == count + 1)<br>
>>                 count++;<br>
>>              format_count[j]++;<br>
>> +            assigned = true;<br>
>> +         }<br>
>> +      }<br>
>> +<br>
>> +      if (!assigned && dri2_dpy->is_different_gpu) {<br>
>> +         struct dri2_egl_config *dri2_conf;<br>
>> +         int alt_dri_image_format, j, k;<br>
><br>
> Let's avoid reusing the same names as the loop variables above?<br>
<br>
Okay, c for client visual index and s for substitute visual index are<br>
still free as short names.<br>
<br>
thanks,<br>
-mario<br>
<br>
><br>
>> +<br>
>> +         /* No match for config. Try if we can blitImage convert to a visual */<br>
>> +         j = dri2_wl_visual_idx_from_config(dri2_dpy,<br>
>> +                                            dri2_dpy->driver_configs[i]);<br>
>> +<br>
>> +         if (j == -1)<br>
>> +            continue;<br>
>> +<br>
>> +         /* Find optimal target visual for blitImage conversion, if any. */<br>
>> +         alt_dri_image_format = dri2_wl_visuals[j].alt_dri_image_format;<br>
>> +         k = dri2_wl_visual_idx_from_dri_image_format(alt_dri_image_format);<br>
>> +<br>
>> +         if (k == -1 || !(dri2_dpy->formats & (1 << k)))<br>
>> +            continue;<br>
>> +<br>
>> +         /* Visual k works for the Wayland server, and j can be converted into k<br>
>> +          * by our client gpu during PRIME blitImage conversion to a linear<br>
>> +          * wl_buffer, so add visual j as supported by the client renderer.<br>
>> +          */<br>
>> +         dri2_conf = dri2_add_config(disp, dri2_dpy->driver_configs[i],<br>
>> +                                     count + 1, EGL_WINDOW_BIT, NULL,<br>
>> +                                     dri2_wl_visuals[j].rgba_masks);<br>
>> +         if (dri2_conf) {<br>
>> +            if (dri2_conf->base.ConfigID == count + 1)<br>
>> +               count++;<br>
>> +            format_count[j]++;<br>
>> +            if (format_count[j] == 1)<br>
>> +               _eglLog(_EGL_DEBUG, "Client format %s to server format %s via "<br>
>> +                       "PRIME blitImage.", dri2_wl_visuals[j].format_name,<br>
>> +                       dri2_wl_visuals[k].format_name);<br>
>>           }<br>
>>        }<br>
>>     }<br>
>> --<br>
>> 2.13.0.rc1.294.g07d810a77f<br>
>><br>
>> _______________________________________________<br>
>> mesa-dev mailing list<br>
>> <a href="mailto:mesa-dev@lists.freedesktop.org" target="_blank">mesa-dev@lists.freedesktop.org</a><br>
>> <a href="https://lists.freedesktop.org/mailman/listinfo/mesa-dev" rel="noreferrer" target="_blank">https://lists.freedesktop.org/mailman/listinfo/mesa-dev</a><br>
_______________________________________________<br>
mesa-dev mailing list<br>
<a href="mailto:mesa-dev@lists.freedesktop.org" target="_blank">mesa-dev@lists.freedesktop.org</a><br>
<a href="https://lists.freedesktop.org/mailman/listinfo/mesa-dev" rel="noreferrer" target="_blank">https://lists.freedesktop.org/mailman/listinfo/mesa-dev</a><br>
</blockquote></div>