diff options
author | Jan Ziak <0xe2.0x9a.0x9b@gmail.com> | 2019-10-12 08:58:23 +0200 |
---|---|---|
committer | Emmanuele Bassi <ebassi@gnome.org> | 2020-06-26 11:45:29 +0100 |
commit | 679e9ed7b056ec3b17921863b5c7d2873a43c3b3 (patch) | |
tree | 6aec31f93e2bf0d2b10642398a7c56183aa49e34 | |
parent | c7eada6cac522d095fdd13770619d807ca538346 (diff) | |
download | gdk-pixbuf-679e9ed7b056ec3b17921863b5c7d2873a43c3b3.tar.gz |
pixops: Avoid division during alpha scaling
This patch significantly improves performance
of gtksourceview-2.10.5 full-screen redraw
on a 4K display with an alpha channel.
Divisions by the common value 0xff0000 are converted into
multiplications by an optimizing C compiler.
For other values, 3 divisions are reduced to 1 division,
3 multiplications and some float-to-int conversions.
-rw-r--r-- | gdk-pixbuf/pixops/pixops.c | 37 |
1 files changed, 28 insertions, 9 deletions
diff --git a/gdk-pixbuf/pixops/pixops.c b/gdk-pixbuf/pixops/pixops.c index a1c3c9bfd..623dbd09e 100644 --- a/gdk-pixbuf/pixops/pixops.c +++ b/gdk-pixbuf/pixops/pixops.c @@ -956,11 +956,20 @@ scale_pixel (guchar *dest, int dest_x, int dest_channels, int dest_has_alpha, { if (src_has_alpha) { - if (a) + if (a == 0xff0000) { - dest[0] = r / a; - dest[1] = g / a; - dest[2] = b / a; + /* Division by a constant is converted into a multiplication by an optimizing C compiler */ + dest[0] = r / 0xff0000; + dest[1] = g / 0xff0000; + dest[2] = b / 0xff0000; + dest[3] = 0xff0000 >> 16; + } + else if (a) + { + double a1 = 1.0 / a; + dest[0] = r * a1; + dest[1] = g * a1; + dest[2] = b * a1; dest[3] = a >> 16; } else @@ -991,6 +1000,7 @@ scale_line (int *weights, int n_x, int n_y, guchar *dest, int dest_x, { int x = x_init; int i, j; + const int n_xy = n_x * n_y; while (dest < dest_end) { @@ -998,7 +1008,7 @@ scale_line (int *weights, int n_x, int n_y, guchar *dest, int dest_x, int *pixel_weights; pixel_weights = weights + - ((x >> (SCALE_SHIFT - SUBSAMPLE_BITS)) & SUBSAMPLE_MASK) * n_x * n_y; + ((x >> (SCALE_SHIFT - SUBSAMPLE_BITS)) & SUBSAMPLE_MASK) * n_xy; if (src_has_alpha) { @@ -1022,11 +1032,20 @@ scale_line (int *weights, int n_x, int n_y, guchar *dest, int dest_x, } } - if (a) + if (a == 0xff0000) + { + /* Division by a constant is converted into a multiplication by an optimizing C compiler */ + dest[0] = r / 0xff0000; + dest[1] = g / 0xff0000; + dest[2] = b / 0xff0000; + dest[3] = 0xff0000 >> 16; + } + else if (a) { - dest[0] = r / a; - dest[1] = g / a; - dest[2] = b / a; + double a1 = 1.0 / a; + dest[0] = r * a1; + dest[1] = g * a1; + dest[2] = b * a1; dest[3] = a >> 16; } else |