drm randr: More work on getting RandR functional in E-Wl. This adds a
authorChris Michael <cp.michael@samsung.com>
Wed, 13 May 2015 18:44:51 +0000 (14:44 -0400)
committerChris Michael <cp.michael@samsung.com>
Wed, 13 May 2015 18:50:40 +0000 (14:50 -0400)
function to remove an output from e_comp_wl also.

NB: Not entirely complete yet

Signed-off-by: Chris Michael <cp.michael@samsung.com>
src/bin/e_comp_wl.c
src/bin/e_comp_wl.h
src/modules/wl_drm/e_mod_main.c

index e35a7ff..beb390e 100644 (file)
@@ -797,7 +797,12 @@ _e_comp_wl_cb_randr_change(void *data EINA_UNUSED, int type EINA_UNUSED, void *e
 
    EINA_LIST_FOREACH(e_randr2->screens, l, screen)
      {
-        if (!screen->config.enabled) continue;
+        if (!screen->config.enabled)
+          {
+             e_comp_wl_output_remove(screen->id);
+             continue;
+          }
+
         switch (screen->config.rotation)
           {
            case 90:
@@ -2454,7 +2459,7 @@ _e_comp_wl_compositor_create(void)
         goto comp_global_err;
      }
 
-   _e_comp_wl_cb_randr_change(NULL, 0, NULL);
+   /* _e_comp_wl_cb_randr_change(NULL, 0, NULL); */
 
    /* try to init data manager */
    if (!e_comp_wl_data_manager_init(cdata))
@@ -2927,5 +2932,29 @@ e_comp_wl_output_init(const char *id, const char *make, const char *model,
         if (wl_resource_get_version(resource) >= WL_OUTPUT_DONE_SINCE_VERSION)
           wl_output_send_done(resource);
      }
+
    return EINA_TRUE;
 }
+
+E_API void
+e_comp_wl_output_remove(const char *id)
+{
+   E_Comp_Data *cdata;
+   E_Comp_Wl_Output *output;
+
+   if (!(cdata = e_comp->wl_comp_data)) return;
+
+   output = _e_comp_wl_output_get(cdata->outputs, id);
+   if (output)
+     {
+        cdata->outputs = eina_list_remove(cdata->outputs, output);
+
+        /* wl_global_destroy(output->global); */
+
+        /* eina_stringshare_del(output->id); */
+        /* eina_stringshare_del(output->make); */
+        /* eina_stringshare_del(output->model); */
+
+        /* free(output); */
+     }
+}
index 8b3454c..4dcc08a 100644 (file)
@@ -291,6 +291,7 @@ E_API E_Comp_Wl_Buffer *e_comp_wl_buffer_get(struct wl_resource *resource);
 E_API struct wl_signal e_comp_wl_surface_create_signal_get(void);
 E_API double e_comp_wl_idle_time_get(void);
 E_API Eina_Bool e_comp_wl_output_init(const char *id, const char *make, const char *model, int x, int y, int w, int h, int pw, int ph, unsigned int refresh, unsigned int subpixel, unsigned int transform);
+E_API void e_comp_wl_output_remove(const char *id);
 
 # endif
 #endif
index c85c32b..cba2b20 100644 (file)
@@ -54,30 +54,41 @@ end:
 static Eina_Bool
 _e_mod_drm_cb_output(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
 {
+   const Eina_List *l;
+   E_Randr2_Screen *screen;
    Ecore_Drm_Event_Output *e;
-   char buff[PATH_MAX];
 
    if (!(e = event)) goto end;
 
-   if (!e->plug)
-     {
-        DBG("Caught Drm Output Unplug Event");
-        /* FIXME: This needs to remove output from e_comp_wl */
-        goto end;
-     }
-
-   snprintf(buff, sizeof(buff), "%d", e->id);
+   DBG("WL_DRM OUTPUT CHANGE");
 
-   if (!e_comp_wl_output_init(buff, e->make, e->model, e->x, e->y, e->w, e->h, 
-                              e->phys_width, e->phys_height, e->refresh, 
-                              e->subpixel_order, e->transform))
+   EINA_LIST_FOREACH(e_randr2->screens, l, screen)
      {
-        ERR("Could not setup new output: %s", buff);
+        if ((!strcmp(screen->info.name, e->name)) && 
+            (!strcmp(screen->info.screen, e->model)))
+          {
+             if (e->plug)
+               {
+                  if (!e_comp_wl_output_init(screen->id, e->make, e->model,
+                                             e->x, e->y, e->w, e->h, 
+                                             e->phys_width, e->phys_height,
+                                             e->refresh, e->subpixel_order,
+                                             e->transform))
+                    {
+                       ERR("Could not setup new output: %s", screen->id);
+                    }
+               }
+             else
+               e_comp_wl_output_remove(screen->id);
+
+             break;
+          }
      }
 
 end:
    if (!e_randr2_cfg->ignore_hotplug_events)
      e_randr2_screen_refresh_queue(EINA_TRUE);
+
    return ECORE_CALLBACK_PASS_ON;
 }
 
@@ -109,6 +120,190 @@ _e_mod_drm_mode_screen_find(E_Randr2_Screen *s, Ecore_Drm_Output *output)
    return m;
 }
 
+static Eina_Bool
+_e_mod_drm_output_exists(Ecore_Drm_Output *output, unsigned int crtc)
+{
+   /* find out if this output can go into the 'possibles' */
+   return ecore_drm_output_possible_crtc_get(output, crtc);
+}
+
+static char *
+_e_mod_drm_output_screen_get(Ecore_Drm_Output *output)
+{
+   const char *model;
+
+   model = ecore_drm_output_model_get(output);
+   if (!model) return NULL;
+
+   return strdup(model);
+}
+
+static E_Randr2_Screen *
+_info_unconf_primary_find(E_Randr2 *r)
+{
+   Eina_List *l;
+   E_Randr2_Screen *s, *s_primary = NULL;
+   int priority = 0;
+
+   EINA_LIST_FOREACH(r->screens, l, s)
+     {
+        if (!((s->config.enabled) && 
+              (s->config.mode.w > 0) && (s->config.mode.h > 0) &&
+              (s->config.geom.w > 0) && (s->config.geom.h > 0)))
+          continue;
+        if (s->config.priority > priority)
+          {
+             s_primary = s;
+             priority = s->config.priority;
+          }
+     }
+
+   return s_primary;
+}
+
+static E_Randr2_Screen *
+_info_unconf_left_find(E_Randr2 *r)
+{
+   Eina_List *l;
+   E_Randr2_Screen *s, *s_left = NULL;
+   int left_x = 0x7fffffff;
+   int left_size = 0;
+
+   EINA_LIST_FOREACH(r->screens, l, s)
+     {
+        if (!((s->config.enabled) &&
+              (s->config.mode.w > 0) && (s->config.mode.h > 0) &&
+              (s->config.geom.w > 0) && (s->config.geom.h > 0)))
+          continue;
+        if ((s->config.geom.x <= left_x) &&
+            ((s->config.geom.w * s->config.geom.h) > left_size))
+          {
+             left_size = s->config.geom.w * s->config.geom.h;
+             left_x = s->config.geom.x;
+             s_left = s;
+          }
+     }
+   return s_left;
+}
+
+static E_Randr2_Screen *
+_info_unconf_closest_find(E_Randr2 *r, E_Randr2_Screen *s2, Eina_Bool configured)
+{
+   Eina_List *l;
+   E_Randr2_Screen *s, *s_sel = NULL;
+   int dist = 0x7fffffff;
+   int dx, dy;
+
+   EINA_LIST_FOREACH(r->screens, l, s)
+     {
+        if (s == s2) continue;
+        if (!((s->config.enabled) &&
+              (s->config.mode.w > 0) && (s->config.mode.h > 0) &&
+              (s->config.geom.w > 0) && (s->config.geom.h > 0)))
+          continue;
+        if ((!configured) &&
+            (s->config.relative.mode != E_RANDR2_RELATIVE_UNKNOWN))
+          continue;
+        else if ((configured) &&
+                 (s->config.relative.mode == E_RANDR2_RELATIVE_UNKNOWN))
+          continue;
+        dx = (s->config.geom.x + (s->config.geom.w / 2)) -
+          (s2->config.geom.x + (s2->config.geom.w / 2));
+        dy = (s->config.geom.y + (s->config.geom.h / 2)) -
+          (s2->config.geom.y + (s2->config.geom.h / 2));
+        dx = sqrt((dx * dx) + (dy * dy));
+        if (dx < dist)
+          {
+             s_sel = s;
+             dist = dx;
+          }
+     }
+   return s_sel;
+}
+
+static void
+_e_mod_drm_relative_fixup(E_Randr2 *r)
+{
+   E_Randr2_Screen *s, *s2;
+   int d, dx, dy;
+
+   s = _info_unconf_primary_find(r);
+   if (s)
+     s->config.relative.mode = E_RANDR2_RELATIVE_NONE;
+   else
+     {
+        s = _info_unconf_left_find(r);
+        if (!s) return;
+        s->config.relative.mode = E_RANDR2_RELATIVE_NONE;
+     }
+
+   for (;;)
+     {
+        // find the next screen that is closest to the last one we configured
+        /// that is still not configured yet
+        s = _info_unconf_closest_find(r, s, EINA_FALSE);
+        if (!s) break;
+        s2 = _info_unconf_closest_find(r, s, EINA_TRUE);
+        // fix up s->config.relative.mode, s->config.relative.to and
+        // s->config.relative.align to match (as closely as possible)
+        // the geometry given - config s relative to s2
+        if (!s2) s->config.relative.mode = E_RANDR2_RELATIVE_NONE;
+        else
+          {
+             s->config.relative.to = strdup(s2->id);
+             s->config.relative.align = 0.0;
+             s->config.relative.mode = E_RANDR2_RELATIVE_NONE;
+             if ((s->config.geom.x + s->config.geom.w) <=
+                 s2->config.geom.x)
+               {
+                  s->config.relative.mode = E_RANDR2_RELATIVE_TO_LEFT;
+                  d = s->config.geom.h - s2->config.geom.h;
+                  dy = s2->config.geom.y - s->config.geom.y;
+                  if (d != 0)
+                    s->config.relative.align = ((double)dy) / ((double)d);
+               }
+             else if (s->config.geom.x >=
+                      (s2->config.geom.x + s2->config.geom.w))
+               {
+                  s->config.relative.mode = E_RANDR2_RELATIVE_TO_RIGHT;
+                  d = s->config.geom.h - s2->config.geom.h;
+                  dy = s2->config.geom.y - s->config.geom.y;
+                  if (d != 0)
+                    s->config.relative.align = ((double)dy) / ((double)d);
+               }
+             else if ((s->config.geom.y + s->config.geom.h) <=
+                      s2->config.geom.y)
+               {
+                  s->config.relative.mode = E_RANDR2_RELATIVE_TO_ABOVE;
+                  d = s->config.geom.w - s2->config.geom.w;
+                  dx = s2->config.geom.x - s->config.geom.x;
+                  if (d != 0)
+                    s->config.relative.align = ((double)dx) / ((double)d);
+               }
+             else if (s->config.geom.y >=
+                      (s2->config.geom.y + s2->config.geom.h))
+               {
+                  s->config.relative.mode = E_RANDR2_RELATIVE_TO_BELOW;
+                  d = s->config.geom.w - s2->config.geom.w;
+                  dx = s2->config.geom.x - s->config.geom.x;
+                  if (d != 0)
+                    s->config.relative.align = ((double)dx) / ((double)d);
+               }
+             else if ((s->config.geom.x == s2->config.geom.x) &&
+                      (s->config.geom.y == s2->config.geom.y) &&
+                      (s->config.geom.w == s2->config.geom.w) &&
+                      (s->config.geom.h == s2->config.geom.h))
+               {
+                  s->config.relative.mode = E_RANDR2_RELATIVE_CLONE;
+               }
+             if (s->config.relative.align < 0.0)
+               s->config.relative.align = 0.0;
+             else if (s->config.relative.align > 1.0)
+               s->config.relative.align = 1.0;
+          }
+     }
+}
+
 static E_Randr2 *
 _drm_randr_create(void)
 {
@@ -159,7 +354,7 @@ _drm_randr_create(void)
              E_Config_Randr2_Screen *cs;
              const Eina_List *m;
              Ecore_Drm_Output_Mode *omode;
-             size_t n, e = 0;
+             // size_t n, e = 0;
              unsigned int j;
              int priority;
              Eina_Bool ok = EINA_FALSE;
@@ -174,15 +369,25 @@ _drm_randr_create(void)
              s->info.connected = ecore_drm_output_connected_get(output);
              printf("DRM RRR: ...... connected %i\n", s->info.connected);
 
-             if (s->info.connected)
+             s->info.screen = _e_mod_drm_output_screen_get(output);
+
+             s->info.edid = ecore_drm_output_edid_get(output);
+             if (s->info.edid)
+               s->id = malloc(strlen(s->info.name) + 1 + strlen(s->info.edid) + 1);
+             else
+               s->id = malloc(strlen(s->info.name) + 1 + 1);
+             if (!s->id)
                {
-                  s->info.edid = ecore_drm_output_edid_get(output);
-                  e = strlen(s->info.edid ?: "");
+                  free(s->info.screen);
+                  free(s->info.edid);
+                  free(s);
+                  continue;
                }
-             n = strlen(s->info.name);
-             s->id = malloc(n + e + 2);
-             eina_str_join_len(s->id, n + e + 2, '/', s->info.name, n, s->info.edid ?: "", e);
-             s->id[n + e + 1] = 0;
+             strcpy(s->id, s->info.name);
+             strcat(s->id, "/");
+             if (s->info.edid) strcat(s->id, s->info.edid);
+
+             printf("DRM RRR: Created Screen: %s\n", s->id);
 
              type = MIN(ecore_drm_output_connector_type_get(output),
                         EINA_C_ARRAY_LENGTH(conn_types) - 1);
@@ -213,8 +418,6 @@ _drm_randr_create(void)
                   s->info.modes = eina_list_append(s->info.modes, rmode);
                }
 
-             /* TODO: this does NOT handle possibles yet */
-
              cs = NULL;
              priority = 0;
              if (e_randr2_cfg)
@@ -237,35 +440,50 @@ _drm_randr_create(void)
              if (!ok)
                {
                   /* get possible crtcs, compare to output_crtc_id_get */
-                  WRN("GET POSSIBLE CRTCS");
+                  for (j = 0; j < dev->crtc_count; j++)
+                    {
+                       if (_e_mod_drm_output_exists(output, dev->crtcs[j]))
+                         {
+                            ok = EINA_TRUE;
+                            possible = EINA_TRUE;
+                            break;
+                         }
+                    }
                }
 
-             if ((ok) && (!possible))
+             if (ok)
                {
-                  unsigned int refresh;
-
-                  ecore_drm_output_position_get(output, &s->config.geom.x,
-                                                &s->config.geom.y);
-                  ecore_drm_output_crtc_size_get(output, &s->config.geom.w,
-                                                 &s->config.geom.h);
-
-                  ecore_drm_output_current_resolution_get(output,
-                                                          &s->config.mode.w,
-                                                          &s->config.mode.h,
-                                                          &refresh);
-                  s->config.mode.refresh = refresh;
-                  s->config.enabled = 
-                    ((s->config.mode.w != 0) && (s->config.mode.h != 0));
-
-                  printf("DRM RRR: '%s' %i %i %ix%i\n", s->info.name,
-                         s->config.geom.x, s->config.geom.y,
-                         s->config.geom.w, s->config.geom.h);
+                  if (!possible)
+                    {
+                       unsigned int refresh;
+
+                       ecore_drm_output_position_get(output, &s->config.geom.x,
+                                                     &s->config.geom.y);
+                       ecore_drm_output_crtc_size_get(output, &s->config.geom.w,
+                                                      &s->config.geom.h);
+
+                       ecore_drm_output_current_resolution_get(output,
+                                                               &s->config.mode.w,
+                                                               &s->config.mode.h,
+                                                               &refresh);
+                       s->config.mode.refresh = refresh;
+                       s->config.enabled = 
+                         ((s->config.mode.w != 0) && (s->config.mode.h != 0));
+
+                       printf("DRM RRR: '%s' %i %i %ix%i\n", s->info.name,
+                              s->config.geom.x, s->config.geom.y,
+                              s->config.geom.w, s->config.geom.h);
+                    }
+
+                  /* TODO: are rotations possible ?? */
                }
 
              r->screens = eina_list_append(r->screens, s);
           }
      }
 
