trap shaped x11 clients and prevent compositor blocking with high rect count
authorMike Blumenkrantz <zmike@osg.samsung.com>
Wed, 14 Oct 2015 16:51:45 +0000 (12:51 -0400)
committerMike Blumenkrantz <zmike@osg.samsung.com>
Wed, 14 Oct 2015 16:59:14 +0000 (12:59 -0400)
in the case where a shaped window with many rects exists, there is a high
probability of the damage rect count being huge, leading to massive blocking for
each frame as the compositor attempts to fetch all of these rects from the xserver.

instead, the compositor can shortcut this by forcing a full-window damage any time
the rect count is sufficiently high, trading a blocking socket operation for some
amount of (potential) overdraw.

testing in affected scenarios has shown huge improvements: where previously the entire
compositor would lock up, things work as expected now

see https://bugzilla.mozilla.org/show_bug.cgi?id=1214746 for a sample case

src/bin/e_comp_x.c

index dadc70a404615d2b743a89b3d5fcb91ecccfe598..9600e4f42c826ed795002e4cde9bd13afa047000 100644 (file)
@@ -2804,15 +2804,13 @@ _e_comp_x_damage(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Dam
    E_Client *ec;
    Ecore_X_Rectangle *rects = NULL;
    int n = 0;
-   Eina_Bool skip = EINA_FALSE;
+   Eina_Bool skip;
 
    ec = _e_comp_x_client_find_by_damage(ev->damage);
    if ((!ec) || e_object_is_del(E_OBJECT(ec))) return ECORE_CALLBACK_PASS_ON;
+   skip = ec->shape_rects_num > 50;
    if (ec->override && (!_e_comp_x_client_data_get(ec)->first_damage))
-     {
-        e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
-        skip = EINA_TRUE;
-     }
+     skip = EINA_TRUE;
    if (_e_comp_x_client_data_get(ec)->damage)
      {
         Ecore_X_Region parts;
@@ -2828,6 +2826,8 @@ _e_comp_x_damage(void *data EINA_UNUSED, int type EINA_UNUSED, Ecore_X_Event_Dam
 
    if (e_comp->nocomp)
      e_pixmap_dirty(ec->pixmap);
+   else if (skip)
+     e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
    else if (n)
      {
         int i;