jpeg pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=ef0ec6bed335175d74e64c99d68e07a97110c86d

commit ef0ec6bed335175d74e64c99d68e07a97110c86d
Author: Jean-Philippe Andre <jp.an...@samsung.com>
Date:   Thu Sep 3 17:38:48 2015 +0900

    evas_render: Fix some clipping issues inside proxy
    
    Inside a proxy, clipping information might be wrong since the
    source object may be at a different position than within
    the proxy. If source_clip is not set, then we need to discard
    all clips that are outside the proxy context.
    
    So we just propagate the clip information inside the current
    draw context, and even recurse from clipper to clipper to
    find the final state of clipping.
    
    Map and proxies and others (who said masks?) should definitely
    rely more on the same model.
    
    This code is not a mess. At all. You gotta love evas_render.
---
 src/lib/evas/canvas/evas_canvas3d_texture.c |   1 +
 src/lib/evas/canvas/evas_render.c           | 123 ++++++++++++++++++++++------
 src/lib/evas/include/evas_private.h         |   1 +
 3 files changed, 102 insertions(+), 23 deletions(-)

diff --git a/src/lib/evas/canvas/evas_canvas3d_texture.c 
b/src/lib/evas/canvas/evas_canvas3d_texture.c
index 58c1e28..e01762d 100644
--- a/src/lib/evas/canvas/evas_canvas3d_texture.c
+++ b/src/lib/evas/canvas/evas_canvas3d_texture.c
@@ -137,6 +137,7 @@ _texture_proxy_subrender(Evas_Canvas3D_Texture *obj)
                   .eo_proxy = NULL,
                   .proxy_obj = NULL,
                   .eo_src = pd->source,
+                  .src_obj = source,
                   .source_clip = EINA_FALSE
              };
 
diff --git a/src/lib/evas/canvas/evas_render.c 
b/src/lib/evas/canvas/evas_render.c
index c4fd0ac..37b4a15 100644
--- a/src/lib/evas/canvas/evas_render.c
+++ b/src/lib/evas/canvas/evas_render.c
@@ -1203,6 +1203,31 @@ _evas_render_can_use_overlay(Evas_Public_Data *e, 
Evas_Object *eo_obj)
    return EINA_TRUE;
 }
 
