[Mesa-dev] [PATCH 4/5] egl/wayland: Allow client->server format conversion for PRIME offload.
Mario Kleiner
mario.kleiner.de at gmail.com
Sat May 19 03:32:41 UTC 2018
Support PRIME render offload between a Wayland server gpu and a Wayland
client gpu with different channel ordering for their color formats,
e.g., between Intel drivers which currently only support ARGB2101010
and XRGB2101010 import/display and nouveau which only supports ABGR2101010
rendering and display on nv-50 and later.
In the wl_visuals table, we also store for each format an alternate
sibling format which stores colors at the same precision, but with
different channel ordering, e.g., ARGB2101010 <-> ABGR2101010.
If a given client-gpu renderable format is not supported by the server
for import, but the alternate format is supported by the server, expose
the client-gpu renderable format as a valid EGLConfig to the client. At
eglSwapBuffers time, during the blitImage() detiling blit from the client
backbuffer to the linear buffer, the client format is converted to the
server supported format. As we have to do a copy for PRIME anyway,
this channel swizzling conversion comes essentially for free.
Note that even if a server gpu in principle does support sampling
from the clients native format, this conversion will be a performance
advantage if it allows to convert to the servers preferred format
for direct scanout, as the Wayland compositor may then be able to
directly page-flip a fullscreen client wl_buffer onto the primary
plane, or onto a hardware overlay plane, avoiding an extra data copy
for desktop composition.
Tested so far under Weston with: nouveau single-gpu, Intel single-gpu,
AMD single-gpu, "Optimus" Intel server iGPU for display + NVidia
client dGPU for rendering.
Signed-off-by: Mario Kleiner <mario.kleiner.de at gmail.com>
Cc: Daniel Stone <daniels at collabora.com>
---
src/egl/drivers/dri2/platform_wayland.c | 67 ++++++++++++++++++++++++++++-----
1 file changed, 58 insertions(+), 9 deletions(-)
diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c
index 89a7f90118..fb364a6233 100644
--- a/src/egl/drivers/dri2/platform_wayland.c
+++ b/src/egl/drivers/dri2/platform_wayland.c
@@ -68,49 +68,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 }
},
};
@@ -450,15 +451,23 @@ 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);
+
/* 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);
@@ -505,7 +514,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);
@@ -514,7 +523,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);
@@ -1278,8 +1287,11 @@ 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;
+
for (unsigned j = 0; j < ARRAY_SIZE(dri2_wl_visuals); j++) {
struct dri2_egl_config *dri2_conf;
@@ -1292,6 +1304,43 @@ dri2_wl_add_configs_for_visuals(_EGLDriver *drv, _EGLDisplay *disp)
if (dri2_conf->base.ConfigID == count + 1)
count++;
format_count[j]++;
+ assigned = true;
+ }
+ }
+
+ 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;
+
+ /* 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;
+
+ /* Visual k works for the Wayland server, and j can be converted into k
+ * by our client gpu during PRIME blitImage conversion to a linear
+ * wl_buffer, so add visual j as supported by the client renderer.
+ */
+ 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]++;
+ if (format_count[j] == 1)
+ _eglLog(_EGL_DEBUG, "Client format %s to server format %s via "
+ "PRIME blitImage.", dri2_wl_visuals[j].format_name,
+ dri2_wl_visuals[k].format_name);
}
}
}
--
2.13.0.rc1.294.g07d810a77f
More information about the mesa-dev
mailing list