[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Emacs-diffs] master b87e5ee: Avoid triple buffering with Xdbe in cairo
From: |
YAMAMOTO Mitsuharu |
Subject: |
[Emacs-diffs] master b87e5ee: Avoid triple buffering with Xdbe in cairo |
Date: |
Sat, 18 May 2019 19:36:09 -0400 (EDT) |
branch: master
commit b87e5eea1dd7c7345d0a9f82759eedfd7c9a8099
Author: YAMAMOTO Mitsuharu <address@hidden>
Commit: YAMAMOTO Mitsuharu <address@hidden>
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.
---
src/xfns.c | 6 ++
src/xterm.c | 211 +++++++++++++++++++++++++++---------------------------------
src/xterm.h | 6 +-
3 files changed, 103 insertions(+), 120 deletions(-)
diff --git a/src/xfns.c b/src/xfns.c
index 2ceb55a..c8cc170 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -2784,6 +2784,9 @@ set_up_x_back_buffer (struct frame *f)
block_input ();
if (FRAME_X_WINDOW (f) && !FRAME_X_DOUBLE_BUFFERED_P (f))
{
+#ifdef USE_CAIRO
+ x_cr_destroy_frame_context (f);
+#endif
FRAME_X_RAW_DRAWABLE (f) = FRAME_X_WINDOW (f);
if (FRAME_DISPLAY_INFO (f)->supports_xdbe)
{
@@ -2813,6 +2816,9 @@ tear_down_x_back_buffer (struct frame *f)
{
if (FRAME_X_DOUBLE_BUFFERED_P (f))
{
+#ifdef USE_CAIRO
+ x_cr_destroy_frame_context (f);
+#endif
XdbeDeallocateBackBufferName (FRAME_X_DISPLAY (f),
FRAME_X_DRAWABLE (f));
FRAME_X_RAW_DRAWABLE (f) = FRAME_X_WINDOW (f);
diff --git a/src/xterm.c b/src/xterm.c
index 9371d47..4f4a1d6 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)
{
diff --git a/src/xterm.h b/src/xterm.h
index 266a42a..84030d5 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -725,8 +725,9 @@ struct x_output
#ifdef USE_CAIRO
/* Cairo drawing context. */
cairo_t *cr_context;
- /* Cairo surface for double buffering */
- cairo_surface_t *cr_surface;
+ /* Width and height reported by the last ConfigureNotify event.
+ They are used when creating the cairo surface next time. */
+ int cr_surface_desired_width, cr_surface_desired_height;
#endif
};
@@ -1107,6 +1108,7 @@ extern int x_dispatch_event (XEvent *, Display *);
#endif
extern int x_x_to_emacs_modifiers (struct x_display_info *, int);
#ifdef USE_CAIRO
+extern void x_cr_destroy_frame_context (struct frame *);
extern cairo_t *x_begin_cr_clip (struct frame *, GC);
extern void x_end_cr_clip (struct frame *);
extern void x_set_cr_source_with_gc_foreground (struct frame *, GC);
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Emacs-diffs] master b87e5ee: Avoid triple buffering with Xdbe in cairo,
YAMAMOTO Mitsuharu <=