[cogl/wip/outputs: 70/71] stash



commit 50bf0bede748338c451c727fbef0f42e8857a3d4
Author: Robert Bragg <robert linux intel com>
Date:   Fri Aug 16 16:52:53 2013 +0100

    stash

 cogl/winsys/cogl-winsys-egl-kms.c |  240 ++++++++++++++++++++++++++-----------
 1 files changed, 172 insertions(+), 68 deletions(-)
---
diff --git a/cogl/winsys/cogl-winsys-egl-kms.c b/cogl/winsys/cogl-winsys-egl-kms.c
index 3223765..950dc92 100644
--- a/cogl/winsys/cogl-winsys-egl-kms.c
+++ b/cogl/winsys/cogl-winsys-egl-kms.c
@@ -395,9 +395,9 @@ update_outputs (CoglRenderer *renderer)
                                         kms_output_destroy_cb);
         }
 
-      for (j = 0; j < resources->count_modes; j++)
+      for (j = 0; j < connector->count_modes; j++)
         {
-          drmModeModeInfo *info = &resources->modes[j];
+          drmModeModeInfo *info = &connector->modes[j];
 
           CoglMode *mode = _cogl_mode_new (info->name);
           mode->width = info->hdisplay;
@@ -1201,6 +1201,14 @@ get_connector_property (int fd,
   return NULL;
 }
 
+/* XXX: NB: Don't assume that the output->state is a reliable cache
+ * of the real hardware state such that state changes can be avoided
+ * by looking for NOP changes between ->state and ->pending since we
+ * sometimes have to deal with the display being changed behind our
+ * back.
+ *
+ * TODO: Support incremental updates in certain cases
+ */
 static void
 _cogl_winsys_commit_outputs (CoglRenderer *renderer,
                              CoglError **error)
@@ -1208,6 +1216,14 @@ _cogl_winsys_commit_outputs (CoglRenderer *renderer,
   CoglRendererEGL *egl_renderer = renderer->winsys;
   CoglRendererKMS *kms_renderer = egl_renderer->platform;
   GList *l;
+  CoglBool roll_back = FALSE;
+
+
+  /* If we hit an error at any point while committing the new
+   * configuration then we revert back to here with roll_back
+   * set to TRUE and instead re-commit the previous
+   * configuration */
+ROLL_BACK:
 
   /*
    * Ideally we never want to mode-switch to un-initialized
@@ -1232,13 +1248,10 @@ _cogl_winsys_commit_outputs (CoglRenderer *renderer,
     {
       CoglOutput *output = l->data;
       CoglOutputKMS *kms_output = output->winsys;
-      CoglOutputState *state_old = output->state;
-      CoglOutputState *state_new = output->pending;
-      GList *old_overlay0_link, *new_overlay0_link;
+      CoglOutputState *state = roll_back ? output->state : output->pending;
+      drmModeConnector *connector;
       drmModeProperty *property;
-
-      if (state_old == state_new)
-        continue;
+      int i;
 
       connector = drmModeGetConnector (kms_renderer->fd,
                                        kms_output->connector_id);
@@ -1248,82 +1261,152 @@ _cogl_winsys_commit_outputs (CoglRenderer *renderer,
           continue;
         }
 
-      if (b->output->pending->overlays)
-        overlay0_new = state_new->output->pending->overlays->data;
+      if (state->overlays)
+        overlay0 = state->overlays->data;
       else
-        overlay0_new = NULL;
+        overlay0 = NULL;
+
+      /* If the output has no associated overlays then we assume
+       * it's ok to try and put it into DPMS_MODE_OFF */
+      dpms_mode = overlay0_new ? state_new->dpms_mode : DRM_MODE_DPMS_OFF;
 
-      if (!overlay0_new ||
-          state_old->dpms_mode != state_new->dpms_mode)
+      property = get_connector_property (kms_renderer->fd,
+                                         connector,
+                                         "DPMS");
+      if (property)
         {
-          /* If the output has no associated overlays then we assume
-           * it's ok to try and put it into DPMS_MODE_OFF */
-          dpms_mode = overlay0_new ? state_new->dpms_mode : DRM_MODE_DPMS_OFF;
-
-          property = get_connector_property (kms_renderer->fd,
-                                             connector,
-                                             "DPMS");
-          if (property)
+          int status = drmModeConnectorSetProperty (kms_renderer->fd,
+                                                    connector->connector_id,
+                                                    property->prop_id,
+                                                    dpms_mode);
+          drmModeFreeProperty (property);
+
+          if (status < 0)
             {
-              drmModeConnectorSetProperty (kms_renderer->fd,
-                                           connector->connector_id,
-                                           property->prop_id, dpms_mode);
-              drmModeFreeProperty (property);
+              const char *dpms_mode_names[] = {
+                  "ON",
+                  "STANDBY",
+                  "SUSPEND",
+                  "OFF"
+              };
+
+              g_return_if_fail (roll_back == FALSE);
+
+              roll_back = TRUE;
+              roll_back_error =
+                g_strdup_printf ("Failed to set DPMS state for "
+                                 "connector %d to %s",
+                                 dpms_mode_names[dpms_mode]);
+              goto ROLL_BACK;
             }
         }
 
-      drmModeFreeConnector (connector);
-
-      if (!state_new->output->pending->overlays)
+      if (!overlay0)
         {
-
+          drmModeFreeConnector (connector);
+          continue;
         }
 
-      /* We assume there is always at least one overlay associated
-       * with each output */
-      g_warn_if_fail (state_new->output->pending->overlays &&
-                      state-new->output->pending->overlays->data);
-      overlay0 = state_new->output->pending->overlays->data;
-
-      /* We also assume there is always a source associated with
+      /* We currently assume there is always a source associated with
        * each overlay */
       g_warn_if_fail (overlay0->onscreen_source);
 
-      overlay0_link = b->output->pending->overlays;
-      if (!
 
-#error FIXME
-      /* First setup the crtc mode, using the source from the
-       * lowest overlay associated with the output. */
-
-      /* Now setup planes for all remaining overlays */
-      for (m = a->overlays, n = b->overlays;
-           ;
-           m = m->next, n = n->next)
+      /* XXX: The corner cases to consider...
+       *
+       * Q: What if we _commit before swapping any onscreen sources?
+       * A: Simply report an error that the overlay sources weren't
+       *    all "primed" and roll back the configuration
+       *
+       * Q: What if we call _swap_buffers() before we have committed
+       *    an output configuration associating the framebuffer with
+       *    a hardware overlay?
+       * A: In this case we'll see that kms_output->overlays is NULL.
+       *    We can lock the front buffer and set it as the ->next_bo.
+       *    If ->next_bo is already set then we can release ->next_bo
+       *    and lock the new front buffer. XXX: what about issuing
+       *    a _FRAME_SYNC event for the previous frame?
+       *
+       *    How this relates to display configuration:
+       *    --
+       *    During a _commit we always check that a source either has
+       *    a valid ->current_bo or ->next_bo (otherwise we report an
+       *    error) since we can't set a mode without a framebuffer and
+       *    we don't want to be automatically allocating place holder
+       *    framebuffers in corner cases or displaying undefined
+       *    buffer contents.
+       *
+       *    If ->current_bo is set then we assume there is no
+       *    rendering outstanding for that buffer and always use that
+       *    buffer when calling drmModeSetCrtc. If we need to call
+       *    drmModeSetCrtc() and ->current_bo is not set then we
+       *    explicitly synchronize with the GPU to make sure all
+       *    rendering to ->next_bo is complete before calling
+       *    drmModeSetCrtc().
+       *
+       *    If ->current_bo and ->next_bo are set when calling
+       *    drmModeSetCrtc then we also call drmModePageFlip() to post
+       *    ->next_bo.
+       *
+       *    After successfully calling drmModeSetCrtc() then we insert
+       *    a reference to the overlay in kms_onscreen->overlays.
+       *
+       * Q: What are the semantics for committing a configuration
+       *    while there are pending page flips?
+       * A: Looking at the intel drm driver it looks like setting
+       *    a mode starts by disabling the crtc, which involves
+       *    waiting for pending flips so I think we can assume
+       *    page flip events will *always* be delivered by drm.
+       *
+       * Q: When do we remove references from the
+       *    kms_onscreen->overlays list?
+       * A: XXX
+       *
+       * Q: What happens in _swap_buffers when the onscreen is
+       *    associated with one or more overlays?
+       * A: iterate through each overlay
+       *
+       * Q: How do we deal with roll-back when this is the first
+       *    configuration to be committed?
+       * A: XXX
+       *
+       * Q: How do we deal with an error in drmModePageFlip() also
+       *    considering that after the error we might commit a
+       *    new display configuration which will want to find
+       *    a next/current_bo to reference.
+       * A: We can pretend there was no error and that the page
+       *    flip completed immediately by calling page_flip_handler()
+       *    directly in this case. This will make sure cogl
+       *    dispatches a _FRAME_SYNC event for the frame otherwise
+       *    applications may freeze. The main problem here is that
+       *    we don't have meaningful timestamp data to pass to
+       *    page_flip_handler(). XXX: wont this potentially break the
+       *    invariable that we should be able to assume ->current_bo
+       *    has no outstanding rendering?
+       *
+       * Q: How do we handle an onscreen framebuffer resize?
+       * A: We don't, you just have to create a new framebuffer
+       */
+
+      for (i = 0; i < connector->count_modes; i++)
         {
-          CoglOverlay *overlay_m, *overlay_n;
-
-          if (m && n && _cogl_overlay_equal (m->data, n->data))
-            continue;
-
-          overlay_m = m->data;
-
-          if (!m || overlay_m->onscreen_source != overlay_n->onscreen_source)
+          drmModeInfo *mode_info = &connector->modes[i];
+          if (strcmp (mode_info->name, state->mode->name) == 0)
             {
-
-            }
-#error FIXME
-        }
-
-  /* Note: In the future we might support other sources, such as for
-   * video */
-  CoglOnscreen *onscreen_source;
-
-  /* XXX: src_x must be the first member for _cogl_overlay_equal() to
-   * work and all remaining members should be comparable via
-   * memcpy() */
-
-  /* What region of the source should be overlayed? */
+              CoglOnscreen *onscreen = overlay0->onscreen_source;
+              CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
+              CoglOnscreenKMS *kms_onscreen = egl_onscreen->platform;
+
+              /* XXX: Overlay 0 has limitations with the KMS api */
+#warning "FIXME: actually these should result in a CoglError not a warning"
+              g_warn_if_fail (overlay->src_x != 0);
+              g_warn_if_fail (overlay->src_y != 0);
+              g_warn_if_fail (overlay->src_width != mode_info->width);
+              g_warn_if_fail (overlay->src_height != mode_info->height);
+
+              if (kms_onscreen->current_fb_id)
+                fb_id = kms_onscreen->current_fb_id;
+              else if (kms_onscreen->next_fb_id)
   int src_x;
   int src_y;
   int src_width;
@@ -1332,6 +1415,27 @@ _cogl_winsys_commit_outputs (CoglRenderer *renderer,
   int dst_x;
   int dst_y;
 
+              int ret = drmModeSetCrtc (kms_renderer->fd,
+                                        kms_output->encoder->crtc_id,
+                                        fb_id, 0, 0,
+                                        &connector->connector_id, 1,
+                                        &kms_mode_info);
+
+            }
+        }
+
+#error FIXME
+      /* First setup the crtc mode, using the source from the
+       * lowest overlay associated with the output. */
+
+      /* Now setup planes for all remaining overlays */
+      for (m = state->overlays->next, m; m = m->next)
+        {
+          CoglOverlay *overlay = m->data;
+
+        }
+
+      drmModeFreeConnector (connector);
 
       _cogl_output_update_state (output);
     }


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