aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPo Lu2022-01-24 12:44:55 +0800
committerPo Lu2022-01-24 12:44:55 +0800
commit45208755d13f23f92edcab4d6959e0fd9423843b (patch)
tree95bdca80a788eeedd491e2ae54941ba2af3a7644 /src
parent3a7b158ffd8d468eb92de1de6418b3831f10142b (diff)
downloademacs-45208755d13f23f92edcab4d6959e0fd9423843b.tar.gz
emacs-45208755d13f23f92edcab4d6959e0fd9423843b.zip
Add some code for transparent frame backgrounds without Cairo
* src/image.c (svg_load_image): Fix build without native image transforms. * src/xfns.c (set_up_x_back_buffer): (tear_down_x_back_buffer): Free XR picture if present. * src/xftfont.c (xftfont_get_xft_draw): Fix formatting issue. * src/xterm.c (x_xr_ensure_picture): New function. (FRAME_CR_CONTEXT, FRAME_CR_CONTEXT): (FRAME_CR_SURFACE_DESIRED_WIDTH) (FRAME_CR_SURFACE_DESIRED_HEIGHT): Move to separate USE_CAIRO block so the ext data code can be used on builds with XRender as well. (x_xr_apply_ext_clip): (x_xr_reset_ext_clip): New functions. (x_set_clip_rectangles): (x_reset_clip_rectangles): Set ext data on XRender as well. (x_term_init): Look for a picture format appropriate for our purposes. (x_clear_area): Use XRenderFillRectangle to draw backgrounds if available. (x_xrender_color_from_gc_foreground): (x_xrender_color_from_gc_background): New functions. * src/xterm.h (FRAME_X_PICTURE): (FRAME_X_PICTURE_FORMAT) (FRAME_CHECK_XR_VERSION): New macros. (struct x_gc_ext_data): Define on XRender as well. (struct x_display_info): Define ext_codes when using XRender and add new field `pict_format'. (struct x_output): New field `picture'.
Diffstat (limited to 'src')
-rw-r--r--src/image.c5
-rw-r--r--src/xfns.c30
-rw-r--r--src/xftfont.c8
-rw-r--r--src/xterm.c132
-rw-r--r--src/xterm.h38
5 files changed, 188 insertions, 25 deletions
diff --git a/src/image.c b/src/image.c
index 7ee595297fa..951531505e6 100644
--- a/src/image.c
+++ b/src/image.c
@@ -10672,11 +10672,16 @@ svg_load_image (struct frame *f, struct image *img, char *contents,
10672 viewbox_height = dimension_data.height; 10672 viewbox_height = dimension_data.height;
10673#endif 10673#endif
10674 10674
10675#ifdef HAVE_NATIVE_TRANSFORMS
10675 compute_image_size (viewbox_width, viewbox_height, img, 10676 compute_image_size (viewbox_width, viewbox_height, img,
10676 &width, &height); 10677 &width, &height);
10677 10678
10678 width = scale_image_size (width, 1, FRAME_SCALE_FACTOR (f)); 10679 width = scale_image_size (width, 1, FRAME_SCALE_FACTOR (f));
10679 height = scale_image_size (height, 1, FRAME_SCALE_FACTOR (f)); 10680 height = scale_image_size (height, 1, FRAME_SCALE_FACTOR (f));
10681#else
10682 width = viewbox_width;
10683 height = viewbox_height;
10684#endif
10680 10685
10681 if (! check_image_size (f, width, height)) 10686 if (! check_image_size (f, width, height))
10682 { 10687 {
diff --git a/src/xfns.c b/src/xfns.c
index 7123198724a..92aed2d46a7 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -3267,6 +3267,17 @@ x_mark_frame_dirty (struct frame *f)
3267static void 3267static void
3268set_up_x_back_buffer (struct frame *f) 3268set_up_x_back_buffer (struct frame *f)
3269{ 3269{
3270#ifdef HAVE_XRENDER
3271 block_input ();
3272 if (FRAME_X_PICTURE (f) != None)
3273 {
3274 XRenderFreePicture (FRAME_X_DISPLAY (f),
3275 FRAME_X_PICTURE (f));
3276 FRAME_X_PICTURE (f) = None;
3277 }
3278 unblock_input ();
3279#endif
3280
3270#ifdef HAVE_XDBE 3281#ifdef HAVE_XDBE
3271 block_input (); 3282 block_input ();
3272 if (FRAME_X_WINDOW (f) && !FRAME_X_DOUBLE_BUFFERED_P (f)) 3283 if (FRAME_X_WINDOW (f) && !FRAME_X_DOUBLE_BUFFERED_P (f))
@@ -3281,10 +3292,10 @@ set_up_x_back_buffer (struct frame *f)
3281 server ran out of memory or we don't have the right kind 3292 server ran out of memory or we don't have the right kind
3282 of visual, just use single-buffered rendering. */ 3293 of visual, just use single-buffered rendering. */
3283 x_catch_errors (FRAME_X_DISPLAY (f)); 3294 x_catch_errors (FRAME_X_DISPLAY (f));
3284 FRAME_X_RAW_DRAWABLE (f) = XdbeAllocateBackBufferName ( 3295 FRAME_X_RAW_DRAWABLE (f)
3285 FRAME_X_DISPLAY (f), 3296 = XdbeAllocateBackBufferName (FRAME_X_DISPLAY (f),
3286 FRAME_X_WINDOW (f), 3297 FRAME_X_WINDOW (f),
3287 XdbeCopied); 3298 XdbeCopied);
3288 if (x_had_errors_p (FRAME_X_DISPLAY (f))) 3299 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
3289 FRAME_X_RAW_DRAWABLE (f) = FRAME_X_WINDOW (f); 3300 FRAME_X_RAW_DRAWABLE (f) = FRAME_X_WINDOW (f);
3290 x_uncatch_errors_after_check (); 3301 x_uncatch_errors_after_check ();
@@ -3297,6 +3308,17 @@ set_up_x_back_buffer (struct frame *f)
3297void 3308void
3298tear_down_x_back_buffer (struct frame *f) 3309tear_down_x_back_buffer (struct frame *f)
3299{ 3310{
3311#ifdef HAVE_XRENDER
3312 block_input ();
3313 if (FRAME_X_PICTURE (f) != None)
3314 {
3315 XRenderFreePicture (FRAME_X_DISPLAY (f),
3316 FRAME_X_PICTURE (f));
3317 FRAME_X_PICTURE (f) = None;
3318 }
3319 unblock_input ();
3320#endif
3321
3300#ifdef HAVE_XDBE 3322#ifdef HAVE_XDBE
3301 block_input (); 3323 block_input ();
3302 if (FRAME_X_WINDOW (f) && FRAME_X_DOUBLE_BUFFERED_P (f)) 3324 if (FRAME_X_WINDOW (f) && FRAME_X_DOUBLE_BUFFERED_P (f))
diff --git a/src/xftfont.c b/src/xftfont.c
index f305738410e..c2175d96141 100644
--- a/src/xftfont.c
+++ b/src/xftfont.c
@@ -441,10 +441,10 @@ xftfont_get_xft_draw (struct frame *f)
441 if (! xft_draw) 441 if (! xft_draw)
442 { 442 {
443 block_input (); 443 block_input ();
444 xft_draw= XftDrawCreate (FRAME_X_DISPLAY (f), 444 xft_draw = XftDrawCreate (FRAME_X_DISPLAY (f),
445 FRAME_X_DRAWABLE (f), 445 FRAME_X_DRAWABLE (f),
446 FRAME_X_VISUAL (f), 446 FRAME_X_VISUAL (f),
447 FRAME_X_COLORMAP (f)); 447 FRAME_X_COLORMAP (f));
448 unblock_input (); 448 unblock_input ();
449 eassert (xft_draw != NULL); 449 eassert (xft_draw != NULL);
450 font_put_frame_data (f, Qxft, xft_draw); 450 font_put_frame_data (f, Qxft, xft_draw);
diff --git a/src/xterm.c b/src/xterm.c
index cc0e1a4485d..436238c4a17 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -358,6 +358,22 @@ x_flush (struct frame *f)
358 unblock_input (); 358 unblock_input ();
359} 359}
360 360
361#ifdef HAVE_XRENDER
362MAYBE_UNUSED static void
363x_xr_ensure_picture (struct frame *f)
364{
365 if (FRAME_X_PICTURE (f) == None && FRAME_X_PICTURE_FORMAT (f))
366 {
367 XRenderPictureAttributes attrs;
368 attrs.clip_mask = None;
369
370 FRAME_X_PICTURE (f) = XRenderCreatePicture (FRAME_X_DISPLAY (f),
371 FRAME_X_RAW_DRAWABLE (f),
372 FRAME_X_PICTURE_FORMAT (f),
373 CPClipMask, &attrs);
374 }
375}
376#endif
361 377
362/* Remove calls to XFlush by defining XFlush to an empty replacement. 378/* Remove calls to XFlush by defining XFlush to an empty replacement.
363 Calls to XFlush should be unnecessary because the X output buffer 379 Calls to XFlush should be unnecessary because the X output buffer
@@ -401,14 +417,7 @@ record_event (char *locus, int type)
401 417
402#endif 418#endif
403 419
404#ifdef USE_CAIRO 420#if defined USE_CAIRO || defined HAVE_XRENDER
405
406#define FRAME_CR_CONTEXT(f) ((f)->output_data.x->cr_context)
407#define FRAME_CR_SURFACE_DESIRED_WIDTH(f) \
408 ((f)->output_data.x->cr_surface_desired_width)
409#define FRAME_CR_SURFACE_DESIRED_HEIGHT(f) \
410 ((f)->output_data.x->cr_surface_desired_height)
411
412static struct x_gc_ext_data * 421static struct x_gc_ext_data *
413x_gc_get_ext_data (struct frame *f, GC gc, int create_if_not_found_p) 422x_gc_get_ext_data (struct frame *f, GC gc, int create_if_not_found_p)
414{ 423{
@@ -441,6 +450,15 @@ x_extension_initialize (struct x_display_info *dpyinfo)
441 450
442 dpyinfo->ext_codes = ext_codes; 451 dpyinfo->ext_codes = ext_codes;
443} 452}
453#endif
454
455#ifdef USE_CAIRO
456
457#define FRAME_CR_CONTEXT(f) ((f)->output_data.x->cr_context)
458#define FRAME_CR_SURFACE_DESIRED_WIDTH(f) \
459 ((f)->output_data.x->cr_surface_desired_width)
460#define FRAME_CR_SURFACE_DESIRED_HEIGHT(f) \
461 ((f)->output_data.x->cr_surface_desired_height)
444 462
445#endif /* HAVE_CAIRO */ 463#endif /* HAVE_CAIRO */
446 464
@@ -1184,11 +1202,37 @@ x_cr_export_frames (Lisp_Object frames, cairo_surface_type_t surface_type)
1184 1202
1185#endif /* USE_CAIRO */ 1203#endif /* USE_CAIRO */
1186 1204
1205#if defined HAVE_XRENDER && !defined USE_CAIRO
1206MAYBE_UNUSED static void
1207x_xr_apply_ext_clip (struct frame *f, GC gc)
1208{
1209 eassert (FRAME_X_PICTURE (f) != None);
1210
1211 struct x_gc_ext_data *data = x_gc_get_ext_data (f, gc, 1);
1212
1213 if (data->n_clip_rects)
1214 XRenderSetPictureClipRectangles (FRAME_X_DISPLAY (f),
1215 FRAME_X_PICTURE (f),
1216 0, 0, data->clip_rects,
1217 data->n_clip_rects);
1218}
1219
1220MAYBE_UNUSED static void
1221x_xr_reset_ext_clip (struct frame *f)
1222{
1223 XRenderPictureAttributes attrs = { .clip_mask = None };
1224
1225 XRenderChangePicture (FRAME_X_DISPLAY (f),
1226 FRAME_X_PICTURE (f),
1227 CPClipMask, &attrs);
1228}
1229#endif
1230
1187static void 1231static void
1188x_set_clip_rectangles (struct frame *f, GC gc, XRectangle *rectangles, int n) 1232x_set_clip_rectangles (struct frame *f, GC gc, XRectangle *rectangles, int n)
1189{ 1233{
1190 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, rectangles, n, Unsorted); 1234 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, rectangles, n, Unsorted);
1191#ifdef USE_CAIRO 1235#if defined USE_CAIRO || defined HAVE_XRENDER
1192 eassert (n >= 0 && n <= MAX_CLIP_RECTS); 1236 eassert (n >= 0 && n <= MAX_CLIP_RECTS);
1193 1237
1194 { 1238 {
@@ -1204,7 +1248,7 @@ static void
1204x_reset_clip_rectangles (struct frame *f, GC gc) 1248x_reset_clip_rectangles (struct frame *f, GC gc)
1205{ 1249{
1206 XSetClipMask (FRAME_X_DISPLAY (f), gc, None); 1250 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
1207#ifdef USE_CAIRO 1251#if defined USE_CAIRO || defined HAVE_XRENDER
1208 { 1252 {
1209 struct x_gc_ext_data *gc_ext = x_gc_get_ext_data (f, gc, 0); 1253 struct x_gc_ext_data *gc_ext = x_gc_get_ext_data (f, gc, 0);
1210 1254
@@ -4510,10 +4554,31 @@ x_clear_area (struct frame *f, int x, int y, int width, int height)
4510#ifndef USE_GTK 4554#ifndef USE_GTK
4511 if (FRAME_X_DOUBLE_BUFFERED_P (f)) 4555 if (FRAME_X_DOUBLE_BUFFERED_P (f))
4512#endif 4556#endif
4513 XFillRectangle (FRAME_X_DISPLAY (f), 4557 {
4514 FRAME_X_DRAWABLE (f), 4558#if defined HAVE_XRENDER && \
4515 f->output_data.x->reverse_gc, 4559 (RENDER_MAJOR > 0 || (RENDER_MINOR >= 2))
4516 x, y, width, height); 4560 x_xr_ensure_picture (f);
4561 if (FRAME_X_PICTURE (f) != None
4562 && FRAME_CHECK_XR_VERSION (f, 0, 2))
4563 {
4564 XRenderColor xc;
4565 GC gc = f->output_data.x->reverse_gc;
4566
4567 x_xr_apply_ext_clip (f, gc);
4568 x_xrender_color_from_gc_foreground (f, gc, &xc);
4569 XRenderFillRectangle (FRAME_X_DISPLAY (f),
4570 PictOpSrc, FRAME_X_PICTURE (f),
4571 &xc, x, y, width, height);
4572 x_xr_reset_ext_clip (f);
4573 x_mark_frame_dirty (f);
4574 }
4575 else
4576#endif
4577 XFillRectangle (FRAME_X_DISPLAY (f),
4578 FRAME_X_DRAWABLE (f),
4579 f->output_data.x->reverse_gc,
4580 x, y, width, height);
4581 }
4517#ifndef USE_GTK 4582#ifndef USE_GTK
4518 else 4583 else
4519 x_clear_area1 (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 4584 x_clear_area1 (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
@@ -15431,6 +15496,9 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
15431 if (!XRenderQueryVersion (dpyinfo->display, &dpyinfo->xrender_major, 15496 if (!XRenderQueryVersion (dpyinfo->display, &dpyinfo->xrender_major,
15432 &dpyinfo->xrender_minor)) 15497 &dpyinfo->xrender_minor))
15433 dpyinfo->xrender_supported_p = false; 15498 dpyinfo->xrender_supported_p = false;
15499 else
15500 dpyinfo->pict_format = XRenderFindVisualFormat (dpyinfo->display,
15501 dpyinfo->visual);
15434 } 15502 }
15435#endif 15503#endif
15436 15504
@@ -15714,7 +15782,7 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
15714 x_session_initialize (dpyinfo); 15782 x_session_initialize (dpyinfo);
15715#endif 15783#endif
15716 15784
15717#ifdef USE_CAIRO 15785#if defined USE_CAIRO || defined HAVE_XRENDER
15718 x_extension_initialize (dpyinfo); 15786 x_extension_initialize (dpyinfo);
15719#endif 15787#endif
15720 15788
@@ -16090,6 +16158,40 @@ init_xterm (void)
16090} 16158}
16091#endif 16159#endif
16092 16160
16161#ifdef HAVE_XRENDER
16162void
16163x_xrender_color_from_gc_foreground (struct frame *f, GC gc, XRenderColor *color)
16164{
16165 XGCValues xgcv;
16166 XColor xc;
16167
16168 XGetGCValues (FRAME_X_DISPLAY (f), gc, GCForeground, &xgcv);
16169 xc.pixel = xgcv.foreground;
16170 x_query_colors (f, &xc, 1);
16171
16172 color->alpha = 65535;
16173 color->red = xc.red;
16174 color->blue = xc.blue;
16175 color->green = xc.green;
16176}
16177
16178void
16179x_xrender_color_from_gc_background (struct frame *f, GC gc, XRenderColor *color)
16180{
16181 XGCValues xgcv;
16182 XColor xc;
16183
16184 XGetGCValues (FRAME_X_DISPLAY (f), gc, GCBackground, &xgcv);
16185 xc.pixel = xgcv.foreground;
16186 x_query_colors (f, &xc, 1);
16187
16188 color->alpha = 65535;
16189 color->red = xc.red;
16190 color->blue = xc.blue;
16191 color->green = xc.green;
16192}
16193#endif
16194
16093void 16195void
16094syms_of_xterm (void) 16196syms_of_xterm (void)
16095{ 16197{
diff --git a/src/xterm.h b/src/xterm.h
index a4ad57eddaa..33887be52b0 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -54,6 +54,10 @@ typedef Widget xt_or_gtk_widget;
54#define GTK_CHECK_VERSION(i, j, k) false 54#define GTK_CHECK_VERSION(i, j, k) false
55#endif 55#endif
56 56
57#ifdef HAVE_XRENDER
58#include <X11/extensions/Xrender.h>
59#endif
60
57#ifdef USE_GTK 61#ifdef USE_GTK
58/* Some definitions to reduce conditionals. */ 62/* Some definitions to reduce conditionals. */
59typedef GtkWidget *xt_or_gtk_widget; 63typedef GtkWidget *xt_or_gtk_widget;
@@ -148,7 +152,7 @@ struct x_bitmap_record
148 int height, width, depth; 152 int height, width, depth;
149}; 153};
150 154
151#ifdef USE_CAIRO 155#if defined USE_CAIRO || defined HAVE_XRENDER
152struct x_gc_ext_data 156struct x_gc_ext_data
153{ 157{
154#define MAX_CLIP_RECTS 2 158#define MAX_CLIP_RECTS 2
@@ -158,7 +162,9 @@ struct x_gc_ext_data
158 /* Clipping rectangles. */ 162 /* Clipping rectangles. */
159 XRectangle clip_rects[MAX_CLIP_RECTS]; 163 XRectangle clip_rects[MAX_CLIP_RECTS];
160}; 164};
165#endif
161 166
167#ifdef USE_CAIRO
162extern cairo_pattern_t *x_bitmap_stipple (struct frame *, Pixmap); 168extern cairo_pattern_t *x_bitmap_stipple (struct frame *, Pixmap);
163#endif 169#endif
164 170
@@ -239,6 +245,11 @@ struct x_display_info
239 /* The Visual being used for this display. */ 245 /* The Visual being used for this display. */
240 Visual *visual; 246 Visual *visual;
241 247
248#ifdef HAVE_XRENDER
249 /* The picture format for this display. */
250 XRenderPictFormat *pict_format;
251#endif
252
242 /* The colormap being used. */ 253 /* The colormap being used. */
243 Colormap cmap; 254 Colormap cmap;
244 255
@@ -509,7 +520,7 @@ struct x_display_info
509 int xrandr_minor_version; 520 int xrandr_minor_version;
510#endif 521#endif
511 522
512#ifdef USE_CAIRO 523#if defined USE_CAIRO || defined HAVE_XRENDER
513 XExtCodes *ext_codes; 524 XExtCodes *ext_codes;
514#endif 525#endif
515 526
@@ -616,6 +627,13 @@ struct x_output
616 window's back buffer. */ 627 window's back buffer. */
617 Drawable draw_desc; 628 Drawable draw_desc;
618 629
630#ifdef HAVE_XRENDER
631 /* The Xrender picture that corresponds to this drawable. None
632 means no picture format was found, or the Xrender extension is
633 not present. */
634 Picture picture;
635#endif
636
619 /* Flag that indicates whether we've modified the back buffer and 637 /* Flag that indicates whether we've modified the back buffer and
620 need to publish our modifications to the front buffer at a 638 need to publish our modifications to the front buffer at a
621 convenient time. */ 639 convenient time. */
@@ -933,6 +951,17 @@ extern void x_mark_frame_dirty (struct frame *f);
933/* This is the Visual which frame F is on. */ 951/* This is the Visual which frame F is on. */
934#define FRAME_X_VISUAL(f) FRAME_DISPLAY_INFO (f)->visual 952#define FRAME_X_VISUAL(f) FRAME_DISPLAY_INFO (f)->visual
935 953
954#ifdef HAVE_XRENDER
955#define FRAME_X_PICTURE_FORMAT(f) FRAME_DISPLAY_INFO (f)->pict_format
956#define FRAME_X_PICTURE(f) ((f)->output_data.x->picture)
957#define FRAME_CHECK_XR_VERSION(f, major, minor) \
958 (FRAME_DISPLAY_INFO (f)->xrender_supported_p \
959 && ((FRAME_DISPLAY_INFO (f)->xrender_major == (major) \
960 && FRAME_DISPLAY_INFO (f)->xrender_minor >= (minor)) \
961 || (FRAME_DISPLAY_INFO (f)->xrender_major > (major))))
962#endif
963
964
936/* This is the Colormap which frame F uses. */ 965/* This is the Colormap which frame F uses. */
937#define FRAME_X_COLORMAP(f) FRAME_DISPLAY_INFO (f)->cmap 966#define FRAME_X_COLORMAP(f) FRAME_DISPLAY_INFO (f)->cmap
938 967
@@ -1212,6 +1241,11 @@ extern void x_cr_draw_frame (cairo_t *, struct frame *);
1212extern Lisp_Object x_cr_export_frames (Lisp_Object, cairo_surface_type_t); 1241extern Lisp_Object x_cr_export_frames (Lisp_Object, cairo_surface_type_t);
1213#endif 1242#endif
1214 1243
1244#ifdef HAVE_XRENDER
1245extern void x_xrender_color_from_gc_foreground (struct frame *, GC, XRenderColor *);
1246extern void x_xrender_color_from_gc_background (struct frame *, GC, XRenderColor *);
1247#endif
1248
1215INLINE int 1249INLINE int
1216x_display_pixel_height (struct x_display_info *dpyinfo) 1250x_display_pixel_height (struct x_display_info *dpyinfo)
1217{ 1251{