X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=synfig-core%2Ftags%2Fsynfig_0_61_07_rc3%2Fsrc%2Fsynfig%2Ftarget_tile.cpp;fp=synfig-core%2Ftags%2Fsynfig_0_61_07_rc3%2Fsrc%2Fsynfig%2Ftarget_tile.cpp;h=803dbd2511b6e54be09b938151f6016dfd359de3;hb=0e729dddd753ed872265ba82c0089bc55e64bf55;hp=0000000000000000000000000000000000000000;hpb=7a4d1b9ab079cc84ccfb4cf46f074c84b8caef2e;p=synfig.git diff --git a/synfig-core/tags/synfig_0_61_07_rc3/src/synfig/target_tile.cpp b/synfig-core/tags/synfig_0_61_07_rc3/src/synfig/target_tile.cpp new file mode 100644 index 0000000..803dbd2 --- /dev/null +++ b/synfig-core/tags/synfig_0_61_07_rc3/src/synfig/target_tile.cpp @@ -0,0 +1,432 @@ +/* === S Y N F I G ========================================================= */ +/*! \file target_tile.cpp +** \brief Template File +** +** $Id$ +** +** \legal +** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley +** +** This package is free software; you can redistribute it and/or +** modify it under the terms of the GNU General Public License as +** published by the Free Software Foundation; either version 2 of +** the License, or (at your option) any later version. +** +** This package is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +** General Public License for more details. +** \endlegal +*/ +/* ========================================================================= */ + +/* === H E A D E R S ======================================================= */ + +#ifdef USING_PCH +# include "pch.h" +#else +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "target_tile.h" +#include "string.h" +#include "surface.h" +#include "render.h" +#include "canvas.h" +#include "context.h" +#include "general.h" +#include + +#endif + +/* === U S I N G =========================================================== */ + +using namespace std; +using namespace etl; +using namespace synfig; + +/* === M A C R O S ========================================================= */ +const unsigned int DEF_TILE_WIDTH = 64; +const unsigned int DEF_TILE_HEIGHT= 64; + +#define SYNFIG_OPTIMIZE_LAYER_TREE 1 +#ifdef _DEBUG +#define SYNFIG_DISPLAY_EFFICIENCY 1 +#endif + +/* === G L O B A L S ======================================================= */ + +/* === P R O C E D U R E S ================================================= */ + +/* === M E T H O D S ======================================================= */ + +Target_Tile::Target_Tile(): + threads_(2), + tile_w_(DEF_TILE_WIDTH), + tile_h_(DEF_TILE_HEIGHT), + curr_tile_(0), + clipping_(true) +{ + curr_frame_=0; +} + +int +Target_Tile::next_frame(Time& time) +{ + int + total_frames(1), + frame_start(0), + frame_end(0); + Time + time_start(0), + time_end(0); + + // If the description's end frame is equal to + // the start frame, then it is assumed that we + // are rendering only one frame. Correct it. + if(desc.get_frame_end()==desc.get_frame_start()) + desc.set_frame_end(desc.get_frame_start()+1); + + frame_start=desc.get_frame_start(); + frame_end=desc.get_frame_end(); + time_start=desc.get_time_start(); + time_end=desc.get_time_end(); + + // Calculate the number of frames + total_frames=frame_end-frame_start; + if(total_frames<=0)total_frames=1; + + //RendDesc rend_desc=desc; + //rend_desc.set_gamma(1); + +// int total_tiles(total_tiles()); + time=(time_end-time_start)*curr_frame_/total_frames+time_start; + curr_frame_++; + +/* synfig::info("curr_frame_: %d",curr_frame_); + synfig::info("total_frames: %d",total_frames); + synfig::info("time_end: %s",time_end.get_string().c_str()); + synfig::info("time_start: %s",time_start.get_string().c_str()); +*/ +// synfig::info("time: %s",time.get_string().c_str()); + + return total_frames- curr_frame_+1; +} + +int +Target_Tile::next_tile(int& x, int& y) +{ + // Width of the image(in tiles) + int tw(rend_desc().get_w()/tile_w_); + int th(rend_desc().get_h()/tile_h_); + + // Add the last tiles (which will be clipped) + if(rend_desc().get_w()%tile_w_!=0)tw++; + if(rend_desc().get_h()%tile_h_!=0)th++; + + x=(curr_tile_%tw)*tile_h_; + y=(curr_tile_/tw)*tile_w_; + + curr_tile_++; + return (tw*th)-curr_tile_+1; +} + +bool +synfig::Target_Tile::render_frame_(Context context,ProgressCallback *cb) +{ + if(tile_w_<=0||tile_h_<=0) + { + if(cb)cb->error(_("Bad Tile Size")); + return false; + } + const RendDesc &rend_desc(desc); +#define total_tiles total_tiles() + + etl::clock total_time; + etl::clock::value_type work_time(0); + etl::clock::value_type find_tile_time(0); + etl::clock::value_type add_tile_time(0); + total_time.reset(); + + // If the quality is set to zero, then we + // use the parametric scanline-renderer. + if(get_quality()==0) + { + Surface surface; + + RendDesc tile_desc; + int x,y,w,h; + int i; + etl::clock tile_timer; + tile_timer.reset(); + while((i=next_tile(x,y))) + { + find_tile_time+=tile_timer(); + SuperCallback super(cb,(total_tiles-i+1)*1000,(total_tiles-i+2)*1000,total_tiles*1000); + if(!super.amount_complete(0,1000)) + return false; + //if(cb && !cb->amount_complete(total_tiles-i,total_tiles)) + // return false; + + // Perform clipping on the tile + if(clipping_) + { + w=x+tile_w_error(_("Parametric Renderer Failure")); + return false; + } + else + { + if(!surface) + { + if(cb)cb->error(_("Bad surface")); + return false; + } + if(get_remove_alpha()) + for(int i=0;ierror(_("add_tile():Unable to put surface on target")); + return false; + } + } + tile_timer.reset(); + } + } + else // If quality is set otherwise, then we use the accelerated renderer + { + Surface surface; + + RendDesc tile_desc; + int x,y,w,h; + int i; + etl::clock tile_timer; + tile_timer.reset(); + while((i=next_tile(x,y))) + { + find_tile_time+=tile_timer(); + SuperCallback super(cb,(total_tiles-i)*1000,(total_tiles-i+1)*1000,total_tiles*1000); + if(!super.amount_complete(0,1000)) + return false; +// if(cb && !cb->amount_complete(total_tiles-i,total_tiles)) +// return false; + // Perform clipping on the tile + if(clipping_) + { + w=x+tile_w_error(_("Accelerated Renderer Failure")); + return false; + } + else + { + work_time+=timer2(); + if(!surface) + { + if(cb)cb->error(_("Bad surface")); + return false; + } + if(get_remove_alpha()) + for(int i=0;ierror(_("add_tile():Unable to put surface on target")); + return false; + } + add_tile_time+=timer(); + } + tile_timer.reset(); + } + } + if(cb && !cb->amount_complete(total_tiles,total_tiles)) + return false; + +#if SYNFIG_DISPLAY_EFFICIENCY==1 + synfig::info(">>>>>> Render Time: %fsec, Find Tile Time: %fsec, Add Tile Time: %fsec, Total Time: %fsec",work_time,find_tile_time,add_tile_time,total_time()); + synfig::info(">>>>>> FRAME EFFICIENCY: %f%%",(100.0f*work_time/total_time())); +#endif +#undef total_tiles + return true; +} + +bool +synfig::Target_Tile::render(ProgressCallback *cb) +{ + SuperCallback super_cb; + int + i=0, + total_frames, + frame_start, + frame_end; + Time + t=0, + time_start, + time_end; + + assert(canvas); + curr_frame_=0; + init(); + if( !init() ){ + if(cb) cb->error(_("Target initialisation failure")); + return false; + } + + + // If the description's end frame is equal to + // the start frame, then it is assumed that we + // are rendering only one frame. Correct it. + if(desc.get_frame_end()==desc.get_frame_start()) + desc.set_frame_end(desc.get_frame_start()+1); + + frame_start=desc.get_frame_start(); + frame_end=desc.get_frame_end(); + time_start=desc.get_time_start(); + time_end=desc.get_time_end(); + + // Calculate the number of frames + total_frames=frame_end-frame_start; + + + + try { + // Grab the time + i=next_frame(t); + + //synfig::info("1time_set_to %s",t.get_string().c_str()); + + if(i>=1) + { + do + { + curr_tile_=0; + + // If we have a callback, and it returns + // false, go ahead and bail. (maybe a use cancel) + if(cb && !cb->amount_complete(total_frames-(i-1),total_frames)) + return false; + + if(!start_frame(cb)) + return false; + + // Set the time that we wish to render + //if(!get_avoid_time_sync() || canvas->get_time()!=t) + canvas->set_time(t); + + Context context; + + #ifdef SYNFIG_OPTIMIZE_LAYER_TREE + Canvas::Handle op_canvas(Canvas::create()); + optimize_layers(canvas->get_context(), op_canvas); + context=op_canvas->get_context(); + #else + context=canvas->get_context(); + #endif + +/* + #ifdef SYNFIG_OPTIMIZE_LAYER_TREE + Context context; + Canvas::Handle op_canvas(Canvas::create()); + // Set the time that we wish to render + canvas->set_time(t); + optimize_layers(canvas->get_context(), op_canvas); + context=op_canvas->get_context(); + #else + Context context; + // Set the time that we wish to render + canvas->set_time(t); + context=canvas->get_context(); + #endif +*/ + + if(!render_frame_(context,0)) + return false; + end_frame(); + }while((i=next_frame(t))); + //synfig::info("tilerenderer: i=%d, t=%s",i,t.get_string().c_str()); + } + else + { + curr_tile_=0; + + if(!start_frame(cb)) + return false; + + // Set the time that we wish to render +// if(!get_avoid_time_sync() || canvas->get_time()!=t) + canvas->set_time(t); + + //synfig::info("2time_set_to %s",t.get_string().c_str()); + + Context context; + + #ifdef SYNFIG_OPTIMIZE_LAYER_TREE + Canvas::Handle op_canvas(Canvas::create()); + optimize_layers(canvas->get_context(), op_canvas); + context=op_canvas->get_context(); + #else + context=canvas->get_context(); + #endif + + if(!render_frame_(context, cb)) + return false; + end_frame(); + } + + } + catch(String str) + { + if(cb)cb->error(_("Caught string :")+str); + return false; + } + catch(std::bad_alloc) + { + if(cb)cb->error(_("Ran out of memory (Probably a bug)")); + return false; + } + catch(...) + { + if(cb)cb->error(_("Caught unknown error, rethrowing...")); + throw; + } + return true; +}