[mutter] renderer/native: use cogl for CPU copy path
- From: Ray Strode <halfline src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter] renderer/native: use cogl for CPU copy path
- Date: Mon, 19 Nov 2018 23:18:29 +0000 (UTC)
commit d4bea60e1aab8e58bd2925d24256ddfdd125dbdb
Author: Pekka Paalanen <pekka paalanen collabora co uk>
Date: Thu Sep 27 16:42:19 2018 +0300
renderer/native: use cogl for CPU copy path
Use cogl_framebuffer_read_pixels_into_bitmap () instead of
glReadPixels () for the CPU copy path in multi-GPU support.
The cogl function employs several tricks to make the read-pixels as fast
as possible and does the y-flip as necessary. This should make the copy
more performant over all kinds of hardware.
This is expected to be used on virtual outputs (e.g. DisplayLink USB
docks and monitors) foremost, where the dumb buffer memory is just
regular system memory. If the dumb buffer memory is somehow slow, like
residing in discrete VRAM or having an unexpected caching mode, it may
be possible for the cogl function perform worse because it might do the
y-flip in-place in the dumb buffer. Hopefully that does not happen in
any practical scenario.
Calling meta_renderer_native_gles3_read_pixels () here was conceptually
wrong to begin with because it was done with the Cogl GL context of the
primary GPU, not on the GL ES 3 context of a secondary GPU. However,
due eglBindAPI being a no-op in Mesa and the glReadPixels () arguments
being compatible, it worked.
This patch adds a pixel format conversion table between DRM and Cogl
formats. It contains more formats than absolutely necessary and the
texture components field which is currently unused for completeness. See
Mutter issue #323. Making the table more complete documents better how
the pixel formats actually map so that posterity should be less likely
to be confused. This table could be shared with
shm_buffer_get_cogl_pixel_format () as well, but not with
meta_wayland_dma_buf_buffer_attach ().
On HP ProBook 4520s laptop (Mesa DRI Intel(R) Ironlake Mobile, Mesa
18.0.5), without this patch copy_shared_framebuffer_cpu () for a
DisplayLink output takes 5 seconds with a 1080p frame. Obviously that
makes Mutter and gnome-shell completely unusable. With this patch, that
function takes 13-18 ms which makes it usable if not fluent.
On Intel i7-4790 (Mesa DRI Intel(R) Haswell Desktop) machine, this patch
makes no significant difference (the copy takes 4-5 ms).
src/backends/native/meta-renderer-native.c | 96 ++++++++++++++++++++++++++----
1 file changed, 86 insertions(+), 10 deletions(-)
---
diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
index 6b0d6d3b0..ab7a2ee40 100644
--- a/src/backends/native/meta-renderer-native.c
+++ b/src/backends/native/meta-renderer-native.c
@@ -1776,22 +1776,82 @@ copy_shared_framebuffer_gpu (CoglOnscreen *onscreen,
&secondary_gpu_state->gbm.next_fb_id);
}
+typedef struct _PixelFormatMap {
+ uint32_t drm_format;
+ CoglPixelFormat cogl_format;
+ CoglTextureComponents cogl_components;
+} PixelFormatMap;
+
+static const PixelFormatMap pixel_format_map[] = {
+/* DRM formats are defined as little-endian, not machine endian. */
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+ { DRM_FORMAT_RGB565, COGL_PIXEL_FORMAT_RGB_565, COGL_TEXTURE_COMPONENTS_RGB },
+ { DRM_FORMAT_ABGR8888, COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
+ { DRM_FORMAT_XBGR8888, COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
+ { DRM_FORMAT_ARGB8888, COGL_PIXEL_FORMAT_BGRA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
+ { DRM_FORMAT_XRGB8888, COGL_PIXEL_FORMAT_BGRA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
+ { DRM_FORMAT_BGRA8888, COGL_PIXEL_FORMAT_ARGB_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
+ { DRM_FORMAT_BGRX8888, COGL_PIXEL_FORMAT_ARGB_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
+ { DRM_FORMAT_RGBA8888, COGL_PIXEL_FORMAT_ABGR_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
+ { DRM_FORMAT_RGBX8888, COGL_PIXEL_FORMAT_ABGR_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
+#elif G_BYTE_ORDER == G_BIG_ENDIAN
+ /* DRM_FORMAT_RGB565 cannot be expressed. */
+ { DRM_FORMAT_ABGR8888, COGL_PIXEL_FORMAT_ABGR_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
+ { DRM_FORMAT_XBGR8888, COGL_PIXEL_FORMAT_ABGR_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
+ { DRM_FORMAT_ARGB8888, COGL_PIXEL_FORMAT_ARGB_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
+ { DRM_FORMAT_XRGB8888, COGL_PIXEL_FORMAT_ARGB_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
+ { DRM_FORMAT_BGRA8888, COGL_PIXEL_FORMAT_BGRA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
+ { DRM_FORMAT_BGRX8888, COGL_PIXEL_FORMAT_BGRA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
+ { DRM_FORMAT_RGBA8888, COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGBA },
+ { DRM_FORMAT_RGBX8888, COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_TEXTURE_COMPONENTS_RGB },
+#else
+#error "unexpected G_BYTE_ORDER"
+#endif
+};
+
+static gboolean
+cogl_pixel_format_from_drm_format (uint32_t drm_format,
+ CoglPixelFormat *out_format,
+ CoglTextureComponents *out_components)
+{
+ const size_t n = G_N_ELEMENTS (pixel_format_map);
+ size_t i;
+
+ for (i = 0; i < n; i++)
+ {
+ if (pixel_format_map[i].drm_format == drm_format)
+ break;
+ }
+
+ if (i == n)
+ return FALSE;
+
+ if (out_format)
+ *out_format = pixel_format_map[i].cogl_format;
+
+ if (out_components)
+ *out_components = pixel_format_map[i].cogl_components;
+
+ return TRUE;
+}
+
static void
copy_shared_framebuffer_cpu (CoglOnscreen *onscreen,
MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state,
MetaRendererNativeGpuData *renderer_gpu_data)
{
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
- CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
- MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
- MetaRendererNative *renderer_native = onscreen_native->renderer_native;
- MetaEgl *egl = meta_renderer_native_get_egl (renderer_native);
+ CoglContext *cogl_context = framebuffer->context;
int width, height;
uint8_t *target_data;
int target_stride_bytes;
uint32_t target_fb_id;
+ uint32_t target_drm_format;
MetaDumbBuffer *next_dumb_fb;
MetaDumbBuffer *current_dumb_fb;
+ CoglBitmap *dumb_bitmap;
+ CoglPixelFormat cogl_format;
+ gboolean ret;
width = cogl_framebuffer_get_width (framebuffer);
height = cogl_framebuffer_get_height (framebuffer);
@@ -1809,12 +1869,28 @@ copy_shared_framebuffer_cpu (CoglOnscreen *onscreen,
target_data = secondary_gpu_state->cpu.dumb_fb->map;
target_stride_bytes = secondary_gpu_state->cpu.dumb_fb->stride_bytes;
target_fb_id = secondary_gpu_state->cpu.dumb_fb->fb_id;
-
- meta_renderer_native_gles3_read_pixels (egl,
- renderer_native->gles3,
- width, height,
- target_data,
- target_stride_bytes);
+ target_drm_format = secondary_gpu_state->cpu.dumb_fb->drm_format;
+
+ ret = cogl_pixel_format_from_drm_format (target_drm_format,
+ &cogl_format,
+ NULL);
+ g_assert (ret);
+
+ dumb_bitmap = cogl_bitmap_new_for_data (cogl_context,
+ width,
+ height,
+ cogl_format,
+ target_stride_bytes,
+ target_data);
+
+ if (!cogl_framebuffer_read_pixels_into_bitmap (framebuffer,
+ 0 /* x */,
+ 0 /* y */,
+ COGL_READ_PIXELS_COLOR_BUFFER,
+ dumb_bitmap))
+ g_warning ("Failed to CPU-copy to a secondary GPU output");
+
+ cogl_object_unref (dumb_bitmap);
secondary_gpu_state->gbm.next_fb_id = target_fb_id;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]