diff options
| author | Ken Raeburn | 2015-10-03 00:15:54 -0400 |
|---|---|---|
| committer | Ken Raeburn | 2015-10-08 01:19:49 -0400 |
| commit | b8eea1d7b1485a147f112127c0ca58cb1a0a8ebb (patch) | |
| tree | 215730e1b1fc26ea26a37f4b454c6da138be4c28 /src | |
| parent | 0360b7f2c4f0358106e229de4dfe91a67445a50c (diff) | |
| download | emacs-b8eea1d7b1485a147f112127c0ca58cb1a0a8ebb.tar.gz emacs-b8eea1d7b1485a147f112127c0ca58cb1a0a8ebb.zip | |
Cache XParseColor results in the X display info structure.
With repeated lookups of foreground and background colors for multiple
faces per frame, we issue a lot of redundant color name lookups to the
X server, waiting every time for the response. On a remote network
with, say, 30ms round-trip time, this can add nearly a full second to
creation of a new frame.
* src/gtkutil.c (xg_check_special_colors): Call x_parse_color.
* src/image.c (get_spec_bg_or_alpha_as_argb):
(xpm_init_color_cache, xpm_lookup_color):
* src/xfns.c (x_defined_color):
* src/xterm.c (x_parse_color): New function; caches color names not
starting with "#" in the display-info structure.
(x_delete_display): Delete the cache content.
* src/xterm.h (struct color_name_cache_entry): New type.
(x_parse_color): Declare.
(struct x_display_info): Add a new field for the cache.
Diffstat (limited to 'src')
| -rw-r--r-- | src/gtkutil.c | 4 | ||||
| -rw-r--r-- | src/image.c | 16 | ||||
| -rw-r--r-- | src/xfns.c | 2 | ||||
| -rw-r--r-- | src/xterm.c | 56 | ||||
| -rw-r--r-- | src/xterm.h | 14 |
5 files changed, 79 insertions, 13 deletions
diff --git a/src/gtkutil.c b/src/gtkutil.c index 725e3306c82..34e81b5c104 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c | |||
| @@ -583,9 +583,7 @@ xg_check_special_colors (struct frame *f, | |||
| 583 | (unsigned) (col.red * 65535), | 583 | (unsigned) (col.red * 65535), |
| 584 | (unsigned) (col.green * 65535), | 584 | (unsigned) (col.green * 65535), |
| 585 | (unsigned) (col.blue * 65535)); | 585 | (unsigned) (col.blue * 65535)); |
| 586 | success_p = (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), | 586 | success_p = x_parse_color (f, buf, color) != 0; |
| 587 | buf, color) | ||
| 588 | != 0); | ||
| 589 | #else | 587 | #else |
| 590 | GtkStyle *gsty = gtk_widget_get_style (FRAME_GTK_WIDGET (f)); | 588 | GtkStyle *gsty = gtk_widget_get_style (FRAME_GTK_WIDGET (f)); |
| 591 | GdkColor *grgb = get_bg | 589 | GdkColor *grgb = get_bg |
diff --git a/src/image.c b/src/image.c index 10b067f889c..79bf21e8865 100644 --- a/src/image.c +++ b/src/image.c | |||
| @@ -1108,10 +1108,7 @@ get_spec_bg_or_alpha_as_argb (struct image *img, | |||
| 1108 | XColor xbgcolor; | 1108 | XColor xbgcolor; |
| 1109 | Lisp_Object bg = image_spec_value (img->spec, QCbackground, NULL); | 1109 | Lisp_Object bg = image_spec_value (img->spec, QCbackground, NULL); |
| 1110 | 1110 | ||
| 1111 | if (STRINGP (bg) && XParseColor (FRAME_X_DISPLAY (f), | 1111 | if (STRINGP (bg) && x_parse_color (f, SSDATA (bg), &xbgcolor)) |
| 1112 | FRAME_X_COLORMAP (f), | ||
| 1113 | SSDATA (bg), | ||
| 1114 | &xbgcolor)) | ||
| 1115 | bgcolor = xcolor_to_argb32 (xbgcolor); | 1112 | bgcolor = xcolor_to_argb32 (xbgcolor); |
| 1116 | 1113 | ||
| 1117 | return bgcolor; | 1114 | return bgcolor; |
| @@ -3241,7 +3238,10 @@ static struct xpm_cached_color *xpm_cache_color (struct frame *, char *, | |||
| 3241 | /* An entry in a hash table used to cache color definitions of named | 3238 | /* An entry in a hash table used to cache color definitions of named |
| 3242 | colors. This cache is necessary to speed up XPM image loading in | 3239 | colors. This cache is necessary to speed up XPM image loading in |
| 3243 | case we do color allocations ourselves. Without it, we would need | 3240 | case we do color allocations ourselves. Without it, we would need |
| 3244 | a call to XParseColor per pixel in the image. */ | 3241 | a call to XParseColor per pixel in the image. |
| 3242 | |||
| 3243 | FIXME Now that we're using x_parse_color and its cache, reevaluate | ||
| 3244 | the need for this caching layer. */ | ||
| 3245 | 3245 | ||
| 3246 | struct xpm_cached_color | 3246 | struct xpm_cached_color |
| 3247 | { | 3247 | { |
| @@ -3276,8 +3276,7 @@ xpm_init_color_cache (struct frame *f, XpmAttributes *attrs) | |||
| 3276 | XColor color; | 3276 | XColor color; |
| 3277 | 3277 | ||
| 3278 | for (i = 0; i < attrs->numsymbols; ++i) | 3278 | for (i = 0; i < attrs->numsymbols; ++i) |
| 3279 | if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), | 3279 | if (x_parse_color (f, attrs->colorsymbols[i].value, &color)) |
| 3280 | attrs->colorsymbols[i].value, &color)) | ||
| 3281 | { | 3280 | { |
| 3282 | color.pixel = lookup_rgb_color (f, color.red, color.green, | 3281 | color.pixel = lookup_rgb_color (f, color.red, color.green, |
| 3283 | color.blue); | 3282 | color.blue); |
| @@ -3356,8 +3355,7 @@ xpm_lookup_color (struct frame *f, char *color_name, XColor *color) | |||
| 3356 | 3355 | ||
| 3357 | if (p != NULL) | 3356 | if (p != NULL) |
| 3358 | *color = p->color; | 3357 | *color = p->color; |
| 3359 | else if (XParseColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), | 3358 | else if (x_parse_color (f, color_name, color)) |
| 3360 | color_name, color)) | ||
| 3361 | { | 3359 | { |
| 3362 | color->pixel = lookup_rgb_color (f, color->red, color->green, | 3360 | color->pixel = lookup_rgb_color (f, color->red, color->green, |
| 3363 | color->blue); | 3361 | color->blue); |
diff --git a/src/xfns.c b/src/xfns.c index fc6111c4fab..7a236e7d6b9 100644 --- a/src/xfns.c +++ b/src/xfns.c | |||
| @@ -454,7 +454,7 @@ x_defined_color (struct frame *f, const char *color_name, | |||
| 454 | success_p = xg_check_special_colors (f, color_name, color); | 454 | success_p = xg_check_special_colors (f, color_name, color); |
| 455 | #endif | 455 | #endif |
| 456 | if (!success_p) | 456 | if (!success_p) |
| 457 | success_p = XParseColor (dpy, cmap, color_name, color) != 0; | 457 | success_p = x_parse_color (f, color_name, color) != 0; |
| 458 | if (success_p && alloc_p) | 458 | if (success_p && alloc_p) |
| 459 | success_p = x_alloc_nearest_color (f, cmap, color); | 459 | success_p = x_alloc_nearest_color (f, cmap, color); |
| 460 | unblock_input (); | 460 | unblock_input (); |
diff --git a/src/xterm.c b/src/xterm.c index dd54552510c..6065f964063 100644 --- a/src/xterm.c +++ b/src/xterm.c | |||
| @@ -2223,6 +2223,52 @@ x_query_color (struct frame *f, XColor *color) | |||
| 2223 | } | 2223 | } |
| 2224 | 2224 | ||
| 2225 | 2225 | ||
| 2226 | /* On frame F, translate the color name to RGB values. Use cached | ||
| 2227 | information, if possible. | ||
| 2228 | |||
| 2229 | Note that there is currently no way to clean old entries out of the | ||
| 2230 | cache. However, it is limited to names in the server's database, | ||
| 2231 | and names we've actually looked up; list-colors-display is probably | ||
| 2232 | the most color-intensive case we're likely to hit. */ | ||
| 2233 | |||
| 2234 | Status x_parse_color (struct frame *f, const char *color_name, | ||
| 2235 | XColor *color) | ||
| 2236 | { | ||
| 2237 | Display *dpy = FRAME_X_DISPLAY (f); | ||
| 2238 | Colormap cmap = FRAME_X_COLORMAP (f); | ||
| 2239 | Status status; | ||
| 2240 | struct color_name_cache_entry *cache_entry; | ||
| 2241 | |||
| 2242 | if (color_name[0] == '#') | ||
| 2243 | { | ||
| 2244 | /* The hex form is parsed directly by XParseColor without | ||
| 2245 | talking to the X server. No need for caching. */ | ||
| 2246 | return XParseColor (dpy, cmap, color_name, color); | ||
| 2247 | } | ||
| 2248 | |||
| 2249 | for (cache_entry = FRAME_DISPLAY_INFO (f)->color_names; cache_entry; | ||
| 2250 | cache_entry = cache_entry->next) | ||
| 2251 | { | ||
| 2252 | if (!xstrcasecmp(cache_entry->name, color_name)) | ||
| 2253 | { | ||
| 2254 | *color = cache_entry->rgb; | ||
| 2255 | return 1; | ||
| 2256 | } | ||
| 2257 | } | ||
| 2258 | |||
| 2259 | if (XParseColor (dpy, cmap, color_name, color) == 0) | ||
| 2260 | /* No caching of negative results, currently. */ | ||
| 2261 | return 0; | ||
| 2262 | |||
| 2263 | cache_entry = xzalloc (sizeof *cache_entry); | ||
| 2264 | cache_entry->rgb = *color; | ||
| 2265 | cache_entry->name = xstrdup (color_name); | ||
| 2266 | cache_entry->next = FRAME_DISPLAY_INFO (f)->color_names; | ||
| 2267 | FRAME_DISPLAY_INFO (f)->color_names = cache_entry; | ||
| 2268 | return 1; | ||
| 2269 | } | ||
| 2270 | |||
| 2271 | |||
| 2226 | /* Allocate the color COLOR->pixel on DISPLAY, colormap CMAP. If an | 2272 | /* Allocate the color COLOR->pixel on DISPLAY, colormap CMAP. If an |
| 2227 | exact match can't be allocated, try the nearest color available. | 2273 | exact match can't be allocated, try the nearest color available. |
| 2228 | Value is true if successful. Set *COLOR to the color | 2274 | Value is true if successful. Set *COLOR to the color |
| @@ -12119,6 +12165,7 @@ static void | |||
| 12119 | x_delete_display (struct x_display_info *dpyinfo) | 12165 | x_delete_display (struct x_display_info *dpyinfo) |
| 12120 | { | 12166 | { |
| 12121 | struct terminal *t; | 12167 | struct terminal *t; |
| 12168 | struct color_name_cache_entry *color_entry, *next_color_entry; | ||
| 12122 | 12169 | ||
| 12123 | /* Close all frames and delete the generic struct terminal for this | 12170 | /* Close all frames and delete the generic struct terminal for this |
| 12124 | X display. */ | 12171 | X display. */ |
| @@ -12148,6 +12195,15 @@ x_delete_display (struct x_display_info *dpyinfo) | |||
| 12148 | tail->next = tail->next->next; | 12195 | tail->next = tail->next->next; |
| 12149 | } | 12196 | } |
| 12150 | 12197 | ||
| 12198 | for (color_entry = dpyinfo->color_names; | ||
| 12199 | color_entry; | ||
| 12200 | color_entry = next_color_entry) | ||
| 12201 | { | ||
| 12202 | next_color_entry = color_entry->next; | ||
| 12203 | xfree (color_entry->name); | ||
| 12204 | xfree (color_entry); | ||
| 12205 | } | ||
| 12206 | |||
| 12151 | xfree (dpyinfo->x_id_name); | 12207 | xfree (dpyinfo->x_id_name); |
| 12152 | xfree (dpyinfo->x_dnd_atoms); | 12208 | xfree (dpyinfo->x_dnd_atoms); |
| 12153 | xfree (dpyinfo->color_cells); | 12209 | xfree (dpyinfo->color_cells); |
diff --git a/src/xterm.h b/src/xterm.h index 61659066809..300a8b769f2 100644 --- a/src/xterm.h +++ b/src/xterm.h | |||
| @@ -153,6 +153,17 @@ struct x_gc_ext_data | |||
| 153 | #endif | 153 | #endif |
| 154 | 154 | ||
| 155 | 155 | ||
| 156 | struct color_name_cache_entry | ||
| 157 | { | ||
| 158 | struct color_name_cache_entry *next; | ||
| 159 | XColor rgb; | ||
| 160 | char *name; | ||
| 161 | }; | ||
| 162 | |||
| 163 | Status x_parse_color (struct frame *f, const char *color_name, | ||
| 164 | XColor *color); | ||
| 165 | |||
| 166 | |||
| 156 | /* For each X display, we have a structure that records | 167 | /* For each X display, we have a structure that records |
| 157 | information about it. */ | 168 | information about it. */ |
| 158 | 169 | ||
| @@ -385,6 +396,9 @@ struct x_display_info | |||
| 385 | struct xim_inst_t *xim_callback_data; | 396 | struct xim_inst_t *xim_callback_data; |
| 386 | #endif | 397 | #endif |
| 387 | 398 | ||
| 399 | /* A cache mapping color names to RGB values. */ | ||
| 400 | struct color_name_cache_entry *color_names; | ||
| 401 | |||
| 388 | /* If non-null, a cache of the colors in the color map. Don't | 402 | /* If non-null, a cache of the colors in the color map. Don't |
| 389 | use this directly, call x_color_cells instead. */ | 403 | use this directly, call x_color_cells instead. */ |
| 390 | XColor *color_cells; | 404 | XColor *color_cells; |