screen-cast-stream: Add explicit modifier support
This change adds modifier-aware screencasting support to Mutter. Implicit modifier support is kept for backward compatibility and the code fallbacks to implicit modifiers in case any new functionality added for explicit modifier support fails. The advertised modifiers are retrieved by a call to eglQueryDmaBufModifiersEXT() function. The "external only" modifiers are excluded as Mutter uses the buffers created with the explicit modifiers as renderbuffers. Support for implicit modifiers is checked with a test allocation since there are drivers that do not support them. This change also removes various implicit modifier support checks that disable DMA-BUF screen casting support globally as they are no longer needed. DMA-BUF support for screencasting is determined by the available formats and modifiers case-by-case now. It also effectively enables DMA-BUF screencasting on NVIDIA hardware as well since GBM buffer objects with linear modifiers are no longer used by default to create a renderbuffer object for screencasting. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3537>
This commit is contained in:
parent
34d00d769e
commit
dc2b2e379b
4 changed files with 397 additions and 169 deletions
|
@ -111,6 +111,8 @@ typedef struct _MetaScreenCastStreamSrcPrivate
|
|||
GHashTable *dmabuf_handles;
|
||||
|
||||
MtkRegion *redraw_clip;
|
||||
|
||||
GHashTable *modifiers;
|
||||
} MetaScreenCastStreamSrcPrivate;
|
||||
|
||||
static const struct {
|
||||
|
@ -164,6 +166,7 @@ push_format_object (struct spa_pod_builder *pod_builder,
|
|||
enum spa_video_format format,
|
||||
uint64_t *modifiers,
|
||||
int n_modifiers,
|
||||
gboolean fixate_modifier,
|
||||
...)
|
||||
{
|
||||
struct spa_pod_frame pod_frames[2];
|
||||
|
@ -182,33 +185,34 @@ push_format_object (struct spa_pod_builder *pod_builder,
|
|||
spa_pod_builder_add (pod_builder,
|
||||
SPA_FORMAT_VIDEO_format, SPA_POD_Id (format),
|
||||
0);
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
if (n_modifiers == 1 && modifiers[0] == DRM_FORMAT_MOD_INVALID)
|
||||
if (n_modifiers > 0)
|
||||
{
|
||||
spa_pod_builder_prop (pod_builder,
|
||||
SPA_FORMAT_VIDEO_modifier,
|
||||
SPA_POD_PROP_FLAG_MANDATORY);
|
||||
spa_pod_builder_long (pod_builder, modifiers[0]);
|
||||
}
|
||||
else if (n_modifiers > 0)
|
||||
{
|
||||
int i;
|
||||
if (fixate_modifier)
|
||||
{
|
||||
spa_pod_builder_prop (pod_builder,
|
||||
SPA_FORMAT_VIDEO_modifier,
|
||||
SPA_POD_PROP_FLAG_MANDATORY);
|
||||
spa_pod_builder_long (pod_builder, modifiers[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
|
||||
spa_pod_builder_prop (pod_builder,
|
||||
SPA_FORMAT_VIDEO_modifier,
|
||||
(SPA_POD_PROP_FLAG_MANDATORY |
|
||||
SPA_POD_PROP_FLAG_DONT_FIXATE));
|
||||
spa_pod_builder_push_choice (pod_builder, &pod_frames[1],
|
||||
SPA_CHOICE_Enum,
|
||||
0);
|
||||
spa_pod_builder_long (pod_builder, modifiers[0]);
|
||||
for (i = 0; i < n_modifiers; i++)
|
||||
spa_pod_builder_long (pod_builder, modifiers[i]);
|
||||
spa_pod_builder_pop (pod_builder, &pod_frames[1]);
|
||||
spa_pod_builder_prop (pod_builder,
|
||||
SPA_FORMAT_VIDEO_modifier,
|
||||
(SPA_POD_PROP_FLAG_MANDATORY |
|
||||
SPA_POD_PROP_FLAG_DONT_FIXATE));
|
||||
spa_pod_builder_push_choice (pod_builder, &pod_frames[1],
|
||||
SPA_CHOICE_Enum,
|
||||
0);
|
||||
spa_pod_builder_long (pod_builder, modifiers[0]);
|
||||
for (i = 0; i < n_modifiers; i++)
|
||||
spa_pod_builder_long (pod_builder, modifiers[i]);
|
||||
spa_pod_builder_pop (pod_builder, &pod_frames[1]);
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_NATIVE_BACKEND */
|
||||
|
||||
va_start (args, n_modifiers);
|
||||
va_start (args, fixate_modifier);
|
||||
spa_pod_builder_addv (pod_builder, args);
|
||||
va_end (args);
|
||||
return spa_pod_builder_pop (pod_builder, &pod_frames[0]);
|
||||
|
@ -967,17 +971,21 @@ meta_screen_cast_stream_src_close (MetaScreenCastStreamSrc *src)
|
|||
priv->emit_closed_after_dispatch = TRUE;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
build_format_params (MetaScreenCastStreamSrc *src,
|
||||
struct spa_pod_builder *pod_builder,
|
||||
const struct spa_pod *params[4])
|
||||
static void
|
||||
build_format_params (MetaScreenCastStreamSrc *src,
|
||||
struct spa_pod_builder *pod_builder,
|
||||
const struct spa_pod **params,
|
||||
uint32_t *n_params)
|
||||
{
|
||||
MetaScreenCastStream *stream = meta_screen_cast_stream_src_get_stream (src);
|
||||
MetaScreenCastSession *session = meta_screen_cast_stream_get_session (stream);
|
||||
MetaScreenCastStream *stream =
|
||||
meta_screen_cast_stream_src_get_stream (src);
|
||||
MetaScreenCastSession *session =
|
||||
meta_screen_cast_stream_get_session (stream);
|
||||
MetaScreenCastStreamSrcPrivate *priv =
|
||||
meta_screen_cast_stream_src_get_instance_private (src);
|
||||
MetaScreenCast *screen_cast =
|
||||
meta_screen_cast_session_get_screen_cast (session);
|
||||
uint64_t *modifiers;
|
||||
int n_modifiers;
|
||||
GArray *modifiers;
|
||||
CoglPixelFormat preferred_cogl_format =
|
||||
meta_screen_cast_stream_src_get_preferred_format (src);
|
||||
enum spa_video_format preferred_spa_video_format;
|
||||
|
@ -989,7 +997,6 @@ build_format_params (MetaScreenCastStreamSrc *src,
|
|||
struct spa_fraction default_framerate = DEFAULT_FRAME_RATE;
|
||||
struct spa_fraction min_framerate = MIN_FRAME_RATE;
|
||||
struct spa_fraction max_framerate = MAX_FRAME_RATE;
|
||||
uint32_t n_params = 0;
|
||||
int width;
|
||||
int height;
|
||||
float frame_rate;
|
||||
|
@ -1026,28 +1033,36 @@ build_format_params (MetaScreenCastStreamSrc *src,
|
|||
if (!cogl_pixel_format_from_spa_video_format (spa_video_formats[i], &cogl_format))
|
||||
continue;
|
||||
|
||||
if (meta_screen_cast_query_modifiers (screen_cast, cogl_format, &modifiers, &n_modifiers))
|
||||
modifiers = g_hash_table_lookup (priv->modifiers,
|
||||
GINT_TO_POINTER (cogl_format));
|
||||
if (modifiers == NULL)
|
||||
{
|
||||
params[n_params++] = push_format_object (
|
||||
pod_builder,
|
||||
spa_video_formats[i], modifiers, n_modifiers,
|
||||
SPA_FORMAT_VIDEO_size, SPA_POD_CHOICE_RANGE_Rectangle (&default_size,
|
||||
&min_size,
|
||||
&max_size),
|
||||
SPA_FORMAT_VIDEO_framerate, SPA_POD_Fraction (&SPA_FRACTION (0, 1)),
|
||||
SPA_FORMAT_VIDEO_maxFramerate,
|
||||
SPA_POD_CHOICE_RANGE_Fraction (&default_framerate,
|
||||
&min_framerate,
|
||||
&max_framerate),
|
||||
0);
|
||||
free (modifiers);
|
||||
modifiers = meta_screen_cast_query_modifiers (screen_cast, cogl_format);
|
||||
g_hash_table_insert (priv->modifiers,
|
||||
GINT_TO_POINTER (cogl_format),
|
||||
modifiers);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < n_spa_video_formats; i++)
|
||||
{
|
||||
params[n_params++] = push_format_object (
|
||||
if (modifiers->len == 0)
|
||||
continue;
|
||||
|
||||
params[(*n_params)++] = push_format_object (
|
||||
pod_builder,
|
||||
spa_video_formats[i], NULL, 0,
|
||||
spa_video_formats[i], (uint64_t *) modifiers->data, modifiers->len, FALSE,
|
||||
SPA_FORMAT_VIDEO_size, SPA_POD_CHOICE_RANGE_Rectangle (&default_size,
|
||||
&min_size,
|
||||
&max_size),
|
||||
SPA_FORMAT_VIDEO_framerate, SPA_POD_Fraction (&SPA_FRACTION (0, 1)),
|
||||
SPA_FORMAT_VIDEO_maxFramerate,
|
||||
SPA_POD_CHOICE_RANGE_Fraction (&default_framerate,
|
||||
&min_framerate,
|
||||
&max_framerate),
|
||||
0);
|
||||
}
|
||||
for (i = 0; i < n_spa_video_formats; i++)
|
||||
{
|
||||
params[(*n_params)++] = push_format_object (
|
||||
pod_builder,
|
||||
spa_video_formats[i], NULL, 0, FALSE,
|
||||
SPA_FORMAT_VIDEO_size, SPA_POD_CHOICE_RANGE_Rectangle (&default_size,
|
||||
&min_size,
|
||||
&max_size),
|
||||
|
@ -1058,8 +1073,6 @@ build_format_params (MetaScreenCastStreamSrc *src,
|
|||
&max_framerate),
|
||||
0);
|
||||
}
|
||||
|
||||
return n_params;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1070,10 +1083,10 @@ renegotiate_pipewire_stream (MetaScreenCastStreamSrc *src)
|
|||
uint8_t buffer[1024];
|
||||
struct spa_pod_builder pod_builder;
|
||||
const struct spa_pod *params[4];
|
||||
int n_params;
|
||||
uint32_t n_params = 0;
|
||||
|
||||
pod_builder = SPA_POD_BUILDER_INIT (buffer, sizeof (buffer));
|
||||
n_params = build_format_params (src, &pod_builder, params);
|
||||
build_format_params (src, &pod_builder, params, &n_params);
|
||||
pw_stream_update_params (priv->pipewire_stream, params, n_params);
|
||||
}
|
||||
|
||||
|
@ -1147,8 +1160,9 @@ on_stream_param_changed (void *data,
|
|||
uint8_t params_buffer[1024];
|
||||
struct spa_pod_builder pod_builder;
|
||||
const struct spa_pod *params[5];
|
||||
int n_params = 0;
|
||||
uint32_t n_params = 0;
|
||||
int buffer_types;
|
||||
const struct spa_pod_prop *prop_modifier;
|
||||
|
||||
if (!format || id != SPA_PARAM_Format)
|
||||
return;
|
||||
|
@ -1157,12 +1171,82 @@ on_stream_param_changed (void *data,
|
|||
&priv->video_format);
|
||||
|
||||
pod_builder = SPA_POD_BUILDER_INIT (params_buffer, sizeof (params_buffer));
|
||||
prop_modifier = spa_pod_find_prop (format, NULL, SPA_FORMAT_VIDEO_modifier);
|
||||
|
||||
if (spa_pod_find_prop (format, NULL, SPA_FORMAT_VIDEO_modifier))
|
||||
if (prop_modifier)
|
||||
buffer_types = 1 << SPA_DATA_DmaBuf;
|
||||
else
|
||||
buffer_types = 1 << SPA_DATA_MemFd;
|
||||
|
||||
if (prop_modifier && (prop_modifier->flags & SPA_POD_PROP_FLAG_DONT_FIXATE))
|
||||
{
|
||||
MetaScreenCastStream *stream =
|
||||
meta_screen_cast_stream_src_get_stream (src);
|
||||
MetaScreenCastSession *session =
|
||||
meta_screen_cast_stream_get_session (stream);
|
||||
MetaScreenCast *screen_cast =
|
||||
meta_screen_cast_session_get_screen_cast (session);
|
||||
CoglPixelFormat cogl_format;
|
||||
const struct spa_pod *pod_modifier = &prop_modifier->value;
|
||||
uint64_t *negotiated_modifiers = SPA_POD_CHOICE_VALUES (pod_modifier);
|
||||
uint32_t n_negotiated_modifiers = SPA_POD_CHOICE_N_VALUES (pod_modifier);
|
||||
GArray *supported_modifiers;
|
||||
uint64_t preferred_modifier;
|
||||
int i;
|
||||
|
||||
if (!cogl_pixel_format_from_spa_video_format (priv->video_format.format,
|
||||
&cogl_format))
|
||||
g_assert_not_reached ();
|
||||
|
||||
supported_modifiers = g_hash_table_lookup (priv->modifiers,
|
||||
GINT_TO_POINTER (cogl_format));
|
||||
g_array_set_size (supported_modifiers, 0);
|
||||
for (i = 0; i < n_negotiated_modifiers; i++)
|
||||
{
|
||||
uint64_t modifier = negotiated_modifiers[i];
|
||||
gboolean found = FALSE;
|
||||
int j;
|
||||
|
||||
for (j = 0; j < supported_modifiers->len; j++)
|
||||
{
|
||||
if (g_array_index (supported_modifiers, uint64_t, j) == modifier)
|
||||
{
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
g_array_append_vals (supported_modifiers, &modifier, 1);
|
||||
}
|
||||
|
||||
if (meta_screen_cast_get_preferred_modifier (screen_cast,
|
||||
cogl_format,
|
||||
supported_modifiers,
|
||||
priv->video_format.size.width,
|
||||
priv->video_format.size.height,
|
||||
&preferred_modifier))
|
||||
{
|
||||
params[n_params++] = push_format_object (
|
||||
&pod_builder,
|
||||
priv->video_format.format, &preferred_modifier, 1, TRUE,
|
||||
SPA_FORMAT_VIDEO_size, SPA_POD_CHOICE_RANGE_Rectangle (&priv->video_format.size,
|
||||
&priv->video_format.size,
|
||||
&priv->video_format.size),
|
||||
SPA_FORMAT_VIDEO_framerate, SPA_POD_Fraction (&SPA_FRACTION (0, 1)),
|
||||
SPA_FORMAT_VIDEO_maxFramerate,
|
||||
SPA_POD_CHOICE_RANGE_Fraction (&priv->video_format.max_framerate,
|
||||
&MIN_FRAME_RATE,
|
||||
&priv->video_format.max_framerate),
|
||||
0);
|
||||
}
|
||||
|
||||
build_format_params (src, &pod_builder, params, &n_params);
|
||||
|
||||
pw_stream_update_params (priv->pipewire_stream, params, n_params);
|
||||
return;
|
||||
}
|
||||
|
||||
params[n_params++] = spa_pod_builder_add_object (
|
||||
&pod_builder,
|
||||
SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers,
|
||||
|
@ -1204,10 +1288,6 @@ on_stream_add_buffer (void *data,
|
|||
MetaScreenCastStreamSrc *src = data;
|
||||
MetaScreenCastStreamSrcPrivate *priv =
|
||||
meta_screen_cast_stream_src_get_instance_private (src);
|
||||
MetaScreenCastStream *stream = meta_screen_cast_stream_src_get_stream (src);
|
||||
MetaScreenCastSession *session = meta_screen_cast_stream_get_session (stream);
|
||||
MetaScreenCast *screen_cast =
|
||||
meta_screen_cast_session_get_screen_cast (session);
|
||||
CoglDmaBufHandle *dmabuf_handle;
|
||||
struct spa_buffer *spa_buffer = buffer->buffer;
|
||||
struct spa_data *spa_data = &spa_buffer->datas[0];
|
||||
|
@ -1220,6 +1300,12 @@ on_stream_add_buffer (void *data,
|
|||
|
||||
if (spa_data->type & (1 << SPA_DATA_DmaBuf))
|
||||
{
|
||||
MetaScreenCastStream *stream =
|
||||
meta_screen_cast_stream_src_get_stream (src);
|
||||
MetaScreenCastSession *session =
|
||||
meta_screen_cast_stream_get_session (stream);
|
||||
MetaScreenCast *screen_cast =
|
||||
meta_screen_cast_session_get_screen_cast (session);
|
||||
CoglPixelFormat cogl_format;
|
||||
|
||||
if (!cogl_pixel_format_from_spa_video_format (priv->video_format.format,
|
||||
|
@ -1229,13 +1315,26 @@ on_stream_add_buffer (void *data,
|
|||
dmabuf_handle =
|
||||
meta_screen_cast_create_dma_buf_handle (screen_cast,
|
||||
cogl_format,
|
||||
priv->video_format.modifier,
|
||||
priv->video_format.size.width,
|
||||
priv->video_format.size.height);
|
||||
if (!dmabuf_handle)
|
||||
{
|
||||
// TODO: Drop dmabuf support more granular
|
||||
meta_screen_cast_disable_dma_bufs (screen_cast);
|
||||
renegotiate_pipewire_stream (src);
|
||||
GArray *modifiers;
|
||||
int i;
|
||||
|
||||
modifiers = g_hash_table_lookup (priv->modifiers,
|
||||
GINT_TO_POINTER (cogl_format));
|
||||
for (i = 0; i < modifiers->len; i++)
|
||||
{
|
||||
if (g_array_index (modifiers, uint64_t, i) == priv->video_format.modifier)
|
||||
{
|
||||
g_array_remove_index (modifiers, i);
|
||||
renegotiate_pipewire_stream (src);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1369,7 +1468,7 @@ create_pipewire_stream (MetaScreenCastStreamSrc *src,
|
|||
struct spa_pod_builder pod_builder =
|
||||
SPA_POD_BUILDER_INIT (buffer, sizeof (buffer));
|
||||
const struct spa_pod *params[4];
|
||||
int n_params = 0;
|
||||
uint32_t n_params = 0;
|
||||
int result;
|
||||
|
||||
priv->node_id = SPA_ID_INVALID;
|
||||
|
@ -1385,7 +1484,7 @@ create_pipewire_stream (MetaScreenCastStreamSrc *src,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
n_params = build_format_params (src, &pod_builder, params);
|
||||
build_format_params (src, &pod_builder, params, &n_params);
|
||||
|
||||
pw_stream_add_listener (pipewire_stream,
|
||||
&priv->pipewire_stream_listener,
|
||||
|
@ -1581,10 +1680,18 @@ meta_screen_cast_stream_src_dispose (GObject *object)
|
|||
MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (object);
|
||||
MetaScreenCastStreamSrcPrivate *priv =
|
||||
meta_screen_cast_stream_src_get_instance_private (src);
|
||||
GHashTableIter modifierIter;
|
||||
gpointer key, value;
|
||||
|
||||
if (meta_screen_cast_stream_src_is_enabled (src))
|
||||
meta_screen_cast_stream_src_disable (src);
|
||||
|
||||
g_hash_table_iter_init (&modifierIter,
|
||||
priv->modifiers);
|
||||
while (g_hash_table_iter_next (&modifierIter, &key, &value))
|
||||
g_array_free (value, TRUE);
|
||||
|
||||
g_clear_pointer (&priv->modifiers, g_hash_table_destroy);
|
||||
g_clear_pointer (&priv->pipewire_stream, pw_stream_destroy);
|
||||
g_clear_pointer (&priv->dmabuf_handles, g_hash_table_destroy);
|
||||
g_clear_pointer (&priv->pipewire_core, pw_core_disconnect);
|
||||
|
@ -1643,6 +1750,8 @@ meta_screen_cast_stream_src_init (MetaScreenCastStreamSrc *src)
|
|||
priv->dmabuf_handles =
|
||||
g_hash_table_new_full (NULL, NULL, NULL,
|
||||
(GDestroyNotify) cogl_dma_buf_handle_free);
|
||||
|
||||
priv->modifiers = g_hash_table_new (NULL, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -24,14 +24,20 @@
|
|||
|
||||
#include <pipewire/pipewire.h>
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
#include <drm_fourcc.h>
|
||||
#endif
|
||||
|
||||
#include "backends/meta-backend-private.h"
|
||||
#include "backends/meta-remote-desktop-session.h"
|
||||
#include "backends/meta-screen-cast-session.h"
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
#include "backends/native/meta-drm-buffer.h"
|
||||
#include "backends/native/meta-render-device.h"
|
||||
#include "backends/native/meta-renderer-native-private.h"
|
||||
|
||||
#include "cogl/cogl-egl.h"
|
||||
|
||||
#include "common/meta-cogl-drm-formats.h"
|
||||
#endif
|
||||
|
||||
#define META_SCREEN_CAST_DBUS_SERVICE "org.gnome.Mutter.ScreenCast"
|
||||
#define META_SCREEN_CAST_DBUS_PATH "/org/gnome/Mutter/ScreenCast"
|
||||
#define META_SCREEN_CAST_API_VERSION 4
|
||||
|
@ -39,8 +45,6 @@
|
|||
struct _MetaScreenCast
|
||||
{
|
||||
MetaDbusSessionManager parent;
|
||||
|
||||
gboolean disable_dma_bufs;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (MetaScreenCast, meta_screen_cast,
|
||||
|
@ -54,68 +58,228 @@ meta_screen_cast_get_backend (MetaScreenCast *screen_cast)
|
|||
return meta_dbus_session_manager_get_backend (session_manager);
|
||||
}
|
||||
|
||||
void
|
||||
meta_screen_cast_disable_dma_bufs (MetaScreenCast *screen_cast)
|
||||
gboolean
|
||||
meta_screen_cast_get_preferred_modifier (MetaScreenCast *screen_cast,
|
||||
CoglPixelFormat format,
|
||||
GArray *modifiers,
|
||||
int width,
|
||||
int height,
|
||||
uint64_t *preferred_modifier)
|
||||
{
|
||||
screen_cast->disable_dma_bufs = TRUE;
|
||||
}
|
||||
|
||||
bool
|
||||
meta_screen_cast_query_modifiers (MetaScreenCast *screen_cast,
|
||||
CoglPixelFormat format,
|
||||
uint64_t **modifiers,
|
||||
int *n_modifiers)
|
||||
{
|
||||
MetaDbusSessionManager *session_manager =
|
||||
META_DBUS_SESSION_MANAGER (screen_cast);
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
MetaBackend *backend =
|
||||
meta_dbus_session_manager_get_backend (session_manager);
|
||||
meta_screen_cast_get_backend (screen_cast);
|
||||
ClutterBackend *clutter_backend =
|
||||
meta_backend_get_clutter_backend (backend);
|
||||
CoglContext *cogl_context =
|
||||
clutter_backend_get_cogl_context (clutter_backend);
|
||||
CoglRenderer *cogl_renderer = cogl_context_get_renderer (cogl_context);
|
||||
CoglRenderer *cogl_renderer =
|
||||
cogl_context_get_renderer (cogl_context);
|
||||
CoglRendererEGL *cogl_renderer_egl =
|
||||
cogl_renderer->winsys;
|
||||
MetaRendererNativeGpuData *renderer_gpu_data =
|
||||
cogl_renderer_egl->platform;
|
||||
MetaRenderDevice *render_device =
|
||||
renderer_gpu_data->render_device;
|
||||
MetaRendererNative *renderer_native =
|
||||
renderer_gpu_data->renderer_native;
|
||||
int dmabuf_fd;
|
||||
uint32_t stride;
|
||||
uint32_t offset;
|
||||
g_autoptr (GError) error = NULL;
|
||||
bool ret;
|
||||
const MetaFormatInfo *format_info;
|
||||
gboolean use_implicit_modifier;
|
||||
|
||||
if (screen_cast->disable_dma_bufs)
|
||||
return FALSE;
|
||||
g_assert (cogl_renderer_is_dma_buf_supported (cogl_renderer));
|
||||
|
||||
format_info = meta_format_info_from_cogl_format (format);
|
||||
g_assert (format_info);
|
||||
|
||||
while (modifiers->len > 0)
|
||||
{
|
||||
g_autoptr (MetaDrmBuffer) dmabuf = NULL;
|
||||
g_autoptr (CoglFramebuffer) fb = NULL;
|
||||
|
||||
if ((modifiers->len > 1) ||
|
||||
(g_array_index (modifiers, uint64_t, 0) != DRM_FORMAT_MOD_INVALID))
|
||||
use_implicit_modifier = FALSE;
|
||||
else
|
||||
use_implicit_modifier = TRUE;
|
||||
|
||||
dmabuf = meta_render_device_allocate_dma_buf (render_device,
|
||||
width, height,
|
||||
format_info->drm_format,
|
||||
(uint64_t *) modifiers->data,
|
||||
use_implicit_modifier ? 0 : modifiers->len,
|
||||
META_DRM_BUFFER_FLAG_NONE,
|
||||
&error);
|
||||
if (!dmabuf)
|
||||
break;
|
||||
|
||||
stride = meta_drm_buffer_get_stride (dmabuf);
|
||||
offset = meta_drm_buffer_get_offset (dmabuf, 0);
|
||||
|
||||
dmabuf_fd = meta_drm_buffer_export_fd (dmabuf, &error);
|
||||
if (dmabuf_fd == -1)
|
||||
break;
|
||||
|
||||
if (use_implicit_modifier)
|
||||
{
|
||||
*preferred_modifier = DRM_FORMAT_MOD_INVALID;
|
||||
fb = meta_renderer_native_create_dma_buf_framebuffer (renderer_native,
|
||||
dmabuf_fd,
|
||||
width, height,
|
||||
stride,
|
||||
offset,
|
||||
NULL,
|
||||
format_info->drm_format,
|
||||
&error);
|
||||
}
|
||||
else
|
||||
{
|
||||
*preferred_modifier = meta_drm_buffer_get_modifier (dmabuf);
|
||||
fb = meta_renderer_native_create_dma_buf_framebuffer (renderer_native,
|
||||
dmabuf_fd,
|
||||
width, height,
|
||||
stride,
|
||||
offset,
|
||||
preferred_modifier,
|
||||
format_info->drm_format,
|
||||
&error);
|
||||
}
|
||||
close (dmabuf_fd);
|
||||
|
||||
if (!fb)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < modifiers->len; i++)
|
||||
{
|
||||
if (g_array_index (modifiers, uint64_t, i) == *preferred_modifier)
|
||||
{
|
||||
g_array_remove_index (modifiers, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
g_array_set_size (modifiers, 0);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GArray *
|
||||
meta_screen_cast_query_modifiers (MetaScreenCast *screen_cast,
|
||||
CoglPixelFormat format)
|
||||
{
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
MetaBackend *backend =
|
||||
meta_screen_cast_get_backend (screen_cast);
|
||||
ClutterBackend *clutter_backend =
|
||||
meta_backend_get_clutter_backend (backend);
|
||||
CoglContext *cogl_context =
|
||||
clutter_backend_get_cogl_context (clutter_backend);
|
||||
CoglRenderer *cogl_renderer =
|
||||
cogl_context_get_renderer (cogl_context);
|
||||
EGLDisplay egl_display =
|
||||
cogl_egl_context_get_egl_display (cogl_context);
|
||||
MetaEgl *egl =
|
||||
meta_backend_get_egl (backend);
|
||||
EGLint num_modifiers;
|
||||
g_autofree EGLuint64KHR *all_modifiers = NULL;
|
||||
g_autofree EGLBoolean *external_only = NULL;
|
||||
g_autoptr (GError) error = NULL;
|
||||
g_autoptr (CoglDmaBufHandle) dmabuf_handle = NULL;
|
||||
GArray *modifiers = NULL;
|
||||
gboolean ret;
|
||||
const MetaFormatInfo *format_info;
|
||||
uint64_t modifier;
|
||||
int i;
|
||||
|
||||
if (!cogl_renderer_is_dma_buf_supported (cogl_renderer))
|
||||
return FALSE;
|
||||
return g_array_new (FALSE, FALSE, sizeof (uint64_t));
|
||||
|
||||
format_info = meta_format_info_from_cogl_format (format);
|
||||
g_assert (format_info);
|
||||
|
||||
// TODO: query cogl_renderer for modifiers
|
||||
// BEGIN stub
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
uint64_t *modifier_list;
|
||||
ret = meta_egl_query_dma_buf_modifiers (egl,
|
||||
egl_display,
|
||||
format_info->drm_format,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
&num_modifiers,
|
||||
&error);
|
||||
if (!ret || num_modifiers == 0)
|
||||
{
|
||||
if (error)
|
||||
g_warning ("Failed to query DMA-BUF modifiers: %s", error->message);
|
||||
goto add_implicit_modifier;
|
||||
}
|
||||
|
||||
modifier_list = calloc (1, sizeof (uint64_t));
|
||||
modifier_list[0] = DRM_FORMAT_MOD_INVALID;
|
||||
all_modifiers = g_new (uint64_t, num_modifiers);
|
||||
external_only = g_new (EGLBoolean, num_modifiers);
|
||||
|
||||
*modifiers = modifier_list;
|
||||
*n_modifiers = 1;
|
||||
ret = TRUE;
|
||||
#else
|
||||
ret = FALSE;
|
||||
#endif
|
||||
ret = meta_egl_query_dma_buf_modifiers (egl,
|
||||
egl_display,
|
||||
format_info->drm_format,
|
||||
num_modifiers,
|
||||
all_modifiers,
|
||||
external_only,
|
||||
&num_modifiers,
|
||||
&error);
|
||||
if (!ret)
|
||||
{
|
||||
g_warning ("Failed to query DMA-BUF modifiers: %s", error->message);
|
||||
goto add_implicit_modifier;
|
||||
}
|
||||
|
||||
modifiers = g_array_sized_new (FALSE, FALSE, sizeof (uint64_t),
|
||||
num_modifiers + 1);
|
||||
|
||||
for (i = 0; i < num_modifiers; i++)
|
||||
{
|
||||
if (!external_only[i])
|
||||
{
|
||||
modifier = all_modifiers[i];
|
||||
g_array_append_vals (modifiers, &modifier, 1);
|
||||
}
|
||||
}
|
||||
// END stub
|
||||
|
||||
if (!ret)
|
||||
g_warning ("Failed to query supported modifiers: %s",
|
||||
error->message);
|
||||
return ret;
|
||||
add_implicit_modifier:
|
||||
if (!modifiers)
|
||||
{
|
||||
g_warning ("Couldn't retrieve the supported modifiers");
|
||||
modifiers = g_array_new (FALSE, FALSE, sizeof (uint64_t));
|
||||
}
|
||||
|
||||
modifier = DRM_FORMAT_MOD_INVALID;
|
||||
g_array_append_vals (modifiers, &modifier, 1);
|
||||
|
||||
return modifiers;
|
||||
#else
|
||||
return g_array_new (FALSE, FALSE, sizeof (uint64_t));
|
||||
#endif
|
||||
}
|
||||
|
||||
CoglDmaBufHandle *
|
||||
meta_screen_cast_create_dma_buf_handle (MetaScreenCast *screen_cast,
|
||||
CoglPixelFormat format,
|
||||
uint64_t modifier,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
MetaDbusSessionManager *session_manager =
|
||||
META_DBUS_SESSION_MANAGER (screen_cast);
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
MetaBackend *backend =
|
||||
meta_dbus_session_manager_get_backend (session_manager);
|
||||
meta_screen_cast_get_backend (screen_cast);
|
||||
ClutterBackend *clutter_backend =
|
||||
meta_backend_get_clutter_backend (backend);
|
||||
CoglContext *cogl_context =
|
||||
|
@ -123,25 +287,20 @@ meta_screen_cast_create_dma_buf_handle (MetaScreenCast *screen_cast,
|
|||
CoglRenderer *cogl_renderer = cogl_context_get_renderer (cogl_context);
|
||||
g_autoptr (GError) error = NULL;
|
||||
CoglDmaBufHandle *dmabuf_handle;
|
||||
int n_modifiers;
|
||||
|
||||
if (screen_cast->disable_dma_bufs)
|
||||
return NULL;
|
||||
n_modifiers = (modifier == DRM_FORMAT_MOD_INVALID) ? 0
|
||||
: 1;
|
||||
|
||||
dmabuf_handle = cogl_renderer_create_dma_buf (cogl_renderer,
|
||||
format,
|
||||
NULL, 0,
|
||||
&modifier, n_modifiers,
|
||||
width, height,
|
||||
&error);
|
||||
if (!dmabuf_handle)
|
||||
{
|
||||
g_warning ("Failed to allocate DMA buffer, "
|
||||
"disabling DMA buffer based screen casting: %s",
|
||||
error->message);
|
||||
screen_cast->disable_dma_bufs = TRUE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return dmabuf_handle;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static MetaRemoteDesktopSession *
|
||||
|
|
|
@ -49,15 +49,19 @@ G_DECLARE_FINAL_TYPE (MetaScreenCast, meta_screen_cast,
|
|||
|
||||
MetaBackend * meta_screen_cast_get_backend (MetaScreenCast *screen_cast);
|
||||
|
||||
void meta_screen_cast_disable_dma_bufs (MetaScreenCast *screen_cast);
|
||||
GArray * meta_screen_cast_query_modifiers (MetaScreenCast *screen_cast,
|
||||
CoglPixelFormat format);
|
||||
|
||||
bool meta_screen_cast_query_modifiers (MetaScreenCast *screen_cast,
|
||||
CoglPixelFormat format,
|
||||
uint64_t **modifiers,
|
||||
int *n_modifiers);
|
||||
gboolean meta_screen_cast_get_preferred_modifier (MetaScreenCast *screen_cast,
|
||||
CoglPixelFormat format,
|
||||
GArray *modifiers,
|
||||
int width,
|
||||
int height,
|
||||
uint64_t *preferred_modifier);
|
||||
|
||||
CoglDmaBufHandle * meta_screen_cast_create_dma_buf_handle (MetaScreenCast *screen_cast,
|
||||
CoglPixelFormat format,
|
||||
uint64_t modifier,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
|
|
|
@ -62,10 +62,6 @@
|
|||
#include "meta/main.h"
|
||||
#include "meta-dbus-rtkit1.h"
|
||||
|
||||
#ifdef HAVE_REMOTE_DESKTOP
|
||||
#include "backends/meta-screen-cast.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_EGL_DEVICE
|
||||
#include "backends/native/meta-render-device-egl-stream.h"
|
||||
#endif
|
||||
|
@ -162,42 +158,6 @@ meta_backend_native_create_default_seat (MetaBackend *backend,
|
|||
NULL));
|
||||
}
|
||||
|
||||
#ifdef HAVE_REMOTE_DESKTOP
|
||||
static void
|
||||
maybe_disable_screen_cast_dma_bufs (MetaBackendNative *native)
|
||||
{
|
||||
MetaBackend *backend = META_BACKEND (native);
|
||||
MetaRenderer *renderer = meta_backend_get_renderer (backend);
|
||||
MetaScreenCast *screen_cast = meta_backend_get_screen_cast (backend);
|
||||
ClutterBackend *clutter_backend =
|
||||
meta_backend_get_clutter_backend (backend);
|
||||
CoglContext *cogl_context =
|
||||
clutter_backend_get_cogl_context (clutter_backend);
|
||||
CoglRenderer *cogl_renderer = cogl_context_get_renderer (cogl_context);
|
||||
g_autoptr (GError) error = NULL;
|
||||
g_autoptr (CoglDmaBufHandle) dmabuf_handle = NULL;
|
||||
|
||||
if (!meta_renderer_is_hardware_accelerated (renderer))
|
||||
{
|
||||
g_message ("Disabling DMA buffer screen sharing "
|
||||
"(not hardware accelerated)");
|
||||
meta_screen_cast_disable_dma_bufs (screen_cast);
|
||||
}
|
||||
|
||||
dmabuf_handle = cogl_renderer_create_dma_buf (cogl_renderer,
|
||||
COGL_PIXEL_FORMAT_BGRX_8888,
|
||||
NULL, 0,
|
||||
1, 1,
|
||||
&error);
|
||||
if (!dmabuf_handle)
|
||||
{
|
||||
g_message ("Disabling DMA buffer screen sharing "
|
||||
"(implicit modifiers not supported)");
|
||||
meta_screen_cast_disable_dma_bufs (screen_cast);
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_REMOTE_DESKTOP */
|
||||
|
||||
static void
|
||||
update_viewports (MetaBackend *backend)
|
||||
{
|
||||
|
@ -220,10 +180,6 @@ meta_backend_native_post_init (MetaBackend *backend)
|
|||
|
||||
META_BACKEND_CLASS (meta_backend_native_parent_class)->post_init (backend);
|
||||
|
||||
#ifdef HAVE_REMOTE_DESKTOP
|
||||
maybe_disable_screen_cast_dma_bufs (backend_native);
|
||||
#endif
|
||||
|
||||
g_clear_pointer (&backend_native->startup_render_devices,
|
||||
g_hash_table_unref);
|
||||
|
||||
|
|
Loading…
Reference in a new issue