|
Carlos Lopez |
a09598 |
/* === S Y N F I G ========================================================= */
|
|
Carlos Lopez |
a09598 |
/*! \file context.cpp
|
|
Carlos Lopez |
a09598 |
** \brief Template File
|
|
Carlos Lopez |
a09598 |
**
|
|
Carlos Lopez |
a09598 |
** $Id$
|
|
Carlos Lopez |
a09598 |
**
|
|
Carlos Lopez |
a09598 |
** \legal
|
|
Carlos Lopez |
a09598 |
** Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
|
|
Carlos Lopez |
a09598 |
** Copyright (c) 2008 Chris Moore
|
|
Carlos Lopez |
e83454 |
** Copyright (c) 2012-2013 Carlos Lรณpez
|
|
Carlos Lopez |
a09598 |
**
|
|
Carlos Lopez |
a09598 |
** This package is free software; you can redistribute it and/or
|
|
Carlos Lopez |
a09598 |
** modify it under the terms of the GNU General Public License as
|
|
Carlos Lopez |
a09598 |
** published by the Free Software Foundation; either version 2 of
|
|
Carlos Lopez |
a09598 |
** the License, or (at your option) any later version.
|
|
Carlos Lopez |
a09598 |
**
|
|
Carlos Lopez |
a09598 |
** This package is distributed in the hope that it will be useful,
|
|
Carlos Lopez |
a09598 |
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Carlos Lopez |
a09598 |
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Carlos Lopez |
a09598 |
** General Public License for more details.
|
|
Carlos Lopez |
a09598 |
** \endlegal
|
|
Carlos Lopez |
a09598 |
*/
|
|
Carlos Lopez |
a09598 |
/* ========================================================================= */
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* === H E A D E R S ======================================================= */
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
#ifdef USING_PCH
|
|
Carlos Lopez |
a09598 |
# include "pch.h"
|
|
Carlos Lopez |
a09598 |
#else
|
|
Carlos Lopez |
a09598 |
#ifdef HAVE_CONFIG_H
|
|
Carlos Lopez |
a09598 |
# include <config.h></config.h>
|
|
Carlos Lopez |
a09598 |
#endif
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
#include "context.h"
|
|
bw |
94d8a6 |
|
|
bw |
94d8a6 |
#include "general.h"
|
|
bw |
94d8a6 |
#include <synfig localization.h=""></synfig>
|
|
Carlos Lopez |
a09598 |
#include "layer.h"
|
|
Carlos Lopez |
a09598 |
#include "string.h"
|
|
Carlos Lopez |
a09598 |
#include "vector.h"
|
|
Carlos Lopez |
a09598 |
#include "color.h"
|
|
Carlos Lopez |
a09598 |
#include "valuenode.h"
|
|
|
068c13 |
#include "transformation.h"
|
|
Carlos Lopez |
a09598 |
|
|
bw |
94d8a6 |
#include "layers/layer_pastecanvas.h"
|
|
bw |
94d8a6 |
|
|
|
4472a9 |
#include "rendering/task.h"
|
|
|
4472a9 |
|
|
Carlos Lopez |
a09598 |
#endif
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* === U S I N G =========================================================== */
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
using namespace std;
|
|
Carlos Lopez |
a09598 |
using namespace etl;
|
|
Carlos Lopez |
a09598 |
using namespace synfig;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* === M A C R O S ========================================================= */
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// #define SYNFIG_PROFILE_LAYERS
|
|
Carlos Lopez |
a09598 |
// #define SYNFIG_DEBUG_LAYERS
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* === G L O B A L S ======================================================= */
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
#ifdef SYNFIG_PROFILE_LAYERS
|
|
Carlos Lopez |
a09598 |
#include <etl clock=""></etl>
|
|
Carlos Lopez |
a09598 |
static int depth(0);
|
|
Carlos Lopez |
a09598 |
static std::map<string,float> time_table;</string,float>
|
|
Carlos Lopez |
a09598 |
static std::map<string,int> run_table;</string,int>
|
|
Carlos Lopez |
a09598 |
static etl::clock profile_timer;
|
|
Carlos Lopez |
a09598 |
static String curr_layer;
|
|
Carlos Lopez |
a09598 |
static void
|
|
Carlos Lopez |
a09598 |
_print_profile_report()
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
synfig::info(">>>> Profile Report: (Times are in msecs)");
|
|
Carlos Lopez |
a09598 |
std::map<string,float>::iterator iter;</string,float>
|
|
Carlos Lopez |
a09598 |
float total_time(0);
|
|
Carlos Lopez |
a09598 |
for(iter=time_table.begin();iter!=time_table.end();++iter)
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
String layer(iter->first);
|
|
Carlos Lopez |
a09598 |
float time(iter->second);
|
|
Carlos Lopez |
a09598 |
int runs(run_table[layer]);
|
|
Carlos Lopez |
a09598 |
total_time+=time;
|
|
Carlos Lopez |
a09598 |
synfig::info(" Layer \"%s\",\tExecs: %03d, Avg Time: %05.1f, Total Time: %05.1f",layer.c_str(),runs,time/runs*1000,time*1000);
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
synfig::info("Total Time: %f seconds", total_time);
|
|
Carlos Lopez |
a09598 |
synfig::info("<<<< End of Profile Report");
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
#endif // SYNFIG_PROFILE_LAYERS
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* === P R O C E D U R E S ================================================= */
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* === M E T H O D S ======================================================= */
|
|
Carlos Lopez |
a09598 |
|
|
|
dd97a8 |
|
|
|
ac6c6c |
void
|
|
|
26a291 |
IndependentContext::set_time(Time time, bool force)const
|
|
|
ac6c6c |
{
|
|
|
ac6c6c |
IndependentContext context(*this);
|
|
|
dd97a8 |
while(*context)
|
|
|
ac6c6c |
{
|
|
|
dd97a8 |
if ( (*context)->active() &&
|
|
|
26a291 |
(force || !(*context)->get_time_mark().is_equal(time)) )
|
|
|
ac6c6c |
break;
|
|
|
ac6c6c |
++context;
|
|
|
ac6c6c |
}
|
|
|
dd97a8 |
if (!*context) return;
|
|
|
ac6c6c |
|
|
|
b98a79 |
Layer::Handle layer(*context);
|
|
|
b98a79 |
++context;
|
|
|
b98a79 |
RWLock::WriterLock lock(layer->get_rw_lock());
|
|
|
b98a79 |
layer->set_time(context, time);
|
|
|
ac6c6c |
}
|
|
|
ac6c6c |
|
|
|
ac6c6c |
void
|
|
|
b98a79 |
IndependentContext::load_resources(Time time, bool /*force*/)const
|
|
|
c006c9 |
{
|
|
|
c006c9 |
IndependentContext context(*this);
|
|
|
c006c9 |
while(*context)
|
|
|
c006c9 |
{
|
|
|
c006c9 |
if ( (*context)->active() )
|
|
|
c006c9 |
break;
|
|
|
c006c9 |
++context;
|
|
|
c006c9 |
}
|
|
|
c006c9 |
if (!*context) return;
|
|
|
c006c9 |
|
|
|
b98a79 |
Layer::Handle layer(*context);
|
|
|
b98a79 |
++context;
|
|
|
b98a79 |
//RWLock::WriterLock lock(layer->get_rw_lock());
|
|
|
b98a79 |
layer->load_resources(context, time);
|
|
|
c006c9 |
}
|
|
|
c006c9 |
|
|
|
c006c9 |
void
|
|
|
dd97a8 |
IndependentContext::set_outline_grow(Real outline_grow)const
|
|
|
ac6c6c |
{
|
|
|
dd97a8 |
IndependentContext context(*this);
|
|
|
dd97a8 |
while(*context)
|
|
|
ac6c6c |
{
|
|
|
dd97a8 |
if ( (*context)->active()
|
|
|
dd97a8 |
&& fabs((*context)->get_outline_grow_mark() - outline_grow) > 1e-8 )
|
|
|
ac6c6c |
break;
|
|
|
ac6c6c |
++context;
|
|
|
ac6c6c |
}
|
|
|
dd97a8 |
if (!*context) return;
|
|
|
ac6c6c |
|
|
|
dd97a8 |
// Set up a writer lock
|
|
|
b98a79 |
|
|
|
b98a79 |
Layer::Handle layer(*context);
|
|
|
b98a79 |
++context;
|
|
|
b98a79 |
RWLock::WriterLock lock(layer->get_rw_lock());
|
|
|
b98a79 |
layer->set_outline_grow(context, outline_grow);
|
|
|
ac6c6c |
}
|
|
|
ac6c6c |
|
|
Carlos Lopez |
a09598 |
Color
|
|
Carlos Lopez |
a09598 |
Context::get_color(const Point &pos)const
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
Context context(*this);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
while(!context->empty())
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
// If this layer is active, then go
|
|
Carlos Lopez |
a09598 |
// ahead and break out of the loop
|
|
|
2fe42f |
if(context.active() && context.in_z_range())
|
|
Carlos Lopez |
a09598 |
break;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// Otherwise, we want to keep searching
|
|
Carlos Lopez |
a09598 |
// till we find either an active layer,
|
|
Carlos Lopez |
a09598 |
// or the end of the layer list
|
|
Carlos Lopez |
a09598 |
++context;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// If this layer isn't defined, return alpha
|
|
Carlos Lopez |
a09598 |
if((context)->empty()) return Color::alpha();
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
RWLock::ReaderLock lock((*context)->get_rw_lock());
|
|
Carlos Lopez |
a09598 |
|
|
|
c06d66 |
return (*context)->get_color(context.get_next(), pos);
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
56fffe |
CairoColor
|
|
Carlos Lopez |
56fffe |
Context::get_cairocolor(const Point &pos)const
|
|
Carlos Lopez |
56fffe |
{
|
|
Carlos Lopez |
56fffe |
Context context(*this);
|
|
Carlos Lopez |
56fffe |
|
|
Carlos Lopez |
56fffe |
while(!context->empty())
|
|
Carlos Lopez |
56fffe |
{
|
|
Carlos Lopez |
56fffe |
// If this layer is active, then go
|
|
Carlos Lopez |
56fffe |
// ahead and break out of the loop
|
|
|
2fe42f |
if(context.active() && context.in_z_range())
|
|
Carlos Lopez |
56fffe |
break;
|
|
Carlos Lopez |
56fffe |
|
|
Carlos Lopez |
56fffe |
// Otherwise, we want to keep searching
|
|
Carlos Lopez |
56fffe |
// till we find either an active layer,
|
|
Carlos Lopez |
56fffe |
// or the end of the layer list
|
|
Carlos Lopez |
56fffe |
++context;
|
|
Carlos Lopez |
56fffe |
}
|
|
Carlos Lopez |
56fffe |
|
|
Carlos Lopez |
56fffe |
// If this layer isn't defined, return alpha
|
|
Carlos Lopez |
56fffe |
if((context)->empty()) return CairoColor::alpha();
|
|
Carlos Lopez |
56fffe |
|
|
Carlos Lopez |
56fffe |
RWLock::ReaderLock lock((*context)->get_rw_lock());
|
|
Carlos Lopez |
56fffe |
|
|
|
c06d66 |
return (*context)->get_cairocolor(context.get_next(), pos);
|
|
Carlos Lopez |
56fffe |
}
|
|
Carlos Lopez |
56fffe |
|
|
Carlos Lopez |
56fffe |
|
|
Carlos Lopez |
a09598 |
Rect
|
|
Carlos Lopez |
a09598 |
Context::get_full_bounding_rect()const
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
Context context(*this);
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
while(!context->empty())
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos López |
ee08a5 |
// If this layer is active and visible in z_depth range,
|
|
Carlos López |
ee08a5 |
// then go ahead and break out of the loop
|
|
|
2fe42f |
if(context.active() && context.in_z_range())
|
|
Carlos Lopez |
a09598 |
break;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// Otherwise, we want to keep searching
|
|
Carlos Lopez |
a09598 |
// till we find either an active layer,
|
|
Carlos Lopez |
a09598 |
// or the end of the layer list
|
|
Carlos Lopez |
a09598 |
++context;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// If this layer isn't defined, return zero-sized rectangle
|
|
Carlos Lopez |
a09598 |
if(context->empty()) return Rect::zero();
|
|
Carlos Lopez |
a09598 |
|
|
|
c06d66 |
return (*context)->get_full_bounding_rect(context.get_next());
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
/* Profiling will go like this:
|
|
Carlos Lopez |
a09598 |
Profile start = +, stop = -
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
+
|
|
Carlos Lopez |
a09598 |
-
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
time diff is recorded
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
to get the independent times we need to break at the one inside and record etc...
|
|
Carlos Lopez |
a09598 |
so it looks more like this:
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
+
|
|
Carlos Lopez |
a09598 |
-
|
|
Carlos Lopez |
a09598 |
+
|
|
Carlos Lopez |
a09598 |
-
|
|
Carlos Lopez |
a09598 |
+
|
|
Carlos Lopez |
a09598 |
...
|
|
Carlos Lopez |
a09598 |
-
|
|
Carlos Lopez |
a09598 |
+
|
|
Carlos Lopez |
a09598 |
-
|
|
Carlos Lopez |
a09598 |
+
|
|
Carlos Lopez |
a09598 |
-
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
at each minus we must record all the info for that which we are worried about...
|
|
Carlos Lopez |
a09598 |
each layer can do work before or after the other work is done... so both values must be recorded...
|
|
Carlos Lopez |
a09598 |
*/
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
etl::handle<layer></layer>
|
|
Carlos Lopez |
a09598 |
Context::hit_check(const Point &pos)const
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
Context context(*this);
|
|
Carlos Lopez |
a09598 |
|
|
|
2fe42f |
while(!context->empty() && context.in_z_range())
|
|
Carlos Lopez |
a09598 |
{
|
|
Carlos Lopez |
a09598 |
// If this layer is active, then go
|
|
Carlos Lopez |
a09598 |
// ahead and break out of the loop
|
|
|
668cc9 |
if(context.active())
|
|
Carlos Lopez |
a09598 |
break;
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// Otherwise, we want to keep searching
|
|
Carlos Lopez |
a09598 |
// till we find either an active layer,
|
|
Carlos Lopez |
a09598 |
// or the end of the layer list
|
|
Carlos Lopez |
a09598 |
++context;
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
a09598 |
|
|
Carlos Lopez |
a09598 |
// If this layer isn't defined, return an empty handle
|
|
Carlos Lopez |
a09598 |
if((context)->empty()) return 0;
|
|
Carlos Lopez |
a09598 |
|
|
|
c06d66 |
return (*context)->hit_check(context.get_next(), pos);
|
|
Carlos Lopez |
a09598 |
}
|
|
Carlos Lopez |
623fab |
|
|
Carlos Lopez |
623fab |
|
|
Carlos Lopez |
623fab |
bool
|
|
Carlos Lopez |
623fab |
Context::accelerated_render(Surface *surface,int quality, const RendDesc &renddesc, ProgressCallback *cb) const
|
|
Carlos Lopez |
623fab |
{
|
|
Carlos Lopez |
623fab |
#ifdef SYNFIG_PROFILE_LAYERS
|
|
Carlos Lopez |
623fab |
String layer_name(curr_layer);
|
|
Carlos Lopez |
623fab |
//sum the pre-work done by layer above us... (curr_layer is layer above us...)
|
|
Carlos Lopez |
623fab |
if(depth>0)
|
|
Carlos Lopez |
623fab |
{
|
|
Carlos Lopez |
623fab |
time_table[curr_layer]+=profile_timer();
|
|
Carlos Lopez |
623fab |
//if(run_table.count(curr_layer))run_table[curr_layer]++;
|
|
Carlos Lopez |
623fab |
// else run_table[curr_layer]=1;
|
|
Carlos Lopez |
623fab |
}
|
|
Carlos Lopez |
623fab |
#endif // SYNFIG_PROFILE_LAYERS
|
|
Carlos Lopez |
623fab |
|
|
Carlos Lopez |
623fab |
const Rect bbox(renddesc.get_rect());
|
|
|
068c13 |
const Matrix &transfromation_matrix(renddesc.get_transformation_matrix());
|
|
Carlos Lopez |
623fab |
// this is going to be set to true if this layer contributes
|
|
Carlos Lopez |
623fab |
// nothing, but it's a straight blend with non-zero amount, and so
|
|
Carlos Lopez |
623fab |
// it has an effect anyway
|
|
Carlos Lopez |
623fab |
bool straight_and_empty = false;
|
|
Carlos Lopez |
623fab |
etl::handle<layer_composite> composite;</layer_composite>
|
|
Carlos Lopez |
623fab |
Context context(*this);
|
|
Carlos Lopez |
623fab |
// Run all layers until context is empty
|
|
Carlos Lopez |
623fab |
for(;!(context)->empty();++context)
|
|
Carlos Lopez |
623fab |
{
|
|
Carlos Lopez |
623fab |
// If we are not active then move on to next layer
|
|
|
668cc9 |
if(!context.active())
|
|
Carlos Lopez |
623fab |
continue;
|
|
|
068c13 |
const Rect layer_bounds(Transformation::transform_bounds(transfromation_matrix, (*context)->get_bounding_rect()));
|
|
Carlos Lopez |
623fab |
// Cast current layer to composite
|
|
Carlos Lopez |
623fab |
composite = etl::handle<layer_composite>::cast_dynamic(*context);</layer_composite>
|
|
Carlos Lopez |
623fab |
// If the box area is less than zero or the boxes do not
|
|
Carlos Lopez |
623fab |
// intersect then move on to next layer, unless the layer is
|
|
Carlos Lopez |
623fab |
// using a straight blend and has a non-zero amount, in which
|
|
Carlos Lopez |
623fab |
// case it will still affect the result
|
|
Carlos Lopez |
623fab |
if(layer_bounds.area() <= 0.0000000000001 || !(layer_bounds && bbox))
|
|
Carlos Lopez |
623fab |
{
|
|
Carlos Lopez |
623fab |
if (composite &&
|
|
Carlos Lopez |
623fab |
Surface::value_type::is_straight(composite->get_blend_method()) &&
|
|
Carlos Lopez |
623fab |
composite->get_amount() != 0.0f)
|
|
Carlos Lopez |
623fab |
{
|
|
Carlos Lopez |
623fab |
straight_and_empty = true;
|
|
Carlos Lopez |
623fab |
break;
|
|
Carlos Lopez |
623fab |
}
|
|
Carlos Lopez |
623fab |
continue;
|
|
Carlos Lopez |
623fab |
}
|
|
Carlos Lopez |
623fab |
// If this layer has Straight as the blend method and amount
|
|
Carlos Lopez |
623fab |
// is 1.0, and the layer doesn't depend on its context, then
|
|
Carlos Lopez |
623fab |
// we don't want to render the context
|
|
Carlos Lopez |
623fab |
if (composite &&
|
|
Carlos Lopez |
623fab |
composite->get_blend_method() == Color::BLEND_STRAIGHT &&
|
|
Carlos Lopez |
623fab |
composite->get_amount() == 1.0f &&
|
|
Carlos Lopez |
623fab |
!composite->reads_context())
|
|
Carlos Lopez |
623fab |
{
|
|
Carlos Lopez |
623fab |
Layer::Handle layer = *context;
|
|
Carlos Lopez |
623fab |
while (!context->empty()) context++; // skip the context
|
|
Carlos Lopez |
623fab |
return layer->accelerated_render(context,surface,quality,renddesc, cb);
|
|
Carlos Lopez |
623fab |
}
|
|
Carlos Lopez |
623fab |
// Break out of the loop--we have found a good layer
|
|
Carlos Lopez |
623fab |
break;
|
|
Carlos Lopez |
623fab |
}
|
|
Carlos Lopez |
623fab |
// If this layer isn't defined, return alpha
|
|
Carlos Lopez |
623fab |
if (context->empty() || (straight_and_empty && composite->get_amount() == 1.0f))
|
|
Carlos Lopez |
623fab |
{
|
|
Carlos Lopez |
623fab |
#ifdef SYNFIG_DEBUG_LAYERS
|
|
Carlos Lopez |
623fab |
synfig::info("Context::accelerated_render(): Hit end of list");
|
|
Carlos Lopez |
623fab |
#endif // SYNFIG_DEBUG_LAYERS
|
|
Carlos Lopez |
623fab |
// resize the surface to the given render description
|
|
Carlos Lopez |
623fab |
surface->set_wh(renddesc.get_w(),renddesc.get_h());
|
|
Carlos Lopez |
623fab |
// and clear the surface
|
|
Carlos Lopez |
623fab |
surface->clear();
|
|
Carlos Lopez |
623fab |
#ifdef SYNFIG_PROFILE_LAYERS
|
|
Carlos Lopez |
623fab |
profile_timer.reset();
|
|
Carlos Lopez |
623fab |
#endif // SYNFIG_PROFILE_LAYERS
|
|
Carlos Lopez |
623fab |
return true;
|
|
Carlos Lopez |
623fab |
}
|
|
Carlos Lopez |
623fab |
|
|
Carlos Lopez |
623fab |
#ifdef SYNFIG_DEBUG_LAYERS
|
|
Carlos Lopez |
623fab |
synfig::info("Context::accelerated_render(): Descending into %s",(*context)->get_name().c_str());
|
|
Carlos Lopez |
623fab |
#endif // SYNFIG_DEBUG_LAYERS
|
|
Carlos Lopez |
623fab |
|
|
Carlos Lopez |
623fab |
try {
|
|
Carlos Lopez |
623fab |
// lock the context for reading
|
|
Carlos Lopez |
623fab |
RWLock::ReaderLock lock((*context)->get_rw_lock());
|
|
Carlos Lopez |
623fab |
#ifdef SYNFIG_PROFILE_LAYERS
|
|
Carlos Lopez |
623fab |
//go down one layer :P
|
|
Carlos Lopez |
623fab |
depth++;
|
|
Carlos Lopez |
623fab |
curr_layer=(*context)->get_name(); //make sure the layer inside is referring to the correct layer outside
|
|
Carlos Lopez |
623fab |
profile_timer.reset(); // +
|
|
Carlos Lopez |
623fab |
#endif // SYNFIG_PROFILE_LAYERS
|
|
Carlos Lopez |
623fab |
bool ret;
|
|
Carlos Lopez |
623fab |
// this layer doesn't draw anything onto the canvas we're
|
|
Carlos Lopez |
623fab |
// rendering, but it uses straight blending, so we need to render
|
|
Carlos Lopez |
623fab |
// the stuff under us and then blit transparent pixels over it
|
|
Carlos Lopez |
623fab |
// using the appropriate 'amount'
|
|
Carlos Lopez |
623fab |
if (straight_and_empty)
|
|
Carlos Lopez |
623fab |
{
|
|
|
c06d66 |
if ((ret = Context((context.get_next())).accelerated_render(surface,quality,renddesc,cb)))
|
|
Carlos Lopez |
623fab |
{
|
|
Carlos Lopez |
623fab |
Surface clearsurface;
|
|
Carlos Lopez |
623fab |
clearsurface.set_wh(renddesc.get_w(),renddesc.get_h());
|
|
Carlos Lopez |
623fab |
clearsurface.clear();
|
|
Carlos Lopez |
623fab |
Surface::alpha_pen apen(surface->begin());
|
|
Carlos Lopez |
623fab |
apen.set_alpha(composite->get_amount());
|
|
Carlos Lopez |
623fab |
apen.set_blend_method(composite->get_blend_method());
|
|
Carlos Lopez |
623fab |
|
|
Carlos Lopez |
623fab |
clearsurface.blit_to(apen);
|
|
Carlos Lopez |
623fab |
}
|
|
Carlos Lopez |
623fab |
}
|
|
Carlos Lopez |
623fab |
else
|
|
|
c06d66 |
ret = (*context)->accelerated_render(context.get_next(),surface,quality,renddesc, cb);
|
|
Carlos Lopez |
623fab |
#ifdef SYNFIG_PROFILE_LAYERS
|
|
Carlos Lopez |
623fab |
//post work for the previous layer
|
|
Carlos Lopez |
623fab |
time_table[curr_layer]+=profile_timer(); //-
|
|
Carlos Lopez |
623fab |
if(run_table.count(curr_layer))run_table[curr_layer]++;
|
|
Carlos Lopez |
623fab |
else run_table[curr_layer]=1;
|
|
Carlos Lopez |
623fab |
depth--;
|
|
Carlos Lopez |
623fab |
curr_layer = layer_name; //we are now onto this layer (make sure the post gets recorded correctly...
|
|
Carlos Lopez |
623fab |
//print out the table it we're done...
|
|
Carlos Lopez |
623fab |
if(depth==0) _print_profile_report(),time_table.clear(),run_table.clear();
|
|
Carlos Lopez |
623fab |
profile_timer.reset(); //+
|
|
Carlos Lopez |
623fab |
#endif // SYNFIG_PROFILE_LAYERS
|
|
Carlos Lopez |
623fab |
return ret;
|
|
Carlos Lopez |
623fab |
}
|
|
|
0d77fe |
catch(std::bad_alloc&)
|
|
Carlos Lopez |
623fab |
{
|
|
Carlos Lopez |
623fab |
synfig::error("Context::accelerated_render(): Layer \"%s\" threw a bad_alloc exception!",(*context)->get_name().c_str());
|
|
Carlos Lopez |
623fab |
#ifdef _DEBUG
|
|
Carlos Lopez |
623fab |
return false;
|
|
Carlos Lopez |
623fab |
#else // _DEBUG
|
|
Carlos Lopez |
623fab |
++context;
|
|
Carlos Lopez |
623fab |
return context.accelerated_render(surface, quality, renddesc, cb);
|
|
Carlos Lopez |
623fab |
#endif // _DEBUG
|
|
Carlos Lopez |
623fab |
}
|
|
Carlos Lopez |
623fab |
catch(...)
|
|
Carlos Lopez |
623fab |
{
|
|
Carlos Lopez |
623fab |
synfig::error("Context::accelerated_render(): Layer \"%s\" threw an exception, rethrowing...",(*context)->get_name().c_str());
|
|
Carlos Lopez |
623fab |
throw;
|
|
Carlos Lopez |
623fab |
}
|
|
Carlos Lopez |
623fab |
}
|
|
Carlos Lopez |
623fab |
|
|
Carlos Lopez |
623fab |
|
|
Carlos Lopez |
623fab |
bool
|
|
Carlos Lopez |
413401 |
Context::accelerated_cairorender(cairo_t *cr,int quality, const RendDesc &renddesc, ProgressCallback *cb) const
|
|
Carlos Lopez |
413401 |
{
|
|
Carlos Lopez |
413401 |
#ifdef SYNFIG_PROFILE_LAYERS
|
|
Carlos Lopez |
413401 |
String layer_name(curr_layer);
|
|
Carlos Lopez |
413401 |
//sum the pre-work done by layer above us... (curr_layer is layer above us...)
|
|
Carlos Lopez |
413401 |
if(depth>0)
|
|
Carlos Lopez |
413401 |
{
|
|
Carlos Lopez |
413401 |
time_table[curr_layer]+=profile_timer();
|
|
Carlos Lopez |
413401 |
}
|
|
Carlos Lopez |
413401 |
#endif // SYNFIG_PROFILE_LAYERS
|
|
Carlos Lopez |
413401 |
|
|
Carlos Lopez |
413401 |
Context context(*this);
|
|
Carlos Lopez |
413401 |
// Run all layers until context is empty
|
|
Carlos Lopez |
413401 |
for(;!(context)->empty();++context)
|
|
Carlos Lopez |
413401 |
{
|
|
Carlos Lopez |
413401 |
// If we are not active then move on to next layer
|
|
|
668cc9 |
if(!context.active())
|
|
Carlos Lopez |
413401 |
continue;
|
|
Carlos Lopez |
1d2a64 |
// Found one good layer
|
|
Carlos Lopez |
413401 |
break;
|
|
Carlos Lopez |
413401 |
}
|
|
Carlos Lopez |
413401 |
// If this layer isn't defined, return alpha
|
|
Carlos Lopez |
1d2a64 |
if (context->empty())
|
|
Carlos Lopez |
413401 |
{
|
|
Carlos Lopez |
413401 |
#ifdef SYNFIG_DEBUG_LAYERS
|
|
Carlos Lopez |
413401 |
synfig::info("Context::accelerated_cairorender(): Hit end of list");
|
|
Carlos Lopez |
413401 |
#endif // SYNFIG_DEBUG_LAYERS
|
|
Carlos Lopez |
413401 |
// clear the surface
|
|
Carlos Lopez |
413401 |
cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
|
|
Carlos Lopez |
413401 |
cairo_paint(cr);
|
|
Carlos Lopez |
413401 |
#ifdef SYNFIG_PROFILE_LAYERS
|
|
Carlos Lopez |
413401 |
profile_timer.reset();
|
|
Carlos Lopez |
413401 |
#endif // SYNFIG_PROFILE_LAYERS
|
|
Carlos Lopez |
413401 |
return true;
|
|
Carlos Lopez |
413401 |
}
|
|
Carlos Lopez |
413401 |
|
|
Carlos Lopez |
413401 |
#ifdef SYNFIG_DEBUG_LAYERS
|
|
Carlos Lopez |
413401 |
synfig::info("Context::accelerated_render(): Descending into %s",(*context)->get_name().c_str());
|
|
Carlos Lopez |
413401 |
#endif // SYNFIG_DEBUG_LAYERS
|
|
Carlos Lopez |
413401 |
|
|
Carlos Lopez |
413401 |
try {
|
|
Carlos Lopez |
413401 |
// lock the context for reading
|
|
Carlos Lopez |
413401 |
RWLock::ReaderLock lock((*context)->get_rw_lock());
|
|
Carlos Lopez |
413401 |
#ifdef SYNFIG_PROFILE_LAYERS
|
|
Carlos Lopez |
413401 |
//go down one layer :P
|
|
Carlos Lopez |
413401 |
depth++;
|
|
Carlos Lopez |
413401 |
curr_layer=(*context)->get_name(); //make sure the layer inside is referring to the correct layer outside
|
|
Carlos Lopez |
413401 |
profile_timer.reset(); // +
|
|
Carlos Lopez |
413401 |
#endif // SYNFIG_PROFILE_LAYERS
|
|
Carlos Lopez |
413401 |
bool ret;
|
|
Carlos Lopez |
413401 |
// this layer doesn't draw anything onto the canvas we're
|
|
Carlos Lopez |
413401 |
// rendering, but it uses straight blending, so we need to render
|
|
Carlos Lopez |
413401 |
// the stuff under us and then blit transparent pixels over it
|
|
Carlos Lopez |
413401 |
// using the appropriate 'amount'
|
|
|
c06d66 |
ret = (*context)->accelerated_cairorender(context.get_next(),cr,quality,renddesc, cb);
|
|
Carlos Lopez |
413401 |
#ifdef SYNFIG_PROFILE_LAYERS
|
|
Carlos Lopez |
413401 |
//post work for the previous layer
|
|
Carlos Lopez |
413401 |
time_table[curr_layer]+=profile_timer(); //-
|
|
Carlos Lopez |
413401 |
if(run_table.count(curr_layer))run_table[curr_layer]++;
|
|
Carlos Lopez |
413401 |
else run_table[curr_layer]=1;
|
|
Carlos Lopez |
413401 |
depth--;
|
|
Carlos Lopez |
413401 |
curr_layer = layer_name; //we are now onto this layer (make sure the post gets recorded correctly...
|
|
Carlos Lopez |
413401 |
//print out the table it we're done...
|
|
Carlos Lopez |
413401 |
if(depth==0) _print_profile_report(),time_table.clear(),run_table.clear();
|
|
Carlos Lopez |
413401 |
profile_timer.reset(); //+
|
|
Carlos Lopez |
413401 |
#endif // SYNFIG_PROFILE_LAYERS
|
|
Carlos Lopez |
413401 |
return ret;
|
|
Carlos Lopez |
413401 |
}
|
|
|
0d77fe |
catch(std::bad_alloc&)
|
|
Carlos Lopez |
413401 |
{
|
|
Carlos Lopez |
413401 |
synfig::error("Context::accelerated_cairorender(): Layer \"%s\" threw a bad_alloc exception!",(*context)->get_name().c_str());
|
|
Carlos Lopez |
413401 |
#ifdef _DEBUG
|
|
Carlos Lopez |
413401 |
return false;
|
|
Carlos Lopez |
413401 |
#else // _DEBUG
|
|
Carlos Lopez |
413401 |
++context;
|
|
Carlos Lopez |
413401 |
return context.accelerated_cairorender(cr, quality, renddesc, cb);
|
|
Carlos Lopez |
413401 |
#endif // _DEBUG
|
|
Carlos Lopez |
413401 |
}
|
|
Carlos Lopez |
413401 |
catch(...)
|
|
Carlos Lopez |
413401 |
{
|
|
Carlos Lopez |
413401 |
synfig::error("Context::accelerated_cairorender(): Layer \"%s\" threw an exception, rethrowing...",(*context)->get_name().c_str());
|
|
Carlos Lopez |
623fab |
throw;
|
|
Carlos Lopez |
623fab |
}
|
|
Carlos Lopez |
623fab |
}
|
|
|
d04c89 |
|
|
|
d04c89 |
//! Make rendering task using ContextParams
|
|
|
d04c89 |
rendering::Task::Handle
|
|
|
d04c89 |
Context::build_rendering_task() const
|
|
|
d04c89 |
{
|
|
|
4472a9 |
Context context = *this;
|
|
|
4472a9 |
while ( *context
|
|
|
d04c89 |
&& ( !context.active()
|
|
|
d04c89 |
|| ( !get_params().render_excluded_contexts
|
|
|
d04c89 |
&& (*context)->get_exclude_from_rendering() )))
|
|
|
d04c89 |
++context;
|
|
|
d04c89 |
|
|
|
d04c89 |
// TODO: apply z_range and z_blur (now applies in Canvas::optimize_layers)
|
|
|
d04c89 |
|
|
|
4472a9 |
return *context
|
|
|
d04c89 |
? (*context)->build_rendering_task(context.get_next())
|
|
|
ce743b |
: rendering::Task::Handle();
|
|
|
d04c89 |
}
|
|
|
d04c89 |
|