Vladimir Vukićević — Words
 

Archive Page 2



Building Fennec for Android under Win32

I’ve been using Windows 7 as my primary development platform for a while (don’t let the MacBook Pro fool you — it’s probably spent less than an hour total in MacOS X), but have always needed to use a virtual machine running Linux to make Android builds.  I don’t mind working in a VM, but it takes up a large chunk of memory, and makes it hard to share code/patches with my main source trees.

However, Google provides the cross-compilers for Windows as well; since the external drive that had my VM on it died a week ago, it seemed like a good opportunity to get the build working under Windows.  Because the native compilers are built using cygwin, this is a bit convoluted, but seems to work.  You’ll need some msys and cygwin tools, as well as the standard Android build prereqs (Java, SDK, NDK):

  • mozilla-build installed
  • the mingw moztools, unpacked somewhere like c:\mozilla-build\moztools-mingw (see bug comment as to why this is required)
  • cygwin installed, including gcc/g++ and the mingw 4.5.1 compilers
  • a JDK (note: I don’t know if OpenJDK supports Windows; if it does, that’s also an option)
  • the Android SDK (with at least the platform level 8 SDK)
  • the Crystax r4 NDK for Win32
  • the patches from bug 607975

You do the build inside the standard mozilla-build shell prompt (not a cygwin shell).  However, you’ll need to copy *.dll from c:/cygwin/bin (assuming you installed cygwin in c:/cygwin) into a new directory, such as c:/cygwin/bindll.  Then add that bindll directory to your msys path.  Adding the cygwin bin directory to your msys path will get you cygwin versions of various tools, and will greatly confuse things.  You just need the DLLs so that the compilers can execute; the compiler binary paths are explicitly specified.

There’s a sample mozconfig inside bug 607975.  You’ll need to use a relative path to run configure, e.g. “MOZCONFIG=../../fennec-config ../mozilla-central/configure”, and you must use mingw make and not pymake to build.  pymake has some weird issues, where it complains that it doesn’t know how to rebuild dependencies like “-lzlib”.  This is likely fixable, because I think this is a magic thing that gnu make special-cases, and something that our build system shouldn’t do in any case.

Some remaining problems with the build:

  • It’s not clear why jemalloc hangs without the TLS patch; mwu says he has seen this in other cases, but it’s consistent here.
  • Opt builds seem to just draw white; not sure why that is, debug builds work fine.  This should be fixable.
  • Disabling automatic dependencies means you have to be extra careful if you modify a header file or something that might not get picked up; they have to be disabled because the cygwin compiler will generate paths like “/cygwin/c/…” in the deps file, which the msys make won’t ever be able to find — thus causing it to rebuild everything on every build.  This is also fixable, perhaps with a postprocessing step after each compilation.
  • Would be nice if pymake worked for building speed.

This is obviously not a full solution, and VMs are still a lot more stable where builds are concerned, but it’s at least possible to build Fennec for Android under Win32.  GDB also seems to work fine, though as always, you’ll want to use the NVIDIA-provided gdb/gdbserver pair, because the one that’s part of the NDK seems to continue to have issues.

Now that we’re doing hardware acceleration on all platforms, we’re touching all sorts of OS components that we haven’t in the past.  One of those is much closer interaction with the graphics card drivers in your system.  Under Windows Vista and Windows 7, problems in the video driver (or in how we use DirectX/OpenGL) sometimes manifest themselves as a graphics driver rest: your screen flashes, and you have a little popup telling you that your video driver had a problem and was reset. If this happens to you while using one of the Firefox 4 betas or nightly builds, here’s how you can collect information to help us and the graphics hardware vendor fix the problem.  This only applies to Windows Vista and Windows 7.

1. Did Firefox recover?

Immediately after the driver reset, did Firefox recover?  If so, skip this step.  If, however, it’s not repainting and otherwise seems hung, forcing a crash report can help give us data that we need to figure out why recovery didn’t happen properly.  To do this, I wrote a tool that forces a hung Firefox to crash in a way that will pop up the crash reporter.  You can download it here: force-firefox-crash.zip.  Just unzip and double click on the .exe, and the current running firefox.exe process will be killed, and you’ll be presented with the crash reporter.

