diff options
author | Dr.Smile <vabnick@gmail.com> | 2022-03-20 02:44:05 +0300 |
---|---|---|
committer | Dr.Smile <vabnick@gmail.com> | 2022-12-04 02:17:38 +0300 |
commit | 6e0991e541ddd6f618e8d98004cab75e3fdbaab8 (patch) | |
tree | 7f90f8f2b7074ec124ed4b64d27481a47c7b2f99 /libass | |
parent | 662b913d4d3d41403985f5fe68cca64b17b2ff9c (diff) | |
download | libass-6e0991e541ddd6f618e8d98004cab75e3fdbaab8.tar.bz2 libass-6e0991e541ddd6f618e8d98004cab75e3fdbaab8.tar.xz |
bitmap_engine: switch to dynamic vtable
This should help with potential combinatorial explosion.
Diffstat (limited to 'libass')
-rw-r--r-- | libass/ass_bitmap.c | 6 | ||||
-rw-r--r-- | libass/ass_bitmap_engine.c | 125 | ||||
-rw-r--r-- | libass/ass_bitmap_engine.h | 4 | ||||
-rw-r--r-- | libass/ass_rasterizer.c | 2 | ||||
-rw-r--r-- | libass/ass_render.c | 46 | ||||
-rw-r--r-- | libass/ass_render.h | 2 |
6 files changed, 101 insertions, 84 deletions
diff --git a/libass/ass_bitmap.c b/libass/ass_bitmap.c index b9ff5ee..41df5e1 100644 --- a/libass/ass_bitmap.c +++ b/libass/ass_bitmap.c @@ -170,7 +170,7 @@ bool ass_outline_to_bitmap(RenderContext *state, Bitmap *bm, int32_t w = x_max - x_min; int32_t h = y_max - y_min; - int mask = (1 << render_priv->engine->tile_order) - 1; + int mask = (1 << render_priv->engine.tile_order) - 1; // XXX: is that possible to trigger at all? if (w < 0 || h < 0 || w > INT_MAX - mask || h > INT_MAX - mask) { @@ -181,12 +181,12 @@ bool ass_outline_to_bitmap(RenderContext *state, Bitmap *bm, int32_t tile_w = (w + mask) & ~mask; int32_t tile_h = (h + mask) & ~mask; - if (!ass_alloc_bitmap(render_priv->engine, bm, tile_w, tile_h, false)) + if (!ass_alloc_bitmap(&render_priv->engine, bm, tile_w, tile_h, false)) return false; bm->left = x_min; bm->top = y_min; - if (!ass_rasterizer_fill(render_priv->engine, rst, bm->buffer, + if (!ass_rasterizer_fill(&render_priv->engine, rst, bm->buffer, x_min, y_min, bm->stride, tile_h, bm->stride)) { ass_msg(render_priv->library, MSGL_WARN, "Failed to rasterize glyph!\n"); ass_free_bitmap(bm); diff --git a/libass/ass_bitmap_engine.c b/libass/ass_bitmap_engine.c index 80aafa5..d203824 100644 --- a/libass/ass_bitmap_engine.c +++ b/libass/ass_bitmap_engine.c @@ -31,12 +31,34 @@ FillGenericTileFunc ass_fill_generic_tile ## tile_size ## _ ## suffix; \ MergeTileFunc ass_merge_tile ## tile_size ## _ ## suffix; +#define RASTERIZER_FUNCTION(name, suffix) \ + engine.name = mask & ASS_FLAG_LARGE_TILES ? \ + ass_ ## name ## _tile32_ ## suffix : \ + ass_ ## name ## _tile16_ ## suffix; + +#define RASTERIZER_FUNCTIONS(suffix) \ + RASTERIZER_FUNCTION(fill_solid, suffix) \ + RASTERIZER_FUNCTION(fill_halfplane, suffix) \ + RASTERIZER_FUNCTION(fill_generic, suffix) \ + RASTERIZER_FUNCTION(merge, suffix) + + #define GENERIC_PROTOTYPES(suffix) \ BitmapBlendFunc ass_add_bitmaps_ ## suffix; \ BitmapBlendFunc ass_imul_bitmaps_ ## suffix; \ BitmapMulFunc ass_mul_bitmaps_ ## suffix; \ BeBlurFunc ass_be_blur_ ## suffix; +#define GENERIC_FUNCTION(name, suffix) \ + engine.name = ass_ ## name ## _ ## suffix; + +#define GENERIC_FUNCTIONS(suffix) \ + GENERIC_FUNCTION(add_bitmaps, suffix) \ + GENERIC_FUNCTION(imul_bitmaps, suffix) \ + GENERIC_FUNCTION(mul_bitmaps, suffix) \ + GENERIC_FUNCTION(be_blur, suffix) + + #define PARAM_BLUR_SET(suffix) \ ass_blur4_ ## suffix, \ ass_blur5_ ## suffix, \ @@ -54,56 +76,38 @@ ParamFilterFunc PARAM_BLUR_SET(horz ## stripe_width ## _ ## suffix); \ ParamFilterFunc PARAM_BLUR_SET(vert ## stripe_width ## _ ## suffix); -#define BITMAP_ENGINE(align_order_, alignment, tile_order_, tile_size, suffix, be_suffix) \ - const BitmapEngine ass_bitmap_engine_ ## be_suffix = { \ - .align_order = align_order_, \ - .tile_order = tile_order_, \ - .fill_solid = ass_fill_solid_tile ## tile_size ## _ ## suffix, \ - .fill_halfplane = ass_fill_halfplane_tile ## tile_size ## _ ## suffix, \ - .fill_generic = ass_fill_generic_tile ## tile_size ## _ ## suffix, \ - .merge_tile = ass_merge_tile ## tile_size ## _ ## suffix, \ - .add_bitmaps = ass_add_bitmaps_ ## suffix, \ - .imul_bitmaps = ass_imul_bitmaps_ ## suffix, \ - .mul_bitmaps = ass_mul_bitmaps_ ## suffix, \ - .be_blur = ass_be_blur_ ## suffix, \ - .stripe_unpack = ass_stripe_unpack ## alignment ## _ ## suffix, \ - .stripe_pack = ass_stripe_pack ## alignment ## _ ## suffix, \ - .shrink_horz = ass_shrink_horz ## alignment ## _ ## suffix, \ - .shrink_vert = ass_shrink_vert ## alignment ## _ ## suffix, \ - .expand_horz = ass_expand_horz ## alignment ## _ ## suffix, \ - .expand_vert = ass_expand_vert ## alignment ## _ ## suffix, \ - .blur_horz = { PARAM_BLUR_SET(horz ## alignment ## _ ## suffix) }, \ - .blur_vert = { PARAM_BLUR_SET(vert ## alignment ## _ ## suffix) }, \ - }; - - -RASTERIZER_PROTOTYPES(16, c) -RASTERIZER_PROTOTYPES(32, c) -GENERIC_PROTOTYPES(c) -BLUR_PROTOTYPES(16, c) -BLUR_PROTOTYPES(32, c) -BITMAP_ENGINE(4, 16, 4, 16, c, c) -BITMAP_ENGINE(4, 16, 5, 32, c, lt_c) -BITMAP_ENGINE(5, 32, 4, 16, c, c32) -BITMAP_ENGINE(5, 32, 5, 32, c, lt_c32) +#define BLUR_FUNCTION(name, alignment, suffix) \ + engine.name = ass_ ## name ## alignment ## _ ## suffix; -#if CONFIG_ASM && ARCH_X86 +#define PARAM_BLUR_FUNCTION(dir, alignment, suffix) \ + engine.blur_ ## dir[0] = ass_blur4_ ## dir ## alignment ## _ ## suffix; \ + engine.blur_ ## dir[1] = ass_blur5_ ## dir ## alignment ## _ ## suffix; \ + engine.blur_ ## dir[2] = ass_blur6_ ## dir ## alignment ## _ ## suffix; \ + engine.blur_ ## dir[3] = ass_blur7_ ## dir ## alignment ## _ ## suffix; \ + engine.blur_ ## dir[4] = ass_blur8_ ## dir ## alignment ## _ ## suffix; -RASTERIZER_PROTOTYPES(16, sse2) -RASTERIZER_PROTOTYPES(32, sse2) -GENERIC_PROTOTYPES(sse2) -BLUR_PROTOTYPES(16, sse2) -BITMAP_ENGINE(4, 16, 4, 16, sse2, sse2) -BITMAP_ENGINE(4, 16, 5, 32, sse2, lt_sse2) +#define BLUR_FUNCTIONS(align_order_, alignment, suffix) \ + BLUR_FUNCTION(stripe_unpack, alignment, suffix) \ + BLUR_FUNCTION(stripe_pack, alignment, suffix) \ + BLUR_FUNCTION(shrink_horz, alignment, suffix) \ + BLUR_FUNCTION(shrink_vert, alignment, suffix) \ + BLUR_FUNCTION(expand_horz, alignment, suffix) \ + BLUR_FUNCTION(expand_vert, alignment, suffix) \ + PARAM_BLUR_FUNCTION(horz, alignment, suffix) \ + PARAM_BLUR_FUNCTION(vert, alignment, suffix) \ + engine.align_order = align_order_; -RASTERIZER_PROTOTYPES(16, avx2) -RASTERIZER_PROTOTYPES(32, avx2) -GENERIC_PROTOTYPES(avx2) -BLUR_PROTOTYPES(32, avx2) -BITMAP_ENGINE(5, 32, 4, 16, avx2, avx2) -BITMAP_ENGINE(5, 32, 5, 32, avx2, lt_avx2) -#endif +#define ALL_PROTOTYPES(alignment, suffix) \ + RASTERIZER_PROTOTYPES(16, suffix) \ + RASTERIZER_PROTOTYPES(32, suffix) \ + GENERIC_PROTOTYPES(suffix) \ + BLUR_PROTOTYPES(alignment, suffix) + +#define ALL_FUNCTIONS(align_order_, alignment, suffix) \ + RASTERIZER_FUNCTIONS(suffix) \ + GENERIC_FUNCTIONS(suffix) \ + BLUR_FUNCTIONS(align_order_, alignment, suffix) unsigned ass_get_cpu_flags(unsigned mask) @@ -148,18 +152,31 @@ unsigned ass_get_cpu_flags(unsigned mask) return flags & mask; } -const BitmapEngine *ass_bitmap_engine_init(unsigned mask) +BitmapEngine ass_bitmap_engine_init(unsigned mask) { + ALL_PROTOTYPES(16, c) + BLUR_PROTOTYPES(32, c) + BitmapEngine engine = {}; + engine.tile_order = mask & ASS_FLAG_LARGE_TILES ? 5 : 4; + #if CONFIG_ASM unsigned flags = ass_get_cpu_flags(mask); #if ARCH_X86 - if (flags & ASS_CPU_FLAG_X86_AVX2) - return mask & ASS_FLAG_LARGE_TILES ? &ass_bitmap_engine_lt_avx2 : &ass_bitmap_engine_avx2; - if (flags & ASS_CPU_FLAG_X86_SSE2) - return mask & ASS_FLAG_LARGE_TILES ? &ass_bitmap_engine_lt_sse2 : &ass_bitmap_engine_sse2; + if (flags & ASS_CPU_FLAG_X86_AVX2) { + ALL_PROTOTYPES(32, avx2) + ALL_FUNCTIONS(5, 32, avx2) + return engine; + } else if (flags & ASS_CPU_FLAG_X86_SSE2) { + ALL_PROTOTYPES(16, sse2) + ALL_FUNCTIONS(4, 16, sse2) + return engine; + } #endif #endif - if (mask & ASS_FLAG_WIDE_STRIPE) - return mask & ASS_FLAG_LARGE_TILES ? &ass_bitmap_engine_lt_c32 : &ass_bitmap_engine_c32; - return mask & ASS_FLAG_LARGE_TILES ? &ass_bitmap_engine_lt_c : &ass_bitmap_engine_c; + + ALL_FUNCTIONS(4, 16, c) + if (mask & ASS_FLAG_WIDE_STRIPE) { + BLUR_FUNCTIONS(5, 32, c) + } + return engine; } diff --git a/libass/ass_bitmap_engine.h b/libass/ass_bitmap_engine.h index e19f618..a143d2b 100644 --- a/libass/ass_bitmap_engine.h +++ b/libass/ass_bitmap_engine.h @@ -61,7 +61,7 @@ typedef struct { FillSolidTileFunc *fill_solid; FillHalfplaneTileFunc *fill_halfplane; FillGenericTileFunc *fill_generic; - MergeTileFunc *merge_tile; + MergeTileFunc *merge; // blend functions BitmapBlendFunc *add_bitmaps, *imul_bitmaps; @@ -91,6 +91,6 @@ enum { unsigned ass_get_cpu_flags(unsigned mask); -const BitmapEngine *ass_bitmap_engine_init(unsigned mask); +BitmapEngine ass_bitmap_engine_init(unsigned mask); #endif /* LIBASS_BITMAP_ENGINE_H */ diff --git a/libass/ass_rasterizer.c b/libass/ass_rasterizer.c index 213cf45..0ac45d1 100644 --- a/libass/ass_rasterizer.c +++ b/libass/ass_rasterizer.c @@ -676,7 +676,7 @@ static bool rasterizer_fill_level(const BitmapEngine *engine, RasterizerData *rs else engine->fill_halfplane(rst->tile, width, line1->a, line1->b, line1->c, flags1 & FLAG_REVERSE ? -line1->scale : line1->scale); - engine->merge_tile(buf, stride, rst->tile); + engine->merge(buf, stride, rst->tile); rst->size[index] = offs; return true; } diff --git a/libass/ass_render.c b/libass/ass_render.c index 64268c1..a7d7f0c 100644 --- a/libass/ass_render.c +++ b/libass/ass_render.c @@ -112,7 +112,7 @@ ASS_Renderer *ass_renderer_init(ASS_Library *library) #endif priv->engine = ass_bitmap_engine_init(flags); - if (!ass_rasterizer_init(priv->engine, &priv->state.rasterizer, RASTERIZER_PRECISION)) + if (!ass_rasterizer_init(&priv->engine, &priv->state.rasterizer, RASTERIZER_PRECISION)) goto fail; priv->cache.font_cache = ass_font_cache_create(); @@ -748,7 +748,7 @@ static void blend_vector_clip(RenderContext *state, ASS_Image *head) bleft = left - bx; btop = top - by; - unsigned align = 1 << render_priv->engine->align_order; + unsigned align = 1 << render_priv->engine.align_order; if (state->clip_drawing_mode) { // Inverse clip if (ax + aw < bx || ay + ah < by || ax > bx + bw || @@ -763,9 +763,9 @@ static void blend_vector_clip(RenderContext *state, ASS_Image *head) // Blend together memcpy(nbuffer, abuffer, ((ah - 1) * as) + aw); - render_priv->engine->imul_bitmaps(nbuffer + atop * as + aleft, as, - bbuffer + btop * bs + bleft, bs, - w, h); + render_priv->engine.imul_bitmaps(nbuffer + atop * as + aleft, as, + bbuffer + btop * bs + bleft, bs, + w, h); } else { // Regular clip if (ax + aw < bx || ay + ah < by || ax > bx + bw || @@ -781,10 +781,10 @@ static void blend_vector_clip(RenderContext *state, ASS_Image *head) break; // Blend together - render_priv->engine->mul_bitmaps(nbuffer, ns, - abuffer + atop * as + aleft, as, - bbuffer + btop * bs + bleft, bs, - w, h); + render_priv->engine.mul_bitmaps(nbuffer, ns, + abuffer + atop * as + aleft, as, + bbuffer + btop * bs + bleft, bs, + w, h); cur->dst_x += aleft; cur->dst_y += atop; cur->w = w; @@ -2702,10 +2702,10 @@ size_t ass_composite_construct(void *key, void *value, void *priv) int bord = ass_be_padding(k->filter.be); if (!bord && n_bm == 1) { - ass_copy_bitmap(render_priv->engine, &v->bm, last->bm); + ass_copy_bitmap(&render_priv->engine, &v->bm, last->bm); v->bm.left += last->pos.x; v->bm.top += last->pos.y; - } else if (n_bm && ass_alloc_bitmap(render_priv->engine, &v->bm, + } else if (n_bm && ass_alloc_bitmap(&render_priv->engine, &v->bm, rect.x_max - rect.x_min + 2 * bord, rect.y_max - rect.y_min + 2 * bord, true)) { @@ -2721,16 +2721,16 @@ size_t ass_composite_construct(void *key, void *value, void *priv) assert(x >= 0 && x + src->w <= dst->w); assert(y >= 0 && y + src->h <= dst->h); unsigned char *buf = dst->buffer + y * dst->stride + x; - render_priv->engine->add_bitmaps(buf, dst->stride, - src->buffer, src->stride, - src->w, src->h); + render_priv->engine.add_bitmaps(buf, dst->stride, + src->buffer, src->stride, + src->w, src->h); } } if (!bord && n_bm_o == 1) { - ass_copy_bitmap(render_priv->engine, &v->bm_o, last_o->bm_o); + ass_copy_bitmap(&render_priv->engine, &v->bm_o, last_o->bm_o); v->bm_o.left += last_o->pos_o.x; v->bm_o.top += last_o->pos_o.y; - } else if (n_bm_o && ass_alloc_bitmap(render_priv->engine, &v->bm_o, + } else if (n_bm_o && ass_alloc_bitmap(&render_priv->engine, &v->bm_o, rect_o.x_max - rect_o.x_min + 2 * bord, rect_o.y_max - rect_o.y_min + 2 * bord, true)) { @@ -2746,9 +2746,9 @@ size_t ass_composite_construct(void *key, void *value, void *priv) assert(x >= 0 && x + src->w <= dst->w); assert(y >= 0 && y + src->h <= dst->h); unsigned char *buf = dst->buffer + y * dst->stride + x; - render_priv->engine->add_bitmaps(buf, dst->stride, - src->buffer, src->stride, - src->w, src->h); + render_priv->engine.add_bitmaps(buf, dst->stride, + src->buffer, src->stride, + src->w, src->h); } } @@ -2756,22 +2756,22 @@ size_t ass_composite_construct(void *key, void *value, void *priv) double r2x = restore_blur(k->filter.blur_x); double r2y = restore_blur(k->filter.blur_y); if (!(flags & FILTER_NONZERO_BORDER) || (flags & FILTER_BORDER_STYLE_3)) - ass_synth_blur(render_priv->engine, &v->bm, k->filter.be, r2x, r2y); - ass_synth_blur(render_priv->engine, &v->bm_o, k->filter.be, r2x, r2y); + ass_synth_blur(&render_priv->engine, &v->bm, k->filter.be, r2x, r2y); + ass_synth_blur(&render_priv->engine, &v->bm_o, k->filter.be, r2x, r2y); if (!(flags & FILTER_FILL_IN_BORDER) && !(flags & FILTER_FILL_IN_SHADOW)) ass_fix_outline(&v->bm, &v->bm_o); if (flags & FILTER_NONZERO_SHADOW) { if (flags & FILTER_NONZERO_BORDER) { - ass_copy_bitmap(render_priv->engine, &v->bm_s, &v->bm_o); + ass_copy_bitmap(&render_priv->engine, &v->bm_s, &v->bm_o); if ((flags & FILTER_FILL_IN_BORDER) && !(flags & FILTER_FILL_IN_SHADOW)) ass_fix_outline(&v->bm, &v->bm_s); } else if (flags & FILTER_BORDER_STYLE_3) { v->bm_s = v->bm_o; memset(&v->bm_o, 0, sizeof(v->bm_o)); } else { - ass_copy_bitmap(render_priv->engine, &v->bm_s, &v->bm); + ass_copy_bitmap(&render_priv->engine, &v->bm_s, &v->bm); } // Works right even for negative offsets diff --git a/libass/ass_render.h b/libass/ass_render.h index 581c131..3c717b8 100644 --- a/libass/ass_render.h +++ b/libass/ass_render.h @@ -337,7 +337,7 @@ struct ass_renderer { TextInfo text_info; CacheStore cache; - const BitmapEngine *engine; + BitmapEngine engine; ASS_Style user_override_style; }; |