Author: Carlos Lopez <[email protected]>
Date: Tue Mar 12 20:10:56 2013 +0100
New class AsyncTarget_Cairo_Tile to render the tiles asynchronously .
---
synfig-studio/src/gui/asyncrenderer.cpp | 199 +++++++++++++++++++++++++++++++
synfig-studio/src/gui/asyncrenderer.h | 1 +
2 files changed, 200 insertions(+), 0 deletions(-)
diff --git a/synfig-studio/src/gui/asyncrenderer.cpp
b/synfig-studio/src/gui/asyncrenderer.cpp
index 7edb5b0..331b294 100644
--- a/synfig-studio/src/gui/asyncrenderer.cpp
+++ b/synfig-studio/src/gui/asyncrenderer.cpp
@@ -241,6 +241,192 @@ public:
}
};
+class AsyncTarget_Cairo_Tile : public synfig::Target_Cairo_Tile
+{
+public:
+ etl::handle<synfig::Target_Cairo_Tile> warm_target;
+
+ class tile_t
+ {
+ public:
+ cairo_surface_t* surface;
+ int x,y;
+ tile_t(): surface(NULL), x(0), y(0)
+ {
+ }
+ tile_t(cairo_surface_t*& surface_,int x_, int y_)
+ {
+ if(surface_)
+ surface=cairo_surface_reference(surface_);
+ else
+ surface=surface_;
+ x=x_;
+ y=y_;
+ }
+ tile_t(const tile_t &other):
+ surface(cairo_surface_reference(other.surface)),
+ x(other.x),
+ y(other.y)
+ {
+ }
+ ~tile_t()
+ {
+ if(surface)
+ cairo_surface_destroy(surface);
+ }
+ };
+ std::list<tile_t> tile_queue;
+ Glib::Mutex mutex;
+
+#ifndef GLIB_DISPATCHER_BROKEN
+ Glib::Dispatcher tile_ready_signal;
+#endif
+ Glib::Cond cond_tile_queue_empty;
+ bool alive_flag;
+
+ sigc::connection ready_connection;
+
+public:
+ AsyncTarget_Cairo_Tile(etl::handle<synfig::Target_Cairo_Tile>
warm_target):
+ warm_target(warm_target)
+ {
+ set_avoid_time_sync(warm_target->get_avoid_time_sync());
+ set_tile_w(warm_target->get_tile_w());
+ set_tile_h(warm_target->get_tile_h());
+ set_canvas(warm_target->get_canvas());
+ set_quality(warm_target->get_quality());
+ set_remove_alpha(warm_target->get_remove_alpha());
+ set_threads(warm_target->get_threads());
+ set_clipping(warm_target->get_clipping());
+ set_rend_desc(&warm_target->rend_desc());
+ alive_flag=true;
+#ifndef GLIB_DISPATCHER_BROKEN
+
ready_connection=tile_ready_signal.connect(sigc::mem_fun(*this,&AsyncTarget_Cairo_Tile::tile_ready));
+#endif
+ }
+
+ ~AsyncTarget_Cairo_Tile()
+ {
+ ready_connection.disconnect();
+ }
+ void set_dead()
+ {
+ Glib::Mutex::Lock lock(mutex);
+ alive_flag=false;
+ }
+
+ virtual int total_tiles()const
+ {
+ return warm_target->total_tiles();
+ }
+
+ virtual int next_tile(int& x, int& y)
+ {
+ if(!alive_flag)
+ return 0;
+
+ return warm_target->next_tile(x,y);
+ }
+
+ virtual int next_frame(Time& time)
+ {
+ if(!alive_flag)
+ return 0;
+ return warm_target->next_frame(time);
+ }
+
+ virtual bool start_frame(synfig::ProgressCallback *cb=0)
+ {
+ if(!alive_flag)
+ return false;
+ return warm_target->start_frame(cb);
+ }
+
+ virtual bool add_tile(cairo_surface_t*& surface, int gx, int gy)
+ {
+ if(cairo_surface_status(surface))
+ return false;
+ if(!alive_flag)
+ return false;
+ Glib::Mutex::Lock lock(mutex);
+ tile_queue.push_back(tile_t(surface,gx,gy));
+ if(tile_queue.size()==1)
+ {
+#ifdef GLIB_DISPATCHER_BROKEN
+ ready_connection=Glib::signal_timeout().connect(
+ sigc::bind_return(
+
sigc::mem_fun(*this,&AsyncTarget_Cairo_Tile::tile_ready),
+ false
+ )
+ ,0
+ );
+#else
+ tile_ready_signal();
+#endif
+ }
+ //cairo_surface_destroy(surface);
+ return alive_flag;
+ }
+
+ void tile_ready()
+ {
+ Glib::Mutex::Lock lock(mutex);
+ if(!alive_flag)
+ {
+ tile_queue.clear();
+ cond_tile_queue_empty.signal();
+ return;
+ }
+ while(!tile_queue.empty() && alive_flag)
+ {
+ tile_t& tile(tile_queue.front());
+
+// if (getenv("SYNFIG_SHOW_TILE_OUTLINES"))
+// {
+// Color red(1,0,0);
+// tile.surface.fill(red, 0, 0, 1,
tile.surface.get_h());
+// tile.surface.fill(red, 0, 0,
tile.surface.get_w(), 1);
+// }
+
+
alive_flag=warm_target->add_tile(tile.surface,tile.x,tile.y);
+
+ tile_queue.pop_front();
+ }
+ cond_tile_queue_empty.signal();
+ }
+
+ virtual void end_frame()
+ {
+#ifdef SINGLE_THREADED
+ if (!single_threaded())
+ {
+#endif
+ while(alive_flag)
+ {
+ Glib::Mutex::Lock lock(mutex);
+ Glib::TimeVal end_time;
+
+ end_time.assign_current_time();
+ end_time.add_microseconds(BOREDOM_TIMEOUT);
+
+ if(!tile_queue.empty() && alive_flag)
+ {
+
if(cond_tile_queue_empty.timed_wait(mutex,end_time))
+ break;
+ }
+ else
+ break;
+ }
+#ifdef SINGLE_THREADED
+ }
+#endif
+ Glib::Mutex::Lock lock(mutex);
+ if(!alive_flag)
+ return;
+ return warm_target->end_frame();
+ }
+};
+
class AsyncTarget_Scanline : public synfig::Target_Scanline
@@ -528,6 +714,19 @@ AsyncRenderer::AsyncRenderer(etl::handle<synfig::Target>
target_,synfig::Progres
target=wrap_target;
}
+ else if(etl::handle<synfig::Target_Cairo_Tile>::cast_dynamic(target_))
+ {
+ etl::handle<AsyncTarget_Cairo_Tile> wrap_target(
+ new AsyncTarget_Cairo_Tile(
+
etl::handle<synfig::Target_Cairo_Tile>::cast_dynamic(target_)
+ )
+ );
+
+
signal_stop_.connect(sigc::mem_fun(*wrap_target,&AsyncTarget_Cairo_Tile::set_dead));
+
+ target=wrap_target;
+ }
+
else if(etl::handle<synfig::Target_Cairo>::cast_dynamic(target_))
{
etl::handle<AsyncTarget_Cairo> wrap_target(
diff --git a/synfig-studio/src/gui/asyncrenderer.h
b/synfig-studio/src/gui/asyncrenderer.h
index a7bf5b3..306f337 100644
--- a/synfig-studio/src/gui/asyncrenderer.h
+++ b/synfig-studio/src/gui/asyncrenderer.h
@@ -36,6 +36,7 @@
#include <synfig/target_scanline.h>
#include <synfig/target_tile.h>
#include <synfig/target_cairo.h>
+#include <synfig/target_cairo_tile.h>
#include <synfig/surface.h>
#include <glibmm/main.h>
#include <ETL/ref_count>
------------------------------------------------------------------------------
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
http://p.sf.net/sfu/appdyn_d2d_mar
_______________________________________________
Synfig-devl mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/synfig-devl