Upstream-Status: Pending --- libmatchbox/libmb/mbpixbuf.c.orig 2007-05-04 14:41:55.000000000 +0100 +++ libmatchbox/libmb/mbpixbuf.c 2007-05-04 14:41:55.000000000 +0100 @@ -710,46 +710,19 @@ return colnum; } - -static unsigned long -mb_pixbuf_get_pixel(MBPixbuf *pb, int r, int g, int b, int a) +/* + * Split the mb_pixbuf_get_pixel() function into several specialized + * functions which we will inline; this allows us to optimize + * mb_pixbuf_img_render_to_drawable_with_gc () by taking some of the + * decision taking outside of the double loop + */ + +/* + * Get pixel value for rgb values and pixel depth <= 8 + */ +static inline unsigned long +mb_pixbuf_get_pixel_le8_rgb (MBPixbuf *pb, int r, int g, int b) { - if (pb->depth > 8) - { - switch (pb->depth) - { - case 15: - return ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3); - case 16: - return ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3); - case 24: - case 32: - switch (pb->byte_order) - { - case BYTE_ORD_24_RGB: - return ((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff); - case BYTE_ORD_24_RBG: - return ((r & 0xff) << 16) | ((b & 0xff) << 8) | (g & 0xff); - case BYTE_ORD_24_BRG: - return ((b & 0xff) << 16) | ((r & 0xff) << 8) | (g & 0xff); - case BYTE_ORD_24_BGR: - return ((b & 0xff) << 16) | ((g & 0xff) << 8) | (r & 0xff); - case BYTE_ORD_24_GRB: - return ((g & 0xff) << 16) | ((r & 0xff) << 8) | (b & 0xff); - case BYTE_ORD_24_GBR: - return ((g & 0xff) << 16) | ((b & 0xff) << 8) | (r & 0xff); - case BYTE_ORD_32_ARGB: - return (a << 24) | (r << 16) | (g << 8) | b; - default: - return 0; - } - default: - return 0; - } - return 0; - } - - /* pb->depth <= 8 */ switch(pb->vis->class) { case PseudoColor: @@ -794,6 +767,111 @@ return 0; } +/* + * Get pixel value from a pointer to 16bbp value for pixel depth <= 8 + * and advance the pointer + */ +static inline unsigned long +mb_pixbuf_get_pixel_le8_16bpp_advance (MBPixbuf *pb, unsigned char ** p) +{ + unsigned short s = SHORT_FROM_2BYTES(*p); + int r, b, g; + + r = (s & 0xf800) >> 8; + g = (s & 0x07e0) >> 3; + b = (s & 0x001f) << 3; + + *p += 2; + + return mb_pixbuf_get_pixel_le8_rgb (pb, r, g, b); +} + +/* + * Get pixel value for rgba values and pixel depth > 8 + * + */ +static inline unsigned long +mb_pixbuf_get_pixel_gt8_rgba (MBPixbuf *pb, int r, int g, int b, int a) +{ + switch (pb->depth) + { + case 15: + switch (pb->byte_order) + { + case BYTE_ORD_24_RGB: + return ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3); + case BYTE_ORD_24_BGR: + return ((b & 0xf8) << 7) | ((g & 0xf8) << 2) | ((r & 0xf8) >> 3); + } + case 16: + switch (pb->byte_order) + { + case BYTE_ORD_24_RGB: + return ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3); + case BYTE_ORD_24_BGR: + return ((b & 0xf8) << 8) | ((g & 0xfc) << 3) | ((r & 0xf8) >> 3); + } + case 24: + case 32: + switch (pb->byte_order) + { + case BYTE_ORD_24_RGB: + return ((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff); + case BYTE_ORD_24_RBG: + return ((r & 0xff) << 16) | ((b & 0xff) << 8) | (g & 0xff); + case BYTE_ORD_24_BRG: + return ((b & 0xff) << 16) | ((r & 0xff) << 8) | (g & 0xff); + case BYTE_ORD_24_BGR: + return ((b & 0xff) << 16) | ((g & 0xff) << 8) | (r & 0xff); + case BYTE_ORD_24_GRB: + return ((g & 0xff) << 16) | ((r & 0xff) << 8) | (b & 0xff); + case BYTE_ORD_24_GBR: + return ((g & 0xff) << 16) | ((b & 0xff) << 8) | (r & 0xff); + case BYTE_ORD_32_ARGB: + return (a << 24) | (r << 16) | (g << 8) | b; + default: + return 0; + } + default: + return 0; + } +} + +/* + * Get pixel value from pointer to 16bpp data for pixel depth > 8 + * and advance the pointer + * + * TODO ? We could take the 32bit case out of here, which would allow + * to ignore the alpha value for <15, 24>, but we might not gain that + * much by this on arm due to the conditional execution. + */ +static inline unsigned long +mb_pixbuf_get_pixel_gt8_16bpp_advance (MBPixbuf *pb, unsigned char ** p, + int has_alpha) +{ + unsigned short s = SHORT_FROM_2BYTES(*p); + int r, b, g, a; + + r = (s & 0xf800) >> 8; + g = (s & 0x07e0) >> 3; + b = (s & 0x001f) << 3; + + *p += 2; + + a = has_alpha ? *(*p)++ : 0xff; + + return mb_pixbuf_get_pixel_gt8_rgba (pb, r, g, b, a); +} + +static inline unsigned long +mb_pixbuf_get_pixel(MBPixbuf *pb, int r, int g, int b, int a) +{ + if (pb->depth > 8) + return mb_pixbuf_get_pixel_gt8_rgba (pb, r, g, b, a); + + return mb_pixbuf_get_pixel_le8_rgb (pb, r, g, b); +} + unsigned long mb_pixbuf_lookup_x_pixel(MBPixbuf *pb, int r, int g, int b, int a) { @@ -1825,7 +1903,6 @@ mb_pixbuf_img_render_to_drawable_with_gc(pb, img, drw, drw_x, drw_y, pb->gc); } - void mb_pixbuf_img_render_to_drawable_with_gc(MBPixbuf *pb, MBPixbufImage *img, @@ -1883,31 +1960,57 @@ if (pb->internal_bytespp == 2) { - for(y=0; yheight; y++) - for(x=0; xwidth; x++) - { - /* Below is potentially dangerous. - */ - pixel = ( *p | (*(p+1) << 8)); - - p += ((img->has_alpha) ? 3 : 2); - - XPutPixel(img->ximg, x, y, pixel); - } + if (pb->depth > 8) + { + for(y=0; yheight; y++) + for(x=0; xwidth; x++) + { + pixel = mb_pixbuf_get_pixel_gt8_16bpp_advance(pb, &p, + img->has_alpha); + XPutPixel(img->ximg, x, y, pixel); + } + } + else + { + for(y=0; yheight; y++) + for(x=0; xwidth; x++) + { + pixel = mb_pixbuf_get_pixel_le8_16bpp_advance(pb, &p); + XPutPixel(img->ximg, x, y, pixel); + } + } } else { - for(y=0; yheight; y++) + if (pb->depth > 8) { - for(x=0; xwidth; x++) + for(y=0; yheight; y++) { - r = ( *p++ ); - g = ( *p++ ); - b = ( *p++ ); - a = ((img->has_alpha) ? *p++ : 0xff); + for(x=0; xwidth; x++) + { + r = ( *p++ ); + g = ( *p++ ); + b = ( *p++ ); + a = ((img->has_alpha) ? *p++ : 0xff); - pixel = mb_pixbuf_get_pixel(pb, r, g, b, a); - XPutPixel(img->ximg, x, y, pixel); + pixel = mb_pixbuf_get_pixel_gt8_rgba(pb, r, g, b, a); + XPutPixel(img->ximg, x, y, pixel); + } + } + } + else + { + for(y=0; yheight; y++) + { + for(x=0; xwidth; x++) + { + r = ( *p++ ); + g = ( *p++ ); + b = ( *p++ ); + + pixel = mb_pixbuf_get_pixel_le8_rgb(pb, r, g, b); + XPutPixel(img->ximg, x, y, pixel); + } } } }