1 /* === S I N F G =========================================================== */
2 /*! \file target_scanline.cpp
3 ** \brief Template File
5 ** $Id: target_scanline.cpp,v 1.1.1.1 2005/01/04 01:23:15 darco Exp $
8 ** Copyright (c) 2002 Robert B. Quattlebaum Jr.
10 ** This software and associated documentation
11 ** are CONFIDENTIAL and PROPRIETARY property of
12 ** the above-mentioned copyright holder.
14 ** You may not copy, print, publish, or in any
15 ** other way distribute this software without
16 ** a prior written agreement with
17 ** the copyright holder.
20 /* ========================================================================= */
22 /* === H E A D E R S ======================================================= */
31 #include "target_scanline.h"
40 /* === U S I N G =========================================================== */
44 using namespace sinfg;
46 /* === M A C R O S ========================================================= */
48 #define SINFG_OPTIMIZE_LAYER_TREE 1
50 #define PIXEL_RENDERING_LIMIT 1500000
52 #define USE_PIXELRENDERING_LIMIT 0
54 /* === G L O B A L S ======================================================= */
56 /* === P R O C E D U R E S ================================================= */
58 /* === M E T H O D S ======================================================= */
60 Target_Scanline::Target_Scanline():
67 Target_Scanline::next_frame(Time& time)
77 // If the description's end frame is equal to
78 // the start frame, then it is assumed that we
79 // are rendering only one frame. Correct it.
80 if(desc.get_frame_end()==desc.get_frame_start())
81 desc.set_frame_end(desc.get_frame_start()+1);
83 frame_start=desc.get_frame_start();
84 frame_end=desc.get_frame_end();
85 time_start=desc.get_time_start();
86 time_end=desc.get_time_end();
88 // Calculate the number of frames
89 total_frames=frame_end-frame_start;
90 if(total_frames<=0)total_frames=1;
92 //RendDesc rend_desc=desc;
93 //rend_desc.set_gamma(1);
95 // int total_tiles(total_tiles());
96 time=(time_end-time_start)*curr_frame_/total_frames+time_start;
99 /* sinfg::info("curr_frame_: %d",curr_frame_);
100 sinfg::info("total_frames: %d",total_frames);
101 sinfg::info("time_end: %s",time_end.get_string().c_str());
102 sinfg::info("time_start: %s",time_start.get_string().c_str());
104 // sinfg::info("time: %s",time.get_string().c_str());
106 return total_frames- curr_frame_+1;
109 sinfg::Target_Scanline::render(ProgressCallback *cb)
111 SuperCallback super_cb;
115 quality=get_quality(),
128 // If the description's end frame is equal to
129 // the start frame, then it is assumed that we
130 // are rendering only one frame. Correct it.
131 if(desc.get_frame_end()==desc.get_frame_start())
132 desc.set_frame_end(desc.get_frame_start()+1);
134 frame_start=desc.get_frame_start();
135 frame_end=desc.get_frame_end();
136 time_start=desc.get_time_start();
137 time_end=desc.get_time_end();
139 // Calculate the number of frames
140 total_frames=frame_end-frame_start;
143 //RendDesc rend_desc=desc;
149 //sinfg::info("1time_set_to %s",t.get_string().c_str());
155 //for(i=0,t=time_start;i<total_frames;i++)
157 //t=((time_end-time_start)*((Real)i/(Real)total_frames)).round(desc.get_frame_rate())+time_start;
159 // If we have a callback, and it returns
160 // false, go ahead and bail. (it may be a user cancel)
161 if(cb && !cb->amount_complete(total_frames-(i-1),total_frames))
164 // Set the time that we wish to render
165 if(!get_avoid_time_sync() || canvas->get_time()!=t)
170 #ifdef SINFG_OPTIMIZE_LAYER_TREE
171 Canvas::Handle op_canvas(Canvas::create());
172 optimize_layers(canvas->get_context(), op_canvas);
173 context=op_canvas->get_context();
175 context=canvas->get_context();
178 // If the quality is set to zero, then we
179 // use the parametric scanline-renderer.
184 if(!sinfg::render(context,this,desc,0))
189 if(!sinfg::render_threaded(context,this,desc,0,threads_))
193 else // If quality is set otherwise, then we use the accelerated renderer
195 #if USE_PIXELRENDERING_LIMIT
196 if(desc.get_w()*desc.get_h() > PIXEL_RENDERING_LIMIT)
198 sinfg::info("Render BROKEN UP! (%d pixels)", desc.get_w()*desc.get_h());
201 int rowheight = PIXEL_RENDERING_LIMIT/desc.get_w();
202 int rows = desc.get_h()/rowheight;
203 int lastrowheight = desc.get_h() - rows*rowheight;
207 sinfg::info("\t blockh=%d,remh=%d,totrows=%d", rowheight,lastrowheight,rows);
209 // loop through all the full rows
212 throw(string("add_frame(): target panic on start_frame()"));
216 for(int i=0; i < rows; ++i)
218 RendDesc blockrd = desc;
220 //render the strip at the normal size unless it's the last one...
223 if(!lastrowheight) break;
224 blockrd.set_subwindow(0,i*rowheight,desc.get_w(),lastrowheight);
228 blockrd.set_subwindow(0,i*rowheight,desc.get_w(),rowheight);
231 if(!context.accelerated_render(&surface,quality,blockrd,0))
233 if(cb)cb->error(_("Accelerated Renderer Failure"));
238 int rowspan=sizeof(Color)*surface.get_w();
239 Surface::pen pen = surface.begin();
241 int yoff = i*rowheight;
243 for(y = 0; y < blockrd.get_h(); y++, pen.inc_y())
245 Color *colordata= start_scanline(y + yoff);
248 throw(string("add_frame(): call to start_scanline(y) returned NULL"));
252 if(get_remove_alpha())
254 for(int i = 0; i < surface.get_w(); i++)
255 colordata[i] = Color::blend(surface[y][i],desc.get_bg_color(),1.0f);
258 memcpy(colordata,surface[y],rowspan);
262 throw(string("add_frame(): target panic on end_scanline()"));
271 }else //use normal rendering...
276 if(!context.accelerated_render(&surface,quality,desc,0))
278 // For some reason, the accelerated renderer failed.
279 if(cb)cb->error(_("Accelerated Renderer Failure"));
284 // Put the surface we renderer
286 if(!add_frame(&surface))
288 if(cb)cb->error(_("Unable to put surface on target"));
292 #if USE_PIXELRENDERING_LIMIT
296 }while((i=next_frame(t)));
299 // Set the time that we wish to render
300 if(!get_avoid_time_sync() || canvas->get_time()!=t)
304 #ifdef SINFG_OPTIMIZE_LAYER_TREE
305 Canvas::Handle op_canvas(Canvas::create());
306 optimize_layers(canvas->get_context(), op_canvas);
307 context=op_canvas->get_context();
309 context=canvas->get_context();
312 // If the quality is set to zero, then we
313 // use the parametric scanline-renderer.
318 if(!sinfg::render(context,this,desc,cb))
323 if(!sinfg::render_threaded(context,this,desc,cb,threads_))
327 else // If quality is set otherwise, then we use the accelerated renderer
329 #if USE_PIXELRENDERING_LIMIT
330 if(desc.get_w()*desc.get_h() > PIXEL_RENDERING_LIMIT)
332 sinfg::info("Render BROKEN UP! (%d pixels)", desc.get_w()*desc.get_h());
335 int totalheight = desc.get_h();
336 int rowheight = PIXEL_RENDERING_LIMIT/desc.get_w();
337 int rows = desc.get_h()/rowheight;
338 int lastrowheight = desc.get_h() - rows*rowheight;
342 sinfg::info("\t blockh=%d,remh=%d,totrows=%d", rowheight,lastrowheight,rows);
344 // loop through all the full rows
347 throw(string("add_frame(): target panic on start_frame()"));
351 for(int i=0; i < rows; ++i)
353 RendDesc blockrd = desc;
355 //render the strip at the normal size unless it's the last one...
358 if(!lastrowheight) break;
359 blockrd.set_subwindow(0,i*rowheight,desc.get_w(),lastrowheight);
363 blockrd.set_subwindow(0,i*rowheight,desc.get_w(),rowheight);
366 SuperCallback sc(cb, i*rowheight, (i+1)*rowheight, totalheight);
368 if(!context.accelerated_render(&surface,quality,blockrd,&sc))
370 if(cb)cb->error(_("Accelerated Renderer Failure"));
375 int rowspan=sizeof(Color)*surface.get_w();
376 Surface::pen pen = surface.begin();
378 int yoff = i*rowheight;
380 for(y = 0; y < blockrd.get_h(); y++, pen.inc_y())
382 Color *colordata= start_scanline(y + yoff);
385 throw(string("add_frame(): call to start_scanline(y) returned NULL"));
389 if(get_remove_alpha())
391 for(int i = 0; i < surface.get_w(); i++)
392 colordata[i] = Color::blend(surface[y][i],desc.get_bg_color(),1.0f);
395 memcpy(colordata,surface[y],rowspan);
399 throw(string("add_frame(): target panic on end_scanline()"));
405 //I'm done with this part
406 sc.amount_complete(100,100);
416 if(!context.accelerated_render(&surface,quality,desc,cb))
418 if(cb)cb->error(_("Accelerated Renderer Failure"));
423 // Put the surface we renderer
425 if(!add_frame(&surface))
427 if(cb)cb->error(_("Unable to put surface on target"));
431 #if USE_PIXELRENDERING_LIMIT
440 if(cb)cb->error(_("Caught string :")+str);
443 catch(std::bad_alloc)
445 if(cb)cb->error(_("Ran out of memory (Probably a bug)"));
450 if(cb)cb->error(_("Caught unknown error, rethrowing..."));
457 Target_Scanline::add_frame(const Surface *surface)
463 int rowspan=sizeof(Color)*surface->get_w();
464 Surface::const_pen pen=surface->begin();
468 throw(string("add_frame(): target panic on start_frame()"));
472 for(y=0;y<surface->get_h();y++,pen.inc_y())
474 Color *colordata= start_scanline(y);
477 throw(string("add_frame(): call to start_scanline(y) returned NULL"));
481 if(get_remove_alpha())
483 for(int i=0;i<surface->get_w();i++)
484 colordata[i]=Color::blend((*surface)[y][i],desc.get_bg_color(),1.0f);
487 memcpy(colordata,(*surface)[y],rowspan);
491 throw(string("add_frame(): target panic on end_scanline()"));