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.
This commit is contained in:
parent
5f9671e57e
commit
b87e5eea1d
3 changed files with 102 additions and 119 deletions
|
@ -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);
|
||||
|
|
209
src/xterm.c
209
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;
|
||||
|
@ -653,35 +664,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)
|
||||
{
|
||||
|
@ -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_surface_t *source_surface = cairo_get_target (FRAME_CR_CONTEXT (f));
|
||||
if (source_surface)
|
||||
{
|
||||
cairo_t *cr;
|
||||
cairo_surface_t *surface;
|
||||
int width, height;
|
||||
|
||||
cairo_set_source_surface (cr, FRAME_CR_SURFACE (f), 0, 0);
|
||||
cairo_paint (cr);
|
||||
cairo_destroy (cr);
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue