diff --git a/src/backends/native/meta-crtc-kms.c b/src/backends/native/meta-crtc-kms.c index 8ac7fb969..126621cc0 100644 --- a/src/backends/native/meta-crtc-kms.c +++ b/src/backends/native/meta-crtc-kms.c @@ -166,6 +166,14 @@ find_property_index (MetaGpu *gpu, return -1; } +MetaKmsCrtc * +meta_crtc_kms_get_kms_crtc (MetaCrtc *crtc) +{ + MetaCrtcKms *crtc_kms = crtc->driver_private; + + return crtc_kms->kms_crtc; +} + /** * meta_crtc_kms_get_modifiers: * @crtc: a #MetaCrtc object that has to be a #MetaCrtcKms diff --git a/src/backends/native/meta-crtc-kms.h b/src/backends/native/meta-crtc-kms.h index 3be1d5db8..609154fe7 100644 --- a/src/backends/native/meta-crtc-kms.h +++ b/src/backends/native/meta-crtc-kms.h @@ -45,6 +45,8 @@ gboolean meta_crtc_kms_is_transform_handled (MetaCrtc *crtc, void meta_crtc_kms_apply_transform (MetaCrtc *crtc); +MetaKmsCrtc * meta_crtc_kms_get_kms_crtc (MetaCrtc *crtc); + GArray * meta_crtc_kms_get_modifiers (MetaCrtc *crtc, uint32_t format); diff --git a/src/backends/native/meta-gpu-kms.c b/src/backends/native/meta-gpu-kms.c index 09b1c87d7..76b6f3857 100644 --- a/src/backends/native/meta-gpu-kms.c +++ b/src/backends/native/meta-gpu-kms.c @@ -737,8 +737,7 @@ init_frame_clock (MetaGpuKms *gpu_kms) } static void -init_outputs (MetaGpuKms *gpu_kms, - MetaKmsResources *resources) +init_outputs (MetaGpuKms *gpu_kms) { MetaGpu *gpu = META_GPU (gpu_kms); GList *old_outputs; @@ -770,7 +769,6 @@ init_outputs (MetaGpuKms *gpu_kms, output = meta_create_kms_output (gpu_kms, kms_connector, connector, - resources, old_output, &error); if (!output) @@ -862,7 +860,7 @@ meta_gpu_kms_read_current (MetaGpu *gpu, init_connectors (gpu_kms, resources.resources); init_modes (gpu_kms, resources.resources); init_crtcs (gpu_kms); - init_outputs (gpu_kms, &resources); + init_outputs (gpu_kms); init_frame_clock (gpu_kms); meta_kms_resources_release (&resources); diff --git a/src/backends/native/meta-kms-connector-private.h b/src/backends/native/meta-kms-connector-private.h index a9bca85ba..f61e96948 100644 --- a/src/backends/native/meta-kms-connector-private.h +++ b/src/backends/native/meta-kms-connector-private.h @@ -22,6 +22,9 @@ #include "backends/native/meta-kms-types.h" +void meta_kms_connector_update_state (MetaKmsConnector *connector, + drmModeRes *drm_resources); + MetaKmsConnector * meta_kms_connector_new (MetaKmsImplDevice *impl_device, drmModeConnector *drm_connector, drmModeRes *drm_resources); diff --git a/src/backends/native/meta-kms-connector.c b/src/backends/native/meta-kms-connector.c index 98b9a2f1b..bcd97e1c3 100644 --- a/src/backends/native/meta-kms-connector.c +++ b/src/backends/native/meta-kms-connector.c @@ -24,6 +24,7 @@ #include +#include "backends/native/meta-kms-device-private.h" #include "backends/native/meta-kms-impl-device.h" struct _MetaKmsConnector @@ -35,6 +36,8 @@ struct _MetaKmsConnector uint32_t id; MetaConnectorType type; char *name; + + MetaKmsConnectorState *current_state; }; G_DEFINE_TYPE (MetaKmsConnector, meta_kms_connector, G_TYPE_OBJECT) @@ -63,6 +66,377 @@ meta_kms_connector_get_name (MetaKmsConnector *connector) return connector->name; } +gboolean +meta_kms_connector_can_clone (MetaKmsConnector *connector, + MetaKmsConnector *other_connector) +{ + MetaKmsConnectorState *state = connector->current_state; + MetaKmsConnectorState *other_state = other_connector->current_state; + + if (state->common_possible_clones == 0 || + other_state->common_possible_clones == 0) + return FALSE; + + if (state->encoder_device_idxs != other_state->encoder_device_idxs) + return FALSE; + + return TRUE; +} + +const MetaKmsConnectorState * +meta_kms_connector_get_current_state (MetaKmsConnector *connector) +{ + return connector->current_state; +} + +static void +set_panel_orientation (MetaKmsConnectorState *state, + drmModePropertyPtr prop, + uint64_t orientation) +{ + const char *name; + + name = prop->enums[orientation].name; + if (strcmp (name, "Upside Down") == 0) + { + state->panel_orientation_transform = META_MONITOR_TRANSFORM_180; + } + else if (strcmp (name, "Left Side Up") == 0) + { + /* Left side up, rotate 90 degrees counter clockwise to correct */ + state->panel_orientation_transform = META_MONITOR_TRANSFORM_90; + } + else if (strcmp (name, "Right Side Up") == 0) + { + /* Right side up, rotate 270 degrees counter clockwise to correct */ + state->panel_orientation_transform = META_MONITOR_TRANSFORM_270; + } + else + { + state->panel_orientation_transform = META_MONITOR_TRANSFORM_NORMAL; + } +} + +static void +state_set_properties (MetaKmsConnectorState *state, + MetaKmsImplDevice *impl_device, + drmModeConnector *drm_connector) +{ + int fd; + int i; + + fd = meta_kms_impl_device_get_fd (impl_device); + + for (i = 0; i < drm_connector->count_props; i++) + { + drmModePropertyPtr prop; + + prop = drmModeGetProperty (fd, drm_connector->props[i]); + if (!prop) + continue; + + if ((prop->flags & DRM_MODE_PROP_RANGE) && + strcmp (prop->name, "suggested X") == 0) + state->suggested_x = drm_connector->prop_values[i]; + else if ((prop->flags & DRM_MODE_PROP_RANGE) && + strcmp (prop->name, "suggested Y") == 0) + state->suggested_y = drm_connector->prop_values[i]; + else if ((prop->flags & DRM_MODE_PROP_RANGE) && + strcmp (prop->name, "hotplug_mode_update") == 0) + state->hotplug_mode_update = drm_connector->prop_values[i]; + else if (strcmp (prop->name, "scaling mode") == 0) + state->has_scaling = TRUE; + else if ((prop->flags & DRM_MODE_PROP_ENUM) && + strcmp (prop->name, "panel orientation") == 0) + set_panel_orientation (state, prop, drm_connector->prop_values[i]); + + drmModeFreeProperty (prop); + } +} + +static CoglSubpixelOrder +drm_subpixel_order_to_cogl_subpixel_order (drmModeSubPixel subpixel) +{ + switch (subpixel) + { + case DRM_MODE_SUBPIXEL_NONE: + return COGL_SUBPIXEL_ORDER_NONE; + break; + case DRM_MODE_SUBPIXEL_HORIZONTAL_RGB: + return COGL_SUBPIXEL_ORDER_HORIZONTAL_RGB; + break; + case DRM_MODE_SUBPIXEL_HORIZONTAL_BGR: + return COGL_SUBPIXEL_ORDER_HORIZONTAL_BGR; + break; + case DRM_MODE_SUBPIXEL_VERTICAL_RGB: + return COGL_SUBPIXEL_ORDER_VERTICAL_RGB; + break; + case DRM_MODE_SUBPIXEL_VERTICAL_BGR: + return COGL_SUBPIXEL_ORDER_VERTICAL_BGR; + break; + case DRM_MODE_SUBPIXEL_UNKNOWN: + return COGL_SUBPIXEL_ORDER_UNKNOWN; + } + return COGL_SUBPIXEL_ORDER_UNKNOWN; +} + +static void +state_set_edid (MetaKmsConnectorState *state, + MetaKmsConnector *connector, + MetaKmsImplDevice *impl_device, + uint32_t blob_id) +{ + int fd; + drmModePropertyBlobPtr edid_blob; + GBytes *edid_data; + + fd = meta_kms_impl_device_get_fd (impl_device); + edid_blob = drmModeGetPropertyBlob (fd, blob_id); + if (!edid_blob) + { + g_warning ("Failed to read EDID of connector %s: %s", + connector->name, g_strerror (errno)); + return; + } + + edid_data = g_bytes_new (edid_blob->data, edid_blob->length); + drmModeFreePropertyBlob (edid_blob); + + state->edid_data = edid_data; +} + +static void +state_set_tile_info (MetaKmsConnectorState *state, + MetaKmsConnector *connector, + MetaKmsImplDevice *impl_device, + uint32_t blob_id) +{ + int fd; + drmModePropertyBlobPtr tile_blob; + + state->tile_info = (MetaTileInfo) { 0 }; + + fd = meta_kms_impl_device_get_fd (impl_device); + tile_blob = drmModeGetPropertyBlob (fd, blob_id); + if (!tile_blob) + { + g_warning ("Failed to read TILE of connector %s: %s", + connector->name, strerror (errno)); + return; + } + + if (tile_blob->length > 0) + { + if (sscanf ((char *) tile_blob->data, "%d:%d:%d:%d:%d:%d:%d:%d", + &state->tile_info.group_id, + &state->tile_info.flags, + &state->tile_info.max_h_tiles, + &state->tile_info.max_v_tiles, + &state->tile_info.loc_h_tile, + &state->tile_info.loc_v_tile, + &state->tile_info.tile_w, + &state->tile_info.tile_h) != 8) + { + g_warning ("Couldn't understand TILE property blob of connector %s", + connector->name); + state->tile_info = (MetaTileInfo) { 0 }; + } + } + + drmModeFreePropertyBlob (tile_blob); +} + +static void +state_set_blobs (MetaKmsConnectorState *state, + MetaKmsConnector *connector, + MetaKmsImplDevice *impl_device, + drmModeConnector *drm_connector) +{ + int fd; + int i; + + fd = meta_kms_impl_device_get_fd (impl_device); + + for (i = 0; i < drm_connector->count_props; i++) + { + drmModePropertyPtr prop; + + prop = drmModeGetProperty (fd, drm_connector->props[i]); + if (!prop) + continue; + + if (prop->flags & DRM_MODE_PROP_BLOB) + { + uint32_t blob_id; + + blob_id = drm_connector->prop_values[i]; + + if (blob_id) + { + if (strcmp (prop->name, "EDID") == 0) + state_set_edid (state, connector, impl_device, blob_id); + else if (strcmp (prop->name, "TILE") == 0) + state_set_tile_info (state, connector, impl_device, blob_id); + } + } + + drmModeFreeProperty (prop); + } +} + +static void +state_set_physical_dimensions (MetaKmsConnectorState *state, + drmModeConnector *drm_connector) +{ + state->width_mm = drm_connector->mmWidth; + state->height_mm = drm_connector->mmHeight; +} + +static void +state_set_modes (MetaKmsConnectorState *state, + drmModeConnector *drm_connector) +{ + state->modes = + g_memdup (drm_connector->modes, + drm_connector->count_modes * sizeof (drmModeModeInfo)); + state->n_modes = drm_connector->count_modes; +} + +static void +set_encoder_device_idx_bit (uint32_t *encoder_device_idxs, + uint32_t encoder_id, + MetaKmsImplDevice *impl_device, + drmModeRes *drm_resources) +{ + int fd; + int i; + + fd = meta_kms_impl_device_get_fd (impl_device); + + for (i = 0; i < drm_resources->count_encoders; i++) + { + drmModeEncoder *drm_encoder; + + drm_encoder = drmModeGetEncoder (fd, drm_resources->encoders[i]); + if (!drm_encoder) + continue; + + if (drm_encoder->encoder_id == encoder_id) + { + *encoder_device_idxs |= (1 << i); + break; + } + } +} + +static void +state_set_crtc_state (MetaKmsConnectorState *state, + drmModeConnector *drm_connector, + MetaKmsImplDevice *impl_device, + drmModeRes *drm_resources) +{ + int fd; + int i; + uint32_t common_possible_crtcs; + uint32_t common_possible_clones; + uint32_t encoder_device_idxs; + + fd = meta_kms_impl_device_get_fd (impl_device); + + common_possible_crtcs = UINT32_MAX; + common_possible_clones = UINT32_MAX; + encoder_device_idxs = 0; + for (i = 0; i < drm_connector->count_encoders; i++) + { + drmModeEncoder *drm_encoder; + + drm_encoder = drmModeGetEncoder (fd, drm_connector->encoders[i]); + if (!drm_encoder) + continue; + + common_possible_crtcs &= drm_encoder->possible_crtcs; + common_possible_clones &= drm_encoder->possible_clones; + + set_encoder_device_idx_bit (&encoder_device_idxs, + drm_encoder->encoder_id, + impl_device, + drm_resources); + + if (drm_connector->encoder_id == drm_encoder->encoder_id) + state->current_crtc_id = drm_encoder->crtc_id; + } + + state->common_possible_crtcs = common_possible_crtcs; + state->common_possible_clones = common_possible_clones; + state->encoder_device_idxs = encoder_device_idxs; +} + +static MetaKmsConnectorState * +meta_kms_connector_state_new (void) +{ + MetaKmsConnectorState *state; + + state = g_new0 (MetaKmsConnectorState, 1); + state->suggested_x = -1; + state->suggested_y = -1; + + return state; +} + +static void +meta_kms_connector_state_free (MetaKmsConnectorState *state) +{ + g_clear_pointer (&state->edid_data, g_bytes_unref); + g_free (state->modes); + g_free (state); +} + +static void +meta_kms_connector_read_state (MetaKmsConnector *connector, + MetaKmsImplDevice *impl_device, + drmModeConnector *drm_connector, + drmModeRes *drm_resources) +{ + MetaKmsConnectorState *state; + + g_clear_pointer (&connector->current_state, meta_kms_connector_state_free); + + if (drm_connector->connection != DRM_MODE_CONNECTED) + return; + + state = meta_kms_connector_state_new (); + + state_set_blobs (state, connector, impl_device, drm_connector); + + state_set_properties (state, impl_device, drm_connector); + + state->subpixel_order = + drm_subpixel_order_to_cogl_subpixel_order (drm_connector->subpixel); + + state_set_physical_dimensions (state, drm_connector); + + state_set_modes (state, drm_connector); + + state_set_crtc_state (state, drm_connector, impl_device, drm_resources); + + connector->current_state = state; +} + +void +meta_kms_connector_update_state (MetaKmsConnector *connector, + drmModeRes *drm_resources) +{ + MetaKmsImplDevice *impl_device; + drmModeConnector *drm_connector; + + impl_device = meta_kms_device_get_impl_device (connector->device); + drm_connector = drmModeGetConnector (meta_kms_impl_device_get_fd (impl_device), + connector->id); + meta_kms_connector_read_state (connector, impl_device, + drm_connector, + drm_resources); +} + static char * make_connector_name (drmModeConnector *drm_connector) { @@ -109,6 +483,10 @@ meta_kms_connector_new (MetaKmsImplDevice *impl_device, connector->type = (MetaConnectorType) drm_connector->connector_type; connector->name = make_connector_name (drm_connector); + meta_kms_connector_read_state (connector, impl_device, + drm_connector, + drm_resources); + return connector; } @@ -117,6 +495,7 @@ meta_kms_connector_finalize (GObject *object) { MetaKmsConnector *connector = META_KMS_CONNECTOR (object); + g_clear_pointer (&connector->current_state, meta_kms_connector_state_free); g_free (connector->name); G_OBJECT_CLASS (meta_kms_connector_parent_class)->finalize (object); diff --git a/src/backends/native/meta-kms-connector.h b/src/backends/native/meta-kms-connector.h index d49b31fe3..d536608e1 100644 --- a/src/backends/native/meta-kms-connector.h +++ b/src/backends/native/meta-kms-connector.h @@ -24,13 +24,41 @@ #include #include -#include "backends/native/meta-kms-types.h" #include "backends/meta-output.h" +#include "backends/native/meta-kms-types.h" #define META_TYPE_KMS_CONNECTOR (meta_kms_connector_get_type ()) G_DECLARE_FINAL_TYPE (MetaKmsConnector, meta_kms_connector, META, KMS_CONNECTOR, GObject) +typedef struct _MetaKmsConnectorState +{ + uint32_t current_crtc_id; + + uint32_t common_possible_crtcs; + uint32_t common_possible_clones; + uint32_t encoder_device_idxs; + + drmModeModeInfo *modes; + int n_modes; + + uint32_t width_mm; + uint32_t height_mm; + + MetaTileInfo tile_info; + GBytes *edid_data; + + gboolean has_scaling; + + CoglSubpixelOrder subpixel_order; + + int suggested_x; + int suggested_y; + gboolean hotplug_mode_update; + + MetaMonitorTransform panel_orientation_transform; +} MetaKmsConnectorState; + MetaKmsDevice * meta_kms_connector_get_device (MetaKmsConnector *connector); MetaConnectorType meta_kms_connector_get_connector_type (MetaKmsConnector *connector); @@ -39,4 +67,9 @@ uint32_t meta_kms_connector_get_id (MetaKmsConnector *connector); const char * meta_kms_connector_get_name (MetaKmsConnector *connector); +gboolean meta_kms_connector_can_clone (MetaKmsConnector *connector, + MetaKmsConnector *other_connector); + +const MetaKmsConnectorState * meta_kms_connector_get_current_state (MetaKmsConnector *connector); + #endif /* META_KMS_CONNECTOR_H */ diff --git a/src/backends/native/meta-kms-impl-device.c b/src/backends/native/meta-kms-impl-device.c index b849a138d..6593f2aee 100644 --- a/src/backends/native/meta-kms-impl-device.c +++ b/src/backends/native/meta-kms-impl-device.c @@ -219,10 +219,16 @@ init_planes (MetaKmsImplDevice *impl_device) void meta_kms_impl_device_update_states (MetaKmsImplDevice *impl_device) { + drmModeRes *drm_resources; + meta_assert_in_kms_impl (meta_kms_impl_get_kms (impl_device->impl)); + drm_resources = drmModeGetResources (impl_device->fd); g_list_foreach (impl_device->crtcs, (GFunc) meta_kms_crtc_update_state, NULL); + g_list_foreach (impl_device->connectors, (GFunc) meta_kms_connector_update_state, + drm_resources); + drmModeFreeResources (drm_resources); } MetaKmsImplDevice * diff --git a/src/backends/native/meta-output-kms.c b/src/backends/native/meta-output-kms.c index 9444d5b62..42c476479 100644 --- a/src/backends/native/meta-output-kms.c +++ b/src/backends/native/meta-output-kms.c @@ -44,26 +44,11 @@ typedef struct _MetaOutputKms drmModeConnector *connector; - /* - * Bitmasks of encoder position in the resources array (used during clone - * setup). - */ - uint32_t encoder_mask; - uint32_t enc_clone_mask; - uint32_t dpms_prop_id; - uint32_t edid_blob_id; - uint32_t tile_blob_id; uint32_t underscan_prop_id; uint32_t underscan_hborder_prop_id; uint32_t underscan_vborder_prop_id; - - int suggested_x; - int suggested_y; - uint32_t hotplug_mode_update; - - gboolean has_scaling; } MetaOutputKms; void @@ -156,177 +141,37 @@ meta_output_kms_can_clone (MetaOutput *output, MetaOutputKms *output_kms = output->driver_private; MetaOutputKms *other_output_kms = other_output->driver_private; - if (output_kms->enc_clone_mask == 0 || - other_output_kms->enc_clone_mask == 0) - return FALSE; - - if (output_kms->encoder_mask != other_output_kms->enc_clone_mask) - return FALSE; - - return TRUE; -} - -static drmModePropertyBlobPtr -read_edid_blob (MetaGpuKms *gpu_kms, - uint32_t edid_blob_id, - GError **error) -{ - int fd; - drmModePropertyBlobPtr edid_blob = NULL; - - fd = meta_gpu_kms_get_fd (gpu_kms); - edid_blob = drmModeGetPropertyBlob (fd, edid_blob_id); - if (!edid_blob) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), - "%s", strerror (errno)); - return NULL; - } - - return edid_blob; -} - -static GBytes * -read_output_edid (MetaGpuKms *gpu_kms, - MetaOutput *output, - GError **error) -{ - MetaOutputKms *output_kms = output->driver_private; - drmModePropertyBlobPtr edid_blob; - - g_assert (output_kms->edid_blob_id != 0); - - edid_blob = read_edid_blob (gpu_kms, output_kms->edid_blob_id, error); - if (!edid_blob) - return NULL; - - if (edid_blob->length == 0) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "EDID blob was empty"); - drmModeFreePropertyBlob (edid_blob); - return NULL; - } - - return g_bytes_new_with_free_func (edid_blob->data, edid_blob->length, - (GDestroyNotify) drmModeFreePropertyBlob, - edid_blob); -} - -static gboolean -output_get_tile_info (MetaGpuKms *gpu_kms, - MetaOutput *output) -{ - MetaOutputKms *output_kms = output->driver_private; - int fd; - drmModePropertyBlobPtr tile_blob = NULL; - - if (output_kms->tile_blob_id == 0) - return FALSE; - - fd = meta_gpu_kms_get_fd (gpu_kms); - tile_blob = drmModeGetPropertyBlob (fd, output_kms->tile_blob_id); - if (!tile_blob) - { - g_warning ("Failed to read TILE of output %s: %s", - output->name, strerror (errno)); - return FALSE; - } - - if (tile_blob->length > 0) - { - int ret; - - ret = sscanf ((char *)tile_blob->data, "%d:%d:%d:%d:%d:%d:%d:%d", - &output->tile_info.group_id, - &output->tile_info.flags, - &output->tile_info.max_h_tiles, - &output->tile_info.max_v_tiles, - &output->tile_info.loc_h_tile, - &output->tile_info.loc_v_tile, - &output->tile_info.tile_w, - &output->tile_info.tile_h); - drmModeFreePropertyBlob (tile_blob); - - if (ret != 8) - { - g_warning ("Couldn't understand output tile property blob"); - return FALSE; - } - return TRUE; - } - else - { - drmModeFreePropertyBlob (tile_blob); - return FALSE; - } + return meta_kms_connector_can_clone (output_kms->kms_connector, + other_output_kms->kms_connector); } GBytes * meta_output_kms_read_edid (MetaOutput *output) { MetaOutputKms *output_kms = output->driver_private; - MetaGpu *gpu = meta_output_get_gpu (output); - MetaGpuKms *gpu_kms = META_GPU_KMS (gpu); - GError *error = NULL; - GBytes *edid; + const MetaKmsConnectorState *connector_state; + GBytes *edid_data; - if (output_kms->edid_blob_id == 0) + connector_state = + meta_kms_connector_get_current_state (output_kms->kms_connector); + edid_data = connector_state->edid_data; + if (!edid_data) return NULL; - edid = read_output_edid (gpu_kms, output, &error); - if (!edid) - { - g_warning ("Failed to read EDID from '%s': %s", - output->name, error->message); - g_error_free (error); - return NULL; - } - - return edid; + return g_bytes_new_from_bytes (edid_data, 0, g_bytes_get_size (edid_data)); } static void -handle_panel_orientation (MetaOutput *output, - drmModePropertyPtr prop, - int orientation) -{ - const char *name = prop->enums[orientation].name; - - if (strcmp (name, "Upside Down") == 0) - { - output->panel_orientation_transform = META_MONITOR_TRANSFORM_180; - } - else if (strcmp (name, "Left Side Up") == 0) - { - /* Left side up, rotate 90 degrees counter clockwise to correct */ - output->panel_orientation_transform = META_MONITOR_TRANSFORM_90; - } - else if (strcmp (name, "Right Side Up") == 0) - { - /* Right side up, rotate 270 degrees counter clockwise to correct */ - output->panel_orientation_transform = META_MONITOR_TRANSFORM_270; - } - else - { - output->panel_orientation_transform = META_MONITOR_TRANSFORM_NORMAL; - } -} - -static void -find_connector_properties (MetaGpuKms *gpu_kms, - MetaOutput *output) +find_connector_properties (MetaGpuKms *gpu_kms, + MetaOutput *output, + drmModeConnector *connector) { MetaOutputKms *output_kms = output->driver_private; - drmModeConnector *connector = output_kms->connector; int fd; int i; fd = meta_gpu_kms_get_fd (gpu_kms); - output_kms->hotplug_mode_update = 0; - output_kms->suggested_x = -1; - output_kms->suggested_y = -1; - for (i = 0; i < connector->count_props; i++) { drmModePropertyPtr prop = drmModeGetProperty (fd, connector->props[i]); @@ -336,27 +181,6 @@ find_connector_properties (MetaGpuKms *gpu_kms, if ((prop->flags & DRM_MODE_PROP_ENUM) && strcmp (prop->name, "DPMS") == 0) output_kms->dpms_prop_id = prop->prop_id; - else if ((prop->flags & DRM_MODE_PROP_BLOB) && - strcmp (prop->name, "EDID") == 0) - output_kms->edid_blob_id = connector->prop_values[i]; - else if ((prop->flags & DRM_MODE_PROP_BLOB) && - strcmp (prop->name, "TILE") == 0) - output_kms->tile_blob_id = connector->prop_values[i]; - else if ((prop->flags & DRM_MODE_PROP_RANGE) && - strcmp (prop->name, "suggested X") == 0) - output_kms->suggested_x = connector->prop_values[i]; - else if ((prop->flags & DRM_MODE_PROP_RANGE) && - strcmp (prop->name, "suggested Y") == 0) - output_kms->suggested_y = connector->prop_values[i]; - else if ((prop->flags & DRM_MODE_PROP_RANGE) && - strcmp (prop->name, "hotplug_mode_update") == 0) - output_kms->hotplug_mode_update = connector->prop_values[i]; - else if (strcmp (prop->name, "scaling mode") == 0) - output_kms->has_scaling = TRUE; - else if ((prop->flags & DRM_MODE_PROP_ENUM) && - strcmp (prop->name, "panel orientation") == 0) - handle_panel_orientation (output, prop, - output_kms->connector->prop_values[i]); else if ((prop->flags & DRM_MODE_PROP_ENUM) && strcmp (prop->name, "underscan") == 0) output_kms->underscan_prop_id = prop->prop_id; @@ -472,20 +296,24 @@ init_output_modes (MetaOutput *output, GError **error) { MetaOutputKms *output_kms = output->driver_private; - unsigned int i; + const MetaKmsConnectorState *connector_state; + int i; + + connector_state = + meta_kms_connector_get_current_state (output_kms->kms_connector); output->preferred_mode = NULL; - output->n_modes = output_kms->connector->count_modes; + + output->n_modes = connector_state->n_modes; output->modes = g_new0 (MetaCrtcMode *, output->n_modes); - for (i = 0; i < output->n_modes; i++) + for (i = 0; i < connector_state->n_modes; i++) { - drmModeModeInfo *drm_mode; + drmModeModeInfo *drm_mode = &connector_state->modes[i]; MetaCrtcMode *crtc_mode; - drm_mode = &output_kms->connector->modes[i]; crtc_mode = meta_gpu_kms_get_mode_from_drm_mode (gpu_kms, drm_mode); output->modes[i] = crtc_mode; - if (output_kms->connector->modes[i].type & DRM_MODE_TYPE_PREFERRED) + if (drm_mode->type & DRM_MODE_TYPE_PREFERRED) output->preferred_mode = output->modes[i]; } @@ -493,7 +321,7 @@ init_output_modes (MetaOutput *output, /* Presume that if the output supports scaling, then we have * a panel fitter capable of adjusting any mode to suit. */ - if (output_kms->has_scaling) + if (connector_state->has_scaling) add_common_modes (output, gpu_kms); if (!output->modes) @@ -516,24 +344,18 @@ MetaOutput * meta_create_kms_output (MetaGpuKms *gpu_kms, MetaKmsConnector *kms_connector, drmModeConnector *connector, - MetaKmsResources *resources, MetaOutput *old_output, GError **error) { MetaGpu *gpu = META_GPU (gpu_kms); MetaOutput *output; MetaOutputKms *output_kms; + const MetaKmsConnectorState *connector_state; + MetaMonitorTransform panel_orientation_transform; uint32_t connector_id; GArray *crtcs; - GBytes *edid; GList *l; - unsigned int i; - unsigned int crtc_mask; - int fd; uint32_t gpu_id; - unsigned int n_encoders; - drmModeEncoderPtr *encoders; - drmModeEncoderPtr current_encoder = NULL; output = g_object_new (META_TYPE_OUTPUT, NULL); @@ -548,43 +370,22 @@ meta_create_kms_output (MetaGpuKms *gpu_kms, connector_id = meta_kms_connector_get_id (kms_connector); output->winsys_id = ((uint64_t) gpu_id << 32) | connector_id; - switch (connector->subpixel) - { - case DRM_MODE_SUBPIXEL_NONE: - output->subpixel_order = COGL_SUBPIXEL_ORDER_NONE; - break; - case DRM_MODE_SUBPIXEL_HORIZONTAL_RGB: - output->subpixel_order = COGL_SUBPIXEL_ORDER_HORIZONTAL_RGB; - break; - case DRM_MODE_SUBPIXEL_HORIZONTAL_BGR: - output->subpixel_order = COGL_SUBPIXEL_ORDER_HORIZONTAL_BGR; - break; - case DRM_MODE_SUBPIXEL_VERTICAL_RGB: - output->subpixel_order = COGL_SUBPIXEL_ORDER_VERTICAL_RGB; - break; - case DRM_MODE_SUBPIXEL_VERTICAL_BGR: - output->subpixel_order = COGL_SUBPIXEL_ORDER_VERTICAL_BGR; - break; - case DRM_MODE_SUBPIXEL_UNKNOWN: - default: - output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN; - break; - } - output_kms->kms_connector = kms_connector; - output_kms->connector = connector; - find_connector_properties (gpu_kms, output); + find_connector_properties (gpu_kms, output, connector); - if (meta_monitor_transform_is_rotated (output->panel_orientation_transform)) + connector_state = meta_kms_connector_get_current_state (kms_connector); + + panel_orientation_transform = connector_state->panel_orientation_transform; + if (meta_monitor_transform_is_rotated (panel_orientation_transform)) { - output->width_mm = connector->mmHeight; - output->height_mm = connector->mmWidth; + output->width_mm = connector_state->height_mm; + output->height_mm = connector_state->width_mm; } else { - output->width_mm = connector->mmWidth; - output->height_mm = connector->mmHeight; + output->width_mm = connector_state->width_mm; + output->height_mm = connector_state->height_mm; } if (!init_output_modes (output, gpu_kms, error)) @@ -593,51 +394,29 @@ meta_create_kms_output (MetaGpuKms *gpu_kms, return NULL; } - n_encoders = connector->count_encoders; - encoders = g_new0 (drmModeEncoderPtr, n_encoders); + crtcs = g_array_new (FALSE, FALSE, sizeof (MetaCrtc *)); - fd = meta_gpu_kms_get_fd (gpu_kms); - - crtc_mask = ~(unsigned int) 0; - for (i = 0; i < n_encoders; i++) + for (l = meta_gpu_get_crtcs (gpu); l; l = l->next) { - encoders[i] = drmModeGetEncoder (fd, connector->encoders[i]); - if (!encoders[i]) - continue; + MetaCrtc *crtc = l->data; + MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc); + uint32_t crtc_idx; - /* We only list CRTCs as supported if they are supported by all encoders - for this connectors. - - This is what xf86-video-modesetting does (see drmmode_output_init()) - */ - crtc_mask &= encoders[i]->possible_crtcs; - - if (encoders[i]->encoder_id == connector->encoder_id) - current_encoder = encoders[i]; - } - - crtcs = g_array_new (FALSE, FALSE, sizeof (MetaCrtc*)); - - for (l = meta_gpu_get_crtcs (gpu), i = 0; l; l = l->next, i++) - { - if (crtc_mask & (1 << i)) - { - MetaCrtc *crtc = l->data; - - g_array_append_val (crtcs, crtc); - } + crtc_idx = meta_kms_crtc_get_idx (kms_crtc); + if (connector_state->common_possible_crtcs & (1 << crtc_idx)) + g_array_append_val (crtcs, crtc); } output->n_possible_crtcs = crtcs->len; - output->possible_crtcs = (void*)g_array_free (crtcs, FALSE); + output->possible_crtcs = (MetaCrtc **) g_array_free (crtcs, FALSE); - if (current_encoder && current_encoder->crtc_id != 0) + if (connector_state->current_crtc_id) { for (l = meta_gpu_get_crtcs (gpu); l; l = l->next) { MetaCrtc *crtc = l->data; - if (crtc->crtc_id == current_encoder->crtc_id) + if (crtc->crtc_id == connector_state->current_crtc_id) { meta_output_assign_crtc (output, crtc); break; @@ -660,34 +439,16 @@ meta_create_kms_output (MetaGpuKms *gpu_kms, output->is_presentation = FALSE; } - output->suggested_x = output_kms->suggested_x; - output->suggested_y = output_kms->suggested_y; - output->hotplug_mode_update = output_kms->hotplug_mode_update; + output->suggested_x = connector_state->suggested_x; + output->suggested_y = connector_state->suggested_y; + output->hotplug_mode_update = connector_state->hotplug_mode_update; output->supports_underscanning = output_kms->underscan_prop_id != 0; - if (output_kms->edid_blob_id != 0) - { - GError *error = NULL; - - edid = read_output_edid (gpu_kms, output, &error); - if (!edid) - { - g_warning ("Failed to read EDID blob from %s: %s", - output->name, error->message); - g_error_free (error); - } - } - else - { - edid = NULL; - } - - meta_output_parse_edid (output, edid); - g_bytes_unref (edid); + meta_output_parse_edid (output, connector_state->edid_data); output->connector_type = meta_kms_connector_get_connector_type (kms_connector); - output_get_tile_info (gpu_kms, output); + output->tile_info = connector_state->tile_info; /* FIXME: backlight is a very driver specific thing unfortunately, every DDX does its own thing, and the dumb KMS API does not include it. @@ -702,32 +463,5 @@ meta_create_kms_output (MetaGpuKms *gpu_kms, output->backlight_max = 0; output->backlight = -1; - output_kms->enc_clone_mask = 0xff; - output_kms->encoder_mask = 0; - - for (i = 0; i < n_encoders; i++) - { - drmModeEncoder *output_encoder = encoders[i]; - unsigned int j; - - for (j = 0; j < resources->n_encoders; j++) - { - drmModeEncoder *encoder = resources->encoders[j]; - - if (output_encoder && encoder && - output_encoder->encoder_id == encoder->encoder_id) - { - output_kms->encoder_mask |= (1 << j); - break; - } - } - - output_kms->enc_clone_mask &= output_encoder->possible_clones; - } - - for (i = 0; i < n_encoders; i++) - drmModeFreeEncoder (encoders[i]); - g_free (encoders); - return output; } diff --git a/src/backends/native/meta-output-kms.h b/src/backends/native/meta-output-kms.h index 2c0bf8f95..f35aa130f 100644 --- a/src/backends/native/meta-output-kms.h +++ b/src/backends/native/meta-output-kms.h @@ -42,7 +42,6 @@ GBytes * meta_output_kms_read_edid (MetaOutput *output); MetaOutput * meta_create_kms_output (MetaGpuKms *gpu_kms, MetaKmsConnector *kms_connector, drmModeConnector *connector, - MetaKmsResources *resources, MetaOutput *old_output, GError **error);