Submit the report, and after restarting Firefox, type in about:crashes in the location bar.  You’ll want the ID of the top entry in this list for when you file a bug or contact support later.  (You can right click the top link and select “Copy Link Location” to grab a link for easy pasting.)

2. Grab the Driver Crash information

Select the start menu, and type in “problem report” in the search box.  Select View all problem reports from the list:

In the problem reports list, scroll down to the Windows section if it’s not visible, and sort by Date — you want the latest “Video hardware error” entry:

Double-click on the latest “Video hardware error” entry.  In the details screen, click “View a temporary copy of these files”:

You’ll get a new explorer window with three files.  Select all three, and compress them into a ZIP file, by right-clicking and selecting “Send To -> Compressed Folder”:

Copy the resulting zip file to your desktop, so that you can include it with your report.

3. Create a bug

Almost done! In bugzilla.mozilla.org, create a new bug in the Core product and the Graphics component.  Attach the zip file you created in step two to the report.  If you also created a Firefox crash dump in step one, include a link to it in your bug report.

This should give us and the graphics hardware vendors enough information to track down what the original problem was, so that we can fix it for Firefox 4!

Fun With Fast JavaScript

Fast JavaScript is a cornerstone of the modern web. In the past, application authors had to wait for browser developers to implement any complex functionality in the browser itself, so that they could access it from script code. Today, many of those functions can move straight into JavaScript itself. This has many advantages for application authors: there’s no need to wait for a new version of a browser before you can develop or ship your app, you can tailor the functionality to exactly what you need, and you can improve it directly (make it faster, higher quality, more precise, etc.).

Here are two examples that show off what can be done with the improved JS engine and capabilities that will be present in Firefox 4. The first example shows a simple web-based Darkroom that allows you to perform color correction on an image. The HTML+JS is around 700 lines of code, not counting jQuery. This is based on a demo that’s included with Google’s Native Client (NaCl) SDK; in that demo, the color correction work is done inside native code going through NaCl. That demo (originally presented as “too slow to run in JavaScript”) is a few thousand lines of code, and involves downloading and installing platform-specific compilers, multiple steps to test/deploy code, and installing a plugin on the browser side.

I get about 15-16 frames per second with the default zoomed out image (around 5 million pixels per second — that number won’t be affected by image size) on my MacBook Pro, which is definitely fast enough for live manipulation. The algorithm could be tightened up to make this faster still. Further optimizations to the JS engine could help here as well; for example, I noticed that we spend a lot of time doing floating point to integer conversions for writing the computed pixels back to the display canvas, due to how the canvas API specifies image data handling.

The Web Darkroom tool also supports drag & drop, so you can take any image from your computer and drop it onto the canvas to load it. A long (long!) time ago, back in 2006, I wrote an addon called “Croppr!”. It was intended to be used with Flickr, allowing users to play around with custom crops of any image, and then leave crop suggestions in comments to be viewed using Croppr. It almost certainly doesn’t work any more, but it would be neat to update it: this time with both cropping and color correction. Someone with the addon (perhaps a Jetpack now!) could then visit a Flickr photo and experiment, and leave suggestions for the photographer.

The second example is based on some work that Dave Humphrey and others have been doing to bring audio manipulation to the web platform. Originally, their spec included a pre-computed FFT with each audio frame delivered to the web app. I suggested that there’s no need for this — while a FFT is useful for some applications, for others it would be wasted work. Those apps that want a FFT could implement one in JS. Some benchmark numbers backed this up — using the typed arrays originally created for WebGL, computing an FFT in JS was approaching the speed of native code. Again, both could be sped up (perhaps using SSE2 or something like Mono.Simd on the JS side), but it’s fast enough to be useful already.

The demo shows this in action. A numeric benchmark isn’t really all that interesting, so instead I take a video clip, and as it’s playing, I extract a portion of the green channel of each frame and compute its 2D FFT, which is then displayed. The original clip plays at 24 frames per second, so that’s the upper bound of this demo. Using Float32 typed arrays, the computation and playback proceeds at around 22-24fps for me.

