native: Release output device files that are unused
In order to make it possible to e.g. unload an unused DRM device, we need to make sure that we don't keep the file descriptor open if we don't need it; otherwise we block anyone from unloading the corresponding module. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1828>
This commit is contained in:
parent
3c47661b78
commit
ce5a5789bb
@ -32,6 +32,8 @@ typedef enum _MetaDeviceFileFlags
|
||||
|
||||
typedef enum _MetaDeviceFileTags
|
||||
{
|
||||
META_DEVICE_FILE_TAG_KMS,
|
||||
|
||||
META_DEVICE_FILE_N_TAGS,
|
||||
} MetaDeviceFileTags;
|
||||
|
||||
|
@ -52,6 +52,8 @@ struct _MetaKmsConnector
|
||||
|
||||
uint32_t edid_blob_id;
|
||||
uint32_t tile_blob_id;
|
||||
|
||||
gboolean fd_held;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (MetaKmsConnector, meta_kms_connector, G_TYPE_OBJECT)
|
||||
@ -128,6 +130,25 @@ meta_kms_connector_is_underscanning_supported (MetaKmsConnector *connector)
|
||||
return underscan_prop_id != 0;
|
||||
}
|
||||
|
||||
static void
|
||||
sync_fd_held (MetaKmsConnector *connector,
|
||||
MetaKmsImplDevice *impl_device)
|
||||
{
|
||||
gboolean should_hold_fd;
|
||||
|
||||
should_hold_fd = connector->current_state->current_crtc_id != 0;
|
||||
|
||||
if (connector->fd_held == should_hold_fd)
|
||||
return;
|
||||
|
||||
if (should_hold_fd)
|
||||
meta_kms_impl_device_hold_fd (impl_device);
|
||||
else
|
||||
meta_kms_impl_device_unhold_fd (impl_device);
|
||||
|
||||
connector->fd_held = should_hold_fd;
|
||||
}
|
||||
|
||||
static void
|
||||
set_panel_orientation (MetaKmsConnectorState *state,
|
||||
drmModePropertyPtr prop,
|
||||
@ -475,6 +496,8 @@ meta_kms_connector_read_state (MetaKmsConnector *connector,
|
||||
state_set_crtc_state (state, drm_connector, impl_device, drm_resources);
|
||||
|
||||
connector->current_state = state;
|
||||
|
||||
sync_fd_held (connector, impl_device);
|
||||
}
|
||||
|
||||
void
|
||||
@ -498,6 +521,7 @@ void
|
||||
meta_kms_connector_predict_state (MetaKmsConnector *connector,
|
||||
MetaKmsUpdate *update)
|
||||
{
|
||||
MetaKmsImplDevice *impl_device;
|
||||
MetaKmsConnectorState *current_state;
|
||||
GList *mode_sets;
|
||||
GList *l;
|
||||
@ -527,6 +551,9 @@ meta_kms_connector_predict_state (MetaKmsConnector *connector,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_device = meta_kms_device_get_impl_device (connector->device);
|
||||
sync_fd_held (connector, impl_device);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -645,6 +672,14 @@ meta_kms_connector_finalize (GObject *object)
|
||||
{
|
||||
MetaKmsConnector *connector = META_KMS_CONNECTOR (object);
|
||||
|
||||
if (connector->fd_held)
|
||||
{
|
||||
MetaKmsImplDevice *impl_device;
|
||||
|
||||
impl_device = meta_kms_device_get_impl_device (connector->device);
|
||||
meta_kms_impl_device_unhold_fd (impl_device);
|
||||
}
|
||||
|
||||
g_clear_pointer (&connector->current_state, meta_kms_connector_state_free);
|
||||
g_free (connector->name);
|
||||
|
||||
|
@ -602,6 +602,8 @@ process_page_flip_listener (MetaKmsImplDevice *impl_device,
|
||||
GUINT_TO_POINTER (crtc_id),
|
||||
page_flip_data);
|
||||
|
||||
meta_kms_impl_device_hold_fd (impl_device);
|
||||
|
||||
meta_topic (META_DEBUG_KMS,
|
||||
"[atomic] Adding page flip data for (%u, %s): %p",
|
||||
crtc_id,
|
||||
@ -709,6 +711,8 @@ atomic_page_flip_handler (int fd,
|
||||
if (!page_flip_data)
|
||||
return;
|
||||
|
||||
meta_kms_impl_device_unhold_fd (impl_device);
|
||||
|
||||
meta_kms_page_flip_data_set_timings_in_impl (page_flip_data,
|
||||
sequence, tv_sec, tv_usec);
|
||||
meta_kms_impl_device_handle_page_flip_callback (impl_device, page_flip_data);
|
||||
@ -1014,8 +1018,10 @@ dispose_page_flip_data (gpointer key,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaKmsPageFlipData *page_flip_data = value;
|
||||
MetaKmsImplDevice *impl_device = user_data;
|
||||
|
||||
meta_kms_page_flip_data_discard_in_impl (page_flip_data, NULL);
|
||||
meta_kms_impl_device_unhold_fd (impl_device);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -1028,7 +1034,7 @@ meta_kms_impl_device_atomic_prepare_shutdown (MetaKmsImplDevice *impl_device)
|
||||
|
||||
g_hash_table_foreach_remove (impl_device_atomic->page_flip_datas,
|
||||
dispose_page_flip_data,
|
||||
NULL);
|
||||
impl_device);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1055,7 +1061,6 @@ meta_kms_impl_device_atomic_open_device_file (MetaKmsImplDevice *impl_device,
|
||||
MetaDevicePool *device_pool =
|
||||
meta_backend_native_get_device_pool (META_BACKEND_NATIVE (backend));
|
||||
g_autoptr (MetaDeviceFile) device_file = NULL;
|
||||
int fd;
|
||||
|
||||
device_file = meta_device_pool_open (device_pool, path,
|
||||
META_DEVICE_FILE_FLAG_TAKE_CONTROL,
|
||||
@ -1063,20 +1068,33 @@ meta_kms_impl_device_atomic_open_device_file (MetaKmsImplDevice *impl_device,
|
||||
if (!device_file)
|
||||
return NULL;
|
||||
|
||||
fd = meta_device_file_get_fd (device_file);
|
||||
|
||||
if (drmSetClientCap (fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1) != 0)
|
||||
if (!meta_device_file_has_tag (device_file,
|
||||
META_DEVICE_FILE_TAG_KMS,
|
||||
META_KMS_DEVICE_FILE_TAG_ATOMIC))
|
||||
{
|
||||
g_set_error (error, META_KMS_ERROR, META_KMS_ERROR_NOT_SUPPORTED,
|
||||
"DRM_CLIENT_CAP_UNIVERSAL_PLANES not supported");
|
||||
return NULL;
|
||||
}
|
||||
int fd = meta_device_file_get_fd (device_file);
|
||||
|
||||
if (drmSetClientCap (fd, DRM_CLIENT_CAP_ATOMIC, 1) != 0)
|
||||
{
|
||||
g_set_error (error, META_KMS_ERROR, META_KMS_ERROR_NOT_SUPPORTED,
|
||||
"DRM_CLIENT_CAP_ATOMIC not supported");
|
||||
return NULL;
|
||||
g_warn_if_fail (!meta_device_file_has_tag (device_file,
|
||||
META_DEVICE_FILE_TAG_KMS,
|
||||
META_KMS_DEVICE_FILE_TAG_SIMPLE));
|
||||
|
||||
if (drmSetClientCap (fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1) != 0)
|
||||
{
|
||||
g_set_error (error, META_KMS_ERROR, META_KMS_ERROR_NOT_SUPPORTED,
|
||||
"DRM_CLIENT_CAP_UNIVERSAL_PLANES not supported");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (drmSetClientCap (fd, DRM_CLIENT_CAP_ATOMIC, 1) != 0)
|
||||
{
|
||||
g_set_error (error, META_KMS_ERROR, META_KMS_ERROR_NOT_SUPPORTED,
|
||||
"DRM_CLIENT_CAP_ATOMIC not supported");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
meta_device_file_tag (device_file,
|
||||
META_DEVICE_FILE_TAG_KMS,
|
||||
META_KMS_DEVICE_FILE_TAG_ATOMIC);
|
||||
}
|
||||
|
||||
return g_steal_pointer (&device_file);
|
||||
|
@ -655,6 +655,7 @@ retry_page_flips (gpointer user_data)
|
||||
g_critical ("Failed to page flip: %s", error->message);
|
||||
|
||||
meta_kms_page_flip_data_discard_in_impl (page_flip_data, error);
|
||||
meta_kms_impl_device_unhold_fd (impl_device);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -977,6 +978,7 @@ dispatch_page_flip (MetaKmsImplDevice *impl_device,
|
||||
fb_id = 0;
|
||||
drm_mode = cached_mode_set->drm_mode;
|
||||
refresh_rate = meta_calculate_drm_mode_refresh_rate (drm_mode);
|
||||
meta_kms_impl_device_hold_fd (impl_device);
|
||||
schedule_retry_page_flip (impl_device_simple,
|
||||
crtc,
|
||||
fb_id,
|
||||
@ -1016,6 +1018,8 @@ dispatch_page_flip (MetaKmsImplDevice *impl_device,
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_kms_impl_device_hold_fd (impl_device);
|
||||
|
||||
impl_device_simple->posted_page_flip_datas =
|
||||
g_list_prepend (impl_device_simple->posted_page_flip_datas,
|
||||
page_flip_data);
|
||||
@ -1367,6 +1371,8 @@ page_flip_handler (int fd,
|
||||
page_flip_data,
|
||||
meta_kms_crtc_get_id (crtc));
|
||||
|
||||
meta_kms_impl_device_unhold_fd (impl_device);
|
||||
|
||||
meta_kms_impl_device_handle_page_flip_callback (impl_device, page_flip_data);
|
||||
impl_device_simple->posted_page_flip_datas =
|
||||
g_list_remove (impl_device_simple->posted_page_flip_datas,
|
||||
@ -1465,6 +1471,14 @@ meta_kms_impl_device_simple_handle_page_flip_callback (MetaKmsImplDevice *impl
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dispose_page_flip_data (MetaKmsPageFlipData *page_flip_data,
|
||||
MetaKmsImplDevice *impl_device)
|
||||
{
|
||||
meta_kms_page_flip_data_discard_in_impl (page_flip_data, NULL);
|
||||
meta_kms_impl_device_unhold_fd (impl_device);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_kms_impl_device_simple_discard_pending_page_flips (MetaKmsImplDevice *impl_device)
|
||||
{
|
||||
@ -1489,7 +1503,7 @@ meta_kms_impl_device_simple_discard_pending_page_flips (MetaKmsImplDevice *impl_
|
||||
meta_kms_impl_device_get_path (
|
||||
meta_kms_page_flip_data_get_impl_device (page_flip_data)));
|
||||
|
||||
meta_kms_page_flip_data_discard_in_impl (page_flip_data, NULL);
|
||||
dispose_page_flip_data (page_flip_data, impl_device);
|
||||
retry_page_flip_data_free (retry_page_flip_data);
|
||||
}
|
||||
g_clear_pointer (&impl_device_simple->pending_page_flip_retries, g_list_free);
|
||||
@ -1505,8 +1519,8 @@ meta_kms_impl_device_simple_prepare_shutdown (MetaKmsImplDevice *impl_device)
|
||||
META_KMS_IMPL_DEVICE_SIMPLE (impl_device);
|
||||
|
||||
g_list_foreach (impl_device_simple->posted_page_flip_datas,
|
||||
(GFunc) meta_kms_page_flip_data_discard_in_impl,
|
||||
NULL);
|
||||
(GFunc) dispose_page_flip_data,
|
||||
impl_device);
|
||||
g_clear_list (&impl_device_simple->posted_page_flip_datas, NULL);
|
||||
}
|
||||
|
||||
@ -1515,18 +1529,16 @@ meta_kms_impl_device_simple_finalize (GObject *object)
|
||||
{
|
||||
MetaKmsImplDeviceSimple *impl_device_simple =
|
||||
META_KMS_IMPL_DEVICE_SIMPLE (object);
|
||||
MetaKmsImplDevice *impl_device = META_KMS_IMPL_DEVICE (impl_device_simple);
|
||||
|
||||
g_list_free_full (impl_device_simple->pending_page_flip_retries,
|
||||
(GDestroyNotify) retry_page_flip_data_free);
|
||||
dispatch_page_flip_datas (&impl_device_simple->posted_page_flip_datas,
|
||||
(GFunc) meta_kms_page_flip_data_discard_in_impl,
|
||||
NULL);
|
||||
dispatch_page_flip_datas (&impl_device_simple->postponed_page_flip_datas,
|
||||
(GFunc) meta_kms_page_flip_data_discard_in_impl,
|
||||
NULL);
|
||||
(GFunc) dispose_page_flip_data,
|
||||
impl_device);
|
||||
dispatch_page_flip_datas (&impl_device_simple->postponed_mode_set_fallback_datas,
|
||||
(GFunc) meta_kms_page_flip_data_discard_in_impl,
|
||||
NULL);
|
||||
(GFunc) dispose_page_flip_data,
|
||||
impl_device);
|
||||
|
||||
g_assert (!impl_device_simple->posted_page_flip_datas);
|
||||
|
||||
@ -1548,7 +1560,6 @@ meta_kms_impl_device_simple_open_device_file (MetaKmsImplDevice *impl_device,
|
||||
MetaDevicePool *device_pool =
|
||||
meta_backend_native_get_device_pool (META_BACKEND_NATIVE (backend));
|
||||
g_autoptr (MetaDeviceFile) device_file = NULL;
|
||||
int fd;
|
||||
|
||||
device_file = meta_device_pool_open (device_pool, path,
|
||||
META_DEVICE_FILE_FLAG_TAKE_CONTROL,
|
||||
@ -1556,13 +1567,26 @@ meta_kms_impl_device_simple_open_device_file (MetaKmsImplDevice *impl_device,
|
||||
if (!device_file)
|
||||
return NULL;
|
||||
|
||||
fd = meta_device_file_get_fd (device_file);
|
||||
|
||||
if (drmSetClientCap (fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1) != 0)
|
||||
if (!meta_device_file_has_tag (device_file,
|
||||
META_DEVICE_FILE_TAG_KMS,
|
||||
META_KMS_DEVICE_FILE_TAG_SIMPLE))
|
||||
{
|
||||
g_set_error (error, META_KMS_ERROR, META_KMS_ERROR_NOT_SUPPORTED,
|
||||
"DRM_CLIENT_CAP_UNIVERSAL_PLANES not supported");
|
||||
return NULL;
|
||||
int fd = meta_device_file_get_fd (device_file);
|
||||
|
||||
g_warn_if_fail (!meta_device_file_has_tag (device_file,
|
||||
META_DEVICE_FILE_TAG_KMS,
|
||||
META_KMS_DEVICE_FILE_TAG_ATOMIC));
|
||||
|
||||
if (drmSetClientCap (fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1) != 0)
|
||||
{
|
||||
g_set_error (error, META_KMS_ERROR, META_KMS_ERROR_NOT_SUPPORTED,
|
||||
"DRM_CLIENT_CAP_UNIVERSAL_PLANES not supported");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
meta_device_file_tag (device_file,
|
||||
META_DEVICE_FILE_TAG_KMS,
|
||||
META_KMS_DEVICE_FILE_TAG_SIMPLE);
|
||||
}
|
||||
|
||||
return g_steal_pointer (&device_file);
|
||||
|
@ -36,7 +36,7 @@
|
||||
#include "backends/native/meta-kms-plane-private.h"
|
||||
#include "backends/native/meta-kms-plane.h"
|
||||
#include "backends/native/meta-kms-private.h"
|
||||
#include "backends/native/meta-kms-update.h"
|
||||
#include "backends/native/meta-kms-update-private.h"
|
||||
|
||||
#include "meta-default-modes.h"
|
||||
#include "meta-private-enum-types.h"
|
||||
@ -60,10 +60,12 @@ typedef struct _MetaKmsImplDevicePrivate
|
||||
MetaKmsDevice *device;
|
||||
MetaKmsImpl *impl;
|
||||
|
||||
int fd_hold_count;
|
||||
MetaDeviceFile *device_file;
|
||||
GSource *fd_source;
|
||||
char *path;
|
||||
MetaKmsDeviceFlag flags;
|
||||
gboolean has_latched_fd_hold;
|
||||
|
||||
char *driver_name;
|
||||
char *driver_description;
|
||||
@ -619,11 +621,81 @@ init_fallback_modes (MetaKmsImplDevice *impl_device)
|
||||
priv->fallback_modes = g_list_reverse (modes);
|
||||
}
|
||||
|
||||
static MetaDeviceFile *
|
||||
meta_kms_impl_device_open_device_file (MetaKmsImplDevice *impl_device,
|
||||
const char *path,
|
||||
GError **error)
|
||||
{
|
||||
MetaKmsImplDevicePrivate *priv =
|
||||
meta_kms_impl_device_get_instance_private (impl_device);
|
||||
MetaKmsImplDeviceClass *klass = META_KMS_IMPL_DEVICE_GET_CLASS (impl_device);
|
||||
|
||||
return klass->open_device_file (impl_device, priv->path, error);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ensure_device_file (MetaKmsImplDevice *impl_device,
|
||||
GError **error)
|
||||
{
|
||||
MetaKmsImplDevicePrivate *priv =
|
||||
meta_kms_impl_device_get_instance_private (impl_device);
|
||||
MetaDeviceFile *device_file;
|
||||
|
||||
if (priv->device_file)
|
||||
return TRUE;
|
||||
|
||||
device_file = meta_kms_impl_device_open_device_file (impl_device,
|
||||
priv->path,
|
||||
error);
|
||||
if (!device_file)
|
||||
return FALSE;
|
||||
|
||||
priv->device_file = device_file;
|
||||
|
||||
if (!(priv->flags & META_KMS_DEVICE_FLAG_NO_MODE_SETTING))
|
||||
{
|
||||
priv->fd_source =
|
||||
meta_kms_register_fd_in_impl (meta_kms_impl_get_kms (priv->impl),
|
||||
meta_device_file_get_fd (device_file),
|
||||
kms_event_dispatch_in_impl,
|
||||
impl_device);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
ensure_latched_fd_hold (MetaKmsImplDevice *impl_device)
|
||||
{
|
||||
MetaKmsImplDevicePrivate *priv =
|
||||
meta_kms_impl_device_get_instance_private (impl_device);
|
||||
|
||||
if (!priv->has_latched_fd_hold)
|
||||
{
|
||||
meta_kms_impl_device_hold_fd (impl_device);
|
||||
priv->has_latched_fd_hold = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clear_latched_fd_hold (MetaKmsImplDevice *impl_device)
|
||||
{
|
||||
MetaKmsImplDevicePrivate *priv =
|
||||
meta_kms_impl_device_get_instance_private (impl_device);
|
||||
|
||||
if (priv->has_latched_fd_hold)
|
||||
{
|
||||
meta_kms_impl_device_unhold_fd (impl_device);
|
||||
priv->has_latched_fd_hold = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_kms_impl_device_update_states (MetaKmsImplDevice *impl_device)
|
||||
{
|
||||
MetaKmsImplDevicePrivate *priv =
|
||||
meta_kms_impl_device_get_instance_private (impl_device);
|
||||
g_autoptr (GError) error = NULL;
|
||||
int fd;
|
||||
drmModeRes *drm_resources;
|
||||
|
||||
@ -631,17 +703,21 @@ meta_kms_impl_device_update_states (MetaKmsImplDevice *impl_device)
|
||||
|
||||
meta_topic (META_DEBUG_KMS, "Updating device state for %s", priv->path);
|
||||
|
||||
if (!ensure_device_file (impl_device, &error))
|
||||
{
|
||||
g_warning ("Failed to reopen '%s': %s", priv->path, error->message);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ensure_latched_fd_hold (impl_device);
|
||||
|
||||
fd = meta_device_file_get_fd (priv->device_file);
|
||||
drm_resources = drmModeGetResources (fd);
|
||||
if (!drm_resources)
|
||||
{
|
||||
g_list_free_full (priv->planes, g_object_unref);
|
||||
g_list_free_full (priv->crtcs, g_object_unref);
|
||||
g_list_free_full (priv->connectors, g_object_unref);
|
||||
priv->planes = NULL;
|
||||
priv->crtcs = NULL;
|
||||
priv->connectors = NULL;
|
||||
return;
|
||||
meta_topic (META_DEBUG_KMS, "Device '%s' didn't return any resources",
|
||||
priv->path);
|
||||
goto err;
|
||||
}
|
||||
|
||||
update_connectors (impl_device, drm_resources);
|
||||
@ -651,6 +727,13 @@ meta_kms_impl_device_update_states (MetaKmsImplDevice *impl_device)
|
||||
g_list_foreach (priv->connectors, (GFunc) meta_kms_connector_update_state,
|
||||
drm_resources);
|
||||
drmModeFreeResources (drm_resources);
|
||||
|
||||
return;
|
||||
|
||||
err:
|
||||
g_clear_list (&priv->planes, g_object_unref);
|
||||
g_clear_list (&priv->crtcs, g_object_unref);
|
||||
g_clear_list (&priv->connectors, g_object_unref);
|
||||
}
|
||||
|
||||
void
|
||||
@ -666,6 +749,12 @@ meta_kms_impl_device_predict_states (MetaKmsImplDevice *impl_device,
|
||||
update);
|
||||
}
|
||||
|
||||
void
|
||||
meta_kms_impl_device_notify_modes_set (MetaKmsImplDevice *impl_device)
|
||||
{
|
||||
clear_latched_fd_hold (impl_device);
|
||||
}
|
||||
|
||||
int
|
||||
meta_kms_impl_device_get_fd (MetaKmsImplDevice *impl_device)
|
||||
{
|
||||
@ -683,8 +772,17 @@ meta_kms_impl_device_process_update (MetaKmsImplDevice *impl_device,
|
||||
MetaKmsUpdateFlag flags)
|
||||
{
|
||||
MetaKmsImplDeviceClass *klass = META_KMS_IMPL_DEVICE_GET_CLASS (impl_device);
|
||||
MetaKmsFeedback *feedback;
|
||||
g_autoptr (GError) error = NULL;
|
||||
|
||||
return klass->process_update (impl_device, update, flags);
|
||||
if (!ensure_device_file (impl_device, &error))
|
||||
return meta_kms_feedback_new_failed (NULL, g_steal_pointer (&error));
|
||||
|
||||
meta_kms_impl_device_hold_fd (impl_device);
|
||||
feedback = klass->process_update (impl_device, update, flags);
|
||||
meta_kms_impl_device_unhold_fd (impl_device);
|
||||
|
||||
return feedback;
|
||||
}
|
||||
|
||||
void
|
||||
@ -704,6 +802,44 @@ meta_kms_impl_device_discard_pending_page_flips (MetaKmsImplDevice *impl_device)
|
||||
klass->discard_pending_page_flips (impl_device);
|
||||
}
|
||||
|
||||
void
|
||||
meta_kms_impl_device_hold_fd (MetaKmsImplDevice *impl_device)
|
||||
{
|
||||
MetaKmsImplDevicePrivate *priv =
|
||||
meta_kms_impl_device_get_instance_private (impl_device);
|
||||
MetaKms *kms = meta_kms_device_get_kms (priv->device);
|
||||
|
||||
meta_assert_in_kms_impl (kms);
|
||||
|
||||
g_assert (priv->device_file);
|
||||
|
||||
priv->fd_hold_count++;
|
||||
}
|
||||
|
||||
void
|
||||
meta_kms_impl_device_unhold_fd (MetaKmsImplDevice *impl_device)
|
||||
{
|
||||
MetaKmsImplDevicePrivate *priv =
|
||||
meta_kms_impl_device_get_instance_private (impl_device);
|
||||
MetaKms *kms = meta_kms_device_get_kms (priv->device);
|
||||
|
||||
meta_assert_in_kms_impl (kms);
|
||||
|
||||
g_return_if_fail (priv->fd_hold_count > 0);
|
||||
|
||||
priv->fd_hold_count--;
|
||||
if (priv->fd_hold_count == 0)
|
||||
{
|
||||
g_clear_pointer (&priv->device_file, meta_device_file_release);
|
||||
|
||||
if (priv->fd_source)
|
||||
{
|
||||
g_source_destroy (priv->fd_source);
|
||||
g_clear_pointer (&priv->fd_source, g_source_unref);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_kms_impl_device_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
@ -776,7 +912,8 @@ meta_kms_impl_device_finalize (GObject *object)
|
||||
g_list_free_full (priv->fallback_modes,
|
||||
(GDestroyNotify) meta_kms_mode_free);
|
||||
|
||||
g_clear_pointer (&priv->device_file, meta_device_file_release);
|
||||
clear_latched_fd_hold (impl_device);
|
||||
g_warn_if_fail (!priv->device_file);
|
||||
|
||||
g_free (priv->driver_name);
|
||||
g_free (priv->driver_description);
|
||||
@ -816,12 +953,6 @@ meta_kms_impl_device_init_mode_setting (MetaKmsImplDevice *impl_device,
|
||||
|
||||
drmModeFreeResources (drm_resources);
|
||||
|
||||
priv->fd_source =
|
||||
meta_kms_register_fd_in_impl (meta_kms_impl_get_kms (priv->impl),
|
||||
fd,
|
||||
kms_event_dispatch_in_impl,
|
||||
impl_device);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -862,13 +993,13 @@ meta_kms_impl_device_initable_init (GInitable *initable,
|
||||
MetaKmsImplDevice *impl_device = META_KMS_IMPL_DEVICE (initable);
|
||||
MetaKmsImplDevicePrivate *priv =
|
||||
meta_kms_impl_device_get_instance_private (impl_device);
|
||||
MetaKmsImplDeviceClass *klass = META_KMS_IMPL_DEVICE_GET_CLASS (impl_device);
|
||||
int fd;
|
||||
|
||||
priv->device_file = klass->open_device_file (impl_device, priv->path, error);
|
||||
if (!priv->device_file)
|
||||
if (!ensure_device_file (impl_device, error))
|
||||
return FALSE;
|
||||
|
||||
ensure_latched_fd_hold (impl_device);
|
||||
|
||||
g_clear_pointer (&priv->path, g_free);
|
||||
priv->path = g_strdup (meta_device_file_get_path (priv->device_file));
|
||||
|
||||
|
@ -87,6 +87,12 @@ enum
|
||||
META_KMS_ERROR_NOT_SUPPORTED,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
META_KMS_DEVICE_FILE_TAG_ATOMIC = 1 << 0,
|
||||
META_KMS_DEVICE_FILE_TAG_SIMPLE = 1 << 1,
|
||||
};
|
||||
|
||||
#define META_KMS_ERROR meta_kms_error_quark ()
|
||||
GQuark meta_kms_error_quark (void);
|
||||
|
||||
@ -124,11 +130,17 @@ drmModePropertyPtr meta_kms_impl_device_find_property (MetaKmsImplDevice *
|
||||
|
||||
int meta_kms_impl_device_get_fd (MetaKmsImplDevice *impl_device);
|
||||
|
||||
void meta_kms_impl_device_hold_fd (MetaKmsImplDevice *impl_device);
|
||||
|
||||
void meta_kms_impl_device_unhold_fd (MetaKmsImplDevice *impl_device);
|
||||
|
||||
void meta_kms_impl_device_update_states (MetaKmsImplDevice *impl_device);
|
||||
|
||||
void meta_kms_impl_device_predict_states (MetaKmsImplDevice *impl_device,
|
||||
MetaKmsUpdate *update);
|
||||
|
||||
void meta_kms_impl_device_notify_modes_set (MetaKmsImplDevice *impl_device);
|
||||
|
||||
MetaKmsPlane * meta_kms_impl_device_add_fake_plane (MetaKmsImplDevice *impl_device,
|
||||
MetaKmsPlaneType plane_type,
|
||||
MetaKmsCrtc *crtc);
|
||||
|
@ -119,6 +119,16 @@ meta_kms_impl_prepare_shutdown (MetaKmsImpl *impl)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_kms_impl_notify_modes_set (MetaKmsImpl *impl)
|
||||
{
|
||||
MetaKmsImplPrivate *priv = meta_kms_impl_get_instance_private (impl);
|
||||
|
||||
g_list_foreach (priv->impl_devices,
|
||||
(GFunc) meta_kms_impl_device_notify_modes_set,
|
||||
NULL);
|
||||
}
|
||||
|
||||
MetaKmsImpl *
|
||||
meta_kms_impl_new (MetaKms *kms)
|
||||
{
|
||||
|
@ -45,6 +45,8 @@ void meta_kms_impl_discard_pending_page_flips (MetaKmsImpl *impl);
|
||||
|
||||
void meta_kms_impl_prepare_shutdown (MetaKmsImpl *impl);
|
||||
|
||||
void meta_kms_impl_notify_modes_set (MetaKmsImpl *impl);
|
||||
|
||||
MetaKmsImpl * meta_kms_impl_new (MetaKms *kms);
|
||||
|
||||
#endif /* META_KMS_IMPL_H */
|
||||
|
@ -345,6 +345,24 @@ meta_kms_discard_pending_page_flips (MetaKms *kms)
|
||||
NULL);
|
||||
}
|
||||
|
||||
static gpointer
|
||||
meta_kms_notify_modes_set_in_impl (MetaKmsImpl *impl,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
meta_kms_impl_notify_modes_set (impl);
|
||||
return GINT_TO_POINTER (TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
meta_kms_notify_modes_set (MetaKms *kms)
|
||||
{
|
||||
meta_kms_run_impl_task_sync (kms,
|
||||
meta_kms_notify_modes_set_in_impl,
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_kms_callback_data_free (MetaKmsCallbackData *callback_data)
|
||||
{
|
||||
|
@ -52,6 +52,8 @@ MetaKmsFeedback * meta_kms_post_pending_update_sync (MetaKms *kms,
|
||||
|
||||
void meta_kms_discard_pending_page_flips (MetaKms *kms);
|
||||
|
||||
void meta_kms_notify_modes_set (MetaKms *kms);
|
||||
|
||||
MetaBackend * meta_kms_get_backend (MetaKms *kms);
|
||||
|
||||
GList * meta_kms_get_devices (MetaKms *kms);
|
||||
|
@ -102,6 +102,11 @@ G_DEFINE_TYPE_WITH_CODE (MetaRendererNative,
|
||||
static const CoglWinsysEGLVtable _cogl_winsys_egl_vtable;
|
||||
static const CoglWinsysVtable *parent_vtable;
|
||||
|
||||
static gboolean
|
||||
meta_renderer_native_ensure_gpu_data (MetaRendererNative *renderer_native,
|
||||
MetaGpuKms *gpu_kms,
|
||||
GError **error);
|
||||
|
||||
static void
|
||||
meta_renderer_native_queue_modes_reset (MetaRendererNative *renderer_native);
|
||||
|
||||
@ -625,6 +630,44 @@ clear_kept_alive_onscreens (MetaRendererNative *renderer_native)
|
||||
g_object_unref);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_gpu_unused (gpointer key,
|
||||
gpointer value,
|
||||
gpointer user_data)
|
||||
{
|
||||
GHashTable *used_gpus = user_data;
|
||||
|
||||
return !g_hash_table_contains (used_gpus, key);
|
||||
}
|
||||
|
||||
static void
|
||||
free_unused_gpu_datas (MetaRendererNative *renderer_native)
|
||||
{
|
||||
MetaRenderer *renderer = META_RENDERER (renderer_native);
|
||||
g_autoptr (GHashTable) used_gpus = NULL;
|
||||
GList *l;
|
||||
|
||||
used_gpus = g_hash_table_new (NULL, NULL);
|
||||
g_hash_table_add (used_gpus, renderer_native->primary_gpu_kms);
|
||||
|
||||
for (l = meta_renderer_get_views (renderer); l; l = l->next)
|
||||
{
|
||||
MetaRendererView *view = l->data;
|
||||
MetaCrtc *crtc = meta_renderer_view_get_crtc (view);
|
||||
MetaGpu *gpu;
|
||||
|
||||
gpu = meta_crtc_get_gpu (crtc);
|
||||
if (!gpu)
|
||||
continue;
|
||||
|
||||
g_hash_table_add (used_gpus, gpu);
|
||||
}
|
||||
|
||||
g_hash_table_foreach_remove (renderer_native->gpu_datas,
|
||||
is_gpu_unused,
|
||||
used_gpus);
|
||||
}
|
||||
|
||||
void
|
||||
meta_renderer_native_post_mode_set_updates (MetaRendererNative *renderer_native)
|
||||
{
|
||||
@ -665,6 +708,10 @@ meta_renderer_native_post_mode_set_updates (MetaRendererNative *renderer_native)
|
||||
}
|
||||
|
||||
clear_kept_alive_onscreens (renderer_native);
|
||||
|
||||
meta_kms_notify_modes_set (kms);
|
||||
|
||||
free_unused_gpu_datas (renderer_native);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1061,21 +1108,15 @@ meta_renderer_native_create_view (MetaRenderer *renderer,
|
||||
if (META_IS_CRTC_KMS (crtc))
|
||||
{
|
||||
MetaGpuKms *gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc));
|
||||
MetaGpuKms *primary_gpu_kms = renderer_native->primary_gpu_kms;
|
||||
MetaOnscreenNative *onscreen_native;
|
||||
|
||||
onscreen_native = meta_onscreen_native_new (renderer_native,
|
||||
primary_gpu_kms,
|
||||
output,
|
||||
crtc,
|
||||
cogl_context,
|
||||
onscreen_width,
|
||||
onscreen_height);
|
||||
|
||||
if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (onscreen_native), &error))
|
||||
if (!meta_renderer_native_ensure_gpu_data (renderer_native,
|
||||
gpu_kms,
|
||||
&error))
|
||||
{
|
||||
g_warning ("Failed to allocate onscreen framebuffer for %s",
|
||||
meta_gpu_kms_get_file_path (gpu_kms));
|
||||
g_warning ("Failed to create secondary GPU data for %s",
|
||||
meta_gpu_kms_get_file_path (gpu_kms));
|
||||
use_shadowfb = FALSE;
|
||||
framebuffer = create_fallback_offscreen (renderer_native,
|
||||
cogl_context,
|
||||
onscreen_width,
|
||||
@ -1083,9 +1124,32 @@ meta_renderer_native_create_view (MetaRenderer *renderer,
|
||||
}
|
||||
else
|
||||
{
|
||||
use_shadowfb = should_force_shadow_fb (renderer_native,
|
||||
primary_gpu_kms);
|
||||
framebuffer = COGL_FRAMEBUFFER (onscreen_native);
|
||||
MetaGpuKms *primary_gpu_kms = renderer_native->primary_gpu_kms;
|
||||
|
||||
onscreen_native = meta_onscreen_native_new (renderer_native,
|
||||
primary_gpu_kms,
|
||||
output,
|
||||
crtc,
|
||||
cogl_context,
|
||||
onscreen_width,
|
||||
onscreen_height);
|
||||
|
||||
if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (onscreen_native), &error))
|
||||
{
|
||||
g_warning ("Failed to allocate onscreen framebuffer for %s",
|
||||
meta_gpu_kms_get_file_path (gpu_kms));
|
||||
use_shadowfb = FALSE;
|
||||
framebuffer = create_fallback_offscreen (renderer_native,
|
||||
cogl_context,
|
||||
onscreen_width,
|
||||
onscreen_height);
|
||||
}
|
||||
else
|
||||
{
|
||||
use_shadowfb = should_force_shadow_fb (renderer_native,
|
||||
primary_gpu_kms);
|
||||
framebuffer = COGL_FRAMEBUFFER (onscreen_native);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -1331,6 +1395,22 @@ meta_renderer_native_ensure_gles3 (MetaRendererNative *renderer_native)
|
||||
renderer_native->gles3 = meta_gles3_new (egl);
|
||||
}
|
||||
|
||||
static void
|
||||
maybe_restore_cogl_egl_api (MetaRendererNative *renderer_native)
|
||||
{
|
||||
CoglContext *cogl_context;
|
||||
CoglDisplay *cogl_display;
|
||||
CoglRenderer *cogl_renderer;
|
||||
|
||||
cogl_context = cogl_context_from_renderer_native (renderer_native);
|
||||
if (!cogl_context)
|
||||
return;
|
||||
|
||||
cogl_display = cogl_context_get_display (cogl_context);
|
||||
cogl_renderer = cogl_display_get_renderer (cogl_display);
|
||||
cogl_renderer_bind_api (cogl_renderer);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
init_secondary_gpu_data_gpu (MetaRendererNativeGpuData *renderer_gpu_data,
|
||||
GError **error)
|
||||
@ -1343,13 +1423,15 @@ init_secondary_gpu_data_gpu (MetaRendererNativeGpuData *renderer_gpu_data,
|
||||
const char **missing_gl_extensions;
|
||||
const char *renderer_str;
|
||||
|
||||
meta_egl_bind_api (egl, EGL_OPENGL_ES_API, NULL);
|
||||
|
||||
if (!create_secondary_egl_config (egl, renderer_gpu_data->mode, egl_display,
|
||||
&egl_config, error))
|
||||
return FALSE;
|
||||
goto err;
|
||||
|
||||
egl_context = create_secondary_egl_context (egl, egl_display, egl_config, error);
|
||||
if (egl_context == EGL_NO_CONTEXT)
|
||||
return FALSE;
|
||||
goto err;
|
||||
|
||||
meta_renderer_native_ensure_gles3 (renderer_native);
|
||||
|
||||
@ -1361,7 +1443,7 @@ init_secondary_gpu_data_gpu (MetaRendererNativeGpuData *renderer_gpu_data,
|
||||
error))
|
||||
{
|
||||
meta_egl_destroy_context (egl, egl_display, egl_context, NULL);
|
||||
return FALSE;
|
||||
goto err;
|
||||
}
|
||||
|
||||
renderer_str = (const char *) glGetString (GL_RENDERER);
|
||||
@ -1372,7 +1454,7 @@ init_secondary_gpu_data_gpu (MetaRendererNativeGpuData *renderer_gpu_data,
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Do not want to use software renderer (%s), falling back to CPU copy path",
|
||||
renderer_str);
|
||||
goto out_fail_with_context;
|
||||
goto err_fail_with_context;
|
||||
}
|
||||
|
||||
if (!meta_gles3_has_extensions (renderer_native->gles3,
|
||||
@ -1390,7 +1472,7 @@ init_secondary_gpu_data_gpu (MetaRendererNativeGpuData *renderer_gpu_data,
|
||||
g_free (missing_gl_extensions_str);
|
||||
g_free (missing_gl_extensions);
|
||||
|
||||
goto out_fail_with_context;
|
||||
goto err_fail_with_context;
|
||||
}
|
||||
|
||||
renderer_gpu_data->secondary.is_hardware_rendering = TRUE;
|
||||
@ -1403,9 +1485,11 @@ init_secondary_gpu_data_gpu (MetaRendererNativeGpuData *renderer_gpu_data,
|
||||
"EGL_EXT_image_dma_buf_import_modifiers",
|
||||
NULL);
|
||||
|
||||
maybe_restore_cogl_egl_api (renderer_native);
|
||||
|
||||
return TRUE;
|
||||
|
||||
out_fail_with_context:
|
||||
err_fail_with_context:
|
||||
meta_egl_make_current (egl,
|
||||
egl_display,
|
||||
EGL_NO_SURFACE,
|
||||
@ -1414,6 +1498,9 @@ out_fail_with_context:
|
||||
NULL);
|
||||
meta_egl_destroy_context (egl, egl_display, egl_context, NULL);
|
||||
|
||||
err:
|
||||
maybe_restore_cogl_egl_api (renderer_native);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -1874,6 +1961,20 @@ create_renderer_gpu_data (MetaRendererNative *renderer_native,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_renderer_native_ensure_gpu_data (MetaRendererNative *renderer_native,
|
||||
MetaGpuKms *gpu_kms,
|
||||
GError **error)
|
||||
{
|
||||
MetaRendererNativeGpuData *renderer_gpu_data;
|
||||
|
||||
renderer_gpu_data = g_hash_table_lookup (renderer_native->gpu_datas, gpu_kms);
|
||||
if (renderer_gpu_data)
|
||||
return TRUE;
|
||||
|
||||
return create_renderer_gpu_data (renderer_native, gpu_kms, error);
|
||||
}
|
||||
|
||||
static void
|
||||
on_gpu_added (MetaBackendNative *backend_native,
|
||||
MetaGpuKms *gpu_kms,
|
||||
|
Loading…
Reference in New Issue
Block a user