GNOME Bugzilla – Bug 314616
Desktop very slow with image background.
Last modified: 2006-02-07 16:22:18 UTC
Version details: garnome 2.11.92 Distribution/Version: Gentoo Set background with an image, as opposed to solid colour. Grabbing an icon and dragging it is severely lagged. Works properly with no background image. Likely cairo-related? The hardware is ATI Radeon M9 with all acceleration working properly.
I should also include that everything else desktop-related is slow, such as opening the context menu: there is a very noticable delay from click to show.
I'm also seeing this. When changing focus from the desktop to another window, the X server is busy for a third of a second. Most of the time this goes away after starting a fullscreen OpenGL game and often comes back some hours later. The X Server is stuck in fbblabla.o in a CopyArea operation. I couldn't figure out what exactly was happening. But when using a broken X server (where you get that funky repeat bug with cairo that screws up your desktop) I'm seeing, that every time this happens the system is busy to redraw the whole desktop. It looks like there's an unnecessary expensive operation going on when drawing the desktop. And he redraws the complete desktop every time it's getting or losing focus (especially noticable and sucking with focus-follows-mousepointer). I'm considering this a gnome 2.12 blocker. If you need more information or help on debugging this, please tell me.
Seeing now that you are correct. The desktop is sluggish as I reported until I started glxgears (note: no need for fullscreen). After that the desktop was as snappy as ever. I agree, this is a blocker. There is a serious redraw bug somewhere.
Hrm. I'm not seeing this at all. Cristophe, what X server are you seeing this on?
My xserver version string is as follows: Gentoo (The X.Org Foundation 6.8.99.15, revision r0-0.1.2) 60899015
I'm using the latest X.org modular release (7.0rc0), but I saw the same with 6.8.99.15 too. Also on Gentoo, but at least the modular release is pretty unmodified. I'm also using the ATI driver, on a Radeon Mobility and Radeon 8500. This might have something to do with the ATI driver, some fallback to non-hardware acceleration. I'm not sure. As I said, sometimes after starting certain programs the problem goes away for some time. But when I'm switching between desktop and programs very quickly, the CPU consumption is still high.
I managed to get a gdb backtrace from nautilus while X was pausing: (gdb) bt
+ Trace 62657
With debug info. It's the XRenderComposite (dpy=0x80fe5b0, op=3, src=..., mask=..., dst=..., src_x=0, src_y=0, mask_x=0, mask_y=0, dst_x=0, dst_y=0, width=1024, height=768); that is taking so much time. The gdb arguments are sometimes bogus, don't know why (I checked using debug output, the arguments are actually ok) (gdb) bt
+ Trace 62658
And the Xserver:
+ Trace 62661
Noticed that it doesn't even have to be a graphical glx app to 'speed up' the desktop, as running glxinfo will temporarily stop the slow performance. Also noticed that this performace slowdown happens after starting nautilus, after changing the background and after changing the gtk-theme. I believe this might be a radeon-driver-xrender-acceleration related issue, as there is no strange slowdown if you run an xserver with no acceleration at all.
The more I am debugging this the more I' coming to the conclusion that this massive slowdown is actually some weird Xorg bug. I mean, why are these simple 1024x768 copy operations in memory so damn slow?! Well, but still. Why does nautilus redraw the whole desktop when it gets or loses the focus? There isn't any actual visible change. Can someone try to figure out what the old GTK+/Nautilus did different and why there was no slowdown?
If by old you mean 2.10.x, then it's simply the lack of cairo.
Maybe you could check whether nautilus_icon_container_set_margins and/or nautilus_file_background_read_desktop_settings is invoked when the excessive redraws take place?
Negative. But I just set a breakpoint at gdk_window_schedule_update and it looks fairly obvious (or is that just my impression?):
+ Trace 62665
static gboolean handle_focus_in_event (GtkWidget *widget, GdkEventFocus *event, gpointer user_data) { update_selected (NAUTILUS_ICON_CONTAINER (widget)); gtk_widget_queue_draw (widget); return FALSE; }
Ok, sorry. This should of course only update the selected icons. Investigating...
Well, something is going wrong in the clipping logic. I just added some debug output to cairo_rectangle, cairo_clip and cairo_fill. And I'm always getting this sequence when focussing/unfocussing the desktop: rectangle: 0:0 1024x768 clip rectangle: 0:0 1024x768 fill It doesn't matter whether icons are selected or not, it's always this sequence. While selecting/deselecting icons the clipping/redrawing operations are normal.
Christophe: When a redraw of the whole widget is queued, the whole area is invalidated, meaning that your whole desktop is redrawn. The diff of the original functionality is available under [1]. The rationale was obviously that different colors may be used for the selected items depending on whether the canvas has focus or not. Why this redraw is additionally requested by Nautilus, although eel_canvas_item_request_redraw in update_selected already invalidates the icon rectangles stays dubious. Dave, do you remember why exactly you added this call? [1] http://cvs.gnome.org/viewcvs/nautilus/libnautilus-private/nautilus-icon-container.c?r1=1.306&r2=1.307
Created attachment 51523 [details] [review] Fix excessive redrawind on desktop (eel canvas) focus change The actual fix seems easy. I just removed the calls to gtk_widget_queue_draw() and it still works. eel_canvas_item_request_update() schedules the correct redrawing procedure using gdk_window_invalidate_rect() itself.
Most Gtk+ widgets typically queue a full redraw on focus in/out. Even GtkWidget itself does this, which is likely why dave added that code when he overrode the parent handle_focus_in_event. This is generally needed because colors can change when focus changes. However, for the nautilus icon container the only things that change on focus is the color of the selection in a rename editor and the icon + text color of the selection. These are redrawn separately, and indeed work with the patch applied, so it should be safe. Even so, the copying of a full-screen pixmap to another pixmap should not take so long time, so someone should try to figure out the X server bug and report that.
this problem is a bug in Radeon acceleration code in X.org 6.9, triggered by Cairo, when it is using XRenderComposite to render background. On older X server, Cairo is using XCopyArea because of a bug in Render in old X servers. This bug can be workaround by running glxinfo (seems to reset Radeon acceleration code) or adding Options NoAccel "true" in xorg.conf. Mandriva bug : http://qa.mandriva.com/show_bug.cgi?id=17723
I've opened a bug on X.org : https://bugs.freedesktop.org/show_bug.cgi?id=4320
I've commited the focus redraw fix. I'm not sure there is much more we can do from the gnome side. We just need to get the Xserver fixed. I'm closing this but as NOTGNOME. Please follow up in the X.org bug.
Created attachment 58604 [details] [review] Patch for gtk+ which works around this This is a bug in Cairo/XRENDER. They get slow if one uses CAIRO_EXTEND_REPEAT for a source pixmap pattern with a pixmap surface as the destination. GTK+ always turns on CAIRO_EXTEND_REPEAT when clearing the double-buffer pixmap for windows which have a pixmap background set on them. With this patch, we detect whether the pixmap background is smaller than the window, and only turn on CAIRO_EXTEND_REPEAT in that case. This makes Nautilus draw the desktop quickly again.
Created attachment 58673 [details] [review] Updated gtk2-117163-cairo-repeat-pattern-workaround.diff This patch fixes the offsetting bug in the previous patch. It is what I've committed to GTK+ HEAD and gtk-2-8. 2006-02-03 Federico Mena Quintero <federico@ximian.com> Work around https://bugs.freedesktop.org/show_bug.cgi?id=4320, which used to be our own http://bugzilla.gnome.org/show_bug.cgi?id=314616. If one uses a pixmap for a pattern in Cairo, and sets the pattern to CAIRO_EXTEND_REPEAT; and if the destination surface is also a pixmap, Cairo does a slow copy instead of using XCopyArea(). So, we use the same code that we used in GTK+ 2.6 (pre-cairo), by filling the double-buffer pixmap with a tiled GC and XFillRectangle(). * gdk/gdkwindow.c (BackingRectMethod): New structure with a cairo_t and a GdkGC field. Depending on which of these fields gets filled in, we'll use Cairo or GDK to clear the double-buffer pixmap when painting a window. (setup_backing_rect_method): Fill a BackingRectMethod as appropriate, depending on the window's configuration and our knowledge of whether Cairo is fast or slow when doing repeating patterns. (gdk_window_clear_backing_rect): Call setup_backing_rect_method(). Depending on what it returns, use Cairo to clear the double-buffer pixmap, or plain GDK.
I applied the patch to the gtk+2.8.11 in Gentoo and it seems to work as advertised. The desktop certainly feels snappier.