summaryrefslogtreecommitdiffstats
path: root/libass
diff options
context:
space:
mode:
authorDr.Smile <vabnick@gmail.com>2022-03-20 02:44:05 +0300
committerDr.Smile <vabnick@gmail.com>2022-12-04 02:17:38 +0300
commit6e0991e541ddd6f618e8d98004cab75e3fdbaab8 (patch)
tree7f90f8f2b7074ec124ed4b64d27481a47c7b2f99 /libass
parent662b913d4d3d41403985f5fe68cca64b17b2ff9c (diff)
downloadlibass-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.c6
-rw-r--r--libass/ass_bitmap_engine.c125
-rw-r--r--libass/ass_bitmap_engine.h4
-rw-r--r--libass/ass_rasterizer.c2
-rw-r--r--libass/ass_render.c46
-rw-r--r--libass/ass_render.h2
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;
};