evas/render: size and draw proxy render surface based on proxy clipper
authorMike Blumenkrantz <zmike@samsung.com>
Fri, 10 May 2019 18:14:49 +0000 (14:14 -0400)
committerJaehyun Cho <jae_hyun.cho@samsung.com>
Mon, 12 Aug 2019 07:35:38 +0000 (16:35 +0900)
if a proxy is not being proxied, it's optimal to create a surface for only
the necessary dimensions and then only draw within those dimensions.

when a proxy is clipped to a size smaller than the proxy object, the required
size for the proxy render becomes smaller as the proxy has less visible area.
this enables us to draw only the clipped region and thus gives a performance
boost

this can only be enabled if the clipper is marked as static

Reviewed-by: Hermet Park <hermetpark@gmail.com>
Differential Revision: https://phab.enlightenment.org/D8881

src/lib/evas/canvas/evas_render.c

index 2a059cd..7f138d7 100644 (file)
@@ -2340,10 +2340,10 @@ evas_render_proxy_subrender(Evas *eo_e, void *output, Evas_Object *eo_source, Ev
                             Eina_Bool source_clip, Eina_Bool do_async)
 {
    Evas_Public_Data *evas = efl_data_scope_get(eo_e, EVAS_CANVAS_CLASS);
-   Evas_Object_Protected_Data *source;
+   Evas_Object_Protected_Data *source, *proxy;
    int level = 1;
    void *ctx;
-   int w, h;
+   int w, h, off_x = 0, off_y = 0;
 
 #ifdef REND_DBG
    level = __RD_level;
@@ -2352,13 +2352,33 @@ evas_render_proxy_subrender(Evas *eo_e, void *output, Evas_Object *eo_source, Ev
    if (!eo_source) return;
    eina_evlog("+proxy_subrender", eo_proxy, 0.0, NULL);
    source = efl_data_scope_get(eo_source, EFL_CANVAS_OBJECT_CLASS);
+   proxy = efl_data_scope_get(eo_proxy, EFL_CANVAS_OBJECT_CLASS);
 
    // FIXME: This is wrong. Object cache should simply not be trusted for
    // proxy subrender. Forcing recalc will not fix anything.
    evas_render_gurantee_recalc(source->object, source);
 
-   w = source->cur->geometry.w;
-   h = source->cur->geometry.h;
+   if (proxy->proxy->proxies || (!proxy->cur->clipper) || (!proxy->cur->has_fixed_size))
+     {
+        /* make full surface available if this proxy is being sampled from */
+        w = source->cur->geometry.w;
+        h = source->cur->geometry.h;
+     }
+   else
+     {
+        Eina_Rectangle clip = _evas_render_smallest_static_clipped_geometry_get(proxy->cur);
+        /* nothing is using this proxy, so the proxy render surface can be sized
+         * to fit exactly the proxy object's render size, and the proxy render will
+         * naturally be clipped to this geometry
+         */
+        w = clip.w;
+        h = clip.h;
+        /* set the render offset for the proxy offset based on the geometry which will
+         * be visible on the proxy surface after clipping
+         */
+        off_x = proxy->cur->geometry.x - clip.x;
+        off_y = proxy->cur->geometry.y - clip.y;
+     }
 
    RD(level, "  proxy_subrender(source: %s, proxy: %s, %dx%d)\n",
       RDNAME(source), RDNAME(proxy_obj), w, h);
@@ -2411,8 +2431,8 @@ evas_render_proxy_subrender(Evas *eo_e, void *output, Evas_Object *eo_source, Ev
         ctx = ENFN->context_new(ENC);
         evas_render_mapped(evas, eo_source, source, ctx,
                            output, proxy_write->surface,
-                           -source->cur->geometry.x,
-                           -source->cur->geometry.y,
+                           -source->cur->geometry.x + off_x,
+                           -source->cur->geometry.y + off_y,
                            level + 1, 0, 0, evas->output.w, evas->output.h,
                            &proxy_render_data, level + 1, do_async);
         ENFN->context_free(ENC, ctx);