evas - work on evas render2 and begin making it work at all
authorCarsten Haitzler (Rasterman) <raster@rasterman.com>
Wed, 16 Jul 2014 11:42:34 +0000 (20:42 +0900)
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>
Wed, 16 Jul 2014 11:43:32 +0000 (20:43 +0900)
src/Makefile_Evas.am
src/lib/evas/canvas/evas_object_main.c
src/lib/evas/canvas/evas_render2.c
src/lib/evas/canvas/evas_render2.h [new file with mode: 0644]
src/lib/evas/canvas/evas_render2_updates.c [new file with mode: 0644]

index 8094b7d..3372143 100644 (file)
@@ -240,6 +240,8 @@ lib/evas/canvas/evas_font_dir.c \
 lib/evas/canvas/evas_rectangle.c \
 lib/evas/canvas/evas_render.c \
 lib/evas/canvas/evas_render2.c \
+lib/evas/canvas/evas_render2.h \
+lib/evas/canvas/evas_render2_updates.c \
 lib/evas/canvas/evas_smart.c \
 lib/evas/canvas/evas_stack.c \
 lib/evas/canvas/evas_async_events.c \
index e8975c8..8c710bc 100644 (file)
@@ -224,6 +224,7 @@ evas_object_change(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj)
         obj->changed_move = EINA_FALSE;
      }
 
+   if (obj->smart.smart) printf("change smart %p %i\n", obj, obj->changed);
    if (obj->changed) return;
 
    evas_render_object_recalc(eo_obj);
index 7957b97..714ec52 100644 (file)
@@ -1,14 +1,4 @@
-#include "evas_common_private.h"
-#include "evas_private.h"
-#include <math.h>
-#include <assert.h>
-#ifdef EVAS_CSERVE2
-#include "evas_cs2_private.h"
-#endif
-
-#ifdef EVAS_RENDER_DEBUG_TIMING
-#include <sys/time.h>
-#endif
+#include "evas_render2.h"
 
 //////////////////////////////////////////////////////////////////////////////
 // this is the start of a rewrite of the evas rendering infra. first port of
 
 // data types
 //////////////////////////////////////////////////////////////////////////////
-typedef struct Update Update;
+typedef struct _Update Update;
 
 struct _Update
 {
-   Eina_Rectangle area;
+   Eina_Rectangle *area;
    void *surface;
 };
 
@@ -47,11 +37,10 @@ static void _evas_render2_wakeup_cb(void *target, Evas_Callback_Type type, void
 static void _evas_render2_wakeup_send(void *data);
 static void _evas_render2_always_call(Eo *eo_e, Evas_Callback_Type type, void *event_info);
 static void _evas_render2_updates_clean(Evas_Public_Data *e);
-static void _evas_render2_stage_last(Eo *eo_e, Eina_Bool make_updates);
-static void _evas_render2_stage_generate_object_updates(Evas_Public_Data *e);
+static void _evas_render2_stage_last(Eo *eo_e, Eina_Bool make_updates, Eina_Bool do_async);
 static void _evas_render2_stage_explicit_updates(Evas_Public_Data *e);
 static void _evas_render2_stage_main_render_prepare(Evas_Public_Data *e);
-static void _evas_render2_stage_render_do(Evas_Public_Data *e);
+static void _evas_render2_stage_render_do(Evas_Public_Data *e, Eina_Bool do_async);
 static void _evas_render2_stage_reset(Evas_Public_Data *e);
 static void _evas_render2_stage_object_cleanup(Evas_Public_Data *e);
 static void _evas_render2_th_render(void *data);
@@ -93,7 +82,7 @@ _evas_render2_all_sync(void)
 {
    // wait for ALL canvases to stop rendering
    Eo *eo_e;
-   
+
    if (!_rendering) return;
    eo_e = eina_list_data_get(eina_list_last(_rendering));
    _evas_render2_wait(eo_e);
@@ -120,7 +109,7 @@ static void
 _evas_render2_always_call(Eo *eo_e, Evas_Callback_Type type, void *event_info)
 {
    int freeze_num = 0, i;
-   
+
    eo_do(eo_e, freeze_num = eo_event_freeze_count_get());
    for (i = 0; i < freeze_num; i++) eo_do(eo_e, eo_event_thaw());
    evas_event_callback_call(eo_e, type, event_info);
@@ -130,21 +119,19 @@ _evas_render2_always_call(Eo *eo_e, Evas_Callback_Type type, void *event_info)
 static void
 _evas_render2_updates_clean(Evas_Public_Data *e)
 {
-   Update *u;
+   void *u;
 
    // clean out updates and tmp surfaces we were holding/tracking
-   EINA_LIST_FREE(e->render.updates, u)
-     {
-        //evas_cache_image_drop(u->surface);
-        free(u);
-     }
+   EINA_LIST_FREE(e->render.updates, u) eina_rectangle_free(u);
 }
 
 static void
-_evas_render2_stage_last(Eo *eo_e, Eina_Bool make_updates)
+_evas_render2_stage_last(Eo *eo_e, Eina_Bool make_updates, Eina_Bool do_async)
 {
    Evas_Public_Data *e = eo_data_scope_get(eo_e, EVAS_CANVAS_CLASS);
-   
+   Eina_List *ret_updates = NULL;
+   Evas_Event_Render_Post post;
+
    // XXX:
    // XXX: actually update screen from mainloop here if needed - eg software
    // XXX: engine needs to xshmputimage here - engine func does this
@@ -153,7 +140,22 @@ _evas_render2_stage_last(Eo *eo_e, Eina_Bool make_updates)
    // if we did do rendering flush output to target and call callbacks
    if (e->render.updates)
      {
+        Update *ru;
+
         _evas_render2_always_call(eo_e, EVAS_CALLBACK_RENDER_FLUSH_PRE, NULL);
+        EINA_LIST_FREE(e->render.updates, ru)
+          {
+             /* punch rect out */
+             e->engine.func->output_redraws_next_update_push
+             (e->engine.data.output, ru->surface,
+              ru->area->x, ru->area->y, ru->area->w, ru->area->h,
+              EVAS_RENDER_MODE_ASYNC_END);
+             ret_updates = eina_list_append(ret_updates, ru->area);
+             evas_cache_image_drop(ru->surface);
+             free(ru);
+          }
+        if (do_async) post.updated_area = ret_updates;
+        else e->render.updates = ret_updates;
         e->engine.func->output_flush(e->engine.data.output,
                                      EVAS_RENDER_MODE_ASYNC_END);
         _evas_render2_always_call(eo_e, EVAS_CALLBACK_RENDER_FLUSH_POST, NULL);
@@ -164,13 +166,8 @@ _evas_render2_stage_last(Eo *eo_e, Eina_Bool make_updates)
    _rendering = eina_list_remove(_rendering, eo_e);
    e->rendering = EINA_FALSE;
    // call the post render callback with info if appropriate
-   if ((1) || (e->render.updates))
-     {
-        Evas_Event_Render_Post post;
-        
-        post.updated_area = e->render.updates;
-        _evas_render2_always_call(eo_e, EVAS_CALLBACK_RENDER_POST, &post);
-     }
+   if (do_async)
+     _evas_render2_always_call(eo_e, EVAS_CALLBACK_RENDER_POST, &post);
    else
      _evas_render2_always_call(eo_e, EVAS_CALLBACK_RENDER_POST, NULL);
    // if we don't want to keep updates after this
@@ -180,47 +177,6 @@ _evas_render2_stage_last(Eo *eo_e, Eina_Bool make_updates)
 }
 
 static void
-_evas_render2_object_basic_process(Evas_Public_Data *e,
-                                   Evas_Object_Protected_Data *obj)
-{
-   printf("_evas_render2_object_basic_process %p %p\n", e, obj);
-}
-
-static void
-_evas_render2_object_process(Evas_Public_Data *e,
-                             Evas_Object_Protected_Data *obj)
-{
-   // process object OR walk through child objects if smart and process those
-   Evas_Object_Protected_Data *obj2;
-
-   // XXX: this needs to become parallel, BUT we need new object methods to
-   // call to make that possible as the current ones work on a single global
-   // engine handle and single orderted redraw queue.
-   if (obj->smart.smart)
-     {
-        EINA_INLIST_FOREACH
-        (evas_object_smart_members_get_direct(obj->object), obj2)
-          _evas_render2_object_process(e, obj2);
-     }
-   else _evas_render2_object_basic_process(e, obj);
-}
-
-static void
-_evas_render2_stage_generate_object_updates(Evas_Public_Data *e)
-{
-   Evas_Layer *lay;
-
-   // XXX: should time this
-   EINA_INLIST_FOREACH(e->layers, lay)
-     {
-        Evas_Object_Protected_Data *obj;
-        
-        EINA_INLIST_FOREACH(lay->objects, obj)
-          _evas_render2_object_process(e, obj);
-     }
-}
-
-static void
 _evas_render2_stage_explicit_updates(Evas_Public_Data *e)
 {
    Eina_Rectangle *r;
@@ -262,12 +218,48 @@ _evas_render2_stage_main_render_prepare(Evas_Public_Data *e)
 }
 
 static void
-_evas_render2_stage_render_do(Evas_Public_Data *e)
+_evas_render2_stage_render_do(Evas_Public_Data *e, Eina_Bool do_async EINA_UNUSED)
 {
-   // XXX:
+   void *surface;
+   int ux, uy, uw, uh;
+   int cx, cy, cw, ch;
+//   Evas_Render_Mode render_mode = EVAS_RENDER_MODE_UNDEF;
+
+//   if (!do_async) render_mode = EVAS_RENDER_MODE_SYNC;
+//   else render_mode = EVAS_RENDER_MODE_ASYNC_INIT;// XXX:
    // XXX: actually render now (either in thread or in mainloop)
    // XXX:
    printf("_evas_render2_stage_render_do %p\n", e);
+   while ((surface =
+           e->engine.func->output_redraws_next_update_get
+           (e->engine.data.output,
+            &ux, &uy, &uw, &uh,
+            &cx, &cy, &cw, &ch)))
+     {
+        Update *ru = NULL;
+        void *ctx;
+
+        ctx = e->engine.func->context_new(e->engine.data.output);
+        e->engine.func->context_color_set
+          (e->engine.data.output, ctx,
+              rand() & 0xff, rand() & 0xff, rand() & 0xff, 0xff);
+        printf("%i %i %i %i\n", cx, cy, cw, ch);
+        e->engine.func->rectangle_draw(e->engine.data.output,
+                                       ctx, surface,
+                                       cx, cy, cw, ch,
+                                       EINA_FALSE);
+        e->engine.func->context_free(e->engine.data.output, ctx);
+        ru = malloc(sizeof(*ru));
+        ru->surface = surface;
+        NEW_RECT(ru->area, ux, uy, uw, uh);
+        e->render.updates = eina_list_append(e->render.updates, ru);
+        evas_cache_image_ref(surface);
+//        e->engine.func->output_redraws_next_update_push(e->engine.data.output,
+//                                                        surface,
+//                                                        ux, uy, uw, uh,
+//                                                        render_mode);
+     }
+   e->engine.func->output_redraws_clear(e->engine.data.output);
 }
 
 static void
@@ -295,8 +287,8 @@ static void
 _evas_render2_th_render(void *data)
 {
    Evas_Public_Data *e = data;
-   printf("th rend %p\n", e);
-   _evas_render2_stage_render_do(e);
+   printf("th rend %p ......................................\n", e);
+   _evas_render2_stage_render_do(e, EINA_TRUE);
 }
 
 // major functions (called from evas_render.c)
@@ -310,7 +302,7 @@ _evas_render2_begin(Eo *eo_e, Eina_Bool make_updates,
                     Eina_Bool do_draw, Eina_Bool do_async)
 {
    Evas_Public_Data *e = eo_data_scope_get(eo_e, EVAS_CANVAS_CLASS);
-   
+
    // if nothing changed at all since last render - skip this frame
    if (!e->changed) return EINA_FALSE;
    // we are still rendering while being asked to render - skip this frame
@@ -344,15 +336,23 @@ _evas_render2_begin(Eo *eo_e, Eina_Bool make_updates,
              evas_thread_queue_flush(_evas_render2_wakeup_send, eo_e);
           }
         // or if not async, do rendering inline now
-        else _evas_render2_stage_render_do(e);
+        else _evas_render2_stage_render_do(e, EINA_FALSE);
      }
    // reset flags since rendering is processed now
    _evas_render2_stage_reset(e);
    // clean/delete/gc objects here
    _evas_render2_stage_object_cleanup(e);
    // if we are not going to be async then do last render stage here
-   if (!do_async) _evas_render2_stage_last(eo_e, make_updates);
+   if (!do_async) _evas_render2_stage_last(eo_e, make_updates, EINA_FALSE);
    if (!do_draw) _evas_render2_updates_clean(e);
+
+   e->changed = EINA_FALSE;
+   e->viewport.changed = EINA_FALSE;
+   e->output.changed = EINA_FALSE;
+   e->framespace.changed = EINA_FALSE;
+   e->invalidate = EINA_FALSE;
+
+   evas_module_clean();
    return EINA_TRUE;
 }
 
@@ -365,7 +365,7 @@ _evas_render2_end(Eo *eo_e)
    // this is actually called if rendering was async and is done. this is
    // run in the mainloop where rendering began and may handle any cleanup
    // or pixel upload if needed here
-   _evas_render2_stage_last(eo_e, EINA_TRUE);
+   _evas_render2_stage_last(eo_e, EINA_TRUE, EINA_TRUE);
    // release canvas object ref
    eo_unref(eo_e);
 }
diff --git a/src/lib/evas/canvas/evas_render2.h b/src/lib/evas/canvas/evas_render2.h
new file mode 100644 (file)
index 0000000..2eb77e7
--- /dev/null
@@ -0,0 +1,43 @@
+#ifndef EVAS_RENDER2_H
+#define EVAS_RENDER2_H
+#include "evas_common_private.h"
+#include "evas_private.h"
+#include <math.h>
+#include <assert.h>
+#ifdef EVAS_CSERVE2
+#include "evas_cs2_private.h"
+#endif
+
+#ifdef EVAS_RENDER_DEBUG_TIMING
+#include <sys/time.h>
+#endif
+
+/* render stuff here */
+void _evas_render2_stage_generate_object_updates(Evas_Public_Data *e);
+
+#ifndef _WIN32
+static inline double
+get_time(void)
+{
+   struct timeval      timev;
+   gettimeofday(&timev, NULL);
+   return (double)timev.tv_sec + (((double)timev.tv_usec) / 1000000);
+}
+#else
+static inline double
+get_time(void)
+{
+   return (double)GetTickCount()/1000.0;
+}
+#endif
+
+static inline void
+out_time(double t)
+{
+   double b;
+
+   b = (t * 100.0) / (1.0 / 60.0);
+   printf("%1.8fs (%1.2f%% 60fps budget)\n", t, b);
+}
+
+#endif
diff --git a/src/lib/evas/canvas/evas_render2_updates.c b/src/lib/evas/canvas/evas_render2_updates.c
new file mode 100644 (file)
index 0000000..50f69b6
--- /dev/null
@@ -0,0 +1,77 @@
+#include "evas_render2.h"
+
+static void
+_obj_basic_process(Evas_Public_Data *e,
+                   Evas_Object_Protected_Data *obj, int l)
+{
+   Evas_Object *eo_obj = obj->object;
+
+   obj->rect_del = EINA_FALSE;
+   obj->render_pre = EINA_FALSE;
+   if (obj->delete_me == 2) return;
+   else if (obj->delete_me != 0) obj->delete_me++;
+   evas_object_clip_recalc(obj);
+   obj->is_active = 1;
+   obj->func->render_pre(eo_obj, obj, obj->private_data);
+   obj->pre_render_done = EINA_TRUE;
+   int i; for (i = 0; i < l; i++) printf(" ");
+   printf("BASIC %p %p\n", e, obj);
+   obj->func->render_post(eo_obj, obj, obj->private_data);
+   obj->restack = EINA_FALSE;
+   obj->pre_render_done = EINA_FALSE;
+   evas_object_change_reset(eo_obj);
+}
+
+static void
+_obj_process(Evas_Public_Data *e,
+             Evas_Object_Protected_Data *obj, int l)
+{
+   // process object OR walk through child objects if smart and process those
+   Evas_Object_Protected_Data *obj2;
+   Evas_Object *eo_obj = obj->object;
+
+   if (obj->smart.smart)
+     {
+        if (!evas_object_smart_changed_get(eo_obj)) return;
+        obj->rect_del = EINA_FALSE;
+        obj->render_pre = EINA_FALSE;
+        if (obj->delete_me == 2) return;
+        else if (obj->delete_me != 0) obj->delete_me++;
+        evas_object_clip_recalc(obj);
+        obj->is_active = 1;
+        obj->func->render_pre(eo_obj, obj, obj->private_data);
+        obj->pre_render_done = EINA_TRUE;
+        int i; for (i = 0; i < l; i++) printf(" ");
+        printf("SMART %p %p\n", e, obj);
+
+        EINA_INLIST_FOREACH
+        (evas_object_smart_members_get_direct(obj->object), obj2)
+          _obj_process(e, obj2, l + 1);
+
+        obj->func->render_post(eo_obj, obj, obj->private_data);
+        obj->restack = EINA_FALSE;
+        obj->pre_render_done = EINA_FALSE;
+        evas_object_change_reset(eo_obj);
+     }
+   else
+     {
+        if (!obj->changed) return;
+        _obj_basic_process(e, obj, l);
+     }
+}
+
+void
+_evas_render2_stage_generate_object_updates(Evas_Public_Data *e)
+{
+   Evas_Layer *lay;
+   Evas_Object_Protected_Data *obj;
+   double t;
+
+   t = get_time();
+   EINA_INLIST_FOREACH(e->layers, lay)
+     {
+        EINA_INLIST_FOREACH(lay->objects, obj) _obj_process(e, obj, 0);
+     }
+   t = get_time() - t;
+   printf("T: update generation: "); out_time(t);
+}