aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKen Raeburn2015-10-03 00:18:50 -0400
committerKen Raeburn2015-10-08 01:44:42 -0400
commite23ed19ff933c35111f3a806b4104fee8ef42f55 (patch)
treedca1de3b389da477befb537c46a3a7992c02b1ea /src
parentb8eea1d7b1485a147f112127c0ca58cb1a0a8ebb (diff)
downloademacs-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.c14
-rw-r--r--src/xfaces.c9
-rw-r--r--src/xftfont.c3
-rw-r--r--src/xterm.c77
-rw-r--r--src/xterm.h27
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
9542x_kill_gs_process (Pixmap pixmap, struct frame *f) 9534x_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,
454void 454void
455x_free_colors (struct frame *f, unsigned long *pixels, int npixels) 455x_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
2349bool 2394bool
2350x_alloc_nearest_color (struct frame *f, Colormap cmap, XColor *color) 2395x_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
1088INLINE unsigned long
1089x_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. */
1108INLINE bool
1109x_mutable_colormap (Visual *visual)
1110{
1111 int class = visual->class;
1112 return (class != StaticColor && class != StaticGray && class != TrueColor);
1113}
1114
1088extern void x_set_sticky (struct frame *, Lisp_Object, Lisp_Object); 1115extern void x_set_sticky (struct frame *, Lisp_Object, Lisp_Object);
1089extern bool x_wm_supports (struct frame *, Atom); 1116extern bool x_wm_supports (struct frame *, Atom);
1090extern void x_wait_for_event (struct frame *, int); 1117extern void x_wait_for_event (struct frame *, int);