diff options
author | Ken Raeburn <raeburn@raeburn.org> | 2015-10-03 00:18:50 -0400 |
---|---|---|
committer | Ken Raeburn <raeburn@raeburn.org> | 2015-10-08 01:44:42 -0400 |
commit | e23ed19ff933c35111f3a806b4104fee8ef42f55 (patch) | |
tree | dca1de3b389da477befb537c46a3a7992c02b1ea /src/xterm.c | |
parent | b8eea1d7b1485a147f112127c0ca58cb1a0a8ebb (diff) | |
download | emacs-e23ed19ff933c35111f3a806b4104fee8ef42f55.tar.gz |
Reduce color allocation/query traffic in the TrueColor case.
When working with an X visual with TrueColor class, pixel values can
be generated from the RGB values according to mask value provided by
the server on connection. Some of the image-handling code was already
doing this.
* src/xterm.h (x_make_truecolor_pixel): New function; code taken from
lookup_rgb_color.
(x_mutable_colormap): New function.
* src/image.c (lookup_rgb_color): Move pixel composition code to
x_make_truecolor_pixel.
(x_kill_gs_process): Call x_mutable_colormap.
* src/xfaces.c (x_free_colors, x_free_dpy_colors): Call
x_mutable_colormap.
* src/xftfont.c (xftfont_get_colors): Call x_query_colors.
* src/xterm.c (x_query_colors): For a TrueColor display, decompose the
pixel value into RGB values directly, and don't send a request to the
server.
(x_alloc_nearest_color): For a TrueColor display, construct the pixel
value with x_make_truecolor_pixel.
(x_copy_color): For an immutable color map, just return the provided
pixel value.
Diffstat (limited to 'src/xterm.c')
-rw-r--r-- | src/xterm.c | 77 |
1 files changed, 71 insertions, 6 deletions
diff --git a/src/xterm.c b/src/xterm.c index 6065f964063..8be893eca6f 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -2197,6 +2197,50 @@ x_query_colors (struct frame *f, XColor *colors, int ncolors) { struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); + if (dpyinfo->red_bits > 0) + { + /* For TrueColor displays, we can decompose the RGB value + directly. */ + int i; + unsigned int rmult, gmult, bmult; + unsigned int rmask, gmask, bmask; + + rmask = (1 << dpyinfo->red_bits) - 1; + gmask = (1 << dpyinfo->green_bits) - 1; + bmask = (1 << dpyinfo->blue_bits) - 1; + /* If we're widening, for example, 8 bits in the pixel value to + 16 bits for the separate-color representation, we want to + extrapolate the lower bits based on those bits available -- + in other words, we'd like 0xff to become 0xffff instead of + the 0xff00 we'd get by just zero-filling the lower bits. + + We generate a 32-bit scaled-up value and shift it, in case + the bit count doesn't divide 16 evently (e.g., when dealing + with a 3-3-2 bit RGB display), to get more of the lower bits + correct. + + Should we cache the multipliers in dpyinfo? Maybe + special-case the 8-8-8 common case? */ + rmult = 0xffffffff / rmask; + gmult = 0xffffffff / gmask; + bmult = 0xffffffff / bmask; + + for (i = 0; i < ncolors; ++i) + { + unsigned int r, g, b; + unsigned long pixel = colors[i].pixel; + + r = (pixel >> dpyinfo->red_offset) & rmask; + g = (pixel >> dpyinfo->green_offset) & gmask; + b = (pixel >> dpyinfo->blue_offset) & bmask; + + colors[i].red = (r * rmult) >> 16; + colors[i].green = (g * gmult) >> 16; + colors[i].blue = (b * bmult) >> 16; + } + return; + } + if (dpyinfo->color_cells) { int i; @@ -2207,9 +2251,10 @@ x_query_colors (struct frame *f, XColor *colors, int ncolors) eassert (dpyinfo->color_cells[pixel].pixel == pixel); colors[i] = dpyinfo->color_cells[pixel]; } + return; } - else - XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, ncolors); + + XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, ncolors); } @@ -2341,15 +2386,27 @@ x_alloc_nearest_color_1 (Display *dpy, Colormap cmap, XColor *color) } -/* Allocate the color COLOR->pixel on frame F, colormap CMAP. If an - exact match can't be allocated, try the nearest color available. - Value is true if successful. Set *COLOR to the color - allocated. */ +/* Allocate the color COLOR->pixel on frame F, colormap CMAP, after + gamma correction. If an exact match can't be allocated, try the + nearest color available. Value is true if successful. Set *COLOR + to the color allocated. */ bool x_alloc_nearest_color (struct frame *f, Colormap cmap, XColor *color) { + struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); + gamma_correct (f, color); + + if (dpyinfo->red_bits > 0) + { + color->pixel = x_make_truecolor_pixel (dpyinfo, + color->red, + color->green, + color->blue); + return true; + } + return x_alloc_nearest_color_1 (FRAME_X_DISPLAY (f), cmap, color); } @@ -2363,8 +2420,16 @@ x_copy_color (struct frame *f, unsigned long pixel) { XColor color; + /* If display has an immutable color map, freeing colors is not + necessary and some servers don't allow it. Since we won't free a + color once we've allocated it, we don't need to re-allocate it to + maintain the server's reference count. */ + if (!x_mutable_colormap (FRAME_X_VISUAL (f))) + return pixel; + color.pixel = pixel; block_input (); + /* The color could still be found in the color_cells array. */ x_query_color (f, &color); XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color); unblock_input (); |