[mutter/wip/gbsneto/kms-transactions-on-steroids: 17/30] output/kms: Outsource connector state fetching to MetaKmsConnector



commit c3acb5a6e9a60f042cf05831c1cc688f02c41761
Author: Jonas Ã…dahl <jadahl gmail com>
Date:   Sat Mar 9 15:55:24 2019 +0100

    output/kms: Outsource connector state fetching to MetaKmsConnector
    
    As with CRTC state, variable connector state is now fetched via the
    MetaKmsConnector. The existance of a connector state is equivalent of
    the connector being connected. MetaOutputKms is changed to fetch
    variable connector state via MetaKmsConnector intsead of KMS directly.
    The drmModeConnector is still used for constructing the MetaOutputKms to
    find properties used for applying configuration.
    
    https://gitlab.gnome.org/GNOME/mutter/issues/548
    https://gitlab.gnome.org/GNOME/mutter/merge_requests/525

 src/backends/native/meta-crtc-kms.c              |   8 +
 src/backends/native/meta-crtc-kms.h              |   2 +
 src/backends/native/meta-gpu-kms.c               |   6 +-
 src/backends/native/meta-kms-connector-private.h |   3 +
 src/backends/native/meta-kms-connector.c         | 379 +++++++++++++++++++++++
 src/backends/native/meta-kms-connector.h         |  35 ++-
 src/backends/native/meta-kms-impl-device.c       |   6 +
 src/backends/native/meta-output-kms.c            | 366 +++-------------------
 src/backends/native/meta-output-kms.h            |   1 -
 9 files changed, 484 insertions(+), 322 deletions(-)
---
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 <errno.h>
 
+#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 <stdint.h>
 #include <xf86drmMode.h>
 
-#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);
-
-  fd = meta_gpu_kms_get_fd (gpu_kms);
+  crtcs = g_array_new (FALSE, FALSE, sizeof (MetaCrtc *));
 
-  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);
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]