summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLouis-Francis Ratté-Boulianne <lfrb@collabora.com>2018-02-14 13:27:28 -0500
committerJonas Ådahl <jadahl@gmail.com>2018-02-22 14:01:48 +0800
commitaec85281ba76dfd564f71b88dc0a2800b6fc4027 (patch)
treecb3a3f04066ab0c402de498081a512661555539a
parentb22875aae971bc28d74a676244fe533b3ccd1462 (diff)
downloadmutter-aec85281ba76dfd564f71b88dc0a2800b6fc4027.tar.gz
native/renderer: Retrieve the right modifiers set for each GPU
We were retrieving the supported KMS modifiers for all GPUs even though what we really need to intersect between these sets of modifiers: 1) KMS supported modifiers for primary GPU if the GPU is used for scanout; 2) EGL supported modifiers for secondary GPUs (different than the primary GPU used for rendering); 3) GBM supported modifiers when creating the surface (already taken care of by gbm_surface_create_with_modifiers()); https://gitlab.gnome.org/GNOME/mutter/issues/18
-rw-r--r--src/backends/native/meta-renderer-native.c381
1 files changed, 241 insertions, 140 deletions
diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
index 5b3a9a925..825833975 100644
--- a/src/backends/native/meta-renderer-native.c
+++ b/src/backends/native/meta-renderer-native.c
@@ -310,6 +310,247 @@ meta_onscreen_native_get_egl (MetaOnscreenNative *onscreen_native)
return meta_renderer_native_get_egl (onscreen_native->renderer_native);
}
+static GArray *
+get_supported_kms_modifiers (CoglOnscreen *onscreen,
+ MetaGpu *gpu,
+ uint32_t format)
+{
+ CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
+ MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
+ MetaLogicalMonitor *logical_monitor = onscreen_native->logical_monitor;
+ GArray *modifiers;
+ GArray *base_mods;
+ GList *l_crtc;
+ MetaCrtc *base_crtc = NULL;
+ GList *other_crtcs = NULL;
+ unsigned int i;
+
+ if (!logical_monitor)
+ return NULL;
+
+ /* Find our base CRTC to intersect against. */
+ for (l_crtc = meta_gpu_get_crtcs (gpu); l_crtc; l_crtc = l_crtc->next)
+ {
+ MetaCrtc *crtc = l_crtc->data;
+
+ if (crtc->logical_monitor != logical_monitor)
+ continue;
+
+ if (!base_crtc)
+ base_crtc = crtc;
+ else if (crtc == base_crtc)
+ continue;
+ else if (g_list_index (other_crtcs, crtc) == -1)
+ other_crtcs = g_list_append (other_crtcs, crtc);
+ }
+
+ if (!base_crtc)
+ goto out;
+
+ base_mods = meta_crtc_kms_get_modifiers (base_crtc, format);
+ if (!base_mods)
+ goto out;
+
+ /*
+ * If this is the only CRTC we have, we don't need to intersect the sets of
+ * modifiers.
+ */
+ if (other_crtcs == NULL)
+ {
+ modifiers = g_array_sized_new (FALSE, FALSE, sizeof (uint64_t),
+ base_mods->len);
+ g_array_append_vals (modifiers, base_mods->data, base_mods->len);
+ return modifiers;
+ }
+
+ modifiers = g_array_new (FALSE, FALSE, sizeof (uint64_t));
+
+ /*
+ * For each modifier from base_crtc, check if it's available on all other
+ * CRTCs.
+ */
+ for (i = 0; i < base_mods->len; i++)
+ {
+ uint64_t modifier = g_array_index (base_mods, uint64_t, i);
+ gboolean found_everywhere = TRUE;
+ GList *k;
+
+ /* Check if we have the same modifier available for all CRTCs. */
+ for (k = other_crtcs; k; k = k->next)
+ {
+ MetaCrtc *crtc = k->data;
+ GArray *crtc_mods;
+ unsigned int m;
+ gboolean found_here = FALSE;
+
+ if (crtc->logical_monitor != logical_monitor)
+ continue;
+
+ crtc_mods = meta_crtc_kms_get_modifiers (crtc, format);
+ if (!crtc_mods)
+ {
+ g_array_free (modifiers, TRUE);
+ goto out;
+ }
+
+ for (m = 0; m < crtc_mods->len; m++)
+ {
+ uint64_t local_mod = g_array_index (crtc_mods, uint64_t, m);
+
+ if (local_mod == modifier)
+ {
+ found_here = TRUE;
+ break;
+ }
+ }
+
+ if (!found_here)
+ {
+ found_everywhere = FALSE;
+ break;
+ }
+ }
+
+ if (found_everywhere)
+ g_array_append_val (modifiers, modifier);
+ }
+
+ if (modifiers->len == 0)
+ {
+ g_array_free (modifiers, TRUE);
+ goto out;
+ }
+
+ return modifiers;
+
+out:
+ g_list_free (other_crtcs);
+ return NULL;
+}
+
+static GArray *
+get_supported_egl_modifiers (CoglOnscreen *onscreen,
+ MetaGpu *gpu,
+ uint32_t format)
+{
+ CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
+ MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
+ MetaRendererNative *renderer_native = onscreen_native->renderer_native;
+ MetaEgl *egl = meta_onscreen_native_get_egl (onscreen_native);
+ MetaRendererNativeGpuData *renderer_gpu_data;
+ EGLint num_modifiers;
+ GArray *modifiers;
+ GError *error = NULL;
+ gboolean ret;
+
+ renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native,
+ META_GPU_KMS (gpu));
+
+ if (!meta_egl_has_extensions (egl, renderer_gpu_data->egl_display, NULL,
+ "EGL_EXT_image_dma_buf_import_modifiers",
+ NULL))
+ return NULL;
+
+ ret = meta_egl_query_dma_buf_modifiers (egl, renderer_gpu_data->egl_display,
+ format, 0, NULL, NULL,
+ &num_modifiers, NULL);
+ if (!ret || num_modifiers == 0)
+ return NULL;
+
+ modifiers = g_array_sized_new (FALSE, FALSE, sizeof (uint64_t),
+ num_modifiers);
+ ret = meta_egl_query_dma_buf_modifiers (egl, renderer_gpu_data->egl_display,
+ format, num_modifiers,
+ (EGLuint64KHR *) modifiers->data, NULL,
+ &num_modifiers, &error);
+
+ if (!ret)
+ {
+ g_warning ("Failed to query DMABUF modifiers: %s", error->message);
+ g_error_free (error);
+ g_array_free (modifiers, TRUE);
+ return NULL;
+ }
+
+ return modifiers;
+}
+
+static GArray *
+get_supported_modifiers (CoglOnscreen *onscreen,
+ uint32_t format)
+{
+ CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
+ MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
+ MetaLogicalMonitor *logical_monitor = onscreen_native->logical_monitor;
+ GArray *modifiers = NULL;
+ GArray *gpu_mods;
+ GList *l_monitor;
+ unsigned int i;
+
+ if (!logical_monitor)
+ return NULL;
+
+ /* Find our base CRTC to intersect against. */
+ for (l_monitor = meta_logical_monitor_get_monitors (logical_monitor);
+ l_monitor;
+ l_monitor = l_monitor->next)
+ {
+ MetaMonitor *monitor = l_monitor->data;
+ MetaGpu *gpu = meta_monitor_get_gpu (monitor);
+
+ if (gpu == META_GPU (onscreen_native->render_gpu))
+ gpu_mods = get_supported_kms_modifiers (onscreen, gpu, format);
+ else
+ gpu_mods = get_supported_egl_modifiers (onscreen, gpu, format);
+
+ if (!gpu_mods)
+ {
+ g_array_free (modifiers, TRUE);
+ return NULL;
+ }
+
+ if (!modifiers)
+ {
+ modifiers = gpu_mods;
+ continue;
+ }
+
+ for (i = 0; i < modifiers->len; i++)
+ {
+ uint64_t modifier = g_array_index (modifiers, uint64_t, i);
+ gboolean found = FALSE;
+ unsigned int m;
+
+ for (m = 0; m < gpu_mods->len; m++)
+ {
+ uint64_t gpu_mod = g_array_index (gpu_mods, uint64_t, m);
+
+ if (gpu_mod == modifier)
+ {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (!found)
+ {
+ g_array_remove_index_fast (modifiers, i);
+ i--;
+ }
+ }
+
+ g_array_free (gpu_mods, TRUE);
+ }
+
+ if (modifiers && modifiers->len == 0)
+ {
+ g_array_free (modifiers, TRUE);
+ return NULL;
+ }
+
+ return modifiers;
+}
+
static gboolean
init_secondary_gpu_state_gpu_copy_mode (MetaRendererNative *renderer_native,
CoglOnscreen *onscreen,
@@ -1639,146 +1880,6 @@ meta_renderer_native_init_egl_context (CoglContext *cogl_context,
return TRUE;
}
-static GArray *
-get_supported_modifiers (CoglOnscreen *onscreen,
- uint32_t format)
-{
- CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
- MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
- MetaRendererNative *renderer_native = onscreen_native->renderer_native;
- MetaLogicalMonitor *logical_monitor = onscreen_native->logical_monitor;
- MetaEgl *egl = meta_onscreen_native_get_egl (onscreen_native);
- CoglContext *cogl_context = COGL_FRAMEBUFFER (onscreen)->context;
- CoglRenderer *cogl_renderer = cogl_context->display->renderer;
- CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys;
- GArray *modifiers;
- GArray *base_mods;
- GList *l_crtc, *l_monitor;
- MetaCrtc *base_crtc = NULL;
- GList *other_crtcs = NULL;
- unsigned int i;
-
- if (!logical_monitor)
- return NULL;
-
- /* Find our base CRTC to intersect against. */
- for (l_monitor = meta_logical_monitor_get_monitors (logical_monitor);
- l_monitor;
- l_monitor = l_monitor->next)
- {
- MetaMonitor *monitor = l_monitor->data;
- MetaGpu *gpu = meta_monitor_get_gpu (monitor);
- MetaRendererNativeGpuData *renderer_gpu_data;
-
- /* All secondary GPUs need to be able to import DMA BUF with modifiers */
- renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native,
- META_GPU_KMS (gpu));
- if (cogl_renderer_egl->platform != renderer_gpu_data &&
- !meta_egl_has_extensions (egl, renderer_gpu_data->egl_display, NULL,
- "EGL_EXT_image_dma_buf_import_modifiers",
- NULL))
- goto out;
-
- for (l_crtc = meta_gpu_get_crtcs (gpu); l_crtc; l_crtc = l_crtc->next)
- {
- MetaCrtc *crtc = l_crtc->data;
-
- if (crtc->logical_monitor != logical_monitor)
- continue;
-
- if (!base_crtc)
- base_crtc = crtc;
- else if (crtc == base_crtc)
- continue;
- else if (g_list_index (other_crtcs, crtc) == -1)
- other_crtcs = g_list_append (other_crtcs, crtc);
- }
- }
-
- if (!base_crtc)
- goto out;
-
- base_mods = meta_crtc_kms_get_modifiers (base_crtc, format);
- if (!base_mods)
- goto out;
-
- /*
- * If this is the only CRTC we have, we don't need to intersect the sets of
- * modifiers.
- */
- if (other_crtcs == NULL)
- {
- modifiers = g_array_sized_new (FALSE, FALSE, sizeof (uint64_t),
- base_mods->len);
- g_array_append_vals (modifiers, base_mods->data, base_mods->len);
- return modifiers;
- }
-
- modifiers = g_array_new (FALSE, FALSE, sizeof (uint64_t));
-
- /*
- * For each modifier from base_crtc, check if it's available on all other
- * CRTCs.
- */
- for (i = 0; i < base_mods->len; i++)
- {
- uint64_t modifier = g_array_index (base_mods, uint64_t, i);
- gboolean found_everywhere = TRUE;
- GList *k;
-
- /* Check if we have the same modifier available for all CRTCs. */
- for (k = other_crtcs; k; k = k->next)
- {
- MetaCrtc *crtc = k->data;
- GArray *crtc_mods;
- unsigned int m;
- gboolean found_here = FALSE;
-
- if (crtc->logical_monitor != logical_monitor)
- continue;
-
- crtc_mods = meta_crtc_kms_get_modifiers (crtc, format);
- if (!crtc_mods)
- {
- g_array_free (modifiers, TRUE);
- goto out;
- }
-
- for (m = 0; m < crtc_mods->len; m++)
- {
- uint64_t local_mod = g_array_index (crtc_mods, uint64_t, m);
-
- if (local_mod == modifier)
- {
- found_here = TRUE;
- break;
- }
- }
-
- if (!found_here)
- {
- found_everywhere = FALSE;
- break;
- }
- }
-
- if (found_everywhere)
- g_array_append_val (modifiers, modifier);
- }
-
- if (modifiers->len == 0)
- {
- g_array_free (modifiers, TRUE);
- goto out;
- }
-
- return modifiers;
-
-out:
- g_list_free (other_crtcs);
- return NULL;
-}
-
static gboolean
should_surface_be_sharable (CoglOnscreen *onscreen)
{