From d05751b1a28d7e99a089203401b0ec940373cbd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Tue, 9 Oct 2018 15:55:23 +0200 Subject: [PATCH] renderer/native: Use shadow fb on software GL if preferred If a KMS device has the DRM_CAP_DUMB_PREFER_SHADOW and a software based GL driver is used, always use a shadow fb. This will speed up read backs in the llvmpipe OpenGL implementation, making blend operations faster. Fixes: https://gitlab.gnome.org/GNOME/mutter/issues/106 --- src/backends/native/meta-renderer-native.c | 61 ++++++++++++++++++++-- 1 file changed, 57 insertions(+), 4 deletions(-) diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c index 470da8845..b15a6da96 100644 --- a/src/backends/native/meta-renderer-native.c +++ b/src/backends/native/meta-renderer-native.c @@ -2746,108 +2746,161 @@ meta_onscreen_native_set_view (CoglOnscreen *onscreen, static MetaMonitorTransform calculate_view_transform (MetaMonitorManager *monitor_manager, MetaLogicalMonitor *logical_monitor) { MetaMonitor *main_monitor; MetaOutput *main_output; MetaCrtc *crtc; MetaMonitorTransform crtc_transform; main_monitor = meta_logical_monitor_get_monitors (logical_monitor)->data; main_output = meta_monitor_get_main_output (main_monitor); crtc = meta_output_get_assigned_crtc (main_output); crtc_transform = meta_monitor_logical_to_crtc_transform (main_monitor, logical_monitor->transform); /* * Pick any monitor and output and check; all CRTCs of a logical monitor will * always have the same transform assigned to them. */ if (meta_monitor_manager_is_transform_handled (monitor_manager, crtc, crtc_transform)) return META_MONITOR_TRANSFORM_NORMAL; else return crtc_transform; } +static CoglContext * +cogl_context_from_renderer_native (MetaRendererNative *renderer_native) +{ + MetaMonitorManager *monitor_manager = + META_MONITOR_MANAGER (renderer_native->monitor_manager_kms); + MetaBackend *backend = meta_monitor_manager_get_backend (monitor_manager); + ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); + + return clutter_backend_get_cogl_context (clutter_backend); +} + +static gboolean +should_force_shadow_fb (MetaRendererNative *renderer_native, + MetaGpuKms *primary_gpu) +{ + CoglContext *cogl_context = + cogl_context_from_renderer_native (renderer_native); + CoglGpuInfo *info = &cogl_context->gpu; + int kms_fd; + uint64_t prefer_shadow = 0; + + switch (info->architecture) + { + case COGL_GPU_INFO_ARCHITECTURE_UNKNOWN: + case COGL_GPU_INFO_ARCHITECTURE_SANDYBRIDGE: + case COGL_GPU_INFO_ARCHITECTURE_SGX: + case COGL_GPU_INFO_ARCHITECTURE_MALI: + return FALSE; + case COGL_GPU_INFO_ARCHITECTURE_LLVMPIPE: + case COGL_GPU_INFO_ARCHITECTURE_SOFTPIPE: + case COGL_GPU_INFO_ARCHITECTURE_SWRAST: + break; + } + + kms_fd = meta_gpu_kms_get_fd (primary_gpu); + if (drmGetCap (kms_fd, DRM_CAP_DUMB_PREFER_SHADOW, &prefer_shadow) == 0) + { + if (prefer_shadow) + { + static gboolean logged_once = FALSE; + + if (!logged_once) + { + g_message ("Forcing shadow framebuffer"); + logged_once = TRUE; + } + + return TRUE; + } + } + + return FALSE; +} + static MetaRendererView * meta_renderer_native_create_view (MetaRenderer *renderer, MetaLogicalMonitor *logical_monitor) { MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer); MetaMonitorManagerKms *monitor_manager_kms = renderer_native->monitor_manager_kms; MetaMonitorManager *monitor_manager = META_MONITOR_MANAGER (monitor_manager_kms); - MetaBackend *backend = meta_monitor_manager_get_backend (monitor_manager); - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); CoglContext *cogl_context = - clutter_backend_get_cogl_context (clutter_backend); + cogl_context_from_renderer_native (renderer_native); CoglDisplay *cogl_display = cogl_context_get_display (cogl_context); MetaGpuKms *primary_gpu; CoglDisplayEGL *cogl_display_egl; CoglOnscreenEGL *onscreen_egl; MetaMonitorTransform view_transform; CoglOnscreen *onscreen = NULL; CoglOffscreen *offscreen = NULL; float scale; int width, height; MetaRendererView *view; GError *error = NULL; view_transform = calculate_view_transform (monitor_manager, logical_monitor); if (meta_is_stage_views_scaled ()) scale = meta_logical_monitor_get_scale (logical_monitor); else scale = 1.0; width = roundf (logical_monitor->rect.width * scale); height = roundf (logical_monitor->rect.height * scale); primary_gpu = meta_monitor_manager_kms_get_primary_gpu (monitor_manager_kms); onscreen = meta_renderer_native_create_onscreen (renderer_native, primary_gpu, logical_monitor, cogl_context, view_transform, width, height, &error); if (!onscreen) g_error ("Failed to allocate onscreen framebuffer: %s", error->message); - if (view_transform != META_MONITOR_TRANSFORM_NORMAL) + if (view_transform != META_MONITOR_TRANSFORM_NORMAL || + should_force_shadow_fb (renderer_native, primary_gpu)) { offscreen = meta_renderer_native_create_offscreen (renderer_native, cogl_context, view_transform, width, height, &error); if (!offscreen) g_error ("Failed to allocate back buffer texture: %s", error->message); } view = g_object_new (META_TYPE_RENDERER_VIEW, "layout", &logical_monitor->rect, "scale", scale, "framebuffer", onscreen, "offscreen", offscreen, "logical-monitor", logical_monitor, "transform", view_transform, NULL); g_clear_pointer (&offscreen, cogl_object_unref); meta_onscreen_native_set_view (onscreen, view); if (!meta_onscreen_native_allocate (onscreen, &error)) { g_warning ("Could not create onscreen: %s", error->message); cogl_object_unref (onscreen); g_object_unref (view); g_error_free (error); return NULL; -- 2.17.1