diff --git a/otherlibs/graph/color.c b/otherlibs/graph/color.c index 75addc608..c2f569738 100644 --- a/otherlibs/graph/color.c +++ b/otherlibs/graph/color.c @@ -29,6 +29,11 @@ static struct color_cache_entry color_cache[Color_cache_size]; static int num_overflows = 0; +Bool direct_rgb = False; +int byte_order; +int bitmap_unit; +int bits_per_pixel; + void gr_init_color_cache(void) { int i; @@ -46,10 +51,22 @@ unsigned long gr_pixel_rgb(int rgb) unsigned int r, g, b; int h, i; XColor color; + unsigned short tmp; r = (rgb >> 16) & 0xFF; g = (rgb >> 8) & 0xFF; b = rgb & 0xFF; + + if (direct_rgb){ + switch ( bits_per_pixel ){ + case 16: + tmp = ((r >> 3) << 11) + ((g >> 2) << 5) + ((b >> 3) << 0); + return (unsigned long) tmp; + case 32: + return (r << 16) + (g << 8) + (b << 0); + } + } + h = Hash_rgb(r, g, b); i = h; while(1) { @@ -57,13 +74,13 @@ unsigned long gr_pixel_rgb(int rgb) if (color_cache[i].rgb == rgb) return color_cache[i].pixel; i = (i + 1) & (Color_cache_size - 1); if (i == h) { - /* Cache is full. Instead of inserting at slot h, which causes - thrasing if many colors hash to the same value, - insert at h + n where n is pseudo-random and - smaller than Color_cache_slack */ - int slack = num_overflows++ & (Color_cache_slack - 1); - i = (i + slack) & (Color_cache_size - 1); - break; + /* Cache is full. Instead of inserting at slot h, which causes + thrasing if many colors hash to the same value, + insert at h + n where n is pseudo-random and + smaller than Color_cache_slack */ + int slack = num_overflows++ & (Color_cache_slack - 1); + i = (i + slack) & (Color_cache_size - 1); + break; } } color.red = r * 0x101; diff --git a/otherlibs/graph/libgraph.h b/otherlibs/graph/libgraph.h index 0e58bace2..ac8a50bd5 100644 --- a/otherlibs/graph/libgraph.h +++ b/otherlibs/graph/libgraph.h @@ -32,6 +32,11 @@ extern int grx, gry; /* Coordinates of the current point */ extern unsigned long grcolor; /* Current drawing color */ extern XFontStruct * grfont; /* Current font */ +extern Bool direct_rgb; +extern int byte_order; +extern int bitmap_unit; +extern int bits_per_pixel; + #define Wcvt(y) (grwindow.h - 1 - (y)) #define Bcvt(y) (grbstore.h - 1 - (y)) #define WtoB(y) ((y) + grbstore.h - grwindow.h) diff --git a/otherlibs/graph/make_img.c b/otherlibs/graph/make_img.c index 2d6bfe960..fdd601cba 100644 --- a/otherlibs/graph/make_img.c +++ b/otherlibs/graph/make_img.c @@ -40,6 +40,22 @@ value gr_make_image(value m) XDefaultDepth(grdisplay, grscreen), ZPixmap, 0, NULL, width, height, BitmapPad(grdisplay), 0); + + /* To optimize RGB => color id calculation */ + if( !direct_rgb ){ + /* they are declared in color.c */ + byte_order = idata->byte_order; + bitmap_unit = idata->bitmap_unit; + bits_per_pixel = idata->bits_per_pixel; +#ifdef DIRECT_RGB_DEBUG + fprintf(stderr, "Byte_order: %d = %s\n", byte_order, + byte_order ? "LSBFirst" : "MSBFirst"); + fprintf(stderr, "Bitmp_unit: %d\n", bitmap_unit); + fprintf(stderr, "Bits per pixel: %d\n", idata->bits_per_pixel); +#endif + direct_rgb = True; + } + bdata = (char *) stat_alloc(height * idata->bytes_per_line); idata->data = bdata; has_transp = False;