From 79896d3eb7f0d2e351196e5c896e21001b75f436 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Mon, 31 Jan 2022 17:59:12 +0800 Subject: [PATCH] Improve portability of alpha channel handling on TrueColor visuals * src/xfns.c (select_visual): Always ask for a TrueColor visual. * src/xfont.c (xfont_draw): * src/xftfont.c (xftfont_draw): Test `alpha_bits' instead of n_planes. * src/xterm.c (x_fill_rectangle, x_clear_rectangle): Likewise. (x_query_colors, x_alloc_nearest_color): Remove code that hard-coded alpha mask. (x_term_init): Calculate alpha bits and offset and populate field appropriately. * src/xterm.h (struct x_display_info): New fields `alpha_bits' and `alpha_offset'. (x_make_truecolor_pixel): Stop hardcoding the value of the alpha mask. --- src/xfns.c | 5 ++- src/xfont.c | 2 +- src/xftfont.c | 2 +- src/xterm.c | 97 ++++++++++++++++++++++++++++++--------------------- src/xterm.h | 11 +++--- 5 files changed, 71 insertions(+), 46 deletions(-) diff --git a/src/xfns.c b/src/xfns.c index 8887b92241c..656e68f0993 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -6401,8 +6401,11 @@ select_visual (struct x_display_info *dpyinfo) /* First attempt to use 32-bit visual if available */ vinfo_template.depth = 32; + vinfo_template.class = TrueColor; - vinfo = XGetVisualInfo (dpy, VisualScreenMask | VisualDepthMask, + vinfo = XGetVisualInfo (dpy, (VisualScreenMask + | VisualDepthMask + | VisualClassMask), &vinfo_template, &n_visuals); if (n_visuals > 0) diff --git a/src/xfont.c b/src/xfont.c index 78f5f19bc84..684c28ab21a 100644 --- a/src/xfont.c +++ b/src/xfont.c @@ -1005,7 +1005,7 @@ xfont_draw (struct glyph_string *s, int from, int to, int x, int y, #if defined HAVE_XRENDER && (RENDER_MAJOR > 0 || (RENDER_MINOR >= 2)) if (with_background - && FRAME_DISPLAY_INFO (s->f)->n_planes == 32 + && FRAME_DISPLAY_INFO (s->f)->alpha_bits && FRAME_CHECK_XR_VERSION (s->f, 0, 2)) { x_xr_ensure_picture (s->f); diff --git a/src/xftfont.c b/src/xftfont.c index cfbf7cdc7ac..6a2b2086df8 100644 --- a/src/xftfont.c +++ b/src/xftfont.c @@ -503,7 +503,7 @@ xftfont_draw (struct glyph_string *s, int from, int to, int x, int y, #if defined HAVE_XRENDER && (RENDER_MAJOR > 0 || (RENDER_MINOR >= 2)) if (with_background - && FRAME_DISPLAY_INFO (s->f)->n_planes == 32 + && FRAME_DISPLAY_INFO (s->f)->alpha_bits && FRAME_CHECK_XR_VERSION (s->f, 0, 2)) { x_xr_ensure_picture (s->f); diff --git a/src/xterm.c b/src/xterm.c index edafd882119..dc4e53759e8 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -1356,7 +1356,7 @@ x_fill_rectangle (struct frame *f, GC gc, int x, int y, int width, int height, #else #if defined HAVE_XRENDER && (RENDER_MAJOR > 0 || (RENDER_MINOR >= 2)) if (respect_alpha_background - && FRAME_DISPLAY_INFO (f)->n_planes == 32 + && FRAME_DISPLAY_INFO (f)->alpha_bits && FRAME_CHECK_XR_VERSION (f, 0, 2)) { x_xr_ensure_picture (f); @@ -1398,7 +1398,7 @@ x_clear_rectangle (struct frame *f, GC gc, int x, int y, int width, int height, #else #if defined HAVE_XRENDER && (RENDER_MAJOR > 0 || (RENDER_MINOR >= 2)) if (respect_alpha_background - && FRAME_DISPLAY_INFO (f)->n_planes == 32 + && FRAME_DISPLAY_INFO (f)->alpha_bits && FRAME_CHECK_XR_VERSION (f, 0, 2)) { x_xr_ensure_picture (f); @@ -2976,12 +2976,6 @@ x_query_colors (struct frame *f, XColor *colors, int ncolors) colors[i].green = (g * gmult) >> 16; colors[i].blue = (b * bmult) >> 16; } - - if (FRAME_DISPLAY_INFO (f)->n_planes == 32) - { - for (i = 0; i < ncolors; ++i) - colors[i].pixel |= ((unsigned long) 0xFF << 24); - } return; } @@ -2999,12 +2993,6 @@ x_query_colors (struct frame *f, XColor *colors, int ncolors) } XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, ncolors); - - if (FRAME_DISPLAY_INFO (f)->n_planes == 32) - { - for (i = 0; i < ncolors; ++i) - colors[i].pixel |= ((unsigned long) 0xFF << 24); - } } /* Store F's background color into *BGCOLOR. */ @@ -3158,7 +3146,9 @@ x_alloc_nearest_color (struct frame *f, Colormap cmap, XColor *color) gamma_correct (f, color); - if (dpyinfo->red_bits > 0) + if (dpyinfo->red_bits > 0 + && (dpyinfo->n_planes != 32 + || dpyinfo->alpha_bits > 0)) { color->pixel = x_make_truecolor_pixel (dpyinfo, color->red, @@ -15539,16 +15529,21 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) reset_mouse_highlight (&dpyinfo->mouse_highlight); - /* See if we can construct pixel values from RGB values. */ - if (dpyinfo->visual->class == TrueColor) +#ifdef HAVE_XRENDER + int event_base, error_base; + dpyinfo->xrender_supported_p + = XRenderQueryExtension (dpyinfo->display, &event_base, &error_base); + + if (dpyinfo->xrender_supported_p) { - get_bits_and_offset (dpyinfo->visual->red_mask, - &dpyinfo->red_bits, &dpyinfo->red_offset); - get_bits_and_offset (dpyinfo->visual->blue_mask, - &dpyinfo->blue_bits, &dpyinfo->blue_offset); - get_bits_and_offset (dpyinfo->visual->green_mask, - &dpyinfo->green_bits, &dpyinfo->green_offset); + if (!XRenderQueryVersion (dpyinfo->display, &dpyinfo->xrender_major, + &dpyinfo->xrender_minor)) + dpyinfo->xrender_supported_p = false; + else + dpyinfo->pict_format = XRenderFindVisualFormat (dpyinfo->display, + dpyinfo->visual); } +#endif /* See if a private colormap is requested. */ if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen)) @@ -15570,6 +15565,46 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window, dpyinfo->visual, AllocNone); + /* See if we can construct pixel values from RGB values. */ + if (dpyinfo->visual->class == TrueColor) + { + get_bits_and_offset (dpyinfo->visual->red_mask, + &dpyinfo->red_bits, &dpyinfo->red_offset); + get_bits_and_offset (dpyinfo->visual->blue_mask, + &dpyinfo->blue_bits, &dpyinfo->blue_offset); + get_bits_and_offset (dpyinfo->visual->green_mask, + &dpyinfo->green_bits, &dpyinfo->green_offset); + +#ifdef HAVE_XRENDER + if (dpyinfo->pict_format) + { + get_bits_and_offset (((unsigned long) dpyinfo->pict_format->direct.alphaMask + << dpyinfo->pict_format->direct.alpha), + &dpyinfo->alpha_bits, &dpyinfo->alpha_offset); + } + else +#endif + { + XColor xc; + unsigned long alpha_mask; + xc.red = 65535; + xc.green = 65535; + xc.blue = 65535; + + if (XAllocColor (dpyinfo->display, + dpyinfo->cmap, &xc) != 0) + { + alpha_mask = xc.pixel & ~(dpyinfo->visual->red_mask + | dpyinfo->visual->blue_mask + | dpyinfo->visual->green_mask); + + if (alpha_mask) + get_bits_and_offset (alpha_mask, &dpyinfo->alpha_bits, + &dpyinfo->alpha_offset); + } + } + } + #ifdef HAVE_XDBE dpyinfo->supports_xdbe = false; int xdbe_major; @@ -15682,22 +15717,6 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) } #endif -#ifdef HAVE_XRENDER - int event_base, error_base; - dpyinfo->xrender_supported_p - = XRenderQueryExtension (dpyinfo->display, &event_base, &error_base); - - if (dpyinfo->xrender_supported_p) - { - if (!XRenderQueryVersion (dpyinfo->display, &dpyinfo->xrender_major, - &dpyinfo->xrender_minor)) - dpyinfo->xrender_supported_p = false; - else - dpyinfo->pict_format = XRenderFindVisualFormat (dpyinfo->display, - dpyinfo->visual); - } -#endif - #ifdef HAVE_XFIXES int xfixes_event_base, xfixes_error_base; dpyinfo->xfixes_supported_p diff --git a/src/xterm.h b/src/xterm.h index 5e17d5b7215..c8c491a7d31 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -460,8 +460,8 @@ struct x_display_info int ncolor_cells; /* Bits and shifts to use to compose pixel values on TrueColor visuals. */ - int red_bits, blue_bits, green_bits; - int red_offset, blue_offset, green_offset; + int red_bits, blue_bits, green_bits, alpha_bits; + int red_offset, blue_offset, green_offset, alpha_offset; /* The type of window manager we have. If we move FRAME_OUTER_WINDOW to x/y 0/0, some window managers (type A) puts the window manager @@ -1285,8 +1285,11 @@ x_make_truecolor_pixel (struct x_display_info *dpyinfo, int r, int g, int b) pg = (g >> (16 - dpyinfo->green_bits)) << dpyinfo->green_offset; pb = (b >> (16 - dpyinfo->blue_bits)) << dpyinfo->blue_offset; - if (dpyinfo->n_planes == 32) - pa = ((unsigned long) 0xFF << 24); + if (dpyinfo->alpha_bits) + pa = (((unsigned long) 0xffff >> (16 - dpyinfo->alpha_bits)) + << dpyinfo->alpha_offset); + else + pa = 0; /* Assemble the pixel color. */ return pr | pg | pb | pa; -- 2.39.5