diff options
| author | Ken Raeburn | 2015-10-03 00:18:50 -0400 |
|---|---|---|
| committer | Ken Raeburn | 2015-10-08 01:44:42 -0400 |
| commit | e23ed19ff933c35111f3a806b4104fee8ef42f55 (patch) | |
| tree | dca1de3b389da477befb537c46a3a7992c02b1ea /src | |
| parent | b8eea1d7b1485a147f112127c0ca58cb1a0a8ebb (diff) | |
| download | emacs-e23ed19ff933c35111f3a806b4104fee8ef42f55.tar.gz emacs-e23ed19ff933c35111f3a806b4104fee8ef42f55.zip | |
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')
| -rw-r--r-- | src/image.c | 14 | ||||
| -rw-r--r-- | src/xfaces.c | 9 | ||||
| -rw-r--r-- | src/xftfont.c | 3 | ||||
| -rw-r--r-- | src/xterm.c | 77 | ||||
| -rw-r--r-- | src/xterm.h | 27 |
5 files changed, 104 insertions, 26 deletions
diff --git a/src/image.c b/src/image.c index 79bf21e8865..401689e940a 100644 --- a/src/image.c +++ b/src/image.c | |||
| @@ -4442,15 +4442,7 @@ lookup_rgb_color (struct frame *f, int r, int g, int b) | |||
| 4442 | r = color.red, g = color.green, b = color.blue; | 4442 | r = color.red, g = color.green, b = color.blue; |
| 4443 | } | 4443 | } |
| 4444 | 4444 | ||
| 4445 | /* Scale down RGB values to the visual's bits per RGB, and shift | 4445 | return x_make_truecolor_pixel (dpyinfo, r, g, b); |
| 4446 | them to the right position in the pixel color. Note that the | ||
| 4447 | original RGB values are 16-bit values, as usual in X. */ | ||
| 4448 | pr = (r >> (16 - dpyinfo->red_bits)) << dpyinfo->red_offset; | ||
| 4449 | pg = (g >> (16 - dpyinfo->green_bits)) << dpyinfo->green_offset; | ||
| 4450 | pb = (b >> (16 - dpyinfo->blue_bits)) << dpyinfo->blue_offset; | ||
| 4451 | |||
| 4452 | /* Assemble the pixel color. */ | ||
| 4453 | return pr | pg | pb; | ||
| 4454 | } | 4446 | } |
| 4455 | 4447 | ||
| 4456 | for (p = ct_table[i]; p; p = p->next) | 4448 | for (p = ct_table[i]; p; p = p->next) |
| @@ -9542,7 +9534,6 @@ void | |||
| 9542 | x_kill_gs_process (Pixmap pixmap, struct frame *f) | 9534 | x_kill_gs_process (Pixmap pixmap, struct frame *f) |
| 9543 | { | 9535 | { |
| 9544 | struct image_cache *c = FRAME_IMAGE_CACHE (f); | 9536 | struct image_cache *c = FRAME_IMAGE_CACHE (f); |
| 9545 | int class; | ||
| 9546 | ptrdiff_t i; | 9537 | ptrdiff_t i; |
| 9547 | struct image *img; | 9538 | struct image *img; |
| 9548 | 9539 | ||
| @@ -9568,8 +9559,7 @@ x_kill_gs_process (Pixmap pixmap, struct frame *f) | |||
| 9568 | /* On displays with a mutable colormap, figure out the colors | 9559 | /* On displays with a mutable colormap, figure out the colors |
| 9569 | allocated for the image by looking at the pixels of an XImage for | 9560 | allocated for the image by looking at the pixels of an XImage for |
| 9570 | img->pixmap. */ | 9561 | img->pixmap. */ |
| 9571 | class = FRAME_X_VISUAL (f)->class; | 9562 | if (x_mutable_colormap (FRAME_X_VISUAL (f))) |
| 9572 | if (class != StaticColor && class != StaticGray && class != TrueColor) | ||
| 9573 | { | 9563 | { |
| 9574 | XImagePtr ximg; | 9564 | XImagePtr ximg; |
| 9575 | 9565 | ||
diff --git a/src/xfaces.c b/src/xfaces.c index 8cf0b427799..a3d122fbf46 100644 --- a/src/xfaces.c +++ b/src/xfaces.c | |||
| @@ -454,11 +454,9 @@ DEFUN ("dump-colors", Fdump_colors, Sdump_colors, 0, 0, 0, | |||
| 454 | void | 454 | void |
| 455 | x_free_colors (struct frame *f, unsigned long *pixels, int npixels) | 455 | x_free_colors (struct frame *f, unsigned long *pixels, int npixels) |
| 456 | { | 456 | { |
| 457 | int class = FRAME_DISPLAY_INFO (f)->visual->class; | ||
| 458 | |||
| 459 | /* If display has an immutable color map, freeing colors is not | 457 | /* If display has an immutable color map, freeing colors is not |
| 460 | necessary and some servers don't allow it. So don't do it. */ | 458 | necessary and some servers don't allow it. So don't do it. */ |
| 461 | if (class != StaticColor && class != StaticGray && class != TrueColor) | 459 | if (x_mutable_colormap (FRAME_X_VISUAL (f))) |
| 462 | { | 460 | { |
| 463 | #ifdef DEBUG_X_COLORS | 461 | #ifdef DEBUG_X_COLORS |
| 464 | unregister_colors (pixels, npixels); | 462 | unregister_colors (pixels, npixels); |
| @@ -471,7 +469,7 @@ x_free_colors (struct frame *f, unsigned long *pixels, int npixels) | |||
| 471 | 469 | ||
| 472 | #ifdef USE_X_TOOLKIT | 470 | #ifdef USE_X_TOOLKIT |
| 473 | 471 | ||
| 474 | /* Free colors used on frame F. PIXELS is an array of NPIXELS pixel | 472 | /* Free colors used on display DPY. PIXELS is an array of NPIXELS pixel |
| 475 | color values. Interrupt input must be blocked when this function | 473 | color values. Interrupt input must be blocked when this function |
| 476 | is called. */ | 474 | is called. */ |
| 477 | 475 | ||
| @@ -480,11 +478,10 @@ x_free_dpy_colors (Display *dpy, Screen *screen, Colormap cmap, | |||
| 480 | unsigned long *pixels, int npixels) | 478 | unsigned long *pixels, int npixels) |
| 481 | { | 479 | { |
| 482 | struct x_display_info *dpyinfo = x_display_info_for_display (dpy); | 480 | struct x_display_info *dpyinfo = x_display_info_for_display (dpy); |
| 483 | int class = dpyinfo->visual->class; | ||
| 484 | 481 | ||
| 485 | /* If display has an immutable color map, freeing colors is not | 482 | /* If display has an immutable color map, freeing colors is not |
| 486 | necessary and some servers don't allow it. So don't do it. */ | 483 | necessary and some servers don't allow it. So don't do it. */ |
| 487 | if (class != StaticColor && class != StaticGray && class != TrueColor) | 484 | if (x_mutable_colormap (dpyinfo->visual)) |
| 488 | { | 485 | { |
| 489 | #ifdef DEBUG_X_COLORS | 486 | #ifdef DEBUG_X_COLORS |
| 490 | unregister_colors (pixels, npixels); | 487 | unregister_colors (pixels, npixels); |
diff --git a/src/xftfont.c b/src/xftfont.c index a1846e8d461..851edb69fa0 100644 --- a/src/xftfont.c +++ b/src/xftfont.c | |||
| @@ -111,8 +111,7 @@ xftfont_get_colors (struct frame *f, struct face *face, GC gc, | |||
| 111 | colors[0].pixel = fg->pixel = xgcv.foreground; | 111 | colors[0].pixel = fg->pixel = xgcv.foreground; |
| 112 | if (bg) | 112 | if (bg) |
| 113 | colors[1].pixel = bg->pixel = xgcv.background; | 113 | colors[1].pixel = bg->pixel = xgcv.background; |
| 114 | XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, | 114 | x_query_colors (f, colors, bg ? 2 : 1); |
| 115 | bg ? 2 : 1); | ||
| 116 | fg->color.alpha = 0xFFFF; | 115 | fg->color.alpha = 0xFFFF; |
| 117 | fg->color.red = colors[0].red; | 116 | fg->color.red = colors[0].red; |
| 118 | fg->color.green = colors[0].green; | 117 | fg->color.green = colors[0].green; |
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) | |||
| 2197 | { | 2197 | { |
| 2198 | struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); | 2198 | struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); |
| 2199 | 2199 | ||
| 2200 | if (dpyinfo->red_bits > 0) | ||
| 2201 | { | ||
| 2202 | /* For TrueColor displays, we can decompose the RGB value | ||
| 2203 | directly. */ | ||
| 2204 | int i; | ||
| 2205 | unsigned int rmult, gmult, bmult; | ||
| 2206 | unsigned int rmask, gmask, bmask; | ||
| 2207 | |||
| 2208 | rmask = (1 << dpyinfo->red_bits) - 1; | ||
| 2209 | gmask = (1 << dpyinfo->green_bits) - 1; | ||
| 2210 | bmask = (1 << dpyinfo->blue_bits) - 1; | ||
| 2211 | /* If we're widening, for example, 8 bits in the pixel value to | ||
| 2212 | 16 bits for the separate-color representation, we want to | ||
| 2213 | extrapolate the lower bits based on those bits available -- | ||
| 2214 | in other words, we'd like 0xff to become 0xffff instead of | ||
| 2215 | the 0xff00 we'd get by just zero-filling the lower bits. | ||
| 2216 | |||
| 2217 | We generate a 32-bit scaled-up value and shift it, in case | ||
| 2218 | the bit count doesn't divide 16 evently (e.g., when dealing | ||
| 2219 | with a 3-3-2 bit RGB display), to get more of the lower bits | ||
| 2220 | correct. | ||
| 2221 | |||
| 2222 | Should we cache the multipliers in dpyinfo? Maybe | ||
| 2223 | special-case the 8-8-8 common case? */ | ||
| 2224 | rmult = 0xffffffff / rmask; | ||
| 2225 | gmult = 0xffffffff / gmask; | ||
| 2226 | bmult = 0xffffffff / bmask; | ||
| 2227 | |||
| 2228 | for (i = 0; i < ncolors; ++i) | ||
| 2229 | { | ||
| 2230 | unsigned int r, g, b; | ||
| 2231 | unsigned long pixel = colors[i].pixel; | ||
| 2232 | |||
| 2233 | r = (pixel >> dpyinfo->red_offset) & rmask; | ||
| 2234 | g = (pixel >> dpyinfo->green_offset) & gmask; | ||
| 2235 | b = (pixel >> dpyinfo->blue_offset) & bmask; | ||
| 2236 | |||
| 2237 | colors[i].red = (r * rmult) >> 16; | ||
| 2238 | colors[i].green = (g * gmult) >> 16; | ||
| 2239 | colors[i].blue = (b * bmult) >> 16; | ||
| 2240 | } | ||
| 2241 | return; | ||
| 2242 | } | ||
| 2243 | |||
| 2200 | if (dpyinfo->color_cells) | 2244 | if (dpyinfo->color_cells) |
| 2201 | { | 2245 | { |
| 2202 | int i; | 2246 | int i; |
| @@ -2207,9 +2251,10 @@ x_query_colors (struct frame *f, XColor *colors, int ncolors) | |||
| 2207 | eassert (dpyinfo->color_cells[pixel].pixel == pixel); | 2251 | eassert (dpyinfo->color_cells[pixel].pixel == pixel); |
| 2208 | colors[i] = dpyinfo->color_cells[pixel]; | 2252 | colors[i] = dpyinfo->color_cells[pixel]; |
| 2209 | } | 2253 | } |
| 2254 | return; | ||
| 2210 | } | 2255 | } |
| 2211 | else | 2256 | |
| 2212 | XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, ncolors); | 2257 | XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, ncolors); |
| 2213 | } | 2258 | } |
| 2214 | 2259 | ||
| 2215 | 2260 | ||
| @@ -2341,15 +2386,27 @@ x_alloc_nearest_color_1 (Display *dpy, Colormap cmap, XColor *color) | |||
| 2341 | } | 2386 | } |
| 2342 | 2387 | ||
| 2343 | 2388 | ||
| 2344 | /* Allocate the color COLOR->pixel on frame F, colormap CMAP. If an | 2389 | /* Allocate the color COLOR->pixel on frame F, colormap CMAP, after |
| 2345 | exact match can't be allocated, try the nearest color available. | 2390 | gamma correction. If an exact match can't be allocated, try the |
| 2346 | Value is true if successful. Set *COLOR to the color | 2391 | nearest color available. Value is true if successful. Set *COLOR |
| 2347 | allocated. */ | 2392 | to the color allocated. */ |
| 2348 | 2393 | ||
| 2349 | bool | 2394 | bool |
| 2350 | x_alloc_nearest_color (struct frame *f, Colormap cmap, XColor *color) | 2395 | x_alloc_nearest_color (struct frame *f, Colormap cmap, XColor *color) |
| 2351 | { | 2396 | { |
| 2397 | struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); | ||
| 2398 | |||
| 2352 | gamma_correct (f, color); | 2399 | gamma_correct (f, color); |
| 2400 | |||
| 2401 | if (dpyinfo->red_bits > 0) | ||
| 2402 | { | ||
| 2403 | color->pixel = x_make_truecolor_pixel (dpyinfo, | ||
| 2404 | color->red, | ||
| 2405 | color->green, | ||
| 2406 | color->blue); | ||
| 2407 | return true; | ||
| 2408 | } | ||
| 2409 | |||
| 2353 | return x_alloc_nearest_color_1 (FRAME_X_DISPLAY (f), cmap, color); | 2410 | return x_alloc_nearest_color_1 (FRAME_X_DISPLAY (f), cmap, color); |
| 2354 | } | 2411 | } |
| 2355 | 2412 | ||
| @@ -2363,8 +2420,16 @@ x_copy_color (struct frame *f, unsigned long pixel) | |||
| 2363 | { | 2420 | { |
| 2364 | XColor color; | 2421 | XColor color; |
| 2365 | 2422 | ||
| 2423 | /* If display has an immutable color map, freeing colors is not | ||
| 2424 | necessary and some servers don't allow it. Since we won't free a | ||
| 2425 | color once we've allocated it, we don't need to re-allocate it to | ||
| 2426 | maintain the server's reference count. */ | ||
| 2427 | if (!x_mutable_colormap (FRAME_X_VISUAL (f))) | ||
| 2428 | return pixel; | ||
| 2429 | |||
| 2366 | color.pixel = pixel; | 2430 | color.pixel = pixel; |
| 2367 | block_input (); | 2431 | block_input (); |
| 2432 | /* The color could still be found in the color_cells array. */ | ||
| 2368 | x_query_color (f, &color); | 2433 | x_query_color (f, &color); |
| 2369 | XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color); | 2434 | XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color); |
| 2370 | unblock_input (); | 2435 | unblock_input (); |
diff --git a/src/xterm.h b/src/xterm.h index 300a8b769f2..d8edbc208f4 100644 --- a/src/xterm.h +++ b/src/xterm.h | |||
| @@ -1085,6 +1085,33 @@ x_display_set_last_user_time (struct x_display_info *dpyinfo, Time t) | |||
| 1085 | dpyinfo->last_user_time = t; | 1085 | dpyinfo->last_user_time = t; |
| 1086 | } | 1086 | } |
| 1087 | 1087 | ||
| 1088 | INLINE unsigned long | ||
| 1089 | x_make_truecolor_pixel (struct x_display_info *dpyinfo, int r, int g, int b) | ||
| 1090 | { | ||
| 1091 | unsigned long pr, pg, pb; | ||
| 1092 | |||
| 1093 | /* Scale down RGB values to the visual's bits per RGB, and shift | ||
| 1094 | them to the right position in the pixel color. Note that the | ||
| 1095 | original RGB values are 16-bit values, as usual in X. */ | ||
| 1096 | pr = (r >> (16 - dpyinfo->red_bits)) << dpyinfo->red_offset; | ||
| 1097 | pg = (g >> (16 - dpyinfo->green_bits)) << dpyinfo->green_offset; | ||
| 1098 | pb = (b >> (16 - dpyinfo->blue_bits)) << dpyinfo->blue_offset; | ||
| 1099 | |||
| 1100 | /* Assemble the pixel color. */ | ||
| 1101 | return pr | pg | pb; | ||
| 1102 | } | ||
| 1103 | |||
| 1104 | /* If display has an immutable color map, freeing colors is not | ||
| 1105 | necessary and some servers don't allow it, so we won't do it. That | ||
| 1106 | also allows us to make other optimizations relating to server-side | ||
| 1107 | reference counts. */ | ||
| 1108 | INLINE bool | ||
| 1109 | x_mutable_colormap (Visual *visual) | ||
| 1110 | { | ||
| 1111 | int class = visual->class; | ||
| 1112 | return (class != StaticColor && class != StaticGray && class != TrueColor); | ||
| 1113 | } | ||
| 1114 | |||
| 1088 | extern void x_set_sticky (struct frame *, Lisp_Object, Lisp_Object); | 1115 | extern void x_set_sticky (struct frame *, Lisp_Object, Lisp_Object); |
| 1089 | extern bool x_wm_supports (struct frame *, Atom); | 1116 | extern bool x_wm_supports (struct frame *, Atom); |
| 1090 | extern void x_wait_for_event (struct frame *, int); | 1117 | extern void x_wait_for_event (struct frame *, int); |