gpu/kms: Init global mode list from MetaKmsConnectors

Instead of iterating over the available drmModeConnector objects to
construct a GPU wide mode list, use the state managed by
MetaKmsConnector. This also removes the last user of drmModeRes from
MetaGpuKms.

https://gitlab.gnome.org/GNOME/mutter/issues/548
https://gitlab.gnome.org/GNOME/mutter/merge_requests/525
This commit is contained in:
Jonas Ådahl 2019-03-09 17:24:20 +01:00 committed by Georges Basile Stavracas Neto
parent f2d9a11013
commit aba689312f
2 changed files with 27 additions and 117 deletions

View File

@ -72,9 +72,6 @@ struct _MetaGpuKms
clockid_t clock_id; clockid_t clock_id;
drmModeConnector **connectors;
unsigned int n_connectors;
gboolean resources_init_failed_before; gboolean resources_init_failed_before;
}; };
@ -445,17 +442,6 @@ meta_gpu_kms_is_platform_device (MetaGpuKms *gpu_kms)
return !!(flags & META_KMS_DEVICE_FLAG_PLATFORM_DEVICE); return !!(flags & META_KMS_DEVICE_FLAG_PLATFORM_DEVICE);
} }
static void
free_resources (MetaGpuKms *gpu_kms)
{
unsigned i;
for (i = 0; i < gpu_kms->n_connectors; i++)
drmModeFreeConnector (gpu_kms->connectors[i]);
g_free (gpu_kms->connectors);
}
static int static int
compare_outputs (gconstpointer one, compare_outputs (gconstpointer one,
gconstpointer two) gconstpointer two)
@ -616,51 +602,32 @@ setup_output_clones (MetaGpu *gpu)
} }
static void static void
init_connectors (MetaGpuKms *gpu_kms, init_modes (MetaGpuKms *gpu_kms)
drmModeRes *resources)
{
unsigned int i;
gpu_kms->n_connectors = resources->count_connectors;
gpu_kms->connectors = g_new (drmModeConnector *, gpu_kms->n_connectors);
for (i = 0; i < gpu_kms->n_connectors; i++)
{
drmModeConnector *drm_connector;
drm_connector = drmModeGetConnector (gpu_kms->fd,
resources->connectors[i]);
gpu_kms->connectors[i] = drm_connector;
}
}
static void
init_modes (MetaGpuKms *gpu_kms,
drmModeRes *resources)
{ {
MetaGpu *gpu = META_GPU (gpu_kms); MetaGpu *gpu = META_GPU (gpu_kms);
GHashTable *modes_table; GHashTable *modes_table;
GList *l;
GList *modes; GList *modes;
GHashTableIter iter; GHashTableIter iter;
drmModeModeInfo *drm_mode; drmModeModeInfo *drm_mode;
unsigned int i; int i;
long mode_id; long mode_id;
/* /*
* Gather all modes on all connected connectors. * Gather all modes on all connected connectors.
*/ */
modes_table = g_hash_table_new (drm_mode_hash, (GEqualFunc) meta_drm_mode_equal); modes_table = g_hash_table_new (drm_mode_hash, (GEqualFunc) meta_drm_mode_equal);
for (i = 0; i < gpu_kms->n_connectors; i++) for (l = meta_kms_device_get_connectors (gpu_kms->kms_device); l; l = l->next)
{ {
drmModeConnector *drm_connector; MetaKmsConnector *kms_connector = l->data;
const MetaKmsConnectorState *state;
drm_connector = gpu_kms->connectors[i]; state = meta_kms_connector_get_current_state (kms_connector);
if (drm_connector && drm_connector->connection == DRM_MODE_CONNECTED) if (!state)
{ continue;
unsigned int j;
for (j = 0; j < (unsigned int) drm_connector->count_modes; j++) for (i = 0; i < state->n_modes; i++)
g_hash_table_add (modes_table, &drm_connector->modes[j]); g_hash_table_add (modes_table, &state->modes[i]);
}
} }
modes = NULL; modes = NULL;
@ -742,23 +709,23 @@ init_outputs (MetaGpuKms *gpu_kms)
MetaGpu *gpu = META_GPU (gpu_kms); MetaGpu *gpu = META_GPU (gpu_kms);
GList *old_outputs; GList *old_outputs;
GList *outputs; GList *outputs;
unsigned int i;
GList *l; GList *l;
old_outputs = meta_gpu_get_outputs (gpu); old_outputs = meta_gpu_get_outputs (gpu);
outputs = NULL; outputs = NULL;
i = 0;
for (l = meta_kms_device_get_connectors (gpu_kms->kms_device); l; l = l->next) for (l = meta_kms_device_get_connectors (gpu_kms->kms_device); l; l = l->next)
{ {
MetaKmsConnector *kms_connector = l->data; MetaKmsConnector *kms_connector = l->data;
MetaOutput *output; MetaOutput *output;
MetaOutput *old_output; MetaOutput *old_output;
GError *error = NULL; GError *error = NULL;
uint32_t connector_id;
drmModeConnector *connector; drmModeConnector *connector;
connector = gpu_kms->connectors[i++]; connector_id = meta_kms_connector_get_id (kms_connector);
connector = drmModeGetConnector (gpu_kms->fd, connector_id);
if (!connector || connector->connection != DRM_MODE_CONNECTED) if (!connector || connector->connection != DRM_MODE_CONNECTED)
continue; continue;
@ -790,88 +757,40 @@ init_outputs (MetaGpuKms *gpu_kms)
setup_output_clones (gpu); setup_output_clones (gpu);
} }
static gboolean
meta_kms_resources_init (MetaKmsResources *resources,
int fd,
GError **error)
{
drmModeRes *drm_resources;
unsigned int i;
drm_resources = drmModeGetResources (fd);
if (!drm_resources)
{
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_FAILED,
"Calling drmModeGetResources() failed");
return FALSE;
}
resources->resources = drm_resources;
resources->n_encoders = (unsigned int) drm_resources->count_encoders;
resources->encoders = g_new (drmModeEncoder *, resources->n_encoders);
for (i = 0; i < resources->n_encoders; i++)
resources->encoders[i] = drmModeGetEncoder (fd, drm_resources->encoders[i]);
return TRUE;
}
static void
meta_kms_resources_release (MetaKmsResources *resources)
{
unsigned int i;
for (i = 0; i < resources->n_encoders; i++)
drmModeFreeEncoder (resources->encoders[i]);
g_free (resources->encoders);
g_clear_pointer (&resources->resources, drmModeFreeResources);
}
static gboolean static gboolean
meta_gpu_kms_read_current (MetaGpu *gpu, meta_gpu_kms_read_current (MetaGpu *gpu,
GError **error) GError **error)
{ {
MetaGpuKms *gpu_kms = META_GPU_KMS (gpu); MetaGpuKms *gpu_kms = META_GPU_KMS (gpu);
MetaKmsResources resources;
g_autoptr (GError) local_error = NULL;
if (!meta_kms_resources_init (&resources, gpu_kms->fd, &local_error))
{
if (!gpu_kms->resources_init_failed_before)
{
g_warning ("meta_kms_resources_init failed: %s, assuming we have no outputs",
local_error->message);
gpu_kms->resources_init_failed_before = TRUE;
}
return TRUE;
}
/* Note: we must not free the public structures (output, crtc, monitor /* Note: we must not free the public structures (output, crtc, monitor
mode and monitor info) here, they must be kept alive until the API mode and monitor info) here, they must be kept alive until the API
users are done with them after we emit monitors-changed, and thus users are done with them after we emit monitors-changed, and thus
are freed by the platform-independent layer. */ are freed by the platform-independent layer. */
free_resources (gpu_kms);
init_connectors (gpu_kms, resources.resources); init_modes (gpu_kms);
init_modes (gpu_kms, resources.resources);
init_crtcs (gpu_kms); init_crtcs (gpu_kms);
init_outputs (gpu_kms); init_outputs (gpu_kms);
init_frame_clock (gpu_kms); init_frame_clock (gpu_kms);
meta_kms_resources_release (&resources);
return TRUE; return TRUE;
} }
gboolean gboolean
meta_gpu_kms_can_have_outputs (MetaGpuKms *gpu_kms) meta_gpu_kms_can_have_outputs (MetaGpuKms *gpu_kms)
{ {
return gpu_kms->n_connectors > 0; GList *l;
int n_connected_connectors = 0;
for (l = meta_kms_device_get_connectors (gpu_kms->kms_device); l; l = l->next)
{
MetaKmsConnector *kms_connector = l->data;
if (meta_kms_connector_get_current_state (kms_connector))
n_connected_connectors++;
}
return n_connected_connectors > 0;
} }
MetaGpuKms * MetaGpuKms *
@ -915,8 +834,6 @@ meta_gpu_kms_finalize (GObject *object)
g_source_destroy (gpu_kms->source); g_source_destroy (gpu_kms->source);
free_resources (gpu_kms);
G_OBJECT_CLASS (meta_gpu_kms_parent_class)->finalize (object); G_OBJECT_CLASS (meta_gpu_kms_parent_class)->finalize (object);
} }

View File

@ -35,13 +35,6 @@ G_DECLARE_FINAL_TYPE (MetaGpuKms, meta_gpu_kms, META, GPU_KMS, MetaGpu)
typedef struct _MetaGpuKmsFlipClosureContainer MetaGpuKmsFlipClosureContainer; typedef struct _MetaGpuKmsFlipClosureContainer MetaGpuKmsFlipClosureContainer;
typedef struct _MetaKmsResources
{
drmModeRes *resources;
drmModeEncoder **encoders;
unsigned int n_encoders;
} MetaKmsResources;
typedef void (*MetaKmsFlipCallback) (void *user_data); typedef void (*MetaKmsFlipCallback) (void *user_data);
MetaGpuKms * meta_gpu_kms_new (MetaBackendNative *backend_native, MetaGpuKms * meta_gpu_kms_new (MetaBackendNative *backend_native,