bool TaskClampSW::run(RunParams&) const { RectInt r = target_rect; if (!r.valid()) { VectorInt offset = get_offset(); RectInt ra = sub_task()->target_rect + r.get_min() + get_offset(); if (ra.valid()) { etl::set_intersect(ra, ra, r); if (ra.valid()) { LockWrite ldst(this); if (!ldst) return false; LockRead lsrc(sub_task()); if (!lsrc) return false; const synfig::Surface &a = lsrc->get_surface(); synfig::Surface &c = ldst->get_surface(); for(int y = ra.miny; y < ra.maxy; ++y) { const Color *ca = &a[y - r.miny + offset[1]][ra.minx - r.minx + offset[0]]; Color *cc = &c[y][ra.minx]; for(int x = ra.minx; x < ra.maxx; ++x, ++ca, ++cc) clamp_pixel(*cc, *ca); } } } } return true; }
bool TaskBlendSW::run(RunParams & /* params */) const { const synfig::Surface &a = SurfaceSW::Handle::cast_dynamic( sub_task_a()->target_surface )->get_surface(); const synfig::Surface &b = SurfaceSW::Handle::cast_dynamic( sub_task_b()->target_surface )->get_surface(); synfig::Surface &c = SurfaceSW::Handle::cast_dynamic( target_surface )->get_surface(); //debug::DebugSurface::save_to_file(a, "TaskBlendSW__run__a"); //debug::DebugSurface::save_to_file(b, "TaskBlendSW__run__b"); RectInt r = get_target_rect(); if (r.valid()) { RectInt ra = sub_task_a()->get_target_rect() + r.get_min() + offset_a; if (ra.valid()) { etl::set_intersect(ra, ra, r); if (ra.valid() && &a != &c) { synfig::Surface::pen p = c.get_pen(ra.minx, ra.maxx); const_cast<synfig::Surface*>(&a)->blit_to( p, ra.minx - r.minx - offset_a[0], ra.miny - r.miny - offset_a[1], ra.maxx - ra.minx, ra.maxy - ra.miny ); } } RectInt fill[] = { ra, RectInt::zero(), RectInt::zero(), RectInt::zero() }; RectInt rb = sub_task_b()->get_target_rect() + r.get_min() + offset_b; if (rb.valid()) { etl::set_intersect(rb, rb, r); if (rb.valid()) { synfig::Surface::alpha_pen ap(c.get_pen(rb.minx, rb.miny)); ap.set_blend_method(blend_method); ap.set_alpha(amount); const_cast<synfig::Surface*>(&b)->blit_to( ap, rb.minx - r.minx - offset_b[0], rb.miny - r.miny - offset_b[1], rb.maxx - rb.minx, rb.maxy - rb.miny ); if (ra.valid()) { // mark unfilled regions fill[0] = fill[1] = fill[2] = fill[3] = ra; fill[0].maxx = fill[2].minx = fill[3].minx = std::max(ra.minx, std::min(ra.maxx, rb.minx)); fill[1].minx = fill[2].maxx = fill[3].maxx = std::max(ra.minx, std::min(ra.maxx, rb.maxx)); fill[2].maxy = std::max(ra.miny, std::min(ra.maxy, rb.miny)); fill[3].miny = std::max(ra.miny, std::min(ra.maxy, rb.maxy)); } } } if (Color::is_straight(blend_method)) { for(int i = 0; i < 4; ++i) { if (fill[i].valid()) { synfig::Surface::alpha_pen ap( c.get_pen(fill[i].minx, fill[i].miny) ); ap.set_blend_method(blend_method); ap.set_alpha(amount); c.fill( Color(0, 0, 0, 0), ap, fill[i].maxx - fill[i].minx, fill[i].maxy - fill[i].miny ); } } } } //debug::DebugSurface::save_to_file(c, "TaskBlendSW__run__c"); return true; }
bool synfig::Target_Tile::render_frame_(Context context,ProgressCallback *cb) { const RendDesc &rend_desc(desc); 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; RectInt rect; int i = 0; etl::clock tile_timer; tile_timer.reset(); while(next_tile(rect)) { find_tile_time+=tile_timer(); SuperCallback super(cb,i,i+1,10000); if(!super.amount_complete(0,1000)) return false; ++i; // Perform clipping on the tile if(clipping_) etl::set_intersect(rect, rect, RectInt(0, 0, rend_desc.get_w(), rend_desc.get_h())); tile_desc=rend_desc; tile_desc.set_subwindow(rect.minx, rect.miny, rect.maxx - rect.minx, rect.maxy - rect. miny); if(!parametric_render(context, surface, tile_desc,&super)) { // For some reason, the parametric renderer failed. if(cb)cb->error(_("Parametric Renderer Failure")); return false; } else { if(!surface) { if(cb)cb->error(_("Bad surface")); return false; } switch(get_alpha_mode()) { case TARGET_ALPHA_MODE_FILL: for(int i=0;i<surface.get_w()*surface.get_h();i++) surface[0][i]=Color::blend(surface[0][i],desc.get_bg_color(),1.0f); break; case TARGET_ALPHA_MODE_EXTRACT: for(int i=0;i<surface.get_w()*surface.get_h();i++) { float a=surface[0][i].get_a(); surface[0][i] = Color(a,a,a,a); } break; case TARGET_ALPHA_MODE_REDUCE: for(int i=0;i<surface.get_w()*surface.get_h();i++) surface[0][i].set_a(1.0f); break; default: break; } // Add the tile to the target if(!add_tile(surface, rect.minx, rect.miny)) { if(cb)cb->error(_("add_tile():Unable to put surface on target")); return false; } } tile_timer.reset(); } SuperCallback super(cb,i,10000,10000); } else // If quality is set otherwise, then we use the accelerated renderer { etl::clock tile_timer; tile_timer.reset(); // Gather tiles std::vector<RectInt> tiles; RectInt rect; while(next_tile(rect)) { if (clipping_) if (rect.minx >= rend_desc.get_w() || rect.miny >= rend_desc.get_h()) continue; tiles.push_back(rect); } find_tile_time += tile_timer(); // Render tiles for(std::vector<RectInt>::iterator i = tiles.begin(); i != tiles.end(); ++i) { // Progress callback int index = i - tiles.begin(); int count = (int)tiles.size(); SuperCallback super(cb, (count-index)*1000, (count-index+1)*1000, count*1000); if(!super.amount_complete(0,1000)) return false; // Render tile tile_timer.reset(); rect = *i; if (clipping_) etl::set_intersect(rect, rect, RectInt(0, 0, rend_desc.get_w(), rend_desc.get_h())); if (!rect.valid()) continue; RendDesc tile_desc=rend_desc; tile_desc.set_subwindow(rect.minx, rect.miny, rect.maxx - rect.minx, rect.maxy - rect.miny); async_render_tile(rect, context, tile_desc, &super); } } if (!wait_render_tiles(cb)) return false; if(cb && !cb->amount_complete(10000,10000)) return false; #ifdef SYNFIG_DISPLAY_EFFICIENCY 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 return true; }