diff --git a/cogl/cogl/cogl-renderer.h b/cogl/cogl/cogl-renderer.h index 1a35eefff..fffb1ed22 100644 --- a/cogl/cogl/cogl-renderer.h +++ b/cogl/cogl/cogl-renderer.h @@ -39,6 +39,12 @@ G_BEGIN_DECLS +typedef enum _CoglDrmModifierFilter +{ + COGL_DRM_MODIFIER_FILTER_NONE = 0, + COGL_DRM_MODIFIER_FILTER_SINGLE_PLANE = 1 << 0, +} CoglDrmModifierFilter; + /** * CoglRenderer: * diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c index 47b5a2c2b..bc6d98c35 100644 --- a/src/backends/native/meta-onscreen-native.c +++ b/src/backends/native/meta-onscreen-native.c @@ -2083,47 +2083,27 @@ get_supported_egl_modifiers (CoglOnscreen *onscreen, { MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen); MetaRendererNative *renderer_native = onscreen_native->renderer_native; - MetaEgl *egl = meta_onscreen_native_get_egl (onscreen_native); MetaGpu *gpu; MetaRendererNativeGpuData *renderer_gpu_data; MetaRenderDevice *render_device; - EGLDisplay egl_display; - EGLint num_modifiers; - g_autofree EGLuint64KHR *modifiers = NULL; + GArray *modifiers; g_autoptr (GError) error = NULL; - gboolean ret; gpu = meta_crtc_get_gpu (META_CRTC (crtc_kms)); renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native, META_GPU_KMS (gpu)); render_device = renderer_gpu_data->render_device; - egl_display = meta_render_device_get_egl_display (render_device); - if (!meta_egl_has_extensions (egl, egl_display, NULL, - "EGL_EXT_image_dma_buf_import_modifiers", - NULL)) - return NULL; - - ret = meta_egl_query_dma_buf_modifiers (egl, egl_display, - format, 0, NULL, NULL, - &num_modifiers, NULL); - if (!ret || num_modifiers == 0) - return NULL; - - modifiers = g_new (typeof (*modifiers), num_modifiers); - ret = meta_egl_query_dma_buf_modifiers (egl, egl_display, - format, num_modifiers, - modifiers, NULL, - &num_modifiers, &error); - - if (!ret) + modifiers = meta_render_device_query_drm_modifiers (render_device, format, + COGL_DRM_MODIFIER_FILTER_NONE, + &error); + if (!modifiers) { g_warning ("Failed to query DMABUF modifiers: %s", error->message); return NULL; } - return g_array_new_take (g_steal_pointer (&modifiers), num_modifiers, FALSE, - sizeof (*modifiers)); + return modifiers; } static GArray * diff --git a/src/backends/native/meta-render-device-gbm.c b/src/backends/native/meta-render-device-gbm.c index 7a381b98e..57685e276 100644 --- a/src/backends/native/meta-render-device-gbm.c +++ b/src/backends/native/meta-render-device-gbm.c @@ -106,6 +106,86 @@ meta_render_device_gbm_import_dma_buf (MetaRenderDevice *render_device, return META_DRM_BUFFER (buffer_import); } +static GArray * +meta_render_device_gbm_query_drm_modifiers (MetaRenderDevice *render_device, + uint32_t drm_format, + CoglDrmModifierFilter filter, + GError **error) +{ + MetaRenderDeviceGbm *render_device_gbm = + META_RENDER_DEVICE_GBM (render_device); + MetaBackend *backend = meta_render_device_get_backend (render_device); + MetaEgl *egl = meta_backend_get_egl (backend); + EGLDisplay egl_display; + EGLint n_modifiers; + g_autoptr (GArray) modifiers = NULL; + + egl_display = meta_render_device_get_egl_display (render_device); + + if (!meta_egl_has_extensions (egl, egl_display, NULL, + "EGL_EXT_image_dma_buf_import_modifiers", + NULL)) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + "Missing EGL extension " + "'EGL_EXT_image_dma_buf_import_modifiers'"); + return NULL; + } + + if (!meta_egl_query_dma_buf_modifiers (egl, egl_display, + drm_format, 0, NULL, NULL, + &n_modifiers, error)) + return NULL; + + if (n_modifiers == 0) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "No modifiers supported for given format"); + return NULL; + } + + modifiers = g_array_sized_new (FALSE, FALSE, sizeof (uint64_t), + n_modifiers); + if (!meta_egl_query_dma_buf_modifiers (egl, egl_display, + drm_format, n_modifiers, + (EGLuint64KHR *) modifiers->data, NULL, + &n_modifiers, error)) + return NULL; + + g_array_set_size (modifiers, n_modifiers); + + if (filter & COGL_DRM_MODIFIER_FILTER_SINGLE_PLANE) + { + g_autoptr (GArray) filtered_modifiers = NULL; + struct gbm_device *gbm_device = render_device_gbm->gbm_device; + int i; + + filtered_modifiers = g_array_new (FALSE, FALSE, sizeof (uint64_t)); + + for (i = 0; i < modifiers->len; i++) + { + uint64_t modifier = g_array_index (modifiers, uint64_t, i); + + if (gbm_device_get_format_modifier_plane_count (gbm_device, + drm_format, + modifier) == 1) + g_array_append_val (filtered_modifiers, modifier); + } + + if (filtered_modifiers->len == 0) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, + "No single plane modifiers found"); + return NULL; + } + + g_array_free (modifiers, TRUE); + modifiers = g_steal_pointer (&filtered_modifiers); + } + + return g_steal_pointer (&modifiers); +} + static EGLDisplay meta_render_device_gbm_create_egl_display (MetaRenderDevice *render_device, GError **error) @@ -213,6 +293,8 @@ meta_render_device_gbm_class_init (MetaRenderDeviceGbmClass *klass) meta_render_device_gbm_allocate_dma_buf; render_device_class->import_dma_buf = meta_render_device_gbm_import_dma_buf; + render_device_class->query_drm_modifiers = + meta_render_device_gbm_query_drm_modifiers; } static void diff --git a/src/backends/native/meta-render-device-private.h b/src/backends/native/meta-render-device-private.h index 321d57a5a..6fc0cf971 100644 --- a/src/backends/native/meta-render-device-private.h +++ b/src/backends/native/meta-render-device-private.h @@ -44,4 +44,9 @@ struct _MetaRenderDeviceClass MetaDrmBuffer * (* import_dma_buf) (MetaRenderDevice *render_device, MetaDrmBuffer *buffer, GError **error); + + GArray * (* query_drm_modifiers) (MetaRenderDevice *render_device, + uint32_t format, + CoglDrmModifierFilter filter, + GError **error); }; diff --git a/src/backends/native/meta-render-device.c b/src/backends/native/meta-render-device.c index 8141cf9c4..5b209e606 100644 --- a/src/backends/native/meta-render-device.c +++ b/src/backends/native/meta-render-device.c @@ -340,6 +340,28 @@ meta_render_device_get_name (MetaRenderDevice *render_device) return "(device-less)"; } +GArray * +meta_render_device_query_drm_modifiers (MetaRenderDevice *render_device, + uint32_t drm_format, + CoglDrmModifierFilter filter, + GError **error) +{ + MetaRenderDeviceClass *klass = META_RENDER_DEVICE_GET_CLASS (render_device); + + if (klass->query_drm_modifiers) + { + return klass->query_drm_modifiers (render_device, + drm_format, filter, + error); + } + + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + "Render device '%s' doesn't support allocating DMA buffers", + meta_render_device_get_name (render_device)); + + return NULL; +} + MetaDrmBuffer * meta_render_device_allocate_dma_buf (MetaRenderDevice *render_device, int width, diff --git a/src/backends/native/meta-render-device.h b/src/backends/native/meta-render-device.h index 90c2de911..8cc173524 100644 --- a/src/backends/native/meta-render-device.h +++ b/src/backends/native/meta-render-device.h @@ -38,6 +38,11 @@ gboolean meta_render_device_is_hardware_accelerated (MetaRenderDevice *render_de MetaDeviceFile * meta_render_device_get_device_file (MetaRenderDevice *render_device); +GArray * meta_render_device_query_drm_modifiers (MetaRenderDevice *render_device, + uint32_t drm_format, + CoglDrmModifierFilter filter, + GError **error); + MetaDrmBuffer * meta_render_device_allocate_dma_buf (MetaRenderDevice *render_device, int width, int height,