Archive Page 5
(or, "If I only had a nickel...")
I needed a permanent Linux machine to do some recent bugs; I have a Mac Mini here that's been a champion for the past few months, triple-booting between Linux, OSX, and Windows XP. But, lately, I've been needing to switch between Windows XP and Linux quickly, so I decided to fire up this Dell Dimension 8100 I've had sitting next to me (powered off) for a while. I figure it was old enough (over a year, maybe more?) that there should be no problems. Alas, it wasn't to be. I installed Ubuntu 7.10; I got some display corruption in the installer, but that went away when I rebooted the installer in "safe graphics mode". That really should've been a warning to stay away, but I figured that it was just some quirk of the installer and it'll fix itself.
So. Things install and boot up. The display is in 1680x1050 instead of 1920x1200, but I don't care. This machine has a Radeon X300 SE in it, nowhere near the latest and greatest. I figure, ok, I'll install fglrx; people have been telling me how things are looking up for ATI's driver since AMD took them over. (Which isn't hard -- it's not hard to improve when you've been releasing a terrifyingly awful driver for years.) Enable restricted drivers in ubuntu, fglrx gets installed, I reboot, great! Everything looks good.
But there's a twist. (Ahem.) My monitor is rotated 90 degrees; this is my secondary monitor that sits to the left of my main one. On the Mac Mini (using Intel's drivers), a simple "xrandr -o left" fixed things up nicely. Not so much here. fglrx hasn't heard of XRandR. Okay, let's give up on fuglyrx; clearly there's been loads of hype and very little substance there. I don't care about 3D accel at this point, I just want something that works, so I can get on with my work. I go back to the radeon driver. Woo, xrandr shows multiple supported rotations! Ok, a simple "xrandr -o left" and.... well, the display gets rotated. Half of it gets corrupted. Moving windows around is measured in seconds per frame. This isn't going to work.
Then I proceed to fiddle with Xorg configs, thinking how could this possibly not work, there must at least be a simple way to force a rotation in xorg.conf.. but after about 20 minutes of going through random wiki pages, mailing list archives, etc., I realize I have better things to do.
So, instead, I'm going to go back to either running Linux in a VM, or setting up Xvnc and using that as my X server (which, of course, means I don't get RENDER... hmm, maybe I'll have to use Xephyr and xserver-vnc or something). If anyone wants to know why working with Linux on the desktop is a pain in the ass, here's a good start.
Oh, and sound doesn't work.
Rob Sayre just checked in bug 411365, which adds some global functions to JS for starting and stopping profiling using Shark on OSX. This makes it extremely easy to get a clean profile for a specific testcase, especially if the action is deep in the UI or otherwise hard to isolate. Shark is pretty awesome overall; it's by far the best profiling tool I've used on all three of our main platforms. The oprofile/syspof based tools on Linux can obtain much the same raw information, but Shark's analysis and data mining tools blow oprofile's tools away. On Windows I've only used VTune, which always manages to disappoint me. There's a lot of functionality there, but somehow none of it ever helps me actually solve problems (unless I was microoptimizing a tight loop at the instruction level or something, I guess).
beltzner recently sent me an email asking for some background regarding dropping support for gtk1. I didn't think much of this --- the decision was made before Firefox 2, based on the total utter lack of support for gtk1 from Linux and Unix vendors and the fact that gtk1 had been end-of-lifed for a while by then. All continuing work was happening on gtk2. Now, with Firefox 2, the gtk1 widget backend continued to build, and Sun provided contributed builds for Solaris using both gtk2 and gtk1.
However, very little interesting work happened on the widget and graphics front between Firefox 1.0 and 2 (even between pre-1.0 and 2). There weren't many changes necessary in any of the widget backends; in most cases, none at all. With the graphics system overhaul that's happening as part of Firefox 3, though, that changed. Changes were necessary to fully support Cairo, and we did the work for Windows, Mac OS X, and Gtk2, as those were our main supported platforms. Other widget backends that were living in the tree with no owners for years fell by the wayside -- these included backends for Photon, for Qt, for Xlib, and, yes, for Gtk1. Notably, the OS/2 backend stayed alive through the transition -- the development community there pitched in and did the work necessary to get things rolling, and, as far as I understand it, ended up in a better place as a result with better support for international text among other things.
However, unlike OS/2, noone stepped up to do the work for gtk1. There are certainly some benefits to the gtk1 backend; it was, in fact, a good chunk faster than gtk2 in many cases. I'm sure that speed could be recovered if someone spent a good chunk of time with the gtk2 backend, but so far no owner has stepped up to the plate for that large of a time investment. But, lacking a large group of people working on gtk2 (or, really, even one full time person -- and not for want of trying to find or hire), the decision was made to support just gtk2. After all, gtk2 is where the current toolkit development is happening on the Linux/Unix side, and various Linux and Unix vendors were in agreement with the decision to drop gtk1 support.
All that aside, posts like this one and this one are entirely uncalled for. A call for mail spam directed at beltzner is even more ridiculous, because it wasn't his decision in the first place, nor was it any one person's. I guess all internet rage needs an outlet, and unfortunately beltzner has been the public face of Firefox in a lot of these online discussions; he's got a thick skin, so I'm sure it won't put him off too much from continuing to engage the community and create a meaningful dialogue with users. It is, apparently, just one person leading this misguided charge, but I'm not sure what the end goal is here. Insulting people isn't going to make myself, Stuart, or most other people that I know of write gtk1 code.
All the angst misses one important point: want Gtk 1 support? Great! Write some damn code. There was no edict from on high saying "thou shalt excise gtk 1 support and ne'er shall it return". Code's still in CVS. Make a hg branch. Contribute patches. If there are people who feel this passionately about gtk1 support, surely there's someone out there who's willing to spend a few weekends and get it working.
Does anyone out there have any idea how to force a specific SpeedStep frequency under MacOS X (specifically on a Core Duo and Core 2 Duo Mac Mini)? We can do this under Windows XP using SpeedswitchXP, and under Linux using cpufreq, but I can't find anything similar for OS X. This is important for our performance profiling machines, where SpeedStep introduces huge variance in the results.
We've tried using reggie_se to twiddle the CPU frequency multiplier register. While this does work to slow down the machine, SpeedStep still goes on. I've found lots of references to SpeedIt from InCrew software, but their kernel extension seems tied to a specific Darwin version, and they don't have anything for recent releases of 10.4 (and nothing for 10.5). I've also tried passing "idlehalt=0" to the kernel, but that seemed to have odd results: the CPU frequency seemed to be reported as pegged at the maximum, but perf test results were identical to when idlehalt=0 was not specified and SpeedStep was occuring as normal. In contrast, running our performance benchmark while a "cat /dev/random > /dev/null" is going on gives us perf numbers that are 50% lower than without the /dev/random business.
Anyone out there have any ideas on how we can do this? Forcing the CPU at its highest frequency would be fine; forcing it at the lowest would be better, but at this point we just need to be able to force it to some constant frequency.
Edit: Thanks Matt and others, CoolBook is exactly what we're looking for! Works fine on all Core Duo/Core 2 Duo-based macs.
A while ago, I put together a presentation about the graphics architecture in Mozilla, and what we were working towards with Thebes and Cairo. It was supposed to be a video presentation, but I was never happy with the way the video turned out, so never put it up. After seeing John Resig's post about putting his presentations online, I decided to do the same.
I plan to go over the reasoning behind switching Gecko's rendering engine to Cairo, what purpose Thebes serves, and how it all interacts with the rest of the layout engine. First, let's look at how Gecko used to render pre-1.9.
Each platform had separate implementations for their widget code (which manages windows, input events, repaint events, and so on), and implementations of the old gfx interfaces nsIDeviceContext and nsIRenderingContext. These provided the set of basic rendering capabilities that each platform had in common.
These capabilities were very limited. Besides text, the old gfx implementations could draw non-antialiased lines, rectangles, polygons, and ellipses. They could also draw images (but only undergoing a scale, not a rotation), and could clip content to rectangular regions. Images could also be alpha blended, but at a cost on most platforms.
With Gecko 1.9, things have changed significantly.
Switching to Cairo and Thebes lets us unify a large chunk of code. The widget implementations still remain separate, as this is where code has to work in terms of the platform native concepts of windows, widgets, and events (HWND, GdkWindow, and so on). However, everything below that is shared common code.
Because we didn't want to have to rewrite all code that still used the previous interfaces, there is a shared implementation of nsIDeviceContext and nsIRenderingContext that uses Thebes under the hood. This code lives in mozilla/gfx/src/thebes, and is used on all platforms. There is still some platform-specific code left inside here, most of it having to deal with images and optimizing images for fast rendering. In Mozilla 2, we hope to remove these old interfaces and have everything speak directly to Thebes.
Let's take a look at Thebes itself.
Thebes consists of two parts. One part is a direct C++ wrapper for Cairo that simplifies reference counting (Thebes objects can be used with the standard nsRefPtr<> found in Mozilla) and provides some Mozilla-specific helpers. For example, in many places in our code we want to draw pixel-aligned rectangles. There are convenience functions on gfxContext to perform this task (gfxContext::Rectangle with the snapped paramemter set to TRUE). The core Thebes code lives in mozilla/gfx/thebes.
gfxContext, gfx*Surface (with gfxASurface being the generic abstract implementation), and gfxPattern map directly to cairo_t, cairo_surface_t, and cairo_pattern_t. Additional geometry helper classes such as gfxMatrix, gfxPoint, and gfxRect are also provided.
The core Thebes rendering functionality is directly provided by Cairo and the full feature set of Cairo is available.
Instead of the basic capabilities exposed by the previous gfx implementations, Cairo provides antialiased path fills or clips, along with generic support for transforms, Porter-Duff compositing operators, native support for gradients and more. Most of these capabilities are exposed to the web only through SVG and the HTML Canvas, but some are beginning to appear as proposals and experiments within CSS.
As Cairo itself does not provide a text rendering implementation, a larger and more significant part of Thebes is the text API.
Cairo exposes only a method of drawing glyphs in a platform-specific font at specific locations. (The toy font API that's present in Cairo can be ignored, as it does not support international text and is there only for convenience for smaller projects.) Cairo font objects such as cairo_font_face_t (listed incorrectly as cairo_font_t on the slide) and cairo_scaled_font_t are used internally by the Thebes text classes, but are not otherwise exposed. Thebes works with each platform's native complex text handling APIs (Uniscribe on Windows, Pango on Linux, and ATSU on MacOS X) and presents a unified interface to the rest of Gecko.
The Thebes text API provides high performance cross platform text rendering capabilities, including full support for ligatures, kerning, and complex script shaping. In conjunction with Gecko's text layout capabilities, all of these are supported across DOM element boundaries.
Because not all platforms have the same 2D capabilities in their graphics APIs, Thebes leverages Cairo's fallback mechanism whereby operations that cannot be handled natively are rendered using a pure software backend.
Any of the fundamental Cairo operations (such as fill, stroke, show_glyphs, etc.) are first passed to the platform-specific Cairo surface implementation. The surface then performs the operation, if possible. If the surface indicates that it cannot perform the operation, Cairo's fallback mechanism is invoked which attempts to decompose the operation into a set of simpler steps. For example, paths are tessellated into trapezoids, and a set of trapezoids are given to the surface for rendering. Eventually, the software renderer is invoked, which will read the pixels from the native surface, perform the rendering, then update the contents of the surface.
The various Cairo backends provide different levels of support for native operations.
Due to the dependance on GDI, the Windows platform provides the fewest native operations. However, the ones that it does provide are the most common operations used by Gecko to render web content. On Linux, the RENDER capabilities of the X server are used. On MacOS X, Cairo ends up mapping directly to Quartz, the native 2D API. Thus, all rendering operations result in native Quartz methods being used, and no software fallback within Cairo is ever used on MacOS X. In addition to these platform specific surfaces, Cairo can also generate PDF and PostScript output.
The final component of the low-level rendering bundle is native rendering. In some cases, platform-specific code needs to render directly to one of Gecko's widgets. This is most commonly seen in the native theme drawing code, where the widgets themselves are drawn using the platform's existing theme API.
The approach is to check whether the current Cairo state (destination surface, transformation, compositing operator, etc.) is representable to the native API. If it is, the appropriate setup happens and drawing occurs normally to the underlying platform drawing target. If the state cannot be represented, Gecko creates a temporary surface with no complex transforms, performs the drawing operation here, and then applies transforms and operators as this surface is rendered to the destination. In this way, we can do things such as render rotated and/or scaled widgets on Windows or print widgets with the native theme with Gtk on Linux.
In the future, it will be possible to transform plugins and other content over which we don't have control using this same mechanism. Such transformed content won't be as sharp as it could be, but we could mitigate that by rendering at a higher resolution than we need (assuming we control the rendering, as in the native theme case).
Conclusion
That's it for the first part. In future parts I plan on giving example code that uses Thebes to do rendering to serve as a cookbook for anyone writing rendering code in Gecko. This should be especially useful as legacy code slowly gets converted from nsIRenderingContext to Thebes. I also plan on discussing how painting and invalidation are handled from the OS/widget level down to the thebes level. In addition, a separate presentation on the text API would probably be useful --- there is significant complexity there, especially regarding the interaction of the Thebes font code and the layout TextFrame code.
Any mistakes here are almost certainly mine; please leave me a comment with any corrections, and I'll update the post!
Search BlogAbout |
||||