+static Eina_Bool
+_proxy_context_clip(Evas_Public_Data *evas, void *ctx, Evas_Proxy_Render_Data 
*proxy_render_data, Evas_Object_Protected_Data *obj, int off_x, int off_y)
+{
+   const Evas_Coord_Rectangle *clip;
+   Evas_Object_Protected_Data *clipper;
+
+   /* cache.clip can not be relied on, since the evas is frozen, but we need
+    * to set the clip. so we recurse from clipper to clipper until we reach
+    * the source object's clipper */
+
+   if (!proxy_render_data || proxy_render_data->source_clip) return EINA_TRUE;
+   if (!obj || !obj->cur->clipper) return EINA_TRUE;
+
+   clipper = obj->cur->clipper;
+   if (!clipper->cur->visible) return EINA_FALSE;
+   clip = &clipper->cur->geometry;
+   ENFN->context_clip_clip(ENDT, ctx, clip->x + off_x, clip->y + off_y, 
clip->w, clip->h);
+
+   /* stop if we found the source object's clipper */
+   if (clipper == proxy_render_data->proxy_obj->cur->clipper) return EINA_TRUE;
+
+   /* recurse to the clipper itself */
+   return _proxy_context_clip(evas, ctx, proxy_render_data, clipper, off_x, 
off_y);
+}
+
 static void
 _evas_render_mapped_context_clip_set(Evas_Public_Data *evas, Evas_Object 
*eo_obj, Evas_Object_Protected_Data *obj, void *ctx, Evas_Proxy_Render_Data 
*proxy_render_data, int off_x, int off_y)
 {
@@ -1253,9 +1278,9 @@ evas_render_mapped(Evas_Public_Data *evas, Evas_Object 
*eo_obj,
    Eina_Bool proxy_src_clip = EINA_TRUE;
    void *ctx;
 
-   //Don't Render if the source is invisible.
    if (!proxy_render_data)
      {
+        /* don't render if the source is invisible */
         if ((evas_object_is_source_invisible(eo_obj, obj)))
           return clean_them;
      }
@@ -1264,6 +1289,10 @@ evas_render_mapped(Evas_Public_Data *evas, Evas_Object 
*eo_obj,
 
    evas_object_clip_recalc(obj);
 
+   /* leave early if clipper is not visible */
+   if (obj->cur->clipper && !obj->cur->clipper->cur->visible)
+     return clean_them;
+
 #ifdef REND_DBG
    RD(level, "{\n");
    RD(level, "  evas_render_mapped(evas:%p, obj:%p", evas, obj);
@@ -1500,6 +1529,7 @@ evas_render_mapped(Evas_Public_Data *evas, Evas_Object 
*eo_obj,
         /* duplicate context and reset clip */
         ctx = ENFN->context_dup(ENDT, context);
         ENFN->context_clip_unset(ENDT, ctx);
+        //ENFN->context_multiplier_unset(ENDT, ctx); // this probably should 
be here, too
 
         if (obj->map->surface)
           {
@@ -1611,6 +1641,18 @@ evas_render_mapped(Evas_Public_Data *evas, Evas_Object 
*eo_obj,
                                                          evas, do_async);
                          }
                     }
+                  else if (!proxy_src_clip)
+                    {
+                       if (!_proxy_context_clip(evas, ctx, proxy_render_data, 
obj, off_x, off_y))
+                         return clean_them;
+                    }
+
+#ifdef REND_DBG
+                  int _c, _cx, _cy, _cw, _ch;
+                  _c = ENFN->context_clip_get(ENDT, ctx, &_cx, &_cy, &_cw, 
&_ch);
+                  RD(level, "  draw smart children(clip: [%d] %d,%d %dx%d)\n",
+                     _c, _cx, _cy, _cw, _ch);
+#endif
 
                   EINA_INLIST_FOREACH
                      (evas_object_smart_members_get_direct(eo_obj), obj2)
@@ -1634,14 +1676,25 @@ evas_render_mapped(Evas_Public_Data *evas, Evas_Object 
*eo_obj,
                }
              else
                {
+                  const Evas_Coord_Rectangle *clip = &obj->cur->geometry;
+                  ENFN->context_clip_clip(ENDT, ctx, clip->x + off_x, clip->y 
+ off_y, clip->w, clip->h);
+
                   if (obj->cur->clipper && (mapped > 1))
                     {
-                       if (_evas_render_has_map(eo_obj, obj) ||
-                           _evas_render_object_is_mask(obj->cur->clipper))
-                         evas_object_clip_recalc(obj);
-                       _evas_render_mapped_context_clip_set(evas, eo_obj, obj, 
ctx,
-                                                            proxy_render_data,
-                                                            off_x, off_y);
+                       if (proxy_src_clip)
+                         {
+                            if (_evas_render_has_map(eo_obj, obj) ||
+                                _evas_render_object_is_mask(obj->cur->clipper))
+                              evas_object_clip_recalc(obj);
+                            _evas_render_mapped_context_clip_set(evas, eo_obj, 
obj, ctx,
+                                                                 
proxy_render_data,
+                                                                 off_x, off_y);
+                         }
+                       else
+                         {
+                            if (!_proxy_context_clip(evas, ctx, 
proxy_render_data, obj, off_x, off_y))
+                              return clean_them;
+                         }
 
                        /* Clipper masks */
                        if (_evas_render_object_is_mask(obj->cur->clipper))
@@ -1664,11 +1717,13 @@ evas_render_mapped(Evas_Public_Data *evas, Evas_Object 
*eo_obj,
                               }
                          }
                     }
+
 #ifdef REND_DBG
                   int _c, _cx, _cy, _cw, _ch;
                   _c = ENFN->context_clip_get(ENDT, ctx, &_cx, &_cy, &_cw, 
&_ch);
                   RD(level, "  render(clip: [%d] %d,%d %dx%d)\n", _c, _cx, 
_cy, _cw, _ch);
 #endif
+
                   obj->func->render(eo_obj, obj, obj->private_data,
                                     ENDT, ctx, surface, off_x, off_y, 
EINA_FALSE);
                }
@@ -1677,26 +1732,39 @@ evas_render_mapped(Evas_Public_Data *evas, Evas_Object 
*eo_obj,
           }
         else
           {
-             /* in this case we keep the parent context */
+             const Evas_Coord_Rectangle *clip = &obj->cur->geometry;
+
+             ctx = ENFN->context_dup(ENDT, context);
+             ENFN->context_clip_clip(ENDT, ctx, clip->x + off_x, clip->y + 
off_y, clip->w, clip->h);
+
              if (obj->cur->clipper)
                {
                   Evas_Object_Protected_Data *clipper = obj->cur->clipper;
                   int x, y, w, h;
 
-                  if (_evas_render_has_map(eo_obj, obj) ||
-                      _evas_render_object_is_mask(obj->cur->clipper))
-                    evas_object_clip_recalc(obj);
-                  x = obj->cur->cache.clip.x;
-                  y = obj->cur->cache.clip.y;
-                  w = obj->cur->cache.clip.w;
-                  h = obj->cur->cache.clip.h;
-                  RECTS_CLIP_TO_RECT(x, y, w, h,
-                                     clipper->cur->cache.clip.x,
-                                     clipper->cur->cache.clip.y,
-                                     clipper->cur->cache.clip.w,
-                                     clipper->cur->cache.clip.h);
-                  ENFN->context_clip_set(ENDT, context, x + off_x, y + off_y, 
w, h);
-                  ENFN->context_clip_clip(ENDT, context, ecx, ecy, ecw, ech);
+                  if (proxy_src_clip)
+                    {
+                       if (_evas_render_has_map(eo_obj, obj) ||
+                           _evas_render_object_is_mask(obj->cur->clipper))
+                         evas_object_clip_recalc(obj);
+                       x = obj->cur->cache.clip.x;
+                       y = obj->cur->cache.clip.y;
+                       w = obj->cur->cache.clip.w;
+                       h = obj->cur->cache.clip.h;
+                       RECTS_CLIP_TO_RECT(x, y, w, h,
+                                          clipper->cur->cache.clip.x,
+                                          clipper->cur->cache.clip.y,
+                                          clipper->cur->cache.clip.w,
+                                          clipper->cur->cache.clip.h);
+                       ENFN->context_clip_set(ENDT, ctx, x + off_x, y + off_y, 
w, h);
+                       if (proxy_src_clip)
+                         ENFN->context_clip_clip(ENDT, ctx, ecx, ecy, ecw, 
ech);
+                    }
+                  else
+                    {
+                       if (!_proxy_context_clip(evas, ctx, proxy_render_data, 
obj, off_x, off_y))
+                         return clean_them;
+                    }
                }
 
 #ifdef REND_DBG
@@ -1704,9 +1772,11 @@ evas_render_mapped(Evas_Public_Data *evas, Evas_Object 
*eo_obj,
              _c = ENFN->context_clip_get(ENDT, context, &_cx, &_cy, &_cw, 
&_ch);
              RD(level, "  draw normal obj: render(clip: [%d] %d,%d %dx%d)\n", 
_c, _cx, _cy, _cw, _ch);
 #endif
+
              obj->func->render(eo_obj, obj, obj->private_data,
-                               ENDT, context, surface,
+                               ENDT, ctx, surface,
                                off_x, off_y, do_async);
+             ENFN->context_free(ENDT, ctx);
           }
         if (obj->changed_map) clean_them = EINA_TRUE;
      }
@@ -1782,9 +1852,13 @@ evas_render_proxy_subrender(Evas *eo_e, Evas_Object 
*eo_source, Evas_Object *eo_
              .eo_proxy = eo_proxy,
              .proxy_obj = proxy_obj,
              .eo_src = eo_source,
+             .src_obj = source,
              .source_clip = source_clip
         };
 
+        /* protect changes to the objects' cache.clip */
+        evas_event_freeze(evas->evas);
+
         ctx = ENFN->context_new(ENDT);
         evas_render_mapped(evas, eo_source, source, ctx, proxy_write->surface,
                            -source->cur->geometry.x,
@@ -1794,6 +1868,9 @@ evas_render_proxy_subrender(Evas *eo_e, Evas_Object 
*eo_source, Evas_Object *eo_
         ENFN->context_free(ENDT, ctx);
 
         proxy_write->surface = ENFN->image_dirty_region(ENDT, 
proxy_write->surface, 0, 0, w, h);
+
+        /* restore previous state */
+        evas_event_thaw(evas->evas);
      }
  end:
    EINA_COW_WRITE_END(evas_object_proxy_cow, source->proxy, proxy_write);
diff --git a/src/lib/evas/include/evas_private.h 
b/src/lib/evas/include/evas_private.h
index 80c04a0..491344f 100644
--- a/src/lib/evas/include/evas_private.h
+++ b/src/lib/evas/include/evas_private.h
@@ -1824,6 +1824,7 @@ struct _Evas_Proxy_Render_Data
    Evas_Object *eo_proxy;
    Evas_Object_Protected_Data *proxy_obj;
    Evas_Object *eo_src;
+   Evas_Object_Protected_Data *src_obj;
    Eina_Bool source_clip : 1;
 };
 

-- 


Reply via email to