+   _e_mod_drm_relative_fixup(r);
+
    return r;
 }
 
@@ -283,12 +501,12 @@ static void
 _drm_randr_apply(void)
 {
    Ecore_Drm_Device *dev;
-   Ecore_Drm_Output *out, **outconf;
-   E_Randr2_Screen *s, **screenconf;
+   Ecore_Drm_Output *out;
+   E_Randr2_Screen *s;
    const Eina_List *l, *ll;
    int nw, nh, pw, ph, ww, hh;
    int minw, minh, maxw, maxh;
-   int top_priority = 0, i, numout;
+   int top_priority = 0;
 
    /* TODO: what the actual fuck */
 
@@ -296,8 +514,6 @@ _drm_randr_apply(void)
    nh = e_randr2->h;
    EINA_LIST_FOREACH(ecore_drm_devices_get(), l, dev)
      {
-        int outputs_num, crtcs_num;
-
         ecore_drm_screen_size_range_get(dev, &minw, &minh, &maxw, &maxh);
         printf("DRM RRR: size range: %ix%i -> %ix%i\n", minw, minh, maxw, maxh);
 
@@ -313,85 +529,80 @@ _drm_randr_apply(void)
 
         printf("DRM RRR: set vsize: %ix%i\n", ww, hh);
 
-        outputs_num = eina_list_count(dev->outputs);
-        crtcs_num = dev->crtc_count;
-
-        if ((crtcs_num > 0) && (outputs_num > 0))
+        EINA_LIST_FOREACH(e_randr2->screens, ll, s)
           {
-             outconf = calloc(crtcs_num, sizeof(Ecore_Drm_Output *));
-             screenconf = alloca(crtcs_num * sizeof(E_Randr2_Screen *));
-             memset(screenconf, 0, crtcs_num * sizeof(E_Randr2_Screen *));
+             int orient = 0;
+             Ecore_Drm_Output_Mode *mode = NULL;
+
+             printf("DRM RRR: find output for '%s'\n", s->info.name);
 
-             EINA_LIST_FOREACH(e_randr2->screens, ll, s)
+             out = ecore_drm_device_output_name_find(dev, s->info.name);
+             if (!out) continue;
+
+             if (s->config.configured)
                {
-                  printf("DRM RRR: find output for '%s'\n", s->info.name);
+                  printf("\tDRM RRR: configured by E\n");
 
-                  if (s->config.configured)
+                  if (s->config.enabled)
                     {
-                       out = ecore_drm_device_output_name_find(dev, s->info.name);
-                       if (out)
-                         {
-                            printf("DRM RRR:   enabled: %i\n", s->config.enabled);
-                            if (s->config.enabled)
-                              {
-                                 if (s->config.priority > top_priority)
-                                   top_priority = s->config.priority;
-
-                                 for (i = 0; i < crtcs_num; i++)
-                                   {
-                                      if (!outconf[i])
-                                        {
-                                           printf("DRM RRR:     crtc slot empty: %i\n", i);
-
-                                           /* TODO: get crtc info for dev->crtcs[i] */
-                                           /* check if this output can go on this crtc */
-
-                                           outconf[i] = out;
-                                           screenconf[i] = s;
-
-                                           break;
-                                        }
-                                   }
-                              }
-                         }
+                       printf("\tDRM RRR: Enabled\n");
+                       ecore_drm_output_enable(out);
+                       mode = _e_mod_drm_mode_screen_find(s, out);
+                    }
+                  else
+                    {
+                       printf("\tDRM RRR: Disabled\n");
+                       ecore_drm_output_disable(out);
                     }
-               }
 
-             numout = 0;
-             for (i = 0; i < crtcs_num; i++)
-               if (outconf[i]) numout++;
+                  if (s->config.priority > top_priority)
+                    top_priority = s->config.priority;
 
-             if (numout)
-               {
-                  for (i = 0; i < crtcs_num; i++)
+                  printf("\tDRM RRR: Priority: %d\n", s->config.priority);
+
+                  printf("\tDRM RRR: Geom: %d %d %d %d\n", 
+                         s->config.geom.x, s->config.geom.y,
+                         s->config.geom.w, s->config.geom.h);
+
+                  if (mode)
                     {
-                       /* TODO: find clones */
-                       if (outconf[i])
-                         {
-                            int orient = 0;
-                            Ecore_Drm_Output_Mode *mode;
-
-                            mode = _e_mod_drm_mode_screen_find(screenconf[i],
-                                                               outconf[i]);
-                            printf("DRM RRR: crtc on: %i = '%s'     @ %i %i    - %ix%i orient %i mode %s out %s\n",
-                                   i, screenconf[i]->info.name,
-                                   screenconf[i]->config.geom.x,
-                                   screenconf[i]->config.geom.y,
-                                   screenconf[i]->config.geom.w,
-                                   screenconf[i]->config.geom.h,
-                                   orient, mode->info.name,
-                                   ecore_drm_output_name_get(outconf[i]));
-                         }
+                       printf("\tDRM RRR: Found Valid Drm Mode\n");
+                       printf("\t\tDRM RRR: %dx%d\n", mode->width, mode->height);
                     }
+                  else
+                    printf("\tDRM RRR: No Valid Drm Mode Found\n");
+
+                  if (s->config.rotation == 0)
+                    orient = (1 << 0);
+                  else if (s->config.rotation == 90)
+                    orient = (1 << 1);
+                  else if (s->config.rotation == 180)
+                    orient = (1 << 2);
+                  else if (s->config.rotation == 270)
+                    orient = (1 << 3);
+
+                  ecore_drm_output_mode_set(out, mode,
+                                            s->config.geom.x, s->config.geom.y);
+                  if (s->config.priority == top_priority)
+                    ecore_drm_output_primary_set(out);
+
+                  printf("\tDRM RRR: Mode\n");
+                  printf("\t\tDRM RRR: Geom: %d %d\n",
+                         s->config.mode.w, s->config.mode.h);
+                  printf("\t\tDRM RRR: Refresh: %f\n", s->config.mode.refresh);
+                  printf("\t\tDRM RRR: Preferred: %d\n",
+                         s->config.mode.preferred);
+
+                  printf("\tDRM RRR: Rotation: %d\n", s->config.rotation);
+
+                  printf("\tDRM RRR: Relative Mode: %d\n",
+                         s->config.relative.mode);
+                  printf("\tDRM RRR: Relative To: %s\n",
+                         s->config.relative.to);
+                  printf("\tDRM RRR: Align: %f\n", s->config.relative.align);
                }
-             else
-               printf("DRM RRR: EERRRRRROOOORRRRRRR no outputs to configure!\n");
-
-             free(outconf);
           }
      }
-
-   printf("DRM RRR: set vsize: %ix%i\n", nw, nh);
 }
 
 static E_Comp_Screen_Iface drmiface =