Backout bug 537857
authorTaras Glek <tglek@mozilla.com>
Mon, 24 May 2010 15:21:24 -0700
changeset 42636 714faf8ec1493fb9d7a3c15bdd513e367f8aff63
parent 42635 d05aa79f947adb5eecc46cb1b6b414a2148513a1 (current diff)
parent 42634 56c19c5c416eec7c8368a8114f5dc2d000d271ad (diff)
child 42637 0c440c656ada5d6e87f694a93663584aea656ae0
push id13434
push usertglek@mozilla.com
push dateMon, 24 May 2010 22:22:07 +0000
treeherdermozilla-central@714faf8ec149 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs537857
milestone1.9.3a5pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
Backout bug 537857
configure.in
js/src/xpconnect/tools/Makefile.in
js/src/xpconnect/tools/idl/Makefile.in
js/src/xpconnect/tools/idl/nsIXPCToolsCompiler.idl
js/src/xpconnect/tools/idl/nsIXPCToolsProfiler.idl
js/src/xpconnect/tools/js/CompileJSFiles.js
js/src/xpconnect/tools/js/ListJSFiles.js
js/src/xpconnect/tools/src/Makefile.in
js/src/xpconnect/tools/src/nsXPCToolsCompiler.cpp
js/src/xpconnect/tools/src/nsXPCToolsModule.cpp
js/src/xpconnect/tools/src/nsXPCToolsProfiler.cpp
js/src/xpconnect/tools/src/xpctools_private.h
widget/src/qt/keysym2ucs.c
widget/src/qt/keysym2ucs.h
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -176,17 +176,17 @@ pref("general.autoScroll", true);
 
 // Whether or not the application should check at startup each time if it 
 // is the default browser.
 pref("browser.shell.checkDefaultBrowser", true);
 
 // 0 = blank, 1 = home (browser.startup.homepage), 2 = last visited page, 3 = resume previous browser session
 // The behavior of option 3 is detailed at: http://wiki.mozilla.org/Session_Restore
 pref("browser.startup.page",                1);
-pref("browser.startup.homepage",            "resource:/browserconfig.properties");
+pref("browser.startup.homepage",            "chrome://branding/locale/browserconfig.properties");
 
 pref("browser.enable_automatic_image_resizing", true);
 pref("browser.chrome.site_icons", true);
 pref("browser.chrome.favicons", true);
 pref("browser.warnOnQuit", true);
 pref("browser.warnOnRestart", true);
 pref("browser.fullscreen.autohide", true);
 pref("browser.fullscreen.animateUp", 1);
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -4259,17 +4259,17 @@ var XULBrowserWindow = {
   },
 
   // simulate all change notifications after switching tabs
   onUpdateCurrentBrowser: function (aStateFlags, aStatus, aMessage, aTotalProgress) {
     if (FullZoom.updateBackgroundTabs)
       FullZoom.onLocationChange(gBrowser.currentURI, true);
     var nsIWebProgressListener = Components.interfaces.nsIWebProgressListener;
     var loadingDone = aStateFlags & nsIWebProgressListener.STATE_STOP;
-    // use a pseudo-object instead of a (potentially non-existing) channel for getting
+    // use a pseudo-object instead of a (potentially nonexistent) channel for getting
     // a correct error message - and make sure that the UI is always either in
     // loading (STATE_START) or done (STATE_STOP) mode
     this.onStateChange(
       gBrowser.webProgress,
       { URI: gBrowser.currentURI },
       loadingDone ? nsIWebProgressListener.STATE_STOP : nsIWebProgressListener.STATE_START,
       aStatus
     );
@@ -4770,17 +4770,17 @@ var gHomeButton = {
       url = gPrefService.getComplexValue(this.prefDomain,
                                 Components.interfaces.nsIPrefLocalizedString).data;
     } catch (e) {
     }
 
     // use this if we can't find the pref
     if (!url) {
       var SBS = Cc["@mozilla.org/intl/stringbundle;1"].getService(Ci.nsIStringBundleService);
-      var configBundle = SBS.createBundle("resource:/browserconfig.properties");
+      var configBundle = SBS.createBundle("chrome://branding/locale/browserconfig.properties");
       url = configBundle.GetStringFromName(this.prefDomain);
     }
 
     return url;
   },
 
   updatePersonalToolbarStyle: function (homeButton)
   {
--- a/browser/base/content/pageinfo/pageInfo.js
+++ b/browser/base/content/pageinfo/pageInfo.js
@@ -163,23 +163,29 @@ const COL_IMAGE_BG      = 6;
 const COPYCOL_NONE = -1;
 const COPYCOL_META_CONTENT = 1;
 const COPYCOL_IMAGE = COL_IMAGE_ADDRESS;
 
 // one nsITreeView for each tree in the window
 var gMetaView = new pageInfoTreeView(COPYCOL_META_CONTENT);
 var gImageView = new pageInfoTreeView(COPYCOL_IMAGE);
 
+
+var atomSvc = Components.classes["@mozilla.org/atom-service;1"]
+                        .getService(Components.interfaces.nsIAtomService);
+gImageView._ltrAtom = atomSvc.getAtom("ltr");
+gImageView._brokenAtom = atomSvc.getAtom("broken");
+
 gImageView.getCellProperties = function(row, col, props) {
-  var aserv = Components.classes[ATOM_CONTRACTID]
-                        .getService(Components.interfaces.nsIAtomService);
-
   if (gImageView.data[row][COL_IMAGE_SIZE] == gStrings.unknown &&
       !/^https:/.test(gImageView.data[row][COL_IMAGE_ADDRESS]))
-    props.AppendElement(aserv.getAtom("broken"));
+    props.AppendElement(this._brokenAtom);
+
+  if (col.element.id == "image-address")
+    props.AppendElement(this._ltrAtom);
 };
 
 var gImageHash = { };
 
 // localized strings (will be filled in when the document is loaded)
 // this isn't all of them, these are just the ones that would otherwise have been loaded inside a loop
 var gStrings = { };
 var gBundle;
--- a/browser/branding/nightly/locales/Makefile.in
+++ b/browser/branding/nightly/locales/Makefile.in
@@ -40,16 +40,8 @@ srcdir         = @srcdir@
 VPATH          = @srcdir@
 relativesrcdir = browser/branding/nightly/locales
 
 include $(DEPTH)/config/autoconf.mk
 
 DEFINES += -DAB_CD=$(AB_CD) -DMOZ_DISTRIBUTION_ID_UNQUOTED=$(MOZ_DISTRIBUTION_ID)
 
 include $(topsrcdir)/config/rules.mk
-
-libs::
-	@$(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) \
-	  $(srcdir)/browserconfig.properties > $(FINAL_TARGET)/browserconfig.properties
-
-install::
-	@$(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) \
-	  $(srcdir)/browserconfig.properties > $(DESTDIR)$(mozappdir)/browserconfig.properties
--- a/browser/branding/nightly/locales/jar.mn
+++ b/browser/branding/nightly/locales/jar.mn
@@ -1,7 +1,8 @@
 #filter substitution
 
 @AB_CD@.jar:
 % locale branding @AB_CD@ %locale/branding/
 # Nightly branding only exists in en-US
   locale/branding/brand.dtd        (en-US/brand.dtd)
 * locale/branding/brand.properties (en-US/brand.properties)
+* locale/branding/browserconfig.properties (browserconfig.properties)
--- a/browser/branding/unofficial/locales/Makefile.in
+++ b/browser/branding/unofficial/locales/Makefile.in
@@ -40,16 +40,8 @@ srcdir         = @srcdir@
 VPATH          = @srcdir@
 relativesrcdir = browser/branding/unofficial/locales
 
 include $(DEPTH)/config/autoconf.mk
 
 DEFINES += -DAB_CD=$(AB_CD) -DMOZ_DISTRIBUTION_ID_UNQUOTED=$(MOZ_DISTRIBUTION_ID)
 
 include $(topsrcdir)/config/rules.mk
-
-libs::
-	@$(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) \
-	  $(srcdir)/browserconfig.properties > $(FINAL_TARGET)/browserconfig.properties
-
-install::
-	@$(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) \
-	  $(srcdir)/browserconfig.properties > $(DESTDIR)$(mozappdir)/browserconfig.properties
--- a/browser/branding/unofficial/locales/jar.mn
+++ b/browser/branding/unofficial/locales/jar.mn
@@ -1,7 +1,8 @@
 #filter substitution
 
 @AB_CD@.jar:
 % locale branding @AB_CD@ %locale/branding/
 # Unofficial branding only exists in en-US
   locale/branding/brand.dtd        (en-US/brand.dtd)
 * locale/branding/brand.properties (en-US/brand.properties)
+* locale/branding/browserconfig.properties (browserconfig.properties)
--- a/browser/components/places/tests/unit/test_bookmarksRestoreNotification.js
+++ b/browser/components/places/tests/unit/test_bookmarksRestoreNotification.js
@@ -104,17 +104,17 @@ var tests = [
       }
       catch (e) {
         do_throw("  Restore should not have failed");
       }
     }
   },
 
   {
-    desc:       "JSON restore: nonexisting file should fail",
+    desc:       "JSON restore: nonexistent file should fail",
     currTopic:  NSIOBSERVER_TOPIC_BEGIN,
     finalTopic: NSIOBSERVER_TOPIC_FAILED,
     data:       NSIOBSERVER_DATA_JSON,
     folderId:   null,
     run:        function () {
       this.file = Services.dirsvc.get("ProfD", Ci.nsILocalFile);
       this.file.append("this file doesn't exist because nobody created it");
       try {
@@ -158,17 +158,17 @@ var tests = [
       }
       catch (e) {
         do_throw("  Restore should not have failed");
       }
     }
   },
 
   {
-    desc:       "HTML restore: nonexisting file should fail",
+    desc:       "HTML restore: nonexistent file should fail",
     currTopic:  NSIOBSERVER_TOPIC_BEGIN,
     finalTopic: NSIOBSERVER_TOPIC_FAILED,
     data:       NSIOBSERVER_DATA_HTML,
     folderId:   null,
     run:        function () {
       this.file = Services.dirsvc.get("ProfD", Ci.nsILocalFile);
       this.file.append("this file doesn't exist because nobody created it");
       try {
@@ -212,17 +212,17 @@ var tests = [
       }
       catch (e) {
         do_throw("  Restore should not have failed");
       }
     }
   },
 
   {
-    desc:       "HTML initial restore: nonexisting file should fail",
+    desc:       "HTML initial restore: nonexistent file should fail",
     currTopic:  NSIOBSERVER_TOPIC_BEGIN,
     finalTopic: NSIOBSERVER_TOPIC_FAILED,
     data:       NSIOBSERVER_DATA_HTML_INIT,
     folderId:   null,
     run:        function () {
       this.file = Services.dirsvc.get("ProfD", Ci.nsILocalFile);
       this.file.append("this file doesn't exist because nobody created it");
       try {
@@ -274,17 +274,17 @@ var tests = [
       }
       catch (e) {
         do_throw("  Restore should not have failed");
       }
     }
   },
 
   {
-    desc:       "HTML restore into folder: nonexisting file should fail",
+    desc:       "HTML restore into folder: nonexistent file should fail",
     currTopic:  NSIOBSERVER_TOPIC_BEGIN,
     finalTopic: NSIOBSERVER_TOPIC_FAILED,
     data:       NSIOBSERVER_DATA_HTML,
     run:        function () {
       this.file = Services.dirsvc.get("ProfD", Ci.nsILocalFile);
       this.file.append("this file doesn't exist because nobody created it");
       this.folderId = bmsvc.createFolder(bmsvc.unfiledBookmarksFolder,
                                          "test folder",
--- a/browser/fuel/test/browser_ApplicationPrefs.js
+++ b/browser/fuel/test/browser_ApplicationPrefs.js
@@ -3,21 +3,21 @@ var testdata = {
   missing: "fuel.fuel-test-missing",
   dummy: "fuel.fuel-test",
   string: "browser.active_color",
   integer: "permissions.default.image",
   boolean: "browser.blink_allowed"
 };
 
 function test() {
-  // test getting non-existing values
+  // test getting nonexistent values
   var itemValue = Application.prefs.getValue(testdata.missing, "default");
-  is(itemValue, "default", "Check 'Application.prefs.getValue' for non-existing item");
+  is(itemValue, "default", "Check 'Application.prefs.getValue' for nonexistent item");
 
-  is(Application.prefs.get(testdata.missing), null, "Check 'Application.prefs.get' for non-existing item");
+  is(Application.prefs.get(testdata.missing), null, "Check 'Application.prefs.get' for nonexistent item");
 
   // test setting and getting a value
   Application.prefs.setValue(testdata.dummy, "dummy");
   itemValue = Application.prefs.getValue(testdata.dummy, "default");
   is(itemValue, "dummy", "Check 'Application.prefs.getValue' for existing item");
 
   // test for overwriting an existing value
   Application.prefs.setValue(testdata.dummy, "smarty");
--- a/browser/fuel/test/browser_ApplicationStorage.js
+++ b/browser/fuel/test/browser_ApplicationStorage.js
@@ -1,19 +1,19 @@
 function test() {
   // test for existence of values
   var hasItem = Application.storage.has("fuel-test-missing");
-  is(hasItem, false, "Check 'Application.storage.has' for non-existing item");
+  is(hasItem, false, "Check 'Application.storage.has' for nonexistent item");
   Application.storage.set("fuel-test", "dummy");
   hasItem = Application.storage.has("fuel-test");
   is(hasItem, true, "Check 'Application.storage.has' for existing item");
 
-  // test getting non-existing and existing values
+  // test getting nonexistent and existing values
   var itemValue = Application.storage.get("fuel-test-missing", "default");
-  is(itemValue, "default", "Check 'Application.storage.get' for non-existing item");
+  is(itemValue, "default", "Check 'Application.storage.get' for nonexistent item");
   itemValue = Application.storage.get("fuel-test", "default");
   is(itemValue, "dummy", "Check 'Application.storage.get' for existing item");
 
   // test for overwriting an existing value
   Application.storage.set("fuel-test", "smarty");
   itemValue = Application.storage.get("fuel-test", "default");
   is(itemValue, "smarty", "Check 'Application.storage.get' for overwritten item");
 
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -17,17 +17,16 @@
 @APPNAME@/Contents/Plug-Ins/
 @APPNAME@/Contents/Resources/
 #endif
 
 [@AB_CD@]
 @BINPATH@/chrome/@AB_CD@.jar
 @BINPATH@/chrome/@AB_CD@.manifest
 @BINPATH@/@PREF_DIR@/firefox-l10n.js
-@BINPATH@/browserconfig.properties
 @BINPATH@/searchplugins/*
 @BINPATH@/defaults/profile/bookmarks.html
 @BINPATH@/defaults/profile/localstore.rdf
 @BINPATH@/defaults/profile/mimeTypes.rdf
 @BINPATH@/defaults/profile/chrome/*
 @BINPATH@/update.locale
 @BINPATH@/updater.ini
 @BINPATH@/dictionaries/*
--- a/browser/installer/removed-files.in
+++ b/browser/installer/removed-files.in
@@ -5,16 +5,17 @@
 # Inspector files are at the very end.
 .autoreg
 @DLL_PREFIX@jsj@DLL_SUFFIX@
 @DLL_PREFIX@sqlite3@DLL_SUFFIX@
 @DLL_PREFIX@xpcom_compat@DLL_SUFFIX@
 @DLL_PREFIX@xpistub@DLL_SUFFIX@
 @DLL_PREFIX@zlib@DLL_SUFFIX@
 LICENSE
+browserconfig.properties
 chrome.manifest
 chrome/US.jar
 chrome/app-chrome.manifest
 chrome/chrome.rdf
 chrome/chromelist.txt
 chrome/classic.jar
 chrome/classic.manifest
 chrome/comm.jar
--- a/browser/themes/winstripe/browser/browser-aero.css
+++ b/browser/themes/winstripe/browser/browser-aero.css
@@ -1,13 +1,12 @@
 %define WINSTRIPE_AERO
 %include browser.css
 %undef WINSTRIPE_AERO
 
-%if 0
 @media all and (-moz-windows-compositor) {
   #main-window:not(:-moz-lwtheme) {
     -moz-appearance: -moz-win-glass;
     background: transparent;
   }
 
   #navigator-toolbox:not(:-moz-lwtheme),
   #navigator-toolbox > toolbar {
@@ -68,17 +67,16 @@
     -moz-appearance: -moz-win-glass;
     -moz-border-radius: 0;
     border: none;
     font: normal 1.2em "Segoe UI";
     color: black;
     text-shadow: white -1px -1px .5em, white -1px 1px .5em, white 1px 1px .5em, white 1px -1px .5em;
   }
 }
-%endif
 
 @media not all and (-moz-windows-compositor) {
   #print-preview-toolbar:not(:-moz-lwtheme) {
     -moz-appearance: -moz-win-browsertabbar-toolbox;
   }
 }
 
 @media all and (-moz-windows-default-theme) {
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -108,17 +108,16 @@ MOZ_LEAKY	= @MOZ_LEAKY@
 MOZ_MEMORY      = @MOZ_MEMORY@
 MOZ_JPROF       = @MOZ_JPROF@
 MOZ_SHARK       = @MOZ_SHARK@
 MOZ_CALLGRIND   = @MOZ_CALLGRIND@
 MOZ_VTUNE       = @MOZ_VTUNE@
 MOZ_TRACEVIS    = @MOZ_TRACEVIS@
 DEHYDRA_PATH    = @DEHYDRA_PATH@
 
-MOZ_XPCTOOLS    = @MOZ_XPCTOOLS@
 NS_TRACE_MALLOC = @NS_TRACE_MALLOC@
 USE_ELF_DYNSTR_GC = @USE_ELF_DYNSTR_GC@
 INCREMENTAL_LINKER = @INCREMENTAL_LINKER@
 MACOSX_DEPLOYMENT_TARGET = @MACOSX_DEPLOYMENT_TARGET@
 MOZ_MAIL_NEWS	= @MOZ_MAIL_NEWS@
 MOZ_PLAINTEXT_EDITOR_ONLY = @MOZ_PLAINTEXT_EDITOR_ONLY@
 BUILD_STATIC_LIBS = @BUILD_STATIC_LIBS@
 MOZ_ENABLE_LIBXUL = @MOZ_ENABLE_LIBXUL@
--- a/config/outofdate.pl
+++ b/config/outofdate.pl
@@ -36,17 +36,17 @@
 #
 # ***** END LICENSE BLOCK *****
 
 #
 #Input: [-d dir] foo1.java foo2.java
 #Compares with: foo1.class foo2.class (if -d specified, checks in 'dir', 
 #  otherwise assumes .class files in same directory as .java files)
 #Returns: list of input arguments which are newer than corresponding class
-#files (non-existent class files are considered to be real old :-)
+#files (nonexistent class files are considered to be real old :-)
 #
 
 $found = 1;
 
 # GLOBALS
 $SEP = 0; # the paltform independent path separator
 $CFG = 0; # the value of the -cfg flag
 
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -1513,17 +1513,17 @@ SPACE := $(EMPTY) $(EMPTY)
 # and class paths to be in the DOS form (i.e. e:/builds/...).  This function
 # does the appropriate conversion on Windows, but is a noop on other systems.
 ifeq (,$(filter-out WINNT WINCE, $(HOST_OS_ARCH)))
 ifdef CYGWIN_WRAPPER
 normalizepath = $(foreach p,$(1),$(shell cygpath -m $(p)))
 else
 # assume MSYS
 #  We use 'pwd -W' to get DOS form of the path.  However, since the given path
-#  could be a file or a non-existent path, we cannot call 'pwd -W' directly
+#  could be a file or a nonexistent path, we cannot call 'pwd -W' directly
 #  on the path.  Instead, we extract the root path (i.e. "c:/"), call 'pwd -W'
 #  on it, then merge with the rest of the path.
 root-path = $(shell echo $(1) | sed -e "s|\(/[^/]*\)/\?\(.*\)|\1|")
 non-root-path = $(shell echo $(1) | sed -e "s|\(/[^/]*\)/\?\(.*\)|\2|")
 normalizepath = $(foreach p,$(1),$(if $(filter /%,$(1)),$(patsubst %/,%,$(shell cd $(call root-path,$(1)) && pwd -W))/$(call non-root-path,$(1)),$(1)))
 endif
 else
 normalizepath = $(1)
--- a/config/system-headers
+++ b/config/system-headers
@@ -207,16 +207,17 @@ curl/types.h
 curses.h
 cxxabi.h
 DateTimeUtils.h
 dbus/dbus.h
 dbus/dbus-glib.h
 dbus/dbus-glib-lowlevel.h
 ddeml.h
 Debug.h
+deque
 dem.h
 descrip.h
 Devices.h
 Dialogs.h
 direct.h
 dirent.h
 DiskInit.h
 dlfcn.h
@@ -269,16 +270,17 @@ freetype/ftcache.h
 freetype/ftglyph.h
 freetype/ftsynth.h
 freetype/ftoutln.h
 freetype/ttnameid.h
 freetype/tttables.h
 freetype/t1tables.h
 fribidi/fribidi.h
 FSp_fopen.h
+fstream
 fstream.h
 ft2build.h
 fts.h
 gconf/gconf-client.h
 Gdiplus.h
 gdk/gdk.h
 gdk/gdkkeysyms.h
 gdk/gdkprivate.h
@@ -324,16 +326,17 @@ inttypes.h
 iodef.h
 io.h
 IOKit/IOKitLib.h
 IOKit/IOMessage.h
 IOKit/pwr_mgt/IOPMLib.h
 iomanip
 iostream
 iostream.h
+iterator
 jar.h
 JavaControl.h
 JavaEmbedding/JavaControl.h
 JavaVM/jni.h
 JManager.h
 JNIEnvTests.h
 jni.h
 #if MOZ_NATIVE_JPEG==1
@@ -602,16 +605,17 @@ Process.h
 proto/dos.h
 proto/exec.h
 psap.h
 Pt.h
 pthread.h
 pwd.h
 Python.h
 QDOffscreen.h
+queue
 Quickdraw.h
 QuickDraw.h
 QuickTimeComponents.h
 quipu/attr.h
 rasdlg.h
 raserror.h
 ras.h
 regex.h
@@ -636,16 +640,17 @@ seccomon.h
 sec.h
 secmod.h
 secmodt.h
 secrng.h
 security.h
 secutil.h
 semaphore.h
 servprov.h
+set
 setjmp.h
 SFNTLayoutTypes.h
 SFNTTypes.h
 share.h
 shellapi.h
 shlguid.h
 shlobj.h
 sigcontext.h
@@ -829,16 +834,17 @@ unixio.h
 unixlib.h
 unknwn.h
 UPrinting.h
 UQuickTime.h
 UReanimator.h
 URegions.h
 URegistrar.h
 UResourceMgr.h
+utility
 urlhist.h
 urlmon.h
 UScrap.h
 UScreenPort.h
 UTCUtils.h
 UTETextAction.h
 UTEViewTextAction.h
 UTextEdit.h
--- a/configure.in
+++ b/configure.in
@@ -6268,17 +6268,17 @@ if test `echo "$MOZ_EXTENSIONS" | grep -
     AC_MSG_WARN([spellcheck is no longer an extension.])
     MOZ_EXTENSIONS=`echo $MOZ_EXTENSIONS | sed -e 's|spellcheck||g'`
 fi
 
 dnl Remove dupes
 MOZ_EXTENSIONS=`${PERL} ${srcdir}/build/unix/uniq.pl ${MOZ_EXTENSIONS}`
 
 dnl Ensure every extension exists, to avoid mostly-inscrutable error messages
-dnl when trying to build a non-existent extension.
+dnl when trying to build a nonexistent extension.
 for extension in $MOZ_EXTENSIONS; do
     if test ! -d "${srcdir}/extensions/${extension}"; then
         AC_MSG_ERROR([Unrecognized extension provided to --enable-extensions: ${extension}.])
     fi
 done
 
 
 dnl ========================================================
@@ -6523,25 +6523,16 @@ dnl leaky
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(leaky,
 [  --enable-leaky          Build leaky memory tool],
     MOZ_LEAKY=1,
     MOZ_LEAKY=)
 
 
 dnl ========================================================
-dnl xpctools
-dnl ========================================================
-MOZ_ARG_ENABLE_BOOL(xpctools,
-[  --enable-xpctools       Build JS profiling tool],
-    MOZ_XPCTOOLS=1,
-    MOZ_XPCTOOLS= )
-
-
-dnl ========================================================
 dnl build the tests by default
 dnl ========================================================
 MOZ_ARG_DISABLE_BOOL(tests,
 [  --disable-tests         Do not build test libraries & programs],
     ENABLE_TESTS=,
     ENABLE_TESTS=1 )
 
 dnl ========================================================
@@ -6929,17 +6920,29 @@ MOZ_ARG_ENABLE_STRING(debug,
         MOZ_DEBUG_FLAGS=`echo $enableval | sed -e 's|\\\ | |g'`
         _MOZ_DEBUG_FLAGS_SET=1
     fi
   else
     MOZ_DEBUG=
   fi ],
   MOZ_DEBUG=)
 
-MOZ_DEBUG_ENABLE_DEFS="-DDEBUG -D_DEBUG -DTRACING"
+MOZ_DEBUG_ENABLE_DEFS="-DDEBUG -D_DEBUG"
+ case "${target_os}" in
+    beos*)
+        MOZ_DEBUG_ENABLE_DEFS="$MOZ_DEBUG_ENABLE_DEFS -DDEBUG_${USER}"
+        ;;
+    msvc*|mks*|cygwin*|mingw*|os2*|wince*|winmo*)
+        MOZ_DEBUG_ENABLE_DEFS="$MOZ_DEBUG_ENABLE_DEFS -DDEBUG_`echo ${USERNAME} | sed -e 's| |_|g'`"
+        ;;
+    *) 
+        MOZ_DEBUG_ENABLE_DEFS="$MOZ_DEBUG_ENABLE_DEFS -DDEBUG_`$WHOAMI`"
+        ;;
+  esac
+MOZ_DEBUG_ENABLE_DEFS="$MOZ_DEBUG_ENABLE_DEFS -DTRACING"
 
 MOZ_DEBUG_DISABLE_DEFS="-DNDEBUG -DTRIMMED"
 
 if test -n "$MOZ_DEBUG"; then
     AC_MSG_CHECKING([for valid debug flags])
     _SAVE_CFLAGS=$CFLAGS
     CFLAGS="$CFLAGS $MOZ_DEBUG_FLAGS"
     AC_TRY_COMPILE([#include <stdio.h>], 
@@ -8471,17 +8474,16 @@ AC_SUBST(MOZ_IMG_ENCODERS)
 AC_SUBST(MOZ_JSDEBUGGER)
 AC_SUBST(MOZ_PLUGINS)
 AC_SUBST(MOZ_LOG_REFCNT)
 AC_SUBST(MOZ_LEAKY)
 AC_SUBST(MOZ_JPROF)
 AC_SUBST(MOZ_SHARK)
 AC_SUBST(MOZ_CALLGRIND)
 AC_SUBST(MOZ_VTUNE)
-AC_SUBST(MOZ_XPCTOOLS)
 AC_SUBST(MOZ_JSLOADER)
 AC_SUBST(MOZ_USE_NATIVE_UCONV)
 AC_SUBST(MOZ_QUANTIFY)
 AC_SUBST(LIBICONV)
 AC_SUBST(MOZ_PLACES)
 AC_SUBST(MOZ_PLACES_BOOKMARKS)
 AC_SUBST(MOZ_STORAGE)
 AC_SUBST(MOZ_TOOLKIT_SEARCH)
--- a/content/base/src/nsAttrValue.cpp
+++ b/content/base/src/nsAttrValue.cpp
@@ -1094,16 +1094,33 @@ nsAttrValue::ParseNonNegativeIntValue(co
     return PR_FALSE;
   }
 
   SetIntValueAndType(originalVal, eInteger, nsnull);
 
   return PR_TRUE;
 }
 
+PRBool
+nsAttrValue::ParsePositiveIntValue(const nsAString& aString)
+{
+  ResetIfSet();
+
+  PRInt32 ec;
+  PRBool strict;
+  PRInt32 originalVal = StringToInteger(aString, &strict, &ec);
+  if (NS_FAILED(ec) || originalVal <= 0) {
+    return PR_FALSE;
+  }
+
+  SetIntValueAndType(originalVal, eInteger, nsnull);
+
+  return PR_TRUE;
+}
+
 void
 nsAttrValue::SetColorValue(nscolor aColor, const nsAString& aString)
 {
   nsStringBuffer* buf = GetStringBuffer(aString);
   if (!buf) {
     return;
   }
 
--- a/content/base/src/nsAttrValue.h
+++ b/content/base/src/nsAttrValue.h
@@ -254,16 +254,31 @@ public:
    * http://dev.w3.org/html5/spec/infrastructure.html#rules-for-parsing-non-negative-integers
    *
    * @param  aString the string to parse
    * @return whether the value is valid
    */
   PRBool ParseNonNegativeIntValue(const nsAString& aString);
 
   /**
+   * Parse a string value into a positive integer.
+   * This method follows the rules for parsing non-negative integer from:
+   * http://dev.w3.org/html5/spec/infrastructure.html#rules-for-parsing-non-negative-integers
+   * In addition of these rules, the value has to be greater than zero.
+   *
+   * This is generally used for parsing content attributes which reflecting IDL
+   * attributes are limited to only non-negative numbers greater than zero, see:
+   * http://dev.w3.org/html5/spec/common-dom-interfaces.html#limited-to-only-non-negative-numbers-greater-than-zero
+   *
+   * @param aString       the string to parse
+   * @return              whether the value was valid
+   */
+  PRBool ParsePositiveIntValue(const nsAString& aString);
+
+  /**
    * Parse a string into a color.
    *
    * @param aString the string to parse
    * @param aDocument the document (to find out whether we're in quirks mode)
    * @return whether the value could be parsed
    */
   PRBool ParseColor(const nsAString& aString, nsIDocument* aDocument);
 
--- a/content/base/src/nsImageLoadingContent.cpp
+++ b/content/base/src/nsImageLoadingContent.cpp
@@ -427,17 +427,17 @@ nsImageLoadingContent::RemoveObserver(im
     // splice it out
     ImageObserver* oldObserver = observer->mNext;
     observer->mNext = oldObserver->mNext;
     oldObserver->mNext = nsnull;  // so we don't destroy them all
     delete oldObserver;
   }
 #ifdef DEBUG
   else {
-    NS_WARNING("Asked to remove non-existent observer");
+    NS_WARNING("Asked to remove nonexistent observer");
   }
 #endif
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsImageLoadingContent::GetRequest(PRInt32 aRequestType,
                                   imgIRequest** aRequest)
--- a/content/base/test/file_bug416317.xhtml
+++ b/content/base/test/file_bug416317.xhtml
@@ -660,17 +660,17 @@
       t( "Broken Selector", "()" );
       t( "Broken Selector", "<>" );
       t( "Broken Selector", "{}" );
 
       t( "ID Selector", "#body", ["body"], false );
       t( "ID Selector w/ Element", "body#body", ["body"], false );
       t( "ID Selector w/ Element", "ul#first", [] );
       t( "ID selector with existing ID descendant", "#firstp #simon1", ["simon1"] );
-      t( "ID selector with non-existent descendant", "#firstp #foobar", [] );
+      t( "ID selector with nonexistent descendant", "#firstp #foobar", [] );
 
       t( "ID selector using UTF8", "#台北Táiběi", ["台北Táiběi"] );
       t( "Multiple ID selectors using UTF8", "#台北Táiběi, #台北", ["台北Táiběi","台北"] );
       t( "Descendant ID selector using UTF8", "div #台北", ["台北"] );
       t( "Child ID selector using UTF8", "form > #台北", ["台北"] );
   
       t( "Escaped ID", "#foo\\:bar", ["foo:bar"] );
       t( "Escaped ID", "#test\\.foo\\[5\\]bar", ["test.foo[5]bar"] );
@@ -681,17 +681,17 @@
   
       t( "ID Selector, child ID present", "#form > #radio1", ["radio1"] ); // bug #267
       t( "ID Selector, not an ancestor ID", "#form #first", [] );
       t( "ID Selector, not a child ID", "#form > #option1a", [] );
       
       t( "All Children of ID", "#foo > *", ["sndp", "en", "sap"] );
       t( "All Children of ID with no children", "#firstUL > *", [] );
 
-      t( "ID selector with non-existent ancestor", "#asdfasdf #foobar", [] ); // bug #986
+      t( "ID selector with nonexistent ancestor", "#asdfasdf #foobar", [] ); // bug #986
 
       //t( "body div#form", [], "ID selector within the context of another element" );
 
       t( "Class Selector", ".blog", ["mark","simon"] );
       t( "Class Selector", ".blog.link", ["simon"] );
       t( "Class Selector w/ Element", "a.blog", ["mark","simon"] );
       t( "Parent Class Selector", "p .blog", ["mark","simon"] );
   
--- a/content/base/test/test_bug390219.html
+++ b/content/base/test/test_bug390219.html
@@ -16,17 +16,17 @@ https://bugzilla.mozilla.org/show_bug.cg
   
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 /** Test for Bug 390219 **/
 
 SimpleTest.waitForExplicitFinish();
 xhr = new XMLHttpRequest();
-xhr.open("GET", "non-existing_url", true);
+xhr.open("GET", "nonexistent_url", true);
 xhr.send(null);
 xhr.abort();
 xhr.open("GET", ".", true);
 xhr.onreadystatechange = function() {
   if (xhr.readyState == 4) {
     is(xhr.status, 200, "wrong status");
     SimpleTest.finish();
   }
--- a/content/base/test/test_classList.html
+++ b/content/base/test/test_classList.html
@@ -64,17 +64,17 @@ function checkModification(e, funcName, 
     is(e.code, expectedException, "wrong exception thrown " + contextMsg);
   }
   e.removeEventListener("DOMAttrModified", onAttrModified, false);
   if (expectedRes !== null)
     is(res, expectedRes, "wrong return value from " + funcName +
        " " + contextMsg);
 
   var expectedAfter = after;
-  // XUL returns an empty string when getting a non-existing class attribute.
+  // XUL returns an empty string when getting a nonexistent class attribute.
   if (e.namespaceURI == XUL_NS && expectedAfter === null)
     expectedAfter = "";
 
   is(e.getAttribute("class"), expectedAfter, "wrong class after modification " +
      contextMsg);
   var expectedMutation = before != after;
   is(gMutationEvents.length, expectedMutation ? 1 : 0,
      "unexpected mutation event count " + contextMsg);
--- a/content/base/test/test_fileapi.html
+++ b/content/base/test/test_fileapi.html
@@ -249,27 +249,27 @@ r.abort();
 is(reuseAbortHasRun, false, "abort() is a no-op unless loading");
 r.readAsText(asciiFile);
 r.readAsText(asciiFile);
 is(reuseAbortHasRun, true, "abort should fire sync");
 r.onload = getLoadHandler(testASCIIData, testASCIIData.length, "reuse-as-abort reading");
 expectedTestCount++;
 
 
-// Test reading from non-existing files
+// Test reading from nonexistent files
 r = new FileReader();
 var didThrow = false;
 try {
   r.readAsDataURL(nonExistingFile);
 } catch(ex) {
   didThrow = true;
 }
 // Once this test passes, we shoud test that onerror gets called and
 // that the FileReader object is in the right state during that call.
-todo(!didThrow, "shouldn't throw when opening non-existing file, should fire error instead");
+todo(!didThrow, "shouldn't throw when opening nonexistent file, should fire error instead");
 
 
 function getLoadHandler(expectedResult, expectedLength, testName) {
   return function (event) {
     is(event.target.readyState, FileReader.DONE,
        "readyState in test " + testName);
     is(event.target.error, null,
        "no error in test " + testName);
--- a/content/canvas/src/WebGLContextGL.cpp
+++ b/content/canvas/src/WebGLContextGL.cpp
@@ -2153,23 +2153,22 @@ WebGLContext::DOMElementToImageSurface(n
 
                 *dst++ = r;
                 *dst++ = g;
                 *dst++ = b;
                 *dst++ = a;
             }
         }
     } else if (surf->Format() == gfxASurface::ImageFormatRGB24) {
-        PRUint8* src = surf->Data();
         PRUint8* dst = surf->Data();
 
         // this wants some SSE love
 
         for (int j = 0; j < height; j++) {
-            src = surf->Data() + j * surf->Stride();
+            PRUint8* src = surf->Data() + j * surf->Stride();
             // note that dst's stride is always tightly packed
             for (int i = 0; i < width; i++) {
 #ifdef IS_LITTLE_ENDIAN
                 PRUint8 b = *src++;
                 PRUint8 g = *src++;
                 PRUint8 r = *src++;
                 src++;
 #else
--- a/content/html/content/src/nsGenericHTMLElement.h
+++ b/content/html/content/src/nsGenericHTMLElement.h
@@ -1102,16 +1102,41 @@ NS_NewHTML##_elementName##Element(nsINod
   }                                                                       \
   NS_IMETHODIMP                                                           \
   _class::Set##_method(const nsAString& aValue)                           \
   {                                                                       \
     return SetAttrHelper(nsGkAtoms::_atom, aValue);                       \
   }
 
 /**
+ * A macro to implement the getter and setter for a given content
+ * property that needs to set a positive integer. The method uses
+ * the generic GetAttr and SetAttr methods. This macro is much like
+ * the NS_IMPL_NON_NEGATIVE_INT_ATTR macro except the exception is
+ * thrown also when the value is equal to 0.
+ */
+#define NS_IMPL_POSITIVE_INT_ATTR(_class, _method, _atom)                 \
+  NS_IMPL_POSITIVE_INT_ATTR_DEFAULT_VALUE(_class, _method, _atom, 1)
+
+#define NS_IMPL_POSITIVE_INT_ATTR_DEFAULT_VALUE(_class, _method, _atom, _default)  \
+  NS_IMETHODIMP                                                           \
+  _class::Get##_method(PRInt32* aValue)                                   \
+  {                                                                       \
+    return GetIntAttr(nsGkAtoms::_atom, _default, aValue);                \
+  }                                                                       \
+  NS_IMETHODIMP                                                           \
+  _class::Set##_method(PRInt32 aValue)                                    \
+  {                                                                       \
+    if (aValue <= 0) {                                                    \
+      return NS_ERROR_DOM_INDEX_SIZE_ERR;                                 \
+    }                                                                     \
+    return SetIntAttr(nsGkAtoms::_atom, aValue);                          \
+  }
+
+/**
  * QueryInterface() implementation helper macros
  */
 
 #define NS_HTML_CONTENT_INTERFACE_TABLE_AMBIGUOUS_BEGIN(_class, _base)        \
   NS_NODE_OFFSET_AND_INTERFACE_TABLE_BEGIN(_class)                            \
     NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsIDOMNode, _base)             \
     NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsIDOMElement, _base)          \
     NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsIDOMHTMLElement, _base)
--- a/content/html/content/src/nsHTMLSelectElement.cpp
+++ b/content/html/content/src/nsHTMLSelectElement.cpp
@@ -1201,17 +1201,18 @@ nsHTMLSelectElement::SetValue(const nsAS
   return rv;
 }
 
 
 NS_IMPL_BOOL_ATTR(nsHTMLSelectElement, Autofocus, autofocus)
 NS_IMPL_BOOL_ATTR(nsHTMLSelectElement, Disabled, disabled)
 NS_IMPL_BOOL_ATTR(nsHTMLSelectElement, Multiple, multiple)
 NS_IMPL_STRING_ATTR(nsHTMLSelectElement, Name, name)
-NS_IMPL_INT_ATTR_DEFAULT_VALUE(nsHTMLSelectElement, Size, size, 0)
+NS_IMPL_POSITIVE_INT_ATTR_DEFAULT_VALUE(nsHTMLSelectElement, Size, size,
+                                        GetDefaultSize())
 NS_IMPL_INT_ATTR_DEFAULT_VALUE(nsHTMLSelectElement, TabIndex, tabindex, 0)
 
 NS_IMETHODIMP
 nsHTMLSelectElement::Blur()
 {
   return nsGenericHTMLElement::Blur();
 }
 
@@ -1363,17 +1364,17 @@ nsHTMLSelectElement::DoneAddingChildren(
 
 PRBool
 nsHTMLSelectElement::ParseAttribute(PRInt32 aNamespaceID,
                                     nsIAtom* aAttribute,
                                     const nsAString& aValue,
                                     nsAttrValue& aResult)
 {
   if (aAttribute == nsGkAtoms::size && kNameSpaceID_None == aNamespaceID) {
-    return aResult.ParseIntWithBounds(aValue, 0);
+    return aResult.ParsePositiveIntValue(aValue);
   }
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                               aResult);
 }
 
 static void
 MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
                       nsRuleData* aData)
--- a/content/html/content/src/nsHTMLSelectElement.h
+++ b/content/html/content/src/nsHTMLSelectElement.h
@@ -468,16 +468,24 @@ protected:
   void VerifyOptionsArray();
 #endif
 
   virtual PRBool AcceptAutofocus() const
   {
     return PR_TRUE;
   }
 
+  /**
+   * Helper method to get the default size.
+   */
+  PRInt32 GetDefaultSize() const
+  {
+    return HasAttr(kNameSpaceID_None, nsGkAtoms::multiple) ? 4 : 1;
+  }
+
   /** The options[] array */
   nsRefPtr<nsHTMLOptionCollection> mOptions;
   /** false if the parser is in the middle of adding children. */
   PRPackedBool    mIsDoneAddingChildren;
   /** true if our disabled state has changed from the default **/
   PRPackedBool    mDisabledChanged;
   /** true if child nodes are being added or removed.
    *  Used by nsSafeOptionListMutation.
--- a/content/html/content/test/Makefile.in
+++ b/content/html/content/test/Makefile.in
@@ -172,12 +172,13 @@ include $(topsrcdir)/config/rules.mk
 		test_bug546995-1.html \
 		test_bug546995-2.html \
 		test_bug546995-3.html \
 		test_bug546995-4.html \
 		test_bug546995-5.html \
 		file_bug546995.html \
 		test_bug377624.html \
 		test_bug562932.html \
+		test_bug551846.html \
 		$(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/content/html/content/test/test_bug551846.html
@@ -0,0 +1,159 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=551846
+-->
+<head>
+  <title>Test for Bug 551846</title>
+  <script type="application/javascript" src="/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=551846">Mozilla Bug 551846</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  <select id='s'>
+    <option>Tulip</option>
+    <option>Lily</option>
+    <option>Gagea</option>
+    <option>Snowflake</option>
+    <option>Ismene</option>
+  </select>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 551846 **/
+
+function checkSizeReflection(element, defaultValue)
+{
+  is(element.size, defaultValue, "Default size should be " + defaultValue);
+
+  element.setAttribute('size', -15);
+  is(element.size, defaultValue,
+    "The reflecting IDL attribute should return the default value when content attribute value is invalid");
+  is(element.getAttribute('size'), -15,
+    "The content attribute should containt the previously set value");
+
+  element.setAttribute('size', 0);
+  is(element.size, defaultValue,
+    "The reflecting IDL attribute should return the default value when content attribute value is invalid");
+
+  element.setAttribute('size', 2147483647); /* PR_INT32_MAX */
+  is(element.size, 2147483647,
+    "PR_INT32_MAX should be considered as a valid value");
+  is(element.getAttribute('size'), 2147483647,
+    "The content attribute should containt the previously set value");
+
+  element.setAttribute('size', -2147483648); /* PR_INT32_MIN */
+  is(element.size, defaultValue,
+    "The reflecting IDL attribute should return the default value when content attribute value is invalid");
+  is(element.getAttribute('size'), -2147483648,
+    "The content attribute should containt the previously set value");
+
+  element.setAttribute('size', 'non-numerical-value');
+  is(element.size, defaultValue,
+    "The reflecting IDL attribute should return the default value when content attribute value is invalid");
+  is(element.getAttribute('size'), 'non-numerical-value',
+    "The content attribute should containt the previously set value");
+
+  element.setAttribute('size', 4294967294); /* PR_INT32_MAX * 2 */
+  is(element.size, defaultValue,
+    "Value greater than PR_INT32_MAX should be considered as invalid");
+  is(element.getAttribute('size'), 4294967294,
+    "The content attribute should containt the previously set value");
+
+  element.setAttribute('size', -4294967296); /* PR_INT32_MIN * 2 */
+  is(element.size, defaultValue,
+    "The reflecting IDL attribute should return the default value when content attribute value is invalid");
+  is(element.getAttribute('size'), -4294967296,
+    "The content attribute should containt the previously set value");
+
+  element.size = defaultValue + 1;
+  element.removeAttribute('size');
+  is(element.size, defaultValue,
+    "When the attribute is removed, the size should be the default size");
+
+  element.setAttribute('size', 'foobar');
+  is(element.size, defaultValue,
+    "The reflecting IDL attribute should return the default value when content attribute value is invalid");
+  element.removeAttribute('size');
+  is(element.size, defaultValue,
+    "When the attribute is removed, the size should be the default size");
+}
+
+function checkSetSizeException(element)
+{
+  var caught = false;
+
+  try {
+    element.size = 1;
+  } catch(e) {
+    caught = true;
+  }
+  ok(!caught, "Setting a valid size shouldn't throw an exception");
+
+  caught = false;
+  try {
+    element.size = 0;
+  } catch(e) {
+    caught = true;
+  }
+  ok(caught, "Setting an invalid size from the IDL should throw an exception");
+
+  caught = false;
+  try {
+    element.size = -1;
+  } catch(e) {
+    caught = true;
+  }
+  ok(caught, "Setting an invalid size from the IDL should throw an exception");
+
+  caught = false;
+  try {
+    element.setAttribute('size', -10);
+  } catch(e) {
+    caught = true;
+  }
+  ok(!caught, "Setting an invalid size in the content attribute shouldn't throw an exception");
+
+  // reverting to defalut
+  element.removeAttribute('size');
+}
+
+function checkSizeWhenChangeMultiple(element)
+{
+  s.setAttribute('size', -1)
+  is(s.size, 1, "Size IDL attribute should be 1");
+
+  s.multiple = true;
+  is(s.size, 4, "Size IDL attribute should be 4");
+
+  is(s.getAttribute('size'), -1, "Size content attribute should be -1");
+
+  s.setAttribute('size', -2);
+  is(s.size, 4, "Size IDL attribute should be 4");
+
+  s.multiple = false;
+  is(s.size, 1, "Size IDL attribute should be 1");
+
+  is(s.getAttribute('size'), -2, "Size content attribute should be -2");
+}
+
+var s = document.getElementById('s');
+
+checkSizeReflection(s, 1);
+checkSetSizeException(s);
+
+s.setAttribute('multiple', 'true');
+checkSizeReflection(s, 4);
+checkSetSizeException(s);
+s.removeAttribute('multiple');
+
+checkSizeWhenChangeMultiple(s);
+
+</script>
+</pre>
+</body>
+</html>
--- a/content/html/document/src/nsHTMLContentSink.cpp
+++ b/content/html/document/src/nsHTMLContentSink.cpp
@@ -1759,17 +1759,17 @@ HTMLContentSink::BeginContext(PRInt32 aP
 
   // Create new context
   SinkContext* sc = new SinkContext(this);
   if (!sc) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   if (!mCurrentContext) {
-    NS_ERROR("Non-existing context");
+    NS_ERROR("Nonexistent context");
 
     return NS_ERROR_FAILURE;
   }
 
   // Flush everything in the current context so that we don't have
   // to worry about insertions resulting in inconsistent frame creation.
   mCurrentContext->FlushTags();
 
@@ -1799,17 +1799,17 @@ HTMLContentSink::BeginContext(PRInt32 aP
   mContextStack.AppendElement(mCurrentContext);
   mCurrentContext = sc;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 HTMLContentSink::EndContext(PRInt32 aPosition)
 {
-  NS_PRECONDITION(mCurrentContext && aPosition > -1, "non-existing context");
+  NS_PRECONDITION(mCurrentContext && aPosition > -1, "nonexistent context");
 
   PRUint32 n = mContextStack.Length() - 1;
   SinkContext* sc = mContextStack.ElementAt(n);
 
   const SinkContext::Node &bottom = mCurrentContext->mStack[0];
   
   NS_ASSERTION(sc->mStack[aPosition].mType == bottom.mType,
                "ending a wrong context");
--- a/content/html/document/src/nsHTMLDocument.cpp
+++ b/content/html/document/src/nsHTMLDocument.cpp
@@ -2149,17 +2149,17 @@ nsHTMLDocument::Close()
       FlushPendingNotifications(Flush_Layout);
     }
 
     // Remove the wyciwyg channel request from the document load group
     // that we added in OpenCommon().  If all other requests between
     // document.open() and document.close() have completed, then this
     // method should cause the firing of an onload event.
     NS_ASSERTION(mWyciwygChannel, "nsHTMLDocument::Close(): Trying to remove "
-                 "non-existent wyciwyg channel!");
+                 "nonexistent wyciwyg channel!");
     RemoveWyciwygChannel();
     NS_ASSERTION(!mWyciwygChannel, "nsHTMLDocument::Close(): "
                  "nsIWyciwygChannel could not be removed!");
   }
 
   return NS_OK;
 }
 
--- a/content/media/nsBuiltinDecoderReader.h
+++ b/content/media/nsBuiltinDecoderReader.h
@@ -51,30 +51,30 @@
 
 class nsBuiltinDecoderStateMachine;
 
 // Stores info relevant to presenting media samples.
 class nsVideoInfo {
 public:
   nsVideoInfo()
     : mFramerate(0.0),
-      mAspectRatio(1.0),
+      mPixelAspectRatio(1.0),
       mCallbackPeriod(1),
       mAudioRate(0),
       mAudioChannels(0),
       mFrame(0,0),
       mHasAudio(PR_FALSE),
       mHasVideo(PR_FALSE)
   {}
 
   // Frames per second.
   float mFramerate;
 
-  // Aspect ratio, as stored in the metadata.
-  float mAspectRatio;
+  // Pixel aspect ratio, as stored in the metadata.
+  float mPixelAspectRatio;
 
   // Length of a video frame in milliseconds, or the callback period if
   // there's no audio.
   PRUint32 mCallbackPeriod;
 
   // Samples per second.
   PRUint32 mAudioRate;
 
--- a/content/media/nsBuiltinDecoderStateMachine.cpp
+++ b/content/media/nsBuiltinDecoderStateMachine.cpp
@@ -1025,17 +1025,17 @@ void nsBuiltinDecoderStateMachine::Rende
 
   if (aData->mDuplicate) {
     return;
   }
 
   nsRefPtr<Image> image = aData->mImage;
   if (image) {
     const nsVideoInfo& info = mReader->GetInfo();
-    mDecoder->SetVideoData(gfxIntSize(info.mPicture.width, info.mPicture.height), info.mAspectRatio, image);
+    mDecoder->SetVideoData(gfxIntSize(info.mPicture.width, info.mPicture.height), info.mPixelAspectRatio, image);
   }
 }
 
 PRInt64
 nsBuiltinDecoderStateMachine::GetAudioClock()
 {
   NS_ASSERTION(IsCurrentThread(mDecoder->mStateMachineThread), "Should be on state machine thread.");
   if (!mAudioStream || !HasAudio())
--- a/content/media/nsMediaDecoder.cpp
+++ b/content/media/nsMediaDecoder.cpp
@@ -65,17 +65,17 @@
 
 nsMediaDecoder::nsMediaDecoder() :
   mElement(0),
   mRGBWidth(-1),
   mRGBHeight(-1),
   mProgressTime(),
   mDataTime(),
   mVideoUpdateLock(nsnull),
-  mAspectRatio(1.0),
+  mPixelAspectRatio(1.0),
   mSizeChanged(PR_FALSE),
   mShuttingDown(PR_FALSE)
 {
   MOZ_COUNT_CTOR(nsMediaDecoder);
 }
 
 nsMediaDecoder::~nsMediaDecoder()
 {
@@ -121,24 +121,24 @@ void nsMediaDecoder::Invalidate()
   nsIFrame* frame = mElement->GetPrimaryFrame();
 
   {
     nsAutoLock lock(mVideoUpdateLock);
     if (mSizeChanged) {
       nsIntSize scaledSize(mRGBWidth, mRGBHeight);
       // Apply the aspect ratio to produce the intrinsic size we report
       // to the element.
-      if (mAspectRatio > 1.0) {
+      if (mPixelAspectRatio > 1.0) {
         // Increase the intrinsic width
         scaledSize.width =
-          ConditionDimension(mAspectRatio*scaledSize.width, scaledSize.width);
+          ConditionDimension(mPixelAspectRatio*scaledSize.width, scaledSize.width);
       } else {
         // Increase the intrinsic height
         scaledSize.height =
-          ConditionDimension(scaledSize.height/mAspectRatio, scaledSize.height);
+          ConditionDimension(scaledSize.height/mPixelAspectRatio, scaledSize.height);
       }
       mElement->UpdateMediaSize(scaledSize);
 
       mSizeChanged = PR_FALSE;
       if (frame) {
         nsPresContext* presContext = frame->PresContext();
         nsIPresShell *presShell = presContext->PresShell();
         presShell->FrameNeedsReflow(frame,
@@ -208,24 +208,24 @@ nsresult nsMediaDecoder::StopProgress()
 
   nsresult rv = mProgressTimer->Cancel();
   mProgressTimer = nsnull;
 
   return rv;
 }
 
 void nsMediaDecoder::SetVideoData(const gfxIntSize& aSize,
-                                  float aAspectRatio,
+                                  float aPixelAspectRatio,
                                   Image* aImage)
 {
   nsAutoLock lock(mVideoUpdateLock);
 
   if (mRGBWidth != aSize.width || mRGBHeight != aSize.height ||
-      mAspectRatio != aAspectRatio) {
+      mPixelAspectRatio != aPixelAspectRatio) {
     mRGBWidth = aSize.width;
     mRGBHeight = aSize.height;
-    mAspectRatio = aAspectRatio;
+    mPixelAspectRatio = aPixelAspectRatio;
     mSizeChanged = PR_TRUE;
   }
   if (mImageContainer && aImage) {
     mImageContainer->SetCurrentImage(aImage);
   }
 }
--- a/content/media/nsMediaDecoder.h
+++ b/content/media/nsMediaDecoder.h
@@ -226,17 +226,17 @@ public:
   // Gets the image container for the media element. Will return null if
   // the element is not a video element. This can be called from any
   // thread; ImageContainers can be used from any thread.
   ImageContainer* GetImageContainer() { return mImageContainer; }
 
   // Set the video width, height, pixel aspect ratio, and current image.
   // Ownership of the image is transferred to the decoder.
   void SetVideoData(const gfxIntSize& aSize,
-                    float aAspectRatio,
+                    float aPixelAspectRatio,
                     Image* aImage);
 
 protected:
 
   // Start timer to update download progress information.
   nsresult StartProgress();
 
   // Stop progress information timer.
@@ -278,17 +278,17 @@ protected:
   // in the midst of being changed.
   PRLock* mVideoUpdateLock;
 
   // Framerate of video being displayed in the element
   // expressed in numbers of frames per second.
   float mFramerate;
 
   // Pixel aspect ratio (ratio of the pixel width to pixel height)
-  float mAspectRatio;
+  float mPixelAspectRatio;
 
   // Has our size changed since the last repaint?
   PRPackedBool mSizeChanged;
 
   // True if the decoder is being shutdown. At this point all events that
   // are currently queued need to return immediately to prevent javascript
   // being run that operates on the element and decoder during shutdown.
   // Read/Write from the main thread only.
--- a/content/media/ogg/nsOggCodecState.cpp
+++ b/content/media/ogg/nsOggCodecState.cpp
@@ -144,17 +144,17 @@ PRBool nsOggCodecState::PageInFromBuffer
 }
 
 nsTheoraState::nsTheoraState(ogg_page* aBosPage) :
   nsOggCodecState(aBosPage),
   mSetup(0),
   mCtx(0),
   mFrameDuration(0),
   mFrameRate(0),
-  mAspectRatio(0)
+  mPixelAspectRatio(0)
 {
   MOZ_COUNT_CTOR(nsTheoraState);
   th_info_init(&mInfo);
   th_comment_init(&mComment);
 }
 
 nsTheoraState::~nsTheoraState() {
   MOZ_COUNT_DTOR(nsTheoraState);
@@ -186,17 +186,17 @@ PRBool nsTheoraState::Init() {
   if (f > PR_UINT32_MAX) {
     return mActive = PR_FALSE;
   }
   mFrameDuration = static_cast<PRUint32>(f);
 
   n = mInfo.aspect_numerator;
 
   d = mInfo.aspect_denominator;
-  mAspectRatio = (n == 0 || d == 0) ?
+  mPixelAspectRatio = (n == 0 || d == 0) ?
     1.0f : static_cast<float>(n) / static_cast<float>(d);
 
   // Ensure the frame isn't larger than our prescribed maximum.
   PRUint32 pixels;
   if (!MulOverflow32(mInfo.pic_width, mInfo.pic_height, pixels) ||
       pixels > MAX_VIDEO_WIDTH * MAX_VIDEO_HEIGHT ||
       pixels == 0)
   {
--- a/content/media/ogg/nsOggCodecState.h
+++ b/content/media/ogg/nsOggCodecState.h
@@ -185,17 +185,17 @@ public:
   th_dec_ctx* mCtx;
 
   // Frame duration in ms.
   PRUint32 mFrameDuration;
 
   // Number of frames per second.
   float mFrameRate;
 
-  float mAspectRatio;
+  float mPixelAspectRatio;
 };
 
 class nsSkeletonState : public nsOggCodecState {
 public:
   nsSkeletonState(ogg_page* aBosPage);
   virtual ~nsSkeletonState();
   virtual CodecType GetType() { return TYPE_SKELETON; }
   virtual PRBool DecodeHeader(ogg_packet* aPacket);
--- a/content/media/ogg/nsOggReader.cpp
+++ b/content/media/ogg/nsOggReader.cpp
@@ -245,26 +245,24 @@ nsresult nsOggReader::ReadMetadata()
     if (s != mVorbisState && s != mTheoraState) {
       s->Deactivate();
     }
   }
 
   // Initialize the first Theora and Vorbis bitstreams. According to the
   // Theora spec these can be considered the 'primary' bitstreams for playback.
   // Extract the metadata needed from these streams.
-  float aspectRatio = 0;
   // Set a default callback period for if we have no video data
   mCallbackPeriod = 1000 / AUDIO_FRAME_RATE;
   if (mTheoraState) {
     if (mTheoraState->Init()) {
       mCallbackPeriod = mTheoraState->mFrameDuration;
-      aspectRatio = mTheoraState->mAspectRatio;
       gfxIntSize sz(mTheoraState->mInfo.pic_width,
                     mTheoraState->mInfo.pic_height);
-      mDecoder->SetVideoData(sz, mTheoraState->mAspectRatio, nsnull);
+      mDecoder->SetVideoData(sz, mTheoraState->mPixelAspectRatio, nsnull);
     } else {
       mTheoraState = nsnull;
     }
   }
   if (mVorbisState) {
     mVorbisState->Init();
   }
 
@@ -272,17 +270,17 @@ nsresult nsOggReader::ReadMetadata()
   mInfo.mHasVideo = HasVideo();
   mInfo.mCallbackPeriod = mCallbackPeriod;
   if (HasAudio()) {
     mInfo.mAudioRate = mVorbisState->mInfo.rate;
     mInfo.mAudioChannels = mVorbisState->mInfo.channels;
   }
   if (HasVideo()) {
     mInfo.mFramerate = mTheoraState->mFrameRate;
-    mInfo.mAspectRatio = mTheoraState->mAspectRatio;
+    mInfo.mPixelAspectRatio = mTheoraState->mPixelAspectRatio;
     mInfo.mPicture.width = mTheoraState->mInfo.pic_width;
     mInfo.mPicture.height = mTheoraState->mInfo.pic_height;
     mInfo.mPicture.x = mTheoraState->mInfo.pic_x;
     mInfo.mPicture.y = mTheoraState->mInfo.pic_y;
     mInfo.mFrame.width = mTheoraState->mInfo.frame_width;
     mInfo.mFrame.height = mTheoraState->mInfo.frame_height;
   }
   mInfo.mDataOffset = mDataOffset;
--- a/content/svg/content/src/nsSVGAltGlyphElement.cpp
+++ b/content/svg/content/src/nsSVGAltGlyphElement.cpp
@@ -27,60 +27,54 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
-#include "nsSVGStylableElement.h"
 #include "nsGkAtoms.h"
 #include "nsIDOMSVGAltGlyphElement.h"
 #include "nsIDOMSVGURIReference.h"
 #include "nsSVGString.h"
 #include "nsSVGTextPositioningElement.h"
 
-typedef nsSVGStylableElement nsSVGAltGlyphElementBase;
+typedef nsSVGTextPositioningElement nsSVGAltGlyphElementBase;
 
-class nsSVGAltGlyphElement : public nsSVGAltGlyphElementBase,
+class nsSVGAltGlyphElement : public nsSVGAltGlyphElementBase, // = nsIDOMSVGTextPositioningElement
                              public nsIDOMSVGAltGlyphElement,
-                             public nsIDOMSVGURIReference, 
-                             public nsSVGTextPositioningElement // = nsIDOMSVGTextPositioningElement
+                             public nsIDOMSVGURIReference
 {
 protected:
   friend nsresult NS_NewSVGAltGlyphElement(nsIContent **aResult,
                                            nsINodeInfo *aNodeInfo);
   nsSVGAltGlyphElement(nsINodeInfo* aNodeInfo);
-  nsresult Init();
   
 public:
   // interfaces:
   
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIDOMSVGALTGLYPHELEMENT
   NS_DECL_NSIDOMSVGURIREFERENCE
 
   // xxx If xpcom allowed virtual inheritance we wouldn't need to
   // forward here :-(
   NS_FORWARD_NSIDOMNODE(nsSVGAltGlyphElementBase::)
   NS_FORWARD_NSIDOMELEMENT(nsSVGAltGlyphElementBase::)
   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGAltGlyphElementBase::)
-  NS_FORWARD_NSIDOMSVGTEXTCONTENTELEMENT(nsSVGTextContentElement::)
-  NS_FORWARD_NSIDOMSVGTEXTPOSITIONINGELEMENT(nsSVGTextPositioningElement::)
+  NS_FORWARD_NSIDOMSVGTEXTCONTENTELEMENT(nsSVGAltGlyphElementBase::)
+  NS_FORWARD_NSIDOMSVGTEXTPOSITIONINGELEMENT(nsSVGAltGlyphElementBase::)
 
   // nsIContent interface
   NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
 protected:
-  virtual nsSVGTextContainerFrame* GetTextContainerFrame() {
-    return do_QueryFrame(GetPrimaryFrame(Flush_Layout));
-  }
 
   // nsSVGElement overrides
   virtual StringAttributesInfo GetStringInfo();
 
   virtual PRBool IsEventName(nsIAtom* aName);
 
   enum { HREF };
   nsSVGString mStringAttributes[1];
@@ -114,27 +108,16 @@ NS_INTERFACE_MAP_END_INHERITING(nsSVGAlt
 //----------------------------------------------------------------------
 // Implementation
 
 nsSVGAltGlyphElement::nsSVGAltGlyphElement(nsINodeInfo *aNodeInfo)
   : nsSVGAltGlyphElementBase(aNodeInfo)
 {
 }
 
-nsresult
-nsSVGAltGlyphElement::Init()
-{
-  nsresult rv = nsSVGAltGlyphElementBase::Init();
-  NS_ENSURE_SUCCESS(rv,rv);
-
-  rv = Initialise(this);
-  NS_ENSURE_SUCCESS(rv,rv);
-
-  return rv;
-}
 
 //----------------------------------------------------------------------
 // nsIDOMNode methods
 
 NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGAltGlyphElement)
 
 //----------------------------------------------------------------------
 // nsIDOMSVGURIReference methods
--- a/content/svg/content/src/nsSVGElement.h
+++ b/content/svg/content/src/nsSVGElement.h
@@ -189,17 +189,16 @@ protected:
   virtual nsresult AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
                                 const nsAString* aValue, PRBool aNotify);
   virtual PRBool ParseAttribute(PRInt32 aNamespaceID, nsIAtom* aAttribute,
                                 const nsAString& aValue, nsAttrValue& aResult);
   static nsresult ReportAttributeParseFailure(nsIDocument* aDocument,
                                               nsIAtom* aAttribute,
                                               const nsAString& aValue);
 
-  friend class nsSVGTextPositioningElement;
   // Hooks for subclasses
   virtual PRBool IsEventName(nsIAtom* aName);
 
   void UpdateContentStyleRule();
 #ifdef MOZ_SMIL
   void UpdateAnimatedContentStyleRule();
   nsICSSStyleRule* GetAnimatedContentStyleRule();
 #endif // MOZ_SMIL
--- a/content/svg/content/src/nsSVGTSpanElement.cpp
+++ b/content/svg/content/src/nsSVGTSpanElement.cpp
@@ -31,57 +31,51 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
-#include "nsSVGStylableElement.h"
 #include "nsGkAtoms.h"
 #include "nsIDOMSVGTSpanElement.h"
 #include "nsSVGSVGElement.h"
 #include "nsSVGTextPositioningElement.h"
 
-typedef nsSVGStylableElement nsSVGTSpanElementBase;
+typedef nsSVGTextPositioningElement nsSVGTSpanElementBase;
 
-class nsSVGTSpanElement : public nsSVGTSpanElementBase,
-                          public nsIDOMSVGTSpanElement,
-                          public nsSVGTextPositioningElement // = nsIDOMSVGTextPositioningElement
+class nsSVGTSpanElement : public nsSVGTSpanElementBase, // = nsIDOMSVGTextPositioningElement
+                          public nsIDOMSVGTSpanElement
 {
 protected:
   friend nsresult NS_NewSVGTSpanElement(nsIContent **aResult,
                                         nsINodeInfo *aNodeInfo);
   nsSVGTSpanElement(nsINodeInfo* aNodeInfo);
-  nsresult Init();
   
 public:
   // interfaces:
   
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIDOMSVGTSPANELEMENT
 
   // xxx If xpcom allowed virtual inheritance we wouldn't need to
   // forward here :-(
   NS_FORWARD_NSIDOMNODE(nsSVGTSpanElementBase::)
   NS_FORWARD_NSIDOMELEMENT(nsSVGTSpanElementBase::)
   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGTSpanElementBase::)
-  NS_FORWARD_NSIDOMSVGTEXTCONTENTELEMENT(nsSVGTextContentElement::)
-  NS_FORWARD_NSIDOMSVGTEXTPOSITIONINGELEMENT(nsSVGTextPositioningElement::)
+  NS_FORWARD_NSIDOMSVGTEXTCONTENTELEMENT(nsSVGTSpanElementBase::)
+  NS_FORWARD_NSIDOMSVGTEXTPOSITIONINGELEMENT(nsSVGTSpanElementBase::)
 
   // nsIContent interface
   NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
 protected:
-  virtual nsSVGTextContainerFrame* GetTextContainerFrame() {
-    return do_QueryFrame(GetPrimaryFrame(Flush_Layout));
-  }
 
   // nsSVGElement overrides
   virtual PRBool IsEventName(nsIAtom* aName);
 };
 
 
 NS_IMPL_NS_NEW_SVG_ELEMENT(TSpan)
 
@@ -107,28 +101,16 @@ NS_INTERFACE_MAP_END_INHERITING(nsSVGTSp
 
 nsSVGTSpanElement::nsSVGTSpanElement(nsINodeInfo *aNodeInfo)
   : nsSVGTSpanElementBase(aNodeInfo)
 {
 
 }
 
   
-nsresult
-nsSVGTSpanElement::Init()
-{
-  nsresult rv = nsSVGTSpanElementBase::Init();
-  NS_ENSURE_SUCCESS(rv,rv);
-
-  rv = Initialise(this);
-  NS_ENSURE_SUCCESS(rv,rv);
-
-  return rv;
-}
-
 //----------------------------------------------------------------------
 // nsIDOMNode methods
 
 
 NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGTSpanElement)
 
 
 //----------------------------------------------------------------------
--- a/content/svg/content/src/nsSVGTextContentElement.h
+++ b/content/svg/content/src/nsSVGTextContentElement.h
@@ -36,19 +36,35 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef __NS_SVGTEXTCONTENTELEMENTBASE_H__
 #define __NS_SVGTEXTCONTENTELEMENTBASE_H__
 
 #include "nsIDOMSVGTextContentElement.h"
 #include "nsSVGTextContainerFrame.h"
+#include "nsSVGStylableElement.h"
 
-class nsSVGTextContentElement
+typedef nsSVGStylableElement nsSVGTextContentElementBase;
+
+/**
+ * Note that nsSVGTextElement does not inherit nsSVGTextPositioningElement, or
+ * this class - it reimplements us instead (see its documenting comment). The
+ * upshot is that any changes to this class also need to be made in
+ * nsSVGTextElement.
+ */
+class nsSVGTextContentElement : public nsSVGTextContentElementBase
 {
 public:
   NS_DECL_NSIDOMSVGTEXTCONTENTELEMENT
 
 protected:
-  virtual nsSVGTextContainerFrame* GetTextContainerFrame()=0;
+
+  nsSVGTextContentElement(nsINodeInfo *aNodeInfo)
+    : nsSVGTextContentElementBase(aNodeInfo)
+  {}
+
+  nsSVGTextContainerFrame* GetTextContainerFrame() {
+    return do_QueryFrame(GetPrimaryFrame(Flush_Layout));
+  }
 };
 
 #endif
--- a/content/svg/content/src/nsSVGTextElement.cpp
+++ b/content/svg/content/src/nsSVGTextElement.cpp
@@ -39,53 +39,74 @@
 #include "nsSVGGraphicElement.h"
 #include "nsGkAtoms.h"
 #include "nsIDOMSVGTextElement.h"
 #include "nsCOMPtr.h"
 #include "nsSVGSVGElement.h"
 #include "nsSVGTextPositioningElement.h"
 #include "nsIFrame.h"
 #include "nsDOMError.h"
+#include "nsSVGLengthList.h"
+#include "nsSVGAnimatedLengthList.h"
+#include "nsSVGNumberList.h"
+#include "nsSVGAnimatedNumberList.h"
 
 typedef nsSVGGraphicElement nsSVGTextElementBase;
 
+/**
+ * This class does not inherit nsSVGTextPositioningElement - it reimplements it
+ * instead.
+ *
+ * Ideally this class would inherit nsSVGTextPositioningElement in addition to
+ * nsSVGGraphicElement, but we don't want two instances of nsSVGStylableElement
+ * and all the classes it inherits. Instead we choose to inherit one of the
+ * classes (nsSVGGraphicElement) and reimplement the missing pieces from the
+ * other (nsSVGTextPositioningElement (and thus nsSVGTextContentElement)). Care
+ * must be taken when making changes to the reimplemented pieces to keep
+ * nsSVGTextPositioningElement in sync (and vice versa).
+ */
 class nsSVGTextElement : public nsSVGTextElementBase,
-                         public nsIDOMSVGTextElement,
-                         public nsSVGTextPositioningElement // = nsIDOMSVGTextPositioningElement
+                         public nsIDOMSVGTextElement // nsIDOMSVGTextPositioningElement
 {
 protected:
   friend nsresult NS_NewSVGTextElement(nsIContent **aResult,
                                        nsINodeInfo *aNodeInfo);
   nsSVGTextElement(nsINodeInfo* aNodeInfo);
   nsresult Init();
   
 public:
   // interfaces:
   
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIDOMSVGTEXTELEMENT
+  NS_DECL_NSIDOMSVGTEXTPOSITIONINGELEMENT
+  NS_DECL_NSIDOMSVGTEXTCONTENTELEMENT
 
   // xxx If xpcom allowed virtual inheritance we wouldn't need to
   // forward here :-(
   NS_FORWARD_NSIDOMNODE(nsSVGTextElementBase::)
   NS_FORWARD_NSIDOMELEMENT(nsSVGTextElementBase::)
   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGTextElementBase::)
-  NS_FORWARD_NSIDOMSVGTEXTCONTENTELEMENT(nsSVGTextContentElement::)
-  NS_FORWARD_NSIDOMSVGTEXTPOSITIONINGELEMENT(nsSVGTextPositioningElement::)
 
   // nsIContent interface
   NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
 protected:
-  virtual nsSVGTextContainerFrame* GetTextContainerFrame() {
+  nsSVGTextContainerFrame* GetTextContainerFrame() {
     return do_QueryFrame(GetPrimaryFrame(Flush_Layout));
   }
 
+  // nsIDOMSVGTextPositioning properties:
+  nsCOMPtr<nsIDOMSVGAnimatedLengthList> mX;
+  nsCOMPtr<nsIDOMSVGAnimatedLengthList> mY;
+  nsCOMPtr<nsIDOMSVGAnimatedLengthList> mdX;
+  nsCOMPtr<nsIDOMSVGAnimatedLengthList> mdY;
+  nsCOMPtr<nsIDOMSVGAnimatedNumberList> mRotate;
 };
 
 
 NS_IMPL_NS_NEW_SVG_ELEMENT(Text)
 
 
 //----------------------------------------------------------------------
 // nsISupports methods
@@ -113,34 +134,280 @@ nsSVGTextElement::nsSVGTextElement(nsINo
 }
   
 nsresult
 nsSVGTextElement::Init()
 {
   nsresult rv = nsSVGTextElementBase::Init();
   NS_ENSURE_SUCCESS(rv,rv);
 
-  rv = Initialise(this);
-  NS_ENSURE_SUCCESS(rv,rv);
+  // DOM property: nsIDOMSVGTextPositioningElement::x, #IMPLIED attrib: x
+  {
+    nsCOMPtr<nsIDOMSVGLengthList> lengthList;
+    rv = NS_NewSVGLengthList(getter_AddRefs(lengthList), this, nsSVGUtils::X);
+    NS_ENSURE_SUCCESS(rv,rv);
+    rv = NS_NewSVGAnimatedLengthList(getter_AddRefs(mX),
+                                     lengthList);
+    NS_ENSURE_SUCCESS(rv,rv);
+    rv = AddMappedSVGValue(nsGkAtoms::x, mX);
+    NS_ENSURE_SUCCESS(rv,rv);
+  }
+
+  // DOM property: nsIDOMSVGTextPositioningElement::y, #IMPLIED attrib: y
+  {
+    nsCOMPtr<nsIDOMSVGLengthList> lengthList;
+    rv = NS_NewSVGLengthList(getter_AddRefs(lengthList), this, nsSVGUtils::Y);
+    NS_ENSURE_SUCCESS(rv,rv);
+    rv = NS_NewSVGAnimatedLengthList(getter_AddRefs(mY),
+                                     lengthList);
+    NS_ENSURE_SUCCESS(rv,rv);
+    rv = AddMappedSVGValue(nsGkAtoms::y, mY);
+    NS_ENSURE_SUCCESS(rv,rv);
+  }
+
+  // DOM property: nsIDOMSVGTextPositioningElement::dx, #IMPLIED attrib: dx
+  {
+    nsCOMPtr<nsIDOMSVGLengthList> lengthList;
+    rv = NS_NewSVGLengthList(getter_AddRefs(lengthList), this, nsSVGUtils::X);
+    NS_ENSURE_SUCCESS(rv,rv);
+    rv = NS_NewSVGAnimatedLengthList(getter_AddRefs(mdX),
+                                     lengthList);
+    NS_ENSURE_SUCCESS(rv,rv);
+    rv = AddMappedSVGValue(nsGkAtoms::dx, mdX);
+    NS_ENSURE_SUCCESS(rv,rv);
+  }
+
+  // DOM property: nsIDOMSVGTextPositioningElement::dy, #IMPLIED attrib: dy
+  {
+    nsCOMPtr<nsIDOMSVGLengthList> lengthList;
+    rv = NS_NewSVGLengthList(getter_AddRefs(lengthList), this, nsSVGUtils::Y);
+    NS_ENSURE_SUCCESS(rv,rv);
+    rv = NS_NewSVGAnimatedLengthList(getter_AddRefs(mdY),
+                                     lengthList);
+    NS_ENSURE_SUCCESS(rv,rv);
+    rv = AddMappedSVGValue(nsGkAtoms::dy, mdY);
+    NS_ENSURE_SUCCESS(rv,rv);
+  }
+
+  // DOM property: nsIDOMSVGTextPositioningElement::rotate, #IMPLIED attrib: rotate
+  {
+    nsCOMPtr<nsIDOMSVGNumberList> numberList;
+    rv = NS_NewSVGNumberList(getter_AddRefs(numberList));
+    NS_ENSURE_SUCCESS(rv,rv);
+    rv = NS_NewSVGAnimatedNumberList(getter_AddRefs(mRotate),
+                                     numberList);
+    NS_ENSURE_SUCCESS(rv,rv);
+    rv = AddMappedSVGValue(nsGkAtoms::rotate, mRotate);
+    NS_ENSURE_SUCCESS(rv,rv);
+  }
 
   return rv;
 }
 
 //----------------------------------------------------------------------
 // nsIDOMNode methods
 
 
 NS_IMPL_ELEMENT_CLONE_WITH_INIT(nsSVGTextElement)
 
 
 //----------------------------------------------------------------------
 // nsIDOMSVGTextElement methods
 
 // - no methods -
 
+
+//----------------------------------------------------------------------
+// nsIDOMSVGTextPositioningElement methods
+
+/* readonly attribute nsIDOMSVGAnimatedLengthList x; */
+NS_IMETHODIMP
+nsSVGTextElement::GetX(nsIDOMSVGAnimatedLengthList * *aX)
+{
+  *aX = mX;
+  NS_IF_ADDREF(*aX);
+  return NS_OK;
+}
+
+/* readonly attribute nsIDOMSVGAnimatedLengthList y; */
+NS_IMETHODIMP
+nsSVGTextElement::GetY(nsIDOMSVGAnimatedLengthList * *aY)
+{
+  *aY = mY;
+  NS_IF_ADDREF(*aY);
+  return NS_OK;
+}
+
+/* readonly attribute nsIDOMSVGAnimatedLengthList dx; */
+NS_IMETHODIMP
+nsSVGTextElement::GetDx(nsIDOMSVGAnimatedLengthList * *aDx)
+{
+  *aDx = mdX;
+  NS_IF_ADDREF(*aDx);
+  return NS_OK;
+}
+
+/* readonly attribute nsIDOMSVGAnimatedLengthList dy; */
+NS_IMETHODIMP
+nsSVGTextElement::GetDy(nsIDOMSVGAnimatedLengthList * *aDy)
+{
+  *aDy = mdY;
+  NS_IF_ADDREF(*aDy);
+  return NS_OK;
+}
+
+/* readonly attribute nsIDOMSVGAnimatedNumberList rotate; */
+NS_IMETHODIMP
+nsSVGTextElement::GetRotate(nsIDOMSVGAnimatedNumberList * *aRotate)
+{
+  *aRotate = mRotate;
+  NS_IF_ADDREF(*aRotate);
+  return NS_OK;
+}
+
+
+//----------------------------------------------------------------------
+// nsIDOMSVGTextContentElement methods
+
+/* readonly attribute nsIDOMSVGAnimatedLength textLength; */
+NS_IMETHODIMP
+nsSVGTextElement::GetTextLength(nsIDOMSVGAnimatedLength * *aTextLength)
+{
+  NS_NOTYETIMPLEMENTED("nsSVGTextElement::GetTextLength");
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* readonly attribute nsIDOMSVGAnimatedEnumeration lengthAdjust; */
+NS_IMETHODIMP
+nsSVGTextElement::GetLengthAdjust(nsIDOMSVGAnimatedEnumeration * *aLengthAdjust)
+{
+  NS_NOTYETIMPLEMENTED("nsSVGTextElement::GetLengthAdjust");
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/* long getNumberOfChars (); */
+NS_IMETHODIMP
+nsSVGTextElement::GetNumberOfChars(PRInt32 *_retval)
+{
+  *_retval = 0;
+
+  nsSVGTextContainerFrame* metrics = GetTextContainerFrame();
+  if (metrics)
+    *_retval = metrics->GetNumberOfChars();
+
+  return NS_OK;
+}
+
+/* float getComputedTextLength (); */
+NS_IMETHODIMP
+nsSVGTextElement::GetComputedTextLength(float *_retval)
+{
+  *_retval = 0.0;
+
+  nsSVGTextContainerFrame* metrics = GetTextContainerFrame();
+  if (metrics)
+    *_retval = metrics->GetComputedTextLength();
+
+  return NS_OK;
+}
+
+/* float getSubStringLength (in unsigned long charnum, in unsigned long nchars); */
+NS_IMETHODIMP
+nsSVGTextElement::GetSubStringLength(PRUint32 charnum, PRUint32 nchars, float *_retval)
+{
+  *_retval = 0.0f;
+  nsSVGTextContainerFrame* metrics = GetTextContainerFrame();
+  if (!metrics)
+    return NS_OK;
+
+  PRUint32 charcount = metrics->GetNumberOfChars();
+  if (charcount <= charnum || nchars > charcount - charnum)
+    return NS_ERROR_DOM_INDEX_SIZE_ERR;
+
+  if (nchars == 0)
+    return NS_OK;
+
+  *_retval = metrics->GetSubStringLength(charnum, nchars);
+  return NS_OK;
+}
+
+/* nsIDOMSVGPoint getStartPositionOfChar (in unsigned long charnum); */
+NS_IMETHODIMP
+nsSVGTextElement::GetStartPositionOfChar(PRUint32 charnum, nsIDOMSVGPoint **_retval)
+{
+  *_retval = nsnull;
+  nsSVGTextContainerFrame* metrics = GetTextContainerFrame();
+
+  if (!metrics) return NS_ERROR_FAILURE;
+
+  return metrics->GetStartPositionOfChar(charnum, _retval);
+}
+
+/* nsIDOMSVGPoint getEndPositionOfChar (in unsigned long charnum); */
+NS_IMETHODIMP
+nsSVGTextElement::GetEndPositionOfChar(PRUint32 charnum, nsIDOMSVGPoint **_retval)
+{
+  *_retval = nsnull;
+  nsSVGTextContainerFrame* metrics = GetTextContainerFrame();
+
+  if (!metrics) return NS_ERROR_FAILURE;
+
+  return metrics->GetEndPositionOfChar(charnum, _retval);
+}
+
+/* nsIDOMSVGRect getExtentOfChar (in unsigned long charnum); */
+NS_IMETHODIMP
+nsSVGTextElement::GetExtentOfChar(PRUint32 charnum, nsIDOMSVGRect **_retval)
+{
+  *_retval = nsnull;
+  nsSVGTextContainerFrame* metrics = GetTextContainerFrame();
+
+  if (!metrics) return NS_ERROR_FAILURE;
+
+  return metrics->GetExtentOfChar(charnum, _retval);
+}
+
+/* float getRotationOfChar (in unsigned long charnum); */
+NS_IMETHODIMP
+nsSVGTextElement::GetRotationOfChar(PRUint32 charnum, float *_retval)
+{
+  *_retval = 0.0;
+
+  nsSVGTextContainerFrame* metrics = GetTextContainerFrame();
+
+  if (!metrics) return NS_ERROR_FAILURE;
+
+  return metrics->GetRotationOfChar(charnum, _retval);
+}
+
+/* long getCharNumAtPosition (in nsIDOMSVGPoint point); */
+NS_IMETHODIMP
+nsSVGTextElement::GetCharNumAtPosition(nsIDOMSVGPoint *point, PRInt32 *_retval)
+{
+  if (!point)
+    return NS_ERROR_DOM_SVG_WRONG_TYPE_ERR;
+
+  *_retval = -1;
+
+  nsSVGTextContainerFrame* metrics = GetTextContainerFrame();
+  if (metrics)
+    *_retval = metrics->GetCharNumAtPosition(point);
+
+  return NS_OK;
+}
+
+/* void selectSubString (in unsigned long charnum, in unsigned long nchars); */
+NS_IMETHODIMP
+nsSVGTextElement::SelectSubString(PRUint32 charnum, PRUint32 nchars)
+{
+  NS_NOTYETIMPLEMENTED("nsSVGTextElement::SelectSubString");
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+
 //----------------------------------------------------------------------
 // nsIContent methods
 
 NS_IMETHODIMP_(PRBool)
 nsSVGTextElement::IsAttributeMapped(const nsIAtom* name) const
 {
   static const MappedAttributeEntry* const map[] = {
     sTextContentElementsMap,
--- a/content/svg/content/src/nsSVGTextPathElement.h
+++ b/content/svg/content/src/nsSVGTextPathElement.h
@@ -38,22 +38,21 @@
 #ifndef __NS_SVGTEXTPATHELEMENT_H__
 #define __NS_SVGTEXTPATHELEMENT_H__
 
 #include "nsSVGEnum.h"
 #include "nsSVGLength2.h"
 #include "nsSVGString.h"
 #include "nsSVGTextContentElement.h"
 
-typedef nsSVGStylableElement nsSVGTextPathElementBase;
+typedef nsSVGTextContentElement nsSVGTextPathElementBase;
 
-class nsSVGTextPathElement : public nsSVGTextPathElementBase,
+class nsSVGTextPathElement : public nsSVGTextPathElementBase, // = nsIDOMSVGTextContentElement
                              public nsIDOMSVGTextPathElement,
-                             public nsIDOMSVGURIReference,
-                             public nsSVGTextContentElement // = nsIDOMSVGTextContentElement
+                             public nsIDOMSVGURIReference
 {
 friend class nsSVGTextPathFrame;
 
 protected:
   friend nsresult NS_NewSVGTextPathElement(nsIContent **aResult,
                                         nsINodeInfo *aNodeInfo);
   nsSVGTextPathElement(nsINodeInfo* aNodeInfo);
   
@@ -64,29 +63,25 @@ public:
   NS_DECL_NSIDOMSVGTEXTPATHELEMENT
   NS_DECL_NSIDOMSVGURIREFERENCE
 
   // xxx If xpcom allowed virtual inheritance we wouldn't need to
   // forward here :-(
   NS_FORWARD_NSIDOMNODE(nsSVGTextPathElementBase::)
   NS_FORWARD_NSIDOMELEMENT(nsSVGTextPathElementBase::)
   NS_FORWARD_NSIDOMSVGELEMENT(nsSVGTextPathElementBase::)
-  NS_FORWARD_NSIDOMSVGTEXTCONTENTELEMENT(nsSVGTextContentElement::)
+  NS_FORWARD_NSIDOMSVGTEXTCONTENTELEMENT(nsSVGTextPathElementBase::)
 
   // nsIContent interface
   NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
 protected:
 
-  virtual nsSVGTextContainerFrame* GetTextContainerFrame() {
-    return do_QueryFrame(GetPrimaryFrame(Flush_Layout));
-  }
-
   virtual LengthAttributesInfo GetLengthInfo();
   virtual EnumAttributesInfo GetEnumInfo();
   virtual StringAttributesInfo GetStringInfo();
 
   virtual PRBool IsEventName(nsIAtom* aName);
 
   enum { STARTOFFSET };
   nsSVGLength2 mLengthAttributes[1];
--- a/content/svg/content/src/nsSVGTextPositioningElement.cpp
+++ b/content/svg/content/src/nsSVGTextPositioningElement.cpp
@@ -35,78 +35,80 @@
 
 #include "nsSVGTextPositioningElement.h"
 #include "nsSVGAnimatedLengthList.h"
 #include "nsSVGAnimatedNumberList.h"
 #include "nsSVGLengthList.h"
 #include "nsSVGNumberList.h"
 
 nsresult
-nsSVGTextPositioningElement::Initialise(nsSVGElement *aSVGElement)
+nsSVGTextPositioningElement::Init()
 {
-  nsresult rv;
+  nsresult rv = nsSVGTextPositioningElementBase::Init();
+  NS_ENSURE_SUCCESS(rv,rv);
+
   // Create mapped properties:
 
   // DOM property: nsIDOMSVGTextPositioningElement::x, #IMPLIED attrib: x
   {
     nsCOMPtr<nsIDOMSVGLengthList> lengthList;
-    rv = NS_NewSVGLengthList(getter_AddRefs(lengthList), aSVGElement, nsSVGUtils::X);
+    rv = NS_NewSVGLengthList(getter_AddRefs(lengthList), this, nsSVGUtils::X);
     NS_ENSURE_SUCCESS(rv,rv);
     rv = NS_NewSVGAnimatedLengthList(getter_AddRefs(mX),
                                      lengthList);
     NS_ENSURE_SUCCESS(rv,rv);
-    rv = aSVGElement->AddMappedSVGValue(nsGkAtoms::x, mX);
+    rv = AddMappedSVGValue(nsGkAtoms::x, mX);
     NS_ENSURE_SUCCESS(rv,rv);
   }
   
   // DOM property: nsIDOMSVGTextPositioningElement::y, #IMPLIED attrib: y
   {
     nsCOMPtr<nsIDOMSVGLengthList> lengthList;
-    rv = NS_NewSVGLengthList(getter_AddRefs(lengthList), aSVGElement, nsSVGUtils::Y);
+    rv = NS_NewSVGLengthList(getter_AddRefs(lengthList), this, nsSVGUtils::Y);
     NS_ENSURE_SUCCESS(rv,rv);
     rv = NS_NewSVGAnimatedLengthList(getter_AddRefs(mY),
                                      lengthList);
     NS_ENSURE_SUCCESS(rv,rv);
-    rv = aSVGElement->AddMappedSVGValue(nsGkAtoms::y, mY);
+    rv = AddMappedSVGValue(nsGkAtoms::y, mY);
     NS_ENSURE_SUCCESS(rv,rv);
   }
 
   // DOM property: nsIDOMSVGTextPositioningElement::dx, #IMPLIED attrib: dx
   {
     nsCOMPtr<nsIDOMSVGLengthList> lengthList;
-    rv = NS_NewSVGLengthList(getter_AddRefs(lengthList), aSVGElement, nsSVGUtils::X);
+    rv = NS_NewSVGLengthList(getter_AddRefs(lengthList), this, nsSVGUtils::X);
     NS_ENSURE_SUCCESS(rv,rv);
     rv = NS_NewSVGAnimatedLengthList(getter_AddRefs(mdX),
                                      lengthList);
     NS_ENSURE_SUCCESS(rv,rv);
-    rv = aSVGElement->AddMappedSVGValue(nsGkAtoms::dx, mdX);
+    rv = AddMappedSVGValue(nsGkAtoms::dx, mdX);
     NS_ENSURE_SUCCESS(rv,rv);
   }
   
   // DOM property: nsIDOMSVGTextPositioningElement::dy, #IMPLIED attrib: dy
   {
     nsCOMPtr<nsIDOMSVGLengthList> lengthList;
-    rv = NS_NewSVGLengthList(getter_AddRefs(lengthList), aSVGElement, nsSVGUtils::Y);
+    rv = NS_NewSVGLengthList(getter_AddRefs(lengthList), this, nsSVGUtils::Y);
     NS_ENSURE_SUCCESS(rv,rv);
     rv = NS_NewSVGAnimatedLengthList(getter_AddRefs(mdY),
                                      lengthList);
     NS_ENSURE_SUCCESS(rv,rv);
-    rv = aSVGElement->AddMappedSVGValue(nsGkAtoms::dy, mdY);
+    rv = AddMappedSVGValue(nsGkAtoms::dy, mdY);
     NS_ENSURE_SUCCESS(rv,rv);
   }
 
   // DOM property: nsIDOMSVGTextPositioningElement::rotate, #IMPLIED attrib: rotate
   {
     nsCOMPtr<nsIDOMSVGNumberList> numberList;
     rv = NS_NewSVGNumberList(getter_AddRefs(numberList));
     NS_ENSURE_SUCCESS(rv,rv);
     rv = NS_NewSVGAnimatedNumberList(getter_AddRefs(mRotate),
                                      numberList);
     NS_ENSURE_SUCCESS(rv,rv);
-    rv = aSVGElement->AddMappedSVGValue(nsGkAtoms::rotate, mRotate);
+    rv = AddMappedSVGValue(nsGkAtoms::rotate, mRotate);
     NS_ENSURE_SUCCESS(rv,rv);
   }
 
   return rv;
 }
 
 //----------------------------------------------------------------------
 // nsIDOMSVGTextPositioningElement methods
--- a/content/svg/content/src/nsSVGTextPositioningElement.h
+++ b/content/svg/content/src/nsSVGTextPositioningElement.h
@@ -36,23 +36,37 @@
 #ifndef __NS_SVGTEXTPOSITIONINGELEMENTBASE_H__
 #define __NS_SVGTEXTPOSITIONINGELEMENTBASE_H__
 
 #include "nsIDOMSVGTextPositionElem.h"
 #include "nsSVGTextContentElement.h"
 #include "nsIDOMSVGAnimatedLengthList.h"
 #include "nsIDOMSVGAnimatedNumberList.h"
 
-class nsSVGTextPositioningElement : public nsSVGTextContentElement
+class nsSVGElement;
+
+typedef nsSVGTextContentElement nsSVGTextPositioningElementBase;
+
+/**
+ * Note that nsSVGTextElement does not inherit this class - it reimplements it
+ * instead (see its documenting comment). The upshot is that any changes to
+ * this class also need to be made in nsSVGTextElement.
+ */
+class nsSVGTextPositioningElement : public nsSVGTextPositioningElementBase
 {
 public:
   NS_DECL_NSIDOMSVGTEXTPOSITIONINGELEMENT
 
 protected:
-  nsresult Initialise(nsSVGElement *aSVGElement);
+
+  nsSVGTextPositioningElement(nsINodeInfo *aNodeInfo)
+    : nsSVGTextPositioningElementBase(aNodeInfo)
+  {}
+
+  nsresult Init();
 
   // nsIDOMSVGTextPositioning properties:
   nsCOMPtr<nsIDOMSVGAnimatedLengthList> mX;
   nsCOMPtr<nsIDOMSVGAnimatedLengthList> mY;
   nsCOMPtr<nsIDOMSVGAnimatedLengthList> mdX;
   nsCOMPtr<nsIDOMSVGAnimatedLengthList> mdY;
   nsCOMPtr<nsIDOMSVGAnimatedNumberList> mRotate;
 };
--- a/content/xul/templates/src/nsXULTreeBuilder.cpp
+++ b/content/xul/templates/src/nsXULTreeBuilder.cpp
@@ -1703,22 +1703,19 @@ nsresult
 nsXULTreeBuilder::CloseContainer(PRInt32 aIndex)
 {
     NS_ASSERTION(aIndex >= 0 && aIndex < mRows.Count(), "bad row");
     if (aIndex < 0 || aIndex >= mRows.Count())
         return NS_ERROR_INVALID_ARG;
 
     nsTreeRows::iterator iter = mRows[aIndex];
 
-    nsTreeRows::Subtree& subtree = *(iter->mSubtree);
+    if (iter->mSubtree)
+        RemoveMatchesFor(*iter->mSubtree);
 
-    RemoveMatchesFor(subtree);
-
-    // Update the view
-    iter = mRows[aIndex];
 
     PRInt32 count = mRows.GetSubtreeSizeFor(iter);
     mRows.RemoveSubtreeFor(iter);
 
     iter->mContainerState = nsTreeRows::eContainerState_Closed;
 
     if (mBoxObject) {
         mBoxObject->InvalidateRow(aIndex);
--- a/docshell/resources/content/netError.xhtml
+++ b/docshell/resources/content/netError.xhtml
@@ -115,17 +115,17 @@
       {
         // Session history has the URL of the page that failed
         // to load, not the one of the error page. So, just call
         // reload(), which will also repost POST data correctly.
         try {
           location.reload();
         } catch (e) {
           // We probably tried to reload a URI that caused an exception to
-          // occur;  e.g. a non-existent file.
+          // occur;  e.g. a nonexistent file.
         }
 
         buttonEl.disabled = true;
       }
 
       function initPage()
       {
         var err = getErrorCode();
--- a/docshell/test/test_bug529119-1.html
+++ b/docshell/test/test_bug529119-1.html
@@ -6,17 +6,17 @@
 <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>        
 <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
 
 <script class="testbody" type="text/javascript">
 
 SimpleTest.waitForExplicitFinish();
 
 var workingURL = "http://mochi.test:8888/tests/docshell/test/bug529119-window.html";
-var faultyURL = "http://some-non-existent-domain-27489274c892748217cn2384.com/";
+var faultyURL = "http://some-nonexistent-domain-27489274c892748217cn2384.com/";
 
 var w = null;
 var phase = 0;
 var gotWrongPageOnTryAgainClick = false;
 
 function pollForPage(f, w)
 {
   // Start with polling after a delay, we might mistakenly take the current page
--- a/docshell/test/test_bug529119-2.html
+++ b/docshell/test/test_bug529119-2.html
@@ -6,17 +6,17 @@
 <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>        
 <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
 
 <script class="testbody" type="text/javascript">
 
 SimpleTest.waitForExplicitFinish();
 
 var workingURL = "http://mochi.test:8888/tests/docshell/test/bug529119-window.html";
-var faultyURL = "http://some-non-existent-domain-27489274c892748217cn2384.com/";
+var faultyURL = "http://some-nonexistent-domain-27489274c892748217cn2384.com/";
 
 var w = null;
 var phase = 0;
 
 function pollForPage(expectErrorPage, f, w)
 {
   // Start with polling after a delay, we might mistakenly take the current page
   // as an expected one.
--- a/dom/src/storage/nsDOMStorage.cpp
+++ b/dom/src/storage/nsDOMStorage.cpp
@@ -1294,17 +1294,17 @@ nsDOMStorage::SetSecure(const nsAString&
 
     return gStorageDB->SetSecure(this, aKey, aSecure);
   }
 #else
   return NS_ERROR_NOT_IMPLEMENTED;
 #endif
 
   nsSessionStorageEntry *entry = mItems.GetEntry(aKey);
-  NS_ASSERTION(entry, "Don't use SetSecure() with non-existing keys!");
+  NS_ASSERTION(entry, "Don't use SetSecure() with nonexistent keys!");
 
   if (entry) {
     entry->mItem->SetSecureInternal(aSecure);
   }  
 
   return NS_OK;
 }
 
--- a/editor/libeditor/html/nsHTMLAbsPosition.cpp
+++ b/editor/libeditor/html/nsHTMLAbsPosition.cpp
@@ -495,17 +495,17 @@ nsHTMLEditor::SetFinalPosition(PRInt32 a
   // keep track of that size
   mPositionedObjectX  = newX;
   mPositionedObjectY  = newY;
 
   return RefreshResizers();
 }
 
 void
-nsHTMLEditor::AddPositioningOffet(PRInt32 & aX, PRInt32 & aY)
+nsHTMLEditor::AddPositioningOffset(PRInt32 & aX, PRInt32 & aY)
 {
   // Get the positioning offset
   nsresult res;
   nsCOMPtr<nsIPrefBranch> prefBranch =
     do_GetService(NS_PREFSERVICE_CONTRACTID, &res);
   PRInt32 positioningOffset = 0;
   if (NS_SUCCEEDED(res) && prefBranch) {
     res = prefBranch->GetIntPref("editor.positioning.offset", &positioningOffset);
@@ -539,17 +539,17 @@ nsHTMLEditor::AbsolutelyPositionElement(
     PRInt32 x, y;
     GetElementOrigin(aElement, x, y);
 
     mHTMLCSSUtils->SetCSSProperty(aElement,
                                   nsEditProperty::cssPosition,
                                   NS_LITERAL_STRING("absolute"),
                                   PR_FALSE);
 
-    AddPositioningOffet(x, y);
+    AddPositioningOffset(x, y);
     SnapToGrid(x, y);
     SetElementPosition(aElement, x, y);
 
     // we may need to create a br if the positioned element is alone in its
     // container
     nsCOMPtr<nsIDOMNode> parentNode;
     res = aElement->GetParentNode(getter_AddRefs(parentNode));
     if (NS_FAILED(res)) return res;
--- a/editor/libeditor/html/nsHTMLEditor.h
+++ b/editor/libeditor/html/nsHTMLEditor.h
@@ -501,17 +501,17 @@ protected:
   NS_IMETHOD SplitCellIntoColumns(nsIDOMElement *aTable, PRInt32 aRowIndex, PRInt32 aColIndex,
                                   PRInt32 aColSpanLeft, PRInt32 aColSpanRight, nsIDOMElement **aNewCell);
 
   NS_IMETHOD SplitCellIntoRows(nsIDOMElement *aTable, PRInt32 aRowIndex, PRInt32 aColIndex,
                                PRInt32 aRowSpanAbove, PRInt32 aRowSpanBelow, nsIDOMElement **aNewCell);
 
   nsresult CopyCellBackgroundColor(nsIDOMElement *destCell, nsIDOMElement *sourceCell);
 
-  // Reduce rowspan/colspan when cells span into non-existent rows/columns
+  // Reduce rowspan/colspan when cells span into nonexistent rows/columns
   NS_IMETHOD FixBadRowSpan(nsIDOMElement *aTable, PRInt32 aRowIndex, PRInt32& aNewRowCount);
   NS_IMETHOD FixBadColSpan(nsIDOMElement *aTable, PRInt32 aColIndex, PRInt32& aNewColCount);
 
   // Fallback method: Call this after using ClearSelection() and you
   //  failed to set selection to some other content in the document
   NS_IMETHOD SetSelectionAtDocumentStart(nsISelection *aSelection);
 
 // End of Table Editing utilities
@@ -902,17 +902,17 @@ protected:
   nsCOMPtr<nsIDOMElement> mGrabber;
   nsCOMPtr<nsIDOMElement> mPositioningShadow;
 
   PRInt32      mGridSize;
 
   nsresult CreateGrabber(nsIDOMNode * aParentNode, nsIDOMElement ** aReturn);
   nsresult StartMoving(nsIDOMElement * aHandle);
   nsresult SetFinalPosition(PRInt32 aX, PRInt32 aY);
-  void     AddPositioningOffet(PRInt32 & aX, PRInt32 & aY);
+  void     AddPositioningOffset(PRInt32 & aX, PRInt32 & aY);
   void     SnapToGrid(PRInt32 & newX, PRInt32 & newY);
   nsresult GrabberClicked();
   nsresult EndMoving();
   nsresult CheckPositionedElementBGandFG(nsIDOMElement * aElement,
                                          nsAString & aReturn);
 
   /* INLINE TABLE EDITING */
 
--- a/editor/libeditor/html/nsWSRunObject.h
+++ b/editor/libeditor/html/nsWSRunObject.h
@@ -316,22 +316,22 @@ class NS_STACK_CLASS nsWSRunObject
     
     // member variables ---------------------------------------------------------
     
     nsCOMPtr<nsIDOMNode> mNode;           // the node passed to our constructor
     PRInt32 mOffset;                      // the offset passed to our contructor
     // together, the above represent the point at which we are building up ws info.
     
     PRBool  mPRE;                         // true if we are in preformatted whitespace context
-    nsCOMPtr<nsIDOMNode> mStartNode;      // node/offet where ws starts
+    nsCOMPtr<nsIDOMNode> mStartNode;      // node/offset where ws starts
     PRInt32 mStartOffset;                 // ...
     PRInt16 mStartReason;                 // reason why ws starts (eText, eOtherBlock, etc)
     nsCOMPtr<nsIDOMNode> mStartReasonNode;// the node that implicated by start reason
     
-    nsCOMPtr<nsIDOMNode> mEndNode;        // node/offet where ws ends
+    nsCOMPtr<nsIDOMNode> mEndNode;        // node/offset where ws ends
     PRInt32 mEndOffset;                   // ...
     PRInt16 mEndReason;                   // reason why ws ends (eText, eOtherBlock, etc)
     nsCOMPtr<nsIDOMNode> mEndReasonNode;  // the node that implicated by end reason
     
     nsCOMPtr<nsIDOMNode> mFirstNBSPNode;  // location of first nbsp in ws run, if any
     PRInt32 mFirstNBSPOffset;             // ...
     
     nsCOMPtr<nsIDOMNode> mLastNBSPNode;   // location of last nbsp in ws run, if any
--- a/editor/libeditor/html/tests/browserscope/lib/browserscope/README
+++ b/editor/libeditor/html/tests/browserscope/lib/browserscope/README
@@ -13,17 +13,17 @@ http://code.google.com/appengine/downloa
 For local development, just startup the server:
 ./pathto/google_appengine/dev_appserver.py --port=8080 browserscope
 
 You should then be able to access the local application at:
 http://localhost:8080/
 
 Note: the first time you hit the homepage it may take a little
 while - that's because it's trying to read out median times for all
-of the tests from a non-existent datastore and write to memcache.
+of the tests from a nonexistent datastore and write to memcache.
 Just be a lil patient.
 
 You can run the unit tests at:
   http://localhost:8080/test
 
 
 CONTRIBUTING
 ------------------
--- a/embedding/browser/webBrowser/nsWebBrowser.cpp
+++ b/embedding/browser/webBrowser/nsWebBrowser.cpp
@@ -1661,16 +1661,29 @@ NS_IMETHODIMP nsWebBrowser::EnsureDocShe
    NS_ENSURE_TRUE(mDocShellTreeOwner, NS_ERROR_OUT_OF_MEMORY);
 
    NS_ADDREF(mDocShellTreeOwner);
    mDocShellTreeOwner->WebBrowser(this);
    
    return NS_OK;
 }
 
+static void DrawThebesLayer(ThebesLayer* aLayer,
+                            gfxContext* aContext,
+                            const nsIntRegion& aRegionToDraw,
+                            void* aCallbackData)
+{
+  nscolor* color = static_cast<nscolor*>(aCallbackData);
+  aContext->NewPath();
+  aContext->SetColor(gfxRGBA(*color));
+  nsIntRect dirtyRect = aRegionToDraw.GetBounds();
+  aContext->Rectangle(gfxRect(dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height));
+  aContext->Fill();  
+}
+
 /* static */
 nsEventStatus nsWebBrowser::HandleEvent(nsGUIEvent *aEvent)
 {
   nsWebBrowser  *browser = nsnull;
   void          *data = nsnull;
   nsIWidget     *widget = aEvent->widget;
 
   if (!widget)
@@ -1691,29 +1704,17 @@ nsEventStatus nsWebBrowser::HandleEvent(
       layerManager->BeginTransaction();
       nsRefPtr<ThebesLayer> root = layerManager->CreateThebesLayer();
       nsPaintEvent* paintEvent = static_cast<nsPaintEvent*>(aEvent);
       nsIntRect dirtyRect = paintEvent->region.GetBounds();
       if (root) {
           root->SetVisibleRegion(dirtyRect);
           layerManager->SetRoot(root);
       }
-      layerManager->EndConstruction();
-      if (root) {
-          nsIntRegion toDraw;
-          gfxContext* ctx = root->BeginDrawing(&toDraw);
-          if (ctx) {
-              ctx->NewPath();
-              ctx->SetColor(gfxRGBA(browser->mBackgroundColor));
-              ctx->Rectangle(gfxRect(dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height));
-              ctx->Fill();
-          }
-      }
-      root->EndDrawing();
-      layerManager->EndTransaction();
+      layerManager->EndTransaction(DrawThebesLayer, &browser->mBackgroundColor);
       return nsEventStatus_eConsumeDoDefault;
     }
 
   case NS_ACTIVATE: {
 #if defined(DEBUG_smaug)
     nsCOMPtr<nsIDOMDocument> domDocument = do_GetInterface(browser->mDocShell);
     nsAutoString documentURI;
     if (domDocument) {
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -117,17 +117,18 @@ class CanvasLayer;
  * root layer, and each container layer holds a reference to its children.
  */
 class THEBES_API LayerManager {
   NS_INLINE_DECL_REFCOUNTING(LayerManager)
 
 public:
   enum LayersBackend {
     LAYERS_BASIC = 0,
-    LAYERS_OPENGL
+    LAYERS_OPENGL,
+    LAYERS_D3D9
   };
 
   virtual ~LayerManager() {}
 
   /**
    * Start a new transaction. Nested transactions are not allowed so
    * there must be no transaction currently in progress.
    * This transaction will update the state of the window from which
@@ -138,24 +139,39 @@ public:
    * Start a new transaction. Nested transactions are not allowed so
    * there must be no transaction currently in progress. 
    * This transaction will render the contents of the layer tree to
    * the given target context. The rendering will be complete when
    * EndTransaction returns.
    */
   virtual void BeginTransactionWithTarget(gfxContext* aTarget) = 0;
   /**
-   * Finish the construction phase of the transaction and enter the
-   * drawing phase.
+   * Function called to draw the contents of each ThebesLayer.
+   * aRegionToDraw contains the region that needs to be drawn.
+   * This would normally be a subregion of the visible region. Drawing is
+   * not necessarily clipped to aRegionToDraw.
+   * The callee must draw all of aRegionToDraw.
+   * 
+   * aContext must not be used after the call has returned.
+   * We guarantee that buffered contents in the visible
+   * region are valid once drawing is complete.
    */
-  virtual void EndConstruction() = 0;
+  typedef void (* DrawThebesLayerCallback)(ThebesLayer* aLayer,
+                                           gfxContext* aContext,
+                                           const nsIntRegion& aRegionToDraw,
+                                           void* aCallbackData);
   /**
-   * Complete the transaction.
+   * Finish the construction phase of the transaction, perform the
+   * drawing phase, and end the transaction.
+   * During the drawing phase, all ThebesLayers in the tree are
+   * drawn in tree order, exactly once each, except for those layers
+   * where it is known that the visible region is empty.
    */
-  virtual void EndTransaction() = 0;
+  virtual void EndTransaction(DrawThebesLayerCallback aCallback,
+                              void* aCallbackData) = 0;
 
   /**
    * CONSTRUCTION PHASE ONLY
    * Set the root layer.
    */
   virtual void SetRoot(Layer* aLayer) = 0;
 
   /**
@@ -192,16 +208,18 @@ public:
   /**
    * Type of layer manager his is. This is to be used sparsely in order to
    * avoid a lot of Layers backend specific code. It should be used only when
    * Layers backend specific functionality is necessary.
    */
   virtual LayersBackend GetBackendType() = 0;
 };
 
+class ThebesLayer;
+
 /**
  * A Layer represents anything that can be rendered onto a destination
  * surface.
  */
 class THEBES_API Layer {
   NS_INLINE_DECL_REFCOUNTING(Layer)  
 
 public:
@@ -293,16 +311,22 @@ public:
   virtual Layer* GetFirstChild() { return nsnull; }
   const gfx3DMatrix& GetTransform() { return mTransform; }
 
   // This setter and getter can be used anytime.
   void SetUserData(void* aData) { mUserData = aData; }
   void* GetUserData() { return mUserData; }
 
   /**
+   * Dynamic downcast to a Thebes layer. Returns null if this is not
+   * a ThebesLayer.
+   */
+  virtual ThebesLayer* AsThebesLayer() { return nsnull; }
+  
+  /**
    * Only the implementation should call this. This is per-implementation
    * private data. Normally, all layers with a given layer manager
    * use the same type of ImplData.
    */
   void* ImplData() { return mImplData; }
 
   /**
    * Only the implementation should use these methods.
@@ -353,46 +377,17 @@ public:
   /**
    * CONSTRUCTION PHASE ONLY
    * Tell this layer that the content in some region has changed and
    * will need to be repainted. This area is removed from the valid
    * region.
    */
   virtual void InvalidateRegion(const nsIntRegion& aRegion) = 0;
 
-  /**
-   * DRAWING PHASE ONLY
-   * Start drawing into the layer. On return, aRegionToDraw contains the
-   * region that needs to be drawn in by the caller. This would normally
-   * be a subregion of the visible region. Drawing is not necessarily
-   * clipped to aRegionToDraw.
-   * 
-   * No other layer operations are allowed until we call EndDrawing on this
-   * layer. During the drawing phase, all ThebesLayers in the tree must be
-   * drawn in tree order, exactly once each, except for those layers
-   * where it is known that the visible region is empty. (Calling
-   * BeginDrawing on non-visible layers is allowed, but aRegionToDraw
-   * will return empty.)
-   * 
-   * When an empty region is returned in aRegionToDraw, BeginDrawing
-   * may return a null context.
-   * 
-   * The layer system will hold a reference to the returned gfxContext*
-   * until EndDrawing is called. The returned gfxContext must not be used
-   * after EndDrawing is called.
-   */
-  virtual gfxContext* BeginDrawing(nsIntRegion* aRegionToDraw) = 0;
-  /**
-   * DRAWING PHASE ONLY
-   * We've finished drawing into this layer. At this point the caller
-   * must have drawn all of aRegionToDraw that was returned by
-   * BeginDrawing, and we guarantee that buffered contents in the visible
-   * region are now valid.
-   */
-  virtual void EndDrawing() = 0;
+  virtual ThebesLayer* AsThebesLayer() { return this; }
 
 protected:
   ThebesLayer(LayerManager* aManager, void* aImplData)
     : Layer(aManager, aImplData) {}
 };
 
 /**
  * A Layer which other layers render into. It holds references to its
--- a/gfx/layers/Makefile.in
+++ b/gfx/layers/Makefile.in
@@ -37,26 +37,30 @@
 
 DEPTH       = ../..
 topsrcdir   = @top_srcdir@
 srcdir      = @srcdir@
 VPATH       = \
   $(srcdir) \
   $(srcdir)/basic \
   $(srcdir)/opengl \
+  $(srcdir)/d3d9 \
   $(NULL)
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE         = thebes
 LIBRARY_NAME   = layers
 LIBXUL_LIBRARY = 1
 FORCE_STATIC_LIB = 1
 
 DEFINES += -DIMPL_THEBES
+ifdef MOZ_DEBUG
+DEFINES += -DD3D_DEBUG_INFO
+endif
 
 EXPORTS = \
         BasicLayers.h \
         ImageLayers.h \
         Layers.h \
         LayerManagerOGL.h \
         $(NULL)
 
@@ -65,12 +69,27 @@ CPPSRCS = \
         BasicLayers.cpp \
         LayerManagerOGL.cpp \
         ColorLayerOGL.cpp \
         ThebesLayerOGL.cpp \
         ContainerLayerOGL.cpp \
         ImageLayerOGL.cpp \
 	CanvasLayerOGL.cpp \
         $(NULL)
+ 
+ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
+ifndef WINCE
+EXPORTS += LayerManagerD3D9.h
+
+CPPSRCS += \
+        LayerManagerD3D9.cpp \
+        ThebesLayerD3D9.cpp \
+        ContainerLayerD3D9.cpp \
+        ImageLayerD3D9.cpp \
+        ColorLayerD3D9.cpp \
+        CanvasLayerD3D9.cpp \
+        $(NULL)
+endif
+endif
 
 include $(topsrcdir)/config/rules.mk
 
 CXXFLAGS += $(MOZ_CAIRO_CFLAGS)
--- a/gfx/layers/basic/BasicLayers.cpp
+++ b/gfx/layers/basic/BasicLayers.cpp
@@ -89,17 +89,19 @@ public:
   const nsIntRegion& GetVisibleRegion() { return mVisibleRegion; }
 
   /**
    * Layers that paint themselves, such as ImageLayers, should paint
    * in response to this method call. aContext will already have been
    * set up to account for all the properties of the layer (transform,
    * opacity, etc).
    */
-  virtual void Paint(gfxContext* aContext) {}
+  virtual void Paint(gfxContext* aContext,
+                     LayerManager::DrawThebesLayerCallback aCallback,
+                     void* aCallbackData) {}
 
 protected:
   nsIntRegion mVisibleRegion;
 };
 
 static BasicImplData*
 ToData(Layer* aLayer)
 {
@@ -235,50 +237,38 @@ public:
     mVisibleRegion = aRegion;
   }
   virtual void InvalidateRegion(const nsIntRegion& aRegion)
   {
     NS_ASSERTION(BasicManager()->InConstruction(),
                  "Can only set properties in construction phase");
   }
 
-  virtual gfxContext* BeginDrawing(nsIntRegion* aRegionToDraw);
-  virtual void EndDrawing();
+  virtual void Paint(gfxContext* aContext,
+                     LayerManager::DrawThebesLayerCallback aCallback,
+                     void* aCallbackData);
 
 protected:
   BasicLayerManager* BasicManager()
   {
     return static_cast<BasicLayerManager*>(mManager);
   }
 };
 
-gfxContext*
-BasicThebesLayer::BeginDrawing(nsIntRegion* aRegionToDraw)
+void
+BasicThebesLayer::Paint(gfxContext* aContext,
+                        LayerManager::DrawThebesLayerCallback aCallback,
+                        void* aCallbackData)
 {
-  NS_ASSERTION(BasicManager()->IsBeforeInTree(BasicManager()->GetLastPainted(), this),
-               "Painting layers out of order");
   NS_ASSERTION(BasicManager()->InDrawing(),
                "Can only draw in drawing phase");
   gfxContext* target = BasicManager()->GetTarget();
-  if (!target)
-    return nsnull;
-
-  BasicManager()->AdvancePaintingTo(this);
+  NS_ASSERTION(target, "We shouldn't be called if there's no target");
 
-  *aRegionToDraw = mVisibleRegion;
-  return target;
-}
-
-void
-BasicThebesLayer::EndDrawing()
-{
-  NS_ASSERTION(BasicManager()->InDrawing(),
-               "Can only draw in drawing phase");
-  NS_ASSERTION(BasicManager()->GetLastPainted() == this,
-               "Not currently drawing this layer");
+  aCallback(this, target, mVisibleRegion, aCallbackData);
 }
 
 class BasicImageLayer : public ImageLayer, BasicImplData {
 public:
   BasicImageLayer(BasicLayerManager* aLayerManager) :
     ImageLayer(aLayerManager, static_cast<BasicImplData*>(this))
   {
     MOZ_COUNT_CTOR(BasicImageLayer);
@@ -290,27 +280,31 @@ public:
 
   virtual void SetVisibleRegion(const nsIntRegion& aRegion)
   {
     NS_ASSERTION(BasicManager()->InConstruction(),
                  "Can only set properties in construction phase");
     mVisibleRegion = aRegion;
   }
 
-  virtual void Paint(gfxContext* aContext);
+  virtual void Paint(gfxContext* aContext,
+                     LayerManager::DrawThebesLayerCallback aCallback,
+                     void* aCallbackData);
 
 protected:
   BasicLayerManager* BasicManager()
   {
     return static_cast<BasicLayerManager*>(mManager);
   }
 };
 
 void
-BasicImageLayer::Paint(gfxContext* aContext)
+BasicImageLayer::Paint(gfxContext* aContext,
+                       LayerManager::DrawThebesLayerCallback aCallback,
+                       void* aCallbackData)
 {
   if (!mContainer)
     return;
 
   gfxIntSize size;
   nsRefPtr<gfxASurface> surface = mContainer->GetCurrentAsSurface(&size);
   if (!surface) {
     return;
@@ -360,27 +354,31 @@ public:
 
   virtual void SetVisibleRegion(const nsIntRegion& aRegion)
   {
     NS_ASSERTION(BasicManager()->InConstruction(),
                  "Can only set properties in construction phase");
     mVisibleRegion = aRegion;
   }
 
-  virtual void Paint(gfxContext* aContext);
+  virtual void Paint(gfxContext* aContext,
+                     LayerManager::DrawThebesLayerCallback aCallback,
+                     void* aCallbackData);
 
 protected:
   BasicLayerManager* BasicManager()
   {
     return static_cast<BasicLayerManager*>(mManager);
   }
 };
 
 void
-BasicColorLayer::Paint(gfxContext* aContext)
+BasicColorLayer::Paint(gfxContext* aContext,
+                       LayerManager::DrawThebesLayerCallback aCallback,
+                       void* aCallbackData)
 {
   aContext->SetColor(mColor);
   aContext->Paint();
 }
 
 class BasicCanvasLayer : public CanvasLayer,
                          BasicImplData
 {
@@ -392,17 +390,19 @@ public:
   }
   virtual ~BasicCanvasLayer()
   {
     MOZ_COUNT_DTOR(BasicCanvasLayer);
   }
 
   virtual void Initialize(const Data& aData);
   virtual void Updated(const nsIntRect& aRect);
-  virtual void Paint(gfxContext* aContext);
+  virtual void Paint(gfxContext* aContext,
+                     LayerManager::DrawThebesLayerCallback aCallback,
+                     void* aCallbackData);
 
 protected:
   nsRefPtr<gfxASurface> mSurface;
   nsRefPtr<mozilla::gl::GLContext> mGLContext;
 
   nsIntRect mBounds;
   nsIntRect mUpdatedRect;
 
@@ -479,17 +479,19 @@ BasicCanvasLayer::Updated(const nsIntRec
   }
 
   // sanity
   NS_ASSERTION(mUpdatedRect.IsEmpty() || mBounds.Contains(mUpdatedRect),
                "CanvasLayer: Updated rect bigger than bounds!");
 }
 
 void
-BasicCanvasLayer::Paint(gfxContext* aContext)
+BasicCanvasLayer::Paint(gfxContext* aContext,
+                        LayerManager::DrawThebesLayerCallback aCallback,
+                        void* aCallbackData)
 {
   nsRefPtr<gfxPattern> pat = new gfxPattern(mSurface);
 
   pat->SetFilter(mFilter);
   pat->SetExtend(gfxPattern::EXTEND_PAD);
 
   gfxRect r(0, 0, mBounds.width, mBounds.height);
   gfxMatrix m;
@@ -506,17 +508,17 @@ BasicCanvasLayer::Paint(gfxContext* aCon
   if (mNeedsYFlip) {
     aContext->SetMatrix(m);
   }
 
   mUpdatedRect.Empty();
 }
 
 BasicLayerManager::BasicLayerManager(gfxContext* aContext) :
-  mDefaultTarget(aContext), mLastPainted(nsnull)
+  mDefaultTarget(aContext)
 #ifdef DEBUG
   , mPhase(PHASE_NONE)
 #endif
 {
   MOZ_COUNT_CTOR(BasicLayerManager);
 }
 
 BasicLayerManager::~BasicLayerManager()
@@ -549,34 +551,33 @@ BasicLayerManager::BeginTransactionWithT
   NS_ASSERTION(mPhase == PHASE_NONE, "Nested transactions not allowed");
 #ifdef DEBUG
   mPhase = PHASE_CONSTRUCTION;
 #endif
   mTarget = aTarget;
 }
 
 void
-BasicLayerManager::EndConstruction()
+BasicLayerManager::EndTransaction(DrawThebesLayerCallback aCallback,
+                                  void* aCallbackData)
 {
   NS_ASSERTION(mRoot, "Root not set");
   NS_ASSERTION(mPhase == PHASE_CONSTRUCTION, "Should be in construction phase");
 #ifdef DEBUG
   mPhase = PHASE_DRAWING;
 #endif
-}
 
-void
-BasicLayerManager::EndTransaction()
-{
-  NS_ASSERTION(mPhase == PHASE_DRAWING, "Should be in drawing phase");
+  if (mTarget) {
+    PaintLayer(mRoot, aCallback, aCallbackData);
+    mTarget = nsnull;
+  }
+
 #ifdef DEBUG
   mPhase = PHASE_NONE;
 #endif
-  AdvancePaintingTo(nsnull);
-  mTarget = nsnull;
   // No retained layers supported for now
   mRoot = nsnull;
 }
 
 void
 BasicLayerManager::SetRoot(Layer* aLayer)
 {
   NS_ASSERTION(aLayer, "Root can't be null");
@@ -620,20 +621,24 @@ UseOpaqueSurface(Layer* aLayer)
   // in the container.
   BasicContainerLayer* parent =
     static_cast<BasicContainerLayer*>(aLayer->GetParent());
   return parent && parent->GetFirstChild() == aLayer &&
          UseOpaqueSurface(parent);
 }
 
 void
-BasicLayerManager::BeginPaintingLayer(Layer* aLayer)
+BasicLayerManager::PaintLayer(Layer* aLayer,
+                              DrawThebesLayerCallback aCallback,
+                              void* aCallbackData)
 {
   PRBool needsGroup = NeedsGroup(aLayer);
-  if ((needsGroup || NeedsState(aLayer)) && mTarget) {
+  PRBool needsSaveRestore = needsGroup || NeedsState(aLayer);
+
+ if (needsSaveRestore) {
     mTarget->Save();
 
     if (aLayer->GetClipRect()) {
       const nsIntRect& r = *aLayer->GetClipRect();
       mTarget->NewPath();
       mTarget->Rectangle(gfxRect(r.x, r.y, r.width, r.height), PR_TRUE);
       mTarget->Clip();
     }
@@ -662,76 +667,32 @@ BasicLayerManager::BeginPaintingLayer(La
       mTarget->SetMatrix(currentMatrix);
 
       gfxASurface::gfxContentType type = UseOpaqueSurface(aLayer)
           ? gfxASurface::CONTENT_COLOR : gfxASurface::CONTENT_COLOR_ALPHA;
       mTarget->PushGroup(type);
     }
   }
 
-  mLastPainted = aLayer;
+  ToData(aLayer)->Paint(mTarget, aCallback, aCallbackData);
+  for (Layer* child = aLayer->GetFirstChild(); child;
+       child = child->GetNextSibling()) {
+    PaintLayer(child, aCallback, aCallbackData);
+  }
 
-  // For layers that paint themselves (e.g., BasicImageLayer), paint
-  // them now.
-  ToData(aLayer)->Paint(mTarget);
-}
-
-void
-BasicLayerManager::EndPaintingLayer()
-{
-  PRBool needsGroup = NeedsGroup(mLastPainted);
-  if ((needsGroup || NeedsState(mLastPainted)) && mTarget) {
+  if (needsSaveRestore) {
     if (needsGroup) {
       mTarget->PopGroupToSource();
-      mTarget->Paint(mLastPainted->GetOpacity());
+      mTarget->Paint(aLayer->GetOpacity());
     }
 
     mTarget->Restore();
   }
 }
 
-void
-BasicLayerManager::AdvancePaintingTo(BasicThebesLayer* aLayer)
-{
-  NS_ASSERTION(!aLayer || IsBeforeInTree(mLastPainted, aLayer),
-               "Painting layers out of order");
-
-  // Traverse the layer tree from mLastPainted to aLayer, calling
-  // BeginPaintingLayer and EndPaintingLayer as we enter or exit layers.
-  do {
-    Layer* firstChild;
-    Layer* nextSibling;
-    // Advance mLastPainted one step through the tree in preorder
-    if (!mLastPainted) {
-      // This is the first AdvancePaintingTo call. Start at the root.
-      BeginPaintingLayer(mRoot);
-    } else if ((firstChild = mLastPainted->GetFirstChild()) != nsnull) {
-      // Descend into our first child, if there is one.
-      BeginPaintingLayer(firstChild);
-    } else if ((nextSibling = mLastPainted->GetNextSibling()) != nsnull) {
-      // There are no children to descend into. Leave this layer and
-      // advance to our next sibling, if there is one.
-      EndPaintingLayer();
-      BeginPaintingLayer(nextSibling);
-    } else {
-      // There are no children to descend into and we have no next sibling.
-      // Exit layers until we find a layer which has a next sibling
-      // (or we exit the root).
-      do {
-        EndPaintingLayer();
-        mLastPainted = mLastPainted->GetParent();
-      } while (mLastPainted && !mLastPainted->GetNextSibling());
-      if (mLastPainted) {
-        EndPaintingLayer();
-        BeginPaintingLayer(mLastPainted->GetNextSibling());
-      }
-    }
-  } while (mLastPainted != aLayer);
-}
-
 already_AddRefed<ThebesLayer>
 BasicLayerManager::CreateThebesLayer()
 {
   NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
   nsRefPtr<ThebesLayer> layer = new BasicThebesLayer(this);
   return layer.forget();
 }
 
@@ -762,59 +723,10 @@ BasicLayerManager::CreateColorLayer()
 already_AddRefed<CanvasLayer>
 BasicLayerManager::CreateCanvasLayer()
 {
   NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
   nsRefPtr<CanvasLayer> layer = new BasicCanvasLayer(this);
   return layer.forget();
 }
 
-#ifdef DEBUG
-static void
-AppendAncestors(Layer* aLayer, nsTArray<Layer*>* aAncestors)
-{
-  while (aLayer) {
-    aAncestors->AppendElement(aLayer);
-    aLayer = aLayer->GetParent();
-  }
-}
-
-PRBool
-BasicLayerManager::IsBeforeInTree(Layer* aBefore, Layer* aLayer)
-{
-  if (!aBefore) {
-    return PR_TRUE;
-  }
-  nsAutoTArray<Layer*,8> beforeAncestors, afterAncestors;
-  AppendAncestors(aBefore, &beforeAncestors);
-  AppendAncestors(aLayer, &afterAncestors);
-  PRInt32 beforeIndex = beforeAncestors.Length() - 1;
-  PRInt32 afterIndex = afterAncestors.Length() - 1;
-  NS_ASSERTION(beforeAncestors[beforeIndex] == mRoot, "aBefore not in tree?");
-  NS_ASSERTION(afterAncestors[afterIndex] == mRoot, "aLayer not in tree?");
-  --beforeIndex;
-  --afterIndex;
-  while (beforeIndex >= 0 && afterIndex >= 0) {
-    if (beforeAncestors[beforeIndex] != afterAncestors[afterIndex]) {
-      BasicContainerLayer* parent =
-        static_cast<BasicContainerLayer*>(beforeAncestors[beforeIndex + 1]);
-      for (Layer* child = parent->GetFirstChild();
-           child != afterAncestors[afterIndex];
-           child = child->GetNextSibling()) {
-        if (child == beforeAncestors[beforeIndex]) {
-          return PR_TRUE;
-        }
-      }
-      return PR_FALSE;
-    }
-    --beforeIndex;
-    --afterIndex;
-  }
-  if (afterIndex > 0) {
-    // aBefore is an ancestor of aLayer, so it's before aLayer in preorder
-    return PR_TRUE;
-  }
-  return PR_FALSE;
-}
-#endif
-
 }
 }
--- a/gfx/layers/basic/BasicLayers.h
+++ b/gfx/layers/basic/BasicLayers.h
@@ -73,62 +73,46 @@ public:
   /**
    * Set the default target context that will be used when BeginTransaction
    * is called. This can only be called outside a transaction.
    */
   void SetDefaultTarget(gfxContext* aContext);
 
   virtual void BeginTransaction();
   virtual void BeginTransactionWithTarget(gfxContext* aTarget);
-  virtual void EndConstruction();
-  virtual void EndTransaction();
+  virtual void EndTransaction(DrawThebesLayerCallback aCallback,
+                              void* aCallbackData);
 
   virtual void SetRoot(Layer* aLayer);
 
   virtual already_AddRefed<ThebesLayer> CreateThebesLayer();
   virtual already_AddRefed<ContainerLayer> CreateContainerLayer();
   virtual already_AddRefed<ImageLayer> CreateImageLayer();
   virtual already_AddRefed<CanvasLayer> CreateCanvasLayer();
   virtual already_AddRefed<ImageContainer> CreateImageContainer();
   virtual already_AddRefed<ColorLayer> CreateColorLayer();
   virtual LayersBackend GetBackendType() { return LAYERS_BASIC; }
 
 #ifdef DEBUG
   PRBool InConstruction() { return mPhase == PHASE_CONSTRUCTION; }
   PRBool InDrawing() { return mPhase == PHASE_DRAWING; }
-  PRBool IsBeforeInTree(Layer* aBefore, Layer* aLayer);
 #endif
-  // Prepares mTarget for painting into aLayer. Layers are painted
-  // in tree order, so this method essentially traverses the layer tree
-  // in preorder from mLastPainted to aLayer, doing whatever's needed
-  // as we exit container layers and enter new container layers, and
-  // drawing any non-ThebesLayers we encounter.
-  void AdvancePaintingTo(BasicThebesLayer* aLayer);
-  Layer* GetLastPainted() { return mLastPainted; }
   gfxContext* GetTarget() { return mTarget; }
 
 private:
-  // This gets called when we start painting aLayer. It can change
-  // the state of mTarget by saving state, setting clipping and/or
-  // pushing a group.
-  void BeginPaintingLayer(Layer* aLayer);
-  // This gets called when we finish painting aLayer. It can change
-  // the state of mTarget by popping a group and/or restoring the state.
-  void EndPaintingLayer();
+  // Paints aLayer to mTarget.
+  void PaintLayer(Layer* aLayer,
+                  DrawThebesLayerCallback aCallback,
+                  void* aCallbackData);
 
   nsRefPtr<Layer> mRoot;
   // The default context for BeginTransaction.
   nsRefPtr<gfxContext> mDefaultTarget;
-  // The context to draw into. This is always the context that
-  // our ThebesLayers will return.
+  // The context to draw into.
   nsRefPtr<gfxContext> mTarget;
-  // The most recently painted layer during the drawing phase of
-  // a transaction, or null if no layer has been painted in this
-  // transaction.
-  Layer* mLastPainted;
 
 #ifdef DEBUG
   enum TransactionPhase { PHASE_NONE, PHASE_CONSTRUCTION, PHASE_DRAWING };
   TransactionPhase mPhase;
 #endif
 };
 
 }
new file mode 100644
--- /dev/null
+++ b/gfx/layers/d3d9/CanvasLayerD3D9.cpp
@@ -0,0 +1,231 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Corporation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Vladimir Vukicevic <vladimir@pobox.com>
+ *   Bas Schouten <bschouten@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "CanvasLayerD3D9.h"
+
+#include "gfxImageSurface.h"
+#include "gfxWindowsSurface.h"
+
+namespace mozilla {
+namespace layers {
+
+CanvasLayerD3D9::~CanvasLayerD3D9()
+{
+}
+
+void
+CanvasLayerD3D9::Initialize(const Data& aData)
+{
+  NS_ASSERTION(mSurface == nsnull, "BasicCanvasLayer::Initialize called twice!");
+
+  if (aData.mSurface) {
+    mSurface = aData.mSurface;
+    NS_ASSERTION(aData.mGLContext == nsnull,
+                 "CanvasLayer can't have both surface and GLContext");
+    mNeedsYFlip = PR_FALSE;
+  } else if (aData.mGLContext) {
+    mGLContext = aData.mGLContext;
+    mGLBufferIsPremultiplied = aData.mGLBufferIsPremultiplied;
+    mNeedsYFlip = PR_TRUE;
+  } else {
+    NS_ERROR("CanvasLayer created without mSurface or mGLContext?");
+  }
+
+  mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height);
+
+  device()->CreateTexture(mBounds.width, mBounds.height, 1, 0,
+                          D3DFMT_A8R8G8B8, D3DPOOL_MANAGED,
+                          getter_AddRefs(mTexture), NULL);
+}
+
+void
+CanvasLayerD3D9::Updated(const nsIntRect& aRect)
+{
+  if (!mTexture) {
+    NS_WARNING("CanvasLayerD3D9::Updated called but no texture present!");
+    return;
+  }
+
+  if (mGLContext) {
+    // WebGL reads entire surface.
+    D3DLOCKED_RECT r;
+    mTexture->LockRect(0, &r, NULL, 0);
+
+    PRUint8 *destination;
+    if (r.Pitch != mBounds.width * 4) {
+      destination = new PRUint8[mBounds.width * mBounds.height * 4];
+    } else {
+      destination = (PRUint8*)r.pBits;
+    }
+
+    // We have to flush to ensure that any buffered GL operations are
+    // in the framebuffer before we read.
+    mGLContext->fFlush();
+
+    // For simplicity, we read the entire framebuffer for now -- in
+    // the future we should use aRect, though with WebGL we don't
+    // have an easy way to generate one.
+    mGLContext->fReadPixels(0, 0, mBounds.width, mBounds.height,
+                            LOCAL_GL_BGRA, LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV,
+                            destination);
+
+    if (r.Pitch != mBounds.width * 4) {
+      for (int y = 0; y < mBounds.height; y++) {
+        memcpy((PRUint8*)r.pBits + r.Pitch * y,
+               destination + mBounds.width * 4 * y,
+               mBounds.width * 4);
+      }
+      delete [] destination;
+    }
+    mTexture->UnlockRect(0);
+  } else if (mSurface) {
+    RECT r;
+    r.left = aRect.x;
+    r.top = aRect.y;
+    r.right = aRect.XMost();
+    r.bottom = aRect.YMost();
+
+    D3DLOCKED_RECT lockedRect;
+    mTexture->LockRect(0, &lockedRect, &r, 0);
+
+    PRUint8 *startBits;
+    PRUint32 sourceStride;
+
+    nsRefPtr<gfxImageSurface> sourceSurface;
+
+    if (mSurface->GetType() == gfxASurface::SurfaceTypeWin32) {
+      sourceSurface = static_cast<gfxWindowsSurface*>(mSurface.get())->GetImageSurface();
+      startBits = sourceSurface->Data() + sourceSurface->Stride() * aRect.y +
+                  aRect.x * 4;
+      sourceStride = sourceSurface->Stride();
+    } else if (mSurface->GetType() == gfxASurface::SurfaceTypeImage) {
+      sourceSurface = static_cast<gfxImageSurface*>(sourceSurface.get());
+      if (sourceSurface->Format() != gfxASurface::ImageFormatARGB32 &&
+          sourceSurface->Format() != gfxASurface::ImageFormatRGB24)
+      {
+        mTexture->UnlockRect(0);
+        return;
+      }
+      startBits = sourceSurface->Data() + sourceSurface->Stride() * aRect.y +
+                  aRect.x * 4;
+      sourceStride = sourceSurface->Stride();
+    } else {
+      sourceSurface = new gfxImageSurface(gfxIntSize(aRect.width, aRect.height),
+                                          gfxASurface::ImageFormatARGB32);
+      nsRefPtr<gfxContext> ctx = new gfxContext(sourceSurface);
+      ctx->Translate(gfxPoint(-aRect.x, -aRect.y));
+      ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
+      ctx->SetSource(sourceSurface);
+      ctx->Paint();
+      startBits = sourceSurface->Data();
+      sourceStride = sourceSurface->Stride();
+    }
+
+    for (int y = 0; y < aRect.height; y++) {
+      memcpy((PRUint8*)lockedRect.pBits + lockedRect.Pitch * y,
+             startBits + sourceStride * y,
+             aRect.width * 4);
+    }
+
+    mTexture->UnlockRect(0);    
+  }
+}
+
+LayerD3D9::LayerType
+CanvasLayerD3D9::GetType()
+{
+  return TYPE_CANVAS;
+}
+
+Layer*
+CanvasLayerD3D9::GetLayer()
+{
+  return this;
+}
+
+void
+CanvasLayerD3D9::RenderLayer()
+{
+  float quadTransform[4][4];
+  /*
+   * Matrix to transform the <0.0,0.0>, <1.0,1.0> quad to the correct position
+   * and size. To get pixel perfect mapping we offset the quad half a pixel
+   * to the top-left. We also flip the Y axis here, note we can only do this
+   * because we are in CULL_NONE mode!
+   * 
+   * See: http://msdn.microsoft.com/en-us/library/bb219690%28VS.85%29.aspx
+   */
+  memset(&quadTransform, 0, sizeof(quadTransform));
+  quadTransform[0][0] = (float)mBounds.width;
+  if (mNeedsYFlip) {
+    quadTransform[1][1] = (float)-mBounds.height;
+    quadTransform[3][1] = (float)mBounds.height - 0.5f;
+  } else {
+    quadTransform[1][1] = (float)mBounds.height;
+    quadTransform[3][1] = -0.5f;
+  }
+  quadTransform[2][2] = 1.0f;
+  quadTransform[3][0] = -0.5f;
+  quadTransform[3][3] = 1.0f;
+
+  device()->SetVertexShaderConstantF(0, &quadTransform[0][0], 4);
+
+  device()->SetVertexShaderConstantF(4, &mTransform._11, 4);
+
+  float opacity[4];
+  /*
+   * We always upload a 4 component float, but the shader will use only the
+   * first component since it's declared as a 'float'.
+   */
+  opacity[0] = GetOpacity();
+  device()->SetPixelShaderConstantF(0, opacity, 1);
+
+  mD3DManager->SetShaderMode(LayerManagerD3D9::RGBLAYER);
+
+  if (!mGLBufferIsPremultiplied) {
+    device()->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
+  }
+  device()->SetTexture(0, mTexture);
+  device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
+  if (!mGLBufferIsPremultiplied) {
+    device()->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
+  }
+}
+
+} /* namespace layers */
+} /* namespace mozilla */
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/gfx/layers/d3d9/CanvasLayerD3D9.h
@@ -0,0 +1,90 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Corporation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Vladimir Vukicevic <vladimir@pobox.com>
+ *   Bas Schouten <bschouten@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef GFX_CANVASLAYEROGL_H
+#define GFX_CANVASLAYEROGL_H
+
+#include "LayerManagerD3D9.h"
+#include "GLContext.h"
+#include "gfxASurface.h"
+
+namespace mozilla {
+namespace layers {
+
+class THEBES_API CanvasLayerD3D9 :
+  public CanvasLayer,
+  public LayerD3D9
+{
+public:
+  CanvasLayerD3D9(LayerManagerD3D9 *aManager)
+    : CanvasLayer(aManager, NULL),
+      LayerD3D9(aManager),
+      mTexture(0),
+      mGLBufferIsPremultiplied(PR_FALSE),
+      mNeedsYFlip(PR_FALSE)
+  { 
+      mImplData = static_cast<LayerD3D9*>(this);
+  }
+
+  ~CanvasLayerD3D9();
+
+  // CanvasLayer implementation
+  virtual void Initialize(const Data& aData);
+  virtual void Updated(const nsIntRect& aRect);
+
+  // LayerD3D9 implementation
+  virtual LayerType GetType();
+  virtual Layer* GetLayer();
+  virtual void RenderLayer();
+
+protected:
+  typedef mozilla::gl::GLContext GLContext;
+
+  nsRefPtr<gfxASurface> mSurface;
+  nsRefPtr<GLContext> mGLContext;
+  nsRefPtr<IDirect3DTexture9> mTexture;
+
+  nsIntRect mBounds;
+
+  PRPackedBool mGLBufferIsPremultiplied;
+  PRPackedBool mNeedsYFlip;
+};
+
+} /* layers */
+} /* mozilla */
+#endif /* GFX_CANVASLAYERD3D9_H */
new file mode 100644
--- /dev/null
+++ b/gfx/layers/d3d9/ColorLayerD3D9.cpp
@@ -0,0 +1,91 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Corporation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Robert O'Callahan <robert@ocallahan.org>
+ *   Bas Schouten <bschouten@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "ColorLayerD3D9.h"
+
+namespace mozilla {
+namespace layers {
+
+LayerD3D9::LayerType
+ColorLayerD3D9::GetType()
+{
+  return TYPE_COLOR;
+}
+
+Layer*
+ColorLayerD3D9::GetLayer()
+{
+  return this;
+}
+
+void
+ColorLayerD3D9::RenderLayer()
+{
+  // XXX we might be able to improve performance by using 
+  // IDirect3DDevice9::Clear
+
+  float quadTransform[4][4];
+  nsIntRect visibleRect = mVisibleRegion.GetBounds();
+  // Transform the quad to the size of the visible area.
+  memset(&quadTransform, 0, sizeof(quadTransform));
+  quadTransform[0][0] = (float)visibleRect.width;
+  quadTransform[1][1] = (float)visibleRect.height;
+  quadTransform[2][2] = 1.0f;
+  quadTransform[3][0] = (float)visibleRect.x;
+  quadTransform[3][1] = (float)visibleRect.y;
+  quadTransform[3][3] = 1.0f;
+
+  device()->SetVertexShaderConstantF(0, &quadTransform[0][0], 4);
+  device()->SetVertexShaderConstantF(4, &mTransform._11, 4);
+
+  float color[4];
+  // color is premultiplied, so we need to adjust all channels
+  color[0] = (float)(mColor.r * GetOpacity());
+  color[1] = (float)(mColor.g * GetOpacity());
+  color[2] = (float)(mColor.b * GetOpacity());
+  color[3] = (float)(mColor.a * GetOpacity());
+
+  device()->SetPixelShaderConstantF(0, color, 1);
+
+  mD3DManager->SetShaderMode(LayerManagerD3D9::SOLIDCOLORLAYER);
+
+  device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
+}
+
+} /* layers */
+} /* mozilla */
new file mode 100644
--- /dev/null
+++ b/gfx/layers/d3d9/ColorLayerD3D9.h
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Corporation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Robert O'Callahan <robert@ocallahan.org>
+ *   Bas Schouten <bschouten@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef GFX_COLORLAYERD3D9_H
+#define GFX_COLORLAYERD3D9_H
+
+#include "LayerManagerD3D9.h"
+
+namespace mozilla {
+namespace layers {
+
+class THEBES_API ColorLayerD3D9 : public ColorLayer,
+                                 public LayerD3D9
+{
+public:
+  ColorLayerD3D9(LayerManagerD3D9 *aManager)
+    : ColorLayer(aManager, NULL)
+    , LayerD3D9(aManager)
+  { 
+    mImplData = static_cast<LayerD3D9*>(this);
+  }
+
+  virtual void SetVisibleRegion(const nsIntRegion& aRegion) { mVisibleRegion = aRegion; }
+
+  // LayerD3D9 Implementation
+  virtual LayerType GetType();
+
+  virtual Layer* GetLayer();
+
+  virtual void RenderLayer();
+
+protected:
+  nsIntRegion mVisibleRegion;
+};
+
+} /* layers */
+} /* mozilla */
+
+#endif /* GFX_COLORLAYERD3D9_H */
new file mode 100644
--- /dev/null
+++ b/gfx/layers/d3d9/ContainerLayerD3D9.cpp
@@ -0,0 +1,252 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Corporation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Bas Schouten <bschouten@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "ContainerLayerD3D9.h"
+
+namespace mozilla {
+namespace layers {
+
+ContainerLayerD3D9::ContainerLayerD3D9(LayerManagerD3D9 *aManager)
+  : ContainerLayer(aManager, NULL)
+  , LayerD3D9(aManager)
+{
+  mImplData = static_cast<LayerD3D9*>(this);
+}
+
+const nsIntRect&
+ContainerLayerD3D9::GetVisibleRect()
+{
+  return mVisibleRect;
+}
+
+void
+ContainerLayerD3D9::SetVisibleRegion(const nsIntRegion &aRegion)
+{
+  mVisibleRect = aRegion.GetBounds();
+}
+
+void
+ContainerLayerD3D9::InsertAfter(Layer* aChild, Layer* aAfter)
+{
+  LayerD3D9 *newChild = static_cast<LayerD3D9*>(aChild->ImplData());
+  aChild->SetParent(this);
+  if (!aAfter) {
+    LayerD3D9 *oldFirstChild = GetFirstChildD3D9();
+    mFirstChild = newChild->GetLayer();
+    newChild->SetNextSibling(oldFirstChild);
+    return;
+  }
+  for (LayerD3D9 *child = GetFirstChildD3D9(); 
+    child; child = child->GetNextSibling()) {
+    if (aAfter == child->GetLayer()) {
+      LayerD3D9 *oldNextSibling = child->GetNextSibling();
+      child->SetNextSibling(newChild);
+      child->GetNextSibling()->SetNextSibling(oldNextSibling);
+      return;
+    }
+  }
+  NS_WARNING("Failed to find aAfter layer!");
+}
+
+void
+ContainerLayerD3D9::RemoveChild(Layer *aChild)
+{
+  if (GetFirstChild() == aChild) {
+    mFirstChild = GetFirstChildD3D9()->GetNextSibling() ?
+      GetFirstChildD3D9()->GetNextSibling()->GetLayer() : nsnull;
+    return;
+  }
+  LayerD3D9 *lastChild = NULL;
+  for (LayerD3D9 *child = GetFirstChildD3D9(); child; 
+    child = child->GetNextSibling()) {
+    if (child->GetLayer() == aChild) {
+      // We're sure this is not our first child. So lastChild != NULL.
+      lastChild->SetNextSibling(child->GetNextSibling());
+      child->SetNextSibling(NULL);
+      child->GetLayer()->SetParent(NULL);
+      return;
+    }
+    lastChild = child;
+  }
+}
+
+LayerD3D9::LayerType
+ContainerLayerD3D9::GetType()
+{
+  return TYPE_CONTAINER;
+}
+
+Layer*
+ContainerLayerD3D9::GetLayer()
+{
+  return this;
+}
+
+LayerD3D9*
+ContainerLayerD3D9::GetFirstChildD3D9()
+{
+  if (!mFirstChild) {
+    return nsnull;
+  }
+  return static_cast<LayerD3D9*>(mFirstChild->ImplData());
+}
+
+void
+ContainerLayerD3D9::RenderLayer()
+{
+  float opacity = GetOpacity();
+  nsRefPtr<IDirect3DSurface9> previousRenderTarget;
+  nsRefPtr<IDirect3DTexture9> renderTexture;
+  float previousRenderTargetOffset[4];
+  float renderTargetOffset[] = { 0, 0, 0, 0 };
+  float oldViewMatrix[4][4];
+
+  PRBool useIntermediate = (opacity != 1.0 || !mTransform.IsIdentity());
+
+  if (useIntermediate) {
+    device()->GetRenderTarget(0, getter_AddRefs(previousRenderTarget));
+    device()->CreateTexture(mVisibleRect.width, mVisibleRect.height, 1,
+			    D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8,
+			    D3DPOOL_DEFAULT, getter_AddRefs(renderTexture),
+                            NULL);
+    nsRefPtr<IDirect3DSurface9> renderSurface;
+    renderTexture->GetSurfaceLevel(0, getter_AddRefs(renderSurface));
+    device()->SetRenderTarget(0, renderSurface);
+    device()->GetVertexShaderConstantF(12, previousRenderTargetOffset, 1);
+    renderTargetOffset[0] = (float)GetVisibleRect().x;
+    renderTargetOffset[1] = (float)GetVisibleRect().y;
+    device()->SetVertexShaderConstantF(12, renderTargetOffset, 1);
+
+    float viewMatrix[4][4];
+    /*
+     * Matrix to transform to viewport space ( <-1.0, 1.0> topleft, 
+     * <1.0, -1.0> bottomright)
+     */
+    memset(&viewMatrix, 0, sizeof(viewMatrix));
+    viewMatrix[0][0] = 2.0f / mVisibleRect.width;
+    viewMatrix[1][1] = -2.0f / mVisibleRect.height;
+    viewMatrix[2][2] = 1.0f;
+    viewMatrix[3][0] = -1.0f;
+    viewMatrix[3][1] = 1.0f;
+    viewMatrix[3][3] = 1.0f;
+    
+    device()->GetVertexShaderConstantF(8, &oldViewMatrix[0][0], 4);
+    device()->SetVertexShaderConstantF(8, &viewMatrix[0][0], 4);
+  }
+
+  /*
+   * Render this container's contents.
+   */
+  LayerD3D9 *layerToRender = GetFirstChildD3D9();
+  while (layerToRender) {
+    const nsIntRect *clipRect = layerToRender->GetLayer()->GetClipRect();
+    RECT r;
+    if (clipRect) {
+      r.left = (LONG)(clipRect->x - renderTargetOffset[0]);
+      r.top = (LONG)(clipRect->y - renderTargetOffset[1]);
+      r.right = (LONG)(clipRect->x - renderTargetOffset[0] + clipRect->width);
+      r.bottom = (LONG)(clipRect->y - renderTargetOffset[1] + clipRect->height);
+    } else {
+      if (useIntermediate) {
+        r.left = 0;
+        r.top = 0;
+      } else {
+        r.left = GetVisibleRect().x;
+        r.top = GetVisibleRect().y;
+      }
+      r.right = r.left + GetVisibleRect().width;
+      r.bottom = r.top + GetVisibleRect().height;
+    }
+
+    nsRefPtr<IDirect3DSurface9> renderSurface;
+    device()->GetRenderTarget(0, getter_AddRefs(renderSurface));
+
+    D3DSURFACE_DESC desc;
+    renderSurface->GetDesc(&desc);
+
+    r.left = NS_MAX<LONG>(0, r.left);
+    r.top = NS_MAX<LONG>(0, r.top);
+    r.bottom = NS_MIN<LONG>(r.bottom, desc.Height);
+    r.right = NS_MIN<LONG>(r.right, desc.Width);
+
+    device()->SetScissorRect(&r);
+
+    layerToRender->RenderLayer();
+    layerToRender = layerToRender->GetNextSibling();
+  }
+
+  if (useIntermediate) {
+    device()->SetRenderTarget(0, previousRenderTarget);
+    device()->SetVertexShaderConstantF(12, previousRenderTargetOffset, 1);
+    device()->SetVertexShaderConstantF(8, &oldViewMatrix[0][0], 4);
+
+    float quadTransform[4][4];
+    /*
+     * Matrix to transform the <0.0,0.0>, <1.0,1.0> quad to the correct position
+     * and size. To get pixel perfect mapping we offset the quad half a pixel
+     * to the top-left.
+     * 
+     * See: http://msdn.microsoft.com/en-us/library/bb219690%28VS.85%29.aspx
+     */
+    memset(&quadTransform, 0, sizeof(quadTransform));
+    quadTransform[0][0] = (float)GetVisibleRect().width;
+    quadTransform[1][1] = (float)GetVisibleRect().height;
+    quadTransform[2][2] = 1.0f;
+    quadTransform[3][0] = (float)GetVisibleRect().x - 0.5f;
+    quadTransform[3][1] = (float)GetVisibleRect().y - 0.5f;
+    quadTransform[3][3] = 1.0f;
+
+    device()->SetVertexShaderConstantF(0, &quadTransform[0][0], 4);
+    device()->SetVertexShaderConstantF(4, &mTransform._11, 4);
+
+    float opacityVector[4];
+    /*
+     * We always upload a 4 component float, but the shader will use only the
+     * first component since it's declared as a 'float'.
+     */
+    opacityVector[0] = opacity;
+    device()->SetPixelShaderConstantF(0, opacityVector, 1);
+
+    mD3DManager->SetShaderMode(LayerManagerD3D9::RGBLAYER);
+
+    device()->SetTexture(0, renderTexture);
+    device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
+  }
+}
+
+} /* layers */
+} /* mozilla */
new file mode 100644
--- /dev/null
+++ b/gfx/layers/d3d9/ContainerLayerD3D9.h
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Corporation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Bas Schouten <bschouten@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef GFX_CONTAINERLAYERD3D9_H
+#define GFX_CONTAINERLAYERD3D9_H
+
+#include "Layers.h"
+#include "LayerManagerD3D9.h"
+
+namespace mozilla {
+namespace layers {
+
+class ContainerLayerD3D9 : public ContainerLayer, 
+                          public LayerD3D9
+{
+public:
+  ContainerLayerD3D9(LayerManagerD3D9 *aManager);
+
+  const nsIntRect &GetVisibleRect();
+
+  /* ContainerLayer implementation */
+  void SetVisibleRegion(const nsIntRegion& aRegion);
+
+  void InsertAfter(Layer* aChild, Layer* aAfter);
+
+  void RemoveChild(Layer* aChild);
+
+  /* LayerD3D9 implementation */
+  LayerType GetType();
+
+  Layer* GetLayer();
+
+  LayerD3D9* GetFirstChildD3D9();
+
+  PRBool IsEmpty();
+
+  void RenderLayer();
+
+private:
+  nsIntRect mVisibleRect;
+};
+
+} /* layers */
+} /* mozilla */
+
+#endif /* GFX_CONTAINERLAYERD3D9_H */
new file mode 100644
--- /dev/null
+++ b/gfx/layers/d3d9/ImageLayerD3D9.cpp
@@ -0,0 +1,463 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Corporation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Bas Schouten <bschouten@mozilla.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "ImageLayerD3D9.h"
+#include "gfxImageSurface.h"
+#include "yuv_convert.h"
+
+namespace mozilla {
+namespace layers {
+
+using mozilla::MutexAutoLock;
+
+ImageContainerD3D9::ImageContainerD3D9(LayerManagerD3D9 *aManager)
+  : ImageContainer(aManager)
+  , mActiveImageLock("mozilla.layers.ImageContainerD3D9.mActiveImageLock")
+{
+}
+
+already_AddRefed<Image>
+ImageContainerD3D9::CreateImage(const Image::Format *aFormats,
+                               PRUint32 aNumFormats)
+{
+  if (!aNumFormats) {
+    return nsnull;
+  }
+  nsRefPtr<Image> img;
+  if (aFormats[0] == Image::PLANAR_YCBCR) {
+    img = new PlanarYCbCrImageD3D9(static_cast<LayerManagerD3D9*>(mManager));
+  } else if (aFormats[0] == Image::CAIRO_SURFACE) {
+    img = new CairoImageD3D9(static_cast<LayerManagerD3D9*>(mManager));
+  }
+  return img.forget();
+}
+
+void
+ImageContainerD3D9::SetCurrentImage(Image *aImage)
+{
+  MutexAutoLock lock(mActiveImageLock);
+
+  mActiveImage = aImage;
+}
+
+already_AddRefed<Image>
+ImageContainerD3D9::GetCurrentImage()
+{
+  MutexAutoLock lock(mActiveImageLock);
+
+  nsRefPtr<Image> retval = mActiveImage;
+  return retval.forget();
+}
+
+already_AddRefed<gfxASurface>
+ImageContainerD3D9::GetCurrentAsSurface(gfxIntSize *aSize)
+{
+  MutexAutoLock lock(mActiveImageLock);
+  if (!mActiveImage) {
+    return nsnull;
+  }
+
+  if (mActiveImage->GetFormat() == Image::PLANAR_YCBCR) {
+    PlanarYCbCrImageD3D9 *yuvImage =
+      static_cast<PlanarYCbCrImageD3D9*>(mActiveImage.get());
+    if (yuvImage->HasData()) {
+      *aSize = yuvImage->mSize;
+    }
+  } else if (mActiveImage->GetFormat() == Image::CAIRO_SURFACE) {
+    CairoImageD3D9 *cairoImage =
+      static_cast<CairoImageD3D9*>(mActiveImage.get());
+    *aSize = cairoImage->mSize;
+  }
+
+  return static_cast<ImageD3D9*>(mActiveImage->GetImplData())->GetAsSurface();
+}
+
+gfxIntSize
+ImageContainerD3D9::GetCurrentSize()
+{
+  MutexAutoLock lock(mActiveImageLock);
+  if (!mActiveImage) {
+    return gfxIntSize(0,0);
+  }
+  if (mActiveImage->GetFormat() == Image::PLANAR_YCBCR) {
+    PlanarYCbCrImageD3D9 *yuvImage =
+      static_cast<PlanarYCbCrImageD3D9*>(mActiveImage.get());
+    if (!yuvImage->HasData()) {
+      return gfxIntSize(0,0);
+    }
+    return yuvImage->mSize;
+
+  } else if (mActiveImage->GetFormat() == Image::CAIRO_SURFACE) {
+    CairoImageD3D9 *cairoImage =
+      static_cast<CairoImageD3D9*>(mActiveImage.get());
+    return cairoImage->mSize;
+  }
+
+  return gfxIntSize(0,0);
+}
+
+LayerD3D9::LayerType
+ImageLayerD3D9::GetType()
+{
+  return TYPE_IMAGE;
+}
+
+Layer*
+ImageLayerD3D9::GetLayer()
+{
+  return this;
+}
+
+void
+ImageLayerD3D9::RenderLayer()
+{
+  if (!GetContainer()) {
+    return;
+  }
+
+  nsRefPtr<Image> image = GetContainer()->GetCurrentImage();
+
+  if (image->GetFormat() == Image::PLANAR_YCBCR) {
+    PlanarYCbCrImageD3D9 *yuvImage =
+      static_cast<PlanarYCbCrImageD3D9*>(image.get());
+
+    if (!yuvImage->HasData()) {
+      return;
+    }
+    yuvImage->AllocateTextures();
+
+    float quadTransform[4][4];
+    /*
+     * Matrix to transform the <0.0,0.0>, <1.0,1.0> quad to the correct position
+     * and size. To get pixel perfect mapping we extend the quad half a pixel
+     * beyond all edges.
+     */
+    memset(&quadTransform, 0, sizeof(quadTransform));
+    quadTransform[0][0] = (float)yuvImage->mSize.width + 0.5f;
+    quadTransform[1][1] = (float)yuvImage->mSize.height + 0.5f;
+    quadTransform[2][2] = 1.0f;
+    quadTransform[3][3] = 1.0f;
+
+
+    device()->SetVertexShaderConstantF(0, &quadTransform[0][0], 4);
+    device()->SetVertexShaderConstantF(4, &mTransform._11, 4);
+
+    float opacity[4];
+    /*
+     * We always upload a 4 component float, but the shader will
+     * only use the the first component since it's declared as a 'float'.
+     */
+    opacity[0] = GetOpacity();
+    device()->SetPixelShaderConstantF(0, opacity, 1);
+
+    mD3DManager->SetShaderMode(LayerManagerD3D9::YCBCRLAYER);
+
+    device()->SetTexture(0, yuvImage->mYTexture);
+    device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
+    device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
+    device()->SetTexture(1, yuvImage->mCbTexture);
+    device()->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
+    device()->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
+    device()->SetTexture(2, yuvImage->mCrTexture);
+    device()->SetSamplerState(2, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
+    device()->SetSamplerState(2, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
+
+    device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
+
+  } else if (image->GetFormat() == Image::CAIRO_SURFACE) {
+    CairoImageD3D9 *cairoImage =
+      static_cast<CairoImageD3D9*>(image.get());
+
+    float quadTransform[4][4];
+    /*
+     * Matrix to transform the <0.0,0.0>, <1.0,1.0> quad to the correct position
+     * and size. To get pixel perfect mapping we extend the quad half a pixel
+     * beyond all edges.
+     */
+    memset(&quadTransform, 0, sizeof(quadTransform));
+    quadTransform[0][0] = (float)cairoImage->mSize.width + 0.5f;
+    quadTransform[1][1] = (float)cairoImage->mSize.height + 0.5f;
+    quadTransform[2][2] = 1.0f;
+    quadTransform[3][3] = 1.0f;
+
+
+    device()->SetVertexShaderConstantF(0, &quadTransform[0][0], 4);
+    device()->SetVertexShaderConstantF(4, &mTransform._11, 4);
+
+    float opacity[4];
+    /*
+     * We always upload a 4 component float, but the shader will
+     * only use the the first component since it's declared as a 'float'.
+     */
+    opacity[0] = GetOpacity();
+    device()->SetPixelShaderConstantF(0, opacity, 1);
+
+    mD3DManager->SetShaderMode(LayerManagerD3D9::RGBLAYER);
+
+    device()->SetTexture(0, cairoImage->mTexture);
+    device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
+  }
+}
+
+PlanarYCbCrImageD3D9::PlanarYCbCrImageD3D9(mozilla::layers::LayerManagerD3D9* aManager)
+  : PlanarYCbCrImage(static_cast<ImageD3D9*>(this))
+  , mManager(aManager)
+  , mHasData(PR_FALSE)
+{
+}
+
+void
+PlanarYCbCrImageD3D9::SetData(const PlanarYCbCrImage::Data &aData)
+{
+  // For now, we copy the data
+  int width_shift = 0;
+  int height_shift = 0;
+  if (aData.mYSize.width == aData.mCbCrSize.width &&
+      aData.mYSize.height == aData.mCbCrSize.height) {
+     // YV24 format
+     width_shift = 0;
+     height_shift = 0;
+  } else if (aData.mYSize.width / 2 == aData.mCbCrSize.width &&
+             aData.mYSize.height == aData.mCbCrSize.height) {
+    // YV16 format
+    width_shift = 1;
+    height_shift = 0;
+  } else if (aData.mYSize.width / 2 == aData.mCbCrSize.width &&
+             aData.mYSize.height / 2 == aData.mCbCrSize.height ) {
+      // YV12 format
+    width_shift = 1;
+    height_shift = 1;
+  } else {
+    NS_ERROR("YCbCr format not supported");
+  }
+
+  mData = aData;
+  mData.mCbCrStride = mData.mCbCrSize.width = aData.mPicSize.width >> width_shift;
+  mData.mCbCrSize.height = aData.mPicSize.height >> height_shift;
+  mData.mYSize = aData.mPicSize;
+  mData.mYStride = mData.mYSize.width;
+  
+  mBuffer = new PRUint8[mData.mCbCrStride * mData.mCbCrSize.height * 2 +
+                        mData.mYStride * mData.mYSize.height];
+  mData.mYChannel = mBuffer;
+  mData.mCbChannel = mData.mYChannel + mData.mYStride * mData.mYSize.height;
+  mData.mCrChannel = mData.mCbChannel + mData.mCbCrStride * mData.mCbCrSize.height;
+
+  mData.mCrChannel = new PRUint8[mData.mCbCrStride * mData.mCbCrSize.height];
+  int cbcr_x = aData.mPicX >> width_shift;
+  int cbcr_y = aData.mPicY >> height_shift;
+
+  for (int i = 0; i < mData.mYSize.height; i++) {
+    memcpy(mData.mYChannel + i * mData.mYStride,
+           aData.mYChannel + ((aData.mPicY + i) * aData.mYStride) + aData.mPicX,
+           mData.mYStride);
+  }
+  for (int i = 0; i < mData.mCbCrSize.height; i++) {
+    memcpy(mData.mCbChannel + i * mData.mCbCrStride,
+           aData.mCbChannel + ((cbcr_y + i) * aData.mCbCrStride) + cbcr_x,
+           mData.mCbCrStride);
+  }
+  for (int i = 0; i < mData.mCbCrSize.height; i++) {
+    memcpy(mData.mCrChannel + i * mData.mCbCrStride,
+           aData.mCrChannel + ((cbcr_y + i) * aData.mCbCrStride) + cbcr_x,
+           mData.mCbCrStride);
+  }
+
+  // Fix picture rect to be correct
+  mData.mPicX = mData.mPicY = 0;
+  mSize = aData.mPicSize;
+
+  mHasData = PR_TRUE;
+}
+
+void
+PlanarYCbCrImageD3D9::AllocateTextures()
+{
+
+
+  D3DLOCKED_RECT lockrect;
+  PRUint8* src;
+  PRUint8* dest;
+  //XXX: ensure correct usage flags
+  mManager->device()->CreateTexture(mData.mYSize.width, mData.mYSize.height,
+                          1, 0, D3DFMT_L8, D3DPOOL_MANAGED,
+                          getter_AddRefs(mYTexture), NULL);
+
+
+  /* lock the entire texture */
+  mYTexture->LockRect(0, &lockrect, NULL, 0);
+
+  src  = mData.mYChannel;
+  //FIX cast
+  dest = (PRUint8*)lockrect.pBits;
+
+  // copy over data
+  for (int h=0; h<mData.mYSize.height; h++) {
+    memcpy(dest, src, mData.mYSize.width);
+    dest += lockrect.Pitch;
+    src += mData.mYStride;
+  }
+
+  mYTexture->UnlockRect(0);
+
+  //XXX: ensure correct usage flags
+  mManager->device()->CreateTexture(mData.mCbCrSize.width, mData.mCbCrSize.height,
+                          1, 0, D3DFMT_L8, D3DPOOL_MANAGED,
+                          getter_AddRefs(mCbTexture), NULL);
+
+
+  /* lock the entire texture */
+  mCbTexture->LockRect(0, &lockrect, NULL, 0);
+
+  src  = mData.mCbChannel;
+  //FIX cast
+  dest = (PRUint8*)lockrect.pBits;
+
+  // copy over data
+  for (int h=0; h<mData.mCbCrSize.height; h++) {
+    memcpy(dest, src, mData.mCbCrSize.width);
+    dest += lockrect.Pitch;
+    src += mData.mCbCrStride;
+  }
+
+  mCbTexture->UnlockRect(0);
+
+
+  //XXX: ensure correct usage flags
+  mManager->device()->CreateTexture(mData.mCbCrSize.width, mData.mCbCrSize.height,
+                          1, 0, D3DFMT_L8, D3DPOOL_MANAGED,
+                          getter_AddRefs(mCrTexture), NULL);
+
+
+  /* lock the entire texture */
+  mCrTexture->LockRect(0, &lockrect, NULL, 0);
+
+  src  = mData.mCrChannel;
+  //FIX cast
+  dest = (PRUint8*)lockrect.pBits;
+
+  // copy over data
+  for (int h=0; h<mData.mCbCrSize.height; h++) {
+    memcpy(dest, src, mData.mCbCrSize.width);
+    dest += lockrect.Pitch;
+    src += mData.mCbCrStride;
+  }
+
+  mCrTexture->UnlockRect(0);
+
+}
+
+void
+PlanarYCbCrImageD3D9::FreeTextures()
+{
+}
+
+already_AddRefed<gfxASurface>
+PlanarYCbCrImageD3D9::GetAsSurface()
+{
+  nsRefPtr<gfxImageSurface> imageSurface =
+    new gfxImageSurface(mSize, gfxASurface::ImageFormatRGB24);
+ 
+  // Convert from YCbCr to RGB now
+  gfx::ConvertYCbCrToRGB32(mData.mYChannel,
+                           mData.mCbChannel,
+                           mData.mCrChannel,
+                           imageSurface->Data(),
+                           0,
+                           0,
+                           mSize.width,
+                           mSize.height,
+                           mData.mYStride,
+                           mData.mCbCrStride,
+                           imageSurface->Stride(),
+                           gfx::YV12); 
+
+  return imageSurface.forget().get();
+}
+
+CairoImageD3D9::~CairoImageD3D9()
+{
+}
+
+void
+CairoImageD3D9::SetData(const CairoImage::Data &aData)
+{
+  mSize = aData.mSize;
+
+  nsRefPtr<gfxImageSurface> imageSurface =
+    new gfxImageSurface(aData.mSize, gfxASurface::ImageFormatARGB32);
+
+  nsRefPtr<gfxContext> context = new gfxContext(imageSurface);
+
+  context->SetSource(aData.mSurface);
+  context->Paint();
+
+  //XXX: make sure we're using the correct usage flags
+  mManager->device()->CreateTexture(aData.mSize.width, aData.mSize.height,
+                  1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED,
+                  getter_AddRefs(mTexture), NULL);
+
+  D3DLOCKED_RECT lockrect;
+  /* lock the entire texture */
+  mTexture->LockRect(0, &lockrect, NULL, 0);
+
+  PRUint8* src  = imageSurface->Data();
+  //FIX cast
+  PRUint8* dest = (PRUint8*)lockrect.pBits;
+
+  // copy over data. If we don't need to do any swaping we can
+  // use memcpy
+  for (int i=0; i<aData.mSize.width*aData.mSize.height; i++) {
+    dest[0] = src[0];
+    dest[1] = src[1];
+    dest[2] = src[2];
+    dest[3] = src[3];
+    dest += 4;
+    src += 4;
+  }
+
+  mTexture->UnlockRect(0);
+}
+
+already_AddRefed<gfxASurface>
+CairoImageD3D9::GetAsSurface()
+{
+  return nsnull;
+}
+
+} /* layers */
+} /* mozilla */
new file mode 100644
--- /dev/null
+++ b/gfx/layers/d3d9/ImageLayerD3D9.h
@@ -0,0 +1,155 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Corporation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Bas Schouten <bschouten@mozilla.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef GFX_IMAGELAYERD3D9_H
+#define GFX_IMAGELAYERD3D9_H
+
+#include "LayerManagerD3D9.h"
+#include "ImageLayers.h"
+#include "mozilla/Mutex.h"
+
+namespace mozilla {
+namespace layers {
+
+class THEBES_API ImageContainerD3D9 : public ImageContainer
+{
+public:
+  ImageContainerD3D9(LayerManagerD3D9 *aManager);
+  virtual ~ImageContainerD3D9() {}
+
+  virtual already_AddRefed<Image> CreateImage(const Image::Format* aFormats,
+                                              PRUint32 aNumFormats);
+
+  virtual void SetCurrentImage(Image* aImage);
+
+  virtual already_AddRefed<Image> GetCurrentImage();
+
+  virtual already_AddRefed<gfxASurface> GetCurrentAsSurface(gfxIntSize* aSize);
+
+  virtual gfxIntSize GetCurrentSize();
+
+private:
+  typedef mozilla::Mutex Mutex;
+
+  nsRefPtr<Image> mActiveImage;
+
+  Mutex mActiveImageLock;
+};
+
+class THEBES_API ImageLayerD3D9 : public ImageLayer,
+                                  public LayerD3D9
+{
+public:
+  ImageLayerD3D9(LayerManagerD3D9 *aManager)
+    : ImageLayer(aManager, NULL)
+    , LayerD3D9(aManager)
+  { 
+    mImplData = static_cast<LayerD3D9*>(this);
+  }
+
+  // LayerD3D9 Implementation
+  virtual LayerType GetType();
+
+  virtual Layer* GetLayer();
+
+  virtual void RenderLayer();
+};
+
+class THEBES_API ImageD3D9
+{
+public:
+  virtual already_AddRefed<gfxASurface> GetAsSurface() = 0;
+};
+
+class THEBES_API PlanarYCbCrImageD3D9 : public PlanarYCbCrImage,
+                                        public ImageD3D9
+{
+public:
+  PlanarYCbCrImageD3D9(LayerManagerD3D9 *aManager);
+
+  virtual void SetData(const Data &aData);
+
+  /*
+   * Upload the data from out mData into our textures. For now we use this to
+   * make sure the textures are created and filled on the main thread.
+   */
+  void AllocateTextures();
+  /*
+   * XXX
+   * Free the textures, we call this from the main thread when we're done
+   * drawing this frame. We cannot free this from the constructor since it may
+   * be destroyed off the main-thread and might not be able to properly clean
+   * up its textures
+   */
+  void FreeTextures();
+  PRBool HasData() { return mHasData; }
+
+  virtual already_AddRefed<gfxASurface> GetAsSurface();
+  
+  nsAutoArrayPtr<PRUint8> mBuffer;
+  LayerManagerD3D9 *mManager;
+  Data mData;
+  gfxIntSize mSize;
+  nsRefPtr<IDirect3DTexture9> mYTexture;
+  nsRefPtr<IDirect3DTexture9> mCrTexture;
+  nsRefPtr<IDirect3DTexture9> mCbTexture;
+  PRPackedBool mHasData;
+};
+
+
+class THEBES_API CairoImageD3D9 : public CairoImage,
+                                  public ImageD3D9
+{
+public:
+  CairoImageD3D9(LayerManagerD3D9 *aManager)
+    : CairoImage(static_cast<ImageD3D9*>(this))
+    , mManager(aManager)
+  { }
+  ~CairoImageD3D9();
+
+  virtual void SetData(const Data &aData);
+
+  virtual already_AddRefed<gfxASurface> GetAsSurface();
+
+  nsRefPtr<IDirect3DTexture9> mTexture;
+  gfxIntSize mSize;
+  LayerManagerD3D9 *mManager;
+};
+
+} /* layers */
+} /* mozilla */
+#endif /* GFX_IMAGELAYERD3D9_H */
new file mode 100644
--- /dev/null
+++ b/gfx/layers/d3d9/LayerManagerD3D9.cpp
@@ -0,0 +1,578 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Corporation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Bas Schouten <bschouten@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "LayerManagerD3D9.h"
+
+#include "ThebesLayerD3D9.h"
+#include "ContainerLayerD3D9.h"
+#include "ImageLayerD3D9.h"
+#include "ColorLayerD3D9.h"
+#include "CanvasLayerD3D9.h"
+
+#include "LayerManagerD3D9Shaders.h"
+
+#include "nsIServiceManager.h"
+#include "nsIConsoleService.h"
+#include "nsPrintfCString.h"
+
+namespace mozilla {
+namespace layers {
+
+struct vertex {
+  float x, y;
+};
+
+IDirect3D9 *LayerManagerD3D9::mD3D9 = NULL;
+
+typedef IDirect3D9* (WINAPI*Direct3DCreate9Func)(
+  UINT SDKVersion
+);
+
+
+LayerManagerD3D9::LayerManagerD3D9(nsIWidget *aWidget)
+{
+    mWidget = aWidget;
+    mCurrentCallbackInfo.Callback = NULL;
+    mCurrentCallbackInfo.CallbackData = NULL;
+}
+
+LayerManagerD3D9::~LayerManagerD3D9()
+{
+}
+
+#define HAS_CAP(a, b) (((a) & (b)) == (b))
+#define LACKS_CAP(a, b) !(((a) & (b)) == (b))
+
+PRBool
+LayerManagerD3D9::Initialize()
+{
+  if (!mD3D9) {
+    Direct3DCreate9Func d3d9create = (Direct3DCreate9Func)
+      GetProcAddress(LoadLibraryW(L"d3d9.dll"), "Direct3DCreate9");
+    if (!d3d9create) {
+      return PR_FALSE;
+    }
+
+    mD3D9 = d3d9create(D3D_SDK_VERSION);
+    if (!mD3D9) {
+      return PR_FALSE;
+    }
+  }
+
+  D3DPRESENT_PARAMETERS pp;
+  memset(&pp, 0, sizeof(D3DPRESENT_PARAMETERS));
+
+  pp.BackBufferFormat = D3DFMT_A8R8G8B8;
+  pp.SwapEffect = D3DSWAPEFFECT_COPY;
+  pp.Windowed = TRUE;
+  pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+  pp.hDeviceWindow = (HWND)mWidget->GetNativeData(NS_NATIVE_WINDOW);
+
+  HRESULT hr = mD3D9->CreateDevice(D3DADAPTER_DEFAULT,
+                                   D3DDEVTYPE_HAL,
+                                   NULL,
+                                   D3DCREATE_FPU_PRESERVE |
+                                   D3DCREATE_MULTITHREADED |
+                                   D3DCREATE_MIXED_VERTEXPROCESSING,
+                                   &pp,
+                                   getter_AddRefs(mDevice));
+
+  if (FAILED(hr)) {
+    return PR_FALSE;
+  }
+
+  if (!VerifyCaps()) {
+    return PR_FALSE;
+  }
+
+  hr = mDevice->CreateVertexShader((DWORD*)LayerQuadVS,
+                                   getter_AddRefs(mLayerVS));
+
+  if (FAILED(hr)) {
+    return PR_FALSE;
+  }
+
+  hr = mDevice->CreatePixelShader((DWORD*)RGBShaderPS,
+                                  getter_AddRefs(mRGBPS));
+
+  if (FAILED(hr)) {
+    return PR_FALSE;
+  }
+
+  hr = mDevice->CreatePixelShader((DWORD*)YCbCrShaderPS,
+                                  getter_AddRefs(mYCbCrPS));
+
+  if (FAILED(hr)) {
+    return PR_FALSE;
+  }
+
+  hr = mDevice->CreatePixelShader((DWORD*)SolidColorShaderPS,
+                                  getter_AddRefs(mSolidColorPS));
+
+  if (FAILED(hr)) {
+    return PR_FALSE;
+  }
+
+  hr = mDevice->CreateVertexBuffer(sizeof(vertex) * 4,
+                                   0,
+                                   0,
+                                   D3DPOOL_MANAGED,
+                                   getter_AddRefs(mVB),
+                                   NULL);
+
+  if (FAILED(hr)) {
+    return PR_FALSE;
+  }
+
+  vertex *vertices;
+  hr = mVB->Lock(0, 0, (void**)&vertices, 0);
+  if (FAILED(hr)) {
+    return PR_FALSE;
+  }
+  
+  vertices[0].x = vertices[0].y = 0;
+  vertices[1].x = 1; vertices[1].y = 0;
+  vertices[2].x = 0; vertices[2].y = 1;
+  vertices[3].x = 1; vertices[3].y = 1;
+
+  mVB->Unlock();
+
+  hr = mDevice->SetStreamSource(0, mVB, 0, sizeof(vertex));
+  if (FAILED(hr)) {
+    return PR_FALSE;
+  }
+
+  D3DVERTEXELEMENT9 elements[] = {
+    { 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT,
+      D3DDECLUSAGE_POSITION, 0 },
+    D3DDECL_END()
+  };
+  
+  mDevice->CreateVertexDeclaration(elements, getter_AddRefs(mVD));
+
+  SetupRenderState();
+
+  nsCOMPtr<nsIConsoleService> 
+    console(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
+
+  D3DADAPTER_IDENTIFIER9 identifier;
+  mD3D9->GetAdapterIdentifier(D3DADAPTER_DEFAULT, 0, &identifier);
+
+  if (console) {
+    nsString msg;
+    msg +=
+      NS_LITERAL_STRING("Direct3D 9 LayerManager Initialized Succesfully.\nDriver: ");
+    msg += NS_ConvertUTF8toUTF16(
+      nsDependentCString((const char*)identifier.Driver));
+    msg += NS_LITERAL_STRING("\nDescription: ");
+    msg += NS_ConvertUTF8toUTF16(
+      nsDependentCString((const char*)identifier.Description));
+    msg += NS_LITERAL_STRING("\nVersion: ");
+    msg += NS_ConvertUTF8toUTF16(
+      nsPrintfCString("%d.%d.%d.%d",
+                      HIWORD(identifier.DriverVersion.HighPart),
+                      LOWORD(identifier.DriverVersion.HighPart),
+                      HIWORD(identifier.DriverVersion.LowPart),
+                      LOWORD(identifier.DriverVersion.LowPart)));
+    console->LogStringMessage(msg.get());
+  }
+
+  return PR_TRUE;
+}
+
+void
+LayerManagerD3D9::SetClippingRegion(const nsIntRegion &aClippingRegion)
+{
+  mClippingRegion = aClippingRegion;
+}
+
+void
+LayerManagerD3D9::BeginTransaction()
+{
+}
+
+void
+LayerManagerD3D9::BeginTransactionWithTarget(gfxContext *aTarget)
+{
+  mTarget = aTarget;
+}
+
+void
+LayerManagerD3D9::EndConstruction()
+{
+}
+
+void
+LayerManagerD3D9::EndTransaction(DrawThebesLayerCallback aCallback,
+                                 void* aCallbackData)
+{
+  mCurrentCallbackInfo.Callback = aCallback;
+  mCurrentCallbackInfo.CallbackData = aCallbackData;
+  Render();
+  /* Clean this out for sanity */
+  mCurrentCallbackInfo.Callback = NULL;
+  mCurrentCallbackInfo.CallbackData = NULL;
+}
+
+void
+LayerManagerD3D9::SetRoot(Layer *aLayer)
+{
+  mRootLayer = static_cast<LayerD3D9*>(aLayer->ImplData());
+}
+
+already_AddRefed<ThebesLayer>
+LayerManagerD3D9::CreateThebesLayer()
+{
+  nsRefPtr<ThebesLayer> layer = new ThebesLayerD3D9(this);
+  return layer.forget();
+}
+
+already_AddRefed<ContainerLayer>
+LayerManagerD3D9::CreateContainerLayer()
+{
+  nsRefPtr<ContainerLayer> layer = new ContainerLayerD3D9(this);
+  return layer.forget();
+}
+
+already_AddRefed<ImageLayer>
+LayerManagerD3D9::CreateImageLayer()
+{
+  nsRefPtr<ImageLayer> layer = new ImageLayerD3D9(this);
+  return layer.forget();
+}
+
+already_AddRefed<ColorLayer>
+LayerManagerD3D9::CreateColorLayer()
+{
+  nsRefPtr<ColorLayer> layer = new ColorLayerD3D9(this);
+  return layer.forget();
+}
+
+already_AddRefed<CanvasLayer>
+LayerManagerD3D9::CreateCanvasLayer()
+{
+  nsRefPtr<CanvasLayer> layer = new CanvasLayerD3D9(this);
+  return layer.forget();
+}
+
+already_AddRefed<ImageContainer>
+LayerManagerD3D9::CreateImageContainer()
+{
+  nsRefPtr<ImageContainer> container = new ImageContainerD3D9(this);
+  return container.forget();
+}
+
+void
+LayerManagerD3D9::SetShaderMode(ShaderMode aMode)
+{
+  switch (aMode) {
+    case RGBLAYER:
+      mDevice->SetVertexShader(mLayerVS);
+      mDevice->SetPixelShader(mRGBPS);
+      break;
+    case YCBCRLAYER:
+      mDevice->SetVertexShader(mLayerVS);
+      mDevice->SetPixelShader(mYCbCrPS);
+      break;
+    case SOLIDCOLORLAYER:
+      mDevice->SetVertexShader(mLayerVS);
+      mDevice->SetPixelShader(mSolidColorPS);
+      break;
+  }
+}
+
+void
+LayerManagerD3D9::Render()
+{
+  if (!SetupBackBuffer()) {
+    return;
+  }
+  SetupPipeline();
+  nsIntRect rect;
+  mWidget->GetBounds(rect);
+
+  mDevice->Clear(0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0, 0);
+
+  mDevice->BeginScene();
+  
+  if (mRootLayer) {
+    const nsIntRect *clipRect = mRootLayer->GetLayer()->GetClipRect();
+    RECT r;
+    if (clipRect) {
+      r.left = (LONG)clipRect->x;
+      r.top = (LONG)clipRect->y;
+      r.right = (LONG)(clipRect->x + clipRect->width);
+      r.bottom = (LONG)(clipRect->y + clipRect->height);
+    } else {
+      r.left = r.top = 0;
+      r.right = rect.width;
+      r.bottom = rect.height;
+    }
+    mDevice->SetScissorRect(&r);
+
+    mRootLayer->RenderLayer();
+  }
+
+  mDevice->EndScene();
+
+  if (!mTarget) {
+    const nsIntRect *r;
+    for (nsIntRegionRectIterator iter(mClippingRegion);
+         (r = iter.Next()) != nsnull;) {
+      RECT rect;
+      rect.left = r->x;
+      rect.top = r->y;
+      rect.right = r->XMost();
+      rect.bottom = r->YMost();
+
+      mDevice->Present(&rect, &rect, NULL, NULL);
+    }
+  } else {
+    PaintToTarget();
+  }
+}
+
+void
+LayerManagerD3D9::SetupPipeline()
+{
+  nsIntRect rect;
+  mWidget->GetBounds(rect);
+
+  float viewMatrix[4][4];
+  /*
+   * Matrix to transform to viewport space ( <-1.0, 1.0> topleft, 
+   * <1.0, -1.0> bottomright)
+   */
+  memset(&viewMatrix, 0, sizeof(viewMatrix));
+  viewMatrix[0][0] = 2.0f / rect.width;
+  viewMatrix[1][1] = -2.0f / rect.height;
+  viewMatrix[2][2] = 1.0f;
+  viewMatrix[3][0] = -1.0f;
+  viewMatrix[3][1] = 1.0f;
+  viewMatrix[3][3] = 1.0f;
+  
+  HRESULT hr = mDevice->SetVertexShaderConstantF(8, &viewMatrix[0][0], 4);
+
+  if (FAILED(hr)) {
+    NS_WARNING("Failed to set projection shader constant!");
+  }
+}
+
+PRBool
+LayerManagerD3D9::SetupBackBuffer()
+{
+  nsRefPtr<IDirect3DSurface9> backBuffer;
+  mDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO,
+			 getter_AddRefs(backBuffer));
+
+  D3DSURFACE_DESC desc;
+  nsIntRect rect;
+  mWidget->GetBounds(rect);
+  backBuffer->GetDesc(&desc);
+
+  HRESULT hr = mDevice->TestCooperativeLevel();
+
+  /* The device is lost or something else is wrong, failure */
+  if (FAILED(hr) && hr != D3DERR_DEVICENOTRESET) {
+    return PR_FALSE;
+  }
+
+  /*
+   * If the backbuffer is the right size, and the device is not lost, we can
+   * safely render without doing anything.
+   */
+  if ((desc.Width == rect.width && desc.Height == rect.height) &&
+      SUCCEEDED(hr)) {
+    return PR_TRUE;
+  }
+
+  /*
+   * Our device is lost or our backbuffer needs resizing, start by clearing
+   * out all D3DPOOL_DEFAULT surfaces.
+   */
+  for(unsigned int i = 0; i < mThebesLayers.Length(); i++) {
+    mThebesLayers[i]->CleanResources();
+  }
+
+  backBuffer = NULL;
+
+  D3DPRESENT_PARAMETERS pp;
+  memset(&pp, 0, sizeof(D3DPRESENT_PARAMETERS));
+
+  pp.BackBufferFormat = D3DFMT_A8R8G8B8;
+  pp.SwapEffect = D3DSWAPEFFECT_COPY;
+  pp.Windowed = TRUE;
+  pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+  pp.hDeviceWindow = (HWND)mWidget->GetNativeData(NS_NATIVE_WINDOW);
+
+  hr = mDevice->Reset(&pp);
+  if (FAILED(hr)) {
+    return PR_FALSE;
+  }
+
+  SetupRenderState();
+
+  return PR_TRUE;
+}
+
+void
+LayerManagerD3D9::PaintToTarget()
+{
+  nsRefPtr<IDirect3DSurface9> backBuff;
+  nsRefPtr<IDirect3DSurface9> destSurf;
+  mDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO,
+                         getter_AddRefs(backBuff));
+
+  D3DSURFACE_DESC desc;
+  backBuff->GetDesc(&desc);
+
+  mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height,
+                                       D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM,
+                                       getter_AddRefs(destSurf), NULL);
+
+  mDevice->GetRenderTargetData(backBuff, destSurf);
+
+  D3DLOCKED_RECT rect;
+  destSurf->LockRect(&rect, NULL, D3DLOCK_READONLY);
+
+  nsRefPtr<gfxImageSurface> imageSurface =
+    new gfxImageSurface((unsigned char*)rect.pBits,
+                        gfxIntSize(desc.Width, desc.Height),
+                        rect.Pitch,
+                        gfxASurface::ImageFormatARGB32);
+
+  mTarget->SetSource(imageSurface);
+  mTarget->SetOperator(gfxContext::OPERATOR_OVER);
+  mTarget->Paint();
+  destSurf->UnlockRect();
+}
+
+void
+LayerManagerD3D9::SetupRenderState()
+{
+  mDevice->SetStreamSource(0, mVB, 0, sizeof(vertex));
+  mDevice->SetVertexDeclaration(mVD);
+  mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
+  mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
+  mDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
+  mDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
+  mDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
+  mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
+  mDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
+  mDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
+  mDevice->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
+  mDevice->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
+  mDevice->SetSamplerState(2, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
+  mDevice->SetSamplerState(2, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
+}
+
+PRBool
+LayerManagerD3D9::VerifyCaps()
+{
+  D3DCAPS9 caps;
+  HRESULT hr = mDevice->GetDeviceCaps(&caps);
+
+  if (FAILED(hr)) {
+    return PR_FALSE;
+  }
+
+  if (LACKS_CAP(caps.DevCaps, D3DDEVCAPS_TEXTUREVIDEOMEMORY)) {
+    return PR_FALSE;
+  }
+
+  if (LACKS_CAP(caps.PrimitiveMiscCaps, D3DPMISCCAPS_CULLNONE)) {
+    return PR_FALSE;
+  }
+
+  if (LACKS_CAP(caps.SrcBlendCaps, D3DPBLENDCAPS_ONE) ||
+      LACKS_CAP(caps.SrcBlendCaps, D3DBLEND_SRCALPHA) ||
+      LACKS_CAP(caps.DestBlendCaps, D3DPBLENDCAPS_INVSRCALPHA)) {
+    return PR_FALSE;
+  }
+
+  if (LACKS_CAP(caps.RasterCaps, D3DPRASTERCAPS_SCISSORTEST)) {
+    return PR_FALSE;
+  }
+
+  if (LACKS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_ALPHA) ||
+      HAS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_SQUAREONLY) ||
+      (HAS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_POW2) &&
+       LACKS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_NONPOW2CONDITIONAL))) {
+    return PR_FALSE;
+  }
+
+  if (LACKS_CAP(caps.TextureFilterCaps, D3DPTFILTERCAPS_MAGFLINEAR) ||
+      LACKS_CAP(caps.TextureFilterCaps, D3DPTFILTERCAPS_MINFLINEAR)) {
+    return PR_FALSE;
+  }
+
+  if (LACKS_CAP(caps.TextureAddressCaps, D3DPTADDRESSCAPS_CLAMP)) {
+    return PR_FALSE;
+  }
+
+  if (caps.MaxTextureHeight < 4096 ||
+      caps.MaxTextureWidth < 4096) {
+    return PR_FALSE;
+  }
+
+  if ((caps.PixelShaderVersion & 0xffff) < 0x200 ||
+      (caps.VertexShaderVersion & 0xffff) < 0x200) {
+    return PR_FALSE;
+  }
+  return PR_TRUE;
+}
+
+LayerD3D9::LayerD3D9(LayerManagerD3D9 *aManager)
+  : mD3DManager(aManager)
+  , mNextSibling(NULL)
+{
+}
+
+LayerD3D9*
+LayerD3D9::GetNextSibling()
+{
+  return mNextSibling;
+}
+
+void
+LayerD3D9::SetNextSibling(LayerD3D9 *aNextSibling)
+{
+  mNextSibling = aNextSibling;
+}
+
+} /* namespace layers */
+} /* namespace mozilla */
new file mode 100644
--- /dev/null
+++ b/gfx/layers/d3d9/LayerManagerD3D9.h
@@ -0,0 +1,239 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Corporation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Bas Schouten <bschouten@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef GFX_LAYERMANAGERD3D9_H
+#define GFX_LAYERMANAGERD3D9_H
+
+#include "Layers.h"
+
+#include <windows.h>
+#include <d3d9.h>
+
+#include "gfxContext.h"
+#include "nsIWidget.h"
+
+namespace mozilla {
+namespace layers {
+
+class LayerD3D9;
+class ThebesLayerD3D9;
+
+/*
+ * This is the LayerManager used for Direct3D 9. For now this will render on
+ * the main thread.
+ */
+class THEBES_API LayerManagerD3D9 : public LayerManager {
+public:
+  LayerManagerD3D9(nsIWidget *aWidget);
+  virtual ~LayerManagerD3D9();
+
+  /*
+   * Initializes the layer manager, this is when the layer manager will
+   * actually access the device and attempt to create the swap chain used
+   * to draw to the window. If this method fails the device cannot be used.
+   * This function is not threadsafe.
+   *
+   * \return True is initialization was succesful, false when it was not.
+   */
+  PRBool Initialize();
+
+  /*
+   * Sets the clipping region for this layer manager. This is important on 
+   * windows because using OGL we no longer have GDI's native clipping. Therefor
+   * widget must tell us what part of the screen is being invalidated,
+   * and we should clip to this.
+   *
+   * \param aClippingRegion Region to clip to. Setting an empty region
+   * will disable clipping.
+   */
+  void SetClippingRegion(const nsIntRegion& aClippingRegion);
+
+  /*
+   * LayerManager implementation.
+   */
+  void BeginTransaction();
+
+  void BeginTransactionWithTarget(gfxContext* aTarget);
+
+  void EndConstruction();
+
+  struct CallbackInfo {
+    DrawThebesLayerCallback Callback;
+    void *CallbackData;
+  };
+
+  void EndTransaction(DrawThebesLayerCallback aCallback,
+                      void* aCallbackData);
+
+  const CallbackInfo &GetCallbackInfo() { return mCurrentCallbackInfo; }
+
+  void SetRoot(Layer* aLayer);
+  
+  virtual already_AddRefed<ThebesLayer> CreateThebesLayer();
+
+  virtual already_AddRefed<ContainerLayer> CreateContainerLayer();
+
+  virtual already_AddRefed<ImageLayer> CreateImageLayer();
+
+  virtual already_AddRefed<ColorLayer> CreateColorLayer();
+
+  virtual already_AddRefed<CanvasLayer> CreateCanvasLayer();
+
+  virtual already_AddRefed<ImageContainer> CreateImageContainer();
+
+  virtual LayersBackend GetBackendType() { return LAYERS_D3D9; }
+
+  /*
+   * Helper methods.
+   */
+  void SetClippingEnabled(PRBool aEnabled);
+
+  IDirect3DDevice9 *device() const { return mDevice; }
+
+  enum ShaderMode {
+    RGBLAYER,
+    YCBCRLAYER,
+    SOLIDCOLORLAYER
+  };
+
+  void SetShaderMode(ShaderMode aMode);
+
+  nsTArray<ThebesLayerD3D9*> mThebesLayers;
+
+private:
+  /* Direct3D9 instance */
+  static IDirect3D9 *mD3D9;
+
+  /* Widget associated with this layer manager */
+  nsIWidget *mWidget;
+  /* 
+   * Context target, NULL when drawing directly to our swap chain.
+   */
+  nsRefPtr<gfxContext> mTarget;
+
+  nsRefPtr<IDirect3DDevice9> mDevice;
+
+  /* Vertex shader used for layer quads */
+  nsRefPtr<IDirect3DVertexShader9> mLayerVS;
+
+  /* Pixel shader used for RGB textures */
+  nsRefPtr<IDirect3DPixelShader9> mRGBPS;
+
+  /* Pixel shader used for RGB textures */
+  nsRefPtr<IDirect3DPixelShader9> mYCbCrPS;
+
+  /* Pixel shader used for solid colors */
+  nsRefPtr<IDirect3DPixelShader9> mSolidColorPS;
+
+  /* Vertex buffer containing our basic vertex structure */
+  nsRefPtr<IDirect3DVertexBuffer9> mVB;
+
+  /* Our vertex declaration */
+  nsRefPtr<IDirect3DVertexDeclaration9> mVD;
+
+  /* Current root layer. */
+  LayerD3D9 *mRootLayer;
+
+  /* Callback info for current transaction */
+  CallbackInfo mCurrentCallbackInfo;
+  
+  /*
+   * Region we're clipping our current drawing to.
+   */
+  nsIntRegion mClippingRegion;
+  /*
+   * Render the current layer tree to the active target.
+   */
+  void Render();
+  /*
+   * Setup the pipeline.
+   */
+  void SetupPipeline();
+  /*
+   * Setup the backbuffer.
+   *
+   * \return PR_TRUE if setup was succesful
+   */
+  PRBool SetupBackBuffer();
+  /*
+   * Setup the render state for the surface.
+   */
+  void SetupRenderState();
+  /*
+   * Copies the content of our backbuffer to the set transaction target.
+   */
+  void PaintToTarget();
+  /*
+   * Verifies all required device capabilities are present.
+   */
+  PRBool VerifyCaps();
+
+};
+
+/*
+ * General information and tree management for OGL layers.
+ */
+class LayerD3D9
+{
+public:
+  LayerD3D9(LayerManagerD3D9 *aManager);
+
+  enum LayerType { TYPE_THEBES, TYPE_CONTAINER, TYPE_IMAGE, TYPE_COLOR,
+                   TYPE_CANVAS };
+  
+  virtual LayerType GetType() = 0;
+
+  LayerD3D9 *GetNextSibling();
+  virtual LayerD3D9 *GetFirstChildD3D9() { return nsnull; }
+
+  void SetNextSibling(LayerD3D9 *aParent);
+  void SetFirstChild(LayerD3D9 *aParent);
+
+  virtual Layer* GetLayer() = 0;
+
+  virtual void RenderLayer() = 0;
+
+  IDirect3DDevice9 *device() const { return mD3DManager->device(); }
+protected:
+  LayerManagerD3D9 *mD3DManager;
+  LayerD3D9 *mNextSibling;
+};
+
+} /* layers */
+} /* mozilla */
+
+#endif /* GFX_LAYERMANAGERD3D9_H */
new file mode 100644
--- /dev/null
+++ b/gfx/layers/d3d9/LayerManagerD3D9Shaders.h
@@ -0,0 +1,435 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 9.27.952.3022
+//
+//   fxc LayerManagerD3D9Shaders.hlsl /ELayerQuadVS /nologo
+//    /FhLayerManagerD3D9Shaders.h /VnLayerQuadVS
+//
+//
+// Parameters:
+//
+//   float4x4 mLayerQuadTransform;
+//   float4x4 mLayerTransform;
+//   float4x4 mProjection;
+//   float4 vRenderTargetOffset;
+//
+//
+// Registers:
+//
+//   Name                Reg   Size
+//   ------------------- ----- ----
+//   mLayerQuadTransform c0       4
+//   mLayerTransform     c4       4
+//   mProjection         c8       4
+//   vRenderTargetOffset c12      1
+//
+
+    vs_2_0
+    dcl_position v0
+    mul r0, v0.y, c1
+    mad r0, c0, v0.x, r0
+    mad r0, c2, v0.z, r0
+    mad r0, c3, v0.w, r0
+    mul r1, r0.y, c5
+    mad r1, c4, r0.x, r1
+    mad r1, c6, r0.z, r1
+    mad r0, c7, r0.w, r1
+    add r0, r0, -c12
+    mul r1, r0.y, c9
+    mad r1, c8, r0.x, r1
+    mad r1, c10, r0.z, r1
+    mad oPos, c11, r0.w, r1
+    mov oT0.xy, v0
+
+// approximately 14 instruction slots used
+#endif
+
+const BYTE LayerQuadVS[] =
+{
+      0,   2, 254, 255, 254, 255, 
+     67,   0,  67,  84,  65,  66, 
+     28,   0,   0,   0, 215,   0, 
+      0,   0,   0,   2, 254, 255, 
+      4,   0,   0,   0,  28,   0, 
+      0,   0,   0,   1,   0,   0, 
+    208,   0,   0,   0, 108,   0, 
+      0,   0,   2,   0,   0,   0, 
+      4,   0,   0,   0, 128,   0, 
+      0,   0,   0,   0,   0,   0, 
+    144,   0,   0,   0,   2,   0, 
+      4,   0,   4,   0,   0,   0, 
+    128,   0,   0,   0,   0,   0, 
+      0,   0, 160,   0,   0,   0, 
+      2,   0,   8,   0,   4,   0, 
+      0,   0, 128,   0,   0,   0, 
+      0,   0,   0,   0, 172,   0, 
+      0,   0,   2,   0,  12,   0, 
+      1,   0,   0,   0, 192,   0, 
+      0,   0,   0,   0,   0,   0, 
+    109,  76,  97, 121, 101, 114, 
+     81, 117,  97, 100,  84, 114, 
+     97, 110, 115, 102, 111, 114, 
+    109,   0,   3,   0,   3,   0, 
+      4,   0,   4,   0,   1,   0, 
+      0,   0,   0,   0,   0,   0, 
+    109,  76,  97, 121, 101, 114, 
+     84, 114,  97, 110, 115, 102, 
+    111, 114, 109,   0, 109,  80, 
+    114, 111, 106, 101,  99, 116, 
+    105, 111, 110,   0, 118,  82, 
+    101, 110, 100, 101, 114,  84, 
+     97, 114, 103, 101, 116,  79, 
+    102, 102, 115, 101, 116,   0, 
+      1,   0,   3,   0,   1,   0, 
+      4,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0, 118, 115, 
+     95,  50,  95,  48,   0,  77, 
+    105,  99, 114, 111, 115, 111, 
+    102, 116,  32,  40,  82,  41, 
+     32,  72,  76,  83,  76,  32, 
+     83, 104,  97, 100, 101, 114, 
+     32,  67, 111, 109, 112, 105, 
+    108, 101, 114,  32,  57,  46, 
+     50,  55,  46,  57,  53,  50, 
+     46,  51,  48,  50,  50,   0, 
+     31,   0,   0,   2,   0,   0, 
+      0, 128,   0,   0,  15, 144, 
+      5,   0,   0,   3,   0,   0, 
+     15, 128,   0,   0,  85, 144, 
+      1,   0, 228, 160,   4,   0, 
+      0,   4,   0,   0,  15, 128, 
+      0,   0, 228, 160,   0,   0, 
+      0, 144,   0,   0, 228, 128, 
+      4,   0,   0,   4,   0,   0, 
+     15, 128,   2,   0, 228, 160, 
+      0,   0, 170, 144,   0,   0, 
+    228, 128,   4,   0,   0,   4, 
+      0,   0,  15, 128,   3,   0, 
+    228, 160,   0,   0, 255, 144, 
+      0,   0, 228, 128,   5,   0, 
+      0,   3,   1,   0,  15, 128, 
+      0,   0,  85, 128,   5,   0, 
+    228, 160,   4,   0,   0,   4, 
+      1,   0,  15, 128,   4,   0, 
+    228, 160,   0,   0,   0, 128, 
+      1,   0, 228, 128,   4,   0, 
+      0,   4,   1,   0,  15, 128, 
+      6,   0, 228, 160,   0,   0, 
+    170, 128,   1,   0, 228, 128, 
+      4,   0,   0,   4,   0,   0, 
+     15, 128,   7,   0, 228, 160, 
+      0,   0, 255, 128,   1,   0, 
+    228, 128,   2,   0,   0,   3, 
+      0,   0,  15, 128,   0,   0, 
+    228, 128,  12,   0, 228, 161, 
+      5,   0,   0,   3,   1,   0, 
+     15, 128,   0,   0,  85, 128, 
+      9,   0, 228, 160,   4,   0, 
+      0,   4,   1,   0,  15, 128, 
+      8,   0, 228, 160,   0,   0, 
+      0, 128,   1,   0, 228, 128, 
+      4,   0,   0,   4,   1,   0, 
+     15, 128,  10,   0, 228, 160, 
+      0,   0, 170, 128,   1,   0, 
+    228, 128,   4,   0,   0,   4, 
+      0,   0,  15, 192,  11,   0, 
+    228, 160,   0,   0, 255, 128, 
+      1,   0, 228, 128,   1,   0, 
+      0,   2,   0,   0,   3, 224, 
+      0,   0, 228, 144, 255, 255, 
+      0,   0
+};
+
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 9.27.952.3022
+//
+//   fxc LayerManagerD3D9Shaders.hlsl /ERGBShader /nologo /Tps_2_0
+//    /FhLayerManagerD3D9Shaders.h /VnRGBShaderPS
+//
+//
+// Parameters:
+//
+//   float fLayerOpacity;
+//   sampler2D s2D;
+//
+//
+// Registers:
+//
+//   Name          Reg   Size
+//   ------------- ----- ----
+//   fLayerOpacity c0       1
+//   s2D           s0       1
+//
+
+    ps_2_0
+    dcl t0.xy
+    dcl_2d s0
+    texld r0, t0, s0
+    mul r0, r0, c0.x
+    mov oC0, r0
+
+// approximately 3 instruction slots used (1 texture, 2 arithmetic)
+#endif
+
+const BYTE RGBShaderPS[] =
+{
+      0,   2, 255, 255, 254, 255, 
+     45,   0,  67,  84,  65,  66, 
+     28,   0,   0,   0, 127,   0, 
+      0,   0,   0,   2, 255, 255, 
+      2,   0,   0,   0,  28,   0, 
+      0,   0,   0,   1,   0,   0, 
+    120,   0,   0,   0,  68,   0, 
+      0,   0,   2,   0,   0,   0, 
+      1,   0,   0,   0,  84,   0, 
+      0,   0,   0,   0,   0,   0, 
+    100,   0,   0,   0,   3,   0, 
+      0,   0,   1,   0,   0,   0, 
+    104,   0,   0,   0,   0,   0, 
+      0,   0, 102,  76,  97, 121, 
+    101, 114,  79, 112,  97,  99, 
+    105, 116, 121,   0, 171, 171, 
+      0,   0,   3,   0,   1,   0, 
+      1,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0, 115,  50, 
+     68,   0,   4,   0,  12,   0, 
+      1,   0,   1,   0,   1,   0, 
+      0,   0,   0,   0,   0,   0, 
+    112, 115,  95,  50,  95,  48, 
+      0,  77, 105,  99, 114, 111, 
+    115, 111, 102, 116,  32,  40, 
+     82,  41,  32,  72,  76,  83, 
+     76,  32,  83, 104,  97, 100, 
+    101, 114,  32,  67, 111, 109, 
+    112, 105, 108, 101, 114,  32, 
+     57,  46,  50,  55,  46,  57, 
+     53,  50,  46,  51,  48,  50, 
+     50,   0,  31,   0,   0,   2, 
+      0,   0,   0, 128,   0,   0, 
+      3, 176,  31,   0,   0,   2, 
+      0,   0,   0, 144,   0,   8, 
+     15, 160,  66,   0,   0,   3, 
+      0,   0,  15, 128,   0,   0, 
+    228, 176,   0,   8, 228, 160, 
+      5,   0,   0,   3,   0,   0, 
+     15, 128,   0,   0, 228, 128, 
+      0,   0,   0, 160,   1,   0, 
+      0,   2,   0,   8,  15, 128, 
+      0,   0, 228, 128, 255, 255, 
+      0,   0
+};
+
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 9.27.952.3022
+//
+//   fxc LayerManagerD3D9Shaders.hlsl /EYCbCrShader /nologo /Tps_2_0
+//    /FhLayerManagerD3D9Shaders.h /VnYCbCrShaderPS
+//
+//
+// Parameters:
+//
+//   float fLayerOpacity;
+//   sampler2D s2DCb;
+//   sampler2D s2DCr;
+//   sampler2D s2DY;
+//
+//
+// Registers:
+//
+//   Name          Reg   Size
+//   ------------- ----- ----
+//   fLayerOpacity c0       1
+//   s2DY          s0       1
+//   s2DCb         s1       1
+//   s2DCr         s2       1
+//
+
+    ps_2_0
+    def c1, -0.5, -0.0625, 1.16400003, 1.59599996
+    def c2, 0.813000023, 0.391000003, 2.01799989, 1
+    dcl t0.xy
+    dcl_2d s0
+    dcl_2d s1
+    dcl_2d s2
+    texld r0, t0, s2
+    texld r1, t0, s0
+    texld r2, t0, s1
+    add r0.x, r0.x, c1.x
+    add r0.y, r1.x, c1.y
+    mul r0.y, r0.y, c1.z
+    mad r0.z, r0.x, -c2.x, r0.y
+    mad r1.x, r0.x, c1.w, r0.y
+    add r0.x, r2.x, c1.x
+    mad r1.y, r0.x, -c2.y, r0.z
+    mad r1.z, r0.x, c2.z, r0.y
+    mov r1.w, c2.w
+    mul r0, r1, c0.x
+    mov oC0, r0
+
+// approximately 14 instruction slots used (3 texture, 11 arithmetic)
+#endif
+
+const BYTE YCbCrShaderPS[] =
+{
+      0,   2, 255, 255, 254, 255, 
+     68,   0,  67,  84,  65,  66, 
+     28,   0,   0,   0, 219,   0, 
+      0,   0,   0,   2, 255, 255, 
+      4,   0,   0,   0,  28,   0, 
+      0,   0,   0,   1,   0,   0, 
+    212,   0,   0,   0, 108,   0, 
+      0,   0,   2,   0,   0,   0, 
+      1,   0,   0,   0, 124,   0, 
+      0,   0,   0,   0,   0,   0, 
+    140,   0,   0,   0,   3,   0, 
+      1,   0,   1,   0,   0,   0, 
+    148,   0,   0,   0,   0,   0, 
+      0,   0, 164,   0,   0,   0, 
+      3,   0,   2,   0,   1,   0, 
+      0,   0, 172,   0,   0,   0, 
+      0,   0,   0,   0, 188,   0, 
+      0,   0,   3,   0,   0,   0, 
+      1,   0,   0,   0, 196,   0, 
+      0,   0,   0,   0,   0,   0, 
+    102,  76,  97, 121, 101, 114, 
+     79, 112,  97,  99, 105, 116, 
+    121,   0, 171, 171,   0,   0, 
+      3,   0,   1,   0,   1,   0, 
+      1,   0,   0,   0,   0,   0, 
+      0,   0, 115,  50,  68,  67, 
+     98,   0, 171, 171,   4,   0, 
+     12,   0,   1,   0,   1,   0, 
+      1,   0,   0,   0,   0,   0, 
+      0,   0, 115,  50,  68,  67, 
+    114,   0, 171, 171,   4,   0, 
+     12,   0,   1,   0,   1,   0, 
+      1,   0,   0,   0,   0,   0, 
+      0,   0, 115,  50,  68,  89, 
+      0, 171, 171, 171,   4,   0, 
+     12,   0,   1,   0,   1,   0, 
+      1,   0,   0,   0,   0,   0, 
+      0,   0, 112, 115,  95,  50, 
+     95,  48,   0,  77, 105,  99, 
+    114, 111, 115, 111, 102, 116, 
+     32,  40,  82,  41,  32,  72, 
+     76,  83,  76,  32,  83, 104, 
+     97, 100, 101, 114,  32,  67, 
+    111, 109, 112, 105, 108, 101, 
+    114,  32,  57,  46,  50,  55, 
+     46,  57,  53,  50,  46,  51, 
+     48,  50,  50,   0,  81,   0, 
+      0,   5,   1,   0,  15, 160, 
+      0,   0,   0, 191,   0,   0, 
+    128, 189, 244, 253, 148,  63, 
+    186,  73, 204,  63,  81,   0, 
+      0,   5,   2,   0,  15, 160, 
+    197,  32,  80,  63,  39,  49, 
+    200,  62, 233,  38,   1,  64, 
+      0,   0, 128,  63,  31,   0, 
+      0,   2,   0,   0,   0, 128, 
+      0,   0,   3, 176,  31,   0, 
+      0,   2,   0,   0,   0, 144, 
+      0,   8,  15, 160,  31,   0, 
+      0,   2,   0,   0,   0, 144, 
+      1,   8,  15, 160,  31,   0, 
+      0,   2,   0,   0,   0, 144, 
+      2,   8,  15, 160,  66,   0, 
+      0,   3,   0,   0,  15, 128, 
+      0,   0, 228, 176,   2,   8, 
+    228, 160,  66,   0,   0,   3, 
+      1,   0,  15, 128,   0,   0, 
+    228, 176,   0,   8, 228, 160, 
+     66,   0,   0,   3,   2,   0, 
+     15, 128,   0,   0, 228, 176, 
+      1,   8, 228, 160,   2,   0, 
+      0,   3,   0,   0,   1, 128, 
+      0,   0,   0, 128,   1,   0, 
+      0, 160,   2,   0,   0,   3, 
+      0,   0,   2, 128,   1,   0, 
+      0, 128,   1,   0,  85, 160, 
+      5,   0,   0,   3,   0,   0, 
+      2, 128,   0,   0,  85, 128, 
+      1,   0, 170, 160,   4,   0, 
+      0,   4,   0,   0,   4, 128, 
+      0,   0,   0, 128,   2,   0, 
+      0, 161,   0,   0,  85, 128, 
+      4,   0,   0,   4,   1,   0, 
+      1, 128,   0,   0,   0, 128, 
+      1,   0, 255, 160,   0,   0, 
+     85, 128,   2,   0,   0,   3, 
+      0,   0,   1, 128,   2,   0, 
+      0, 128,   1,   0,   0, 160, 
+      4,   0,   0,   4,   1,   0, 
+      2, 128,   0,   0,   0, 128, 
+      2,   0,  85, 161,   0,   0, 
+    170, 128,   4,   0,   0,   4, 
+      1,   0,   4, 128,   0,   0, 
+      0, 128,   2,   0, 170, 160, 
+      0,   0,  85, 128,   1,   0, 
+      0,   2,   1,   0,   8, 128, 
+      2,   0, 255, 160,   5,   0, 
+      0,   3,   0,   0,  15, 128, 
+      1,   0, 228, 128,   0,   0, 
+      0, 160,   1,   0,   0,   2, 
+      0,   8,  15, 128,   0,   0, 
+    228, 128, 255, 255,   0,   0
+};
+
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 9.27.952.3022
+//
+//   fxc LayerManagerD3D9Shaders.hlsl /ESolidColorShader /nologo /Tps_2_0
+//    /FhLayerManagerD3D9Shaders.h /VnSolidColorShaderPS
+//
+//
+// Parameters:
+//
+//   float4 fLayerColor;
+//
+//
+// Registers:
+//
+//   Name         Reg   Size
+//   ------------ ----- ----
+//   fLayerColor  c0       1
+//
+
+    ps_2_0
+    mov oC0, c0
+
+// approximately 1 instruction slot used
+#endif
+
+const BYTE SolidColorShaderPS[] =
+{
+      0,   2, 255, 255, 254, 255, 
+     34,   0,  67,  84,  65,  66, 
+     28,   0,   0,   0,  83,   0, 
+      0,   0,   0,   2, 255, 255, 
+      1,   0,   0,   0,  28,   0, 
+      0,   0,   0,   1,   0,   0, 
+     76,   0,   0,   0,  48,   0, 
+      0,   0,   2,   0,   0,   0, 
+      1,   0,   0,   0,  60,   0, 
+      0,   0,   0,   0,   0,   0, 
+    102,  76,  97, 121, 101, 114, 
+     67, 111, 108, 111, 114,   0, 
+      1,   0,   3,   0,   1,   0, 
+      4,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0, 112, 115, 
+     95,  50,  95,  48,   0,  77, 
+    105,  99, 114, 111, 115, 111, 
+    102, 116,  32,  40,  82,  41, 
+     32,  72,  76,  83,  76,  32, 
+     83, 104,  97, 100, 101, 114, 
+     32,  67, 111, 109, 112, 105, 
+    108, 101, 114,  32,  57,  46, 
+     50,  55,  46,  57,  53,  50, 
+     46,  51,  48,  50,  50,   0, 
+      1,   0,   0,   2,   0,   8, 
+     15, 128,   0,   0, 228, 160, 
+    255, 255,   0,   0
+};
new file mode 100644
--- /dev/null
+++ b/gfx/layers/d3d9/LayerManagerD3D9Shaders.hlsl
@@ -0,0 +1,61 @@
+float4x4 mLayerQuadTransform;
+float4x4 mLayerTransform;
+float4 vRenderTargetOffset;
+float4x4 mProjection;
+
+texture tex0;
+sampler s2D;
+sampler s2DY;
+sampler s2DCb;
+sampler s2DCr;
+
+float fLayerOpacity;
+float4 fLayerColor;
+
+struct VS_INPUT {
+  float4 vPosition : POSITION;
+};
+
+struct VS_OUTPUT {
+  float4 vPosition : POSITION;
+  float2 vTexCoords : TEXCOORD0;
+};
+
+VS_OUTPUT LayerQuadVS(const VS_INPUT aVertex)
+{
+  VS_OUTPUT outp;
+  outp.vPosition = aVertex.vPosition;
+  outp.vPosition = mul(mLayerQuadTransform, outp.vPosition);
+  outp.vPosition = mul(mLayerTransform, outp.vPosition);
+  outp.vPosition = outp.vPosition - vRenderTargetOffset;
+  outp.vPosition = mul(mProjection, outp.vPosition);
+  outp.vTexCoords = aVertex.vPosition.xy;
+  return outp;
+}
+
+float4 RGBShader(const VS_OUTPUT aVertex) : COLOR
+{
+  return tex2D(s2D, aVertex.vTexCoords) * fLayerOpacity;
+}
+
+float4 YCbCrShader(const VS_OUTPUT aVertex) : COLOR
+{
+  float4 yuv;
+  float4 color;
+
+  yuv.r = tex2D(s2DCr, aVertex.vTexCoords).r - 0.5;
+  yuv.g = tex2D(s2DY, aVertex.vTexCoords).r - 0.0625;
+  yuv.b = tex2D(s2DCb, aVertex.vTexCoords).r - 0.5;
+
+  color.r = yuv.g * 1.164 + yuv.r * 1.596;
+  color.g = yuv.g * 1.164 - 0.813 * yuv.r - 0.391 * yuv.b;
+  color.b = yuv.g * 1.164 + yuv.b * 2.018;
+  color.a = 1.0f;
+  
+  return color * fLayerOpacity;
+}
+
+float4 SolidColorShader(const VS_OUTPUT aVertex) : COLOR
+{
+  return fLayerColor;
+}
new file mode 100644
--- /dev/null
+++ b/gfx/layers/d3d9/ThebesLayerD3D9.cpp
@@ -0,0 +1,216 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Corporation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Bas Schouten <bschouten@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "ThebesLayerD3D9.h"
+#include "gfxPlatform.h"
+
+namespace mozilla {
+namespace layers {
+
+ThebesLayerD3D9::ThebesLayerD3D9(LayerManagerD3D9 *aManager)
+  : ThebesLayer(aManager, NULL)
+  , LayerD3D9(aManager)
+{
+  mImplData = static_cast<LayerD3D9*>(this);
+  aManager->mThebesLayers.AppendElement(this);
+}
+
+ThebesLayerD3D9::~ThebesLayerD3D9()
+{
+  mD3DManager->mThebesLayers.RemoveElement(this);
+}
+
+
+void
+ThebesLayerD3D9::SetVisibleRegion(const nsIntRegion &aRegion)
+{
+  if (aRegion.GetBounds() == mVisibleRect) {
+    return;
+  }
+  mVisibleRect = aRegion.GetBounds();
+
+  device()->CreateTexture(mVisibleRect.width, mVisibleRect.height, 1,
+			  D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8,
+			  D3DPOOL_DEFAULT, getter_AddRefs(mTexture), NULL);
+
+  mInvalidatedRect = mVisibleRect;
+}
+
+
+void
+ThebesLayerD3D9::InvalidateRegion(const nsIntRegion &aRegion)
+{
+  nsIntRegion invalidatedRegion;
+  invalidatedRegion.Or(aRegion, mInvalidatedRect);
+  invalidatedRegion.And(invalidatedRegion, mVisibleRect);
+  mInvalidatedRect = invalidatedRegion.GetBounds();
+}
+
+LayerD3D9::LayerType
+ThebesLayerD3D9::GetType()
+{
+  return TYPE_THEBES;
+}
+
+const nsIntRect&
+ThebesLayerD3D9::GetVisibleRect()
+{
+  return mVisibleRect;
+}
+
+void
+ThebesLayerD3D9::RenderLayer()
+{
+  if (!mTexture) {
+    device()->CreateTexture(mVisibleRect.width, mVisibleRect.height, 1,
+			      D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8,
+			      D3DPOOL_DEFAULT, getter_AddRefs(mTexture), NULL);
+    mInvalidatedRect = mVisibleRect;
+  }
+  if (!mInvalidatedRect.IsEmpty()) {
+    nsIntRegion region = mInvalidatedRect;
+
+    gfxASurface::gfxImageFormat imageFormat = gfxASurface::ImageFormatARGB32;;
+    nsRefPtr<gfxASurface> destinationSurface;
+    nsRefPtr<gfxContext> context;
+
+    destinationSurface =
+      gfxPlatform::GetPlatform()->
+        CreateOffscreenSurface(gfxIntSize(mInvalidatedRect.width,
+                                          mInvalidatedRect.height),
+                               imageFormat);
+
+    context = new gfxContext(destinationSurface);
+    context->Translate(gfxPoint(-mInvalidatedRect.x, -mInvalidatedRect.y));
+    LayerManagerD3D9::CallbackInfo cbInfo = mD3DManager->GetCallbackInfo();
+    cbInfo.Callback(this, context, region, cbInfo.CallbackData);
+    
+    nsRefPtr<IDirect3DTexture9> tmpTexture;
+    device()->CreateTexture(mInvalidatedRect.width, mInvalidatedRect.height, 1,
+			    0, D3DFMT_A8R8G8B8,
+			    D3DPOOL_SYSTEMMEM, getter_AddRefs(tmpTexture), NULL);
+
+    D3DLOCKED_RECT r;
+    tmpTexture->LockRect(0, &r, NULL, 0);
+
+    nsRefPtr<gfxImageSurface> imgSurface =
+      new gfxImageSurface((unsigned char *)r.pBits,
+                          gfxIntSize(mInvalidatedRect.width,
+                                     mInvalidatedRect.height),
+                          r.Pitch,
+                          imageFormat);
+
+    context = new gfxContext(imgSurface);
+    context->SetSource(destinationSurface);
+    context->SetOperator(gfxContext::OPERATOR_SOURCE);
+    context->Paint();
+
+    imgSurface = NULL;
+
+    tmpTexture->UnlockRect(0);
+
+    nsRefPtr<IDirect3DSurface9> srcSurface;
+    nsRefPtr<IDirect3DSurface9> dstSurface;
+    
+    mTexture->GetSurfaceLevel(0, getter_AddRefs(dstSurface));
+    tmpTexture->GetSurfaceLevel(0, getter_AddRefs(srcSurface));
+    
+    POINT point;
+    point.x = mInvalidatedRect.x - mVisibleRect.x;
+    point.y = mInvalidatedRect.y - mVisibleRect.y;
+    device()->UpdateSurface(srcSurface, NULL, dstSurface, &point);
+  }
+  
+  float quadTransform[4][4];
+  /*
+   * Matrix to transform the <0.0,0.0>, <1.0,1.0> quad to the correct position
+   * and size. To get pixel perfect mapping we offset the quad half a pixel
+   * to the top-left.
+   * 
+   * See: http://msdn.microsoft.com/en-us/library/bb219690%28VS.85%29.aspx
+   */
+  memset(&quadTransform, 0, sizeof(quadTransform));
+  quadTransform[0][0] = (float)GetVisibleRect().width;
+  quadTransform[1][1] = (float)GetVisibleRect().height;
+  quadTransform[2][2] = 1.0f;
+  quadTransform[3][0] = (float)GetVisibleRect().x - 0.5f;
+  quadTransform[3][1] = (float)GetVisibleRect().y - 0.5f;
+  quadTransform[3][3] = 1.0f;
+
+  device()->SetVertexShaderConstantF(0, &quadTransform[0][0], 4);
+  device()->SetVertexShaderConstantF(4, &mTransform._11, 4);
+
+  float opacity[4];
+  /*
+   * We always upload a 4 component float, but the shader will use only the
+   * first component since it's declared as a 'float'.
+   */
+  opacity[0] = GetOpacity();
+  device()->SetPixelShaderConstantF(0, opacity, 1);
+
+  mD3DManager->SetShaderMode(LayerManagerD3D9::RGBLAYER);
+
+  device()->SetTexture(0, mTexture);
+  device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
+}
+
+void
+ThebesLayerD3D9::CleanResources()
+{
+  mTexture = nsnull;
+}
+
+const nsIntRect&
+ThebesLayerD3D9::GetInvalidatedRect()
+{
+  return mInvalidatedRect;
+}
+
+Layer*
+ThebesLayerD3D9::GetLayer()
+{
+  return this;
+}
+
+PRBool
+ThebesLayerD3D9::IsEmpty()
+{
+  return !mTexture;
+}
+
+} /* namespace layers */
+} /* namespace mozilla */
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/gfx/layers/d3d9/ThebesLayerD3D9.h
@@ -0,0 +1,92 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Corporation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Bas Schouten <bschouten@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef GFX_THEBESLAYERD3D9_H
+#define GFX_THEBESLAYERD3D9_H
+
+#include "Layers.h"
+#include "LayerManagerD3D9.h"
+#include "gfxImageSurface.h"
+
+
+namespace mozilla {
+namespace layers {
+
+class ThebesLayerD3D9 : public ThebesLayer, 
+                        public LayerD3D9
+{
+public:
+  ThebesLayerD3D9(LayerManagerD3D9 *aManager);
+  virtual ~ThebesLayerD3D9();
+
+  /* Layer implementation */
+  void SetVisibleRegion(const nsIntRegion& aRegion);
+
+  /* ThebesLayer implementation */
+  void InvalidateRegion(const nsIntRegion& aRegion);
+
+  /* LayerD3D9 implementation */
+  LayerType GetType();
+  Layer* GetLayer();
+  virtual PRBool IsEmpty();
+  virtual void RenderLayer();
+  virtual void CleanResources();
+
+  /* ThebesLayerD3D9 */
+  const nsIntRect &GetVisibleRect();
+  const nsIntRect &GetInvalidatedRect();
+
+private:
+  /* 
+   * Visible rectangle, this is used to know the size and position of the quad
+   * when doing the rendering of this layer.
+   */
+  nsIntRect mVisibleRect;
+  /*
+   * Currently invalidated rectangular area.
+   */
+  nsIntRect mInvalidatedRect;
+
+  /*
+   * D3D9 texture
+   */
+  nsRefPtr<IDirect3DTexture9> mTexture;
+};
+
+} /* layers */
+} /* mozilla */
+#endif /* GFX_THEBESLAYERD3D9_H */
--- a/gfx/layers/opengl/CanvasLayerOGL.cpp
+++ b/gfx/layers/opengl/CanvasLayerOGL.cpp
@@ -193,17 +193,19 @@ CanvasLayerOGL::Updated(const nsIntRect&
     }
   }
 
   // sanity
   NS_ASSERTION(mUpdatedRect.IsEmpty() || mBounds.Contains(mUpdatedRect), "CanvasLayer: Updated rect bigger than bounds!");
 }
 
 void
-CanvasLayerOGL::RenderLayer(int aPreviousDestination)
+CanvasLayerOGL::RenderLayer(int aPreviousDestination,
+                            DrawThebesLayerCallback aCallback,
+                            void* aCallbackData)
 {
   LayerManagerOGL *glManager = static_cast<LayerManagerOGL*>(mManager);
   GLContext *gl = glManager->gl();
   glManager->MakeCurrent();
 
   float quadTransform[4][4];
   // Transform the quad to the size of the canvas.
   memset(&quadTransform, 0, sizeof(quadTransform));
--- a/gfx/layers/opengl/CanvasLayerOGL.h
+++ b/gfx/layers/opengl/CanvasLayerOGL.h
@@ -61,17 +61,19 @@ public:
 
   // CanvasLayer implementation
   virtual void Initialize(const Data& aData);
   virtual void Updated(const nsIntRect& aRect);
 
   // LayerOGL implementation
   virtual LayerType GetType() { return TYPE_CANVAS; }
   virtual Layer* GetLayer() { return this; }
-  virtual void RenderLayer(int aPreviousDestination);
+  virtual void RenderLayer(int aPreviousDestination,
+                           DrawThebesLayerCallback aCallback,
+                           void* aCallbackData);
 
 protected:
   nsRefPtr<gfxASurface> mSurface;
   nsRefPtr<GLContext> mGLContext;
 
   unsigned int mTexture;
 
   nsIntRect mBounds;
--- a/gfx/layers/opengl/ColorLayerOGL.cpp
+++ b/gfx/layers/opengl/ColorLayerOGL.cpp
@@ -48,17 +48,17 @@ ColorLayerOGL::GetType()
 
 Layer*
 ColorLayerOGL::GetLayer()
 {
   return this;
 }
 
 void
-ColorLayerOGL::RenderLayer(int)
+ColorLayerOGL::RenderLayer(int, DrawThebesLayerCallback, void*)
 {
   static_cast<LayerManagerOGL*>(mManager)->MakeCurrent();
 
   // XXX we might be able to improve performance by using glClear
 
   float quadTransform[4][4];
   nsIntRect visibleRect = mVisibleRegion.GetBounds();
   // Transform the quad to the size of the visible area.
--- a/gfx/layers/opengl/ColorLayerOGL.h
+++ b/gfx/layers/opengl/ColorLayerOGL.h
@@ -56,17 +56,19 @@ public:
 
   virtual void SetVisibleRegion(const nsIntRegion& aRegion) { mVisibleRegion = aRegion; }
 
   // LayerOGL Implementation
   virtual LayerType GetType();
 
   virtual Layer* GetLayer();
 
-  virtual void RenderLayer(int aPreviousDestination);
+  virtual void RenderLayer(int aPreviousDestination,
+                           DrawThebesLayerCallback aCallback,
+                           void* aCallbackData);
 
 protected:
   nsIntRegion mVisibleRegion;
 };
 
 } /* layers */
 } /* mozilla */
 #endif /* GFX_COLORLAYEROGL_H */
--- a/gfx/layers/opengl/ContainerLayerOGL.cpp
+++ b/gfx/layers/opengl/ContainerLayerOGL.cpp
@@ -42,16 +42,25 @@ namespace layers {
 
 ContainerLayerOGL::ContainerLayerOGL(LayerManagerOGL *aManager)
   : ContainerLayer(aManager, NULL)
   , LayerOGL(aManager)
 {
   mImplData = static_cast<LayerOGL*>(this);
 }
 
+ContainerLayerOGL::~ContainerLayerOGL()
+{
+  LayerOGL *nextChild;
+  for (LayerOGL *child = GetFirstChildOGL(); child; child = nextChild) {
+    nextChild = child->GetNextSibling();
+    child->GetLayer()->Release();
+  }
+}
+
 const nsIntRect&
 ContainerLayerOGL::GetVisibleRect()
 {
   return mVisibleRect;
 }
 
 void
 ContainerLayerOGL::SetVisibleRegion(const nsIntRegion &aRegion)
@@ -60,48 +69,52 @@ ContainerLayerOGL::SetVisibleRegion(cons
 }
 
 void
 ContainerLayerOGL::InsertAfter(Layer* aChild, Layer* aAfter)
 {
   LayerOGL *newChild = static_cast<LayerOGL*>(aChild->ImplData());
   aChild->SetParent(this);
   if (!aAfter) {
+    NS_ADDREF(aChild);
     LayerOGL *oldFirstChild = GetFirstChildOGL();
     mFirstChild = newChild->GetLayer();
     newChild->SetNextSibling(oldFirstChild);
     return;
   }
   for (LayerOGL *child = GetFirstChildOGL(); 
     child; child = child->GetNextSibling()) {
     if (aAfter == child->GetLayer()) {
+      NS_ADDREF(aChild);
       LayerOGL *oldNextSibling = child->GetNextSibling();
       child->SetNextSibling(newChild);
       child->GetNextSibling()->SetNextSibling(oldNextSibling);
       return;
     }
   }
   NS_WARNING("Failed to find aAfter layer!");
 }
 
 void
 ContainerLayerOGL::RemoveChild(Layer *aChild)
 {
   if (GetFirstChild() == aChild) {
     mFirstChild = GetFirstChildOGL()->GetNextSibling()->GetLayer();
+    NS_RELEASE(aChild);
     return;
   }
   LayerOGL *lastChild = NULL;
   for (LayerOGL *child = GetFirstChildOGL(); child; 
     child = child->GetNextSibling()) {
     if (child->GetLayer() == aChild) {
       // We're sure this is not our first child. So lastChild != NULL.
       lastChild->SetNextSibling(child->GetNextSibling());
       child->SetNextSibling(NULL);
       child->GetLayer()->SetParent(NULL);
+      NS_RELEASE(aChild);
       return;
     }
     lastChild = child;
   }
 }
 
 LayerOGL::LayerType
 ContainerLayerOGL::GetType()
@@ -120,31 +133,34 @@ ContainerLayerOGL::GetFirstChildOGL()
 {
   if (!mFirstChild) {
     return nsnull;
   }
   return static_cast<LayerOGL*>(mFirstChild->ImplData());
 }
 
 void
-ContainerLayerOGL::RenderLayer(int aPreviousFrameBuffer)
+ContainerLayerOGL::RenderLayer(int aPreviousFrameBuffer,
+                               DrawThebesLayerCallback aCallback,
+                               void* aCallbackData)
 {
   /**
    * Setup our temporary texture for rendering the contents of this container.
    */
   GLuint containerSurface;
   GLuint frameBuffer;
   RGBLayerProgram *rgbProgram =
     static_cast<LayerManagerOGL*>(mManager)->GetRGBLayerProgram();
   ColorLayerProgram *colorProgram =
     static_cast<LayerManagerOGL*>(mManager)->GetColorLayerProgram();
   YCbCrLayerProgram *yCbCrProgram =
     static_cast<LayerManagerOGL*>(mManager)->GetYCbCrLayerProgram();
 
-  if (GetOpacity() != 1.0) {
+  float opacity = GetOpacity();
+  if (opacity != 1.0) {
     gl()->fGenTextures(1, &containerSurface);
     gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, containerSurface);
     gl()->fTexImage2D(LOCAL_GL_TEXTURE_2D,
 			    0,
 			    LOCAL_GL_RGBA,
 			    mVisibleRect.width,
 			    mVisibleRect.height,
 			    0,
@@ -197,21 +213,21 @@ ContainerLayerOGL::RenderLayer(int aPrev
       gl()->fScissor(clipRect->x - GetVisibleRect().x,
                    clipRect->y - GetVisibleRect().y,
                    clipRect->width,
                    clipRect->height);
     } else {
       gl()->fScissor(0, 0, GetVisibleRect().width, GetVisibleRect().height);
     }
 
-    layerToRender->RenderLayer(frameBuffer);
+    layerToRender->RenderLayer(frameBuffer, aCallback, aCallbackData);
     layerToRender = layerToRender->GetNextSibling();
   }
 
-  if (GetOpacity() != 1.0) {
+  if (opacity != 1.0) {
     // Unbind the current framebuffer and rebind the previous one.
     gl()->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, aPreviousFrameBuffer);
     gl()->fDeleteFramebuffers(1, &frameBuffer);
 
     // Restore old shader program variables.
     yCbCrProgram->Activate();
     yCbCrProgram->PopRenderTargetOffset();
 
@@ -236,17 +252,17 @@ ContainerLayerOGL::RenderLayer(int aPrev
     quadTransform[3][0] = (float)GetVisibleRect().x;
     quadTransform[3][1] = (float)GetVisibleRect().y;
     quadTransform[3][3] = 1.0f;
 
     rgbProgram->SetLayerQuadTransform(&quadTransform[0][0]);
 
     gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, containerSurface);
 
-    rgbProgram->SetLayerOpacity(GetOpacity());
+    rgbProgram->SetLayerOpacity(opacity);
     rgbProgram->SetLayerTransform(&mTransform._11);
     rgbProgram->Apply();
 
     gl()->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4);
 
     // Clean up resources.
     gl()->fDeleteTextures(1, &containerSurface);
   }
--- a/gfx/layers/opengl/ContainerLayerOGL.h
+++ b/gfx/layers/opengl/ContainerLayerOGL.h
@@ -44,16 +44,17 @@
 namespace mozilla {
 namespace layers {
 
 class ContainerLayerOGL : public ContainerLayer, 
                           public LayerOGL
 {
 public:
   ContainerLayerOGL(LayerManagerOGL *aManager);
+  ~ContainerLayerOGL();
 
   const nsIntRect &GetVisibleRect();
 
   /** ContainerLayer implementation */
   void SetVisibleRegion(const nsIntRegion& aRegion);
 
   void InsertAfter(Layer* aChild, Layer* aAfter);
 
@@ -63,17 +64,19 @@ public:
   LayerType GetType();
 
   Layer* GetLayer();
 
   LayerOGL* GetFirstChildOGL();
 
   PRBool IsEmpty();
 
-  void RenderLayer(int aPreviousFrameBuffer);
+  void RenderLayer(int aPreviousFrameBuffer,
+                   DrawThebesLayerCallback aCallback,
+                   void* aCallbackData);
 private:
   nsIntRect mVisibleRect;
 
   GLuint mTexture;
 };
 
 } /* layers */
 } /* mozilla */
--- a/gfx/layers/opengl/ImageLayerOGL.cpp
+++ b/gfx/layers/opengl/ImageLayerOGL.cpp
@@ -264,17 +264,18 @@ ImageLayerOGL::GetType()
 
 Layer*
 ImageLayerOGL::GetLayer()
 {
   return this;
 }
 
 void
-ImageLayerOGL::RenderLayer(int)
+ImageLayerOGL::RenderLayer(int, DrawThebesLayerCallback aCallback,
+                           void* aCallbackData)
 {
   if (!GetContainer()) {
     return;
   }
 
   LayerManagerOGL *manager = static_cast<LayerManagerOGL*>(mManager);
   manager->MakeCurrent();
 
--- a/gfx/layers/opengl/ImageLayerOGL.h
+++ b/gfx/layers/opengl/ImageLayerOGL.h
@@ -170,17 +170,19 @@ public:
     mImplData = static_cast<LayerOGL*>(this);
   }
 
   // LayerOGL Implementation
   virtual LayerType GetType();
 
   virtual Layer* GetLayer();
 
-  virtual void RenderLayer(int aPreviousDestination);
+  virtual void RenderLayer(int aPreviousDestination,
+                           DrawThebesLayerCallback aCallback,
+                           void* aCallbackData);
 };
 
 class THEBES_API PlanarYCbCrImageOGL : public PlanarYCbCrImage
 {
   typedef mozilla::gl::GLContext GLContext;
 
 public:
   PlanarYCbCrImageOGL(RecycleBin *aRecycleBin);
--- a/gfx/layers/opengl/LayerManagerOGL.cpp
+++ b/gfx/layers/opengl/LayerManagerOGL.cpp
@@ -277,24 +277,20 @@ LayerManagerOGL::BeginTransaction()
 
 void
 LayerManagerOGL::BeginTransactionWithTarget(gfxContext *aTarget)
 {
   mTarget = aTarget;
 }
 
 void
-LayerManagerOGL::EndConstruction()
+LayerManagerOGL::EndTransaction(DrawThebesLayerCallback aCallback,
+                                void* aCallbackData)
 {
-}
-
-void
-LayerManagerOGL::EndTransaction()
-{
-  Render();
+  Render(aCallback, aCallbackData);
   mTarget = NULL;
 }
 
 void
 LayerManagerOGL::SetRoot(Layer *aLayer)
 {
   mRootLayer =  static_cast<LayerOGL*>(aLayer->ImplData());;
 }
@@ -353,17 +349,18 @@ LayerManagerOGL::SetClippingEnabled(PRBo
 
 void
 LayerManagerOGL::MakeCurrent()
 {
     mGLContext->MakeCurrent();
 }
 
 void
-LayerManagerOGL::Render()
+LayerManagerOGL::Render(DrawThebesLayerCallback aCallback,
+                        void* aCallbackData)
 {
   nsIntRect rect;
   mWidget->GetBounds(rect);
   GLint width = rect.width;
   GLint height = rect.height;
 
   MakeCurrent();
   SetupBackBuffer();
@@ -379,17 +376,17 @@ LayerManagerOGL::Render()
   if (mRootLayer) {
     const nsIntRect *clipRect = mRootLayer->GetLayer()->GetClipRect();
     if (clipRect) {
       mGLContext->fScissor(clipRect->x, clipRect->y, clipRect->width, clipRect->height);
     } else {
       mGLContext->fScissor(0, 0, width, height);
     }
 
-    mRootLayer->RenderLayer(mFrameBuffer);
+    mRootLayer->RenderLayer(mFrameBuffer, aCallback, aCallbackData);
   }
 
   if (mTarget) {
     CopyToTarget();
   } else {
     /**
      * Draw our backbuffer to the screen without using vertex or fragment
      * shaders. We're fine with just calculating the viewport coordinates
--- a/gfx/layers/opengl/LayerManagerOGL.h
+++ b/gfx/layers/opengl/LayerManagerOGL.h
@@ -211,17 +211,18 @@ public:
    * LayerManager implementation.
    */
   void BeginTransaction();
 
   void BeginTransactionWithTarget(gfxContext* aTarget);
 
   void EndConstruction();
 
-  void EndTransaction();
+  virtual void EndTransaction(DrawThebesLayerCallback aCallback,
+                              void* aCallbackData);
 
   void SetRoot(Layer* aLayer);
   
   virtual already_AddRefed<ThebesLayer> CreateThebesLayer();
 
   virtual already_AddRefed<ContainerLayer> CreateContainerLayer();
 
   virtual already_AddRefed<ImageLayer> CreateImageLayer();
@@ -288,17 +289,18 @@ private:
 
   /**
    * Region we're clipping our current drawing to.
    */
   nsIntRegion mClippingRegion;
   /**
    * Render the current layer tree to the active target.
    */
-  void Render();
+  void Render(DrawThebesLayerCallback aCallback,
+              void* aCallbackData);
   /**
    * Setup the pipeline.
    */
   void SetupPipeline();
   /**
    * Setup the backbuffer.
    *
    * \return PR_TRUE if setup was succesful
@@ -311,16 +313,18 @@ private:
 };
 
 /**
  * General information and tree management for OGL layers.
  */
 class LayerOGL
 {
 public:
+  typedef LayerManager::DrawThebesLayerCallback DrawThebesLayerCallback;
+
   LayerOGL(LayerManagerOGL *aManager);
 
   enum LayerType {
     TYPE_THEBES,
     TYPE_CONTAINER,
     TYPE_IMAGE,
     TYPE_COLOR,
     TYPE_CANVAS
@@ -331,17 +335,18 @@ public:
   LayerOGL *GetNextSibling();
   virtual LayerOGL *GetFirstChildOGL() { return nsnull; }
 
   void SetNextSibling(LayerOGL *aParent);
   void SetFirstChild(LayerOGL *aParent);
 
   virtual Layer* GetLayer() = 0;
 
-  virtual void RenderLayer(int aPreviousFrameBuffer) = 0;
+  virtual void RenderLayer(int aPreviousFrameBuffer, DrawThebesLayerCallback aCallback,
+                           void* aCallbackData) = 0;
 
   typedef mozilla::gl::GLContext GLContext;
 
   GLContext *gl() const { return mOGLManager->gl(); }
 protected:
   LayerManagerOGL *mOGLManager;
   LayerOGL *mNextSibling;
 };
--- a/gfx/layers/opengl/ThebesLayerOGL.cpp
+++ b/gfx/layers/opengl/ThebesLayerOGL.cpp
@@ -123,125 +123,100 @@ void
 ThebesLayerOGL::InvalidateRegion(const nsIntRegion &aRegion)
 {
   nsIntRegion invalidatedRegion;
   invalidatedRegion.Or(aRegion, mInvalidatedRect);
   invalidatedRegion.And(invalidatedRegion, mVisibleRect);
   mInvalidatedRect = invalidatedRegion.GetBounds();
 }
 
-gfxContext *
-ThebesLayerOGL::BeginDrawing(nsIntRegion *aRegion)
-{
-  if (mInvalidatedRect.IsEmpty()) {
-    aRegion->SetEmpty();
-    return NULL;
-  }
-  if (!mTexture) {
-    aRegion->SetEmpty();
-    return NULL;
-  }
-  *aRegion = mInvalidatedRect;
-
-  gfxASurface::gfxImageFormat imageFormat;
-
-  if (UseOpaqueSurface(this)) {
-    imageFormat = gfxASurface::ImageFormatRGB24;
-  } else {
-    imageFormat = gfxASurface::ImageFormatARGB32;
-  }
-
-  mDestinationSurface =
-    gfxPlatform::GetPlatform()->
-      CreateOffscreenSurface(gfxIntSize(mInvalidatedRect.width,
-                                        mInvalidatedRect.height),
-                             imageFormat);
-
-  mContext = new gfxContext(mDestinationSurface);
-  mContext->Translate(gfxPoint(-mInvalidatedRect.x, -mInvalidatedRect.y));
-  return mContext.get();
-}
-
-void
-ThebesLayerOGL::EndDrawing()
-{
-  static_cast<LayerManagerOGL*>(mManager)->MakeCurrent();
-
-  nsRefPtr<gfxImageSurface> imageSurface;
-
-  gfxASurface::gfxImageFormat imageFormat;
-
-  if (UseOpaqueSurface(this)) {
-    imageFormat = gfxASurface::ImageFormatRGB24;
-  } else {
-    imageFormat = gfxASurface::ImageFormatARGB32;
-  }
-
-  switch (mDestinationSurface->GetType()) {
-    case gfxASurface::SurfaceTypeImage:
-      imageSurface = static_cast<gfxImageSurface*>(mDestinationSurface.get());
-      break;
-#ifdef XP_WIN
-    case gfxASurface::SurfaceTypeWin32:
-      imageSurface =
-        static_cast<gfxWindowsSurface*>(mDestinationSurface.get())->
-          GetImageSurface();
-      break;
-#endif
-    default:
-      /** 
-       * XXX - This is very undesirable. Implement this for other platforms in
-       * a more efficient way as well!
-       */
-      {
-        imageSurface = new gfxImageSurface(gfxIntSize(mInvalidatedRect.width,
-                                                      mInvalidatedRect.height),
-                                           imageFormat);
-        nsRefPtr<gfxContext> tmpContext = new gfxContext(imageSurface);
-        tmpContext->SetSource(mDestinationSurface);
-        tmpContext->SetOperator(gfxContext::OPERATOR_SOURCE);
-        tmpContext->Paint();
-      }
-      break;
-  }
-
-  gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
-  gl()->fTexSubImage2D(LOCAL_GL_TEXTURE_2D,
-                       0,
-                       mInvalidatedRect.x - mVisibleRect.x,
-                       mInvalidatedRect.y - mVisibleRect.y,
-                       mInvalidatedRect.width,
-                       mInvalidatedRect.height,
-                       LOCAL_GL_BGRA,
-                       LOCAL_GL_UNSIGNED_BYTE,
-                       imageSurface->Data());
-
-  mDestinationSurface = NULL;
-  mContext = NULL;
-}
-
 LayerOGL::LayerType
 ThebesLayerOGL::GetType()
 {
   return TYPE_THEBES;
 }
 
 const nsIntRect&
 ThebesLayerOGL::GetVisibleRect()
 {
   return mVisibleRect;
 }
 
 void
-ThebesLayerOGL::RenderLayer(int aPreviousFrameBuffer)
+ThebesLayerOGL::RenderLayer(int aPreviousFrameBuffer,
+                            DrawThebesLayerCallback aCallback,
+                            void* aCallbackData)
 {
   if (!mTexture) {
     return;
   }
 
+  if (!mInvalidatedRect.IsEmpty()) {
+    gfxASurface::gfxImageFormat imageFormat;
+
+    if (UseOpaqueSurface(this)) {
+      imageFormat = gfxASurface::ImageFormatRGB24;
+    } else {
+      imageFormat = gfxASurface::ImageFormatARGB32;
+    }
+
+    nsRefPtr<gfxASurface> surface =
+      gfxPlatform::GetPlatform()->
+        CreateOffscreenSurface(gfxIntSize(mInvalidatedRect.width,
+                                          mInvalidatedRect.height),
+                               imageFormat);
+
+    nsRefPtr<gfxContext> ctx = new gfxContext(surface);
+    ctx->Translate(gfxPoint(-mInvalidatedRect.x, -mInvalidatedRect.y));
+    aCallback(this, ctx, mInvalidatedRect, aCallbackData);
+
+    static_cast<LayerManagerOGL*>(mManager)->MakeCurrent();
+
+    nsRefPtr<gfxImageSurface> imageSurface;
+
+    switch (surface->GetType()) {
+      case gfxASurface::SurfaceTypeImage:
+        imageSurface = static_cast<gfxImageSurface*>(surface.get());
+        break;
+#ifdef XP_WIN
+      case gfxASurface::SurfaceTypeWin32:
+        imageSurface =
+          static_cast<gfxWindowsSurface*>(surface.get())->
+            GetImageSurface();
+        break;
+#endif
+      default:
+        /** 
+         * XXX - This is very undesirable. Implement this for other platforms in
+         * a more efficient way as well!
+         */
+        {
+          imageSurface = new gfxImageSurface(gfxIntSize(mInvalidatedRect.width,
+                                                        mInvalidatedRect.height),
+                                             imageFormat);
+          nsRefPtr<gfxContext> tmpContext = new gfxContext(imageSurface);
+          tmpContext->SetSource(surface);
+          tmpContext->SetOperator(gfxContext::OPERATOR_SOURCE);
+          tmpContext->Paint();
+        }
+        break;
+    }
+
+    gl()->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
+    gl()->fTexSubImage2D(LOCAL_GL_TEXTURE_2D,
+                         0,
+                         mInvalidatedRect.x - mVisibleRect.x,
+                         mInvalidatedRect.y - mVisibleRect.y,
+                         mInvalidatedRect.width,
+                         mInvalidatedRect.height,
+                         LOCAL_GL_BGRA,
+                         LOCAL_GL_UNSIGNED_BYTE,
+                         imageSurface->Data());
+  }
+
   float quadTransform[4][4];
   /*
    * Matrix to transform the <0.0,0.0>, <1.0,1.0> quad to the correct position
    * and size.
    */
   memset(&quadTransform, 0, sizeof(quadTransform));
   quadTransform[0][0] = (float)GetVisibleRect().width;
   quadTransform[1][1] = (float)GetVisibleRect().height;
--- a/gfx/layers/opengl/ThebesLayerOGL.h
+++ b/gfx/layers/opengl/ThebesLayerOGL.h
@@ -54,50 +54,38 @@ public:
   virtual ~ThebesLayerOGL();
 
   /** Layer implementation */
   void SetVisibleRegion(const nsIntRegion& aRegion);
 
   /** ThebesLayer implementation */
   void InvalidateRegion(const nsIntRegion& aRegion);
 
-  gfxContext *BeginDrawing(nsIntRegion* aRegionToDraw);
-
-  void EndDrawing();
-
   /** LayerOGL implementation */
   LayerType GetType();
   Layer* GetLayer();
   virtual PRBool IsEmpty();
-  virtual void RenderLayer(int aPreviousFrameBuffer);
+  virtual void RenderLayer(int aPreviousFrameBuffer,
+                           DrawThebesLayerCallback aCallback,
+                           void* aCallbackData);
 
   /** ThebesLayerOGL */
   const nsIntRect &GetVisibleRect();
   const nsIntRect &GetInvalidatedRect();
 
 private:
   /** 
    * Visible rectangle, this is used to know the size and position of the quad
    * when doing the rendering of this layer.
    */
   nsIntRect mVisibleRect;
   /**
    * Currently invalidated rectangular area.
    */
   nsIntRect mInvalidatedRect;
-  /**
-   * Destination surface used for this layer's drawing operation. This is 
-   * created on BeginDrawing() and should be removed on EndDrawing().
-   */
-  nsRefPtr<gfxASurface> mDestinationSurface;
-
-  /**
-   * We hold the reference to the context.
-   */
-  nsRefPtr<gfxContext> mContext;
 
   /**
    * OpenGL Texture
    */
   GLuint mTexture;
 
 };
 
--- a/gfx/public/nsRegion.h
+++ b/gfx/public/nsRegion.h
@@ -174,16 +174,17 @@ public:
   }
 
   PRBool IsEmpty () const { return mRectCount == 0; }
   PRBool IsComplex () const { return mRectCount > 1; }
   PRBool IsEqual (const nsRegion& aRegion) const;
   PRUint32 GetNumRects () const { return mRectCount; }
   const nsRect& GetBounds () const { return mBoundRect; }
   nsIntRegion ToOutsidePixels (nscoord aAppUnitsPerPixel) const;
+  nsRect GetLargestRectangle () const;
 
   /**
    * Make sure the region has at most aMaxRects by adding area to it
    * if necessary. The simplified region will be a superset of the
    * original region. The simplified region's bounding box will be
    * the same as for the current region.
    */
   void SimplifyOutward (PRUint32 aMaxRects);
@@ -404,16 +405,17 @@ public:
   PRBool IsEmpty () const { return mImpl.IsEmpty (); }
   PRBool IsComplex () const { return mImpl.IsComplex (); }
   PRBool IsEqual (const nsIntRegion& aRegion) const
   {
     return mImpl.IsEqual (aRegion.mImpl);
   }
   PRUint32 GetNumRects () const { return mImpl.GetNumRects (); }
   nsIntRect GetBounds () const { return FromRect (mImpl.GetBounds ()); }
+  nsIntRect GetLargestRectangle () const { return FromRect (mImpl.GetLargestRectangle()); }
 
   /**
    * Make sure the region has at most aMaxRects by adding area to it
    * if necessary. The simplified region will be a superset of the
    * original region. The simplified region's bounding box will be
    * the same as for the current region.
    */
   void SimplifyOutward (PRUint32 aMaxRects)
--- a/gfx/src/nsRegion.cpp
+++ b/gfx/src/nsRegion.cpp
@@ -32,16 +32,17 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "prlock.h"
 #include "nsRegion.h"
 #include "nsISupportsImpl.h"
+#include "nsTArray.h"
 
 /*
  * The SENTINEL values below guaranties that a < or >
  * comparison with it will be false for all values of the
  * underlying nscoord type.  E.g. this is always false:
  *   aCoord > NS_COORD_GREATER_SENTINEL
  * Setting the mRectListHead dummy rectangle to these values
  * allows us to loop without checking for the list end.
@@ -1294,16 +1295,262 @@ nsIntRegion nsRegion::ToOutsidePixels(ns
   const nsRect *currentRect;
   while ((currentRect = rgnIter.Next())) {
     nsIntRect deviceRect = currentRect->ToOutsidePixels(aAppUnitsPerPixel);
     result.Or(result, deviceRect);
   }
   return result;
 }
 
+// This algorithm works in three phases:
+//  1) Convert the region into a grid by adding vertical/horizontal lines for
+//     each edge of each rectangle in the region.
+//  2) For each rectangle in the region, for each cell it contains, set that
+//     cells's value to the area of the subrectangle it corresponds to. Cells
+//     that are not contained by any rectangle have the value 0.
+//  3) Calculate the submatrix with the largest sum such that none of its cells
+//     contain any 0s (empty regions). The rectangle represented by the
+//     submatrix is the largest rectangle in the region.
+//
+// Let k be the number of rectangles in the region.
+// Let m be the height of the grid generated in step 1.
+// Let n be the width of the grid generated in step 1.
+//
+// Step 1 is O(k) in time and O(m+n) in space for the sparse grid.
+// Step 2 is O(mn) in time and O(mn) in additional space for the full grid.
+// Step 3 is O(m^2 n) in time and O(mn) in additional space
+//
+// The implementation of steps 1 and 2 are rather straightforward. However our
+// implementation of step 3 uses dynamic programming to achieve its efficiency.
+//
+// Psuedo code for step 3 is as follows where G is the grid from step 1 and A
+// is the array from step 2:
+// Phase3 = function (G, A, m, n) {
+//   let (t,b,l,r,_) = MaxSum2D(A,m,n)
+//   return rect(G[t],G[l],G[r],G[b]);
+// }
+// MaxSum2D = function (A, m, n) {
+//   S = array(m+1,n+1)
+//   S[0][i] = 0 for i in [0,n]
+//   S[j][0] = 0 for j in [0,m]
+//   S[j][i] = (if A[j-1][i-1] = 0 then some large negative number else A[j-1][i-1])
+//           + S[j-1][n] + S[j][i-1] - S[j-1][i-1]
+//
+//   // top, bottom, left, right, area
+//   var maxRect = (-1, -1, -1, -1, 0);
+//
+//   for all (m',m'') in [0, m]^2 {
+//     let B = { S[m'][i] - S[m''][i] | 0 <= i <= n }
+//     let ((l,r),area) = MaxSum1D(B,n+1)
+//     if (area > maxRect.area) {
+//       maxRect := (m', m'', l, r, area)
+//     }
+//   }
+//
+//   return maxRect;
+// }
+//
+// Originally taken from Improved algorithms for the k-maximum subarray problem
+// for small k - SE Bae, T Takaoka but modified to show the explicit tracking
+// of indices and we already have the prefix sums from our one call site so
+// there's no need to construct them.
+// MaxSum1D = function (A,n) {
+//   var minIdx = 0;
+//   var min = 0;
+//   var maxIndices = (0,0);
+//   var max = 0;
+//   for i in range(n) {
+//     let cand = A[i] - min;
+//     if (cand > max) {
+//       max := cand;
+//       maxIndices := (minIdx, i)
+//     }
+//     if (min > A[i]) {
+//       min := A[i];
+//       minIdx := i;
+//     }
+//   }
+//   return (minIdx, maxIdx, max);
+// }
+
+namespace {
+  // This class represents a partitioning of an axis delineated by coordinates.
+  // It internally maintains a sorted array of coordinates.
+  class AxisPartition {
+  public:
+    // Adds a new partition at the given coordinate to this partitioning. If
+    // the coordinate is already present in the partitioning, this does nothing.
+    void InsertCoord(nscoord c) {
+      PRUint32 i;
+      if (!mStops.GreatestIndexLtEq(c, i)) {
+        mStops.InsertElementAt(i, c);
+      }
+    }
+
+    // Returns the array index of the given partition point. The partition
+    // point must already be present in the partitioning.
+    PRInt32 IndexOf(nscoord p) const {
+      return mStops.BinaryIndexOf(p);
+    }
+
+    // Returns the partition at the given index which must be non-zero and
+    // less than the number of partitions in this partitioning.
+    nscoord StopAt(PRInt32 index) const {
+      return mStops[index];
+    }
+
+    // Returns the size of the gap between the partition at the given index and
+    // the next partition in this partitioning. If the index is the last index
+    // in the partitioning, the result is undefined.
+    nscoord StopSize(PRInt32 index) const {
+      return mStops[index+1] - mStops[index];
+    }
+
+    // Returns the number of partitions in this partitioning.
+    PRInt32 GetNumStops() const { return mStops.Length(); }
+
+  private:
+    nsTArray<nscoord> mStops;
+  };
+
+  const PRInt64 kVeryLargeNegativeNumber = 0xffff000000000000ll;
+
+  // Returns the sum and indices of the subarray with the maximum sum of the
+  // given array (A,n), assuming the array is already in prefix sum form.
+  PRInt64 MaxSum1D(const nsTArray<PRInt64> &A, PRInt32 n,
+                   PRInt32 *minIdx, PRInt32 *maxIdx) {
+    // The min/max indicies of the largest subarray found so far
+    PRInt64 min = 0,
+            max = 0;
+    PRInt32 currentMinIdx = 0;
+
+    *minIdx = 0;
+    *maxIdx = 0;
+
+    // Because we're given the array in prefix sum form, we know the first
+    // element is 0
+    for(PRInt32 i = 1; i < n; i++) {
+      PRInt64 cand = A[i] - min;
+      if (cand > max) {
+        max = cand;
+        *minIdx = currentMinIdx;
+        *maxIdx = i;
+      }
+      if (min > A[i]) {
+        min = A[i];
+        currentMinIdx = i;
+      }
+    }
+
+    return max;
+  }
+}
+
+nsRect nsRegion::GetLargestRectangle () const {
+  nsRect bestRect;
+
+  if (!mRectCount)
+    return bestRect;
+
+  AxisPartition xaxis, yaxis;
+
+  // Step 1: Calculate the grid lines
+  nsRegionRectIterator iter(*this);
+  const nsRect *currentRect;
+  while ((currentRect = iter.Next())) {
+    xaxis.InsertCoord(currentRect->x);
+    xaxis.InsertCoord(currentRect->XMost());
+    yaxis.InsertCoord(currentRect->y);
+    yaxis.InsertCoord(currentRect->YMost());
+  }
+
+  // Step 2: Fill out the grid with the areas
+  // Note: due to the ordering of rectangles in the region, it is not always
+  // possible to combine steps 2 and 3 so we don't try to be clever.
+  PRInt32 matrixHeight = yaxis.GetNumStops() - 1;
+  PRInt32 matrixWidth = xaxis.GetNumStops() - 1;
+  PRInt32 matrixSize = matrixHeight * matrixWidth;
+  nsTArray<PRInt64> areas(matrixSize);
+  areas.SetLength(matrixSize);
+  memset(areas.Elements(), 0, matrixSize * sizeof(PRInt64));
+
+  iter.Reset();
+  while ((currentRect = iter.Next())) {
+    PRInt32 xstart = xaxis.IndexOf(currentRect->x);
+    PRInt32 xend = xaxis.IndexOf(currentRect->XMost());
+    PRInt32 y = yaxis.IndexOf(currentRect->y);
+    PRInt32 yend = yaxis.IndexOf(currentRect->YMost());
+
+    for (; y < yend; y++) {
+      nscoord height = yaxis.StopSize(y);
+      for (PRInt32 x = xstart; x < xend; x++) {
+        nscoord width = xaxis.StopSize(x);
+        areas[y*matrixWidth+x] = width*PRInt64(height);
+      }
+    }
+  }
+
+  // Step 3: Find the maximum submatrix sum that does not contain a rectangle
+  {
+    // First get the prefix sum array
+    PRInt32 m = matrixHeight + 1;
+    PRInt32 n = matrixWidth + 1;
+    nsTArray<PRInt64> pareas(m*n);
+    pareas.SetLength(m*n);
+    // Zero out the first row
+    for (PRInt32 x = 0; x < n; x++)
+      pareas[x] = 0;
+    for (PRInt32 y = 1; y < m; y++) {
+      // Zero out the left column
+      pareas[y*n] = 0;
+      for (PRInt32 x = 1; x < n; x++) {
+        PRInt64 area = areas[(y-1)*matrixWidth+x-1];
+        if (!area)
+          area = kVeryLargeNegativeNumber;
+        area += pareas[    y*n+x-1]
+              + pareas[(y-1)*n+x  ]
+              - pareas[(y-1)*n+x-1];
+        pareas[y*n+x] = area;
+      }
+    }
+
+    // No longer need the grid
+    areas.SetLength(0);
+
+    PRInt64 bestArea = 0;
+    struct {
+      PRInt32 left, top, right, bottom;
+    } bestRectIndices = { 0, 0, 0, 0 };
+    for (PRInt32 m1 = 0; m1 < m; m1++) {
+      for (PRInt32 m2 = m1+1; m2 < m; m2++) {
+        nsTArray<PRInt64> B;
+        B.SetLength(n);
+        for (PRInt32 i = 0; i < n; i++)
+          B[i] = pareas[m2*n+i] - pareas[m1*n+i];
+        PRInt32 minIdx, maxIdx;
+        PRInt64 area = MaxSum1D(B, n, &minIdx, &maxIdx);
+        if (area > bestArea) {
+          bestRectIndices.left = minIdx;
+          bestRectIndices.top = m1;
+          bestRectIndices.right = maxIdx;
+          bestRectIndices.bottom = m2;
+          bestArea = area;
+        }
+      }
+    }
+
+    bestRect.MoveTo(xaxis.StopAt(bestRectIndices.left),
+                    yaxis.StopAt(bestRectIndices.top));
+    bestRect.SizeTo(xaxis.StopAt(bestRectIndices.right) - bestRect.x,
+                    yaxis.StopAt(bestRectIndices.bottom) - bestRect.y);
+  }
+
+  return bestRect;
+}
+
 void nsRegion::SimplifyOutward (PRUint32 aMaxRects)
 {
   NS_ASSERTION(aMaxRects >= 1, "Invalid max rect count");
   
   if (mRectCount <= aMaxRects)
     return;
 
   *this = GetBounds();
--- a/gfx/tests/Makefile.in
+++ b/gfx/tests/Makefile.in
@@ -45,16 +45,17 @@ include $(DEPTH)/config/autoconf.mk
 MODULE		= gfx
 
 MOZILLA_INTERNAL_API = 1
 
 
 CPP_UNIT_TESTS	= \
 		TestColorNames.cpp \
 		TestRect.cpp \
+		TestRegion.cpp \
 		$(NULL)
 
 LIBS		= \
 		$(call EXPAND_LIBNAME_PATH,gkgfx,../src) \
 		$(XPCOM_LIBS) \
 		$(MOZ_JS_LIBS) \
 		$(TK_LIBS) \
 		$(NULL)
new file mode 100644
--- /dev/null
+++ b/gfx/tests/TestRegion.cpp
@@ -0,0 +1,163 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Rob Arnold <robarnold@cs.cmu.edu>
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "TestHarness.h"
+#include "nsRegion.h"
+
+class TestLargestRegion {
+  static PRBool TestSingleRect(nsRect r) {
+    nsRegion region(r);
+    if (region.GetLargestRectangle() != r) {
+      fail("largest rect of singleton %d %d %d %d", r.x, r.y, r.width, r.height);
+      return PR_FALSE;
+    }
+    return PR_TRUE;
+  }
+  // Construct a rectangle, remove part of it, then check the remainder
+  static PRBool TestNonRectangular() {
+    nsRegion r(nsRect(0, 0, 30, 30));
+
+    const int nTests = 19;
+    struct {
+      nsRect rect;
+      PRInt64 expectedArea;
+    } tests[nTests] = {
+      // Remove a 20x10 chunk from the square
+      { nsRect(0, 0, 20, 10), 600 },
+      { nsRect(10, 0, 20, 10), 600 },
+      { nsRect(10, 20, 20, 10), 600 },
+      { nsRect(0, 20, 20, 10), 600 },
+      // Remove a 10x20 chunk from the square
+      { nsRect(0, 0, 10, 20), 600 },
+      { nsRect(20, 0, 10, 20), 600 },
+      { nsRect(20, 10, 10, 20), 600 },
+      { nsRect(0, 10, 10, 20), 600 },
+      // Remove the center 10x10
+      { nsRect(10, 10, 10, 10), 300 },
+      // Remove the middle column
+      { nsRect(10, 0, 10, 30), 300 },
+      // Remove the middle row
+      { nsRect(0, 10, 30, 10), 300 },
+      // Remove the corners 10x10
+      { nsRect(0, 0, 10, 10), 600 },
+      { nsRect(20, 20, 10, 10), 600 },
+      { nsRect(20, 0, 10, 10), 600 },
+      { nsRect(0, 20, 10, 10), 600 },
+      // Remove the corners 20x20
+      { nsRect(0, 0, 20, 20), 300 },
+      { nsRect(10, 10, 20, 20), 300 },
+      { nsRect(10, 0, 20, 20), 300 },
+      { nsRect(0, 10, 20, 20), 300 }
+    };
+
+    PRBool success = PR_TRUE;
+    for (PRInt32 i = 0; i < nTests; i++) {
+      nsRegion r2;
+      r2.Sub(r, tests[i].rect);
+
+      if (!r2.IsComplex())
+        fail("nsRegion code got unexpectedly smarter!");
+
+      nsRect largest = r2.GetLargestRectangle();
+      if (largest.width * largest.height != tests[i].expectedArea) {
+        fail("Did not succesfully find largest rectangle in non-rectangular region on iteration %d", i);
+        success = PR_FALSE;
+      }
+    }
+
+    return success;
+  }
+  static PRBool TwoRectTest() {
+    nsRegion r(nsRect(0, 0, 100, 100));
+    const int nTests = 4;
+    struct {
+      nsRect rect1, rect2;
+      PRInt64 expectedArea;
+    } tests[nTests] = {
+      { nsRect(0, 0, 75, 40),  nsRect(0, 60, 75, 40),  2500 },
+      { nsRect(25, 0, 75, 40), nsRect(25, 60, 75, 40), 2500 },
+      { nsRect(25, 0, 75, 40), nsRect(0, 60, 75, 40),  2000 },
+      { nsRect(0, 0, 75, 40),  nsRect(25, 60, 75, 40), 2000 },
+    };
+    PRBool success = PR_TRUE;
+    for (PRInt32 i = 0; i < nTests; i++) {
+      nsRegion r2;
+
+      r2.Sub(r, tests[i].rect1);
+      r2.Sub(r2, tests[i].rect2);
+
+      if (!r2.IsComplex())
+        fail("nsRegion code got unexpectedly smarter!");
+
+      nsRect largest = r2.GetLargestRectangle();
+      if (largest.width * largest.height != tests[i].expectedArea) {
+        fail("Did not succesfully find largest rectangle in two-rect-subtract region on iteration %d", i);
+        success = PR_FALSE;
+      }
+    }
+    return success;
+  }
+public:
+  static PRBool Test() {
+    if (!TestSingleRect(nsRect(0, 52, 720, 480)) ||
+        !TestSingleRect(nsRect(-20, 40, 50, 20)) ||
+        !TestSingleRect(nsRect(-20, 40, 10, 8)) ||
+        !TestSingleRect(nsRect(-20, -40, 10, 8)) ||
+        !TestSingleRect(nsRect(-10, -10, 20, 20)))
+      return PR_FALSE;
+    if (!TestNonRectangular())
+      return PR_FALSE;
+    if (!TwoRectTest())
+      return PR_FALSE;
+    passed("TestLargestRegion");
+    return PR_TRUE;
+  }
+};
+
+int main(int argc, char** argv) {
+  ScopedXPCOM xpcom("TestRegion");
+  if (xpcom.failed())
+    return -1;
+  if (NS_FAILED(nsRegion::InitStatic())) {
+    fail("Could not initialize region statics");
+    return -1;
+  }
+  if (!TestLargestRegion::Test())
+    return -1;
+  nsRegion::ShutdownStatic();
+  return 0;
+}
--- a/gfx/thebes/public/GLContextProvider.h
+++ b/gfx/thebes/public/GLContextProvider.h
@@ -57,17 +57,17 @@ public:
             Empty,
             BasicRGBA32,
             StrictBasicRGBA32,
             BasicRGBX32,
             StrictBasicRGBX32
         };
 
         ContextFormat(const StandardContextFormat cf) {
-            memset(this, sizeof(ContextFormat), 0);
+            memset(this, 0, sizeof(ContextFormat));
 
             switch (cf) {
             case BasicRGBA32:
                 red = green = blue = alpha = 8;
                 minRed = minGreen = minBlue = minAlpha = 1;
                 break;
 
             case StrictBasicRGBA32:
--- a/gfx/thebes/src/GLContextProviderOSMesa.cpp
+++ b/gfx/thebes/src/GLContextProviderOSMesa.cpp
@@ -190,16 +190,20 @@ public:
         mContext = sOSMesaLibrary.fCreateContextExt(osmesa_format, aFormat.depth, aFormat.stencil, 0, NULL);
         if (!mContext) {
             NS_WARNING("OSMesaCreateContextExt failed!");
             return PR_FALSE;
         }
 
         if (!MakeCurrent()) return PR_FALSE;
         if (!SetupLookupFunction()) return PR_FALSE;
+
+        // OSMesa's different from the other GL providers, it renders to an image surface, not to a pbuffer
+        sOSMesaLibrary.fPixelStore(OSMESA_Y_UP, 0);
+
         return InitWithPrefix("gl", PR_TRUE);
     }
 
     PRBool MakeCurrent()
     {
         PRBool succeeded
           = sOSMesaLibrary.fMakeCurrent (mContext, mThebesSurface->Data(),
                                          LOCAL_GL_UNSIGNED_BYTE,
--- a/intl/unicharutil/tools/ccmapbin.pl
+++ b/intl/unicharutil/tools/ccmapbin.pl
@@ -223,17 +223,17 @@ sub read_input
       ($comments_p->{'FILE'} = $_) =~ s/^\s*FILE::\s*//, next;
 
     next unless /^\s*0[Xx][0-9A-Fa-f]{4}/; 
 
     /^\s*(.*)\s*$/;
     my ($u, $comment) = split /\s+/, $1, 2;
     $u =~ s/,//g;
     $u =~ tr/A-Z/a-z/;
-    next if /^0x.*[^0-9a-f]+.*/;
+    next if $u =~ /^0x.*[^0-9a-f]+.*/;
 
     my $usv = oct $u;
     if ( 0xd800 <= $usv && $usv <= 0xdfff || # surrogate code points
          $usv > 0x10ffff ) {
       printf STDERR "Invalid input $u at %4d\n", $lc;
       next;
     }
     $fillinfo_p->[($usv >> 4)] |= (1 << ($usv & 0x0f));
new file mode 100644
--- /dev/null
+++ b/intl/unicharutil/tools/genignorable.pl
@@ -0,0 +1,66 @@
+#!/usr/bin/perl 
+
+open $f, 'UnicodeData-Latest.txt' or die $!;
+while (<$f>) {
+  @columns = split(/;/);
+#  print "$columns[0] : $columns[1]\n";
+  $names{hex($columns[0])} = $columns[1];
+}
+close $f;
+
+open $f, 'DerivedCoreProperties.txt' or die $!;
+$re = '[';
+while (<$f>) {
+  next unless /Default_Ignorable_Code_Point/;
+  next unless /^([0-9A-F]{4,6})(?:\.\.([0-9A-F]{4,6}))?/;
+
+  ($start, $end) = (hex($1), hex($2));
+  $end = $start unless $end;
+
+  for ($c = $start; $c <= $end; $c++) {
+    printf "0x%04X", $c;
+    printf " // $names{$c}" if $names{$c};
+    print "\n";
+  }
+
+  if (!$prevend || $start > $prevend + 1) {
+    $re .= make_unicode_range($prevstart, $prevend) if $prevstart;
+    $prevstart = $start;
+  }
+  $prevend = $end;
+}
+$re .= make_unicode_range($prevstart, $prevend).']';
+print STDERR $re;
+close $f;
+
+sub make_unicode_range
+{
+  my ($start, $end) = @_;
+
+  if ($start > 0xffff) {
+    my $starths = ($start - 0x10000) >> 10 | 0xd800;
+    my $startls = ($start - 0x10000) & 0x3ff | 0xdc00;
+    my $endhs = ($end - 0x10000) >> 10 | 0xd800;
+    my $endls = ($end - 0x10000) & 0x3ff | 0xdc00;
+    if ($starths == $endhs) {
+      return sprintf("]|\\u%04x[\\u%04x-\\u%04x", $starths, $startls, $endls)
+    }
+    my $re = '';
+    if ($startls > 0xdc00) {
+      $re .= sprintf("]|\\u%04x[\\u%04x-\\udfff", $starths, $startls);
+      $starths++;
+    }
+    if ($endhs > $starths) {
+      $endhs-- if ($endls < 0xdfff);
+      $re .= sprintf("]|[\\u%04x-\\u%04x][\\udc00-\\udfff", $starths, $endhs);
+    }
+    if ($endls < 0xdfff) {
+      $re .= sprintf("]|\\u%04x[\\udc00-\\u%04x", $endhs, $endls);
+    }
+    return $re;
+  } elsif ($start == $end) {
+    return sprintf("\\u%04x", $start);
+  } else {
+    return sprintf("\\u%04x-\\u%04x", $start, $end);
+  }
+}
--- a/ipc/chromium/Makefile.in
+++ b/ipc/chromium/Makefile.in
@@ -69,22 +69,16 @@ vpath %.cc \
   $(srcdir)/src/chrome/common \
   $(NULL)
 
 vpath %.mm \
   $(srcdir)/src/base \
   $(srcdir)/src/chrome/common \
   $(NULL)
 
-# TODO: remove this hack when we switch to GCC 4.3! GCC 4.1
-# instantiates template declarations in wrapped system headers with
-# the wrong visibility, which is causing the Linux tinderboxen to die in
-# std::string internals.
-VISIBILITY_FLAGS=
-
 include $(topsrcdir)/config/config.mk
 include $(topsrcdir)/ipc/chromium/chromium-config.mk
 
 CPPSRCS += \
   dtoa.cc \
   g_fmt.cc \
   prtime.cc \
   at_exit.cc \
--- a/js/src/config/rules.mk
+++ b/js/src/config/rules.mk
@@ -1513,17 +1513,17 @@ SPACE := $(EMPTY) $(EMPTY)
 # and class paths to be in the DOS form (i.e. e:/builds/...).  This function
 # does the appropriate conversion on Windows, but is a noop on other systems.
 ifeq (,$(filter-out WINNT WINCE, $(HOST_OS_ARCH)))
 ifdef CYGWIN_WRAPPER
 normalizepath = $(foreach p,$(1),$(shell cygpath -m $(p)))
 else
 # assume MSYS
 #  We use 'pwd -W' to get DOS form of the path.  However, since the given path
-#  could be a file or a non-existent path, we cannot call 'pwd -W' directly
+#  could be a file or a nonexistent path, we cannot call 'pwd -W' directly
 #  on the path.  Instead, we extract the root path (i.e. "c:/"), call 'pwd -W'
 #  on it, then merge with the rest of the path.
 root-path = $(shell echo $(1) | sed -e "s|\(/[^/]*\)/\?\(.*\)|\1|")
 non-root-path = $(shell echo $(1) | sed -e "s|\(/[^/]*\)/\?\(.*\)|\2|")
 normalizepath = $(foreach p,$(1),$(if $(filter /%,$(1)),$(patsubst %/,%,$(shell cd $(call root-path,$(1)) && pwd -W))/$(call non-root-path,$(1)),$(1)))
 endif
 else
 normalizepath = $(1)
--- a/js/src/config/system-headers
+++ b/js/src/config/system-headers
@@ -207,16 +207,17 @@ curl/types.h
 curses.h
 cxxabi.h
 DateTimeUtils.h
 dbus/dbus.h
 dbus/dbus-glib.h
 dbus/dbus-glib-lowlevel.h
 ddeml.h
 Debug.h
+deque
 dem.h
 descrip.h
 Devices.h
 Dialogs.h
 direct.h
 dirent.h
 DiskInit.h
 dlfcn.h
@@ -269,16 +270,17 @@ freetype/ftcache.h
 freetype/ftglyph.h
 freetype/ftsynth.h
 freetype/ftoutln.h
 freetype/ttnameid.h
 freetype/tttables.h
 freetype/t1tables.h
 fribidi/fribidi.h
 FSp_fopen.h
+fstream
 fstream.h
 ft2build.h
 fts.h
 gconf/gconf-client.h
 Gdiplus.h
 gdk/gdk.h
 gdk/gdkkeysyms.h
 gdk/gdkprivate.h
@@ -324,16 +326,17 @@ inttypes.h
 iodef.h
 io.h
 IOKit/IOKitLib.h
 IOKit/IOMessage.h
 IOKit/pwr_mgt/IOPMLib.h
 iomanip
 iostream
 iostream.h
+iterator
 jar.h
 JavaControl.h
 JavaEmbedding/JavaControl.h
 JavaVM/jni.h
 JManager.h
 JNIEnvTests.h
 jni.h
 #if MOZ_NATIVE_JPEG==1
@@ -602,16 +605,17 @@ Process.h
 proto/dos.h
 proto/exec.h
 psap.h
 Pt.h
 pthread.h
 pwd.h
 Python.h
 QDOffscreen.h
+queue
 Quickdraw.h
 QuickDraw.h
 QuickTimeComponents.h
 quipu/attr.h
 rasdlg.h
 raserror.h
 ras.h
 regex.h
@@ -636,16 +640,17 @@ seccomon.h
 sec.h
 secmod.h
 secmodt.h
 secrng.h
 security.h
 secutil.h
 semaphore.h
 servprov.h
+set
 setjmp.h
 SFNTLayoutTypes.h
 SFNTTypes.h
 share.h
 shellapi.h
 shlguid.h
 shlobj.h
 sigcontext.h
@@ -829,16 +834,17 @@ unixio.h
 unixlib.h
 unknwn.h
 UPrinting.h
 UQuickTime.h
 UReanimator.h
 URegions.h
 URegistrar.h
 UResourceMgr.h
+utility
 urlhist.h
 urlmon.h
 UScrap.h
 UScreenPort.h
 UTCUtils.h
 UTETextAction.h
 UTEViewTextAction.h
 UTextEdit.h
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -4994,17 +4994,16 @@ AC_SUBST(MOZ_DEBUG_DISABLE_DEFS)
 AC_SUBST(MOZ_DEBUG_FLAGS)
 AC_SUBST(MOZ_DEBUG_LDFLAGS)
 AC_SUBST(WARNINGS_AS_ERRORS)
 AC_SUBST(MOZ_LEAKY)
 AC_SUBST(MOZ_JPROF)
 AC_SUBST(MOZ_SHARK)
 AC_SUBST(MOZ_CALLGRIND)
 AC_SUBST(MOZ_VTUNE)
-AC_SUBST(MOZ_XPCTOOLS)
 AC_SUBST(MOZ_JSLOADER)
 AC_SUBST(MOZ_QUANTIFY)
 AC_SUBST(LIBICONV)
 
 AC_SUBST(BUILD_STATIC_LIBS)
 AC_SUBST(ENABLE_TESTS)
 
 AC_SUBST(ENABLE_STRIP)
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -2778,17 +2778,17 @@ array_concat(JSContext *cx, uintN argc, 
                     return false;
                 for (slot = 0; slot < alength; slot++) {
                     if (!JS_CHECK_OPERATION_LIMIT(cx) ||
                         !GetArrayElement(cx, aobj, slot, &hole, tvr.addr())) {
                         return false;
                     }
 
                     /*
-                     * Per ECMA 262, 15.4.4.4, step 9, ignore non-existent
+                     * Per ECMA 262, 15.4.4.4, step 9, ignore nonexistent
                      * properties.
                      */
                     if (!hole &&
                         !SetArrayElement(cx, nobj, length+slot, tvr.value())) {
                         return false;
                     }
                 }
                 length += alength;
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -408,17 +408,17 @@ inline void
 JSGCChunkInfo::init(JSRuntime *rt)
 {
     runtime = rt;
     numFreeArenas = GC_ARENAS_PER_CHUNK;
     gcChunkAge = 0;
 
     /*
      * For simplicity we set all bits to 1 including the high bits in the
-     * last word that corresponds to non-existing arenas. This is fine since
+     * last word that corresponds to nonexistent arenas. This is fine since
      * the arena scans the bitmap words from lowest to highest bits and the
      * allocation checks numFreeArenas before doing the search.
      */
     memset(getFreeArenaBitmap(), 0xFF, GC_FREE_ARENA_BITMAP_SIZE);
 }
 
 inline void
 CheckValidGCThingPtr(void *thing)
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -1092,17 +1092,17 @@ js_CheckRedeclaration(JSContext *cx, JSO
     uintN oldAttrs, report;
     bool isFunction;
     jsval value;
     const char *type, *name;
 
     /*
      * Both objp and propp must be either null or given. When given, *propp
      * must be null. This way we avoid an extra "if (propp) *propp = NULL" for
-     * the common case of a non-existing property.
+     * the common case of a nonexistent property.
      */
     JS_ASSERT(!objp == !propp);
     JS_ASSERT_IF(propp, !*propp);
 
     /* The JSPROP_INITIALIZER case below may generate a warning. Since we must
      * drop the property before reporting it, we insists on !propp to avoid
      * looking up the property again after the reporting is done.
      */
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -3708,18 +3708,16 @@ js_InflateUTF8StringToBuffer(JSContext *
                         JS_ReportErrorFlagsAndNumber(cx,
                                                      JSREPORT_ERROR,
                                                      js_GetErrorMessage, NULL,
                                                      JSMSG_UTF8_CHAR_TOO_LARGE,
                                                      buffer);
                     }
                     return JS_FALSE;
                 }
-                if (dstlen < 2)
-                    goto bufferTooSmall;
                 if (dst) {
                     *dst++ = (jschar)((v >> 10) + 0xD800);
                     v = (jschar)((v & 0x3FF) + 0xDC00);
                 }
                 dstlen--;
             }
         }
         if (!dstlen)
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -12981,17 +12981,17 @@ TraceRecorder::prop(JSObject* obj, LIns*
     /*
      * Property cache ensures that we are dealing with an existing property,
      * and guards the shape for us.
      */
     JSObject* obj2;
     PCVal pcval;
     CHECK_STATUS_A(test_property_cache(obj, obj_ins, obj2, pcval));
 
-    /* Check for non-existent property reference, which results in undefined. */
+    /* Check for nonexistent property reference, which results in undefined. */
     if (pcval.isNull()) {
         if (slotp)
             RETURN_STOP_A("property not found");
 
         /*
          * We could specialize to guard on just JSClass.getProperty, but a mere
          * class guard is simpler and slightly faster.
          */
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -3586,19 +3586,20 @@ static void
 CancelExecution(JSRuntime *rt)
 {
     gCanceled = true;
     if (gExitCode == 0)
         gExitCode = EXITCODE_TIMEOUT;
 #ifdef JS_THREADSAFE
     if (gWorkers) {
         JSContext *cx = JS_NewContext(rt, 8192);
-        if (cx)
+        if (cx) {
             js::workers::terminateAll(cx, gWorkers);
-        JS_DestroyContextNoGC(cx);
+            JS_DestroyContextNoGC(cx);
+        }
     }
 #endif
     JS_TriggerAllOperationCallbacks(rt);
 
     static const char msg[] = "Script runs for too long, terminating.\n";
 #if defined(XP_UNIX) && !defined(JS_THREADSAFE)
     /* It is not safe to call fputs from signals. */
     /* Dummy assignment avoids GCC warning on "attribute warn_unused_result" */
--- a/js/src/tests/js1_5/Regress/regress-156354.js
+++ b/js/src/tests/js1_5/Regress/regress-156354.js
@@ -34,25 +34,25 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 /*
  *
  * Date:    16 September 2002
- * SUMMARY: Testing propertyIsEnumerable() on non-existent property
+ * SUMMARY: Testing propertyIsEnumerable() on nonexistent property
  * See http://bugzilla.mozilla.org/show_bug.cgi?id=156354
  *
  */
 //-----------------------------------------------------------------------------
 var gTestfile = 'regress-156354.js';
 var UBound = 0;
 var BUGNUMBER = 156354;
-var summary = 'Testing propertyIsEnumerable() on non-existent property';
+var summary = 'Testing propertyIsEnumerable() on nonexistent property';
 var status = '';
 var statusitems = [];
 var actual = '';
 var actualvalues = [];
 var expect= '';
 var expectedvalues = [];
 
 
--- a/js/src/tests/js1_5/extensions/getset-006.js
+++ b/js/src/tests/js1_5/extensions/getset-006.js
@@ -142,17 +142,17 @@ obj = new TestObject();
 obj.name = cnFRED;
 obj.color = cnRED;
 
 status = 'In SECTION3 of test looking up extant getter/setter';
 actual = [obj.__lookupSetter__(cnName), obj.__lookupGetter__(cnName)];
 expect = [cnNameSetter, cnNameGetter];
 addThis();
 
-status = 'In SECTION3 of test; looking up non-existent getter/setter';
+status = 'In SECTION3 of test; looking up nonexistent getter/setter';
 actual = [obj.__lookupSetter__(cnColor), obj.__lookupGetter__(cnColor)];
 expect = [undefined, undefined];
 addThis();
 
 status = 'In SECTION3 of test; looking up getter/setter on nonexistent property';
 actual = [obj.__lookupSetter__(cnNonExistingProp), obj.__lookupGetter__(cnNonExistingProp)];
 expect = [undefined, undefined];
 addThis();
--- a/js/src/tests/js1_7/iterable/regress-341510.js
+++ b/js/src/tests/js1_7/iterable/regress-341510.js
@@ -34,17 +34,17 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 var gTestfile = 'regress-341510.js';
 //-----------------------------------------------------------------------------
 var BUGNUMBER = 341510;
 var summary = 'Iterators: crash in close handler with assignment to ' +
-  'non-existing name';
+  'nonexistent name';
 var actual = 'No Crash';
 var expect = 'No Crash';
 
 printBugNumber(BUGNUMBER);
 printStatus (summary);
 
 function gen(i) {
   try {
--- a/js/src/xpconnect/src/Makefile.in
+++ b/js/src/xpconnect/src/Makefile.in
@@ -155,20 +155,16 @@ DEFINES += \
   -DFEATURE_NANOJIT=1 \
   $(addprefix -D,$(filter AVMPLUS%,$(CONFIG))) \
   $(NULL)
 
 ENABLE_TRACEABLE_FLAGS = --enable-traceables
 
 endif # ENABLE_JIT
 
-ifdef MOZ_XPCTOOLS
-DEFINES         +=  -DXPC_TOOLS_SUPPORT
-endif
-
 ifdef XPC_IDISPATCH_SUPPORT
 DEFINES		+= -DXPC_IDISPATCH_SUPPORT
 ifdef XPC_COMOBJECT
 DEFINES		+= -DXPC_COMOBJECT
 endif
 
 endif
 
--- a/js/src/xpconnect/src/nsXPConnect.cpp
+++ b/js/src/xpconnect/src/nsXPConnect.cpp
@@ -92,40 +92,16 @@ nsXPConnect::nsXPConnect()
 {
     mRuntime = XPCJSRuntime::newXPCJSRuntime(this);
 
     nsCycleCollector_registerRuntime(nsIProgrammingLanguage::JAVASCRIPT, this);
 #ifdef DEBUG_CC
     mJSRoots.ops = nsnull;
 #endif
 
-#ifdef XPC_TOOLS_SUPPORT
-  {
-    char* filename = PR_GetEnv("MOZILLA_JS_PROFILER_OUTPUT");
-    if(filename && *filename)
-    {
-        mProfilerOutputFile = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID);
-        if(mProfilerOutputFile &&
-           NS_SUCCEEDED(mProfilerOutputFile->InitWithNativePath(nsDependentCString(filename))))
-        {
-            mProfiler = do_GetService(XPCTOOLS_PROFILER_CONTRACTID);
-            if(mProfiler)
-            {
-                if(NS_SUCCEEDED(mProfiler->Start()))
-                {
-#ifdef DEBUG
-                    printf("***** profiling JavaScript. Output to: %s\n",
-                           filename);
-#endif
-                }
-            }
-        }
-    }
-  }
-#endif
     char* reportableEnv = PR_GetEnv("MOZ_REPORT_ALL_JS_EXCEPTIONS");
     if(reportableEnv && *reportableEnv)
         gReportAllJSExceptions = 1;
 }
 
 nsXPConnect::~nsXPConnect()
 {
     NS_ASSERTION(!mCycleCollectionContext,
@@ -215,24 +191,16 @@ nsXPConnect::GetSingleton()
 void
 nsXPConnect::ReleaseXPConnectSingleton()
 {
     nsXPConnect* xpc = gSelf;
     if(xpc)
     {
         NS_SetGlobalThreadObserver(nsnull);
 
-#ifdef XPC_TOOLS_SUPPORT
-        if(xpc->mProfiler)
-        {
-            xpc->mProfiler->Stop();
-            xpc->mProfiler->WriteResults(xpc->mProfilerOutputFile);
-        }
-#endif
-
 #ifdef DEBUG
         // force a dump of the JavaScript gc heap if JS is still alive
         // if requested through XPC_SHUTDOWN_HEAP_DUMP environment variable
         {
             // autoscope
             XPCCallContext ccx(NATIVE_CALLER);
             if(ccx.IsValid())
             {
--- a/js/src/xpconnect/src/xpcprivate.h
+++ b/js/src/xpconnect/src/xpcprivate.h
@@ -122,20 +122,16 @@
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIPrincipal.h"
 #endif
 
 #ifdef XPC_USE_SECURITY_CHECKED_COMPONENT
 #include "nsISecurityCheckedComponent.h"
 #endif
 
-#ifdef XPC_TOOLS_SUPPORT
-#include "nsIXPCToolsProfiler.h"
-#endif
-
 #include "nsIThreadInternal.h"
 
 #ifdef XPC_IDISPATCH_SUPPORT
 // This goop was added because of EXCEPINFO in ThrowCOMError
 // This include is here, because it needs to occur before the undefines below
 #ifdef WINCE
 /* atlbase.h on WINCE has a bug, in that it tries to use
  * GetProcAddress with a wide string, when that is explicitly not
@@ -549,21 +545,16 @@ private:
     JSBool                   mShuttingDown;
     XPCCallContext*          mCycleCollectionContext;
 #ifdef DEBUG_CC
     nsAutoPtr<XPCCallContext> mExplainCycleCollectionContext;
     PLDHashTable             mJSRoots;
 #endif
     PRBool                   mCycleCollecting;
 
-#ifdef XPC_TOOLS_SUPPORT
-    nsCOMPtr<nsIXPCToolsProfiler> mProfiler;
-    nsCOMPtr<nsILocalFile>        mProfilerOutputFile;
-#endif
-
 #ifndef XPCONNECT_STANDALONE
     typedef nsBaseHashtable<nsVoidPtrHashKey, nsISupports*, nsISupports*> ScopeSet;
     ScopeSet mScopes;
 #endif
     nsCOMPtr<nsIXPCScriptable> mBackstagePass;
 
     static PRUint32 gReportAllJSExceptions;
 };
--- a/js/src/xpconnect/src/xpcthreadcontext.cpp
+++ b/js/src/xpconnect/src/xpcthreadcontext.cpp
@@ -278,17 +278,17 @@ XPCJSContextStack::GetSafeJSContext(JSCo
                 // hook.
 #endif
                 if(glob && NS_FAILED(xpc->InitClasses(mSafeJSContext, glob)))
                 {
                     glob = nsnull;
                 }
 
             }
-            if(!glob && mSafeJSContext)
+            if(mSafeJSContext && !glob)
             {
                 // Destroy the context outside the scope of JSAutoRequest that
                 // uses the context in its destructor.
                 JS_DestroyContext(mSafeJSContext);
                 mSafeJSContext = nsnull;
             }
             // Save it off so we can destroy it later, even if
             // mSafeJSContext has been set to another context
--- a/js/src/xpconnect/tests/mochitest/test_cows.html
+++ b/js/src/xpconnect/tests/mochitest/test_cows.html
@@ -74,19 +74,19 @@ function COWTests() {
         } catch (e) {
             ok(/SECURITY_MANAGER/.test(e),
                "not able to access arbitrary property " + uneval(name));
         }
     });
 
     try {
         if (strictCOW.foo)
-            ok(false, "non-existent property shouldn't be truthy.");
+            ok(false, "nonexistent property shouldn't be truthy.");
         else
-            ok(true, "'duck-typing' detection on non-existent prop " +
+            ok(true, "'duck-typing' detection on nonexistent prop " +
                      "should work.");
     } catch (e) {
         todo(false,
              "'duck-typing' detection on a non-exposed prop of a COWed " +
              "obj should not throw");
     }
 
     var writable = { __exposedProps__: {foo: 'w'}};
deleted file mode 100644
--- a/js/src/xpconnect/tools/Makefile.in
+++ /dev/null
@@ -1,49 +0,0 @@
-#
-# ***** BEGIN LICENSE BLOCK *****
-# Version: MPL 1.1/GPL 2.0/LGPL 2.1
-#
-# The contents of this file are subject to the Mozilla Public License Version
-# 1.1 (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-# http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS IS" basis,
-# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-# for the specific language governing rights and limitations under the
-# License.
-#
-# The Original Code is Mozilla Communicator client code, released
-# March 31, 1998.
-#
-# The Initial Developer of the Original Code is
-# Netscape Communications Corporation.
-# Portions created by the Initial Developer are Copyright (C) 1998
-# the Initial Developer. All Rights Reserved.
-#
-# Contributor(s):
-#
-# Alternatively, the contents of this file may be used under the terms of
-# either of the GNU General Public License Version 2 or later (the "GPL"),
-# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
-# in which case the provisions of the GPL or the LGPL are applicable instead
-# of those above. If you wish to allow use of your version of this file only
-# under the terms of either the GPL or the LGPL, and not to allow others to
-# use your version of this file under the terms of the MPL, indicate your
-# decision by deleting the provisions above and replace them with the notice
-# and other provisions required by the GPL or the LGPL. If you do not delete
-# the provisions above, a recipient may use your version of this file under
-# the terms of any one of the MPL, the GPL or the LGPL.
-#
-# ***** END LICENSE BLOCK *****
-
-DEPTH		= ../../../..
-topsrcdir	= @top_srcdir@
-srcdir		= @srcdir@
-VPATH		= @srcdir@
-
-include $(DEPTH)/config/autoconf.mk
-
-DIRS		= idl src
-
-include $(topsrcdir)/config/rules.mk
-
deleted file mode 100644
--- a/js/src/xpconnect/tools/idl/Makefile.in
+++ /dev/null
@@ -1,53 +0,0 @@
-#
-# ***** BEGIN LICENSE BLOCK *****
-# Version: MPL 1.1/GPL 2.0/LGPL 2.1
-#
-# The contents of this file are subject to the Mozilla Public License Version
-# 1.1 (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-# http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS IS" basis,
-# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-# for the specific language governing rights and limitations under the
-# License.
-#
-# The Original Code is Mozilla Communicator client code, released
-# March 31, 1998.
-#
-# The Initial Developer of the Original Code is
-# Netscape Communications Corporation.
-# Portions created by the Initial Developer are Copyright (C) 1999
-# the Initial Developer. All Rights Reserved.
-#
-# Contributor(s):
-#
-# Alternatively, the contents of this file may be used under the terms of
-# either of the GNU General Public License Version 2 or later (the "GPL"),
-# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
-# in which case the provisions of the GPL or the LGPL are applicable instead
-# of those above. If you wish to allow use of your version of this file only
-# under the terms of either the GPL or the LGPL, and not to allow others to
-# use your version of this file under the terms of the MPL, indicate your
-# decision by deleting the provisions above and replace them with the notice
-# and other provisions required by the GPL or the LGPL. If you do not delete
-# the provisions above, a recipient may use your version of this file under
-# the terms of any one of the MPL, the GPL or the LGPL.
-#
-# ***** END LICENSE BLOCK *****
-
-DEPTH		= ../../../../..
-topsrcdir	= @top_srcdir@
-srcdir		= @srcdir@
-VPATH		= @srcdir@
-
-include $(DEPTH)/config/autoconf.mk
-
-MODULE		= xpctools
-
-XPIDLSRCS	= \
-		nsIXPCToolsCompiler.idl \
-        	nsIXPCToolsProfiler.idl \
-		$(NULL)
-
-include $(topsrcdir)/config/rules.mk
deleted file mode 100644
--- a/js/src/xpconnect/tools/idl/nsIXPCToolsCompiler.idl
+++ /dev/null
@@ -1,60 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- *
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Communicator client code, released
- * March 31, 1998.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   John Bandhauer <jband@netscape.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-/* Interface for JS code testing tool which does compile-time checking. */
-
-#include "nsISupports.idl"
-#include "nsILocalFile.idl"
-
-[scriptable, uuid(71151570-e56f-11d3-8f65-0010a4e73d9a)]
-interface nsIXPCToolsCompiler : nsISupports
-{
-    /** 
-    * XXX temporary hack because there does not seem to be another scriptable
-    * way to get this info.
-    */
-    readonly attribute nsILocalFile binDir;
-
-    void  CompileFile(in nsILocalFile aFile, in PRBool strict);
-};
-
-%{ C++
-#define XPCTOOLS_COMPILER_CONTRACTID "xpctools.compiler.1"
-%}
deleted file mode 100644
--- a/js/src/xpconnect/tools/idl/nsIXPCToolsProfiler.idl
+++ /dev/null
@@ -1,57 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- *
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Communicator client code, released
- * March 31, 1998.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   John Bandhauer <jband@netscape.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-/* Interface for JS code testing tool which does code coverage and profiling. */
-
-#include "nsISupports.idl"
-#include "nsILocalFile.idl"
-
-[scriptable, uuid(09ef19b0-e97a-11d3-8f69-0010a4e73d9a)]
-interface nsIXPCToolsProfiler : nsISupports
-{
-    void  start();
-    void  stop();
-    void  clear();
-    void  writeResults(in nsILocalFile aFile);
-};
-
-%{ C++
-#define XPCTOOLS_PROFILER_CONTRACTID "xpctools.profiler.1"
-%}
deleted file mode 100644
--- a/js/src/xpconnect/tools/js/CompileJSFiles.js
+++ /dev/null
@@ -1,28 +0,0 @@
-const nsIFile = Components.interfaces.nsIFile;
-var Compiler = new Components.Constructor("xpctools.compiler.1",
-                                          "nsIXPCToolsCompiler");
-var c = new Compiler;
-
-dump("\n");
-dump("Compiling all .js files under "+c.binDir.path+"\n");
-dump("Will report any compile-time errors...\n\n");
-dump( "compiled "+CompileJSFilesInDir(c.binDir)+" files\n\n");
-
-function CompileJSFilesInDir(dir) {
-    var count = 0;
-    if(!dir.isDirectory())
-        return;
-    var list = dir.directoryEntries;    
-    while(list.hasMoreElements()) {
-        file = list.getNext().QueryInterface(nsIFile);
-        if(file.isDirectory())
-            count += CompileJSFilesInDir(file);
-        else if(file.leafName.match(/\.js$/i)) {
-            // dump("compiling... "+file.path+"\n");
-            c.CompileFile(file, false);
-            ++count;
-        }
-    }
-    return count;
-}
-
deleted file mode 100644
--- a/js/src/xpconnect/tools/js/ListJSFiles.js
+++ /dev/null
@@ -1,18 +0,0 @@
-const nsIFile = Components.interfaces.nsIFile;
-var Compiler = new Components.Constructor("xpctools.compiler.1","nsIXPCToolsCompiler");
-var c = new Compiler;
-ListJSFilesInDir(c.binDir);
-
-function ListJSFilesInDir(dir) {
-    if(!dir.isDirectory())
-        return;
-    var list = dir.directoryEntries;    
-    while(list.hasMoreElements()) {
-        file = list.getNext().QueryInterface(nsIFile);
-        if(file.isDirectory())
-            ListJSFilesInDir(file);
-        else if(file.leafName.match(/\.js$/i))
-            dump(file.path+"\n");
-    }
-}
-
deleted file mode 100644
--- a/js/src/xpconnect/tools/src/Makefile.in
+++ /dev/null
@@ -1,71 +0,0 @@
-#
-# ***** BEGIN LICENSE BLOCK *****
-# Version: MPL 1.1/GPL 2.0/LGPL 2.1
-#
-# The contents of this file are subject to the Mozilla Public License Version
-# 1.1 (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-# http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS IS" basis,
-# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-# for the specific language governing rights and limitations under the
-# License.
-#
-# The Original Code is Mozilla Communicator client code, released
-# March 31, 1998.
-#
-# The Initial Developer of the Original Code is
-# Netscape Communications Corporation.
-# Portions created by the Initial Developer are Copyright (C) 1998
-# the Initial Developer. All Rights Reserved.
-#
-# Contributor(s):
-#   John Bandhauer <jband@netscape.com>
-#
-# Alternatively, the contents of this file may be used under the terms of
-# either of the GNU General Public License Version 2 or later (the "GPL"),
-# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
-# in which case the provisions of the GPL or the LGPL are applicable instead
-# of those above. If you wish to allow use of your version of this file only
-# under the terms of either the GPL or the LGPL, and not to allow others to
-# use your version of this file under the terms of the MPL, indicate your
-# decision by deleting the provisions above and replace them with the notice
-# and other provisions required by the GPL or the LGPL. If you do not delete
-# the provisions above, a recipient may use your version of this file under
-# the terms of any one of the MPL, the GPL or the LGPL.
-#
-# ***** END LICENSE BLOCK *****
-
-DEPTH		= ../../../../..
-topsrcdir	= @top_srcdir@
-srcdir		= @srcdir@
-VPATH		= @srcdir@
-
-include $(DEPTH)/config/autoconf.mk
-
-MODULE		= xpctools
-LIBRARY_NAME	= xpctools
-
-MODULE_NAME	= xpctools
-IS_COMPONENT	= 1
-FORCE_SHARED_LIB = 1
-
-CPPSRCS		= \
-		nsXPCToolsCompiler.cpp \
-		nsXPCToolsProfiler.cpp \
-		nsXPCToolsModule.cpp \
-		$(NULL)
-
-include $(topsrcdir)/config/config.mk
-
-EXTRA_DSO_LDOPTS += \
-		$(XPCOM_GLUE_LDOPTS) \
-		$(MOZ_JS_LIBS) \
-		$(NSPR_LIBS) \
-		$(NULL)
-
-include $(topsrcdir)/config/rules.mk
-
-DEFINES		+= -DJSFILE -DJS_THREADSAFE
-
deleted file mode 100644
--- a/js/src/xpconnect/tools/src/nsXPCToolsCompiler.cpp
+++ /dev/null
@@ -1,161 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- *
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Communicator client code, released
- * March 31, 1998.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1999
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   John Bandhauer <jband@netscape.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-/* Implements nsXPCToolsCompiler. */
-
-#include "xpctools_private.h"
-#include "nsDirectoryServiceDefs.h"
-#include "nsDirectoryServiceUtils.h"
-
-NS_IMPL_ISUPPORTS1(nsXPCToolsCompiler, nsIXPCToolsCompiler)
-
-nsXPCToolsCompiler::nsXPCToolsCompiler()
-{
-}
-
-nsXPCToolsCompiler::~nsXPCToolsCompiler()
-{
-}
-
-/* readonly attribute nsILocalFile binDir; */
-NS_IMETHODIMP nsXPCToolsCompiler::GetBinDir(nsILocalFile * *aBinDir)
-{
-    *aBinDir = nsnull;
-    
-    nsCOMPtr<nsIFile> file;
-    nsresult rv = NS_GetSpecialDirectory(NS_XPCOM_CURRENT_PROCESS_DIR, getter_AddRefs(file));
-    if(NS_FAILED(rv))
-        return rv;
-
-    nsCOMPtr<nsILocalFile> lfile = do_QueryInterface(file);
-    NS_ADDREF(*aBinDir = lfile);
-    return NS_OK;
-}
-
-static void ErrorReporter(JSContext *cx, const char *message,
-                          JSErrorReport *report)
-{
-    printf("compile error!\n");
-}
-
-static JSClass global_class = {
-    "nsXPCToolsCompiler::global", 0,
-    JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,
-    JS_EnumerateStub, JS_ResolveStub,   JS_ConvertStub,   nsnull
-};
-
-/* void CompileFile (in nsILocalFile aFile, in PRBool strict); */
-NS_IMETHODIMP nsXPCToolsCompiler::CompileFile(nsILocalFile *aFile, PRBool strict)
-{
-    // use the xpccallcontext stuff to get the current JSContext
-    
-    // get the xpconnect service
-    nsresult rv;
-    nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));
-    if(NS_FAILED(rv))
-        return NS_ERROR_FAILURE;
-
-    // get the xpconnect native call context
-    nsAXPCNativeCallContext *callContext = nsnull;
-    xpc->GetCurrentNativeCallContext(&callContext);
-    if(!callContext)
-        return NS_ERROR_FAILURE;
-
-    // verify that we are being called from JS (i.e. the current call is
-    // to this object - though we don't verify that it is to this exact method)
-    nsCOMPtr<nsISupports> callee;
-    callContext->GetCallee(getter_AddRefs(callee));
-    if(!callee || callee.get() != (nsISupports*)this)
-        return NS_ERROR_FAILURE;
-
-    // Get JSContext of current call
-    JSContext* cx;
-    rv = callContext->GetJSContext(&cx);
-    if(NS_FAILED(rv) || !cx)
-        return NS_ERROR_FAILURE;
-
-    FILE* handle;
-    if(NS_FAILED(aFile->OpenANSIFileDesc("r", &handle)))
-        return NS_ERROR_FAILURE;
-
-    JSObject* glob = JS_NewObject(cx, &global_class, NULL, NULL);
-    if (!glob)
-        return NS_ERROR_FAILURE;
-    if (!JS_InitStandardClasses(cx, glob))
-        return NS_ERROR_FAILURE;
-
-    nsCAutoString path;
-    if(NS_FAILED(aFile->GetNativePath(path)))
-        return NS_ERROR_FAILURE;
-
-    uint32 oldoptions = JS_GetOptions(cx);
-    JS_SetOptions(cx, JSOPTION_WERROR | (strict ? JSOPTION_STRICT : 0));
-    JSErrorReporter older = JS_SetErrorReporter(cx, ErrorReporter);
-    JSExceptionState *es =JS_SaveExceptionState(cx);
-
-    if(!JS_CompileFileHandle(cx, glob, path.get(), handle))
-    {
-        jsval v;
-        JSErrorReport* report;
-        if(JS_GetPendingException(cx, &v) &&
-           nsnull != (report = JS_ErrorFromException(cx, v)))
-        {
-            JSString* str;
-            const char* msg = "Error";
-            str = JS_ValueToString(cx, v);
-            if(str)
-                msg = JS_GetStringBytes(str);
-            printf("%s [%s,%d]\n\n",
-                    msg,
-                    report->filename, 
-                    (int)report->lineno);            
-        }
-        else
-        {
-            printf("no script and no error report!\n");
-        }
-        
-    }    
-    JS_RestoreExceptionState(cx, es);
-    JS_SetErrorReporter(cx, older);
-    JS_SetOptions(cx, oldoptions);
-        
-    return NS_OK;
-}
deleted file mode 100644
--- a/js/src/xpconnect/tools/src/nsXPCToolsModule.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- *
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Communicator client code, released
- * March 31, 1998.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1999
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   John Bandhauer <jband@netscape.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-/* Module code for XPCTools. */
-
-#include "xpctools_private.h"
-
-// Module implementation for the xpctools library
-
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsXPCToolsCompiler)
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsXPCToolsProfiler)
-
-// {331148C0-E599-11d3-8F65-0010A4E73D9A}
-#define COMPILER_CID \
-    { 0x331148c0, 0xe599, 0x11d3, \
-        { 0x8f, 0x65, 0x0, 0x10, 0xa4, 0xe7, 0x3d, 0x9a } }
-
-// {7F5D12E0-E97B-11d3-8F69-0010A4E73D9A}
-#define PROFILER_CID \
-    { 0x7f5d12e0, 0xe97b, 0x11d3, \
-        { 0x8f, 0x69, 0x0, 0x10, 0xa4, 0xe7, 0x3d, 0x9a } }
-
-static const nsModuleComponentInfo components[] = {
- {nsnull, COMPILER_CID, XPCTOOLS_COMPILER_CONTRACTID, nsXPCToolsCompilerConstructor},
- {nsnull, PROFILER_CID, XPCTOOLS_PROFILER_CONTRACTID, nsXPCToolsProfilerConstructor}
-};
-
-NS_IMPL_NSGETMODULE(xpctools, components)
deleted file mode 100644
--- a/js/src/xpconnect/tools/src/nsXPCToolsProfiler.cpp
+++ /dev/null
@@ -1,370 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- *
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Communicator client code, released
- * March 31, 1998.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1999
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   John Bandhauer <jband@netscape.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-/* Implements nsXPCToolsProfiler. */
-
-#include "xpctools_private.h"
-
-/***************************************************************************/
-
-ProfilerFile::ProfilerFile(const char* filename)
-    :   mName(filename ? strdup(filename) : nsnull)
-{
-    mFunctionTable.Init();
-}
-
-ProfilerFile::~ProfilerFile()
-{
-    if(mName)
-        free(mName);
-}
-
-ProfilerFunction* 
-ProfilerFile::FindOrAddFunction(const char* aName,
-                                uintN aBaseLineNumber,
-                                uintN aLineExtent,
-                                size_t aTotalSize)
-{
-    FunctionID key(aBaseLineNumber, aLineExtent);
-    ProfilerFunction* fun;
-
-    if (!mFunctionTable.Get(key, &fun))
-    {
-        fun = new ProfilerFunction(aName, aBaseLineNumber, aLineExtent,
-                                   aTotalSize, this);
-        if(fun)
-            mFunctionTable.Put(key, fun);
-    }
-    return fun;
-}
-
-void
-ProfilerFile::EnumerateFunctions(EnumeratorType aFunc, void *aClosure) const
-{
-    mFunctionTable.EnumerateRead(aFunc, aClosure);
-}
-
-ProfilerFunction::ProfilerFunction(const char* name, 
-                                   uintN lineno, uintn extent, size_t totalsize,
-                                   ProfilerFile* file)
-    :   mName(name ? strdup(name) : nsnull),
-        mBaseLineNumber(lineno),
-        mLineExtent(extent),
-        mTotalSize(totalsize),
-        mFile(file),
-        mCallCount(0),
-        mCompileCount(0),
-        mQuickTime((PRUint32) -1),
-        mLongTime(0),
-        mStartTime(0),
-        mSum(0)
-{
-    // empty        
-}
-
-ProfilerFunction::~ProfilerFunction()
-{
-    if(mName)
-        free(mName);
-}
-
-/***************************************************************************/
-
-
-NS_IMPL_ISUPPORTS1(nsXPCToolsProfiler, nsIXPCToolsProfiler)
-
-nsXPCToolsProfiler::nsXPCToolsProfiler()
-    :   mLock(PR_NewLock()),
-        mRuntime(nsnull)
-{
-    InitializeRuntime();
-    mFileTable.Init();
-    mScriptTable.Init();
-}
-
-nsXPCToolsProfiler::~nsXPCToolsProfiler()
-{
-    Stop();
-    if(mLock)
-        PR_DestroyLock(mLock);
-}
-
-/***************************************************************************/
-// the hooks...
-
-/* called just after script creation */
-static void
-xpctools_JSNewScriptHook(JSContext  *cx,
-                         const char *filename,  /* URL of script */
-                         uintN      lineno,     /* line script starts */
-                         JSScript   *script,
-                         JSFunction *fun,
-                         void       *callerdata)
-{
-    if(!script)
-        return;
-    if(!filename)
-        filename = "<<<!!! has no name so may represent many different pages !!!>>>";
-    nsXPCToolsProfiler* self = (nsXPCToolsProfiler*) callerdata;    
-
-    PR_Lock(self->mLock);
-
-    ProfilerFile* file;
-    if (!self->mFileTable.Get(filename, &file))
-    {
-        file = new ProfilerFile(filename);
-        if (file)
-            self->mFileTable.Put(filename, file);
-    }
-    if(file)
-    {
-        ProfilerFunction* function = 
-            file->FindOrAddFunction(fun ? JS_GetFunctionName(fun) : nsnull, 
-                                    JS_GetScriptBaseLineNumber(cx, script),
-                                    JS_GetScriptLineExtent(cx, script),
-                                    fun
-                                    ? JS_GetFunctionTotalSize(cx, fun)
-                                    : JS_GetScriptTotalSize(cx, script));
-        if(function)
-        {
-            function->IncrementCompileCount();
-            self->mScriptTable.Put(script, function);
-        }
-    }
-    PR_Unlock(self->mLock);
-}
-
-/* called just before script destruction */
-static void
-xpctools_JSDestroyScriptHook(JSContext  *cx,
-                             JSScript   *script,
-                             void       *callerdata)
-{
-    if(!script)
-        return;
-    nsXPCToolsProfiler* self = (nsXPCToolsProfiler*) callerdata;
-
-    PR_Lock(self->mLock);
-    self->mScriptTable.Remove(script);
-    PR_Unlock(self->mLock);
-}
-
-
-/* called on entry and return of functions and top level scripts */
-static void*
-xpctools_InterpreterHook(JSContext *cx, JSStackFrame *fp, JSBool before,
-                         JSBool *ok, void *closure)
-{
-    // ignore returns
-    NS_ASSERTION(fp, "bad frame pointer!");
-
-    JSScript* script = fp->script;
-    if(script)
-    {
-        nsXPCToolsProfiler* self = (nsXPCToolsProfiler*) closure;    
-
-        PR_Lock(self->mLock);
-
-        ProfilerFunction* fun;
-        if (self->mScriptTable.Get(script, &fun))
-        {
-            if(before)
-            {
-                fun->IncrementCallCount();
-                fun->SetStartTime();
-            }
-            else
-            {
-                PRUint32 delta = fun->SetEndTime();
-
-                JSStackFrame* down = fp->down;
-                if (down) {
-                    JSScript* caller = down->script;
-                    if (caller) {
-                        ProfilerFunction* callfun;
-                        if (self->mScriptTable.Get(caller, &callfun))
-                        {
-                            callfun->AddNotSelfTime(delta);
-                        }
-                    }
-                }
-            }
-        }
-
-        PR_Unlock(self->mLock);
-    }   
-    return closure;
-}
-
-/***************************************************************************/
-// interface methods
-
-/* void start (); */
-NS_IMETHODIMP nsXPCToolsProfiler::Start()
-{
-    PR_Lock(mLock);
-
-    if(!VerifyRuntime())
-    {
-        PR_Unlock(mLock);
-        return NS_ERROR_UNEXPECTED; 
-    }
-
-    JS_SetNewScriptHook(mRuntime, xpctools_JSNewScriptHook, this);
-    JS_SetDestroyScriptHook(mRuntime, xpctools_JSDestroyScriptHook, this);
-    JS_SetExecuteHook(mRuntime, xpctools_InterpreterHook, this);
-    JS_SetCallHook(mRuntime, xpctools_InterpreterHook, this);
-
-    PR_Unlock(mLock);
-    return NS_OK;
-}
-
-/* void stop (); */
-NS_IMETHODIMP nsXPCToolsProfiler::Stop()
-{
-    PR_Lock(mLock);
-
-    if(!VerifyRuntime())
-    {
-        PR_Unlock(mLock);
-        return NS_ERROR_UNEXPECTED; 
-    }
-
-    JS_SetNewScriptHook(mRuntime, nsnull, nsnull);
-    JS_SetDestroyScriptHook(mRuntime, nsnull, nsnull);
-    JS_SetExecuteHook(mRuntime, nsnull, this);
-    JS_SetCallHook(mRuntime, nsnull, this);
-    
-    PR_Unlock(mLock);
-    return NS_OK;
-}
-
-/* void clear (); */
-NS_IMETHODIMP nsXPCToolsProfiler::Clear()
-{
-  // XXX implement me!
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-
-static PLDHashOperator
-xpctools_FunctionNamePrinter(const FunctionID &aKey,
-                             ProfilerFunction* fun, void* closure)
-{
-    FILE* out = (FILE*) closure;
-    const char* name = fun->GetName();
-    PRUint32 average;
-    PRUint32 count;
-
-    count = fun->GetCallCount();
-    if (count != 0)
-        average = fun->GetSum() / count;
-    if(!name)
-        name = "<top level>"; 
-    fprintf(out,
-        "    [%lu,%lu] %s() {%d-%d} %lu ",
-        (unsigned long) fun->GetCompileCount(),
-        (unsigned long) fun->GetCallCount(),
-        name,
-        (int) fun->GetBaseLineNumber(),
-        (int)(fun->GetBaseLineNumber()+fun->GetLineExtent()-1),
-        (unsigned long) fun->GetTotalSize());
-    if(count != 0)
-        fprintf(out,
-            "{min %lu, max %lu, avg %lu, sum %lu, self %lu}\n",
-            (unsigned long) fun->GetQuickTime(),
-            (unsigned long) fun->GetLongTime(),
-            (unsigned long) average,
-            (unsigned long) fun->GetSum(),
-            (unsigned long) fun->GetSelf());
-    else
-        fprintf(out, "\n" );
-    return PL_DHASH_NEXT;
-}        
-
-static PLDHashOperator
-xpctools_FilenamePrinter(const char *keyname, ProfilerFile* file,
-                         void *closure)
-{
-    FILE* out = (FILE*) closure;
-    fprintf(out, "%s\n", file->GetName());
-    file->EnumerateFunctions(xpctools_FunctionNamePrinter, closure);
-    return PL_DHASH_NEXT;
-}        
-
-/* void writeResults (in nsILocalFile aFile); */
-NS_IMETHODIMP nsXPCToolsProfiler::WriteResults(nsILocalFile *aFile)
-{
-    NS_ENSURE_ARG(aFile);
-
-    FILE* out;
-    if(NS_FAILED(aFile->OpenANSIFileDesc("w", &out)) || ! out)
-        return NS_ERROR_FAILURE;
-
-    fprintf(out, "[CompileCount, CallCount] Name {StartLine, EndLine} TotalSize {MinTime, MaxTime, Average, Total, Self}\n\n");
-
-    PR_Lock(mLock);
-    mFileTable.EnumerateRead(xpctools_FilenamePrinter, out);
-    PR_Unlock(mLock);
-    
-    return NS_OK;
-}
-
-/***************************************************************************/
-// additional utility methods
-
-JSBool
-nsXPCToolsProfiler::VerifyRuntime()
-{
-    JSRuntime* rt;
-    nsCOMPtr<nsIJSRuntimeService> rts = do_GetService("@mozilla.org/js/xpc/RuntimeService;1");
-    return rts && NS_SUCCEEDED(rts->GetRuntime(&rt)) && rt && rt == mRuntime;
-}
-
-JSBool 
-nsXPCToolsProfiler::InitializeRuntime()
-{
-    NS_ASSERTION(!mRuntime, "can't init runtime twice");
-    JSRuntime* rt;
-    nsCOMPtr<nsIJSRuntimeService> rts = do_GetService("@mozilla.org/js/xpc/RuntimeService;1");
-    if(rts && NS_SUCCEEDED(rts->GetRuntime(&rt)) && rt)
-        mRuntime = rt;
-    return mRuntime != nsnull;
-}
deleted file mode 100644
--- a/js/src/xpconnect/tools/src/xpctools_private.h
+++ /dev/null
@@ -1,236 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- *
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Communicator client code, released
- * March 31, 1998.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   John Bandhauer <jband@netscape.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-/* All the XPCTools private declarations - only include locally. */
-
-#ifndef xpctoolsprivate_h___
-#define xpctoolsprivate_h___
-
-#include <string.h>
-#include <stdlib.h>
-#include "nscore.h"
-#include "nsISupports.h"
-#include "nsIServiceManager.h"
-#include "nsIComponentManager.h"
-#include "nsIGenericFactory.h"
-#include "nsIMemory.h"
-#include "nsIXPConnect.h"
-#include "nsCOMPtr.h"
-#include "nsIModule.h"
-#include "jsapi.h"
-#include "jshash.h"
-#include "jsprf.h"
-#include "jsinterp.h"
-#include "jscntxt.h"
-#include "jsdbgapi.h"
-
-#include "nsILocalFile.h"
-
-#include "nsIJSRuntimeService.h"
-#include "nsClassHashtable.h"
-#include "nsDataHashtable.h"
-#include "nsServiceManagerUtils.h"
-
-#include "nsIXPCToolsCompiler.h"
-#include "nsIXPCToolsProfiler.h"
-
-class nsXPCToolsCompiler : public nsIXPCToolsCompiler
-{
-public:
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIXPCTOOLSCOMPILER
-
-  nsXPCToolsCompiler();
-  virtual ~nsXPCToolsCompiler();
-  // XXX add additional members
-};
-
-/***************************************************************************/
-
-class ProfilerFile;
-
-class ProfilerFunction
-{
-public:
-    ProfilerFunction(const char* name, 
-                     uintN lineno, uintn extent, size_t totalsize,
-                     ProfilerFile* file);
-    ~ProfilerFunction();
-
-    const char*   GetName() const {return mName;}
-    ProfilerFile* GetFile() const {return mFile;}
-    uintN         GetBaseLineNumber() const {return mBaseLineNumber;}
-    uintN         GetLineExtent() const {return mLineExtent;}
-    size_t        GetTotalSize() const { return mTotalSize; }
-    void          IncrementCallCount() {++mCallCount;}
-    PRUint32      GetCallCount() {return mCallCount;}
-    PRUint32      GetSum() {return mSum;}
-    void          IncrementCompileCount() {++mCompileCount;}
-    PRUint32      GetCompileCount() {return mCompileCount;}
-    PRUint32      NowInMilliSecs()
-        {PRUint64 now64 = LL_INIT(0,1000);
-         PRUint32 now32;
-         LL_DIV(now64,PR_Now(),now64);
-         LL_L2UI(now32, now64);
-         return now32;
-        }
-    void          SetStartTime() {mStartTime = NowInMilliSecs();}
-    PRUint32      SetEndTime()
-        {PRUint32 delta = NowInMilliSecs() - mStartTime;
-         if(delta < mQuickTime)
-            mQuickTime = delta;
-         if (delta > mLongTime)
-            mLongTime = delta;
-         mSum += delta;
-         return delta;}
-    PRUint32      GetQuickTime() {return mQuickTime;}
-    PRUint32      GetLongTime() {return mLongTime;}
-    
-    void          AddNotSelfTime(PRUint32 delta) {mNotSelfSum += delta;}
-    PRUint32      GetSelf() { return mSum - mNotSelfSum;}
-
-    ProfilerFunction(); // not implemented
-
-private:
-    char*           mName;
-    uintN           mBaseLineNumber;
-    uintN           mLineExtent;
-    size_t          mTotalSize;     // JSFunction, JSScript, bytecode, &c, size
-    ProfilerFile*   mFile;
-    PRUint32        mCallCount;
-    PRUint32        mCompileCount;
-    PRUint32        mQuickTime;     // quickest delta in msec
-    PRUint32        mLongTime;      // longest delta in msec
-    PRUint32        mStartTime;     // time on enter
-    PRUint32        mSum;
-    PRUint32        mNotSelfSum;
-};
-
-struct FunctionID
-{
-    uintN lineno;
-    uintN extent;
-
-    FunctionID(uintN aLineno, uintN aExtent) :
-        lineno(aLineno), extent(aExtent) { }
-
-    PRBool operator==(const FunctionID &aOther) const {
-        return aOther.lineno == this->lineno &&
-            aOther.extent == this->extent;
-    }
-};
-
-class FunctionKey : public PLDHashEntryHdr
-{
-public:
-    typedef const FunctionID &KeyType;
-    typedef const FunctionID *KeyTypePointer;
-
-    FunctionKey(KeyTypePointer aF) : mF(*aF) { }
-    FunctionKey(const FunctionKey &toCopy) : mF(toCopy.mF) { }
-    ~FunctionKey() { }
-
-    KeyType GetKey() const { return mF; }
-    PRBool KeyEquals(const KeyTypePointer aKey) const
-    {
-        return mF == *aKey;
-    }
-
-    static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
-    static PLDHashNumber HashKey(const KeyTypePointer aKey) {
-        return (aKey->lineno * 17) | (aKey->extent * 7);
-    }
-
-    enum { ALLOW_MEMMOVE = PR_TRUE };
-
-private:
-    const FunctionID mF;
-};
-
-class ProfilerFile
-{
-public:
-    ProfilerFile(const char* filename);
-    ~ProfilerFile();
-
-    
-    ProfilerFunction* FindOrAddFunction(const char* aName,
-                                        uintN aBaseLineNumber,
-                                        uintN aLineExtent,
-                                        size_t aTotalSize);
-
-    typedef nsClassHashtable<FunctionKey, ProfilerFunction> FunctionTableType;
-    typedef FunctionTableType::EnumReadFunction EnumeratorType;
-
-    void EnumerateFunctions(EnumeratorType aFunc,
-                            void *aClosure) const;
-
-    const char* GetName() const {return mName;}
-
-private:
-    char*             mName;
-    FunctionTableType mFunctionTable;
-};
-
-class nsXPCToolsProfiler : public nsIXPCToolsProfiler
-{
-public:
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIXPCTOOLSPROFILER
-
-  nsXPCToolsProfiler();
-  virtual ~nsXPCToolsProfiler();
-
-private:
-    JSBool InitializeRuntime();
-    JSBool VerifyRuntime();
-
-    /* Taking the unusual step of making all data public to simplify
-    *  the implementation of the "C" static debugger hooks.  
-    */
-
-public:
-    PRLock*         mLock;
-    JSRuntime*      mRuntime;
-    nsClassHashtable<nsCharPtrHashKey, ProfilerFile> mFileTable;
-    nsDataHashtable<nsVoidPtrHashKey, ProfilerFunction*> mScriptTable;
-};
-
-#endif /* xpctoolsprivate_h___ */
new file mode 100644
--- /dev/null
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -0,0 +1,540 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Corporation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Robert O'Callahan <robert@ocallahan.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "FrameLayerBuilder.h"
+
+#include "nsDisplayList.h"
+#include "nsPresContext.h"
+#include "nsLayoutUtils.h"
+
+using namespace mozilla::layers;
+
+namespace mozilla {
+
+namespace {
+
+/**
+ * This class iterates through a display list tree, descending only into
+ * nsDisplayClip items, and returns each display item encountered during
+ * such iteration. Along with each item we also return the clip rect
+ * accumulated for the item.
+ */
+class ClippedItemIterator {
+public:
+  ClippedItemIterator(const nsDisplayList* aList)
+  {
+    DescendIntoList(aList, nsnull, nsnull);
+    AdvanceToItem();
+  }
+  PRBool IsDone()
+  {
+    return mStack.IsEmpty();
+  }
+  void Next()
+  {
+    State* top = StackTop();
+    top->mItem = top->mItem->GetAbove();
+    AdvanceToItem();
+  }
+  // Returns null if there is no clipping affecting the item. The
+  // clip rect is in device pixels
+  const gfxRect* GetEffectiveClipRect()
+  {
+    State* top = StackTop();
+    return top->mHasClipRect ? &top->mEffectiveClipRect : nsnull;
+  }
+  nsDisplayItem* Item()
+  {
+    return StackTop()->mItem;
+  }
+
+private:
+  // We maintain a stack of state objects. Each State object represents
+  // where we're up to in the iteration of a list.
+  struct State {
+    // The current item we're at in the list
+    nsDisplayItem* mItem;
+    // The effective clip rect applying to all the items in this list
+    gfxRect mEffectiveClipRect;
+    PRPackedBool mHasClipRect;
+  };
+
+  State* StackTop()
+  {
+    return &mStack[mStack.Length() - 1];
+  }
+  void DescendIntoList(const nsDisplayList* aList,
+                       nsPresContext* aPresContext,
+                       const nsRect* aClipRect)
+  {
+    State* state = mStack.AppendElement();
+    if (!state)
+      return;
+    if (mStack.Length() >= 2) {
+      *state = mStack[mStack.Length() - 2];
+    } else {
+      state->mHasClipRect = PR_FALSE;
+    }
+    state->mItem = aList->GetBottom();
+    if (aClipRect) {
+      gfxRect r(aClipRect->x, aClipRect->y, aClipRect->width, aClipRect->height);
+      r.ScaleInverse(aPresContext->AppUnitsPerDevPixel());
+      if (state->mHasClipRect) {
+        state->mEffectiveClipRect = state->mEffectiveClipRect.Intersect(r);
+      } else {
+        state->mEffectiveClipRect = r;
+        state->mHasClipRect = PR_TRUE;
+      }
+    }
+  }
+  // Advances to an item that the iterator should return.
+  void AdvanceToItem()
+  {
+    while (!mStack.IsEmpty()) {
+      State* top = StackTop();
+      if (!top->mItem) {
+        mStack.SetLength(mStack.Length() - 1);
+        if (!mStack.IsEmpty()) {
+          top = StackTop();
+          top->mItem = top->mItem->GetAbove();
+        }
+        continue;
+      }
+      if (top->mItem->GetType() != nsDisplayItem::TYPE_CLIP)
+        return;
+      nsDisplayClip* clipItem = static_cast<nsDisplayClip*>(top->mItem);
+      nsRect clip = clipItem->GetClipRect();
+      DescendIntoList(clipItem->GetList(),
+                      clipItem->GetClippingFrame()->PresContext(),
+                      &clip);
+    }
+  }
+
+  nsAutoTArray<State,10> mStack;
+};
+
+/**
+ * This class represents a sublist of consecutive items in an nsDisplayList.
+ * The first item in the sublist is mStartItem and the last item
+ * is the item before mEndItem.
+ * 
+ * These sublists are themselves organized into a linked list of all
+ * the ItemGroups associated with a given layer, via mNextItemsForLayer.
+ * This list will have more than one element if the display items in a layer
+ * come from different nsDisplayLists, or if they come from the same
+ * nsDisplayList but they aren't consecutive in that list.
+ * 
+ * These objects are allocated from the nsDisplayListBuilder arena.
+ */
+struct ItemGroup {
+  // If null, then the item group is empty.
+  nsDisplayItem* mStartItem;
+  nsDisplayItem* mEndItem;
+  ItemGroup* mNextItemsForLayer;
+  // The clipping (if any) that needs to be applied to all these items.
+  gfxRect mClipRect;
+  PRPackedBool mHasClipRect;
+
+  ItemGroup() : mStartItem(nsnull), mEndItem(nsnull),
+    mNextItemsForLayer(nsnull), mHasClipRect(PR_FALSE) {}
+
+  void* operator new(size_t aSize,
+                     nsDisplayListBuilder* aBuilder) CPP_THROW_NEW {
+    return aBuilder->Allocate(aSize);
+  }
+};
+
+/**
+ * This class represents a layer and the display item(s) it
+ * will render. The items are stored in a linked list of ItemGroups.
+ */
+struct LayerItems {
+  nsRefPtr<Layer> mLayer;
+  // equal to mLayer, or null if mLayer is not a ThebesLayer
+  ThebesLayer* mThebesLayer;
+  ItemGroup* mItems;
+  // The bounds of the visible region for this layer, in device pixels
+  nsIntRect mVisibleRect;
+
+  LayerItems(ItemGroup* aItems) :
+    mThebesLayer(nsnull), mItems(aItems)
+  {
+  }
+
+  void* operator new(size_t aSize,
+                     nsDisplayListBuilder* aBuilder) CPP_THROW_NEW {
+    return aBuilder->Allocate(aSize);
+  }
+};
+
+/**
+ * Given a (possibly clipped) display item in aItem, try to append it to
+ * the items in aGroup. If aItem is the next item in the sublist in
+ * aGroup, and the clipping matches, we can just update aGroup in-place,
+ * otherwise we'll allocate a new ItemGroup, add it to the linked list,
+ * and put aItem in the new ItemGroup. We return the ItemGroup into which
+ * aItem was inserted.
+ */
+static ItemGroup*
+AddToItemGroup(nsDisplayListBuilder* aBuilder,
+               ItemGroup* aGroup, nsDisplayItem* aItem,
+               const gfxRect* aClipRect)
+{
+  NS_ASSERTION(!aGroup->mNextItemsForLayer,
+               "aGroup must be the last group in the chain");
+
+  if (!aGroup->mStartItem) {
+    aGroup->mStartItem = aItem;
+    aGroup->mEndItem = aItem->GetAbove();
+    aGroup->mHasClipRect = aClipRect != nsnull;
+    if (aClipRect) {
+      aGroup->mClipRect = *aClipRect;
+    }
+    return aGroup;
+  }
+
+  if (aGroup->mEndItem == aItem &&
+      (aGroup->mHasClipRect
+       ? (aClipRect && aGroup->mClipRect == *aClipRect)
+       : !aClipRect))  {
+    aGroup->mEndItem = aItem->GetAbove();
+    return aGroup;
+  }
+
+  ItemGroup* itemGroup = new (aBuilder) ItemGroup();
+  if (!itemGroup)
+    return aGroup;
+  aGroup->mNextItemsForLayer = itemGroup;
+  return AddToItemGroup(aBuilder, itemGroup, aItem, aClipRect);
+}
+
+/**
+ * Create an empty Thebes layer, with an empty ItemGroup associated with
+ * it, and append it to aLayers.
+ */
+static ItemGroup*
+CreateEmptyThebesLayer(nsDisplayListBuilder* aBuilder,
+                       LayerManager* aManager,
+                       nsTArray<LayerItems*>* aLayers)
+{
+  ItemGroup* itemGroup = new (aBuilder) ItemGroup();
+  if (!itemGroup)
+    return nsnull;
+  nsRefPtr<ThebesLayer> thebesLayer = aManager->CreateThebesLayer();
+  if (!thebesLayer)
+    return nsnull;
+  LayerItems* layerItems = new (aBuilder) LayerItems(itemGroup);
+  aLayers->AppendElement(layerItems);
+  thebesLayer->SetUserData(layerItems);
+  layerItems->mThebesLayer = thebesLayer;
+  layerItems->mLayer = thebesLayer.forget();
+  return itemGroup;
+}
+
+static PRBool
+IsAllUniform(nsDisplayListBuilder* aBuilder, ItemGroup* aGroup,
+             nscolor* aColor)
+{
+  nsRect visibleRect = aGroup->mStartItem->GetVisibleRect();
+  nscolor finalColor = NS_RGBA(0,0,0,0);
+  for (ItemGroup* group = aGroup; group;
+       group = group->mNextItemsForLayer) {
+    for (nsDisplayItem* item = group->mStartItem; item != group->mEndItem;
+         item = item->GetAbove()) {
+      nscolor color;
+      if (visibleRect != item->GetVisibleRect())
+        return PR_FALSE;
+      if (!item->IsUniform(aBuilder, &color))
+        return PR_FALSE;
+      finalColor = NS_ComposeColors(finalColor, color);
+    }
+  }
+  *aColor = finalColor;
+  return PR_TRUE;
+}
+
+/**
+ * This is the heart of layout's integration with layers. We
+ * use a ClippedItemIterator to iterate through descendant display
+ * items. Each item either has its own layer or is assigned to a
+ * ThebesLayer. We create ThebesLayers as necessary, although we try
+ * to put items in the bottom-most ThebesLayer because that is most
+ * likely to be able to render with an opaque background, which will often
+ * be required for subpixel text antialiasing to work.
+ */
+static void BuildLayers(nsDisplayListBuilder* aBuilder,
+                        const nsDisplayList& aList,
+                        LayerManager* aManager,
+                        nsTArray<LayerItems*>* aLayers)
+{
+  NS_ASSERTION(aLayers->IsEmpty(), "aLayers must be initially empty");
+
+  // Create "bottom" Thebes layer. We'll try to put as much content
+  // as possible in this layer because if the container is filled with
+  // opaque content, this bottommost layer can also be treated as opaque,
+  // which means content in this layer can have subpixel AA.
+  // firstThebesLayerItems always points to the last ItemGroup for the
+  // first Thebes layer.
+  ItemGroup* firstThebesLayerItems =
+    CreateEmptyThebesLayer(aBuilder, aManager, aLayers);
+  if (!firstThebesLayerItems)
+    return;
+  // lastThebesLayerItems always points to the last ItemGroup for the
+  // topmost layer, if it's a ThebesLayer. If the top layer is not a
+  // Thebes layer, this is null.
+  ItemGroup* lastThebesLayerItems = firstThebesLayerItems;
+  // This region contains the bounds of all the content that is above
+  // the first Thebes layer.
+  nsRegion areaAboveFirstThebesLayer;
+
+  for (ClippedItemIterator iter(&aList); !iter.IsDone(); iter.Next()) {
+    nsDisplayItem* item = iter.Item();
+    const gfxRect* clipRect = iter.GetEffectiveClipRect();
+    // Ask the item if it manages its own layer
+    nsRefPtr<Layer> layer = item->BuildLayer(aBuilder, aManager);
+    nsRect bounds = item->GetBounds(aBuilder);
+    // We set layerItems to point to the LayerItems object where the
+    // item ends up.
+    LayerItems* layerItems = nsnull;
+    if (layer) {
+      // item has a dedicated layer. Add it to the list, with an ItemGroup
+      // covering this item only.
+      ItemGroup* itemGroup = new (aBuilder) ItemGroup();
+      if (itemGroup) {
+        AddToItemGroup(aBuilder, itemGroup, item, clipRect);
+        layerItems = new (aBuilder) LayerItems(itemGroup);
+        aLayers->AppendElement(layerItems);
+        if (layerItems) {
+          if (itemGroup->mHasClipRect) {
+            gfxRect r = itemGroup->mClipRect;
+            r.Round();
+            nsIntRect intRect(r.X(), r.Y(), r.Width(), r.Height());
+            layer->IntersectClipRect(intRect);
+          }
+          layerItems->mLayer = layer.forget();
+        }
+      }
+      // This item is above the first Thebes layer.
+      areaAboveFirstThebesLayer.Or(areaAboveFirstThebesLayer, bounds);
+      lastThebesLayerItems = nsnull;
+    } else {
+      // No dedicated layer. Add it to a Thebes layer. First try to add
+      // it to the first Thebes layer, which we can do if there's no
+      // content between the first Thebes layer and our display item that
+      // overlaps our display item.
+      if (!areaAboveFirstThebesLayer.Intersects(bounds)) {
+        firstThebesLayerItems =
+          AddToItemGroup(aBuilder, firstThebesLayerItems, item, clipRect);
+        layerItems = aLayers->ElementAt(0);
+      } else if (lastThebesLayerItems) {
+        // Try to add to the last Thebes layer
+        lastThebesLayerItems =
+          AddToItemGroup(aBuilder, lastThebesLayerItems, item, clipRect);
+        // This item is above the first Thebes layer.
+        areaAboveFirstThebesLayer.Or(areaAboveFirstThebesLayer, bounds);
+        layerItems = aLayers->ElementAt(aLayers->Length() - 1);
+      } else {
+        // Create a new Thebes layer
+        ItemGroup* itemGroup =
+          CreateEmptyThebesLayer(aBuilder, aManager, aLayers);
+        if (itemGroup) {
+          lastThebesLayerItems =
+            AddToItemGroup(aBuilder, itemGroup, item, clipRect);
+          NS_ASSERTION(lastThebesLayerItems == itemGroup,
+                       "AddToItemGroup shouldn't create a new group if the "
+                       "initial group is empty");
+          // This item is above the first Thebes layer.
+          areaAboveFirstThebesLayer.Or(areaAboveFirstThebesLayer, bounds);
+          layerItems = aLayers->ElementAt(aLayers->Length() - 1);
+        }
+      }
+    }
+
+    if (layerItems) {
+      // Update the visible region of the layer to account for the new
+      // item
+      nscoord appUnitsPerDevPixel =
+        item->GetUnderlyingFrame()->PresContext()->AppUnitsPerDevPixel();
+      layerItems->mVisibleRect.UnionRect(layerItems->mVisibleRect,
+        item->GetVisibleRect().ToNearestPixels(appUnitsPerDevPixel));
+    }
+  }
+
+  if (!firstThebesLayerItems->mStartItem) {
+    // The first Thebes layer has nothing in it. Delete the layer.
+    // Ensure layer is released.
+    aLayers->ElementAt(0)->mLayer = nsnull;
+    aLayers->RemoveElementAt(0);
+  }
+
+  for (PRUint32 i = 0; i < aLayers->Length(); ++i) {
+    LayerItems* layerItems = aLayers->ElementAt(i);
+
+    nscolor color;
+    // Only convert layers with identity transform to ColorLayers, for now.
+    // This simplifies the code to set the clip region.
+    if (layerItems->mThebesLayer &&
+        IsAllUniform(aBuilder, layerItems->mItems, &color) &&
+        layerItems->mLayer->GetTransform().IsIdentity()) {
+      nsRefPtr<ColorLayer> layer = aManager->CreateColorLayer();
+      layer->SetClipRect(layerItems->mThebesLayer->GetClipRect());
+      // Clip to mVisibleRect to ensure only the pixels we want are filled.
+      layer->IntersectClipRect(layerItems->mVisibleRect);
+      layer->SetColor(gfxRGBA(color));
+      layerItems->mLayer = layer.forget();
+      layerItems->mThebesLayer = nsnull;
+    }
+
+    gfxMatrix transform;
+    nsIntRect visibleRect = layerItems->mVisibleRect;
+    if (layerItems->mLayer->GetTransform().Is2D(&transform)) {
+      // if 'transform' is not invertible, then nothing will be displayed
+      // for the layer, so it doesn't really matter what we do here
+      transform.Invert();
+      gfxRect layerVisible = transform.TransformBounds(
+          gfxRect(visibleRect.x, visibleRect.y, visibleRect.width, visibleRect.height));
+      layerVisible.RoundOut();
+      if (NS_FAILED(nsLayoutUtils::GfxRectToIntRect(layerVisible, &visibleRect))) {
+        NS_ERROR("Visible rect transformed out of bounds");
+      }
+    } else {
+      NS_ERROR("Only 2D transformations currently supported");
+    }
+    layerItems->mLayer->SetVisibleRegion(nsIntRegion(visibleRect));
+  }
+}
+
+} // anonymous namespace
+
+already_AddRefed<Layer>
+FrameLayerBuilder::MakeContainerLayerFor(nsDisplayListBuilder* aBuilder,
+                                         LayerManager* aManager,
+                                         nsDisplayItem* aContainer,
+                                         const nsDisplayList& aChildren)
+{
+  // If there's only one layer, then in principle we can try to flatten
+  // things by returning that layer here. But that adds complexity to
+  // retained layer management so we don't do it. Layer backends can
+  // flatten internally.
+  nsRefPtr<ContainerLayer> container = aManager->CreateContainerLayer();
+  if (!container)
+    return nsnull;
+
+  nsAutoTArray<LayerItems*,10> layerItems;
+  BuildLayers(aBuilder, aChildren, aManager, &layerItems);
+
+  Layer* lastChild = nsnull;
+  for (PRUint32 i = 0; i < layerItems.Length(); ++i) {
+    Layer* child = layerItems[i]->mLayer;
+    container->InsertAfter(child, lastChild);
+    lastChild = child;
+    // release the layer now because the ItemGroup destructor doesn't run;
+    // the container is still holding a reference to it
+    layerItems[i]->mLayer = nsnull;
+  }
+  container->SetIsOpaqueContent(aChildren.IsOpaque());
+  nsRefPtr<Layer> layer = container.forget();
+  return layer.forget();
+}
+
+/* static */ void
+FrameLayerBuilder::DrawThebesLayer(ThebesLayer* aLayer,
+                                   gfxContext* aContext,
+                                   const nsIntRegion& aRegionToDraw,
+                                   void* aCallbackData)
+{
+  LayerItems* layerItems = static_cast<LayerItems*>(aLayer->GetUserData());
+  nsDisplayListBuilder* builder =
+    static_cast<nsDisplayListBuilder*>(aCallbackData);
+
+  // For now, we'll ignore toDraw and just draw the entire visible
+  // area, because the "visible area" is already confined to just the
+  // area that needs to be repainted. Later, when we start reusing layers
+  // from paint to paint, we'll need to pay attention to toDraw and
+  // actually try to avoid drawing stuff that's not in it.
+
+  // Our list may contain content with different prescontexts at
+  // different zoom levels. 'rc' contains the nsIRenderingContext
+  // used for the previous display item, and lastPresContext is the
+  // prescontext for that item. We also cache the clip state for that
+  // item.
+  nsRefPtr<nsIRenderingContext> rc;
+  nsPresContext* lastPresContext = nsnull;
+  gfxRect currentClip;
+  PRBool setClipRect = PR_FALSE;
+  NS_ASSERTION(layerItems->mItems, "No empty layers allowed");
+  for (ItemGroup* group = layerItems->mItems; group;
+       group = group->mNextItemsForLayer) {
+    // If the new desired clip state is different from the current state,
+    // update the clip.
+    if (setClipRect != group->mHasClipRect ||
+        (group->mHasClipRect && group->mClipRect != currentClip)) {
+      if (setClipRect) {
+        aContext->Restore();
+      }
+      setClipRect = group->mHasClipRect;
+      if (setClipRect) {
+        aContext->Save();
+        aContext->NewPath();
+        aContext->Rectangle(group->mClipRect, PR_TRUE);
+        aContext->Clip();
+        currentClip = group->mClipRect;
+      }
+    }
+    NS_ASSERTION(group->mStartItem, "No empty groups allowed");
+    for (nsDisplayItem* item = group->mStartItem; item != group->mEndItem;
+         item = item->GetAbove()) {
+      nsPresContext* presContext = item->GetUnderlyingFrame()->PresContext();
+      if (presContext != lastPresContext) {
+        // Create a new rendering context with the right
+        // appunits-per-dev-pixel.
+        nsresult rv =
+          presContext->DeviceContext()->CreateRenderingContextInstance(*getter_AddRefs(rc));
+        if (NS_FAILED(rv))
+          break;
+        rc->Init(presContext->DeviceContext(), aContext);
+        lastPresContext = presContext;
+      }
+      item->Paint(builder, rc);
+    }
+  }
+  if (setClipRect) {
+    aContext->Restore();
+  }
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/layout/base/FrameLayerBuilder.h
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Corporation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Robert O'Callahan <robert@ocallahan.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef FRAMELAYERBUILDER_H_
+#define FRAMELAYERBUILDER_H_
+
+#include "Layers.h"
+
+class nsDisplayListBuilder;
+class nsDisplayList;
+class nsDisplayItem;
+
+namespace mozilla {
+
+class FrameLayerBuilder {
+public:
+  typedef mozilla::layers::Layer Layer;
+  typedef mozilla::layers::ThebesLayer ThebesLayer;
+  typedef mozilla::layers::LayerManager LayerManager;
+
+  /**
+   * Create a container layer for a display item that contains a child
+   * list, either reusing an existing one or creating a new one.
+   * aContainer may be null, in which case we construct a root layer.
+   */
+  already_AddRefed<Layer> MakeContainerLayerFor(nsDisplayListBuilder* aBuilder,
+                                                LayerManager* aManager,
+                                                nsDisplayItem* aContainer,
+                                                const nsDisplayList& aChildren);
+
+  /**
+   * This callback must be provided to EndTransaction. The callback data
+   * must be the nsDisplayListBuilder containing this FrameLayerBuilder.
+   */
+  static void DrawThebesLayer(ThebesLayer* aLayer,
+                              gfxContext* aContext,
+                              const nsIntRegion& aRegionToDraw,
+                              void* aCallbackData);
+};
+
+}
+
+#endif /* FRAMELAYERBUILDER_H_ */
--- a/layout/base/Makefile.in
+++ b/layout/base/Makefile.in
@@ -54,16 +54,17 @@ LIBXUL_LIBRARY	= 1
 
 
 
 XPIDLSRCS	= \
 		nsIStyleSheetService.idl	\
 		$(NULL)
 
 EXPORTS		= \
+		FrameLayerBuilder.h \
 		FramePropertyTable.h \
 		nsBidi.h \
 		nsBidiPresUtils.h \
 		nsCaret.h \
 		nsCSSFrameConstructor.h \
 		nsChangeHint.h \
 		nsCompatibility.h \
 		nsDisplayList.h \
@@ -83,16 +84,17 @@ EXPORTS		= \
 		nsPresContext.h \
 		nsPresState.h \
 		nsRefreshDriver.h \
 		nsStyleChangeList.h \
 		nsStyleConsts.h \
 		$(NULL)
 
 CPPSRCS		= \
+		FrameLayerBuilder.cpp \
 		FramePropertyTable.cpp \
 		nsCSSColorUtils.cpp \
 		nsCSSFrameConstructor.cpp \
 		nsCSSRendering.cpp \
 		nsCSSRenderingBorders.cpp \
 		nsCaret.cpp \
 		nsChildIterator.cpp \
 		nsCounterManager.cpp \
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -57,16 +57,17 @@
 #include "nsSVGIntegrationUtils.h"
 #endif
 #include "nsLayoutUtils.h"
 
 #include "imgIContainer.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "BasicLayers.h"
 
+using namespace mozilla;
 using namespace mozilla::layers;
 
 nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
     PRBool aIsForEvents, PRBool aBuildCaret)
     : mReferenceFrame(aReferenceFrame),
       mMovingFrame(nsnull),
       mSaveVisibleRegionOfMovingContent(nsnull),
       mIgnoreScrollFrame(nsnull),
@@ -400,380 +401,16 @@ nsDisplayList::ComputeVisibility(nsDispl
     movingContentVisibleRegionAfterMove);
 
   mIsOpaque = aVisibleRegion->IsEmpty();
 #ifdef DEBUG
   mDidComputeVisibility = PR_TRUE;
 #endif
 }
 
-namespace {
-/**
- * This class iterates through a display list tree, descending only into
- * nsDisplayClip items, and returns each display item encountered during
- * such iteration. Along with each item we also return the clip rect
- * accumulated for the item.
- */
-class ClippedItemIterator {
-public:
-  ClippedItemIterator(const nsDisplayList* aList)
-  {
-    DescendIntoList(aList, nsnull, nsnull);
-    AdvanceToItem();
-  }
-  PRBool IsDone()
-  {
-    return mStack.IsEmpty();
-  }
-  void Next()
-  {
-    State* top = StackTop();
-    top->mItem = top->mItem->GetAbove();
-    AdvanceToItem();
-  }
-  // Returns null if there is no clipping affecting the item. The
-  // clip rect is in device pixels
-  const gfxRect* GetEffectiveClipRect()
-  {
-    State* top = StackTop();
-    return top->mHasClipRect ? &top->mEffectiveClipRect : nsnull;
-  }
-  nsDisplayItem* Item()
-  {
-    return StackTop()->mItem;
-  }
-
-private:
-  // We maintain a stack of state objects. Each State object represents
-  // where we're up to in the iteration of a list.
-  struct State {
-    // The current item we're at in the list
-    nsDisplayItem* mItem;
-    // The effective clip rect applying to all the items in this list
-    gfxRect mEffectiveClipRect;
-    PRPackedBool mHasClipRect;
-  };
-
-  State* StackTop()
-  {
-    return &mStack[mStack.Length() - 1];
-  }
-  void DescendIntoList(const nsDisplayList* aList,
-                       nsPresContext* aPresContext,
-                       const nsRect* aClipRect)
-  {
-    State* state = mStack.AppendElement();
-    if (!state)
-      return;
-    if (mStack.Length() >= 2) {
-      *state = mStack[mStack.Length() - 2];
-    } else {
-      state->mHasClipRect = PR_FALSE;
-    }
-    state->mItem = aList->GetBottom();
-    if (aClipRect) {
-      gfxRect r(aClipRect->x, aClipRect->y, aClipRect->width, aClipRect->height);
-      r.ScaleInverse(aPresContext->AppUnitsPerDevPixel());
-      if (state->mHasClipRect) {
-        state->mEffectiveClipRect = state->mEffectiveClipRect.Intersect(r);
-      } else {
-        state->mEffectiveClipRect = r;
-        state->mHasClipRect = PR_TRUE;
-      }
-    }
-  }
-  // Advances to an item that the iterator should return.
-  void AdvanceToItem()
-  {
-    while (!mStack.IsEmpty()) {
-      State* top = StackTop();
-      if (!top->mItem) {
-        mStack.SetLength(mStack.Length() - 1);
-        if (!mStack.IsEmpty()) {
-          top = StackTop();
-          top->mItem = top->mItem->GetAbove();
-        }
-        continue;
-      }
-      if (top->mItem->GetType() != nsDisplayItem::TYPE_CLIP)
-        return;
-      nsDisplayClip* clipItem = static_cast<nsDisplayClip*>(top->mItem);
-      nsRect clip = clipItem->GetClipRect();
-      DescendIntoList(clipItem->GetList(),
-                      clipItem->GetClippingFrame()->PresContext(),
-                      &clip);
-    }
-  }
-
-  nsAutoTArray<State,10> mStack;
-};
-}
-
-/**
- * Given a (possibly clipped) display item in aItem, try to append it to
- * the items in aGroup. If aItem is the next item in the sublist in
- * aGroup, and the clipping matches, we can just update aGroup in-place,
- * otherwise we'll allocate a new ItemGroup, add it to the linked list,
- * and put aItem in the new ItemGroup. We return the ItemGroup into which
- * aItem was inserted.
- */
-static nsDisplayList::ItemGroup*
-AddToItemGroup(nsDisplayListBuilder* aBuilder,
-               nsDisplayList::ItemGroup* aGroup, nsDisplayItem* aItem,
-               const gfxRect* aClipRect) {
-  NS_ASSERTION(!aGroup->mNextItemsForLayer,
-               "aGroup must be the last group in the chain");
-
-  if (!aGroup->mStartItem) {
-    aGroup->mStartItem = aItem;
-    aGroup->mEndItem = aItem->GetAbove();
-    aGroup->mHasClipRect = aClipRect != nsnull;
-    if (aClipRect) {
-      aGroup->mClipRect = *aClipRect;
-    }
-    return aGroup;
-  }
-
-  if (aGroup->mEndItem == aItem &&
-      (aGroup->mHasClipRect
-       ? (aClipRect && aGroup->mClipRect == *aClipRect)
-       : !aClipRect))  {
-    aGroup->mEndItem = aItem->GetAbove();
-    return aGroup;
-  }
-
-  nsDisplayList::ItemGroup* itemGroup =
-    new (aBuilder) nsDisplayList::ItemGroup();
-  if (!itemGroup)
-    return aGroup;
-  aGroup->mNextItemsForLayer = itemGroup;
-  return AddToItemGroup(aBuilder, itemGroup, aItem, aClipRect);
-}
-
-/**
- * Create an empty Thebes layer, with an empty ItemGroup associated with
- * it, and append it to aLayers.
- */
-static nsDisplayList::ItemGroup*
-CreateEmptyThebesLayer(nsDisplayListBuilder* aBuilder,
-                       LayerManager* aManager,
-                       nsTArray<nsDisplayList::LayerItems>* aLayers) {
-  nsDisplayList::ItemGroup* itemGroup =
-    new (aBuilder) nsDisplayList::ItemGroup();
-  if (!itemGroup)
-    return nsnull;
-  nsRefPtr<ThebesLayer> thebesLayer =
-    aManager->CreateThebesLayer();
-  if (!thebesLayer)
-    return nsnull;
-  nsDisplayList::LayerItems* layerItems =
-    aLayers->AppendElement(nsDisplayList::LayerItems(itemGroup));
-  layerItems->mThebesLayer = thebesLayer;
-  layerItems->mLayer = thebesLayer.forget();
-  return itemGroup;
-}
-
-static PRBool
-IsAllUniform(nsDisplayListBuilder* aBuilder, nsDisplayList::ItemGroup* aGroup,
-             nscolor* aColor)
-{
-  nsRect visibleRect = aGroup->mStartItem->GetVisibleRect();
-  nscolor finalColor = NS_RGBA(0,0,0,0);
-  for (nsDisplayList::ItemGroup* group = aGroup; group;
-       group = group->mNextItemsForLayer) {
-    for (nsDisplayItem* item = group->mStartItem; item != group->mEndItem;
-         item = item->GetAbove()) {
-      nscolor color;
-      if (visibleRect != item->GetVisibleRect())
-        return PR_FALSE;
-      if (!item->IsUniform(aBuilder, &color))
-        return PR_FALSE;
-      finalColor = NS_ComposeColors(finalColor, color);
-    }
-  }
-  *aColor = finalColor;
-  return PR_TRUE;
-}
-
-/**
- * This is the heart of layout's integration with layers. We
- * use a ClippedItemIterator to iterate through descendant display
- * items. Each item either has its own layer or is assigned to a
- * ThebesLayer. We create ThebesLayers as necessary, although we try
- * to put items in the bottom-most ThebesLayer because that is most
- * likely to be able to render with an opaque background, which will often
- * be required for subpixel text antialiasing to work.
- */
-void nsDisplayList::BuildLayers(nsDisplayListBuilder* aBuilder,
-                                LayerManager* aManager,
-                                nsTArray<LayerItems>* aLayers) const {
-  NS_ASSERTION(aLayers->IsEmpty(), "aLayers must be initially empty");
-
-  // Create "bottom" Thebes layer. We'll try to put as much content
-  // as possible in this layer because if the container is filled with
-  // opaque content, this bottommost layer can also be treated as opaque,
-  // which means content in this layer can have subpixel AA.
-  // firstThebesLayerItems always points to the last ItemGroup for the
-  // first Thebes layer.
-  ItemGroup* firstThebesLayerItems =
-    CreateEmptyThebesLayer(aBuilder, aManager, aLayers);
-  if (!firstThebesLayerItems)
-    return;
-  // lastThebesLayerItems always points to the last ItemGroup for the
-  // topmost layer, if it's a ThebesLayer. If the top layer is not a
-  // Thebes layer, this is null.
-  ItemGroup* lastThebesLayerItems = firstThebesLayerItems;
-  // This region contains the bounds of all the content that is above
-  // the first Thebes layer.
-  nsRegion areaAboveFirstThebesLayer;
-
-  for (ClippedItemIterator iter(this); !iter.IsDone(); iter.Next()) {
-    nsDisplayItem* item = iter.Item();
-    const gfxRect* clipRect = iter.GetEffectiveClipRect();
-    // Ask the item if it manages its own layer
-    nsRefPtr<Layer> layer = item->BuildLayer(aBuilder, aManager);
-    nsRect bounds = item->GetBounds(aBuilder);
-    // We set layerItems to point to the LayerItems object where the
-    // item ends up.
-    LayerItems* layerItems = nsnull;
-    if (layer) {
-      // item has a dedicated layer. Add it to the list, with an ItemGroup
-      // covering this item only.
-      ItemGroup* itemGroup = new (aBuilder) ItemGroup();
-      if (itemGroup) {
-        AddToItemGroup(aBuilder, itemGroup, item, clipRect);
-        layerItems = aLayers->AppendElement(LayerItems(itemGroup));
-        if (layerItems) {
-          if (itemGroup->mHasClipRect) {
-            gfxRect r = itemGroup->mClipRect;
-            r.Round();
-            nsIntRect intRect(r.X(), r.Y(), r.Width(), r.Height());
-            layer->IntersectClipRect(intRect);
-          }
-          layerItems->mLayer = layer.forget();
-        }
-      }