[AD] Optimized blitting between color depths |
[ Thread Index |
Date Index
| More lists.liballeg.org/allegro-developers Archives
]
Hello,
The attached patch does two optimizations:
- Various small tricks to improve the speed of makecol15_dither() and
makecol16_dither().
- The code in blit.c to convert between color depths with
COLCONV_KEEP_TRANS was unnecessarily involved. I re-factored it to
improve both readability and speed (and reduce code size).
On my AMD Athlon it gives roughly the following improvements depending
on the color conversion and dithering flags set by
set_color_conversion() (the time per call after the patch, in percent of
the time per call before the patch, so small is good):
45% for COLCONV_KEEP_TRANS
68% for COLCONV_DITHERED | COLCONV_KEEP_TRANS
94% for COLCONV_DITHERED
I put my test program, together with the test results on my computer, at
http://user.it.uu.se/~svens/convert-blit.zip
/Sven
Index: src/blit.c
===================================================================
RCS file: /cvsroot/alleg/allegro/src/blit.c,v
retrieving revision 1.13
diff -u -r1.13 blit.c
--- src/blit.c 8 Apr 2004 19:26:20 -0000 1.13
+++ src/blit.c 31 Oct 2004 15:16:35 -0000
@@ -156,121 +156,46 @@
-/* makecol_trans:
- * Helper function to convert pixel values with transparency preserving.
- */
-static int makecol_trans(BITMAP *src, BITMAP *dest, int c, int r, int g, int b)
-{
- static int rc;
- static BITMAP *rc_bmp = NULL;
-
- if (c == bitmap_mask_color(src)) {
- c = bitmap_mask_color(dest);
- return c;
- }
-
- c = makecol_depth(bitmap_color_depth(dest), r, g, b);
-
- if (c == bitmap_mask_color(dest)) {
- if (dest != rc_bmp) {
- rc = get_replacement_mask_color(dest);
- rc_bmp = dest;
- }
- c = rc;
- }
-
- return c;
-}
-
-
-
-/* worker macro for converting between two color formats */
-#define CONVERT_BLIT(sbits, ssize, dbits, dsize) \
+/* worker macro for converting between two color formats, possibly with dithering */
+#define CONVERT_BLIT_EX(sbits, ssize, dbits, dsize, MAKECOL) \
{ \
- for (y=0; y<h; y++) { \
- s = bmp_read_line(src, s_y+y) + s_x*ssize; \
- d = bmp_write_line(dest, d_y+y) + d_x*dsize; \
- \
- if (_color_conv & COLORCONV_KEEP_TRANS) { \
- for (x=0; x<w; x++) { \
- bmp_select(src); \
- c = bmp_read##sbits(s); \
- \
- r = getr##sbits(c); \
- g = getg##sbits(c); \
- b = getb##sbits(c); \
- \
- bmp_select(dest); \
- bmp_write##dbits(d, makecol_trans(src, dest, c, r, g, b)); \
+ if (_color_conv & COLORCONV_KEEP_TRANS) { \
+ int rc = get_replacement_mask_color(dest); \
+ int src_mask = bitmap_mask_color(src); \
+ int dest_mask = bitmap_mask_color(dest); \
+ \
+ for (y=0; y<h; y++) { \
+ s = bmp_read_line(src, s_y+y) + s_x*ssize; \
+ d = bmp_write_line(dest, d_y+y) + d_x*dsize; \
\
- s += ssize; \
- d += dsize; \
- } \
- } \
- else { \
for (x=0; x<w; x++) { \
bmp_select(src); \
c = bmp_read##sbits(s); \
\
- r = getr##sbits(c); \
- g = getg##sbits(c); \
- b = getb##sbits(c); \
+ if (c == src_mask) \
+ c = dest_mask; \
+ else { \
+ r = getr##sbits(c); \
+ g = getg##sbits(c); \
+ b = getb##sbits(c); \
+ c = MAKECOL; \
+ if (c == dest_mask) \
+ c = rc; \
+ } \
\
bmp_select(dest); \
- bmp_write##dbits(d, makecol##dbits(r, g, b)); \
+ bmp_write##dbits(d, c); \
\
s += ssize; \
d += dsize; \
} \
} \
} \
+ else { \
+ for (y=0; y<h; y++) { \
+ s = bmp_read_line(src, s_y+y) + s_x*ssize; \
+ d = bmp_write_line(dest, d_y+y) + d_x*dsize; \
\
- bmp_unwrite_line(src); \
- bmp_unwrite_line(dest); \
-}
-
-
-
-/* makecol_dither_trans:
- * Helper function to convert pixel values with dithering and transparency preserving.
- */
-static int makecol_dither_trans(BITMAP *src, BITMAP *dest, int c, int r, int g, int b,
- int x, int y)
-{
- static int rc;
- static BITMAP *rc_bmp = NULL;
-
- if (c == bitmap_mask_color(src)) {
- c = bitmap_mask_color(dest);
- return c;
- }
-
- if (bitmap_color_depth(dest) == 15)
- c = makecol15_dither(r, g, b, x, y);
- else
- c = makecol16_dither(r, g, b, x, y);
-
- if (c == bitmap_mask_color(dest)) {
- if (dest != rc_bmp) {
- rc = get_replacement_mask_color(dest);
- rc_bmp = dest;
- }
- c = rc;
- }
-
- return c;
-}
-
-
-
-/* worker macro for converting formats with dithering */
-#define CONVERT_DITHER_BLIT(sbits, ssize, dbits, dsize) \
-{ \
- for (y=0; y<h; y++) { \
- s = bmp_read_line(src, s_y+y) + s_x*ssize; \
- d = bmp_write_line(dest, d_y+y) + d_x*dsize; \
- \
- if (_color_conv & COLORCONV_KEEP_TRANS) { \
for (x=0; x<w; x++) { \
bmp_select(src); \
c = bmp_read##sbits(s); \
@@ -280,24 +205,7 @@
b = getb##sbits(c); \
\
bmp_select(dest); \
- bmp_write##dbits(d, makecol_dither_trans(src, dest, c, r, g, b, \
- x ,y )); \
- \
- s += ssize; \
- d += dsize; \
- } \
- } \
- else { \
- for (x=0; x<w; x++) { \
- bmp_select(src); \
- c = bmp_read##sbits(s); \
- \
- r = getr##sbits(c); \
- g = getg##sbits(c); \
- b = getb##sbits(c); \
- \
- bmp_select(dest); \
- bmp_write##dbits(d, makecol##dbits##_dither(r, g, b, x, y)); \
+ bmp_write##dbits(d, MAKECOL); \
\
s += ssize; \
d += dsize; \
@@ -309,6 +217,12 @@
bmp_unwrite_line(dest); \
}
+#define CONVERT_BLIT(sbits, ssize, dbits, dsize) \
+ CONVERT_BLIT_EX(sbits, ssize, dbits, dsize, makecol##dbits(r, g, b))
+#define CONVERT_DITHER_BLIT(sbits, ssize, dbits, dsize) \
+ CONVERT_BLIT_EX(sbits, ssize, dbits, dsize, \
+ makecol##dbits##_dither(r, g, b, x, y))
+
#if (defined ALLEGRO_COLOR8) || (defined GFX_MODEX)
Index: src/dither.c
===================================================================
RCS file: /cvsroot/alleg/allegro/src/dither.c,v
retrieving revision 1.2
diff -u -r1.2 dither.c
--- src/dither.c 24 May 2001 09:30:19 -0000 1.2
+++ src/dither.c 31 Oct 2004 15:16:35 -0000
@@ -20,7 +20,7 @@
-static unsigned char dither_table[7] = { 16, 68, 146, 170, 109, 187, 239 };
+static unsigned char dither_table[8] = { 0, 16, 68, 146, 170, 109, 187, 239 };
static unsigned char dither_ytable[8] = { 1, 5, 2, 7, 4, 0, 6, 3 };
@@ -33,35 +33,24 @@
int returned_r, returned_g, returned_b;
int bpos;
- returned_r = r/8;
- returned_b = b/8;
- returned_g = g/8;
+ returned_r = r>>3;
+ returned_g = g>>3;
+ returned_b = b>>3;
y = dither_ytable[y&7];
- if (r&7) {
- bpos = (x+y)&7;
- returned_r += ((dither_table[((r&7)-1)]) & (1<<bpos)) >> bpos;
- }
-
- if (b&7) {
- bpos = (x+y+3)&7;
- returned_b += ((dither_table[((b&7)-1)]) & (1<<bpos)) >> bpos;
- }
-
- if (g&7) {
- bpos = (x+y+2)&7;
- returned_g += ((dither_table[(g&7)-1]) & (1<<bpos)) >> bpos;
- }
-
- if (returned_r > 31)
- returned_r = 31;
-
- if (returned_b > 31)
- returned_b = 31;
-
- if (returned_g > 31)
- returned_g = 31;
+ bpos = (x+y)&7;
+ returned_r += (dither_table[r&7] >> bpos) & 1;
+
+ bpos = (bpos+3)&7;
+ returned_b += (dither_table[b&7] >> bpos) & 1;
+
+ bpos = (bpos+7)&7;
+ returned_g += (dither_table[g&7] >> bpos) & 1;
+
+ returned_r -= returned_r>>5;
+ returned_g -= returned_g>>5;
+ returned_b -= returned_b>>5;
return (returned_r<<_rgb_r_shift_15) | (returned_g<<_rgb_g_shift_15) | (returned_b<<_rgb_b_shift_15);
}
@@ -76,35 +65,24 @@
int returned_r, returned_g, returned_b;
int bpos;
- returned_r = r/8;
- returned_b = b/8;
- returned_g = g/4;
+ returned_r = r>>3;
+ returned_g = g>>2;
+ returned_b = b>>3;
y = dither_ytable[y&7];
- if (r&7) {
- bpos = (x+y)&7;
- returned_r += ((dither_table[((r&7)-1)]) & (1<<bpos)) >> bpos;
- }
-
- if (b&7) {
- bpos = (x+y+3)&7;
- returned_b += ((dither_table[((b&7)-1)]) & (1<<bpos)) >> bpos;
- }
-
- if (g&3) {
- bpos = (x+y+2)&7;
- returned_g += ((dither_table[(g&3)*2-1]) & (1<<bpos)) >> bpos;
- }
-
- if (returned_r > 31)
- returned_r = 31;
-
- if (returned_b > 31)
- returned_b = 31;
-
- if (returned_g > 63)
- returned_g = 63;
+ bpos = (x+y)&7;
+ returned_r += (dither_table[r&7] >> bpos) & 1;
+
+ bpos = (bpos+3)&7;
+ returned_b += (dither_table[b&7] >> bpos) & 1;
+
+ bpos = (bpos+7)&7;
+ returned_g += (dither_table[(g&3)*2] >> bpos) & 1;
+
+ returned_r -= returned_r>>5;
+ returned_g -= returned_g>>6;
+ returned_b -= returned_b>>5;
return (returned_r<<_rgb_r_shift_16) | (returned_g<<_rgb_g_shift_16) | (returned_b<<_rgb_b_shift_16);
}