From 0f4f404b3bc726918ef4e6b772ab7384282fc3c3 Mon Sep 17 00:00:00 2001 From: Vito Caputo Date: Thu, 31 Aug 2023 19:03:46 -0700 Subject: modules/pixbounce: make pixbounce threaded Pixbounce isn't a particularly costly thing to render, but when used as part of a composition, any time wasted with idle CPUs is CPU time potentially stolen from other layers which could be utilizing those CPUs. So in this commit I've done a rather minimal conversion of the pixbounce code to support threaded rendering. It basically doubles+ lone pixbounce FPS in --video=mem tests here. --- src/modules/pixbounce/pixbounce.c | 63 +++++++++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 22 deletions(-) (limited to 'src/modules/pixbounce/pixbounce.c') diff --git a/src/modules/pixbounce/pixbounce.c b/src/modules/pixbounce/pixbounce.c index e927e76..df0e6be 100644 --- a/src/modules/pixbounce/pixbounce.c +++ b/src/modules/pixbounce/pixbounce.c @@ -255,16 +255,14 @@ static til_module_context_t * pixbounce_create_context(const til_module_t *modul return &ctxt->til_module_context; } -static void pixbounce_render_fragment(til_module_context_t *context, til_stream_t *stream, unsigned ticks, unsigned cpu, til_fb_fragment_t **fragment_ptr) +static void pixbounce_prepare_frame(til_module_context_t *context, til_stream_t *stream, unsigned ticks, til_fb_fragment_t **fragment_ptr, til_frame_plan_t *res_frame_plan) { pixbounce_context_t *ctxt = (pixbounce_context_t *)context; til_fb_fragment_t *fragment = *fragment_ptr; + int width = fragment->width, height = fragment->height; - int width = fragment->width, height = fragment->height; - - /* check for very small fragment */ - if(ctxt->pix->width*2>width||ctxt->pix->height*2>height) - return; + /* tell rototiller how to subfragment the frame for threaded rendering */ + *res_frame_plan = (til_frame_plan_t){ .fragmenter = til_fragmenter_tile64 }; if(ctxt->x == -1) { int multiplier_x, multiplier_y; @@ -287,21 +285,6 @@ static void pixbounce_render_fragment(til_module_context_t *context, til_stream_ } - /* blank the frame */ - til_fb_fragment_clear(fragment); - - /* translate pixmap to multiplier size and draw it to the fragment */ - for(int cursor_y=0; cursor_y < ctxt->pix->height*ctxt->multiplier; cursor_y++) { - for(int cursor_x=0; cursor_x < ctxt->pix->width*ctxt->multiplier; cursor_x++) { - int pix_offset = ((cursor_y/ctxt->multiplier)*ctxt->pix->width) + (cursor_x/ctxt->multiplier); - if(ctxt->pix->pix_map[pix_offset] == 0) continue; - til_fb_fragment_put_pixel_checked( - fragment, TIL_FB_DRAW_FLAG_TEXTURABLE, ctxt->x+cursor_x, ctxt->y+cursor_y, - ctxt->color - ); - } - } - /* update pixmap location */ if (ticks != context->last_ticks) { if(ctxt->x+ctxt->x_dir < 0 || ctxt->x+ctxt->pix->width*ctxt->multiplier+ctxt->x_dir > width) { @@ -317,14 +300,50 @@ static void pixbounce_render_fragment(til_module_context_t *context, til_stream_ } } +static void pixbounce_render_fragment(til_module_context_t *context, til_stream_t *stream, unsigned ticks, unsigned cpu, til_fb_fragment_t **fragment_ptr) +{ + pixbounce_context_t *ctxt = (pixbounce_context_t *)context; + til_fb_fragment_t *fragment = *fragment_ptr; + int pix_y, pix_x, pix_w, pix_h; + + /* blank the fragment */ + til_fb_fragment_clear(fragment); + + /* check if this fragment is entirely outside the scaled pix */ + if (fragment->x > ctxt->x + ctxt->pix->width * ctxt->multiplier || + fragment->x + fragment->width < ctxt->x || + fragment->y > ctxt->y + ctxt->pix->height * ctxt->multiplier || + fragment->y + fragment->height < ctxt->y) + return; + + /* clip the scaled+placed pix to fragment->{x,y,width,height} */ + pix_x = MAX(ctxt->x, fragment->x) - ctxt->x; + pix_y = MAX(ctxt->y, fragment->y) - ctxt->y; + pix_w = MIN(ctxt->x + ctxt->pix->width * ctxt->multiplier, fragment->x + fragment->width) - (ctxt->x + pix_x) ; + pix_h = MIN(ctxt->y + ctxt->pix->height * ctxt->multiplier, fragment->y + fragment->height) - (ctxt->y + pix_y); + + /* translate pixmap to multiplier size and draw it to the fragment */ + for(int cursor_y = 0; cursor_y < pix_h; cursor_y++) { + for(int cursor_x = 0; cursor_x < pix_w; cursor_x++) { + int pix_offset = (((cursor_y+pix_y)/ctxt->multiplier)*ctxt->pix->width) + ((cursor_x+pix_x)/ctxt->multiplier); + if(ctxt->pix->pix_map[pix_offset] == 0) continue; + til_fb_fragment_put_pixel_unchecked( + fragment, TIL_FB_DRAW_FLAG_TEXTURABLE, ctxt->x+pix_x+cursor_x, ctxt->y+pix_y+cursor_y, + ctxt->color + ); + } + } +} + int pixbounce_setup(const til_settings_t *settings, til_setting_t **res_setting, const til_setting_desc_t **res_desc, til_setup_t **res_setup); til_module_t pixbounce_module = { .create_context = pixbounce_create_context, + .prepare_frame = pixbounce_prepare_frame, .render_fragment = pixbounce_render_fragment, .setup = pixbounce_setup, .name = "pixbounce", - .description = "Pixmap bounce", + .description = "Pixmap bounce (threaded)", .author = "Philip J Freeman ", .flags = TIL_MODULE_OVERLAYABLE, }; -- cgit v1.2.1