Optimizing legacy code

Earlier this week, I finally traced down an interesting “bug” in GTK+’s Mac backend. People were complaining that scrolling in certain applications worked very slowly. Which got me puzzled for a good while, since all tests I use showed no obvious performance problems. Profiling a test that did expose this slowness showed that a lot of time was spent on color conversion. Also, it turned out this problem only occurred when drawing to a GdkPixmap first and later copying this GdkPixmap to a window.

So why was this color conversion going on? We were creating a CGImage backing the GdkPixmap using the colorspace returned by CGColorSpaceCreateDeviceRGB(). Judging from the function name, this seems alright. But closely, very closely, reading the documentation revealed the gory details. After switching this to use a different, now generic, color space (as suggested by the documentation), all performance issues were solved. Basically, color conversion from the “device” color space to the “generic” color space was happening, which is now no longer needed.

But not so fast! This change seemed to work fine, after all it is just a color space change, but for the particular test case I was debugging it introduced very awkward drawing issues. This took a long while to track down and it turned out to be another problem with how we implemented GdkPixmaps. Also this has been fixed.

(For details see bug 615917 and especially 624025).

People may wonder why I am spending my copious spare time on debugging GdkPixmaps while all of this is removed in GTK+ 3. The reasons are twofold, firstly debugging problems like this greatly extend my understanding of the Mac platform. This will also help when I am profiling GTK+ 3 code in the future, perhaps the same problems are encountered.

Secondly, I want to leave GTK+ 2.x in a mostly stable shape before fully turning my attention to GTK+ 3. I am planning to fix two more rendering issues in 2.x: one rendering glitch with scrolling windows that are inside an offscreen window and another with drawing depth 1 pixmaps. After that, GTK+ 2.x should be in a pretty good shape rendering-wise.

That might be a good point to switch focus to GTK+ 3.x. Of course, we can always backmerge changes to GTK+ 2.x if useful, for example fixes and improvements to the GtkSelection/DnD code.

To end with a brief note on Mac OS Tiger compatibility. We have always attempted to keep GTK+ working on both (Snow) Leopard and Tiger. I think we will continue with that for the time being, since I still have access to a machine running Tiger. However, in case Cairo goes Leopard-only and drops support for Tiger and earlier, GTK+ will have to follow suit.

Unfortunately, I couldn’t make it to the GTK+ hackfest this year. There seems to be good stuff going on, particularly interested in the GTK+ 4 plans but haven’t seen much elaboration on those yet.

More GTK+ rendering cleanup and Mac

Since my last blog post two or more rendering-cleanup branches followed, which all got merged into master. So some more debugging was needed to get everything to work again on Mac. An interesting observation is that with each subsequent rendering cleanup, it became easier to get things going again on Mac. Very likely a good sign that we are on the right track to make GDK more X11-agnostic and easier to port.

Either way, as far as I can see GTK+ master runs pretty well on OS X now (including offscreen windows). The last rendering thing that really needed fixing was GtkTreeView (surprising or not?), which was actually sometimes resizing its GdkWindow while in the expose handler. This has mostly worked for a decade, but fell apart on OS X recently, since Cairo Quartz does not support resizing surfaces, so instead we destroy and re-create. The tree view is now patched in such a way that all resizing is done before we get to the draw method, so this resizing is no longer needed from inside the draw handler. I added a bunch of old scrolling test cases to the main tree view scrolling unit test, and all tests pass, so we should be safe. If your application depends heavily on tree view scrolling and you experience issues with GTK+ master, report this ASAP and we can get it fixed. Stand-alone test cases are appreciated as always :)

With the rendering working fine again on Mac, I hope to focus on other improvements now.

Finally: the work that has been done on the resize grip for GtkWindows is actually great news for GTK+ on Mac. Mac applications typically don’t have a window manager frame and thus rely on a resize grip. We had to leave the default Mac resize grip enabled, even though the GTK+ application didn’t expect such a grip there, obviously leading to sometimes awkward situations. So far I didn’t turn off the Mac resize grip (they seem to work fine together), since for GtkWindows without resize grip we still need some kind of fallback.