void OptimizerBlendZero::apply_zero(const RunParams ¶ms, const TaskBlend::Handle &blend, const Task::Handle &task) const { if (!task || !task->valid_target()) { Task::Handle empty = new TaskSurfaceEmpty(); empty->target_surface = params.ref_task->target_surface; apply(params, empty); return; } if (task->target_surface == blend->target_surface) { apply(params, task); return; } apply(params, task->clone()); params.ref_task->target_surface = blend->target_surface; params.ref_task->move_target_rect( blend->get_target_offset() - task->get_target_offset() + (task == blend->sub_task_a() ? blend->offset_a : blend->offset_b) ); assert( params.ref_task->check() ); }
void OptimizerBlendSplit::run(const RunParams& params) const { TaskBlend::Handle blend = TaskBlend::Handle::cast_dynamic(params.ref_task); if ( blend && blend->target_surface && blend->sub_task_a() && blend->sub_task_a()->target_surface == blend->target_surface && (blend->sub_task_a().type_is<TaskSurface>() || blend->sub_task_a().type_is<TaskSurfaceEmpty>()) && blend->sub_task_b() && blend->sub_task_b()->target_surface && !Color::is_straight(blend->blend_method) ) { if (TaskList::Handle list_b = TaskList::Handle::cast_dynamic(blend->sub_task_b())) { // try to find dedicated groups std::vector<RectInt> groups; for(Task::List::const_iterator i = list_b->sub_tasks.begin(); i != list_b->sub_tasks.end(); ++i) if (*i && (*i)->valid_target()) groups.push_back((*i)->get_target_rect()); #ifndef NDEBUG int sub_tasks_count = (int)groups.size(); #endif bool retry = true; while(retry) { retry = false; for(int i = 0; i < (int)groups.size(); ++i) { for(int j = i+1; j < (int)groups.size(); ++j) { if (etl::intersect(groups[i], groups[j])) { etl::set_union(groups[i], groups[i], groups[j]); groups.erase(groups.begin() + j); --j; retry = true; } } } } // split task if (groups.size() > 1) { // create list TaskList::Handle list; list = new TaskList(); assign(list, Task::Handle(blend)); list->sub_tasks.clear(); #ifndef NDEBUG Task::Set processed; #endif // fill list for(int j = 0; j < (int)groups.size(); ++j) { // create sub-blend TaskList::Handle sub_list_b = TaskList::Handle::cast_dynamic(blend->sub_task_b()->clone()); sub_list_b->sub_tasks.clear(); sub_list_b->trunc_target_rect(groups[j]); RectInt rect = groups[j] + blend->get_target_offset() + blend->get_offset_b(); TaskBlend::Handle sub_blend = TaskBlend::Handle::cast_dynamic(blend->clone()); sub_blend->trunc_target_rect(rect); sub_blend->sub_task_a() = new TaskSurface(); assign(sub_blend->sub_task_a(), blend->sub_task_a()); sub_blend->sub_task_a()->sub_tasks.clear(); sub_blend->sub_task_a()->trunc_target_rect(rect); sub_blend->sub_task_b() = sub_list_b; list->sub_tasks.push_back(sub_blend); // fill list-b of sub-blend for(Task::List::const_iterator i = list_b->sub_tasks.begin(); i != list_b->sub_tasks.end(); ++i) if (*i && (*i)->valid_target() && etl::contains(groups[j], (*i)->get_target_rect())) { #ifndef NDEBUG assert(processed.count(*i) == 0); processed.insert(*i); #endif sub_list_b->sub_tasks.push_back(*i); } // optimization for list with single task if (sub_list_b->sub_tasks.size() == 1) sub_blend->sub_task_b() = sub_list_b->sub_tasks[0]; } #ifndef NDEBUG assert((int)processed.size() == sub_tasks_count); #endif apply(params, list); } } } }
void OptimizerBlendZero::run(const RunParams& params) const { TaskBlend::Handle blend = TaskBlend::Handle::cast_dynamic(params.ref_task); if ( blend && blend->target_surface && blend->sub_task_a() && blend->sub_task_a()->target_surface && blend->sub_task_b() && blend->sub_task_a()->target_surface) { bool zero_amount = fabsf(blend->amount) <= 1e-6; if (zero_amount) { apply_zero(params, blend, blend->sub_task_a()); return; } bool valid_a = blend->sub_task_a()->valid_target(); bool valid_b = blend->sub_task_b()->valid_target(); if (!valid_b && !valid_a) { apply_zero(params, blend, Task::Handle()); return; } bool one_amount = fabsf(blend->amount - 1.f) <= 1e-6; bool intertsects = valid_a && valid_b && etl::intersect(blend->sub_task_a()->get_target_rect(), blend->sub_task_b()->get_target_rect()); if (one_amount && !intertsects) { bool onto = Color::is_onto(blend->blend_method); bool straight = Color::is_straight(blend->blend_method); if ( onto && straight) { apply_zero(params, blend, Task::Handle()); return; } if ( onto ) { apply_zero(params, blend, blend->sub_task_a()); return; } //if ( straight ) // { apply_zero(params, blend, blend->sub_task_b()); return; } } } }