summaryrefslogtreecommitdiffstats
path: root/libass/ass_rasterizer.c
diff options
context:
space:
mode:
authorDr.Smile <vabnick@gmail.com>2015-06-26 02:14:21 +0300
committerDr.Smile <vabnick@gmail.com>2015-06-26 02:14:21 +0300
commit38a175cad5a894467cb7187ad0187db1ae3f89ff (patch)
treea7262be6620f31c2f0d8df26218c6160c5354f56 /libass/ass_rasterizer.c
parent88f1fd37fe5785851f069e3dc6939f1ab905f4bc (diff)
downloadlibass-38a175cad5a894467cb7187ad0187db1ae3f89ff.tar.bz2
libass-38a175cad5a894467cb7187ad0187db1ae3f89ff.tar.xz
Switch to virtual function table
Use one pointer to table of functions instead of scattered bunch of function pointers. Different versions of these tables can be constructed in compile time. Also, bitmap memory alignment now depends only on SSE2/AVX2 support and is constant for every width. That simplifies code without noticeable performance penalty.
Diffstat (limited to 'libass/ass_rasterizer.c')
-rw-r--r--libass/ass_rasterizer.c92
1 files changed, 47 insertions, 45 deletions
diff --git a/libass/ass_rasterizer.c b/libass/ass_rasterizer.c
index 05463de7..8a0ee3bf 100644
--- a/libass/ass_rasterizer.c
+++ b/libass/ass_rasterizer.c
@@ -47,8 +47,9 @@ static inline int ilog2(uint32_t n) // XXX: different compilers
}
-void rasterizer_init(ASS_Rasterizer *rst)
+void rasterizer_init(RasterizerData *rst, int outline_error)
{
+ rst->outline_error = outline_error;
rst->linebuf[0] = rst->linebuf[1] = NULL;
rst->size[0] = rst->capacity[0] = 0;
rst->size[1] = rst->capacity[1] = 0;
@@ -60,7 +61,7 @@ void rasterizer_init(ASS_Rasterizer *rst)
* \param delta requested size increase
* \return zero on error
*/
-static inline int check_capacity(ASS_Rasterizer *rst, int index, size_t delta)
+static inline int check_capacity(RasterizerData *rst, int index, size_t delta)
{
delta += rst->size[index];
if (rst->capacity[index] >= delta)
@@ -78,7 +79,7 @@ static inline int check_capacity(ASS_Rasterizer *rst, int index, size_t delta)
return 1;
}
-void rasterizer_done(ASS_Rasterizer *rst)
+void rasterizer_done(RasterizerData *rst)
{
free(rst->linebuf[0]);
free(rst->linebuf[1]);
@@ -145,7 +146,7 @@ static inline int segment_subdivide(const OutlineSegment *seg,
/**
* \brief Add new segment to polyline
*/
-static inline int add_line(ASS_Rasterizer *rst, OutlinePoint pt0, OutlinePoint pt1)
+static inline int add_line(RasterizerData *rst, OutlinePoint pt0, OutlinePoint pt1)
{
int32_t x = pt1.x - pt0.x;
int32_t y = pt1.y - pt0.y;
@@ -192,7 +193,7 @@ static inline int add_line(ASS_Rasterizer *rst, OutlinePoint pt0, OutlinePoint p
* \brief Add quadratic spline to polyline
* Performs recursive subdivision if necessary.
*/
-static int add_quadratic(ASS_Rasterizer *rst,
+static int add_quadratic(RasterizerData *rst,
OutlinePoint pt0, OutlinePoint pt1, OutlinePoint pt2)
{
OutlineSegment seg;
@@ -218,7 +219,7 @@ static int add_quadratic(ASS_Rasterizer *rst,
* \brief Add cubic spline to polyline
* Performs recursive subdivision if necessary.
*/
-static int add_cubic(ASS_Rasterizer *rst,
+static int add_cubic(RasterizerData *rst,
OutlinePoint pt0, OutlinePoint pt1, OutlinePoint pt2, OutlinePoint pt3)
{
OutlineSegment seg;
@@ -251,7 +252,7 @@ static int add_cubic(ASS_Rasterizer *rst,
}
-int rasterizer_set_outline(ASS_Rasterizer *rst, const ASS_Outline *path)
+int rasterizer_set_outline(RasterizerData *rst, const ASS_Outline *path)
{
enum Status {
S_ON, S_Q, S_C1, S_C2
@@ -612,56 +613,56 @@ static int polyline_split_vert(const struct segment *src, size_t n_src,
}
-static inline void rasterizer_fill_solid(ASS_Rasterizer *rst,
+static inline void rasterizer_fill_solid(const BitmapEngine *engine,
uint8_t *buf, int width, int height, ptrdiff_t stride,
int set)
{
- assert(!(width & ((1 << rst->tile_order) - 1)));
- assert(!(height & ((1 << rst->tile_order) - 1)));
+ assert(!(width & ((1 << engine->tile_order) - 1)));
+ assert(!(height & ((1 << engine->tile_order) - 1)));
int i, j;
- ptrdiff_t step = 1 << rst->tile_order;
- ptrdiff_t tile_stride = stride * (1 << rst->tile_order);
- width >>= rst->tile_order;
- height >>= rst->tile_order;
+ ptrdiff_t step = 1 << engine->tile_order;
+ ptrdiff_t tile_stride = stride * (1 << engine->tile_order);
+ width >>= engine->tile_order;
+ height >>= engine->tile_order;
for (j = 0; j < height; ++j) {
for (i = 0; i < width; ++i)
- rst->fill_solid(buf + i * step, stride, set);
+ engine->fill_solid(buf + i * step, stride, set);
buf += tile_stride;
}
}
-static inline void rasterizer_fill_halfplane(ASS_Rasterizer *rst,
+static inline void rasterizer_fill_halfplane(const BitmapEngine *engine,
uint8_t *buf, int width, int height, ptrdiff_t stride,
int32_t a, int32_t b, int64_t c, int32_t scale)
{
- assert(!(width & ((1 << rst->tile_order) - 1)));
- assert(!(height & ((1 << rst->tile_order) - 1)));
- if (width == 1 << rst->tile_order && height == 1 << rst->tile_order) {
- rst->fill_halfplane(buf, stride, a, b, c, scale);
+ assert(!(width & ((1 << engine->tile_order) - 1)));
+ assert(!(height & ((1 << engine->tile_order) - 1)));
+ if (width == 1 << engine->tile_order && height == 1 << engine->tile_order) {
+ engine->fill_halfplane(buf, stride, a, b, c, scale);
return;
}
uint32_t abs_a = a < 0 ? -a : a;
uint32_t abs_b = b < 0 ? -b : b;
- int64_t size = (int64_t)(abs_a + abs_b) << (rst->tile_order + 5);
- int64_t offs = ((int64_t)a + b) * (1 << (rst->tile_order + 5));
+ int64_t size = (int64_t)(abs_a + abs_b) << (engine->tile_order + 5);
+ int64_t offs = ((int64_t)a + b) * (1 << (engine->tile_order + 5));
int i, j;
- ptrdiff_t step = 1 << rst->tile_order;
- ptrdiff_t tile_stride = stride * (1 << rst->tile_order);
- width >>= rst->tile_order;
- height >>= rst->tile_order;
+ ptrdiff_t step = 1 << engine->tile_order;
+ ptrdiff_t tile_stride = stride * (1 << engine->tile_order);
+ width >>= engine->tile_order;
+ height >>= engine->tile_order;
for (j = 0; j < height; ++j) {
for (i = 0; i < width; ++i) {
- int64_t cc = c - (a * (int64_t)i + b * (int64_t)j) * (1 << (rst->tile_order + 6));
+ int64_t cc = c - (a * (int64_t)i + b * (int64_t)j) * (1 << (engine->tile_order + 6));
int64_t offs_c = offs - cc;
int64_t abs_c = offs_c < 0 ? -offs_c : offs_c;
if (abs_c < size)
- rst->fill_halfplane(buf + i * step, stride, a, b, cc, scale);
+ engine->fill_halfplane(buf + i * step, stride, a, b, cc, scale);
else
- rst->fill_solid(buf + i * step, stride,
- ((uint32_t)(offs_c >> 32) ^ scale) & 0x80000000);
+ engine->fill_solid(buf + i * step, stride,
+ ((uint32_t)(offs_c >> 32) ^ scale) & 0x80000000);
}
buf += tile_stride;
}
@@ -676,18 +677,19 @@ static inline void rasterizer_fill_halfplane(ASS_Rasterizer *rst,
* Rasterizes (possibly recursive) one quad-tree level.
* Truncates used input buffer.
*/
-static int rasterizer_fill_level(ASS_Rasterizer *rst,
- uint8_t *buf, int width, int height, ptrdiff_t stride, int index, size_t offs, int winding)
+static int rasterizer_fill_level(const BitmapEngine *engine, RasterizerData *rst,
+ uint8_t *buf, int width, int height, ptrdiff_t stride,
+ int index, size_t offs, int winding)
{
assert(width > 0 && height > 0);
assert((unsigned)index < 2u && offs <= rst->size[index]);
- assert(!(width & ((1 << rst->tile_order) - 1)));
- assert(!(height & ((1 << rst->tile_order) - 1)));
+ assert(!(width & ((1 << engine->tile_order) - 1)));
+ assert(!(height & ((1 << engine->tile_order) - 1)));
size_t n = rst->size[index] - offs;
struct segment *line = rst->linebuf[index] + offs;
if (!n) {
- rasterizer_fill_solid(rst, buf, width, height, stride, winding);
+ rasterizer_fill_solid(engine, buf, width, height, stride, winding);
return 1;
}
if (n == 1) {
@@ -701,16 +703,16 @@ static int rasterizer_fill_level(ASS_Rasterizer *rst,
if (winding - 1)
flag ^= 3;
if (flag & 1)
- rasterizer_fill_halfplane(rst, buf, width, height, stride,
+ rasterizer_fill_halfplane(engine, buf, width, height, stride,
line->a, line->b, line->c,
flag & 2 ? -line->scale : line->scale);
else
- rasterizer_fill_solid(rst, buf, width, height, stride, flag & 2);
+ rasterizer_fill_solid(engine, buf, width, height, stride, flag & 2);
rst->size[index] = offs;
return 1;
}
- if (width == 1 << rst->tile_order && height == 1 << rst->tile_order) {
- rst->fill_generic(buf, stride, line, rst->size[index] - offs, winding);
+ if (width == 1 << engine->tile_order && height == 1 << engine->tile_order) {
+ engine->fill_generic(buf, stride, line, rst->size[index] - offs, winding);
rst->size[index] = offs;
return 1;
}
@@ -739,21 +741,21 @@ static int rasterizer_fill_level(ASS_Rasterizer *rst,
rst->size[index ^ 0] = dst0 - rst->linebuf[index ^ 0];
rst->size[index ^ 1] = dst1 - rst->linebuf[index ^ 1];
- if (!rasterizer_fill_level(rst, buf, width, height, stride, index ^ 0, offs, winding))
+ if (!rasterizer_fill_level(engine, rst, buf, width, height, stride, index ^ 0, offs, winding))
return 0;
assert(rst->size[index ^ 0] == offs);
- if (!rasterizer_fill_level(rst, buf1, width1, height1, stride, index ^ 1, offs1, winding1))
+ if (!rasterizer_fill_level(engine, rst, buf1, width1, height1, stride, index ^ 1, offs1, winding1))
return 0;
assert(rst->size[index ^ 1] == offs1);
return 1;
}
-int rasterizer_fill(ASS_Rasterizer *rst,
+int rasterizer_fill(const BitmapEngine *engine, RasterizerData *rst,
uint8_t *buf, int x0, int y0, int width, int height, ptrdiff_t stride)
{
assert(width > 0 && height > 0);
- assert(!(width & ((1 << rst->tile_order) - 1)));
- assert(!(height & ((1 << rst->tile_order) - 1)));
+ assert(!(width & ((1 << engine->tile_order) - 1)));
+ assert(!(height & ((1 << engine->tile_order) - 1)));
x0 *= 1 << 6; y0 *= 1 << 6;
size_t n = rst->size[0];
@@ -805,6 +807,6 @@ int rasterizer_fill(ASS_Rasterizer *rst,
}
rst->size[index] = n;
rst->size[index ^ 1] = 0;
- return rasterizer_fill_level(rst, buf, width, height, stride,
+ return rasterizer_fill_level(engine, rst, buf, width, height, stride,
index, 0, winding);
}