framerate issue
I observe a significant performance difference between totem and gtk-play (from gst-examples), using the same gstreamer pipeline on the same file, an H264 video 1280x720, hardware decoded at 50fps with vaapi, using the same gtkglsink. The performance issue is better observed using the "Power Saver" power profile, and using a screen with enough refresh rate to not limit the fps per itself.
Both totem and gtk-play use a GtkOverlay to display the video controls over the video widget.
When the overlay is visible, an expensive code path is executed at frame rate:
(gdb) bt
#0 glx_pixmap_get (surface=0xcd4980, texture_target=3553) at ../gdk/x11/gdkglcontext-x11.c:314
#1 0x00007ffff6a9e067 in gdk_x11_gl_context_texture_from_surface (paint_context=0x10f18b0, surface=0xcd4980, region=0x14ced70) at ../gdk/x11/gdkglcontext-x11
.c:464
#2 0x00007ffff6a2a328 in gdk_gl_texture_from_surface (surface=0xcd4980, region=0x14ced70) at ../gdk/gdkgl.c:745
#3 0x00007ffff6a3ce07 in gdk_window_end_paint_internal (window=0xa2d070) at ../gdk/gdkwindow.c:3066
#4 0x00007ffff6a3d4ca in gdk_window_end_draw_frame (window=0xa2d070, context=0x97ad50) at ../gdk/gdkwindow.c:3312
#5 0x00007ffff78aa2b2 in gtk_widget_render (widget=0x7664a0, window=0xa2d070, region=0x6dacd0) at ../gtk/gtkwidget.c:17613
#6 0x00007ffff76acbbe in gtk_main_do_event (event=0x7fffffffca30) at ../gtk/gtkmain.c:1844
#7 0x00007ffff6a24c3e in _gdk_event_emit (event=0x7fffffffca30) at ../gdk/gdkevents.c:73
#8 0x00007ffff6a3e418 in _gdk_window_process_updates_recurse_helper (window=0xa2d070, expose_region=0x981600) at ../gdk/gdkwindow.c:3875
#9 0x00007ffff6a3e639 in _gdk_window_process_updates_recurse (window=0xa2d070, expose_region=0x981600) at ../gdk/gdkwindow.c:3932
#10 0x00007ffff6a4c3ff in gdk_window_impl_process_updates_recurse (window=0xa2d070, region=0x981600) at ../gdk/gdkwindowimpl.c:333
#11 0x00007ffff6a3e8d7 in gdk_window_process_updates_internal (window=0xa2d070) at ../gdk/gdkwindow.c:4021
#12 0x00007ffff6a3eda1 in gdk_window_process_updates_with_mode (window=0xa2d070, recurse_mode=2) at ../gdk/gdkwindow.c:4216
#13 0x00007ffff6a4adfa in gdk_window_paint_on_clock (clock=0xa01140, data=0xa2d070) at ../gdk/gdkwindow.c:11722
#14 0x00007ffff7ee75c9 in g_cclosure_marshal_VOID__VOIDv (closure=0xa2d2b0, return_value=0x0, instance=0xa01140, args=0x7fffffffcfb8, marshal_data=0x0, n_para
ms=0, param_types=0x0) at ../gobject/gmarshal.c:165
#15 0x00007ffff7ee402f in _g_closure_invoke_va (closure=0xa2d2b0, return_value=0x0, instance=0xa01140, args=0x7fffffffcfb8, n_params=0, param_types=0x0) at ..
/gobject/gclosure.c:895
#16 0x00007ffff7f03495 in g_signal_emit_valist (instance=0xa01140, signal_id=85, detail=0, var_args=0x7fffffffcfb8) at ../gobject/gsignal.c:3456
#17 0x00007ffff7f04691 in g_signal_emit (instance=0xa01140, signal_id=85, detail=0) at ../gobject/gsignal.c:3606
#18 0x00007ffff6a30bfd in _gdk_frame_clock_emit_paint (frame_clock=0xa01140) at ../gdk/gdkframeclock.c:657
#19 0x00007ffff6a31d39 in gdk_frame_clock_paint_idle (data=0xa01140) at ../gdk/gdkframeclockidle.c:597
#20 0x00007ffff6a15531 in gdk_threads_dispatch (data=0x7fff7c0093d0) at ../gdk/gdk.c:769
This code path is expensive, also because in some cases, gtk makes a huge number of calls to XGetVisualInfo
(gtk#4704).
But in gtk-play, this code path is executed only when the controls overlay is visible, which leads to good framerate most of the time, when the overlay is hidden (export LIBGL_SHOW_FPS=1
).
As I'm trying to obtain a close framerate with totem, I'm surprised to see that this code path is always followed, even when the controls are hidden. After some investigation, I found that the reason in totem that prevents it, is the modification of the application titlebar with gtk_window_set_titlebar
, which is quite surprising. It looks to me like a gtk bug.
This workaround (using the fullscreen header even in windowed mode) gives me back the same performance than with gtk-play:
--- a/src/totem-object.c
+++ b/src/totem-object.c
@@ -1859,9 +1859,8 @@ set_controls_visibility (TotemObject *totem,
gboolean visible,
gboolean animate)
{
- gtk_widget_set_visible (GTK_WIDGET (gtk_builder_get_object (totem->xml, "toolbar")), visible);
- gtk_widget_set_visible (totem->fullscreen_header, visible &&
- totem->controls_visibility == TOTEM_CONTROLS_FULLSCREEN);
+ gtk_widget_set_visible (GTK_WIDGET (gtk_builder_get_object (totem->xml, "bvw_grid")), visible);
+ gtk_widget_set_visible (totem->fullscreen_header, visible);
bacon_video_widget_set_show_cursor (totem->bvw, visible);
if (visible && animate)
schedule_hiding_popup (totem);
@@ -3865,7 +3864,6 @@ totem_setup_window (TotemObject *totem)
NULL);
g_signal_connect (G_OBJECT (totem->header), "back-clicked",
G_CALLBACK (back_button_clicked_cb), totem);
- gtk_window_set_titlebar (GTK_WINDOW (totem->win), totem->header);
return;
}
My setup is a fully uptodate Fedora 37 (totem 43.0 and gtk 3.24.36), running Xorg, on an Intel Kabylake (Gen9) integrated GPU.