update the texture with lower priority
authorVladimir Nadvornik <nadvornik@suse.cz>
Tue, 14 Aug 2012 21:55:16 +0000 (23:55 +0200)
committerVladimir Nadvornik <nadvornik@suse.cz>
Sat, 18 Aug 2012 17:20:07 +0000 (19:20 +0200)
src/renderer-clutter.c

index cd468d5..59f403c 100644 (file)
@@ -80,8 +80,9 @@ struct _RendererClutter
        gint stereo_off_x;
        gint stereo_off_y;
        
-       gint x_scroll;  /* allow local adjustment and mirroring */
-       gint y_scroll;
+       
+       GList *pending_updates;
+       gint idle_update;
        
        GtkWidget *widget; /* widget and stage may be shared with other renderers */
        ClutterActor *stage;
@@ -89,6 +90,16 @@ struct _RendererClutter
        ClutterActor *group;
 };
 
+typedef struct _RendererClutterAreaParam RendererClutterAreaParam;
+struct _RendererClutterAreaParam {
+       RendererClutter *rc;
+       gint x;
+       gint y;
+       gint w;
+       gint h;
+};
+
+
 static void rc_sync_actor(RendererClutter *rc)
 {
        PixbufRenderer *pr = rc->pr;
@@ -98,7 +109,7 @@ static void rc_sync_actor(RendererClutter *rc)
        clutter_actor_set_anchor_point(CLUTTER_ACTOR(rc->texture), 0, 0);
 
        printf("scale %d %d\n", rc->pr->width, rc->pr->height);
-       printf("pos   %d %d        %d %d\n", rc->pr->x_offset, rc->pr->y_offset, rc->x_scroll, rc->y_scroll);
+       printf("pos   %d %d\n", rc->pr->x_offset, rc->pr->y_offset);
        
        switch (pr->orientation)
                {
@@ -207,34 +218,85 @@ static void rc_sync_actor(RendererClutter *rc)
 
 }
 
+#define MAX_REGION_AREA (8192 * 1024)
 
-static void renderer_area_changed(void *renderer, gint src_x, gint src_y, gint src_w, gint src_h)
+static gboolean renderer_area_changed_cb(gpointer data)
 {
-       RendererClutter *rc = (RendererClutter *)renderer;
+       RendererClutter *rc = (RendererClutter *)data;
        PixbufRenderer *pr = rc->pr;
        
+       RendererClutterAreaParam *par = rc->pending_updates->data;
        
+       gint h = MAX_REGION_AREA / par->w;
+       if (h == 0) h = 1;
+       if (h > par->h) h = par->h;
        
-       printf("renderer_area_changed %d %d %d %d\n", src_x, src_y, src_w, src_h);
+       
+       printf("renderer_area_changed_cb %d %d %d %d  (%d)\n", par->x, par->y, par->w, h, par->h);
        if (pr->pixbuf)
                {
                CoglHandle texture = clutter_texture_get_cogl_texture(CLUTTER_TEXTURE(rc->texture));
                
                cogl_texture_set_region(texture,
-                                       src_x,
-                                       src_y,
-                                       src_x,
-                                       src_y,
-                                       src_w,
-                                       src_h,
-                                       src_w,
-                                       src_h,
+                                       par->x,
+                                       par->y,
+                                       par->x,
+                                       par->y,
+                                       par->w,
+                                       h,
+                                       par->w,
+                                       h,
                                        gdk_pixbuf_get_has_alpha(pr->pixbuf) ? COGL_PIXEL_FORMAT_RGBA_8888 : COGL_PIXEL_FORMAT_RGB_888,
                                        gdk_pixbuf_get_rowstride(pr->pixbuf),
                                        gdk_pixbuf_get_pixels(pr->pixbuf));
+               }
+               
+       par->y += h;
+       par->h -= h;
+       
+       if (par->h == 0)
+               {
+               rc->pending_updates = g_list_remove(rc->pending_updates, par);
+               g_free(par);
+               }
+       if (!rc->pending_updates)
+               {
                clutter_actor_queue_redraw(CLUTTER_ACTOR(rc->texture));
+               rc->idle_update = 0;
+               return FALSE;
                }
+       return TRUE;
+}
 
+
+static void renderer_area_changed(void *renderer, gint src_x, gint src_y, gint src_w, gint src_h)
+{
+       RendererClutter *rc = (RendererClutter *)renderer;
+       PixbufRenderer *pr = rc->pr;
+       
+       RendererClutterAreaParam *par = g_new0(RendererClutterAreaParam, 1);
+       par->rc = rc;
+       par->x = src_x;
+       par->y = src_y;
+       par->w = src_w;
+       par->h = src_h;
+       rc->pending_updates = g_list_append(rc->pending_updates, par);
+       if (!rc->idle_update) 
+               {
+               rc->idle_update = g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, renderer_area_changed_cb, rc, NULL);
+               }
+}
+
+static void renderer_remove_pending_updates(RendererClutter *rc)
+{
+       if (rc->idle_update) g_idle_remove_by_data(rc);
+       rc->idle_update = 0;
+       while (rc->pending_updates)
+               {
+               RendererClutterAreaParam *par = rc->pending_updates->data;
+               rc->pending_updates = g_list_remove(rc->pending_updates, par);
+               g_free(par);
+               }
 }
 
 static void renderer_update_pixbuf(void *renderer, gboolean lazy)
@@ -242,6 +304,8 @@ static void renderer_update_pixbuf(void *renderer, gboolean lazy)
        RendererClutter *rc = (RendererClutter *)renderer;
        PixbufRenderer *pr = rc->pr;
        
+       renderer_remove_pending_updates(rc);
+       
        if (pr->pixbuf)
                {
                gint width = gdk_pixbuf_get_width(pr->pixbuf);
@@ -383,6 +447,8 @@ static void renderer_stereo_set(void *renderer, gint stereo_mode)
 static void renderer_free(void *renderer)
 {
        RendererClutter *rc = (RendererClutter *)renderer;
+       renderer_remove_pending_updates(rc);
+       
        GtkWidget *widget = gtk_bin_get_child(GTK_BIN(rc->pr));
        if (widget)
                {
@@ -430,6 +496,8 @@ RendererFuncs *renderer_clutter_new(PixbufRenderer *pr)
        rc->stereo_off_x = 0;
        rc->stereo_off_y = 0;
 
+       rc->idle_update = 0;
+       rc->pending_updates = NULL;
 
        rc->widget = gtk_bin_get_child(GTK_BIN(rc->pr));