summaryrefslogtreecommitdiff
path: root/src/xterm.c
diff options
context:
space:
mode:
authorYAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>2019-05-19 08:35:40 +0900
committerYAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>2019-05-19 08:35:40 +0900
commitb87e5eea1dd7c7345d0a9f82759eedfd7c9a8099 (patch)
tree1da68babb2bf8cbf738766506c23283bf6ec486b /src/xterm.c
parent5f9671e57ee99cfe4653b2cb6aca16d52f9a5c53 (diff)
downloademacs-b87e5eea1dd7c7345d0a9f82759eedfd7c9a8099.tar.gz
Avoid triple buffering with Xdbe in cairo
* src/xterm.h (struct x_output): Remove member cr_surface. Add members cr_surface_desired_width and cr_surface_desired_height. (x_cr_destroy_frame_context) [USE_CAIRO]: Add extern. * src/xterm.c (x_free_cr_resources): Remove function. (FRAME_CR_SURFACE) [USE_CAIRO]: Remove macro. (FRAME_CR_SURFACE_DESIRED_WIDTH, FRAME_CR_SURFACE_DESIRED_HEIGHT) [USE_CAIRO]: New macros. (x_cr_destroy_frame_context) [USE_CAIRO]: Rename from x_cr_destroy_surface. All Uses changed. Don't use FRAME_CR_SURFACE. Make non-static. (x_cr_update_surface_desired_size) [USE_CAIRO]: New function. (x_begin_cr_clip) [USE_CAIRO]: Create Xlib surface if Xdbe is in use. Use FRAME_CR_SURFACE_DESIRED_WIDTH and FRAME_CR_SURFACE_DESIRED_HEIGHT. (x_end_cr_clip) [USE_CAIRO]: Call x_mark_frame_dirty if Xdbe is in use. (x_cr_draw_frame, x_cr_export_frames) [USE_CAIRO]: Save and restore cairo context instead of freeing and clearing it. (x_update_begin) [USE_CAIRO]: Don't create cairo surface here. (show_back_buffer) [USE_CAIRO]: Call cairo_surface_flush before swapping. (x_update_end) [USE_CAIRO]: Don't copy image surface if Xdbe is in use. Get image surface by cairo_get_target instead of FRAME_CR_SURFACE. (x_scroll_run) [USE_CAIRO]: Use XCopyArea if Xdbe is in use. (handle_one_xevent) [USE_CAIRO] <ConfigureNotify>: Call x_cr_update_surface_desired_size instead of x_cr_destroy_surface. (x_free_frame_resources) [USE_CAIRO]: Call x_cr_destroy_frame_context instead of x_free_cr_resources. * src/xfns.c (set_up_x_back_buffer, tear_down_x_back_buffer) [USE_CAIRO]: Call x_cr_destroy_frame_context.
Diffstat (limited to 'src/xterm.c')
-rw-r--r--src/xterm.c211
1 files changed, 93 insertions, 118 deletions
diff --git a/src/xterm.c b/src/xterm.c
index 9371d47c95e..4f4a1d6d02a 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -201,7 +201,6 @@ enum xembed_message
XEMBED_ACTIVATE_ACCELERATOR = 14
};
-static void x_free_cr_resources (struct frame *);
static bool x_alloc_nearest_color_1 (Display *, Colormap, XColor *);
static void x_raise_frame (struct frame *);
static void x_lower_frame (struct frame *);
@@ -298,7 +297,10 @@ record_event (char *locus, int type)
#ifdef USE_CAIRO
#define FRAME_CR_CONTEXT(f) ((f)->output_data.x->cr_context)
-#define FRAME_CR_SURFACE(f) ((f)->output_data.x->cr_surface)
+#define FRAME_CR_SURFACE_DESIRED_WIDTH(f) \
+ ((f)->output_data.x->cr_surface_desired_width)
+#define FRAME_CR_SURFACE_DESIRED_HEIGHT(f) \
+ ((f)->output_data.x->cr_surface_desired_height)
static struct x_gc_ext_data *
x_gc_get_ext_data (struct frame *f, GC gc, int create_if_not_found_p)
@@ -333,19 +335,28 @@ x_extension_initialize (struct x_display_info *dpyinfo)
dpyinfo->ext_codes = ext_codes;
}
-static void
-x_cr_destroy_surface (struct frame *f)
+void
+x_cr_destroy_frame_context (struct frame *f)
{
- if (FRAME_CR_SURFACE (f))
+ if (FRAME_CR_CONTEXT (f))
{
- cairo_t *cr = FRAME_CR_CONTEXT (f);
- cairo_surface_destroy (FRAME_CR_SURFACE (f));
- FRAME_CR_SURFACE (f) = 0;
- if (cr) cairo_destroy (cr);
+ cairo_destroy (FRAME_CR_CONTEXT (f));
FRAME_CR_CONTEXT (f) = NULL;
}
}
+static void
+x_cr_update_surface_desired_size (struct frame *f, int width, int height)
+{
+ if (FRAME_CR_SURFACE_DESIRED_WIDTH (f) != width
+ || FRAME_CR_SURFACE_DESIRED_HEIGHT (f) != height)
+ {
+ x_cr_destroy_frame_context (f);
+ FRAME_CR_SURFACE_DESIRED_WIDTH (f) = width;
+ FRAME_CR_SURFACE_DESIRED_HEIGHT (f) = height;
+ }
+}
+
cairo_t *
x_begin_cr_clip (struct frame *f, GC gc)
{
@@ -353,21 +364,19 @@ x_begin_cr_clip (struct frame *f, GC gc)
if (!cr)
{
-
- if (! FRAME_CR_SURFACE (f))
- {
- int scale = 1;
-#ifdef USE_GTK
- scale = xg_get_scale (f);
-#endif
-
- FRAME_CR_SURFACE (f) =
- cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
- scale * FRAME_PIXEL_WIDTH (f),
- scale * FRAME_PIXEL_HEIGHT (f));
- }
- cr = cairo_create (FRAME_CR_SURFACE (f));
- FRAME_CR_CONTEXT (f) = cr;
+ int width = FRAME_CR_SURFACE_DESIRED_WIDTH (f);
+ int height = FRAME_CR_SURFACE_DESIRED_HEIGHT (f);
+ cairo_surface_t *surface;
+ if (FRAME_X_DOUBLE_BUFFERED_P (f))
+ surface = cairo_xlib_surface_create (FRAME_X_DISPLAY (f),
+ FRAME_X_RAW_DRAWABLE (f),
+ FRAME_X_VISUAL (f),
+ width, height);
+ else
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+ width, height);
+ cr = FRAME_CR_CONTEXT (f) = cairo_create (surface);
+ cairo_surface_destroy (surface);
}
cairo_save (cr);
@@ -395,6 +404,8 @@ void
x_end_cr_clip (struct frame *f)
{
cairo_restore (FRAME_CR_CONTEXT (f));
+ if (FRAME_X_DOUBLE_BUFFERED_P (f))
+ x_mark_frame_dirty (f);
}
void
@@ -532,11 +543,11 @@ x_cr_draw_frame (cairo_t *cr, struct frame *f)
width = FRAME_PIXEL_WIDTH (f);
height = FRAME_PIXEL_HEIGHT (f);
- x_free_cr_resources (f);
+ cairo_t *saved_cr = FRAME_CR_CONTEXT (f);
FRAME_CR_CONTEXT (f) = cr;
x_clear_area (f, 0, 0, width, height);
expose_frame (f, 0, 0, width, height);
- FRAME_CR_CONTEXT (f) = NULL;
+ FRAME_CR_CONTEXT (f) = saved_cr;
}
static cairo_status_t
@@ -615,11 +626,11 @@ x_cr_export_frames (Lisp_Object frames, cairo_surface_type_t surface_type)
while (1)
{
- x_free_cr_resources (f);
+ cairo_t *saved_cr = FRAME_CR_CONTEXT (f);
FRAME_CR_CONTEXT (f) = cr;
x_clear_area (f, 0, 0, width, height);
expose_frame (f, 0, 0, width, height);
- FRAME_CR_CONTEXT (f) = NULL;
+ FRAME_CR_CONTEXT (f) = saved_cr;
if (NILP (frames))
break;
@@ -654,35 +665,6 @@ x_cr_export_frames (Lisp_Object frames, cairo_surface_type_t surface_type)
#endif /* USE_CAIRO */
static void
-x_free_cr_resources (struct frame *f)
-{
-#ifdef USE_CAIRO
- if (f == NULL)
- {
- Lisp_Object rest, frame;
- FOR_EACH_FRAME (rest, frame)
- if (FRAME_X_P (XFRAME (frame)))
- x_free_cr_resources (XFRAME (frame));
- }
- else
- {
- cairo_t *cr = FRAME_CR_CONTEXT (f);
-
- if (cr)
- {
- cairo_surface_t *surface = cairo_get_target (cr);
-
- if (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_XLIB)
- {
- cairo_destroy (cr);
- FRAME_CR_CONTEXT (f) = NULL;
- }
- }
- }
-#endif
-}
-
-static void
x_set_clip_rectangles (struct frame *f, GC gc, XRectangle *rectangles, int n)
{
XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, rectangles, n, Unsorted);
@@ -996,41 +978,7 @@ x_set_frame_alpha (struct frame *f)
static void
x_update_begin (struct frame *f)
{
-#ifdef USE_CAIRO
- if (FRAME_TOOLTIP_P (f) && !FRAME_VISIBLE_P (f))
- return;
-
- if (! FRAME_CR_SURFACE (f))
- {
- int width, height;
-#ifdef USE_GTK
- if (FRAME_GTK_WIDGET (f))
- {
- GdkWindow *w = gtk_widget_get_window (FRAME_GTK_WIDGET (f));
- int scale = xg_get_scale (f);
- width = scale * gdk_window_get_width (w);
- height = scale * gdk_window_get_height (w);
- }
- else
-#endif
- {
- width = FRAME_PIXEL_WIDTH (f);
- height = FRAME_PIXEL_HEIGHT (f);
- if (! FRAME_EXTERNAL_TOOL_BAR (f))
- height += FRAME_TOOL_BAR_HEIGHT (f);
- if (! FRAME_EXTERNAL_MENU_BAR (f))
- height += FRAME_MENU_BAR_HEIGHT (f);
- }
-
- if (width > 0 && height > 0)
- {
- block_input();
- FRAME_CR_SURFACE (f) = cairo_image_surface_create
- (CAIRO_FORMAT_ARGB32, width, height);
- unblock_input();
- }
- }
-#endif /* USE_CAIRO */
+ /* Nothing to do. */
}
/* Draw a vertical window border from (x,y0) to (x,y1) */
@@ -1122,6 +1070,11 @@ show_back_buffer (struct frame *f)
if (FRAME_X_DOUBLE_BUFFERED_P (f))
{
#ifdef HAVE_XDBE
+#ifdef USE_CAIRO
+ cairo_t *cr = FRAME_CR_CONTEXT (f);
+ if (cr)
+ cairo_surface_flush (cairo_get_target (cr));
+#endif
XdbeSwapInfo swap_info;
memset (&swap_info, 0, sizeof (swap_info));
swap_info.swap_window = FRAME_X_WINDOW (f);
@@ -1158,30 +1111,33 @@ x_update_end (struct frame *f)
MOUSE_HL_INFO (f)->mouse_face_defer = false;
#ifdef USE_CAIRO
- if (FRAME_CR_SURFACE (f))
+ if (!FRAME_X_DOUBLE_BUFFERED_P (f))
{
- cairo_t *cr;
- cairo_surface_t *surface;
- int width, height;
-
block_input ();
- width = FRAME_PIXEL_WIDTH (f);
- height = FRAME_PIXEL_HEIGHT (f);
- if (! FRAME_EXTERNAL_TOOL_BAR (f))
- height += FRAME_TOOL_BAR_HEIGHT (f);
- if (! FRAME_EXTERNAL_MENU_BAR (f))
- height += FRAME_MENU_BAR_HEIGHT (f);
- surface = cairo_xlib_surface_create (FRAME_X_DISPLAY (f),
- FRAME_X_DRAWABLE (f),
- FRAME_DISPLAY_INFO (f)->visual,
- width,
- height);
- cr = cairo_create (surface);
- cairo_surface_destroy (surface);
-
- cairo_set_source_surface (cr, FRAME_CR_SURFACE (f), 0, 0);
- cairo_paint (cr);
- cairo_destroy (cr);
+ cairo_surface_t *source_surface = cairo_get_target (FRAME_CR_CONTEXT (f));
+ if (source_surface)
+ {
+ cairo_t *cr;
+ cairo_surface_t *surface;
+ int width, height;
+
+ width = FRAME_PIXEL_WIDTH (f);
+ height = FRAME_PIXEL_HEIGHT (f);
+ if (! FRAME_EXTERNAL_TOOL_BAR (f))
+ height += FRAME_TOOL_BAR_HEIGHT (f);
+ if (! FRAME_EXTERNAL_MENU_BAR (f))
+ height += FRAME_MENU_BAR_HEIGHT (f);
+ surface = cairo_xlib_surface_create (FRAME_X_DISPLAY (f),
+ FRAME_X_DRAWABLE (f),
+ FRAME_X_VISUAL (f),
+ width, height);
+ cr = cairo_create (surface);
+ cairo_surface_destroy (surface);
+
+ cairo_set_source_surface (cr, source_surface, 0, 0);
+ cairo_paint (cr);
+ cairo_destroy (cr);
+ }
unblock_input ();
}
#endif
@@ -4253,7 +4209,21 @@ x_scroll_run (struct window *w, struct run *run)
gui_clear_cursor (w);
#ifdef USE_CAIRO
- if (FRAME_CR_CONTEXT (f))
+ if (FRAME_X_DOUBLE_BUFFERED_P (f))
+ {
+ cairo_t *cr = FRAME_CR_CONTEXT (f);
+ if (cr)
+ cairo_surface_flush (cairo_get_target (cr));
+ XCopyArea (FRAME_X_DISPLAY (f),
+ FRAME_X_DRAWABLE (f), FRAME_X_DRAWABLE (f),
+ f->output_data.x->normal_gc,
+ x, from_y,
+ width, height,
+ x, to_y);
+ if (cr)
+ cairo_surface_mark_dirty (cairo_get_target (cr));
+ }
+ else if (FRAME_CR_CONTEXT (f))
{
cairo_surface_t *s = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
width, height);
@@ -8711,7 +8681,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
font_drop_xrender_surfaces (f);
unblock_input ();
#ifdef USE_CAIRO
- if (f) x_cr_destroy_surface (f);
+ if (f)
+ x_cr_update_surface_desired_size (f, configureEvent.xconfigure.width,
+ configureEvent.xconfigure.height);
#endif
#ifdef USE_GTK
if (!f
@@ -8725,7 +8697,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
xg_frame_resized (f, configureEvent.xconfigure.width,
configureEvent.xconfigure.height);
#ifdef USE_CAIRO
- x_cr_destroy_surface (f);
+ x_cr_update_surface_desired_size (f, configureEvent.xconfigure.width,
+ configureEvent.xconfigure.height);
#endif
f = 0;
}
@@ -11835,7 +11808,9 @@ x_free_frame_resources (struct frame *f)
free_frame_xic (f);
#endif
- x_free_cr_resources (f);
+#ifdef USE_CAIRO
+ x_cr_destroy_frame_context (f);
+#endif
#ifdef USE_X_TOOLKIT
if (f->output_data.x->widget)
{