emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] master e23ed19 2/4: Reduce color allocation/query traffic


From: Ken Raeburn
Subject: [Emacs-diffs] master e23ed19 2/4: Reduce color allocation/query traffic in the TrueColor case.
Date: Thu, 08 Oct 2015 05:51:23 +0000

branch: master
commit e23ed19ff933c35111f3a806b4104fee8ef42f55
Author: Ken Raeburn <address@hidden>
Commit: Ken Raeburn <address@hidden>

    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.
---
 src/image.c   |   14 +---------
 src/xfaces.c  |    9 ++----
 src/xftfont.c |    3 +-
 src/xterm.c   |   77 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
 src/xterm.h   |   27 ++++++++++++++++++++
 5 files changed, 104 insertions(+), 26 deletions(-)

diff --git a/src/image.c b/src/image.c
index 79bf21e..401689e 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)
          r = color.red, g = color.green, b = color.blue;
        }
 
-      /* Scale down RGB values to the visual's bits per RGB, and shift
-        them to the right position in the pixel color.  Note that the
-        original RGB values are 16-bit values, as usual in X.  */
-      pr = (r >> (16 - dpyinfo->red_bits))   << dpyinfo->red_offset;
-      pg = (g >> (16 - dpyinfo->green_bits)) << dpyinfo->green_offset;
-      pb = (b >> (16 - dpyinfo->blue_bits))  << dpyinfo->blue_offset;
-
-      /* Assemble the pixel color.  */
-      return pr | pg | pb;
+      return x_make_truecolor_pixel (dpyinfo, r, g, b);
     }
 
   for (p = ct_table[i]; p; p = p->next)
@@ -9542,7 +9534,6 @@ void
 x_kill_gs_process (Pixmap pixmap, struct frame *f)
 {
   struct image_cache *c = FRAME_IMAGE_CACHE (f);
-  int class;
   ptrdiff_t i;
   struct image *img;
 
@@ -9568,8 +9559,7 @@ x_kill_gs_process (Pixmap pixmap, struct frame *f)
   /* On displays with a mutable colormap, figure out the colors
      allocated for the image by looking at the pixels of an XImage for
      img->pixmap.  */
-  class = FRAME_X_VISUAL (f)->class;
-  if (class != StaticColor && class != StaticGray && class != TrueColor)
+  if (x_mutable_colormap (FRAME_X_VISUAL (f)))
     {
       XImagePtr ximg;
 
diff --git a/src/xfaces.c b/src/xfaces.c
index 8cf0b42..a3d122f 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -454,11 +454,9 @@ DEFUN ("dump-colors", Fdump_colors, Sdump_colors, 0, 0, 0,
 void
 x_free_colors (struct frame *f, unsigned long *pixels, int npixels)
 {
-  int class = FRAME_DISPLAY_INFO (f)->visual->class;
-
   /* If display has an immutable color map, freeing colors is not
      necessary and some servers don't allow it.  So don't do it.  */
-  if (class != StaticColor && class != StaticGray && class != TrueColor)
+  if (x_mutable_colormap (FRAME_X_VISUAL (f)))
     {
 #ifdef DEBUG_X_COLORS
       unregister_colors (pixels, npixels);
@@ -471,7 +469,7 @@ x_free_colors (struct frame *f, unsigned long *pixels, int 
npixels)
 
 #ifdef USE_X_TOOLKIT
 
-/* Free colors used on frame F.  PIXELS is an array of NPIXELS pixel
+/* Free colors used on display DPY.  PIXELS is an array of NPIXELS pixel
    color values.  Interrupt input must be blocked when this function
    is called.  */
 
@@ -480,11 +478,10 @@ x_free_dpy_colors (Display *dpy, Screen *screen, Colormap 
cmap,
                   unsigned long *pixels, int npixels)
 {
   struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
-  int class = dpyinfo->visual->class;
 
   /* If display has an immutable color map, freeing colors is not
      necessary and some servers don't allow it.  So don't do it.  */
-  if (class != StaticColor && class != StaticGray && class != TrueColor)
+  if (x_mutable_colormap (dpyinfo->visual))
     {
 #ifdef DEBUG_X_COLORS
       unregister_colors (pixels, npixels);
diff --git a/src/xftfont.c b/src/xftfont.c
index a1846e8..851edb6 100644
--- a/src/xftfont.c
+++ b/src/xftfont.c
@@ -111,8 +111,7 @@ xftfont_get_colors (struct frame *f, struct face *face, GC 
gc,
          colors[0].pixel = fg->pixel = xgcv.foreground;
          if (bg)
            colors[1].pixel = bg->pixel = xgcv.background;
-         XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors,
-                       bg ? 2 : 1);
+         x_query_colors (f, colors, bg ? 2 : 1);
          fg->color.alpha = 0xFFFF;
          fg->color.red = colors[0].red;
          fg->color.green = colors[0].green;
diff --git a/src/xterm.c b/src/xterm.c
index 6065f96..8be893e 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 ();
diff --git a/src/xterm.h b/src/xterm.h
index 300a8b7..d8edbc2 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)
   dpyinfo->last_user_time = t;
 }
 
+INLINE unsigned long
+x_make_truecolor_pixel (struct x_display_info *dpyinfo, int r, int g, int b)
+{
+  unsigned long pr, pg, pb;
+
+  /* Scale down RGB values to the visual's bits per RGB, and shift
+     them to the right position in the pixel color.  Note that the
+     original RGB values are 16-bit values, as usual in X.  */
+  pr = (r >> (16 - dpyinfo->red_bits))   << dpyinfo->red_offset;
+  pg = (g >> (16 - dpyinfo->green_bits)) << dpyinfo->green_offset;
+  pb = (b >> (16 - dpyinfo->blue_bits))  << dpyinfo->blue_offset;
+
+  /* Assemble the pixel color.  */
+  return pr | pg | pb;
+}
+
+/* If display has an immutable color map, freeing colors is not
+   necessary and some servers don't allow it, so we won't do it.  That
+   also allows us to make other optimizations relating to server-side
+   reference counts.  */
+INLINE bool
+x_mutable_colormap (Visual *visual)
+{
+  int class = visual->class;
+  return (class != StaticColor && class != StaticGray && class != TrueColor);
+}
+
 extern void x_set_sticky (struct frame *, Lisp_Object, Lisp_Object);
 extern bool x_wm_supports (struct frame *, Atom);
 extern void x_wait_for_event (struct frame *, int);



reply via email to

[Prev in Thread] Current Thread [Next in Thread]