1 /* === S I N F G =========================================================== */
3 ** \brief Template File
5 ** $Id: context.cpp,v 1.4 2005/01/24 05:00:18 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 ======================================================= */
38 #include "valuenode.h"
42 /* === U S I N G =========================================================== */
46 using namespace sinfg;
48 /* === M A C R O S ========================================================= */
50 //#define SINFG_PROFILE_LAYERS
51 //#define SINFG_DEBUG_LAYERS
53 /* === G L O B A L S ======================================================= */
55 #ifdef SINFG_PROFILE_LAYERS
58 static std::map<String,float> time_table;
59 static std::map<String,int> run_table;
60 static etl::clock profile_timer;
61 static String curr_layer;
63 _print_profile_report()
65 sinfg::info(">>>> Profile Report: (Times are in msecs)");
66 std::map<String,float>::iterator iter;
68 for(iter=time_table.begin();iter!=time_table.end();++iter)
70 String layer(iter->first);
71 float time(iter->second);
72 int runs(run_table[layer]);
74 sinfg::info(" Layer \"%s\",\tExecs: %03d, Avg Time: %05.1f, Total Time: %05.1f",layer.c_str(),runs,time/runs*1000,time*1000);
76 sinfg::info("Total Time: %f seconds", total_time);
77 sinfg::info("<<<< End of Profile Report");
82 /* === P R O C E D U R E S ================================================= */
84 /* === M E T H O D S ======================================================= */
87 Context::get_color(const Point &pos)const
89 Context context(*this);
91 while(!context->empty())
93 // If this layer is active, then go
94 // ahead and break out of the loop
95 if((*context)->active())
98 // Otherwise, we want to keep searching
99 // till we find either an active layer,
100 // or the end of the layer list
104 // If this layer isn't defined, return alpha
105 if((context)->empty()) return Color::alpha();
107 RWLock::ReaderLock lock((*context)->get_rw_lock());
109 return (*context)->get_color(context+1, pos);
113 Context::get_full_bounding_rect()const
115 Context context(*this);
117 while(!context->empty())
119 // If this layer is active, then go
120 // ahead and break out of the loop
121 if((*context)->active())
124 // Otherwise, we want to keep searching
125 // till we find either an active layer,
126 // or the end of the layer list
133 return (*context)->get_full_bounding_rect(*this+1);
137 /* Profiling will go like this:
138 Profile start = +, stop = -
143 time diff is recorded
145 to get the independent times we need to break at the one inside and record etc...
146 so it looks more like this:
160 at each minus we must record all the info for that which we are worried about...
161 each layer can do work before or after the other work is done... so both values must be recorded...
165 Context::accelerated_render(Surface *surface,int quality, const RendDesc &renddesc, ProgressCallback *cb) const
167 #ifdef SINFG_PROFILE_LAYERS
168 String layer_name(curr_layer);
170 //sum the pre-work done by layer above us... (curr_layer is layer above us...)
173 time_table[curr_layer]+=profile_timer();
174 //if(run_table.count(curr_layer))run_table[curr_layer]++;
175 // else run_table[curr_layer]=1;
179 const Rect bbox(renddesc.get_rect());
181 Context context(*this);
182 for(;!(context)->empty();++context)
184 // If we are not active
185 // then move on to next layer
186 if(!(*context)->active())
189 const Rect layer_bounds((*context)->get_bounding_rect());
191 // If the box area is less than zero
192 // then move on to next layer
193 if(layer_bounds.area()<=0.0000000000001)
196 // If the boxes do not intersect
197 // then move on to next layer
198 if(!(layer_bounds && bbox))
201 // Break out of the loop--we have found a good layer
205 // If this layer isn't defined, return alpha
206 if((context)->empty())
208 #ifdef SINFG_DEBUG_LAYERS
209 sinfg::info("Context::accelerated_render(): Hit end of list");
211 surface->set_wh(renddesc.get_w(),renddesc.get_h());
213 #ifdef SINFG_PROFILE_LAYERS
214 profile_timer.reset();
219 #ifdef SINFG_DEBUG_LAYERS
220 sinfg::info("Context::accelerated_render(): Descending into %s",(*context)->get_name().c_str());
224 RWLock::ReaderLock lock((*context)->get_rw_lock());
226 #ifdef SINFG_PROFILE_LAYERS
228 //go down one layer :P
230 curr_layer=(*context)->get_name(); //make sure the layer inside is referring to the correct layer outside
231 profile_timer.reset(); // +
232 bool ret((*context)->accelerated_render(context+1,surface,quality,renddesc, cb));
234 //post work for the previous layer
235 time_table[curr_layer]+=profile_timer(); //-
236 if(run_table.count(curr_layer))run_table[curr_layer]++;
237 else run_table[curr_layer]=1;
240 curr_layer = layer_name; //we are now onto this layer (make sure the post gets recorded correctly...
242 //print out the table it we're done...
243 if(depth==0) _print_profile_report(),time_table.clear(),run_table.clear();
244 profile_timer.reset(); //+
247 return (*context)->accelerated_render(context+1,surface,quality,renddesc, cb);
251 catch(std::bad_alloc)
253 sinfg::error("Context::accelerated_render(): Layer \"%s\" threw a bad_alloc exception!",(*context)->get_name().c_str());
258 return context.accelerated_render(surface, quality, renddesc, cb);
263 sinfg::error("Context::accelerated_render(): Layer \"%s\" threw an exception, rethrowing...",(*context)->get_name().c_str());
269 Context::set_time(Time time)const
271 Context context(*this);
272 while(!(context)->empty())
274 // If this layer is active, then go
275 // ahead and break out of the loop
276 if((*context)->active() && !(*context)->dirty_time_.is_equal(time))
279 // Otherwise, we want to keep searching
280 // till we find either an active layer,
281 // or the end of the layer list
285 // If this layer isn't defined, just return
286 if((context)->empty()) return;
288 // Set up a wrter lock
289 RWLock::WriterLock lock((*context)->get_rw_lock());
291 //sinfg::info("%s: dirty_time=%f",(*context)->get_name().c_str(),(float)(*context)->dirty_time_);
292 //sinfg::info("%s: time=%f",(*context)->get_name().c_str(),(float)time);
295 Layer::ParamList params;
296 Layer::DynamicParamList::const_iterator iter;
298 for(iter=(*context)->dynamic_param_list().begin();iter!=(*context)->dynamic_param_list().end();iter++)
299 params[iter->first]=(*iter->second)(time);
301 (*context)->set_param_list(params);
303 (*context)->set_time(context+1,time);
304 (*context)->dirty_time_=time;
310 Context::set_time(Time time,const Vector &pos)const
314 Context context(*this);
315 while(!(context)->empty())
317 // If this layer is active, then go
318 // ahead and break out of the loop
319 if((*context)->active())
322 // Otherwise, we want to keep searching
323 // till we find either an active layer,
324 // or the end of the layer list
328 // If this layer isn't defined, just return
329 if((context)->empty()) return;
333 Layer::ParamList params;
334 Layer::DynamicParamList::const_iterator iter;
336 for(iter=(*context)->dynamic_param_list().begin();iter!=(*context)->dynamic_param_list().end();iter++)
337 params[iter->first]=(*iter->second)(time);
339 (*context)->set_param_list(params);
341 (*context)->set_time(context+1,time,pos);
347 Context::hit_check(const Point &pos)const
349 Context context(*this);
351 while(!context->empty())
353 // If this layer is active, then go
354 // ahead and break out of the loop
355 if((*context)->active())
358 // Otherwise, we want to keep searching
359 // till we find either an active layer,
360 // or the end of the layer list
364 // If this layer isn't defined, return an empty handle
365 if((context)->empty()) return 0;
367 return (*context)->hit_check(context+1, pos);