You can grab the video controls and scrub to a specific frame. (The frame rate calculation is only correct while the video is playing normally, not while you’re scrubbing.) The video source uses Theora, so you’ll need a browser that can play Theora content. (I didn’t have a similar clip that uses WebM, or I could have used that.)

These examples are demonstrating the strength of the trace-based JIT technique that Firefox has used for accelerating JavaScript since Firefox 3.5. However, not all code can see such dramatic speedups from that type of acceleration. Because of that, we’ll be including a full method-based JIT for Firefox 4 (for more details, see David Anderson’s blog, as well as David Mandelin’s blog). This will provide significantly faster baseline JS performance, with the trace JIT becoming a turbocharger for code that it would naturally apply to.

Combining fast JavaScript performance alongside new web platform technologies such as WebGL and Audio will make for some pretty exciting web apps, and I’m looking forward to seeing what developers do with them!

Edit: Made some last-minute changes to the demos, which ended up pulling in a slightly broken version of jQuery UI that wasn’t all that happy with Safari. Should be fixed now!

Edit #2: This post is available in Belorussian, courtesy of Jason Fragoso!

It’s SIGGRAPH time, and this means all sorts of interesting announcements in the graphics world. One of these came today from AMD, who announced that they plan on shipping both EGL and OpenGL ES drivers on Windows for their recent GPUs.

One of the most challenging things in getting Firefox working with WebGL and hardware graphics acceleration has been dealing with platform-specific pieces to get access to OpenGL. In many cases similar functionality works differently (often in subtle ways), requiring both lots of testing and lots of very specific codepaths. EGL replaces all of these with a modern system designed with portability in mind. Until now, however, EGL has only been adopted in the mobile space. On the desktop, the older GLX, CGL, and WGL subsystems have held this role; in the case of GLX and WGL in particular, they bring along years of accumulated cruft.

Having a native EGL driver will allow us to ship one particular hardware acceleration provider that will work and be tested across various desktop and mobile platforms. Additionally, the same provider can connect to the ANGLE project, which implements EGL and OpenGL ES on top of Direct3D 9. Having OpenGL ES will allow us to test and develop truly identical code across desktop and mobile. As mobile graphics development has become important (not just to Mozilla, but in general!), having the same API implemented on the desktop will make it easier to catch problems and portability issues in an environment that’s much more conducive to development and debugging.

Native OpenGL ES on the desktop will also mean that we can tie our WebGL implementation directly to it, instead of going through the desktop OpenGL driver. Because WebGL follows the OpenGL ES specification, the native ES driver on the desktop will allow us to make a more efficient binding between WebGL and the underlying platform, potentially leading to higher performance.

As with any such change, it will be a while before we can depend on the presence of these APIs on the desktop. These first steps are important to making that change happen. I’m looking forward to seeing other vendors following AMD here, both on Windows and on other platforms.

WinDbg Image Viewer Extension

Since I often work on graphics code, one of the things I frequently want to do while debugging is take a chunk of memory and view it as an image.  No standard debugger seems to do this, which is surprising given how useful it is.  I’ve made do with other tools in the past — there’s a great debugging image viewer somewhere for win32 (I can’t find it via google this time around) that lets you attach to a process and manually put in an address, dimensions, etc. to grab the data from the process and view it.  It’s somewhat buggy though, and hasn’t been udpated in a while.  There’s also the image debugger, which is handy, but requires you to link it into your program.

So, I finally wrote the (very simple) debug extension I wish I’d had.  You can find the source for imext here (it’s a hg repo), and a binary DLL built for x86 here.  Rename it to imext.dll and drop it alongside your x86 WinDbg.  Use “!imext.help” to get some basic instructions.  It’s pretty rough code and only does exactly what I needed yesterday, but it can become more useful pretty quickly.  There are some weird bugs with WinDbg’s expression evaluators that make it difficult to use with actual expressions; passing addresses directly works better. Also remember that WinDbg’s default expression evaluator is MASM, not C++ — the main thing is that this means that any bare numbers are interpreted as hex (use 0n123 to get decimal).

I’ll probably extend this quite a bit over time, including teaching it about Mozilla-specific things like gfxImageSurfaces.