Merge inbound to m-c.
authorRyan VanderMeulen <ryanvm@gmail.com>
Fri, 11 Oct 2013 15:39:14 -0400
changeset 150496 342e9d40235aea91cb28a4e3a10e61ffe7b48bc0
parent 150453 500765bd8dd9b772701c86c34e62948ec7f0eab5 (current diff)
parent 150495 4a2c4921ff7cabb2ca41bdf30b0f58b0a9e16c67 (diff)
child 150497 1144854a01d663bef5cbd0dc86775cdb2f18f41a
push id3001
push userryanvm@gmail.com
push dateFri, 11 Oct 2013 21:03:10 +0000
treeherderfx-team@9ab188de8245 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone27.0a1
Merge inbound to m-c.
config/buildlist.py
config/tests/unit-buildlist.py
config/utils.py
netwerk/streamconv/public/nsIAppleFileDecoder.idl
netwerk/streamconv/src/nsAppleFileDecoder.cpp
netwerk/streamconv/src/nsAppleFileDecoder.h
--- a/browser/extensions/Makefile.in
+++ b/browser/extensions/Makefile.in
@@ -24,25 +24,22 @@ exclude_files = \
 
 libs:: $(FINAL_TARGET)/chrome/pdfjs.manifest $(FINAL_TARGET)/chrome/shumway.manifest
 	$(PYTHON) $(topsrcdir)/config/nsinstall.py \
 	  $(srcdir)/pdfjs \
           $(foreach exclude,$(exclude_files), -X $(srcdir)/pdfjs/$(exclude)) \
 	  $(srcdir)/shumway \
           $(foreach exclude,$(exclude_files), -X $(srcdir)/shumway/$(exclude)) \
           $(FINAL_TARGET)/chrome
-	$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py \
-	  $(FINAL_TARGET)/chrome.manifest "manifest chrome/pdfjs.manifest"
-	$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py \
-	  $(FINAL_TARGET)/chrome.manifest "manifest chrome/shumway.manifest"
+	$(call py_action,buildlist,$(FINAL_TARGET)/chrome.manifest "manifest chrome/pdfjs.manifest")
+	$(call py_action,buildlist,$(FINAL_TARGET)/chrome.manifest "manifest chrome/shumway.manifest")
 
 ifdef MOZ_METRO
 $(DIST)/bin/metro/chrome/pdfjs.manifest: $(GLOBAL_DEPS)
 	printf "manifest pdfjs/chrome.manifest" > $@
 
 libs:: $(DIST)/bin/metro/chrome/pdfjs.manifest
 	$(PYTHON) $(topsrcdir)/config/nsinstall.py \
 	  $(srcdir)/pdfjs \
           $(foreach exclude,$(exclude_files), -X $(srcdir)/pdfjs/$(exclude)) \
           $(DIST)/bin/metro/chrome
-	$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py \
-	  $(DIST)/bin/metro/chrome.manifest "manifest chrome/pdfjs.manifest"
+	$(call py_action,buildlist,$(DIST)/bin/metro/chrome.manifest "manifest chrome/pdfjs.manifest")
 endif
--- a/browser/metro/base/content/helperui/AlertsHelper.js
+++ b/browser/metro/base/content/helperui/AlertsHelper.js
@@ -1,25 +1,41 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 var AlertsHelper = {
   _listener: null,
-  _cookie: "",
 
   showAlertNotification: function ah_show(aImageURL, aTitle, aText, aTextClickable, aCookie, aListener) {
-    Services.obs.addObserver(this, "metro_native_toast_clicked", false);
+    if (aListener) {
+      Services.obs.addObserver(this, "metro_native_toast_clicked", false);
+      Services.obs.addObserver(this, "metro_native_toast_dismissed", false);
+      Services.obs.addObserver(this, "metro_native_toast_shown", false);
+    }
     this._listener = aListener;
-    this._cookie = aCookie;
+
+    Services.metro.showNativeToast(aTitle, aText, aImageURL, aCookie);
+  },
 
-    Services.metro.showNativeToast(aTitle, aText, aImageURL);
+  closeAlert: function ah_close() {
+    if (this._listener) {
+      Services.obs.removeObserver(this, "metro_native_toast_shown");
+      Services.obs.removeObserver(this, "metro_native_toast_clicked");
+      Services.obs.removeObserver(this, "metro_native_toast_dismissed");
+      this._listener = null;
+    }
   },
 
   observe: function(aSubject, aTopic, aData) {
     switch (aTopic) {
       case "metro_native_toast_clicked":
-        Services.obs.removeObserver(this, "metro_native_toast_clicked");
-        this._listener.observe(null, "alertclickcallback", this._cookie);
+        this._listener.observe(null, "alertclickcallback", aData);
+        break;
+      case "metro_native_toast_shown":
+        this._listener.observe(null, "alertshow", aData);
+        break;
+      case "metro_native_toast_dismissed":
+        this._listener.observe(null, "alertfinished", aData);
         break;
     }
   }
 };
--- a/browser/metro/components/AlertsService.js
+++ b/browser/metro/components/AlertsService.js
@@ -13,31 +13,37 @@ Cu.import("resource://gre/modules/Servic
 // -----------------------------------------------------------------------
 
 function AlertsService() { }
 
 AlertsService.prototype = {
   classID: Components.ID("{fe33c107-82a4-41d6-8c64-5353267e04c9}"),
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIAlertsService]),
 
-  showAlertNotification: function(aImageUrl, aTitle, aText, aTextClickable, aCookie, aAlertListener, aName) {
+  showAlertNotification: function(aImageUrl, aTitle, aText, aTextClickable,
+                                  aCookie, aAlertListener, aName, aDir, aLang) {
     let browser = Services.wm.getMostRecentWindow("navigator:browser");
     try {
       browser.AlertsHelper.showAlertNotification(aImageUrl, aTitle, aText, aTextClickable, aCookie, aAlertListener);
     } catch (ex) {
       let chromeWin = this._getChromeWindow(browser).wrappedJSObject;
       let notificationBox = chromeWin.Browser.getNotificationBox();
       notificationBox.appendNotification(aTitle,
                                          aText,
                                          aImageUrl,
                                          notificationBox.PRIORITY_WARNING_MEDIUM,
                                          null);
     }
   },
 
+  closeAlert: function(aName) {
+    let browser = Services.wm.getMostRecentWindow("navigator:browser");
+    browser.AlertsHelper.closeAlert();
+  },
+
   _getChromeWindow: function (aWindow) {
       let chromeWin = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
                             .getInterface(Ci.nsIWebNavigation)
                             .QueryInterface(Ci.nsIDocShellTreeItem)
                             .rootTreeItem
                             .QueryInterface(Ci.nsIInterfaceRequestor)
                             .getInterface(Ci.nsIDOMWindow)
                             .QueryInterface(Ci.nsIDOMChromeWindow);
--- a/build/unix/elfhack/inject.c
+++ b/build/unix/elfhack/inject.c
@@ -4,22 +4,22 @@
 
 #include <stdint.h>
 #include <elf.h>
 
 /* The Android NDK headers define those */
 #undef Elf_Ehdr
 #undef Elf_Addr
 
-#if BITS == 32
+#if defined(__LP64__)
+#define Elf_Ehdr Elf64_Ehdr
+#define Elf_Addr Elf64_Addr
+#else
 #define Elf_Ehdr Elf32_Ehdr
 #define Elf_Addr Elf32_Addr
-#else
-#define Elf_Ehdr Elf64_Ehdr
-#define Elf_Addr Elf64_Addr
 #endif
 
 extern __attribute__((visibility("hidden"))) void original_init(int argc, char **argv, char **env);
 
 extern __attribute__((visibility("hidden"))) Elf32_Rel relhack[];
 extern __attribute__((visibility("hidden"))) Elf_Ehdr elf_header;
 
 int init(int argc, char **argv, char **env)
--- a/build/unix/elfhack/inject/Makefile.in
+++ b/build/unix/elfhack/inject/Makefile.in
@@ -25,11 +25,10 @@ include $(topsrcdir)/config/rules.mk
 
 export:: $(CSRCS:.c=.$(OBJ_SUFFIX))
 
 $(CSRCS): %.c: ../inject.c
 	cp $< $@
 
 GARBAGE += $(CSRCS)
 
-DEFINES += -DBITS=$(if $(HAVE_64BIT_OS),64,32)
 CFLAGS := -O2 -fno-stack-protector $(filter -m% -I%,$(CFLAGS))
 $(CPU)-noinit.$(OBJ_SUFFIX): DEFINES += -DNOINIT
--- a/config/JarMaker.py
+++ b/config/JarMaker.py
@@ -9,24 +9,26 @@ See the documentation for jar.mn on MDC 
 '''
 import sys
 import os
 import os.path
 import errno
 import re
 import logging
 from time import localtime
-from optparse import OptionParser
 from MozZipFile import ZipFile
 from cStringIO import StringIO
-from datetime import datetime
 
-from utils import pushback_iter, lockFile
+from mozbuild.util import (
+    lock_file,
+    PushbackIter,
+)
+
 from Preprocessor import Preprocessor
-from buildlist import addEntriesToListFile
+from mozbuild.action.buildlist import addEntriesToListFile
 if sys.platform == "win32":
   from ctypes import windll, WinError
   CreateHardLink = windll.kernel32.CreateHardLinkA
 
 __all__ = ['JarMaker']
 
 class ZipEntry:
   '''Helper class for jar output.
@@ -169,17 +171,17 @@ class JarMaker(object):
       chromeDir = os.path.basename(os.path.dirname(os.path.normpath(chromeManifest)))
       logging.info("adding '%s' entry to root chrome manifest appid=%s" % (chromeDir, self.rootManifestAppId))
       addEntriesToListFile(rootChromeManifest, ['manifest %s/chrome.manifest application=%s' % (chromeDir, self.rootManifestAppId)])
 
   def updateManifest(self, manifestPath, chromebasepath, register):
     '''updateManifest replaces the % in the chrome registration entries
     with the given chrome base path, and updates the given manifest file.
     '''
-    lock = lockFile(manifestPath + '.lck')
+    lock = lock_file(manifestPath + '.lck')
     try:
       myregister = dict.fromkeys(map(lambda s: s.replace('%', chromebasepath),
                                      register.iterkeys()))
       manifestExists = os.path.isfile(manifestPath)
       mode = (manifestExists and 'r+b') or 'wb'
       mf = open(manifestPath, mode)
       if manifestExists:
         # import previous content into hash, ignoring empty ones and comments
@@ -210,17 +212,17 @@ class JarMaker(object):
     elif self.relativesrcdir:
       self.localedirs = self.generateLocaleDirs(self.relativesrcdir)
     if isinstance(infile, basestring):
       logging.info("processing " + infile)
       self.sourcedirs.append(_normpath(os.path.dirname(infile)))
     pp = self.pp.clone()
     pp.out = StringIO()
     pp.do_include(infile)
-    lines = pushback_iter(pp.out.getvalue().splitlines())
+    lines = PushbackIter(pp.out.getvalue().splitlines())
     try:
       while True:
         l = lines.next()
         m = self.jarline.match(l)
         if not m:
           raise RuntimeError(l)
         if m.group('jarfile') is None:
           # comment
@@ -247,18 +249,18 @@ class JarMaker(object):
       # add en-US if we merge, or if it's not l10n
       locdirs.append(os.path.join(self.topsourcedir, relativesrcdir, 'en-US'))
     return locdirs
 
   def processJarSection(self, jarfile, lines, jardir):
     '''Internal method called by makeJar to actually process a section
     of a jar.mn file.
 
-    jarfile is the basename of the jarfile or the directory name for 
-    flat output, lines is a pushback_iterator of the lines of jar.mn,
+    jarfile is the basename of the jarfile or the directory name for
+    flat output, lines is a PushbackIter of the lines of jar.mn,
     the remaining options are carried over from makeJar.
     '''
 
     # chromebasepath is used for chrome registration manifests
     # {0} is getting replaced with chrome/ for chrome.manifest, and with
     # an empty string for jarfile.manifest
     chromebasepath = '{0}' + os.path.basename(jarfile)
     if self.outputFormat == 'jar':
--- a/config/MozZipFile.py
+++ b/config/MozZipFile.py
@@ -1,30 +1,30 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-import zipfile
+import os
 import time
-import binascii, struct
-import zlib
-import os
-from utils import lockFile
+import zipfile
+
+from mozbuild.util import lock_file
+
 
 class ZipFile(zipfile.ZipFile):
   """ Class with methods to open, read, write, close, list zip files.
 
   Subclassing zipfile.ZipFile to allow for overwriting of existing
   entries, though only for writestr, not for write.
   """
   def __init__(self, file, mode="r", compression=zipfile.ZIP_STORED,
                lock = False):
     if lock:
       assert isinstance(file, basestring)
-      self.lockfile = lockFile(file + '.lck')
+      self.lockfile = lock_file(file + '.lck')
     else:
       self.lockfile = None
 
     if mode == 'a' and lock:
       # appending to a file which doesn't exist fails, but we can't check
       # existence util we hold the lock
       if (not os.path.isfile(file)) or os.path.getsize(file) == 0:
         mode = 'w'
--- a/config/makefiles/target_libs.mk
+++ b/config/makefiles/target_libs.mk
@@ -20,18 +20,18 @@ endif # EXPORT_LIBRARY
 
 binaries libs:: $(SUBMAKEFILES) $(TARGETS)
 ifndef NO_DIST_INSTALL
 ifdef SHARED_LIBRARY
 ifdef IS_COMPONENT
 	$(INSTALL) $(IFLAGS2) $(SHARED_LIBRARY) $(FINAL_TARGET)/components
 	$(ELF_DYNSTR_GC) $(FINAL_TARGET)/components/$(SHARED_LIBRARY)
 ifndef NO_COMPONENTS_MANIFEST
-	@$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/chrome.manifest "manifest components/components.manifest"
-	@$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/components/components.manifest "binary-component $(SHARED_LIBRARY)"
+	$(call py_action,buildlist,$(FINAL_TARGET)/chrome.manifest "manifest components/components.manifest")
+	$(call py_action,buildlist,$(FINAL_TARGET)/components/components.manifest "binary-component $(SHARED_LIBRARY)")
 endif
 endif # IS_COMPONENT
 endif # SHARED_LIBRARY
 endif # !NO_DIST_INSTALL
 
 ifndef NO_DIST_INSTALL
 
 ifneq (,$(strip $(PROGRAM)$(SIMPLE_PROGRAMS)))
--- a/config/makefiles/xpidl/Makefile.in
+++ b/config/makefiles/xpidl/Makefile.in
@@ -52,15 +52,17 @@ idlprocess := $(PYTHON_PATH) $(PLY_INCLU
 
 xpidl_modules := @xpidl_modules@
 
 @xpidl_rules@
 
 linked_xpt_files := $(addprefix $(idl_xpt_dir)/,$(addsuffix .xpt,$(xpidl_modules)))
 depends_files := $(foreach root,$(xpidl_modules),$(idl_deps_dir)/$(root).pp)
 
+GARBAGE += $(linked_xpt_files) $(depends_files)
+
 xpidl:: $(linked_xpt_files)
 
 $(linked_xpt_files): $(process_py) $(call mkdir_deps,$(idl_deps_dir) $(dist_include_dir) $(idl_xpt_dir))
 
 $(call include_deps,$(depends_files))
 
 .PHONY: xpidl
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -1309,18 +1309,18 @@ ifdef XPT_NAME #{
 
 ifndef NO_DIST_INSTALL
 _XPT_NAME_FILES := $(DEPTH)/config/makefiles/xpidl/xpt/$(XPT_NAME)
 _XPT_NAME_DEST := $(FINAL_TARGET)/components
 INSTALL_TARGETS += _XPT_NAME
 
 ifndef NO_INTERFACES_MANIFEST
 libs:: $(call mkdir_deps,$(FINAL_TARGET)/components)
-	@$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/components/interfaces.manifest "interfaces $(XPT_NAME)"
-	@$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/chrome.manifest "manifest components/interfaces.manifest"
+	$(call py_action,buildlist,$(FINAL_TARGET)/components/interfaces.manifest "interfaces $(XPT_NAME)")
+	$(call py_action,buildlist,$(FINAL_TARGET)/chrome.manifest "manifest components/interfaces.manifest")
 endif
 endif
 
 endif #} XPT_NAME
 
 ################################################################################
 # Copy each element of EXTRA_COMPONENTS to $(FINAL_TARGET)/components
 ifneq (,$(filter %.js,$(EXTRA_COMPONENTS) $(EXTRA_PP_COMPONENTS)))
@@ -1346,17 +1346,17 @@ ifndef NO_DIST_INSTALL
 EXTRA_PP_COMPONENTS_PATH := $(FINAL_TARGET)/components
 PP_TARGETS += EXTRA_PP_COMPONENTS
 endif
 endif
 
 EXTRA_MANIFESTS = $(filter %.manifest,$(EXTRA_COMPONENTS) $(EXTRA_PP_COMPONENTS))
 ifneq (,$(EXTRA_MANIFESTS))
 libs:: $(call mkdir_deps,$(FINAL_TARGET))
-	$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/chrome.manifest $(patsubst %,"manifest components/%",$(notdir $(EXTRA_MANIFESTS)))
+	$(call py_action,buildlist,$(FINAL_TARGET)/chrome.manifest $(patsubst %,"manifest components/%",$(notdir $(EXTRA_MANIFESTS))))
 endif
 
 ################################################################################
 # Copy each element of EXTRA_JS_MODULES to
 # $(FINAL_TARGET)/$(JS_MODULES_PATH). JS_MODULES_PATH defaults to "modules"
 # if it is undefined.
 JS_MODULES_PATH ?= modules
 FINAL_JS_MODULES_PATH := $(FINAL_TARGET)/$(JS_MODULES_PATH)
deleted file mode 100644
--- a/config/utils.py
+++ /dev/null
@@ -1,119 +0,0 @@
-# >>sys.stderr,  This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-'''Utility methods to be used by python build infrastructure.
-'''
-
-import os
-import errno
-import sys
-import time
-import stat
-
-class LockFile(object):
-  '''LockFile is used by the lockFile method to hold the lock.
-
-  This object should not be used directly, but only through
-  the lockFile method below.
-  '''
-  def __init__(self, lockfile):
-    self.lockfile = lockfile
-  def __del__(self):
-    while True:
-      try:
-        os.remove(self.lockfile)
-        break
-      except OSError as e:
-        if e.errno == errno.EACCES:
-          # another process probably has the file open, we'll retry.
-          # just a short sleep since we want to drop the lock ASAP
-          # (but we need to let some other process close the file first)
-          time.sleep(0.1)
-        else:
-          # re-raise unknown errors
-          raise
-
-def lockFile(lockfile, max_wait = 600):
-  '''Create and hold a lockfile of the given name, with the given timeout.
-
-  To release the lock, delete the returned object.
-  '''
-  while True:
-    try:
-      fd = os.open(lockfile, os.O_EXCL | os.O_RDWR | os.O_CREAT)
-      # we created the lockfile, so we're the owner
-      break
-    except OSError as e:
-      if (e.errno == errno.EEXIST or 
-          (sys.platform == "win32" and e.errno == errno.EACCES)):
-        pass
-      else:
-        # should not occur
-        raise
-  
-    try:
-      # the lock file exists, try to stat it to get its age
-      # and read its contents to report the owner PID
-      f = open(lockfile, "r")
-      s = os.stat(lockfile)
-    except EnvironmentError as e:
-      if e.errno == errno.ENOENT or e.errno == errno.EACCES:
-        # we didn't create the lockfile, so it did exist, but it's
-        # gone now. Just try again
-        continue
-      sys.exit("{0} exists but stat() failed: {1}"
-               .format(lockfile, e.strerror))
-  
-    # we didn't create the lockfile and it's still there, check
-    # its age
-    now = int(time.time())
-    if now - s[stat.ST_MTIME] > max_wait:
-      pid = f.readline().rstrip()
-      sys.exit("{0} has been locked for more than "
-               "{1} seconds (PID {2})".format(lockfile, max_wait, pid))
-  
-    # it's not been locked too long, wait a while and retry
-    f.close()
-    time.sleep(1)
-  
-  # if we get here. we have the lockfile. Convert the os.open file
-  # descriptor into a Python file object and record our PID in it
-  
-  f = os.fdopen(fd, "w")
-  f.write("{0}\n".format(os.getpid()))
-  f.close()
-  return LockFile(lockfile)
-
-class pushback_iter(object):
-  '''Utility iterator that can deal with pushed back elements.
-
-  This behaves like a regular iterable, just that you can call
-    iter.pushback(item)
-  to get the given item as next item in the iteration.
-  '''
-  def __init__(self, iterable):
-    self.it = iter(iterable)
-    self.pushed_back = []
-
-  def __iter__(self):
-    return self
-
-  def __nonzero__(self):
-    if self.pushed_back:
-      return True
-
-    try:
-      self.pushed_back.insert(0, self.it.next())
-    except StopIteration:
-      return False
-    else:
-      return True
-
-  def next(self):
-    if self.pushed_back:
-      return self.pushed_back.pop()
-    return self.it.next()
-
-  def pushback(self, item):
-    self.pushed_back.append(item)
--- a/configure.in
+++ b/configure.in
@@ -2493,93 +2493,18 @@ AC_CACHE_VAL(ac_cv_siginfo_t,
                  [ac_cv_siginfo_t=false])])
 if test "$ac_cv_siginfo_t" = true ; then
   AC_DEFINE(HAVE_SIGINFO_T)
   AC_MSG_RESULT(yes)
 else
   AC_MSG_RESULT(no)
 fi
 
-dnl Check for int64, uint, and uint_t.
-dnl ========================================================
-AC_MSG_CHECKING(for int64)
-AC_CACHE_VAL(ac_cv_int64,
- [AC_TRY_COMPILE([#include <stdio.h>
-                  #include <sys/types.h>],
-                 [int64 foo = 0;],
-                 [ac_cv_int64=true],
-                 [ac_cv_int64=false])])
-if test "$ac_cv_int64" = true ; then
-  AC_DEFINE(HAVE_INT64)
-  AC_MSG_RESULT(yes)
-else
-  AC_MSG_RESULT(no)
-fi
-AC_MSG_CHECKING(for uint)
-AC_CACHE_VAL(ac_cv_uint,
- [AC_TRY_COMPILE([#include <stdio.h>
-                  #include <sys/types.h>],
-                 [uint foo = 0;],
-                 [ac_cv_uint=true],
-                 [ac_cv_uint=false])])
-if test "$ac_cv_uint" = true ; then
-  AC_DEFINE(HAVE_UINT)
-  AC_MSG_RESULT(yes)
-else
-  AC_MSG_RESULT(no)
-fi
-AC_MSG_CHECKING(for uint_t)
-AC_CACHE_VAL(ac_cv_uint_t,
- [AC_TRY_COMPILE([#include <stdio.h>
-                  #include <sys/types.h>],
-                 [uint_t foo = 0;],
-                 [ac_cv_uint_t=true],
-                 [ac_cv_uint_t=false])])
-if test "$ac_cv_uint_t" = true ; then
-  AC_DEFINE(HAVE_UINT_T)
-  AC_MSG_RESULT(yes)
-else
-  AC_MSG_RESULT(no)
-fi
-
-dnl On the gcc trunk (as of 2001-02-09) _GNU_SOURCE, and thus __USE_GNU,
-dnl are defined when compiling C++ but not C.  Since the result of this
-dnl test is used only in C++, do it in C++.
 AC_LANG_CPLUSPLUS
 
-AC_MSG_CHECKING(for uname.domainname)
-AC_CACHE_VAL(ac_cv_have_uname_domainname_field,
-    [AC_TRY_COMPILE([#include <sys/utsname.h>],
-        [ struct utsname *res; char *domain;
-            (void)uname(res);  if (res != 0) { domain = res->domainname; } ],
-        [ac_cv_have_uname_domainname_field=true],
-        [ac_cv_have_uname_domainname_field=false])])
-
-if test "$ac_cv_have_uname_domainname_field" = "true"; then
-    AC_DEFINE(HAVE_UNAME_DOMAINNAME_FIELD)
-    AC_MSG_RESULT(yes)
-else
-    AC_MSG_RESULT(no)
-fi
-
-AC_MSG_CHECKING(for uname.__domainname)
-AC_CACHE_VAL(ac_cv_have_uname_us_domainname_field,
-    [AC_TRY_COMPILE([#include <sys/utsname.h>],
-        [ struct utsname *res; char *domain;
-            (void)uname(res);  if (res != 0) { domain = res->__domainname; } ],
-        [ac_cv_have_uname_us_domainname_field=true],
-        [ac_cv_have_uname_us_domainname_field=false])])
-
-if test "$ac_cv_have_uname_us_domainname_field" = "true"; then
-    AC_DEFINE(HAVE_UNAME_US_DOMAINNAME_FIELD)
-    AC_MSG_RESULT(yes)
-else
-    AC_MSG_RESULT(no)
-fi
-
 MOZ_CXX11
 
 AC_LANG_C
 
 dnl Check for .hidden assembler directive and visibility attribute.
 dnl Borrowed from glibc configure.in
 dnl ===============================================================
 if test "$GNU_CC"; then
@@ -3141,33 +3066,16 @@ if test "$ac_cv_func_res_ninit" = "yes";
     AC_DEFINE(HAVE_RES_NINIT)
 dnl must add the link line we do something as foolish as this... dougt
 dnl else
 dnl    AC_CHECK_LIB(bind, res_ninit, AC_DEFINE(HAVE_RES_NINIT),
 dnl        AC_CHECK_LIB(resolv, res_ninit, AC_DEFINE(HAVE_RES_NINIT)))
 fi
 
 AC_LANG_CPLUSPLUS
-AC_CACHE_CHECK(
-    [for gnu_get_libc_version()],
-    ac_cv_func_gnu_get_libc_version,
-    [AC_TRY_LINK([
-        #ifdef HAVE_GNU_LIBC_VERSION_H
-        #include <gnu/libc-version.h>
-        #endif
-        ],
-        [const char *glibc_version = gnu_get_libc_version();],
-        [ac_cv_func_gnu_get_libc_version=yes],
-        [ac_cv_func_gnu_get_libc_version=no]
-        )]
-    )
-
-if test "$ac_cv_func_gnu_get_libc_version" = "yes"; then
-    AC_DEFINE(HAVE_GNU_GET_LIBC_VERSION)
-fi
 
 case $target_os in
     darwin*|mingw*|os2*)
         ;;
     *)
 
 AC_CHECK_LIB(c, iconv, [_ICONV_LIBS="$_ICONV_LIBS"],
     AC_CHECK_LIB(iconv, iconv, [_ICONV_LIBS="$_ICONV_LIBS -liconv"],
@@ -6973,38 +6881,16 @@ if test -z "$MOZ_MEMORY"; then
   case "${target}" in
     *-mingw*)
       if test -z "$WIN32_REDIST_DIR" -a -z "$MOZ_DEBUG"; then
         AC_MSG_WARN([When not building jemalloc, you need to set WIN32_REDIST_DIR to the path to the Visual C++ Redist (usually VCINSTALLDIR\redist\x86\Microsoft.VC80.CRT, for VC++ v8) if you intend to distribute your build.])
       fi
       ;;
   esac
 else
-  dnl Don't try to run compiler tests on Windows
-  if test "$OS_ARCH" = "WINNT"; then
-    if test -z "$HAVE_64BIT_OS"; then
-      AC_DEFINE_UNQUOTED([MOZ_MEMORY_SIZEOF_PTR_2POW], 2)
-    else
-      AC_DEFINE_UNQUOTED([MOZ_MEMORY_SIZEOF_PTR_2POW], 3)
-    fi
-  else
-    AC_CHECK_SIZEOF([int *], [4])
-    case "${ac_cv_sizeof_int_p}" in
-    4)
-      AC_DEFINE_UNQUOTED([MOZ_MEMORY_SIZEOF_PTR_2POW], 2)
-      ;;
-    8)
-      AC_DEFINE_UNQUOTED([MOZ_MEMORY_SIZEOF_PTR_2POW], 3)
-      ;;
-    *)
-      AC_MSG_ERROR([Unexpected pointer size])
-      ;;
-    esac
-  fi
-
   AC_DEFINE(MOZ_MEMORY)
   if test -n "$MOZ_JEMALLOC3"; then
     AC_DEFINE(MOZ_JEMALLOC3)
   fi
   if test "x$MOZ_DEBUG" = "x1"; then
     AC_DEFINE(MOZ_MEMORY_DEBUG)
   fi
   dnl The generic feature tests that determine how to compute ncpus are long and
--- a/content/canvas/src/CanvasRenderingContext2D.cpp
+++ b/content/canvas/src/CanvasRenderingContext2D.cpp
@@ -1037,17 +1037,17 @@ CanvasRenderingContext2D::Render(gfxCont
   ctx->Fill();
 
   if (mOpaque)
       ctx->SetOperator(op);
 
   if (!(aFlags & RenderFlagPremultAlpha)) {
       nsRefPtr<gfxASurface> curSurface = ctx->CurrentSurface();
       nsRefPtr<gfxImageSurface> gis = curSurface->GetAsImageSurface();
-      NS_ABORT_IF_FALSE(gis, "If non-premult alpha, must be able to get image surface!");
+      MOZ_ASSERT(gis, "If non-premult alpha, must be able to get image surface!");
 
       gfxUtils::UnpremultiplyImageSurface(gis);
   }
 
   return rv;
 }
 
 NS_IMETHODIMP
@@ -3579,17 +3579,17 @@ CanvasRenderingContext2D::GetImageDataAr
 void
 CanvasRenderingContext2D::EnsureErrorTarget()
 {
   if (sErrorTarget) {
     return;
   }
 
   RefPtr<DrawTarget> errorTarget = gfxPlatform::GetPlatform()->CreateOffscreenCanvasDrawTarget(IntSize(1, 1), FORMAT_B8G8R8A8);
-  NS_ABORT_IF_FALSE(errorTarget, "Failed to allocate the error target!");
+  MOZ_ASSERT(errorTarget, "Failed to allocate the error target!");
 
   sErrorTarget = errorTarget;
   NS_ADDREF(sErrorTarget);
 }
 
 void
 CanvasRenderingContext2D::FillRuleChanged()
 {
--- a/content/canvas/src/WebGLContext.cpp
+++ b/content/canvas/src/WebGLContext.cpp
@@ -116,30 +116,29 @@ WebGLContext::WebGLContext()
     mActiveTexture = 0;
     mWebGLError = LOCAL_GL_NO_ERROR;
     mPixelStoreFlipY = false;
     mPixelStorePremultiplyAlpha = false;
     mPixelStoreColorspaceConversion = BROWSER_DEFAULT_WEBGL;
 
     mShaderValidation = true;
 
-    mBlackTexturesAreInitialized = false;
-    mFakeBlackStatus = DoNotNeedFakeBlack;
+    mFakeBlackStatus = WebGLContextFakeBlackStatus::NotNeeded;
 
     mVertexAttrib0Vector[0] = 0;
     mVertexAttrib0Vector[1] = 0;
     mVertexAttrib0Vector[2] = 0;
     mVertexAttrib0Vector[3] = 1;
     mFakeVertexAttrib0BufferObjectVector[0] = 0;
     mFakeVertexAttrib0BufferObjectVector[1] = 0;
     mFakeVertexAttrib0BufferObjectVector[2] = 0;
     mFakeVertexAttrib0BufferObjectVector[3] = 1;
     mFakeVertexAttrib0BufferObjectSize = 0;
     mFakeVertexAttrib0BufferObject = 0;
-    mFakeVertexAttrib0BufferStatus = VertexAttrib0Status::Default;
+    mFakeVertexAttrib0BufferStatus = WebGLVertexAttrib0Status::Default;
 
     // these are de default values, see 6.2 State tables in the OpenGL ES 2.0.25 spec
     mColorWriteMask[0] = 1;
     mColorWriteMask[1] = 1;
     mColorWriteMask[2] = 1;
     mColorWriteMask[3] = 1;
     mDepthWriteMask = 1;
     mColorClearValue[0] = 0.f;
@@ -259,21 +258,20 @@ WebGLContext::DestroyResourcesAndContext
         mFramebuffers.getLast()->DeleteOnce();
     while (!mShaders.isEmpty())
         mShaders.getLast()->DeleteOnce();
     while (!mPrograms.isEmpty())
         mPrograms.getLast()->DeleteOnce();
     while (!mQueries.isEmpty())
         mQueries.getLast()->DeleteOnce();
 
-    if (mBlackTexturesAreInitialized) {
-        gl->fDeleteTextures(1, &mBlackTexture2D);
-        gl->fDeleteTextures(1, &mBlackTextureCubeMap);
-        mBlackTexturesAreInitialized = false;
-    }
+    mBlackOpaqueTexture2D = nullptr;
+    mBlackOpaqueTextureCubeMap = nullptr;
+    mBlackTransparentTexture2D = nullptr;
+    mBlackTransparentTextureCubeMap = nullptr;
 
     if (mFakeVertexAttrib0BufferObject) {
         gl->fDeleteBuffers(1, &mFakeVertexAttrib0BufferObject);
     }
 
     // We just got rid of everything, so the context had better
     // have been going away.
 #ifdef DEBUG
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -21,16 +21,17 @@
 #include "nsWrapperCache.h"
 #include "nsIObserver.h"
 
 #include "GLContextProvider.h"
 #include "gfxImageSurface.h"
 
 #include "mozilla/LinkedList.h"
 #include "mozilla/CheckedInt.h"
+#include "mozilla/Scoped.h"
 
 #ifdef XP_MACOSX
 #include "ForceDiscreteGPUHelperCGL.h"
 #endif
 
 #include "mozilla/dom/TypedArray.h"
 #include "mozilla/ErrorResult.h"
 
@@ -78,18 +79,16 @@ class ImageData;
 struct WebGLContextAttributes;
 template<typename> struct Nullable;
 }
 
 namespace gfx {
 class SourceSurface;
 }
 
-using WebGLTexelConversions::WebGLTexelFormat;
-
 WebGLTexelFormat GetWebGLTexelFormat(GLenum format, GLenum type);
 
 struct WebGLContextOptions {
     // these are defaults
     WebGLContextOptions();
 
     bool operator==(const WebGLContextOptions& other) const {
         return
@@ -793,25 +792,27 @@ private:
     void VertexAttrib4fv_base(GLuint idx, uint32_t arrayLength, const GLfloat* ptr);
 
     bool ValidateBufferFetching(const char *info);
     bool BindArrayAttribToLocation0(WebGLProgram *program);
 
 // -----------------------------------------------------------------------------
 // PROTECTED
 protected:
-    void SetDontKnowIfNeedFakeBlack() {
-        mFakeBlackStatus = DontKnowIfNeedFakeBlack;
+    void SetFakeBlackStatus(WebGLContextFakeBlackStatus x) {
+        mFakeBlackStatus = x;
     }
+    // Returns the current fake-black-status, except if it was Unknown,
+    // in which case this function resolves it first, so it never returns Unknown.
+    WebGLContextFakeBlackStatus ResolvedFakeBlackStatus();
 
-    bool NeedFakeBlack();
     void BindFakeBlackTextures();
     void UnbindFakeBlackTextures();
 
-    int WhatDoesVertexAttrib0Need();
+    WebGLVertexAttrib0Status WhatDoesVertexAttrib0Need();
     bool DoFakeVertexAttrib0(GLuint vertexCount);
     void UndoFakeVertexAttrib0();
     void InvalidateFakeVertexAttrib0();
 
     static CheckedUint32 GetImageSize(GLsizei height, 
                                       GLsizei width, 
                                       uint32_t pixelSize,
                                       uint32_t alignment);
@@ -1085,26 +1086,45 @@ protected:
     LinkedList<WebGLVertexArray> mVertexArrays;
 
     WebGLRefPtr<WebGLVertexArray> mDefaultVertexArray;
 
     // PixelStore parameters
     uint32_t mPixelStorePackAlignment, mPixelStoreUnpackAlignment, mPixelStoreColorspaceConversion;
     bool mPixelStoreFlipY, mPixelStorePremultiplyAlpha;
 
-    FakeBlackStatus mFakeBlackStatus;
+    WebGLContextFakeBlackStatus mFakeBlackStatus;
+
+    class FakeBlackTexture
+    {
+        gl::GLContext* mGL;
+        GLuint mGLName;
 
-    GLuint mBlackTexture2D, mBlackTextureCubeMap;
-    bool mBlackTexturesAreInitialized;
+    public:
+        FakeBlackTexture(gl::GLContext* gl, GLenum target, GLenum format);
+        ~FakeBlackTexture();
+        GLuint GLName() const { return mGLName; }
+    };
+
+    ScopedDeletePtr<FakeBlackTexture> mBlackOpaqueTexture2D,
+                                      mBlackOpaqueTextureCubeMap,
+                                      mBlackTransparentTexture2D,
+                                      mBlackTransparentTextureCubeMap;
+
+    void BindFakeBlackTexturesHelper(
+        GLenum target,
+        const nsTArray<WebGLRefPtr<WebGLTexture> >& boundTexturesArray,
+        ScopedDeletePtr<FakeBlackTexture> & opaqueTextureScopedPtr,
+        ScopedDeletePtr<FakeBlackTexture> & transparentTextureScopedPtr);
 
     GLfloat mVertexAttrib0Vector[4];
     GLfloat mFakeVertexAttrib0BufferObjectVector[4];
     size_t mFakeVertexAttrib0BufferObjectSize;
     GLuint mFakeVertexAttrib0BufferObject;
-    int mFakeVertexAttrib0BufferStatus;
+    WebGLVertexAttrib0Status mFakeVertexAttrib0BufferStatus;
 
     GLint mStencilRefFront, mStencilRefBack;
     GLuint mStencilValueMaskFront, mStencilValueMaskBack,
               mStencilWriteMaskFront, mStencilWriteMaskBack;
     realGLboolean mColorWriteMask[4];
     realGLboolean mDepthWriteMask;
     GLfloat mColorClearValue[4];
     GLint mStencilClearValue;
--- a/content/canvas/src/WebGLContextBuffers.cpp
+++ b/content/canvas/src/WebGLContextBuffers.cpp
@@ -378,18 +378,18 @@ WebGLContext::DeleteBuffer(WebGLBuffer *
     }
 
     if (mBoundVertexArray->mBoundElementArrayBuffer == buffer) {
         BindBuffer(LOCAL_GL_ELEMENT_ARRAY_BUFFER,
                    static_cast<WebGLBuffer*>(nullptr));
     }
 
     for (int32_t i = 0; i < mGLMaxVertexAttribs; i++) {
-        if (mBoundVertexArray->mAttribBuffers[i].buf == buffer)
-            mBoundVertexArray->mAttribBuffers[i].buf = nullptr;
+        if (mBoundVertexArray->HasAttrib(i) && mBoundVertexArray->mAttribs[i].buf == buffer)
+            mBoundVertexArray->mAttribs[i].buf = nullptr;
     }
 
     buffer->RequestDelete();
 }
 
 bool
 WebGLContext::IsBuffer(WebGLBuffer *buffer)
 {
@@ -476,17 +476,17 @@ WebGLContext::CheckedBufferData(GLenum t
     }
 #endif
     WebGLBuffer *boundBuffer = nullptr;
     if (target == LOCAL_GL_ARRAY_BUFFER) {
         boundBuffer = mBoundArrayBuffer;
     } else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
         boundBuffer = mBoundVertexArray->mBoundElementArrayBuffer;
     }
-    NS_ABORT_IF_FALSE(boundBuffer != nullptr, "no buffer bound for this target");
+    MOZ_ASSERT(boundBuffer != nullptr, "no buffer bound for this target");
 
     bool sizeChanges = uint32_t(size) != boundBuffer->ByteLength();
     if (sizeChanges) {
         UpdateWebGLErrorAndClearGLError();
         gl->fBufferData(target, size, data, usage);
         GLenum error = LOCAL_GL_NO_ERROR;
         UpdateWebGLErrorAndClearGLError(&error);
         return error;
--- a/content/canvas/src/WebGLContextExtensions.cpp
+++ b/content/canvas/src/WebGLContextExtensions.cpp
@@ -175,16 +175,23 @@ WebGLContext::GetExtension(JSContext *cx
             ext = WEBGL_compressed_texture_atc;
         }
         else if (CompareWebGLExtensionName(name, "MOZ_WEBGL_compressed_texture_pvrtc")) {
             ext = WEBGL_compressed_texture_pvrtc;
         }
         else if (CompareWebGLExtensionName(name, "MOZ_WEBGL_depth_texture")) {
             ext = WEBGL_depth_texture;
         }
+
+        if (ext != WebGLExtensionID_unknown_extension) {
+            GenerateWarning("getExtension('%s'): MOZ_ prefixed WebGL extension strings are deprecated. "
+                            "Support for them will be removed in the future. Use unprefixed extension strings. "
+                            "To get draft extensions, set the webgl.enable-draft-extensions preference.",
+                            name.get());
+        }
     }
 
     if (ext == WebGLExtensionID_unknown_extension) {
         return nullptr;
     }
 
     // step 2: check if the extension is supported
     if (!IsExtensionSupported(cx, ext)) {
--- a/content/canvas/src/WebGLContextFramebufferOperations.cpp
+++ b/content/canvas/src/WebGLContextFramebufferOperations.cpp
@@ -25,17 +25,17 @@ WebGLContext::Clear(GLbitfield mask)
 
     if (mask == 0) {
         GenerateWarning("Calling gl.clear(0) has no effect.");
     } else if (mRasterizerDiscardEnabled) {
         GenerateWarning("Calling gl.clear() with RASTERIZER_DISCARD enabled has no effects.");
     }
 
     if (mBoundFramebuffer) {
-        if (!mBoundFramebuffer->CheckAndInitializeRenderbuffers())
+        if (!mBoundFramebuffer->CheckAndInitializeAttachments())
             return ErrorInvalidFramebufferOperation("clear: incomplete framebuffer");
 
         gl->fClear(mask);
         return;
     }
 
     // Ok, we're clearing the default framebuffer/screen.
 
--- a/content/canvas/src/WebGLContextGL.cpp
+++ b/content/canvas/src/WebGLContextGL.cpp
@@ -47,25 +47,68 @@
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::gl;
 
 static bool BaseTypeAndSizeFromUniformType(GLenum uType, GLenum *baseType, GLint *unitSize);
 static GLenum InternalFormatForFormatAndType(GLenum format, GLenum type, bool isGLES2);
 
-//
-//  WebGL API
-//
-
 inline const WebGLRectangleObject *WebGLContext::FramebufferRectangleObject() const {
     return mBoundFramebuffer ? mBoundFramebuffer->RectangleObject()
                              : static_cast<const WebGLRectangleObject*>(this);
 }
 
+WebGLContext::FakeBlackTexture::FakeBlackTexture(GLContext *gl, GLenum target, GLenum format)
+    : mGL(gl)
+    , mGLName(0)
+{
+  MOZ_ASSERT(target == LOCAL_GL_TEXTURE_2D || target == LOCAL_GL_TEXTURE_CUBE_MAP);
+  MOZ_ASSERT(format == LOCAL_GL_RGB || format == LOCAL_GL_RGBA);
+
+  mGL->MakeCurrent();
+  GLuint formerBinding = 0;
+  gl->GetUIntegerv(target == LOCAL_GL_TEXTURE_2D
+                   ? LOCAL_GL_TEXTURE_BINDING_2D
+                   : LOCAL_GL_TEXTURE_BINDING_CUBE_MAP,
+                   &formerBinding);
+  gl->fGenTextures(1, &mGLName);
+  gl->fBindTexture(target, mGLName);
+
+  // we allocate our zeros on the heap, and we overallocate (16 bytes instead of 4)
+  // to minimize the risk of running into a driver bug in texImage2D, as it is
+  // a bit unusual maybe to create 1x1 textures, and the stack may not have the alignment
+  // that texImage2D expects.
+  void* zeros = calloc(1, 16);
+  if (target == LOCAL_GL_TEXTURE_2D) {
+      gl->fTexImage2D(target, 0, format, 1, 1,
+                      0, format, LOCAL_GL_UNSIGNED_BYTE, zeros);
+  } else {
+      for (GLuint i = 0; i < 6; ++i) {
+          gl->fTexImage2D(LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, format, 1, 1,
+                          0, format, LOCAL_GL_UNSIGNED_BYTE, zeros);
+      }
+  }
+  free(zeros);
+
+  gl->fBindTexture(target, formerBinding);
+}
+
+WebGLContext::FakeBlackTexture::~FakeBlackTexture()
+{
+  if (mGL) {
+      mGL->MakeCurrent();
+      mGL->fDeleteTextures(1, &mGLName);
+  }
+}
+
+//
+//  WebGL API
+//
+
 void
 WebGLContext::ActiveTexture(GLenum texture)
 {
     if (IsContextLost()) 
         return;
 
     if (texture < LOCAL_GL_TEXTURE0 ||
         texture >= LOCAL_GL_TEXTURE0 + uint32_t(mGLMaxTextureUnits))
@@ -186,41 +229,57 @@ WebGLContext::BindRenderbuffer(GLenum ta
     } else {
         gl->fBindRenderbuffer(target, 0);
     }
 
     mBoundRenderbuffer = wrb;
 }
 
 void
-WebGLContext::BindTexture(GLenum target, WebGLTexture *tex)
+WebGLContext::BindTexture(GLenum target, WebGLTexture *newTex)
 {
     if (IsContextLost())
         return;
 
-    if (!ValidateObjectAllowDeletedOrNull("bindTexture", tex))
+     if (!ValidateObjectAllowDeletedOrNull("bindTexture", newTex))
         return;
 
     // silently ignore a deleted texture
-    if (tex && tex->IsDeleted())
+    if (newTex && newTex->IsDeleted())
         return;
 
+    WebGLRefPtr<WebGLTexture>* currentTexPtr = nullptr;
+
     if (target == LOCAL_GL_TEXTURE_2D) {
-        mBound2DTextures[mActiveTexture] = tex;
+        currentTexPtr = &mBound2DTextures[mActiveTexture];
     } else if (target == LOCAL_GL_TEXTURE_CUBE_MAP) {
-        mBoundCubeMapTextures[mActiveTexture] = tex;
+        currentTexPtr = &mBoundCubeMapTextures[mActiveTexture];
     } else {
         return ErrorInvalidEnumInfo("bindTexture: target", target);
     }
 
-    SetDontKnowIfNeedFakeBlack();
+    WebGLTextureFakeBlackStatus currentTexFakeBlackStatus = WebGLTextureFakeBlackStatus::NotNeeded;
+    if (*currentTexPtr) {
+        currentTexFakeBlackStatus = (*currentTexPtr)->ResolvedFakeBlackStatus();
+    }
+    WebGLTextureFakeBlackStatus newTexFakeBlackStatus = WebGLTextureFakeBlackStatus::NotNeeded;
+    if (newTex) {
+        newTexFakeBlackStatus = newTex->ResolvedFakeBlackStatus();
+    }
+
+    *currentTexPtr = newTex;
+
+    if (currentTexFakeBlackStatus != newTexFakeBlackStatus) {
+        SetFakeBlackStatus(WebGLContextFakeBlackStatus::Unknown);
+    }
+
     MakeContextCurrent();
 
-    if (tex)
-        tex->Bind(target);
+    if (newTex)
+        newTex->Bind(target);
     else
         gl->fBindTexture(target, 0 /* == texturename */);
 }
 
 void WebGLContext::BlendEquation(GLenum mode)
 {
     if (IsContextLost())
         return;
@@ -503,17 +562,17 @@ WebGLContext::CopyTexImage2D(GLenum targ
         return ErrorInvalidOperation("copyTexImage2D: texture format requires an alpha channel "
                                      "but the framebuffer doesn't have one");
 
     if (internalformat == LOCAL_GL_DEPTH_COMPONENT ||
         internalformat == LOCAL_GL_DEPTH_STENCIL)
         return ErrorInvalidOperation("copyTexImage2D: a base internal format of DEPTH_COMPONENT or DEPTH_STENCIL isn't supported");
 
     if (mBoundFramebuffer)
-        if (!mBoundFramebuffer->CheckAndInitializeRenderbuffers())
+        if (!mBoundFramebuffer->CheckAndInitializeAttachments())
             return ErrorInvalidFramebufferOperation("copyTexImage2D: incomplete framebuffer");
 
     WebGLTexture *tex = activeBoundTextureForTarget(target);
     if (!tex)
         return ErrorInvalidOperation("copyTexImage2D: no texture bound to this target");
 
     // copyTexImage2D only generates textures with type = UNSIGNED_BYTE
     GLenum type = LOCAL_GL_UNSIGNED_BYTE;
@@ -532,22 +591,23 @@ WebGLContext::CopyTexImage2D(GLenum targ
     if (sizeMayChange) {
         UpdateWebGLErrorAndClearGLError();
         CopyTexSubImage2D_base(target, level, internalformat, 0, 0, x, y, width, height, false);
         GLenum error = LOCAL_GL_NO_ERROR;
         UpdateWebGLErrorAndClearGLError(&error);
         if (error) {
             GenerateWarning("copyTexImage2D generated error %s", ErrorName(error));
             return;
-        }          
+        }
     } else {
         CopyTexSubImage2D_base(target, level, internalformat, 0, 0, x, y, width, height, false);
     }
-    
-    tex->SetImageInfo(target, level, width, height, internalformat, type);
+
+    tex->SetImageInfo(target, level, width, height, internalformat, type,
+                      WebGLImageDataStatus::InitializedImageData);
 }
 
 void
 WebGLContext::CopyTexSubImage2D(GLenum target,
                                 GLint level,
                                 GLint xoffset,
                                 GLint yoffset,
                                 GLint x,
@@ -612,19 +672,23 @@ WebGLContext::CopyTexSubImage2D(GLenum t
         return ErrorInvalidOperation("copyTexSubImage2D: texture format requires an alpha channel "
                                      "but the framebuffer doesn't have one");
 
     if (format == LOCAL_GL_DEPTH_COMPONENT ||
         format == LOCAL_GL_DEPTH_STENCIL)
         return ErrorInvalidOperation("copyTexSubImage2D: a base internal format of DEPTH_COMPONENT or DEPTH_STENCIL isn't supported");
 
     if (mBoundFramebuffer)
-        if (!mBoundFramebuffer->CheckAndInitializeRenderbuffers())
+        if (!mBoundFramebuffer->CheckAndInitializeAttachments())
             return ErrorInvalidFramebufferOperation("copyTexSubImage2D: incomplete framebuffer");
 
+    if (imageInfo.HasUninitializedImageData()) {
+        tex->DoDeferredImageInitialization(target, level);
+    }
+
     return CopyTexSubImage2D_base(target, level, format, xoffset, yoffset, x, y, width, height, true);
 }
 
 
 already_AddRefed<WebGLProgram>
 WebGLContext::CreateProgram()
 {
     if (IsContextLost())
@@ -800,42 +864,42 @@ WebGLContext::DepthRange(GLfloat zNear, 
 
     if (zNear > zFar)
         return ErrorInvalidOperation("depthRange: the near value is greater than the far value!");
 
     MakeContextCurrent();
     gl->fDepthRange(zNear, zFar);
 }
 
-int
+WebGLVertexAttrib0Status
 WebGLContext::WhatDoesVertexAttrib0Need()
 {
   // here we may assume that mCurrentProgram != null
 
     // work around Mac OSX crash, see bug 631420
 #ifdef XP_MACOSX
     if (gl->WorkAroundDriverBugs() &&
-        mBoundVertexArray->mAttribBuffers[0].enabled &&
+        mBoundVertexArray->IsAttribArrayEnabled(0) &&
         !mCurrentProgram->IsAttribInUse(0))
     {
-        return VertexAttrib0Status::EmulatedUninitializedArray;
+        return WebGLVertexAttrib0Status::EmulatedUninitializedArray;
     }
 #endif
 
-    return (gl->IsGLES2() || mBoundVertexArray->mAttribBuffers[0].enabled) ? VertexAttrib0Status::Default
-         : mCurrentProgram->IsAttribInUse(0)            ? VertexAttrib0Status::EmulatedInitializedArray
-                                                        : VertexAttrib0Status::EmulatedUninitializedArray;
+    return (gl->IsGLES2() || mBoundVertexArray->IsAttribArrayEnabled(0)) ? WebGLVertexAttrib0Status::Default
+         : mCurrentProgram->IsAttribInUse(0) ? WebGLVertexAttrib0Status::EmulatedInitializedArray
+                                             : WebGLVertexAttrib0Status::EmulatedUninitializedArray;
 }
 
 bool
 WebGLContext::DoFakeVertexAttrib0(GLuint vertexCount)
 {
-    int whatDoesAttrib0Need = WhatDoesVertexAttrib0Need();
-
-    if (whatDoesAttrib0Need == VertexAttrib0Status::Default)
+    WebGLVertexAttrib0Status whatDoesAttrib0Need = WhatDoesVertexAttrib0Need();
+
+    if (whatDoesAttrib0Need == WebGLVertexAttrib0Status::Default)
         return true;
 
     if (!mAlreadyWarnedAboutFakeVertexAttrib0) {
         GenerateWarning("Drawing without vertex attrib 0 array enabled forces the browser "
                         "to do expensive emulation work when running on desktop OpenGL "
                         "platforms, for example on Mac. It is preferable to always draw "
                         "with vertex attrib 0 array enabled, by using bindAttribLocation "
                         "to bind some always-used attribute to location 0.");
@@ -855,18 +919,18 @@ WebGLContext::DoFakeVertexAttrib0(GLuint
     if (!mFakeVertexAttrib0BufferObject) {
         gl->fGenBuffers(1, &mFakeVertexAttrib0BufferObject);
     }
 
     // if the VBO status is already exactly what we need, or if the only difference is that it's initialized and
     // we don't need it to be, then consider it OK
     bool vertexAttrib0BufferStatusOK =
         mFakeVertexAttrib0BufferStatus == whatDoesAttrib0Need ||
-        (mFakeVertexAttrib0BufferStatus == VertexAttrib0Status::EmulatedInitializedArray &&
-         whatDoesAttrib0Need == VertexAttrib0Status::EmulatedUninitializedArray);
+        (mFakeVertexAttrib0BufferStatus == WebGLVertexAttrib0Status::EmulatedInitializedArray &&
+         whatDoesAttrib0Need == WebGLVertexAttrib0Status::EmulatedUninitializedArray);
 
     if (!vertexAttrib0BufferStatusOK ||
         mFakeVertexAttrib0BufferObjectSize < dataSize ||
         mFakeVertexAttrib0BufferObjectVector[0] != mVertexAttrib0Vector[0] ||
         mFakeVertexAttrib0BufferObjectVector[1] != mVertexAttrib0Vector[1] ||
         mFakeVertexAttrib0BufferObjectVector[2] != mVertexAttrib0Vector[2] ||
         mFakeVertexAttrib0BufferObjectVector[3] != mVertexAttrib0Vector[3])
     {
@@ -877,17 +941,17 @@ WebGLContext::DoFakeVertexAttrib0(GLuint
         mFakeVertexAttrib0BufferObjectVector[2] = mVertexAttrib0Vector[2];
         mFakeVertexAttrib0BufferObjectVector[3] = mVertexAttrib0Vector[3];
 
         gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mFakeVertexAttrib0BufferObject);
 
         GLenum error = LOCAL_GL_NO_ERROR;
         UpdateWebGLErrorAndClearGLError();
 
-        if (mFakeVertexAttrib0BufferStatus == VertexAttrib0Status::EmulatedInitializedArray) {
+        if (mFakeVertexAttrib0BufferStatus == WebGLVertexAttrib0Status::EmulatedInitializedArray) {
             nsAutoArrayPtr<GLfloat> array(new GLfloat[4 * vertexCount]);
             for(size_t i = 0; i < vertexCount; ++i) {
                 array[4 * i + 0] = mVertexAttrib0Vector[0];
                 array[4 * i + 1] = mVertexAttrib0Vector[1];
                 array[4 * i + 2] = mVertexAttrib0Vector[2];
                 array[4 * i + 3] = mVertexAttrib0Vector[3];
             }
             gl->fBufferData(LOCAL_GL_ARRAY_BUFFER, dataSize, array, LOCAL_GL_DYNAMIC_DRAW);
@@ -910,116 +974,130 @@ WebGLContext::DoFakeVertexAttrib0(GLuint
     gl->fVertexAttribPointer(0, 4, LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0, 0);
     
     return true;
 }
 
 void
 WebGLContext::UndoFakeVertexAttrib0()
 {
-    int whatDoesAttrib0Need = WhatDoesVertexAttrib0Need();
-
-    if (whatDoesAttrib0Need == VertexAttrib0Status::Default)
+    WebGLVertexAttrib0Status whatDoesAttrib0Need = WhatDoesVertexAttrib0Need();
+
+    if (whatDoesAttrib0Need == WebGLVertexAttrib0Status::Default)
         return;
 
-    gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mBoundVertexArray->mAttribBuffers[0].buf ? mBoundVertexArray->mAttribBuffers[0].buf->GLName() : 0);
-    gl->fVertexAttribPointer(0,
-                             mBoundVertexArray->mAttribBuffers[0].size,
-                             mBoundVertexArray->mAttribBuffers[0].type,
-                             mBoundVertexArray->mAttribBuffers[0].normalized,
-                             mBoundVertexArray->mAttribBuffers[0].stride,
-                             reinterpret_cast<const GLvoid *>(mBoundVertexArray->mAttribBuffers[0].byteOffset));
+    if (mBoundVertexArray->HasAttrib(0) && mBoundVertexArray->mAttribs[0].buf) {
+        const WebGLVertexAttribData& attrib0 = mBoundVertexArray->mAttribs[0];
+        gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, attrib0.buf->GLName());
+        gl->fVertexAttribPointer(0,
+                                 attrib0.size,
+                                 attrib0.type,
+                                 attrib0.normalized,
+                                 attrib0.stride,
+                                 reinterpret_cast<const GLvoid *>(attrib0.byteOffset));
+    } else {
+        gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
+    }
 
     gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mBoundArrayBuffer ? mBoundArrayBuffer->GLName() : 0);
 }
 
-bool
-WebGLContext::NeedFakeBlack()
+WebGLContextFakeBlackStatus
+WebGLContext::ResolvedFakeBlackStatus()
 {
     // handle this case first, it's the generic case
-    if (mFakeBlackStatus == DoNotNeedFakeBlack)
-        return false;
-
-    if (mFakeBlackStatus == DoNeedFakeBlack)
-        return true;
+    if (MOZ_LIKELY(mFakeBlackStatus == WebGLContextFakeBlackStatus::NotNeeded))
+        return mFakeBlackStatus;
+
+    if (mFakeBlackStatus == WebGLContextFakeBlackStatus::Needed)
+        return mFakeBlackStatus;
 
     for (int32_t i = 0; i < mGLMaxTextureUnits; ++i) {
-        if ((mBound2DTextures[i] && mBound2DTextures[i]->NeedFakeBlack()) ||
-            (mBoundCubeMapTextures[i] && mBoundCubeMapTextures[i]->NeedFakeBlack()))
+        if ((mBound2DTextures[i] && mBound2DTextures[i]->ResolvedFakeBlackStatus() != WebGLTextureFakeBlackStatus::NotNeeded) ||
+            (mBoundCubeMapTextures[i] && mBoundCubeMapTextures[i]->ResolvedFakeBlackStatus() != WebGLTextureFakeBlackStatus::NotNeeded))
         {
-            mFakeBlackStatus = DoNeedFakeBlack;
-            return true;
+            mFakeBlackStatus = WebGLContextFakeBlackStatus::Needed;
+            return mFakeBlackStatus;
         }
     }
 
     // we have exhausted all cases where we do need fakeblack, so if the status is still unknown,
     // that means that we do NOT need it.
-    mFakeBlackStatus = DoNotNeedFakeBlack;
-    return false;
+    mFakeBlackStatus = WebGLContextFakeBlackStatus::NotNeeded;
+    return mFakeBlackStatus;
+}
+
+void
+WebGLContext::BindFakeBlackTexturesHelper(
+    GLenum target,
+    const nsTArray<WebGLRefPtr<WebGLTexture> > & boundTexturesArray,
+    ScopedDeletePtr<FakeBlackTexture> & opaqueTextureScopedPtr,
+    ScopedDeletePtr<FakeBlackTexture> & transparentTextureScopedPtr)
+{
+    for (int32_t i = 0; i < mGLMaxTextureUnits; ++i) {
+        if (!boundTexturesArray[i]) {
+            continue;
+        }
+
+        WebGLTextureFakeBlackStatus s = boundTexturesArray[i]->ResolvedFakeBlackStatus();
+        MOZ_ASSERT(s != WebGLTextureFakeBlackStatus::Unknown);
+
+        if (MOZ_LIKELY(s == WebGLTextureFakeBlackStatus::NotNeeded)) {
+            continue;
+        }
+
+        bool alpha = s == WebGLTextureFakeBlackStatus::UninitializedImageData &&
+                     FormatHasAlpha(boundTexturesArray[i]->ImageInfoBase().Format());
+        ScopedDeletePtr<FakeBlackTexture>&
+            blackTexturePtr = alpha
+                              ? transparentTextureScopedPtr
+                              : opaqueTextureScopedPtr;
+
+        if (!blackTexturePtr) {
+            GLenum format = alpha ? LOCAL_GL_RGBA : LOCAL_GL_RGB;
+            blackTexturePtr
+                = new FakeBlackTexture(gl, target, format);
+        }
+
+        gl->fActiveTexture(LOCAL_GL_TEXTURE0 + i);
+        gl->fBindTexture(target,
+                         blackTexturePtr->GLName());
+    }
 }
 
 void
 WebGLContext::BindFakeBlackTextures()
 {
     // this is the generic case: try to return early
-    if (!NeedFakeBlack())
+    if (MOZ_LIKELY(ResolvedFakeBlackStatus() == WebGLContextFakeBlackStatus::NotNeeded))
         return;
 
-    if (!mBlackTexturesAreInitialized) {
-        GLuint bound2DTex = 0;
-        GLuint boundCubeTex = 0;
-        gl->fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_2D, (GLint*) &bound2DTex);
-        gl->fGetIntegerv(LOCAL_GL_TEXTURE_BINDING_CUBE_MAP, (GLint*) &boundCubeTex);
-
-        const uint8_t black[] = {0, 0, 0, 255};
-
-        gl->fGenTextures(1, &mBlackTexture2D);
-        gl->fBindTexture(LOCAL_GL_TEXTURE_2D, mBlackTexture2D);
-        gl->fTexImage2D(LOCAL_GL_TEXTURE_2D, 0, LOCAL_GL_RGBA, 1, 1,
-                        0, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, &black);
-
-        gl->fGenTextures(1, &mBlackTextureCubeMap);
-        gl->fBindTexture(LOCAL_GL_TEXTURE_CUBE_MAP, mBlackTextureCubeMap);
-        for (GLuint i = 0; i < 6; ++i) {
-            gl->fTexImage2D(LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, LOCAL_GL_RGBA, 1, 1,
-                            0, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, &black);
-        }
-
-        // Reset bound textures
-        gl->fBindTexture(LOCAL_GL_TEXTURE_2D, bound2DTex);
-        gl->fBindTexture(LOCAL_GL_TEXTURE_CUBE_MAP, boundCubeTex);
-
-        mBlackTexturesAreInitialized = true;
-    }
-
-    for (int32_t i = 0; i < mGLMaxTextureUnits; ++i) {
-        if (mBound2DTextures[i] && mBound2DTextures[i]->NeedFakeBlack()) {
-            gl->fActiveTexture(LOCAL_GL_TEXTURE0 + i);
-            gl->fBindTexture(LOCAL_GL_TEXTURE_2D, mBlackTexture2D);
-        }
-        if (mBoundCubeMapTextures[i] && mBoundCubeMapTextures[i]->NeedFakeBlack()) {
-            gl->fActiveTexture(LOCAL_GL_TEXTURE0 + i);
-            gl->fBindTexture(LOCAL_GL_TEXTURE_CUBE_MAP, mBlackTextureCubeMap);
-        }
-    }
+    BindFakeBlackTexturesHelper(LOCAL_GL_TEXTURE_2D,
+                                mBound2DTextures,
+                                mBlackOpaqueTexture2D,
+                                mBlackTransparentTexture2D);
+    BindFakeBlackTexturesHelper(LOCAL_GL_TEXTURE_CUBE_MAP,
+                                mBoundCubeMapTextures,
+                                mBlackOpaqueTextureCubeMap,
+                                mBlackTransparentTextureCubeMap);
 }
 
 void
 WebGLContext::UnbindFakeBlackTextures()
 {
     // this is the generic case: try to return early
-    if (!NeedFakeBlack())
+    if (MOZ_LIKELY(ResolvedFakeBlackStatus() == WebGLContextFakeBlackStatus::NotNeeded))
         return;
 
     for (int32_t i = 0; i < mGLMaxTextureUnits; ++i) {
-        if (mBound2DTextures[i] && mBound2DTextures[i]->NeedFakeBlack()) {
+        if (mBound2DTextures[i] && mBound2DTextures[i]->ResolvedFakeBlackStatus() != WebGLTextureFakeBlackStatus::NotNeeded) {
             gl->fActiveTexture(LOCAL_GL_TEXTURE0 + i);
             gl->fBindTexture(LOCAL_GL_TEXTURE_2D, mBound2DTextures[i]->GLName());
         }
-        if (mBoundCubeMapTextures[i] && mBoundCubeMapTextures[i]->NeedFakeBlack()) {
+        if (mBoundCubeMapTextures[i] && mBoundCubeMapTextures[i]->ResolvedFakeBlackStatus() != WebGLTextureFakeBlackStatus::NotNeeded) {
             gl->fActiveTexture(LOCAL_GL_TEXTURE0 + i);
             gl->fBindTexture(LOCAL_GL_TEXTURE_CUBE_MAP, mBoundCubeMapTextures[i]->GLName());
         }
     }
 
     gl->fActiveTexture(LOCAL_GL_TEXTURE0 + mActiveTexture);
 }
 
@@ -1946,28 +2024,28 @@ WebGLContext::IsTexture(WebGLTexture *te
     return ValidateObjectAllowDeleted("isTexture", tex) &&
         !tex->IsDeleted() &&
         tex->HasEverBeenBound();
 }
 
 // Try to bind an attribute that is an array to location 0:
 bool WebGLContext::BindArrayAttribToLocation0(WebGLProgram *program)
 {
-    if (mBoundVertexArray->mAttribBuffers[0].enabled) {
+    if (mBoundVertexArray->IsAttribArrayEnabled(0)) {
         return false;
     }
 
     GLint leastArrayLocation = -1;
 
     std::map<GLint, nsCString>::iterator itr;
     for (itr = program->mActiveAttribMap.begin();
          itr != program->mActiveAttribMap.end();
          itr++) {
         int32_t index = itr->first;
-        if (mBoundVertexArray->mAttribBuffers[index].enabled &&
+        if (mBoundVertexArray->IsAttribArrayEnabled(index) &&
             index < leastArrayLocation)
         {
             leastArrayLocation = index;
         }
     }
 
     if (leastArrayLocation > 0) {
         nsCString& attrName = program->mActiveAttribMap.find(leastArrayLocation)->second;
@@ -2079,17 +2157,17 @@ WebGLContext::LinkProgram(WebGLProgram *
 
                 const char *shaderTypeName = nullptr;
                 if (shader->ShaderType() == LOCAL_GL_VERTEX_SHADER) {
                     shaderTypeName = "vertex";
                 } else if (shader->ShaderType() == LOCAL_GL_FRAGMENT_SHADER) {
                     shaderTypeName = "fragment";
                 } else {
                     // should have been validated earlier
-                    NS_ABORT();
+                    MOZ_ASSERT(false);
                     shaderTypeName = "<unknown>";
                 }
 
                 GetShaderInfoLog(shader, log);
 
                 GenerateWarning("linkProgram: a %s shader used in this program failed to "
                                 "compile, with this log:\n%s\n",
                                 shaderTypeName,
@@ -2249,17 +2327,17 @@ WebGLContext::ReadPixels(GLint x, GLint 
         default:
             return ErrorInvalidOperation("readPixels: Invalid format/type pair");
     }
 
     MakeContextCurrent();
 
     if (mBoundFramebuffer) {
         // prevent readback of arbitrary video memory through uninitialized renderbuffers!
-        if (!mBoundFramebuffer->CheckAndInitializeRenderbuffers())
+        if (!mBoundFramebuffer->CheckAndInitializeAttachments())
             return ErrorInvalidFramebufferOperation("readPixels: incomplete framebuffer");
     }
     // Now that the errors are out of the way, on to actually reading
 
     // If we won't be reading any pixels anyways, just skip the actual reading
     if (width == 0 || height == 0)
         return DummyFramebufferOperation("readPixels");
 
@@ -2435,17 +2513,17 @@ WebGLContext::RenderbufferStorage(GLenum
         }
     } else {
         mBoundRenderbuffer->RenderbufferStorage(internalformatForGL, width, height);
     }
 
     mBoundRenderbuffer->SetInternalFormat(internalformat);
     mBoundRenderbuffer->SetInternalFormatForGL(internalformatForGL);
     mBoundRenderbuffer->setDimensions(width, height);
-    mBoundRenderbuffer->SetInitialized(false);
+    mBoundRenderbuffer->SetImageDataStatus(WebGLImageDataStatus::UninitializedImageData);
 }
 
 void
 WebGLContext::Scissor(GLint x, GLint y, GLsizei width, GLsizei height)
 {
     if (IsContextLost())
         return;
 
@@ -2584,26 +2662,26 @@ WebGLContext::SurfaceFromElementResultTo
 
     gfxImageSurface* surf = static_cast<gfxImageSurface*>(res.mSurface.get());
 
     res.mSurface.forget();
     *imageOut = surf;
 
     switch (surf->Format()) {
         case gfxImageFormatARGB32:
-            *format = WebGLTexelConversions::BGRA8; // careful, our ARGB means BGRA
+            *format = WebGLTexelFormat::BGRA8; // careful, our ARGB means BGRA
             break;
         case gfxImageFormatRGB24:
-            *format = WebGLTexelConversions::BGRX8; // careful, our RGB24 is not tightly packed. Whence BGRX8.
+            *format = WebGLTexelFormat::BGRX8; // careful, our RGB24 is not tightly packed. Whence BGRX8.
             break;
         case gfxImageFormatA8:
-            *format = WebGLTexelConversions::A8;
+            *format = WebGLTexelFormat::A8;
             break;
         case gfxImageFormatRGB16_565:
-            *format = WebGLTexelConversions::RGB565;
+            *format = WebGLTexelFormat::RGB565;
             break;
         default:
             NS_ASSERTION(false, "Unsupported image format. Unimplemented.");
             return NS_ERROR_NOT_IMPLEMENTED;
     }
 
     return NS_OK;
 }
@@ -3298,17 +3376,18 @@ WebGLContext::CompressedTexImage2D(GLenu
     }
 
     uint32_t byteLength = view.Length();
     if (!ValidateCompressedTextureSize(target, level, internalformat, width, height, byteLength, "compressedTexImage2D")) {
         return;
     }
 
     gl->fCompressedTexImage2D(target, level, internalformat, width, height, border, byteLength, view.Data());
-    tex->SetImageInfo(target, level, width, height, internalformat, LOCAL_GL_UNSIGNED_BYTE);
+    tex->SetImageInfo(target, level, width, height, internalformat, LOCAL_GL_UNSIGNED_BYTE,
+                      WebGLImageDataStatus::InitializedImageData);
 
     ReattachTextureToAnyFramebufferToWorkAroundBugs(tex, level);
 }
 
 void
 WebGLContext::CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset,
                                       GLint yoffset, GLsizei width, GLsizei height,
                                       GLenum format, const ArrayBufferView& view)
@@ -3396,16 +3475,20 @@ WebGLContext::CompressedTexSubImage2D(GL
                 height != imageInfo.Height())
             {
                 ErrorInvalidValue("compressedTexSubImage2D: the update rectangle doesn't match the existing image");
                 return;
             }
         }
     }
 
+    if (imageInfo.HasUninitializedImageData()) {
+        tex->DoDeferredImageInitialization(target, level);
+    }
+
     gl->fCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, byteLength, view.Data());
 
     return;
 }
 
 JS::Value
 WebGLContext::GetShaderParameter(WebGLShader *shader, GLenum pname)
 {
@@ -3583,17 +3666,17 @@ GLenum WebGLContext::CheckedTexImage2D(G
                                        GLsizei width,
                                        GLsizei height,
                                        GLint border,
                                        GLenum format,
                                        GLenum type,
                                        const GLvoid *data)
 {
     WebGLTexture *tex = activeBoundTextureForTarget(target);
-    NS_ABORT_IF_FALSE(tex != nullptr, "no texture bound");
+    MOZ_ASSERT(tex != nullptr, "no texture bound");
 
     bool sizeMayChange = true;
     
     if (tex->HasImageInfoAt(target, level)) {
         const WebGLTexture::ImageInfo& imageInfo = tex->ImageInfoAt(target, level);
         sizeMayChange = width != imageInfo.Width() ||
                         height != imageInfo.Height() ||
                         format != imageInfo.Format() ||
@@ -3671,17 +3754,17 @@ WebGLContext::TexImage2D_base(GLenum tar
         }
     }
 
     uint32_t dstTexelSize = 0;
     if (!ValidateTexFormatAndType(format, type, jsArrayType, &dstTexelSize, "texImage2D"))
         return;
 
     WebGLTexelFormat dstFormat = GetWebGLTexelFormat(format, type);
-    WebGLTexelFormat actualSrcFormat = srcFormat == WebGLTexelConversions::Auto ? dstFormat : srcFormat;
+    WebGLTexelFormat actualSrcFormat = srcFormat == WebGLTexelFormat::Auto ? dstFormat : srcFormat;
 
     uint32_t srcTexelSize = WebGLTexelConversions::TexelBytesForFormat(actualSrcFormat);
 
     CheckedUint32 checked_neededByteLength = 
         GetImageSize(height, width, srcTexelSize, mPixelStoreUnpackAlignment);
 
     CheckedUint32 checked_plainRowSize = CheckedUint32(width) * srcTexelSize;
 
@@ -3705,16 +3788,18 @@ WebGLContext::TexImage2D_base(GLenum tar
     MakeContextCurrent();
 
     // Handle ES2 and GL differences in floating point internal formats.  Note that
     // format == internalformat, as checked above and as required by ES.
     internalformat = InternalFormatForFormatAndType(format, type, gl->IsGLES2());
 
     GLenum error = LOCAL_GL_NO_ERROR;
 
+    WebGLImageDataStatus imageInfoStatusIfSuccess = WebGLImageDataStatus::NoImageData;
+
     if (byteLength) {
         size_t srcStride = srcStrideOrZero ? srcStrideOrZero : checked_alignedRowSize.value();
 
         size_t dstPlainRowSize = dstTexelSize * width;
         size_t unpackAlignment = mPixelStoreUnpackAlignment;
         size_t dstStride = ((dstPlainRowSize + unpackAlignment-1) / unpackAlignment) * unpackAlignment;
 
         if (actualSrcFormat == dstFormat &&
@@ -3732,94 +3817,34 @@ WebGLContext::TexImage2D_base(GLenum tar
             nsAutoArrayPtr<uint8_t> convertedData(new uint8_t[convertedDataSize]);
             ConvertImage(width, height, srcStride, dstStride,
                         static_cast<uint8_t*>(data), convertedData,
                         actualSrcFormat, srcPremultiplied,
                         dstFormat, mPixelStorePremultiplyAlpha, dstTexelSize);
             error = CheckedTexImage2D(target, level, internalformat,
                                       width, height, border, format, type, convertedData);
         }
+        imageInfoStatusIfSuccess = WebGLImageDataStatus::InitializedImageData;
     } else {
-        if (isDepthTexture && !gl->IsSupported(GLFeature::depth_texture)) {
-            // There's only one way that we can we supporting depth textures without
-            // supporting the regular depth_texture feature set: that's
-            // with ANGLE_depth_texture.
-
-            // It should be impossible to get here without ANGLE_depth_texture support
-            MOZ_ASSERT(gl->IsExtensionSupported(GLContext::ANGLE_depth_texture));
-            // It should be impossible to get here with a target other than TEXTURE_2D,
-            // a nonzero level, or non-null data
-            MOZ_ASSERT(target == LOCAL_GL_TEXTURE_2D && level == 0 && data == nullptr);
-
-            // We start by calling texImage2D with null data, giving us an uninitialized texture,
-            // which is all it can give us in this case.
-            error = CheckedTexImage2D(LOCAL_GL_TEXTURE_2D, 0, internalformat, width, height,
-                                      border, format, type, nullptr);
-
-            // We then proceed to initializing the texture by assembling a FBO.
-            // We make it a color-less FBO, which isn't supported everywhere, but we should be
-            // fine because we only need this to be successful on ANGLE which is said to support
-            // that. Still, we want to gracefully handle failure in case the FBO is incomplete.
-
-            bool success = false;
-            GLuint fb = 0;
-
-            // dummy do {...} while to be able to break
-            do {
-                gl->fGenFramebuffers(1, &fb);
-                if (!fb)
-                    break;
-
-                ScopedBindFramebuffer autoBindFB(gl, fb);
-
-                gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
-                                          LOCAL_GL_DEPTH_ATTACHMENT,
-                                          LOCAL_GL_TEXTURE_2D,
-                                          tex->GLName(),
-                                          0);
-                if (format == LOCAL_GL_DEPTH_STENCIL) {
-                    gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
-                                              LOCAL_GL_STENCIL_ATTACHMENT,
-                                              LOCAL_GL_TEXTURE_2D,
-                                              tex->GLName(),
-                                              0);
-                }
-                if (gl->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER) != LOCAL_GL_FRAMEBUFFER_COMPLETE)
-                    break;
-
-                gl->ClearSafely();
-                success = true;
-            } while(false);
-
-            gl->fDeleteFramebuffers(1, &fb);
-
-            if (!success) {
-                return ErrorOutOfMemory("texImage2D: sorry, ran out of ways to initialize a depth texture.");
-            }
-        } else {
-            // We need some zero pages, because GL doesn't guarantee the
-            // contents of a texture allocated with nullptr data.
-            // Hopefully calloc will just mmap zero pages here.
-            void *tempZeroData = calloc(1, bytesNeeded);
-            if (!tempZeroData)
-                return ErrorOutOfMemory("texImage2D: could not allocate %d bytes (for zero fill)", bytesNeeded);
-
-            error = CheckedTexImage2D(target, level, internalformat,
-                                      width, height, border, format, type, tempZeroData);
-
-            free(tempZeroData);
-        }
+        error = CheckedTexImage2D(target, level, internalformat,
+                                  width, height, border, format, type, nullptr);
+        imageInfoStatusIfSuccess = WebGLImageDataStatus::UninitializedImageData;
     }
 
     if (error) {
         GenerateWarning("texImage2D generated error %s", ErrorName(error));
         return;
     }
 
-    tex->SetImageInfo(target, level, width, height, format, type);
+    // in all of the code paths above, we should have either initialized data,
+    // or allocated data and left it uninitialized, but in any case we shouldn't
+    // have NoImageData at this point.
+    MOZ_ASSERT(imageInfoStatusIfSuccess != WebGLImageDataStatus::NoImageData);
+
+    tex->SetImageInfo(target, level, width, height, format, type, imageInfoStatusIfSuccess);
 
     ReattachTextureToAnyFramebufferToWorkAroundBugs(tex, level);
 }
 
 void
 WebGLContext::TexImage2D(GLenum target, GLint level,
                          GLenum internalformat, GLsizei width,
                          GLsizei height, GLint border, GLenum format,
@@ -3827,17 +3852,17 @@ WebGLContext::TexImage2D(GLenum target, 
 {
     if (IsContextLost())
         return;
 
     return TexImage2D_base(target, level, internalformat, width, height, 0, border, format, type,
                            pixels.IsNull() ? 0 : pixels.Value().Data(),
                            pixels.IsNull() ? 0 : pixels.Value().Length(),
                            pixels.IsNull() ? -1 : (int)JS_GetArrayBufferViewType(pixels.Value().Obj()),
-                           WebGLTexelConversions::Auto, false);
+                           WebGLTexelFormat::Auto, false);
 }
 
 void
 WebGLContext::TexImage2D(GLenum target, GLint level,
                          GLenum internalformat, GLenum format,
                          GLenum type, ImageData* pixels, ErrorResult& rv)
 {
     if (IsContextLost())
@@ -3847,17 +3872,17 @@ WebGLContext::TexImage2D(GLenum target, 
         // Spec says to generate an INVALID_VALUE error
         return ErrorInvalidValue("texImage2D: null ImageData");
     }
     
     Uint8ClampedArray arr(pixels->GetDataObject());
     return TexImage2D_base(target, level, internalformat, pixels->Width(),
                            pixels->Height(), 4*pixels->Width(), 0,
                            format, type, arr.Data(), arr.Length(), -1,
-                           WebGLTexelConversions::RGBA8, false);
+                           WebGLTexelFormat::RGBA8, false);
 }
 
 
 void
 WebGLContext::TexSubImage2D_base(GLenum target, GLint level,
                                  GLint xoffset, GLint yoffset,
                                  GLsizei width, GLsizei height, GLsizei srcStrideOrZero,
                                  GLenum format, GLenum type,
@@ -3893,17 +3918,17 @@ WebGLContext::TexSubImage2D_base(GLenum 
         return ErrorInvalidOperation("texSubImage2D: format");
     }
 
     uint32_t dstTexelSize = 0;
     if (!ValidateTexFormatAndType(format, type, jsArrayType, &dstTexelSize, "texSubImage2D"))
         return;
 
     WebGLTexelFormat dstFormat = GetWebGLTexelFormat(format, type);
-    WebGLTexelFormat actualSrcFormat = srcFormat == WebGLTexelConversions::Auto ? dstFormat : srcFormat;
+    WebGLTexelFormat actualSrcFormat = srcFormat == WebGLTexelFormat::Auto ? dstFormat : srcFormat;
 
     uint32_t srcTexelSize = WebGLTexelConversions::TexelBytesForFormat(actualSrcFormat);
 
     if (width == 0 || height == 0)
         return; // ES 2.0 says it has no effect, we better return right now
 
     CheckedUint32 checked_neededByteLength = 
         GetImageSize(height, width, srcTexelSize, mPixelStoreUnpackAlignment);
@@ -3932,16 +3957,20 @@ WebGLContext::TexSubImage2D_base(GLenum 
     const WebGLTexture::ImageInfo &imageInfo = tex->ImageInfoAt(target, level);
     if (!CanvasUtils::CheckSaneSubrectSize(xoffset, yoffset, width, height, imageInfo.Width(), imageInfo.Height()))
         return ErrorInvalidValue("texSubImage2D: subtexture rectangle out of bounds");
     
     // Require the format and type in texSubImage2D to match that of the existing texture as created by texImage2D
     if (imageInfo.Format() != format || imageInfo.Type() != type)
         return ErrorInvalidOperation("texSubImage2D: format or type doesn't match the existing texture");
 
+    if (imageInfo.HasUninitializedImageData()) {
+        tex->DoDeferredImageInitialization(target, level);
+    }
+
     MakeContextCurrent();
 
     size_t srcStride = srcStrideOrZero ? srcStrideOrZero : checked_alignedRowSize.value();
 
     size_t dstPlainRowSize = dstTexelSize * width;
     // There are checks above to ensure that this won't overflow.
     size_t dstStride = RoundedToNextMultipleOf(dstPlainRowSize, mPixelStoreUnpackAlignment).value();
 
@@ -3979,17 +4008,17 @@ WebGLContext::TexSubImage2D(GLenum targe
 
     if (pixels.IsNull())
         return ErrorInvalidValue("texSubImage2D: pixels must not be null!");
 
     return TexSubImage2D_base(target, level, xoffset, yoffset,
                               width, height, 0, format, type,
                               pixels.Value().Data(), pixels.Value().Length(),
                               JS_GetArrayBufferViewType(pixels.Value().Obj()),
-                              WebGLTexelConversions::Auto, false);
+                              WebGLTexelFormat::Auto, false);
 }
 
 void
 WebGLContext::TexSubImage2D(GLenum target, GLint level,
                             GLint xoffset, GLint yoffset,
                             GLenum format, GLenum type, ImageData* pixels,
                             ErrorResult& rv)
 {
@@ -4000,17 +4029,17 @@ WebGLContext::TexSubImage2D(GLenum targe
         return ErrorInvalidValue("texSubImage2D: pixels must not be null!");
 
     Uint8ClampedArray arr(pixels->GetDataObject());
     return TexSubImage2D_base(target, level, xoffset, yoffset,
                               pixels->Width(), pixels->Height(),
                               4*pixels->Width(), format, type,
                               arr.Data(), arr.Length(),
                               -1,
-                              WebGLTexelConversions::RGBA8, false);
+                              WebGLTexelFormat::RGBA8, false);
 }
 
 bool
 WebGLContext::LoseContext()
 {
     if (IsContextLost())
         return false;
 
@@ -4104,76 +4133,76 @@ BaseTypeAndSizeFromUniformType(GLenum uT
 
 WebGLTexelFormat mozilla::GetWebGLTexelFormat(GLenum format, GLenum type)
 {
     //
     // WEBGL_depth_texture
     if (format == LOCAL_GL_DEPTH_COMPONENT) {
         switch (type) {
             case LOCAL_GL_UNSIGNED_SHORT:
-                return WebGLTexelConversions::D16;
+                return WebGLTexelFormat::D16;
             case LOCAL_GL_UNSIGNED_INT:
-                return WebGLTexelConversions::D32;
+                return WebGLTexelFormat::D32;
             default:
                 MOZ_CRASH("Invalid WebGL texture format/type?");
         }
     } else if (format == LOCAL_GL_DEPTH_STENCIL) {
         switch (type) {
             case LOCAL_GL_UNSIGNED_INT_24_8_EXT:
-                return WebGLTexelConversions::D24S8;
+                return WebGLTexelFormat::D24S8;
             default:
                 MOZ_CRASH("Invalid WebGL texture format/type?");
         }
     }
 
 
     if (type == LOCAL_GL_UNSIGNED_BYTE) {
         switch (format) {
             case LOCAL_GL_RGBA:
-                return WebGLTexelConversions::RGBA8;
+                return WebGLTexelFormat::RGBA8;
             case LOCAL_GL_RGB:
-                return WebGLTexelConversions::RGB8;
+                return WebGLTexelFormat::RGB8;
             case LOCAL_GL_ALPHA:
-                return WebGLTexelConversions::A8;
+                return WebGLTexelFormat::A8;
             case LOCAL_GL_LUMINANCE:
-                return WebGLTexelConversions::R8;
+                return WebGLTexelFormat::R8;
             case LOCAL_GL_LUMINANCE_ALPHA:
-                return WebGLTexelConversions::RA8;
+                return WebGLTexelFormat::RA8;
             default:
-                NS_ABORT_IF_FALSE(false, "Coding mistake?! Should never reach this point.");
-                return WebGLTexelConversions::BadFormat;
+                MOZ_ASSERT(false, "Coding mistake?! Should never reach this point.");
+                return WebGLTexelFormat::BadFormat;
         }
     } else if (type == LOCAL_GL_FLOAT) {
         // OES_texture_float
         switch (format) {
             case LOCAL_GL_RGBA:
-                return WebGLTexelConversions::RGBA32F;
+                return WebGLTexelFormat::RGBA32F;
             case LOCAL_GL_RGB:
-                return WebGLTexelConversions::RGB32F;
+                return WebGLTexelFormat::RGB32F;
             case LOCAL_GL_ALPHA:
-                return WebGLTexelConversions::A32F;
+                return WebGLTexelFormat::A32F;
             case LOCAL_GL_LUMINANCE:
-                return WebGLTexelConversions::R32F;
+                return WebGLTexelFormat::R32F;
             case LOCAL_GL_LUMINANCE_ALPHA:
-                return WebGLTexelConversions::RA32F;
+                return WebGLTexelFormat::RA32F;
             default:
-                NS_ABORT_IF_FALSE(false, "Coding mistake?! Should never reach this point.");
-                return WebGLTexelConversions::BadFormat;
+                MOZ_ASSERT(false, "Coding mistake?! Should never reach this point.");
+                return WebGLTexelFormat::BadFormat;
         }
     } else {
         switch (type) {
             case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
-                return WebGLTexelConversions::RGBA4444;
+                return WebGLTexelFormat::RGBA4444;
             case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
-                return WebGLTexelConversions::RGBA5551;
+                return WebGLTexelFormat::RGBA5551;
             case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
-                return WebGLTexelConversions::RGB565;
+                return WebGLTexelFormat::RGB565;
             default:
-                NS_ABORT_IF_FALSE(false, "Coding mistake?! Should never reach this point.");
-                return WebGLTexelConversions::BadFormat;
+                MOZ_ASSERT(false, "Coding mistake?! Should never reach this point.");
+                return WebGLTexelFormat::BadFormat;
         }
     }
 }
 
 GLenum
 InternalFormatForFormatAndType(GLenum format, GLenum type, bool isGLES2)
 {
     // ES2 requires that format == internalformat; floating-point is
--- a/content/canvas/src/WebGLContextUtils.cpp
+++ b/content/canvas/src/WebGLContextUtils.cpp
@@ -184,17 +184,17 @@ WebGLContext::ErrorName(GLenum error)
             return "INVALID_VALUE";
         case LOCAL_GL_OUT_OF_MEMORY:
             return "OUT_OF_MEMORY";
         case LOCAL_GL_INVALID_FRAMEBUFFER_OPERATION:
             return "INVALID_FRAMEBUFFER_OPERATION";
         case LOCAL_GL_NO_ERROR:
             return "NO_ERROR";
         default:
-            NS_ABORT();
+            MOZ_ASSERT(false);
             return "[unknown WebGL error!]";
     }
 }
 
 bool
 WebGLContext::IsTextureFormatCompressed(GLenum format)
 {
     switch(format) {
@@ -216,18 +216,17 @@ WebGLContext::IsTextureFormatCompressed(
         case LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA:
         case LOCAL_GL_COMPRESSED_RGB_PVRTC_4BPPV1:
         case LOCAL_GL_COMPRESSED_RGB_PVRTC_2BPPV1:
         case LOCAL_GL_COMPRESSED_RGBA_PVRTC_4BPPV1:
         case LOCAL_GL_COMPRESSED_RGBA_PVRTC_2BPPV1:
             return true;
     }
 
-    NS_NOTREACHED("Invalid WebGL texture format?");
-    NS_ABORT();
+    MOZ_ASSERT(false, "Invalid WebGL texture format?");
     return false;
 }
 
 void
 WebGLContext::UpdateWebGLErrorAndClearGLError(GLenum *currentGLError)
 {
     // get and clear GL error in ALL cases
     GLenum error = gl->GetAndClearError();
--- a/content/canvas/src/WebGLContextValidate.cpp
+++ b/content/canvas/src/WebGLContextValidate.cpp
@@ -60,17 +60,17 @@ WebGLProgram::UpdateInfo()
 
     for (int i = 0; i < attribCount; ++i) {
         GLint attrnamelen;
         GLint attrsize;
         GLenum attrtype;
         mContext->gl->fGetActiveAttrib(mGLName, i, mAttribMaxNameLength, &attrnamelen, &attrsize, &attrtype, nameBuf);
         if (attrnamelen > 0) {
             GLint loc = mContext->gl->fGetAttribLocation(mGLName, nameBuf);
-            NS_ABORT_IF_FALSE(loc >= 0, "major oops in managing the attributes of a WebGL program");
+            MOZ_ASSERT(loc >= 0, "major oops in managing the attributes of a WebGL program");
             if (loc < mContext->mGLMaxVertexAttribs) {
                 mAttribsInUse[loc] = true;
             } else {
                 mContext->GenerateWarning("program exceeds MAX_VERTEX_ATTRIBS");
                 return false;
             }
         }
     }
@@ -486,17 +486,17 @@ uint32_t WebGLContext::GetBitsPerTexel(G
         }
     } else if (type == LOCAL_GL_UNSIGNED_SHORT_4_4_4_4 ||
                type == LOCAL_GL_UNSIGNED_SHORT_5_5_5_1 ||
                type == LOCAL_GL_UNSIGNED_SHORT_5_6_5)
     {
         return 16;
     }
 
-    NS_ABORT();
+    MOZ_ASSERT(false);
     return 0;
 }
 
 bool WebGLContext::ValidateTexFormatAndType(GLenum format, GLenum type, int jsArrayType,
                                               uint32_t *texelSize, const char *info)
 {
     if (IsExtensionEnabled(WEBGL_depth_texture)) {
         if (format == LOCAL_GL_DEPTH_COMPONENT) {
@@ -761,17 +761,17 @@ WebGLContext::ValidateUniformSetter(cons
     if (!ValidateUniformLocation(name, location_object))
         return false;
     location = location_object->Location();
     return true;
 }
 
 bool WebGLContext::ValidateAttribIndex(GLuint index, const char *info)
 {
-    return mBoundVertexArray->EnsureAttribIndex(index, info);
+    return mBoundVertexArray->EnsureAttrib(index, info);
 }
 
 bool WebGLContext::ValidateStencilParamsForDrawCall()
 {
   const char *msg = "%s set different front and back stencil %s. Drawing in this configuration is not allowed.";
   if (mStencilRefFront != mStencilRefBack) {
       ErrorInvalidOperation(msg, "stencilFuncSeparate", "reference values");
       return false;
@@ -993,13 +993,13 @@ WebGLContext::InitAndValidateGL()
         = mozilla::services::GetObserverService();
     if (observerService) {
         observerService->AddObserver(mMemoryPressureObserver,
                                      "memory-pressure",
                                      false);
     }
 
     mDefaultVertexArray = new WebGLVertexArray(this);
-    mDefaultVertexArray->mAttribBuffers.SetLength(mGLMaxVertexAttribs);
+    mDefaultVertexArray->mAttribs.SetLength(mGLMaxVertexAttribs);
     mBoundVertexArray = mDefaultVertexArray;
 
     return true;
 }
--- a/content/canvas/src/WebGLContextVertices.cpp
+++ b/content/canvas/src/WebGLContextVertices.cpp
@@ -191,17 +191,18 @@ WebGLContext::EnableVertexAttribArray(GL
 
     if (!ValidateAttribIndex(index, "enableVertexAttribArray"))
         return;
 
     MakeContextCurrent();
     InvalidateBufferFetching();
 
     gl->fEnableVertexAttribArray(index);
-    mBoundVertexArray->mAttribBuffers[index].enabled = true;
+    MOZ_ASSERT(mBoundVertexArray->HasAttrib(index)); // should have been validated earlier
+    mBoundVertexArray->mAttribs[index].enabled = true;
 }
 
 void
 WebGLContext::DisableVertexAttribArray(GLuint index)
 {
     if (IsContextLost())
         return;
 
@@ -209,49 +210,50 @@ WebGLContext::DisableVertexAttribArray(G
         return;
 
     MakeContextCurrent();
     InvalidateBufferFetching();
 
     if (index || gl->IsGLES2())
         gl->fDisableVertexAttribArray(index);
 
-    mBoundVertexArray->mAttribBuffers[index].enabled = false;
+    MOZ_ASSERT(mBoundVertexArray->HasAttrib(index)); // should have been validated earlier
+    mBoundVertexArray->mAttribs[index].enabled = false;
 }
 
 
 JS::Value
 WebGLContext::GetVertexAttrib(JSContext* cx, GLuint index, GLenum pname,
                               ErrorResult& rv)
 {
     if (IsContextLost())
         return JS::NullValue();
 
-    if (!mBoundVertexArray->EnsureAttribIndex(index, "getVertexAttrib"))
+    if (!ValidateAttribIndex(index, "getVertexAttrib"))
         return JS::NullValue();
 
     MakeContextCurrent();
 
     switch (pname) {
         case LOCAL_GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
         {
-            return WebGLObjectAsJSValue(cx, mBoundVertexArray->mAttribBuffers[index].buf.get(), rv);
+            return WebGLObjectAsJSValue(cx, mBoundVertexArray->mAttribs[index].buf.get(), rv);
         }
 
         case LOCAL_GL_VERTEX_ATTRIB_ARRAY_STRIDE:
         {
-            return JS::Int32Value(mBoundVertexArray->mAttribBuffers[index].stride);
+            return JS::Int32Value(mBoundVertexArray->mAttribs[index].stride);
         }
 
         case LOCAL_GL_VERTEX_ATTRIB_ARRAY_SIZE:
         {
             if (!ValidateAttribIndex(index, "getVertexAttrib"))
                 return JS::NullValue();
 
-            if (!mBoundVertexArray->mAttribBuffers[index].enabled)
+            if (!mBoundVertexArray->mAttribs[index].enabled)
                 return JS::Int32Value(4);
 
             // Don't break; fall through.
         }
         case LOCAL_GL_VERTEX_ATTRIB_ARRAY_TYPE:
         {
             GLint i = 0;
             gl->fGetVertexAttribiv(index, pname, &i);
@@ -260,17 +262,17 @@ WebGLContext::GetVertexAttrib(JSContext*
             MOZ_ASSERT(pname == LOCAL_GL_VERTEX_ATTRIB_ARRAY_TYPE);
             return JS::NumberValue(uint32_t(i));
         }
 
         case LOCAL_GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
         {
             if (IsExtensionEnabled(ANGLE_instanced_arrays))
             {
-                return JS::Int32Value(mBoundVertexArray->mAttribBuffers[index].divisor);
+                return JS::Int32Value(mBoundVertexArray->mAttribs[index].divisor);
             }
             break;
         }
 
         case LOCAL_GL_CURRENT_VERTEX_ATTRIB:
         {
             GLfloat vec[4] = {0, 0, 0, 1};
             if (index) {
@@ -285,22 +287,22 @@ WebGLContext::GetVertexAttrib(JSContext*
             if (!obj) {
                 rv.Throw(NS_ERROR_OUT_OF_MEMORY);
             }
             return JS::ObjectOrNullValue(obj);
         }
 
         case LOCAL_GL_VERTEX_ATTRIB_ARRAY_ENABLED:
         {
-            return JS::BooleanValue(mBoundVertexArray->mAttribBuffers[index].enabled);
+            return JS::BooleanValue(mBoundVertexArray->mAttribs[index].enabled);
         }
 
         case LOCAL_GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
         {
-            return JS::BooleanValue(mBoundVertexArray->mAttribBuffers[index].normalized);
+            return JS::BooleanValue(mBoundVertexArray->mAttribs[index].normalized);
         }
 
         default:
             break;
     }
 
     ErrorInvalidEnumInfo("getVertexAttrib: parameter", pname);
 
@@ -316,17 +318,17 @@ WebGLContext::GetVertexAttribOffset(GLui
     if (!ValidateAttribIndex(index, "getVertexAttribOffset"))
         return 0;
 
     if (pname != LOCAL_GL_VERTEX_ATTRIB_ARRAY_POINTER) {
         ErrorInvalidEnum("getVertexAttribOffset: bad parameter");
         return 0;
     }
 
-    return mBoundVertexArray->mAttribBuffers[index].byteOffset;
+    return mBoundVertexArray->mAttribs[index].byteOffset;
 }
 
 void
 WebGLContext::VertexAttribPointer(GLuint index, GLint size, GLenum type,
                                   WebGLboolean normalized, GLsizei stride,
                                   WebGLintptr byteOffset)
 {
     if (IsContextLost())
@@ -351,17 +353,17 @@ WebGLContext::VertexAttribPointer(GLuint
             break;
         default:
             return ErrorInvalidEnumInfo("vertexAttribPointer: type", type);
     }
 
     // requiredAlignment should always be a power of two.
     GLsizei requiredAlignmentMask = requiredAlignment - 1;
 
-    if ( !mBoundVertexArray->EnsureAttribIndex(index, "vertexAttribPointer") ) {
+    if (!ValidateAttribIndex(index, "vertexAttribPointer")) {
         return;
     }
 
     if (size < 1 || size > 4)
         return ErrorInvalidValue("vertexAttribPointer: invalid element size");
 
     if (stride < 0 || stride > 255) // see WebGL spec section 6.6 "Vertex Attribute Data Stride"
         return ErrorInvalidValue("vertexAttribPointer: negative or too large stride");
@@ -382,17 +384,17 @@ WebGLContext::VertexAttribPointer(GLuint
 
     InvalidateBufferFetching();
 
     /* XXX make work with bufferSubData & heterogeneous types
      if (type != mBoundArrayBuffer->GLType())
      return ErrorInvalidOperation("vertexAttribPointer: type must match bound VBO type: %d != %d", type, mBoundArrayBuffer->GLType());
      */
 
-    WebGLVertexAttribData &vd = mBoundVertexArray->mAttribBuffers[index];
+    WebGLVertexAttribData &vd = mBoundVertexArray->mAttribs[index];
 
     vd.buf = mBoundArrayBuffer;
     vd.stride = stride;
     vd.size = size;
     vd.byteOffset = byteOffset;
     vd.type = type;
     vd.normalized = normalized;
 
@@ -404,21 +406,21 @@ WebGLContext::VertexAttribPointer(GLuint
 }
 
 void
 WebGLContext::VertexAttribDivisor(GLuint index, GLuint divisor)
 {
     if (IsContextLost())
         return;
 
-    if ( !mBoundVertexArray->EnsureAttribIndex(index, "vertexAttribDivisor") ) {
+    if (!ValidateAttribIndex(index, "vertexAttribDivisor")) {
         return;
     }
 
-    WebGLVertexAttribData& vd = mBoundVertexArray->mAttribBuffers[index];
+    WebGLVertexAttribData& vd = mBoundVertexArray->mAttribs[index];
     vd.divisor = divisor;
 
     InvalidateBufferFetching();
 
     MakeContextCurrent();
 
     gl->fVertexAttribDivisor(index, divisor);
 }
@@ -493,17 +495,17 @@ bool WebGLContext::DrawArrays_check(GLin
     if (uint32_t(primcount) > mMaxFetchedInstances) {
         ErrorInvalidOperation("%s: bound instance attribute buffers do not have sufficient size for given primcount", info);
         return false;
     }
 
     MakeContextCurrent();
 
     if (mBoundFramebuffer) {
-        if (!mBoundFramebuffer->CheckAndInitializeRenderbuffers()) {
+        if (!mBoundFramebuffer->CheckAndInitializeAttachments()) {
             ErrorInvalidFramebufferOperation("%s: incomplete framebuffer", info);
             return false;
         }
     }
 
     if (!DoFakeVertexAttrib0(checked_firstPlusCount.value())) {
         return false;
     }
@@ -650,17 +652,17 @@ WebGLContext::DrawElements_check(GLsizei
     if (uint32_t(primcount) > mMaxFetchedInstances) {
         ErrorInvalidOperation("%s: bound instance attribute buffers do not have sufficient size for given primcount", info);
         return false;
     }
 
     MakeContextCurrent();
 
     if (mBoundFramebuffer) {
-        if (!mBoundFramebuffer->CheckAndInitializeRenderbuffers()) {
+        if (!mBoundFramebuffer->CheckAndInitializeAttachments()) {
             ErrorInvalidFramebufferOperation("%s: incomplete framebuffer", info);
             return false;
         }
     }
 
     if (!DoFakeVertexAttrib0(mMaxFetchedVertices)) {
         return false;
     }
@@ -751,20 +753,20 @@ WebGLContext::ValidateBufferFetching(con
 
     if (mBufferFetchingIsVerified) {
         return true;
     }
 
     bool hasPerVertex = false;
     uint32_t maxVertices = UINT32_MAX;
     uint32_t maxInstances = UINT32_MAX;
-    uint32_t attribs = mBoundVertexArray->mAttribBuffers.Length();
+    uint32_t attribs = mBoundVertexArray->mAttribs.Length();
 
     for (uint32_t i = 0; i < attribs; ++i) {
-        const WebGLVertexAttribData& vd = mBoundVertexArray->mAttribBuffers[i];
+        const WebGLVertexAttribData& vd = mBoundVertexArray->mAttribs[i];
 
         // If the attrib array isn't enabled, there's nothing to check;
         // it's a static value.
         if (!vd.enabled)
             continue;
 
         if (vd.buf == nullptr) {
             ErrorInvalidOperation("%s: no VBO bound to enabled vertex attrib index %d!", info, i);
--- a/content/canvas/src/WebGLFramebuffer.cpp
+++ b/content/canvas/src/WebGLFramebuffer.cpp
@@ -46,34 +46,49 @@ WebGLFramebuffer::Attachment::IsDeleteRe
 
 bool
 WebGLFramebuffer::Attachment::HasAlpha() const {
     GLenum format = 0;
     if (Texture() && Texture()->HasImageInfoAt(mTexImageTarget, mTexImageLevel))
         format = Texture()->ImageInfoAt(mTexImageTarget, mTexImageLevel).Format();
     else if (Renderbuffer())
         format = Renderbuffer()->InternalFormat();
-    return format == LOCAL_GL_RGBA ||
-           format == LOCAL_GL_LUMINANCE_ALPHA ||
-           format == LOCAL_GL_ALPHA ||
-           format == LOCAL_GL_RGBA4 ||
-           format == LOCAL_GL_RGB5_A1;
+    return FormatHasAlpha(format);
 }
 
 void
 WebGLFramebuffer::Attachment::SetTexImage(WebGLTexture *tex, GLenum target, GLint level) {
     mTexturePtr = tex;
     mRenderbufferPtr = nullptr;
     mTexImageTarget = target;
     mTexImageLevel = level;
 }
 
 bool
-WebGLFramebuffer::Attachment::HasUninitializedRenderbuffer() const {
-    return mRenderbufferPtr && !mRenderbufferPtr->Initialized();
+WebGLFramebuffer::Attachment::HasUninitializedImageData() const {
+    if (mRenderbufferPtr) {
+        return mRenderbufferPtr->HasUninitializedImageData();
+    } else if (mTexturePtr) {
+        if (!mTexturePtr->HasImageInfoAt(mTexImageTarget, mTexImageLevel))
+            return false;
+        return mTexturePtr->ImageInfoAt(mTexImageTarget, mTexImageLevel).HasUninitializedImageData();
+    } else {
+        return false;
+    }
+}
+
+void
+WebGLFramebuffer::Attachment::SetImageDataStatus(WebGLImageDataStatus newStatus) {
+    if (mRenderbufferPtr) {
+        mRenderbufferPtr->SetImageDataStatus(newStatus);
+    } else if (mTexturePtr) {
+        mTexturePtr->SetImageDataStatus(mTexImageTarget, mTexImageLevel, newStatus);
+    } else {
+        MOZ_ASSERT(false); // should not get here, worth crashing a debug build.
+    }
 }
 
 const WebGLRectangleObject*
 WebGLFramebuffer::Attachment::RectangleObject() const {
     if (Texture() && Texture()->HasImageInfoAt(mTexImageTarget, mTexImageLevel))
         return &Texture()->ImageInfoAt(mTexImageTarget, mTexImageLevel);
     else if (Renderbuffer())
         return Renderbuffer();
@@ -138,17 +153,17 @@ WebGLFramebuffer::Attachment::IsComplete
                  mAttachmentPoint < GLenum(LOCAL_GL_COLOR_ATTACHMENT0 + WebGLContext::sMaxColorAttachments)) {
             return (format == LOCAL_GL_RGB565 ||
                     format == LOCAL_GL_RGB5_A1 ||
                     format == LOCAL_GL_RGBA4);
         }
         MOZ_CRASH("Invalid WebGL attachment poin?");
     }
 
-    NS_ABORT(); // should never get there
+    MOZ_ASSERT(false); // should never get there
     return false;
 }
 
 void
 WebGLFramebuffer::Attachment::FinalizeAttachment(GLenum attachmentLoc) const {
     if (Texture()) {
         GLContext* gl = Texture()->Context()->gl;
         if (attachmentLoc == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
@@ -310,24 +325,24 @@ WebGLFramebuffer::GetAttachment(GLenum a
     if (attachment == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT)
         return mDepthStencilAttachment;
     if (attachment == LOCAL_GL_DEPTH_ATTACHMENT)
         return mDepthAttachment;
     if (attachment == LOCAL_GL_STENCIL_ATTACHMENT)
         return mStencilAttachment;
 
     if (!CheckColorAttachementNumber(attachment, "getAttachment")) {
-        NS_ABORT();
+        MOZ_ASSERT(false);
         return mColorAttachments[0];
     }
 
     uint32_t colorAttachmentId = uint32_t(attachment - LOCAL_GL_COLOR_ATTACHMENT0);
 
     if (colorAttachmentId >= mColorAttachments.Length()) {
-        NS_ABORT();
+        MOZ_ASSERT(false);
         return mColorAttachments[0];
     }
 
     return mColorAttachments[colorAttachmentId];
 }
 
 void
 WebGLFramebuffer::DetachTexture(const WebGLTexture *tex) {
@@ -363,17 +378,17 @@ WebGLFramebuffer::DetachRenderbuffer(con
         FramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT, LOCAL_GL_RENDERBUFFER, nullptr);
     if (mStencilAttachment.Renderbuffer() == rb)
         FramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT, LOCAL_GL_RENDERBUFFER, nullptr);
     if (mDepthStencilAttachment.Renderbuffer() == rb)
         FramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_STENCIL_ATTACHMENT, LOCAL_GL_RENDERBUFFER, nullptr);
 }
 
 bool
-WebGLFramebuffer::CheckAndInitializeRenderbuffers()
+WebGLFramebuffer::CheckAndInitializeAttachments()
 {
     MOZ_ASSERT(mContext->mBoundFramebuffer == this);
     // enforce WebGL section 6.5 which is WebGL-specific, hence OpenGL itself would not
     // generate the INVALID_FRAMEBUFFER_OPERATION that we need here
     if (HasDepthStencilConflict())
         return false;
 
     if (HasIncompleteAttachment())
@@ -382,26 +397,26 @@ WebGLFramebuffer::CheckAndInitializeRend
     mContext->MakeContextCurrent();
 
     // Ok, attach our chosen flavor of {DEPTH, STENCIL, DEPTH_STENCIL}.
     FinalizeAttachments();
 
     size_t colorAttachmentCount = size_t(mColorAttachments.Length());
 
     {
-        bool hasUnitializedRenderbuffers = false;
+        bool hasUnitializedAttachments = false;
 
         for (size_t i = 0; i < colorAttachmentCount; i++) {
-            hasUnitializedRenderbuffers |= mColorAttachments[i].HasUninitializedRenderbuffer();
+            hasUnitializedAttachments |= mColorAttachments[i].HasUninitializedImageData();
         }
 
-        if (!hasUnitializedRenderbuffers &&
-            !mDepthAttachment.HasUninitializedRenderbuffer() &&
-            !mStencilAttachment.HasUninitializedRenderbuffer() &&
-            !mDepthStencilAttachment.HasUninitializedRenderbuffer())
+        if (!hasUnitializedAttachments &&
+            !mDepthAttachment.HasUninitializedImageData() &&
+            !mStencilAttachment.HasUninitializedImageData() &&
+            !mDepthStencilAttachment.HasUninitializedImageData())
         {
             return true;
         }
     }
 
     // ensure INVALID_FRAMEBUFFER_OPERATION in zero-size case
     const WebGLRectangleObject *rect = mColorAttachments[0].RectangleObject();
     if (!rect ||
@@ -415,52 +430,49 @@ WebGLFramebuffer::CheckAndInitializeRend
 
     uint32_t mask = 0;
     bool colorAttachmentsMask[WebGLContext::sMaxColorAttachments] = { false };
 
     MOZ_ASSERT( colorAttachmentCount <= WebGLContext::sMaxColorAttachments );
 
     for (size_t i = 0; i < colorAttachmentCount; i++)
     {
-        colorAttachmentsMask[i] = mColorAttachments[i].HasUninitializedRenderbuffer();
+        colorAttachmentsMask[i] = mColorAttachments[i].HasUninitializedImageData();
 
         if (colorAttachmentsMask[i]) {
             mask |= LOCAL_GL_COLOR_BUFFER_BIT;
         }
     }
 
-    if (mDepthAttachment.HasUninitializedRenderbuffer() ||
-        mDepthStencilAttachment.HasUninitializedRenderbuffer())
+    if (mDepthAttachment.HasUninitializedImageData() ||
+        mDepthStencilAttachment.HasUninitializedImageData())
     {
         mask |= LOCAL_GL_DEPTH_BUFFER_BIT;
     }
 
-    if (mStencilAttachment.HasUninitializedRenderbuffer() ||
-        mDepthStencilAttachment.HasUninitializedRenderbuffer())
+    if (mStencilAttachment.HasUninitializedImageData() ||
+        mDepthStencilAttachment.HasUninitializedImageData())
     {
         mask |= LOCAL_GL_STENCIL_BUFFER_BIT;
     }
 
     mContext->ForceClearFramebufferWithDefaultValues(mask, colorAttachmentsMask);
 
     for (size_t i = 0; i < colorAttachmentCount; i++)
     {
-        if (colorAttachmentsMask[i]) {
-            mColorAttachments[i].Renderbuffer()->SetInitialized(true);
-        }
+        if (mColorAttachments[i].HasUninitializedImageData())
+            mColorAttachments[i].SetImageDataStatus(WebGLImageDataStatus::InitializedImageData);
     }
 
-    if (mDepthAttachment.HasUninitializedRenderbuffer())
-        mDepthAttachment.Renderbuffer()->SetInitialized(true);
-
-    if (mStencilAttachment.HasUninitializedRenderbuffer())
-        mStencilAttachment.Renderbuffer()->SetInitialized(true);
-
-    if (mDepthStencilAttachment.HasUninitializedRenderbuffer())
-        mDepthStencilAttachment.Renderbuffer()->SetInitialized(true);
+    if (mDepthAttachment.HasUninitializedImageData())
+        mDepthAttachment.SetImageDataStatus(WebGLImageDataStatus::InitializedImageData);
+    if (mStencilAttachment.HasUninitializedImageData())
+        mStencilAttachment.SetImageDataStatus(WebGLImageDataStatus::InitializedImageData);
+    if (mDepthStencilAttachment.HasUninitializedImageData())
+        mDepthStencilAttachment.SetImageDataStatus(WebGLImageDataStatus::InitializedImageData);
 
     return true;
 }
 
 bool WebGLFramebuffer::CheckColorAttachementNumber(GLenum attachment, const char * functionName) const
 {
     const char* const errorFormating = "%s: attachment: invalid enum value 0x%x";
 
@@ -540,19 +552,16 @@ ImplCycleCollectionTraverse(nsCycleColle
 {
     CycleCollectionNoteChild(aCallback, aField.mTexturePtr.get(),
                              aName, aFlags);
 
     CycleCollectionNoteChild(aCallback, aField.mRenderbufferPtr.get(),
                              aName, aFlags);
 }
 
-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_7(WebGLFramebuffer,
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_4(WebGLFramebuffer,
   mColorAttachments,
-  mDepthAttachment.mTexturePtr,
-  mDepthAttachment.mRenderbufferPtr,
-  mStencilAttachment.mTexturePtr,
-  mStencilAttachment.mRenderbufferPtr,
-  mDepthStencilAttachment.mTexturePtr,
-  mDepthStencilAttachment.mRenderbufferPtr)
+  mDepthAttachment,
+  mStencilAttachment,
+  mDepthStencilAttachment)
 
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLFramebuffer, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WebGLFramebuffer, Release)
--- a/content/canvas/src/WebGLFramebuffer.h
+++ b/content/canvas/src/WebGLFramebuffer.h
@@ -73,17 +73,18 @@ public:
         }
         GLenum TexImageTarget() const {
             return mTexImageTarget;
         }
         GLint TexImageLevel() const {
             return mTexImageLevel;
         }
 
-        bool HasUninitializedRenderbuffer() const;
+        bool HasUninitializedImageData() const;
+        void SetImageDataStatus(WebGLImageDataStatus x);
 
         void Reset() {
             mTexturePtr = nullptr;
             mRenderbufferPtr = nullptr;
         }
 
         const WebGLRectangleObject* RectangleObject() const;
         bool HasSameDimensionsAs(const Attachment& other) const;
@@ -156,17 +157,17 @@ public:
     void FinalizeAttachments() const;
 
     virtual JSObject* WrapObject(JSContext *cx,
                                  JS::Handle<JSObject*> scope) MOZ_OVERRIDE;
 
     NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLFramebuffer)
     NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLFramebuffer)
 
-    bool CheckAndInitializeRenderbuffers();
+    bool CheckAndInitializeAttachments();
 
     bool CheckColorAttachementNumber(GLenum attachment, const char * functionName) const;
 
     GLuint mGLName;
     bool mHasEverBeenBound;
 
     void EnsureColorAttachments(size_t colorAttachmentId);
 
--- a/content/canvas/src/WebGLObjectModel.h
+++ b/content/canvas/src/WebGLObjectModel.h
@@ -97,28 +97,28 @@ class WebGLRefCountedObject
 public:
     enum DeletionStatus { Default, DeleteRequested, Deleted };
 
     WebGLRefCountedObject()
       : mDeletionStatus(Default)
     { }
 
     ~WebGLRefCountedObject() {
-        NS_ABORT_IF_FALSE(mWebGLRefCnt == 0, "destroying WebGL object still referenced by other WebGL objects");
-        NS_ABORT_IF_FALSE(mDeletionStatus == Deleted, "Derived class destructor must call DeleteOnce()");
+        MOZ_ASSERT(mWebGLRefCnt == 0, "destroying WebGL object still referenced by other WebGL objects");
+        MOZ_ASSERT(mDeletionStatus == Deleted, "Derived class destructor must call DeleteOnce()");
     }
 
     // called by WebGLRefPtr
     void WebGLAddRef() {
         ++mWebGLRefCnt;
     }
 
     // called by WebGLRefPtr
     void WebGLRelease() {
-        NS_ABORT_IF_FALSE(mWebGLRefCnt > 0, "releasing WebGL object with WebGL refcnt already zero");
+        MOZ_ASSERT(mWebGLRefCnt > 0, "releasing WebGL object with WebGL refcnt already zero");
         --mWebGLRefCnt;
         MaybeDelete();
     }
 
     // this is the function that WebGL.deleteXxx() functions want to call
     void RequestDelete() {
         if (mDeletionStatus == Default)
             mDeletionStatus = DeleteRequested;
@@ -210,22 +210,22 @@ public:
         return static_cast<T*>(mRawPtr);
     }
 
     operator T*() const {
         return get();
     }
 
     T* operator->() const {
-        NS_ABORT_IF_FALSE(mRawPtr != 0, "You can't dereference a nullptr WebGLRefPtr with operator->()!");
+        MOZ_ASSERT(mRawPtr != 0, "You can't dereference a nullptr WebGLRefPtr with operator->()!");
         return get();
     }
 
     T& operator*() const {
-        NS_ABORT_IF_FALSE(mRawPtr != 0, "You can't dereference a nullptr WebGLRefPtr with operator*()!");
+        MOZ_ASSERT(mRawPtr != 0, "You can't dereference a nullptr WebGLRefPtr with operator*()!");
         return *get();
     }
 
 private:
 
     static void AddRefOnPtr(T* rawPtr) {
         if (rawPtr) {
             rawPtr->WebGLAddRef();
--- a/content/canvas/src/WebGLRenderbuffer.cpp
+++ b/content/canvas/src/WebGLRenderbuffer.cpp
@@ -43,17 +43,17 @@ WebGLRenderbuffer::WrapObject(JSContext 
 
 WebGLRenderbuffer::WebGLRenderbuffer(WebGLContext *context)
     : WebGLContextBoundObject(context)
     , mPrimaryRB(0)
     , mSecondaryRB(0)
     , mInternalFormat(0)
     , mInternalFormatForGL(0)
     , mHasEverBeenBound(false)
-    , mInitialized(false)
+    , mImageDataStatus(WebGLImageDataStatus::NoImageData)
 {
     SetIsDOMBinding();
     mContext->MakeContextCurrent();
 
     mContext->gl->fGenRenderbuffers(1, &mPrimaryRB);
     if (!SupportsDepthStencil(mContext->gl))
         mContext->gl->fGenRenderbuffers(1, &mSecondaryRB);
 
--- a/content/canvas/src/WebGLRenderbuffer.h
+++ b/content/canvas/src/WebGLRenderbuffer.h
@@ -28,18 +28,23 @@ public:
         DeleteOnce();
     }
 
     void Delete();
 
     bool HasEverBeenBound() { return mHasEverBeenBound; }
     void SetHasEverBeenBound(bool x) { mHasEverBeenBound = x; }
 
-    bool Initialized() const { return mInitialized; }
-    void SetInitialized(bool aInitialized) { mInitialized = aInitialized; }
+    bool HasUninitializedImageData() const { return mImageDataStatus == WebGLImageDataStatus::UninitializedImageData; }
+    void SetImageDataStatus(WebGLImageDataStatus x) {
+        // there is no way to go from having image data to not having any
+        MOZ_ASSERT(x != WebGLImageDataStatus::NoImageData ||
+                   mImageDataStatus == WebGLImageDataStatus::NoImageData);
+        mImageDataStatus = x;
+    }
 
     GLenum InternalFormat() const { return mInternalFormat; }
     void SetInternalFormat(GLenum aInternalFormat) { mInternalFormat = aInternalFormat; }
 
     GLenum InternalFormatForGL() const { return mInternalFormatForGL; }
     void SetInternalFormatForGL(GLenum aInternalFormatForGL) { mInternalFormatForGL = aInternalFormatForGL; }
 
     int64_t MemoryUsage() const;
@@ -61,15 +66,15 @@ public:
     NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLRenderbuffer)
 
 protected:
     GLuint mPrimaryRB;
     GLuint mSecondaryRB;
     GLenum mInternalFormat;
     GLenum mInternalFormatForGL;
     bool mHasEverBeenBound;
-    bool mInitialized;
+    WebGLImageDataStatus mImageDataStatus;
 
     friend class WebGLFramebuffer;
 };
 } // namespace mozilla
 
 #endif
--- a/content/canvas/src/WebGLTexelConversions.cpp
+++ b/content/canvas/src/WebGLTexelConversions.cpp
@@ -32,151 +32,151 @@ class WebGLImageConverter
     bool mAlreadyRun;
     bool mSuccess;
 
     /*
      * Returns sizeof(texel)/sizeof(type). The point is that we will iterate over
      * texels with typed pointers and this value will tell us by how much we need
      * to increment these pointers to advance to the next texel.
      */
-    template<int Format>
+    template<MOZ_ENUM_CLASS_INTEGER_TYPE(WebGLTexelFormat) Format>
     static size_t NumElementsPerTexelForFormat() {
         switch (Format) {
-            case R8:
-            case A8:
-            case R32F:
-            case A32F:
-            case RGBA5551:
-            case RGBA4444:
-            case RGB565:
+            case WebGLTexelFormat::R8:
+            case WebGLTexelFormat::A8:
+            case WebGLTexelFormat::R32F:
+            case WebGLTexelFormat::A32F:
+            case WebGLTexelFormat::RGBA5551:
+            case WebGLTexelFormat::RGBA4444:
+            case WebGLTexelFormat::RGB565:
                 return 1;
-            case RA8:
-            case RA32F:
+            case WebGLTexelFormat::RA8:
+            case WebGLTexelFormat::RA32F:
                 return 2;
-            case RGB8:
-            case RGB32F:
+            case WebGLTexelFormat::RGB8:
+            case WebGLTexelFormat::RGB32F:
                 return 3;
-            case RGBA8:
-            case BGRA8:
-            case BGRX8:
-            case RGBA32F:
+            case WebGLTexelFormat::RGBA8:
+            case WebGLTexelFormat::BGRA8:
+            case WebGLTexelFormat::BGRX8:
+            case WebGLTexelFormat::RGBA32F:
                 return 4;
             default:
-                NS_ABORT_IF_FALSE(false, "Unknown texel format. Coding mistake?");
+                MOZ_ASSERT(false, "Unknown texel format. Coding mistake?");
                 return 0;
         }
     }
 
     /*
      * This is the completely format-specific templatized conversion function,
      * that will be instantiated hundreds of times for all different combinations.
      * It is important to avoid generating useless code here. In particular, many
      * instantiations of this function template will never be called, so we try
      * to return immediately in these cases to allow the compiler to avoid generating
      * useless code.
      */
-    template<WebGLTexelFormat SrcFormat,
-             WebGLTexelFormat DstFormat,
-             WebGLTexelPremultiplicationOp PremultiplicationOp>
+    template<MOZ_ENUM_CLASS_INTEGER_TYPE(WebGLTexelFormat) SrcFormat,
+             MOZ_ENUM_CLASS_INTEGER_TYPE(WebGLTexelFormat) DstFormat,
+             MOZ_ENUM_CLASS_INTEGER_TYPE(WebGLTexelPremultiplicationOp) PremultiplicationOp>
     void run()
     {
         // check for never-called cases. We early-return to allow the compiler
         // to avoid generating this code. It would be tempting to abort() instead,
         // as returning early does leave the destination surface with uninitialized
         // data, but that would not allow the compiler to avoid generating this code.
         // So instead, we return early, so Success() will return false, and the caller
         // must check that and abort in that case. See WebGLContext::ConvertImage.
 
         if (SrcFormat == DstFormat &&
-            PremultiplicationOp == NoPremultiplicationOp)
+            PremultiplicationOp == WebGLTexelPremultiplicationOp::None)
         {
             // Should have used a fast exit path earlier, rather than entering this function.
             // we explicitly return here to allow the compiler to avoid generating this code
             return;
         }
 
         // Only textures uploaded from DOM elements or ImageData can allow DstFormat != SrcFormat.
         // DOM elements can only give BGRA8, BGRX8, A8, RGB565 formats. See DOMElementToImageSurface.
         // ImageData is always RGBA8. So all other SrcFormat will always satisfy DstFormat==SrcFormat,
         // so we can avoid compiling the code for all the unreachable paths.
         const bool CanSrcFormatComeFromDOMElementOrImageData
-            = SrcFormat == BGRA8 ||
-              SrcFormat == BGRX8 ||
-              SrcFormat == A8 ||
-              SrcFormat == RGB565 ||
-              SrcFormat == RGBA8;
+            = SrcFormat == WebGLTexelFormat::BGRA8 ||
+              SrcFormat == WebGLTexelFormat::BGRX8 ||
+              SrcFormat == WebGLTexelFormat::A8 ||
+              SrcFormat == WebGLTexelFormat::RGB565 ||
+              SrcFormat == WebGLTexelFormat::RGBA8;
         if (!CanSrcFormatComeFromDOMElementOrImageData &&
             SrcFormat != DstFormat)
         {
             return;
         }
 
         // Likewise, only textures uploaded from DOM elements or ImageData can possibly have to be unpremultiplied.
         if (!CanSrcFormatComeFromDOMElementOrImageData &&
-            PremultiplicationOp == Unpremultiply)
+            PremultiplicationOp == WebGLTexelPremultiplicationOp::Unpremultiply)
         {
             return;
         }
 
         // there is no point in premultiplication/unpremultiplication
         // in the following cases:
         //  - the source format has no alpha
         //  - the source format has no color
         //  - the destination format has no color
         if (!HasAlpha(SrcFormat) ||
             !HasColor(SrcFormat) ||
             !HasColor(DstFormat))
         {
 
-            if (PremultiplicationOp != NoPremultiplicationOp)
+            if (PremultiplicationOp != WebGLTexelPremultiplicationOp::None)
             {
                 return;
             }
         }
 
         // end of early return cases.
 
-        NS_ABORT_IF_FALSE(!mAlreadyRun, "converter should be run only once!");
+        MOZ_ASSERT(!mAlreadyRun, "converter should be run only once!");
         mAlreadyRun = true;
 
         // gather some compile-time meta-data about the formats at hand.
 
         typedef
             typename DataTypeForFormat<SrcFormat>::Type
             SrcType;
         typedef
             typename DataTypeForFormat<DstFormat>::Type
             DstType;
 
-        const int IntermediateSrcFormat
+        const MOZ_ENUM_CLASS_INTEGER_TYPE(WebGLTexelFormat) IntermediateSrcFormat
             = IntermediateFormat<SrcFormat>::Value;
-        const int IntermediateDstFormat
+        const MOZ_ENUM_CLASS_INTEGER_TYPE(WebGLTexelFormat) IntermediateDstFormat
             = IntermediateFormat<DstFormat>::Value;
         typedef
             typename DataTypeForFormat<IntermediateSrcFormat>::Type
             IntermediateSrcType;
         typedef
             typename DataTypeForFormat<IntermediateDstFormat>::Type
             IntermediateDstType;
 
         const size_t NumElementsPerSrcTexel = NumElementsPerTexelForFormat<SrcFormat>();
         const size_t NumElementsPerDstTexel = NumElementsPerTexelForFormat<DstFormat>();
         const size_t MaxElementsPerTexel = 4;
-        NS_ABORT_IF_FALSE(NumElementsPerSrcTexel <= MaxElementsPerTexel, "unhandled format");
-        NS_ABORT_IF_FALSE(NumElementsPerDstTexel <= MaxElementsPerTexel, "unhandled format");
+        MOZ_ASSERT(NumElementsPerSrcTexel <= MaxElementsPerTexel, "unhandled format");
+        MOZ_ASSERT(NumElementsPerDstTexel <= MaxElementsPerTexel, "unhandled format");
 
         // we assume that the strides are multiples of the sizeof of respective types.
         // this assumption will allow us to iterate over src and dst images using typed
         // pointers, e.g. uint8_t* or uint16_t* or float*, instead of untyped pointers.
         // So this assumption allows us to write cleaner and safer code, but it might
         // not be true forever and if it eventually becomes wrong, we'll have to revert
         // to always iterating using uint8_t* pointers regardless of the types at hand.
-        NS_ABORT_IF_FALSE(mSrcStride % sizeof(SrcType) == 0 &&
-                          mDstStride % sizeof(DstType) == 0,
-                          "Unsupported: texture stride is not a multiple of sizeof(type)");
+        MOZ_ASSERT(mSrcStride % sizeof(SrcType) == 0 &&
+                   mDstStride % sizeof(DstType) == 0,
+                   "Unsupported: texture stride is not a multiple of sizeof(type)");
         const ptrdiff_t srcStrideInElements = mSrcStride / sizeof(SrcType);
         const ptrdiff_t dstStrideInElements = mDstStride / sizeof(DstType);
 
         const SrcType *srcRowStart = static_cast<const SrcType*>(mSrcStart);
         DstType *dstRowStart = static_cast<DstType*>(mDstStart);
 
         // the loop performing the texture format conversion
         for (size_t i = 0; i < mHeight; ++i) {
@@ -208,91 +208,92 @@ class WebGLImageConverter
             srcRowStart += srcStrideInElements;
             dstRowStart += dstStrideInElements;
         }
 
         mSuccess = true;
         return;
     }
 
-    template<WebGLTexelFormat SrcFormat, WebGLTexelFormat DstFormat>
+    template<MOZ_ENUM_CLASS_INTEGER_TYPE(WebGLTexelFormat) SrcFormat,
+             MOZ_ENUM_CLASS_INTEGER_TYPE(WebGLTexelFormat) DstFormat>
     void run(WebGLTexelPremultiplicationOp premultiplicationOp)
     {
         #define WEBGLIMAGECONVERTER_CASE_PREMULTIPLICATIONOP(PremultiplicationOp) \
             case PremultiplicationOp: \
                 return run<SrcFormat, DstFormat, PremultiplicationOp>();
 
         switch (premultiplicationOp) {
-            WEBGLIMAGECONVERTER_CASE_PREMULTIPLICATIONOP(NoPremultiplicationOp)
-            WEBGLIMAGECONVERTER_CASE_PREMULTIPLICATIONOP(Premultiply)
-            WEBGLIMAGECONVERTER_CASE_PREMULTIPLICATIONOP(Unpremultiply)
+            WEBGLIMAGECONVERTER_CASE_PREMULTIPLICATIONOP(WebGLTexelPremultiplicationOp::None)
+            WEBGLIMAGECONVERTER_CASE_PREMULTIPLICATIONOP(WebGLTexelPremultiplicationOp::Premultiply)
+            WEBGLIMAGECONVERTER_CASE_PREMULTIPLICATIONOP(WebGLTexelPremultiplicationOp::Unpremultiply)
             default:
-                NS_ABORT_IF_FALSE(false, "unhandled case. Coding mistake?");
+                MOZ_ASSERT(false, "unhandled case. Coding mistake?");
         }
 
         #undef WEBGLIMAGECONVERTER_CASE_PREMULTIPLICATIONOP
     }
 
-    template<WebGLTexelFormat SrcFormat>
+    template<MOZ_ENUM_CLASS_INTEGER_TYPE(WebGLTexelFormat) SrcFormat>
     void run(WebGLTexelFormat dstFormat,
              WebGLTexelPremultiplicationOp premultiplicationOp)
     {
         #define WEBGLIMAGECONVERTER_CASE_DSTFORMAT(DstFormat) \
             case DstFormat: \
                 return run<SrcFormat, DstFormat>(premultiplicationOp);
 
         switch (dstFormat) {
-            WEBGLIMAGECONVERTER_CASE_DSTFORMAT(R8)
-            WEBGLIMAGECONVERTER_CASE_DSTFORMAT(A8)
-            WEBGLIMAGECONVERTER_CASE_DSTFORMAT(R32F)
-            WEBGLIMAGECONVERTER_CASE_DSTFORMAT(A32F)
-            WEBGLIMAGECONVERTER_CASE_DSTFORMAT(RA8)
-            WEBGLIMAGECONVERTER_CASE_DSTFORMAT(RA32F)
-            WEBGLIMAGECONVERTER_CASE_DSTFORMAT(RGB8)
-            WEBGLIMAGECONVERTER_CASE_DSTFORMAT(RGB565)
-            WEBGLIMAGECONVERTER_CASE_DSTFORMAT(RGB32F)
-            WEBGLIMAGECONVERTER_CASE_DSTFORMAT(RGBA8)
-            WEBGLIMAGECONVERTER_CASE_DSTFORMAT(RGBA5551)
-            WEBGLIMAGECONVERTER_CASE_DSTFORMAT(RGBA4444)
-            WEBGLIMAGECONVERTER_CASE_DSTFORMAT(RGBA32F)
+            WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::R8)
+            WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::A8)
+            WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::R32F)
+            WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::A32F)
+            WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RA8)
+            WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RA32F)
+            WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGB8)
+            WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGB565)
+            WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGB32F)
+            WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGBA8)
+            WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGBA5551)
+            WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGBA4444)
+            WEBGLIMAGECONVERTER_CASE_DSTFORMAT(WebGLTexelFormat::RGBA32F)
             default:
-                NS_ABORT_IF_FALSE(false, "unhandled case. Coding mistake?");
+                MOZ_ASSERT(false, "unhandled case. Coding mistake?");
         }
 
         #undef WEBGLIMAGECONVERTER_CASE_DSTFORMAT
     }
 
 public:
 
     void run(WebGLTexelFormat srcFormat,
              WebGLTexelFormat dstFormat,
              WebGLTexelPremultiplicationOp premultiplicationOp)
     {
         #define WEBGLIMAGECONVERTER_CASE_SRCFORMAT(SrcFormat) \
             case SrcFormat: \
                 return run<SrcFormat>(dstFormat, premultiplicationOp);
 
         switch (srcFormat) {
-            WEBGLIMAGECONVERTER_CASE_SRCFORMAT(R8)
-            WEBGLIMAGECONVERTER_CASE_SRCFORMAT(A8)
-            WEBGLIMAGECONVERTER_CASE_SRCFORMAT(R32F)
-            WEBGLIMAGECONVERTER_CASE_SRCFORMAT(A32F)
-            WEBGLIMAGECONVERTER_CASE_SRCFORMAT(RA8)
-            WEBGLIMAGECONVERTER_CASE_SRCFORMAT(RA32F)
-            WEBGLIMAGECONVERTER_CASE_SRCFORMAT(RGB8)
-            WEBGLIMAGECONVERTER_CASE_SRCFORMAT(BGRX8) // source format only
-            WEBGLIMAGECONVERTER_CASE_SRCFORMAT(RGB565)
-            WEBGLIMAGECONVERTER_CASE_SRCFORMAT(RGB32F)
-            WEBGLIMAGECONVERTER_CASE_SRCFORMAT(RGBA8)
-            WEBGLIMAGECONVERTER_CASE_SRCFORMAT(BGRA8)
-            WEBGLIMAGECONVERTER_CASE_SRCFORMAT(RGBA5551)
-            WEBGLIMAGECONVERTER_CASE_SRCFORMAT(RGBA4444)
-            WEBGLIMAGECONVERTER_CASE_SRCFORMAT(RGBA32F)
+            WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::R8)
+            WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::A8)
+            WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::R32F)
+            WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::A32F)
+            WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RA8)
+            WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RA32F)
+            WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGB8)
+            WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::BGRX8) // source format only
+            WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGB565)
+            WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGB32F)
+            WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGBA8)
+            WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::BGRA8)
+            WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGBA5551)
+            WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGBA4444)
+            WEBGLIMAGECONVERTER_CASE_SRCFORMAT(WebGLTexelFormat::RGBA32F)
             default:
-                NS_ABORT_IF_FALSE(false, "unhandled case. Coding mistake?");
+                MOZ_ASSERT(false, "unhandled case. Coding mistake?");
         }
 
         #undef WEBGLIMAGECONVERTER_CASE_SRCFORMAT
     }
 
     WebGLImageConverter(size_t width, size_t height,
                         const void* srcStart, void* dstStart,
                         ptrdiff_t srcStride, ptrdiff_t dstStride)
@@ -330,17 +331,17 @@ WebGLContext::ConvertImage(size_t width,
         // fast exit path: we just have to memcpy all the rows.
         //
         // The case where absolutely nothing needs to be done is supposed to have
         // been handled earlier (in TexImage2D_base, etc).
         //
         // So the case we're handling here is when even though no format conversion is needed,
         // we still might have to flip vertically and/or to adjust to a different stride.
 
-        NS_ABORT_IF_FALSE(mPixelStoreFlipY || srcStride != dstStride, "Performance trap -- should handle this case earlier, to avoid memcpy");
+        MOZ_ASSERT(mPixelStoreFlipY || srcStride != dstStride, "Performance trap -- should handle this case earlier, to avoid memcpy");
 
         size_t row_size = width * dstTexelSize; // doesn't matter, src and dst formats agree
         const uint8_t* ptr = src;
         const uint8_t* src_end = src + height * srcStride;
 
         uint8_t* dst_row = mPixelStoreFlipY
                            ? dst + (height-1) * dstStride
                            : dst;
@@ -360,20 +361,20 @@ WebGLContext::ConvertImage(size_t width,
     if (mPixelStoreFlipY) {
         dstStart = dst + (height - 1) * dstStride;
         signedDstStride = -signedDstStride;
     }
 
     WebGLImageConverter converter(width, height, src, dstStart, srcStride, signedDstStride);
 
     const WebGLTexelPremultiplicationOp premultiplicationOp
-        = FormatsRequireNoPremultiplicationOp     ? NoPremultiplicationOp
-        : (!srcPremultiplied && dstPremultiplied) ? Premultiply
-        : (srcPremultiplied && !dstPremultiplied) ? Unpremultiply
-                                                  : NoPremultiplicationOp;
+        = FormatsRequireNoPremultiplicationOp     ? WebGLTexelPremultiplicationOp::None
+        : (!srcPremultiplied && dstPremultiplied) ? WebGLTexelPremultiplicationOp::Premultiply
+        : (srcPremultiplied && !dstPremultiplied) ? WebGLTexelPremultiplicationOp::Unpremultiply
+                                                  : WebGLTexelPremultiplicationOp::None;
 
     converter.run(srcFormat, dstFormat, premultiplicationOp);
 
     if (!converter.Success()) {
         // the dst image may be left uninitialized, so we better not try to
         // continue even in release builds. This should never happen anyway,
         // and would be a bug in our code.
         NS_RUNTIMEABORT("programming mistake in WebGL texture conversions");
--- a/content/canvas/src/WebGLTexelConversions.h
+++ b/content/canvas/src/WebGLTexelConversions.h
@@ -29,670 +29,673 @@
 #define WEBGLTEXELCONVERSIONS_H_
 
 #ifdef __SUNPRO_CC
 #define __restrict
 #endif
 
 #include "WebGLTypes.h"
 #include <stdint.h>
-
-#if defined _MSC_VER
-#define FORCE_INLINE __forceinline
-#elif defined __GNUC__
-#define FORCE_INLINE __attribute__((always_inline)) inline
-#else
-#define FORCE_INLINE inline
-#endif
+#include "mozilla/Attributes.h"
 
 namespace mozilla {
 
+MOZ_BEGIN_ENUM_CLASS(WebGLTexelPremultiplicationOp, int)
+    None,
+    Premultiply,
+    Unpremultiply
+MOZ_END_ENUM_CLASS(WebGLTexelPremultiplicationOp)
+
 namespace WebGLTexelConversions {
 
-enum WebGLTexelPremultiplicationOp
-{
-    NoPremultiplicationOp,
-    Premultiply,
-    Unpremultiply
-};
+// remove this as soon as B2G and Windows use newer compilers
+#ifdef MOZ_HAVE_CXX11_STRONG_ENUMS
+#define MOZ_ENUM_CLASS_INTEGER_TYPE(X) X
+#else
+#define MOZ_ENUM_CLASS_INTEGER_TYPE(X) X::Enum
+#endif
 
-template<int Format>
+template<MOZ_ENUM_CLASS_INTEGER_TYPE(WebGLTexelFormat) Format>
 struct IsFloatFormat
 {
     static const bool Value =
-        Format == RGBA32F ||
-        Format == RGB32F ||
-        Format == RA32F ||
-        Format == R32F ||
-        Format == A32F;
+        Format == WebGLTexelFormat::RGBA32F ||
+        Format == WebGLTexelFormat::RGB32F ||
+        Format == WebGLTexelFormat::RA32F ||
+        Format == WebGLTexelFormat::R32F ||
+        Format == WebGLTexelFormat::A32F;
 };
 
-template<int Format>
+template<MOZ_ENUM_CLASS_INTEGER_TYPE(WebGLTexelFormat) Format>
 struct Is16bppFormat
 {
     static const bool Value =
-        Format == RGBA4444 ||
-        Format == RGBA5551 ||
-        Format == RGB565;
+        Format == WebGLTexelFormat::RGBA4444 ||
+        Format == WebGLTexelFormat::RGBA5551 ||
+        Format == WebGLTexelFormat::RGB565;
 };
 
-template<int Format,
+template<MOZ_ENUM_CLASS_INTEGER_TYPE(WebGLTexelFormat) Format,
          bool IsFloat = IsFloatFormat<Format>::Value,
          bool Is16bpp = Is16bppFormat<Format>::Value>
 struct DataTypeForFormat
 {
     typedef uint8_t Type;
 };
 
-template<int Format>
+template<MOZ_ENUM_CLASS_INTEGER_TYPE(WebGLTexelFormat) Format>
 struct DataTypeForFormat<Format, true, false>
 {
     typedef float Type;
 };
 
-template<int Format>
+template<MOZ_ENUM_CLASS_INTEGER_TYPE(WebGLTexelFormat) Format>
 struct DataTypeForFormat<Format, false, true>
 {
     typedef uint16_t Type;
 };
 
-template<int Format>
+template<MOZ_ENUM_CLASS_INTEGER_TYPE(WebGLTexelFormat) Format>
 struct IntermediateFormat
 {
-    static const int Value = IsFloatFormat<Format>::Value ? RGBA32F : RGBA8;
+    static const MOZ_ENUM_CLASS_INTEGER_TYPE(WebGLTexelFormat) Value
+        = IsFloatFormat<Format>::Value
+          ? WebGLTexelFormat::RGBA32F
+          : WebGLTexelFormat::RGBA8;
 };
 
-inline size_t TexelBytesForFormat(int format) {
+inline size_t TexelBytesForFormat(WebGLTexelFormat format) {
     switch (format) {
-        case WebGLTexelConversions::R8:
-        case WebGLTexelConversions::A8:
+        case WebGLTexelFormat::R8:
+        case WebGLTexelFormat::A8:
             return 1;
-        case WebGLTexelConversions::RA8:
-        case WebGLTexelConversions::RGBA5551:
-        case WebGLTexelConversions::RGBA4444:
-        case WebGLTexelConversions::RGB565:
-        case WebGLTexelConversions::D16:
+        case WebGLTexelFormat::RA8:
+        case WebGLTexelFormat::RGBA5551:
+        case WebGLTexelFormat::RGBA4444:
+        case WebGLTexelFormat::RGB565:
+        case WebGLTexelFormat::D16:
             return 2;
-        case WebGLTexelConversions::RGB8:
+        case WebGLTexelFormat::RGB8:
             return 3;
-        case WebGLTexelConversions::RGBA8:
-        case WebGLTexelConversions::BGRA8:
-        case WebGLTexelConversions::BGRX8:
-        case WebGLTexelConversions::R32F:
-        case WebGLTexelConversions::A32F:
-        case WebGLTexelConversions::D32:
-        case WebGLTexelConversions::D24S8:
+        case WebGLTexelFormat::RGBA8:
+        case WebGLTexelFormat::BGRA8:
+        case WebGLTexelFormat::BGRX8:
+        case WebGLTexelFormat::R32F:
+        case WebGLTexelFormat::A32F:
+        case WebGLTexelFormat::D32:
+        case WebGLTexelFormat::D24S8:
             return 4;
-        case WebGLTexelConversions::RA32F:
+        case WebGLTexelFormat::RA32F:
             return 8;
-        case WebGLTexelConversions::RGB32F:
+        case WebGLTexelFormat::RGB32F:
             return 12;
-        case WebGLTexelConversions::RGBA32F:
+        case WebGLTexelFormat::RGBA32F:
             return 16;
         default:
-            NS_ABORT_IF_FALSE(false, "Unknown texel format. Coding mistake?");
+            MOZ_ASSERT(false, "Unknown texel format. Coding mistake?");
             return 0;
     }
 }
 
-FORCE_INLINE bool HasAlpha(int format) {
-    return format == A8 ||
-           format == A32F ||
-           format == RA8 ||
-           format == RA32F ||
-           format == RGBA8 ||
-           format == BGRA8 ||
-           format == RGBA32F ||
-           format == RGBA4444 ||
-           format == RGBA5551;
+MOZ_ALWAYS_INLINE bool HasAlpha(WebGLTexelFormat format) {
+    return format == WebGLTexelFormat::A8 ||
+           format == WebGLTexelFormat::A32F ||
+           format == WebGLTexelFormat::RA8 ||
+           format == WebGLTexelFormat::RA32F ||
+           format == WebGLTexelFormat::RGBA8 ||
+           format == WebGLTexelFormat::BGRA8 ||
+           format == WebGLTexelFormat::RGBA32F ||
+           format == WebGLTexelFormat::RGBA4444 ||
+           format == WebGLTexelFormat::RGBA5551;
 }
 
-FORCE_INLINE bool HasColor(int format) {
-    return format == R8 ||
-           format == R32F ||
-           format == RA8 ||
-           format == RA32F ||
-           format == RGB8 ||
-           format == BGRX8 ||
-           format == RGB565 ||
-           format == RGB32F ||
-           format == RGBA8 ||
-           format == BGRA8 ||
-           format == RGBA32F ||
-           format == RGBA4444 ||
-           format == RGBA5551;
+MOZ_ALWAYS_INLINE bool HasColor(WebGLTexelFormat format) {
+    return format == WebGLTexelFormat::R8 ||
+           format == WebGLTexelFormat::R32F ||
+           format == WebGLTexelFormat::RA8 ||
+           format == WebGLTexelFormat::RA32F ||
+           format == WebGLTexelFormat::RGB8 ||
+           format == WebGLTexelFormat::BGRX8 ||
+           format == WebGLTexelFormat::RGB565 ||
+           format == WebGLTexelFormat::RGB32F ||
+           format == WebGLTexelFormat::RGBA8 ||
+           format == WebGLTexelFormat::BGRA8 ||
+           format == WebGLTexelFormat::RGBA32F ||
+           format == WebGLTexelFormat::RGBA4444 ||
+           format == WebGLTexelFormat::RGBA5551;
 }
 
 
 /****** BEGIN CODE SHARED WITH WEBKIT ******/
 
 // the pack/unpack functions here are originally from this file:
 //   http://trac.webkit.org/browser/trunk/WebCore/platform/graphics/GraphicsContext3D.cpp
 
 //----------------------------------------------------------------------
 // Pixel unpacking routines.
 
-template<int Format, typename SrcType, typename DstType>
-FORCE_INLINE void
+template<MOZ_ENUM_CLASS_INTEGER_TYPE(WebGLTexelFormat) Format, typename SrcType, typename DstType>
+MOZ_ALWAYS_INLINE void
 unpack(const SrcType* __restrict src,
        DstType* __restrict dst)
 {
-    NS_ABORT_IF_FALSE(false, "Unimplemented texture format conversion");
+    MOZ_ASSERT(false, "Unimplemented texture format conversion");
 }
 
-template<> FORCE_INLINE void
-unpack<RGBA8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+unpack<WebGLTexelFormat::RGBA8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
 {
     dst[0] = src[0];
     dst[1] = src[1];
     dst[2] = src[2];
     dst[3] = src[3];
 }
 
-template<> FORCE_INLINE void
-unpack<RGB8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+unpack<WebGLTexelFormat::RGB8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
 {
     dst[0] = src[0];
     dst[1] = src[1];
     dst[2] = src[2];
     dst[3] = 0xFF;
 }
 
-template<> FORCE_INLINE void
-unpack<BGRA8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+unpack<WebGLTexelFormat::BGRA8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
 {
     dst[0] = src[2];
     dst[1] = src[1];
     dst[2] = src[0];
     dst[3] = src[3];
 }
 
-template<> FORCE_INLINE void
-unpack<BGRX8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+unpack<WebGLTexelFormat::BGRX8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
 {
     dst[0] = src[2];
     dst[1] = src[1];
     dst[2] = src[0];
     dst[3] = 0xFF;
 }
 
-template<> FORCE_INLINE void
-unpack<RGBA5551, uint16_t, uint8_t>(const uint16_t* __restrict src, uint8_t* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+unpack<WebGLTexelFormat::RGBA5551, uint16_t, uint8_t>(const uint16_t* __restrict src, uint8_t* __restrict dst)
 {
     uint16_t packedValue = src[0];
     uint8_t r = (packedValue >> 11) & 0x1F;
     uint8_t g = (packedValue >> 6) & 0x1F;
     uint8_t b = (packedValue >> 1) & 0x1F;
     dst[0] = (r << 3) | (r & 0x7);
     dst[1] = (g << 3) | (g & 0x7);
     dst[2] = (b << 3) | (b & 0x7);
     dst[3] = (packedValue & 0x1) ? 0xFF : 0;
 }
 
-template<> FORCE_INLINE void
-unpack<RGBA4444, uint16_t, uint8_t>(const uint16_t* __restrict src, uint8_t* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+unpack<WebGLTexelFormat::RGBA4444, uint16_t, uint8_t>(const uint16_t* __restrict src, uint8_t* __restrict dst)
 {
     uint16_t packedValue = src[0];
     uint8_t r = (packedValue >> 12) & 0x0F;
     uint8_t g = (packedValue >> 8) & 0x0F;
     uint8_t b = (packedValue >> 4) & 0x0F;
     uint8_t a = packedValue & 0x0F;
     dst[0] = (r << 4) | r;
     dst[1] = (g << 4) | g;
     dst[2] = (b << 4) | b;
     dst[3] = (a << 4) | a;
 }
 
-template<> FORCE_INLINE void
-unpack<RGB565, uint16_t, uint8_t>(const uint16_t* __restrict src, uint8_t* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+unpack<WebGLTexelFormat::RGB565, uint16_t, uint8_t>(const uint16_t* __restrict src, uint8_t* __restrict dst)
 {
     uint16_t packedValue = src[0];
     uint8_t r = (packedValue >> 11) & 0x1F;
     uint8_t g = (packedValue >> 5) & 0x3F;
     uint8_t b = packedValue & 0x1F;
     dst[0] = (r << 3) | (r & 0x7);
     dst[1] = (g << 2) | (g & 0x3);
     dst[2] = (b << 3) | (b & 0x7);
     dst[3] = 0xFF;
 }
 
-template<> FORCE_INLINE void
-unpack<R8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+unpack<WebGLTexelFormat::R8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
 {
     dst[0] = src[0];
     dst[1] = src[0];
     dst[2] = src[0];
     dst[3] = 0xFF;
 }
 
-template<> FORCE_INLINE void
-unpack<RA8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+unpack<WebGLTexelFormat::RA8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
 {
     dst[0] = src[0];
     dst[1] = src[0];
     dst[2] = src[0];
     dst[3] = src[1];
 }
 
-template<> FORCE_INLINE void
-unpack<A8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+unpack<WebGLTexelFormat::A8, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
 {
     dst[0] = 0;
     dst[1] = 0;
     dst[2] = 0;
     dst[3] = src[0];
 }
 
-template<> FORCE_INLINE void
-unpack<RGBA32F, float, float>(const float* __restrict src, float* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+unpack<WebGLTexelFormat::RGBA32F, float, float>(const float* __restrict src, float* __restrict dst)
 {
     dst[0] = src[0];
     dst[1] = src[1];
     dst[2] = src[2];
     dst[3] = src[3];
 }
 
-template<> FORCE_INLINE void
-unpack<RGB32F, float, float>(const float* __restrict src, float* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+unpack<WebGLTexelFormat::RGB32F, float, float>(const float* __restrict src, float* __restrict dst)
 {
     dst[0] = src[0];
     dst[1] = src[1];
     dst[2] = src[2];
     dst[3] = 1.0f;
 }
 
-template<> FORCE_INLINE void
-unpack<R32F, float, float>(const float* __restrict src, float* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+unpack<WebGLTexelFormat::R32F, float, float>(const float* __restrict src, float* __restrict dst)
 {
     dst[0] = src[0];
     dst[1] = src[0];
     dst[2] = src[0];
     dst[3] = 1.0f;
 }
 
-template<> FORCE_INLINE void
-unpack<RA32F, float, float>(const float* __restrict src, float* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+unpack<WebGLTexelFormat::RA32F, float, float>(const float* __restrict src, float* __restrict dst)
 {
     dst[0] = src[0];
     dst[1] = src[0];
     dst[2] = src[0];
     dst[3] = src[1];
 }
 
-template<> FORCE_INLINE void
-unpack<A32F, float, float>(const float* __restrict src, float* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+unpack<WebGLTexelFormat::A32F, float, float>(const float* __restrict src, float* __restrict dst)
 {
     dst[0] = 0;
     dst[1] = 0;
     dst[2] = 0;
     dst[3] = src[0];
 }
 
 //----------------------------------------------------------------------
 // Pixel packing routines.
 //
 
-template<int Format, int PremultiplicationOp, typename SrcType, typename DstType>
-FORCE_INLINE void
+template<MOZ_ENUM_CLASS_INTEGER_TYPE(WebGLTexelFormat) Format,
+         MOZ_ENUM_CLASS_INTEGER_TYPE(WebGLTexelPremultiplicationOp) PremultiplicationOp,
+         typename SrcType,
+         typename DstType>
+MOZ_ALWAYS_INLINE void
 pack(const SrcType* __restrict src,
      DstType* __restrict dst)
 {
-    NS_ABORT_IF_FALSE(false, "Unimplemented texture format conversion");
+    MOZ_ASSERT(false, "Unimplemented texture format conversion");
 }
 
-template<> FORCE_INLINE void
-pack<A8, NoPremultiplicationOp, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+pack<WebGLTexelFormat::A8, WebGLTexelPremultiplicationOp::None, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
 {
     dst[0] = src[3];
 }
 
-template<> FORCE_INLINE void
-pack<A8, Premultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+pack<WebGLTexelFormat::A8, WebGLTexelPremultiplicationOp::Premultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
 {
     dst[0] = src[3];
 }
 
-template<> FORCE_INLINE void
-pack<A8, Unpremultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+pack<WebGLTexelFormat::A8, WebGLTexelPremultiplicationOp::Unpremultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
 {
     dst[0] = src[3];
 }
 
-template<> FORCE_INLINE void
-pack<R8, NoPremultiplicationOp, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+pack<WebGLTexelFormat::R8, WebGLTexelPremultiplicationOp::None, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
 {
     dst[0] = src[0];
 }
 
-template<> FORCE_INLINE void
-pack<R8, Premultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+pack<WebGLTexelFormat::R8, WebGLTexelPremultiplicationOp::Premultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
 {
     float scaleFactor = src[3] / 255.0f;
     uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
     dst[0] = srcR;
 }
 
-template<> FORCE_INLINE void
-pack<R8, Unpremultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+pack<WebGLTexelFormat::R8, WebGLTexelPremultiplicationOp::Unpremultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
 {
     float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f;
     uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
     dst[0] = srcR;
 }
 
-template<> FORCE_INLINE void
-pack<RA8, NoPremultiplicationOp, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+pack<WebGLTexelFormat::RA8, WebGLTexelPremultiplicationOp::None, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
 {
     dst[0] = src[0];
     dst[1] = src[3];
 }
 
-template<> FORCE_INLINE void
-pack<RA8, Premultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+pack<WebGLTexelFormat::RA8, WebGLTexelPremultiplicationOp::Premultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
 {
     float scaleFactor = src[3] / 255.0f;
     uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
     dst[0] = srcR;
     dst[1] = src[3];
 }
 
 // FIXME: this routine is lossy and must be removed.
-template<> FORCE_INLINE void
-pack<RA8, Unpremultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+pack<WebGLTexelFormat::RA8, WebGLTexelPremultiplicationOp::Unpremultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
 {
     float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f;
     uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
     dst[0] = srcR;
     dst[1] = src[3];
 }
 
-template<> FORCE_INLINE void
-pack<RGB8, NoPremultiplicationOp, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+pack<WebGLTexelFormat::RGB8, WebGLTexelPremultiplicationOp::None, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
 {
     dst[0] = src[0];
     dst[1] = src[1];
     dst[2] = src[2];
 }
 
-template<> FORCE_INLINE void
-pack<RGB8, Premultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+pack<WebGLTexelFormat::RGB8, WebGLTexelPremultiplicationOp::Premultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
 {
     float scaleFactor = src[3] / 255.0f;
     uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
     uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor);
     uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor);
     dst[0] = srcR;
     dst[1] = srcG;
     dst[2] = srcB;
 }
 
-template<> FORCE_INLINE void
-pack<RGB8, Unpremultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+pack<WebGLTexelFormat::RGB8, WebGLTexelPremultiplicationOp::Unpremultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
 {
     float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f;
     uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
     uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor);
     uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor);
     dst[0] = srcR;
     dst[1] = srcG;
     dst[2] = srcB;
 }
 
-template<> FORCE_INLINE void
-pack<RGBA8, NoPremultiplicationOp, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+pack<WebGLTexelFormat::RGBA8, WebGLTexelPremultiplicationOp::None, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
 {
     dst[0] = src[0];
     dst[1] = src[1];
     dst[2] = src[2];
     dst[3] = src[3];
 }
 
-template<> FORCE_INLINE void
-pack<RGBA8, Premultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+pack<WebGLTexelFormat::RGBA8, WebGLTexelPremultiplicationOp::Premultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
 {
     float scaleFactor = src[3] / 255.0f;
     uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
     uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor);
     uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor);
     dst[0] = srcR;
     dst[1] = srcG;
     dst[2] = srcB;
     dst[3] = src[3];
 }
 
 // FIXME: this routine is lossy and must be removed.
-template<> FORCE_INLINE void
-pack<RGBA8, Unpremultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+pack<WebGLTexelFormat::RGBA8, WebGLTexelPremultiplicationOp::Unpremultiply, uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
 {
     float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f;
     uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
     uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor);
     uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor);
     dst[0] = srcR;
     dst[1] = srcG;
     dst[2] = srcB;
     dst[3] = src[3];
 }
 
-template<> FORCE_INLINE void
-pack<RGBA4444, NoPremultiplicationOp, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+pack<WebGLTexelFormat::RGBA4444, WebGLTexelPremultiplicationOp::None, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
 {
     *dst = ( ((src[0] & 0xF0) << 8)
            | ((src[1] & 0xF0) << 4)
            | (src[2] & 0xF0)
            | (src[3] >> 4) );
 }
 
-template<> FORCE_INLINE void
-pack<RGBA4444, Premultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+pack<WebGLTexelFormat::RGBA4444, WebGLTexelPremultiplicationOp::Premultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
 {
     float scaleFactor = src[3] / 255.0f;
     uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
     uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor);
     uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor);
     *dst = ( ((srcR & 0xF0) << 8)
            | ((srcG & 0xF0) << 4)
            | (srcB & 0xF0)
            | (src[3] >> 4));
 }
 
 // FIXME: this routine is lossy and must be removed.
-template<> FORCE_INLINE void
-pack<RGBA4444, Unpremultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+pack<WebGLTexelFormat::RGBA4444, WebGLTexelPremultiplicationOp::Unpremultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
 {
     float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f;
     uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
     uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor);
     uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor);
     *dst = ( ((srcR & 0xF0) << 8)
            | ((srcG & 0xF0) << 4)
            | (srcB & 0xF0)
            | (src[3] >> 4));
 }
 
-template<> FORCE_INLINE void
-pack<RGBA5551, NoPremultiplicationOp, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+pack<WebGLTexelFormat::RGBA5551, WebGLTexelPremultiplicationOp::None, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
 {
     *dst = ( ((src[0] & 0xF8) << 8)
            | ((src[1] & 0xF8) << 3)
            | ((src[2] & 0xF8) >> 2)
            | (src[3] >> 7));
 }
 
-template<> FORCE_INLINE void
-pack<RGBA5551, Premultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+pack<WebGLTexelFormat::RGBA5551, WebGLTexelPremultiplicationOp::Premultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
 {
     float scaleFactor = src[3] / 255.0f;
     uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
     uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor);
     uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor);
     *dst = ( ((srcR & 0xF8) << 8)
            | ((srcG & 0xF8) << 3)
            | ((srcB & 0xF8) >> 2)
            | (src[3] >> 7));
 }
 
 // FIXME: this routine is lossy and must be removed.
-template<> FORCE_INLINE void
-pack<RGBA5551, Unpremultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+pack<WebGLTexelFormat::RGBA5551, WebGLTexelPremultiplicationOp::Unpremultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
 {
     float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f;
     uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
     uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor);
     uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor);
     *dst = ( ((srcR & 0xF8) << 8)
            | ((srcG & 0xF8) << 3)
            | ((srcB & 0xF8) >> 2)
            | (src[3] >> 7));
 }
 
-template<> FORCE_INLINE void
-pack<RGB565, NoPremultiplicationOp, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+pack<WebGLTexelFormat::RGB565, WebGLTexelPremultiplicationOp::None, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
 {
     *dst = ( ((src[0] & 0xF8) << 8)
            | ((src[1] & 0xFC) << 3)
            | ((src[2] & 0xF8) >> 3));
 }
 
-template<> FORCE_INLINE void
-pack<RGB565, Premultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+pack<WebGLTexelFormat::RGB565, WebGLTexelPremultiplicationOp::Premultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
 {
     float scaleFactor = src[3] / 255.0f;
     uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
     uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor);
     uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor);
     *dst = ( ((srcR & 0xF8) << 8)
            | ((srcG & 0xFC) << 3)
            | ((srcB & 0xF8) >> 3));
 }
 
 // FIXME: this routine is lossy and must be removed.
-template<> FORCE_INLINE void
-pack<RGB565, Unpremultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+pack<WebGLTexelFormat::RGB565, WebGLTexelPremultiplicationOp::Unpremultiply, uint8_t, uint16_t>(const uint8_t* __restrict src, uint16_t* __restrict dst)
 {
     float scaleFactor = src[3] ? 255.0f / src[3] : 1.0f;
     uint8_t srcR = static_cast<uint8_t>(src[0] * scaleFactor);
     uint8_t srcG = static_cast<uint8_t>(src[1] * scaleFactor);
     uint8_t srcB = static_cast<uint8_t>(src[2] * scaleFactor);
     *dst = ( ((srcR & 0xF8) << 8)
            | ((srcG & 0xFC) << 3)
            | ((srcB & 0xF8) >> 3));
 }
 
-template<> FORCE_INLINE void
-pack<RGB32F, NoPremultiplicationOp, float, float>(const float* __restrict src, float* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+pack<WebGLTexelFormat::RGB32F, WebGLTexelPremultiplicationOp::None, float, float>(const float* __restrict src, float* __restrict dst)
 {
     dst[0] = src[0];
     dst[1] = src[1];
     dst[2] = src[2];
 }
 
-template<> FORCE_INLINE void
-pack<RGB32F, Premultiply, float, float>(const float* __restrict src, float* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+pack<WebGLTexelFormat::RGB32F, WebGLTexelPremultiplicationOp::Premultiply, float, float>(const float* __restrict src, float* __restrict dst)
 {
     float scaleFactor = src[3];
     dst[0] = src[0] * scaleFactor;
     dst[1] = src[1] * scaleFactor;
     dst[2] = src[2] * scaleFactor;
 }
 
-template<> FORCE_INLINE void
-pack<RGBA32F, NoPremultiplicationOp, float, float>(const float* __restrict src, float* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+pack<WebGLTexelFormat::RGBA32F, WebGLTexelPremultiplicationOp::None, float, float>(const float* __restrict src, float* __restrict dst)
 {
     dst[0] = src[0];
     dst[1] = src[1];
     dst[2] = src[2];
     dst[3] = src[3];
 }
 
-template<> FORCE_INLINE void
-pack<RGBA32F, Premultiply, float, float>(const float* __restrict src, float* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+pack<WebGLTexelFormat::RGBA32F, WebGLTexelPremultiplicationOp::Premultiply, float, float>(const float* __restrict src, float* __restrict dst)
 {
     float scaleFactor = src[3];
     dst[0] = src[0] * scaleFactor;
     dst[1] = src[1] * scaleFactor;
     dst[2] = src[2] * scaleFactor;
     dst[3] = src[3];
 }
 
-template<> FORCE_INLINE void
-pack<A32F, NoPremultiplicationOp, float, float>(const float* __restrict src, float* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+pack<WebGLTexelFormat::A32F, WebGLTexelPremultiplicationOp::None, float, float>(const float* __restrict src, float* __restrict dst)
 {
     dst[0] = src[3];
 }
 
-template<> FORCE_INLINE void
-pack<A32F, Premultiply, float, float>(const float* __restrict src, float* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+pack<WebGLTexelFormat::A32F, WebGLTexelPremultiplicationOp::Premultiply, float, float>(const float* __restrict src, float* __restrict dst)
 {
     dst[0] = src[3];
 }
 
-template<> FORCE_INLINE void
-pack<R32F, NoPremultiplicationOp, float, float>(const float* __restrict src, float* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+pack<WebGLTexelFormat::R32F, WebGLTexelPremultiplicationOp::None, float, float>(const float* __restrict src, float* __restrict dst)
 {
     dst[0] = src[0];
 }
 
-template<> FORCE_INLINE void
-pack<R32F, Premultiply, float, float>(const float* __restrict src, float* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+pack<WebGLTexelFormat::R32F, WebGLTexelPremultiplicationOp::Premultiply, float, float>(const float* __restrict src, float* __restrict dst)
 {
     float scaleFactor = src[3];
     dst[0] = src[0] * scaleFactor;
 }
 
-template<> FORCE_INLINE void
-pack<RA32F, NoPremultiplicationOp, float, float>(const float* __restrict src, float* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+pack<WebGLTexelFormat::RA32F, WebGLTexelPremultiplicationOp::None, float, float>(const float* __restrict src, float* __restrict dst)
 {
     dst[0] = src[0];
     dst[1] = src[3];
 }
 
-template<> FORCE_INLINE void
-pack<RA32F, Premultiply, float, float>(const float* __restrict src, float* __restrict dst)
+template<> MOZ_ALWAYS_INLINE void
+pack<WebGLTexelFormat::RA32F, WebGLTexelPremultiplicationOp::Premultiply, float, float>(const float* __restrict src, float* __restrict dst)
 {
     float scaleFactor = src[3];
     dst[0] = src[0] * scaleFactor;
     dst[1] = scaleFactor;
 }
 
 /****** END CODE SHARED WITH WEBKIT ******/
 
-template<typename SrcType, typename DstType> FORCE_INLINE void
+template<typename SrcType, typename DstType> MOZ_ALWAYS_INLINE void
 convertType(const SrcType* __restrict src, DstType* __restrict dst)
 {
-    NS_ABORT_IF_FALSE(false, "Unimplemented texture format conversion");
+    MOZ_ASSERT(false, "Unimplemented texture format conversion");
 }
 
-template<> FORCE_INLINE void
+template<> MOZ_ALWAYS_INLINE void
 convertType<uint8_t, uint8_t>(const uint8_t* __restrict src, uint8_t* __restrict dst)
 {
     dst[0] = src[0];
     dst[1] = src[1];
     dst[2] = src[2];
     dst[3] = src[3];
 }
 
-template<> FORCE_INLINE void
+template<> MOZ_ALWAYS_INLINE void
 convertType<float, float>(const float* __restrict src, float* __restrict dst)
 {
     dst[0] = src[0];
     dst[1] = src[1];
     dst[2] = src[2];
     dst[3] = src[3];
 }
 
-template<> FORCE_INLINE void
+template<> MOZ_ALWAYS_INLINE void
 convertType<uint8_t, float>(const uint8_t* __restrict src, float* __restrict dst)
 {
     const float scaleFactor = 1.f / 255.0f;
     dst[0] = src[0] * scaleFactor;
     dst[1] = src[1] * scaleFactor;
     dst[2] = src[2] * scaleFactor;
     dst[3] = src[3] * scaleFactor;
 }
 
-#undef FORCE_INLINE
-
 } // end namespace WebGLTexelConversions
 
 } // end namespace mozilla
 
 #endif // WEBGLTEXELCONVERSIONS_H_
--- a/content/canvas/src/WebGLTexture.cpp
+++ b/content/canvas/src/WebGLTexture.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "WebGLContext.h"
 #include "WebGLTexture.h"
 #include "GLContext.h"
+#include "WebGLTexelConversions.h"
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
 #include <algorithm>
 
 using namespace mozilla;
 
 JSObject*
 WebGLTexture::WrapObject(JSContext *cx, JS::Handle<JSObject*> scope) {
     return dom::WebGLTextureBinding::Wrap(cx, scope, this);
@@ -22,17 +23,17 @@ WebGLTexture::WebGLTexture(WebGLContext 
     , mTarget(0)
     , mMinFilter(LOCAL_GL_NEAREST_MIPMAP_LINEAR)
     , mMagFilter(LOCAL_GL_LINEAR)
     , mWrapS(LOCAL_GL_REPEAT)
     , mWrapT(LOCAL_GL_REPEAT)
     , mFacesCount(0)
     , mMaxLevelWithCustomImages(0)
     , mHaveGeneratedMipmap(false)
-    , mFakeBlackStatus(DoNotNeedFakeBlack)
+    , mFakeBlackStatus(WebGLTextureFakeBlackStatus::IncompleteTexture)
 {
     SetIsDOMBinding();
     mContext->MakeContextCurrent();
     mContext->gl->fGenTextures(1, &mGLName);
     mContext->mTextures.insertBack(this);
 }
 
 void
@@ -40,17 +41,17 @@ WebGLTexture::Delete() {
     mImageInfos.Clear();
     mContext->MakeContextCurrent();
     mContext->gl->fDeleteTextures(1, &mGLName);
     LinkedListElement<WebGLTexture>::removeFrom(mContext->mTextures);
 }
 
 int64_t
 WebGLTexture::ImageInfo::MemoryUsage() const {
-    if (!mIsDefined)
+    if (mImageDataStatus == WebGLImageDataStatus::NoImageData)
         return 0;
     int64_t texelSizeInBits = WebGLContext::GetBitsPerTexel(mFormat, mType);
     return int64_t(mWidth) * int64_t(mHeight) * texelSizeInBits / 8;
 }
 
 int64_t
 WebGLTexture::MemoryUsage() const {
     if (IsDeleted())
@@ -93,22 +94,16 @@ WebGLTexture::DoesTexture2DMipmapHaveAll
             return true;
     }
 
     // if we're here, we've exhausted all levels without finding a 1x1 image
     return false;
 }
 
 void
-WebGLTexture::SetDontKnowIfNeedFakeBlack() {
-    mFakeBlackStatus = DontKnowIfNeedFakeBlack;
-    mContext->SetDontKnowIfNeedFakeBlack();
-}
-
-void
 WebGLTexture::Bind(GLenum aTarget) {
     // this function should only be called by bindTexture().
     // it assumes that the GL context is already current.
 
     bool firstTimeThisTextureIsBound = !mHasEverBeenBound;
 
     if (!firstTimeThisTextureIsBound && aTarget != mTarget) {
         mContext->ErrorInvalidOperation("bindTexture: this texture has already been bound to a different target");
@@ -119,51 +114,51 @@ WebGLTexture::Bind(GLenum aTarget) {
 
     mTarget = aTarget;
 
     mContext->gl->fBindTexture(mTarget, mGLName);
 
     if (firstTimeThisTextureIsBound) {
         mFacesCount = (mTarget == LOCAL_GL_TEXTURE_2D) ? 1 : 6;
         EnsureMaxLevelWithCustomImagesAtLeast(0);
-        SetDontKnowIfNeedFakeBlack();
+        SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
 
         // thanks to the WebKit people for finding this out: GL_TEXTURE_WRAP_R is not
         // present in GLES 2, but is present in GL and it seems as if for cube maps
         // we need to set it to GL_CLAMP_TO_EDGE to get the expected GLES behavior.
         if (mTarget == LOCAL_GL_TEXTURE_CUBE_MAP && !mContext->gl->IsGLES2())
             mContext->gl->fTexParameteri(mTarget, LOCAL_GL_TEXTURE_WRAP_R, LOCAL_GL_CLAMP_TO_EDGE);
     }
 
     mHasEverBeenBound = true;
 }
 
 void
 WebGLTexture::SetImageInfo(GLenum aTarget, GLint aLevel,
                   GLsizei aWidth, GLsizei aHeight,
-                  GLenum aFormat, GLenum aType)
+                  GLenum aFormat, GLenum aType, WebGLImageDataStatus aStatus)
 {
     if ( (aTarget == LOCAL_GL_TEXTURE_2D) != (mTarget == LOCAL_GL_TEXTURE_2D) )
         return;
 
     EnsureMaxLevelWithCustomImagesAtLeast(aLevel);
 
-    ImageInfoAt(aTarget, aLevel) = ImageInfo(aWidth, aHeight, aFormat, aType);
+    ImageInfoAt(aTarget, aLevel) = ImageInfo(aWidth, aHeight, aFormat, aType, aStatus);
 
     if (aLevel > 0)
         SetCustomMipmap();
 
-    SetDontKnowIfNeedFakeBlack();
+    SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
 }
 
 void
 WebGLTexture::SetGeneratedMipmap() {
     if (!mHaveGeneratedMipmap) {
         mHaveGeneratedMipmap = true;
-        SetDontKnowIfNeedFakeBlack();
+        SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
     }
 }
 
 void
 WebGLTexture::SetCustomMipmap() {
     if (mHaveGeneratedMipmap) {
         // if we were in GeneratedMipmap mode and are now switching to CustomMipmap mode,
         // we need to compute now all the mipmap image info.
@@ -239,136 +234,217 @@ WebGLTexture::IsMipmapCubeComplete() con
     for (int i = 0; i < 6; i++) {
         GLenum face = GLCubeMapFaceById(i);
         if (!DoesTexture2DMipmapHaveAllLevelsConsistentlyDefined(face))
             return false;
     }
     return true;
 }
 
-bool
-WebGLTexture::NeedFakeBlack() {
-    // handle this case first, it's the generic case
-    if (mFakeBlackStatus == DoNotNeedFakeBlack)
-        return false;
+WebGLTextureFakeBlackStatus
+WebGLTexture::ResolvedFakeBlackStatus() {
+    if (MOZ_LIKELY(mFakeBlackStatus != WebGLTextureFakeBlackStatus::Unknown)) {
+        return mFakeBlackStatus;
+    }
+
+    // Determine if the texture needs to be faked as a black texture.
+    // See 3.8.2 Shader Execution in the OpenGL ES 2.0.24 spec.
+
+    for (size_t face = 0; face < mFacesCount; ++face) {
+        if (ImageInfoAtFace(face, 0).mImageDataStatus == WebGLImageDataStatus::NoImageData) {
+            // In case of undefined texture image, we don't print any message because this is a very common
+            // and often legitimate case (asynchronous texture loading).
+            mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture;
+            return mFakeBlackStatus;
+        }
+    }
+
+    const char *msg_rendering_as_black
+        = "A texture is going to be rendered as if it were black, as per the OpenGL ES 2.0.24 spec section 3.8.2, "
+          "because it";
+
+    if (mTarget == LOCAL_GL_TEXTURE_2D)
+    {
+        if (DoesMinFilterRequireMipmap())
+        {
+            if (!IsMipmapTexture2DComplete()) {
+                mContext->GenerateWarning
+                    ("%s is a 2D texture, with a minification filter requiring a mipmap, "
+                      "and is not mipmap complete (as defined in section 3.7.10).", msg_rendering_as_black);
+                mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture;
+            } else if (!ImageInfoAt(mTarget, 0).IsPowerOfTwo()) {
+                mContext->GenerateWarning
+                    ("%s is a 2D texture, with a minification filter requiring a mipmap, "
+                      "and either its width or height is not a power of two.", msg_rendering_as_black);
+                mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture;
+            }
+        }
+        else // no mipmap required
+        {
+            if (!ImageInfoAt(mTarget, 0).IsPositive()) {
+                mContext->GenerateWarning
+                    ("%s is a 2D texture and its width or height is equal to zero.",
+                      msg_rendering_as_black);
+                mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture;
+            } else if (!AreBothWrapModesClampToEdge() && !ImageInfoAt(mTarget, 0).IsPowerOfTwo()) {
+                mContext->GenerateWarning
+                    ("%s is a 2D texture, with a minification filter not requiring a mipmap, "
+                      "with its width or height not a power of two, and with a wrap mode "
+                      "different from CLAMP_TO_EDGE.", msg_rendering_as_black);
+                mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture;
+            }
+        }
+    }
+    else // cube map
+    {
+        bool areAllLevel0ImagesPOT = true;
+        for (size_t face = 0; face < mFacesCount; ++face)
+            areAllLevel0ImagesPOT &= ImageInfoAtFace(face, 0).IsPowerOfTwo();
 
-    if (mFakeBlackStatus == DontKnowIfNeedFakeBlack) {
-        // Determine if the texture needs to be faked as a black texture.
-        // See 3.8.2 Shader Execution in the OpenGL ES 2.0.24 spec.
+        if (DoesMinFilterRequireMipmap())
+        {
+            if (!IsMipmapCubeComplete()) {
+                mContext->GenerateWarning("%s is a cube map texture, with a minification filter requiring a mipmap, "
+                            "and is not mipmap cube complete (as defined in section 3.7.10).",
+                            msg_rendering_as_black);
+                mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture;
+            } else if (!areAllLevel0ImagesPOT) {
+                mContext->GenerateWarning("%s is a cube map texture, with a minification filter requiring a mipmap, "
+                            "and either the width or the height of some level 0 image is not a power of two.",
+                            msg_rendering_as_black);
+                mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture;
+            }
+        }
+        else // no mipmap required
+        {
+            if (!IsCubeComplete()) {
+                mContext->GenerateWarning("%s is a cube map texture, with a minification filter not requiring a mipmap, "
+                            "and is not cube complete (as defined in section 3.7.10).",
+                            msg_rendering_as_black);
+                mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture;
+            } else if (!AreBothWrapModesClampToEdge() && !areAllLevel0ImagesPOT) {
+                mContext->GenerateWarning("%s is a cube map texture, with a minification filter not requiring a mipmap, "
+                            "with some level 0 image having width or height not a power of two, and with a wrap mode "
+                            "different from CLAMP_TO_EDGE.", msg_rendering_as_black);
+                mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture;
+            }
+        }
+    }
 
+    if (ImageInfoBase().mType == LOCAL_GL_FLOAT &&
+        !Context()->IsExtensionEnabled(WebGLContext::OES_texture_float_linear))
+    {
+        if (mMinFilter == LOCAL_GL_LINEAR ||
+            mMinFilter == LOCAL_GL_LINEAR_MIPMAP_LINEAR ||
+            mMinFilter == LOCAL_GL_LINEAR_MIPMAP_NEAREST ||
+            mMinFilter == LOCAL_GL_NEAREST_MIPMAP_LINEAR)
+        {
+            mContext->GenerateWarning("%s is a texture with a linear minification filter, "
+                                      "which is not compatible with gl.FLOAT by default. "
+                                      "Try enabling the OES_texture_float_linear extension if supported.", msg_rendering_as_black);
+            mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture;
+        }
+        else if (mMagFilter == LOCAL_GL_LINEAR)
+        {
+            mContext->GenerateWarning("%s is a texture with a linear magnification filter, "
+                                      "which is not compatible with gl.FLOAT by default. "
+                                      "Try enabling the OES_texture_float_linear extension if supported.", msg_rendering_as_black);
+            mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture;
+        }
+    }
+
+    // We have exhausted all cases of incomplete textures, where we would need opaque black.
+    // We may still need transparent black in case of uninitialized image data.
+    bool hasUninitializedImageData = false;
+    for (size_t level = 0; level <= mMaxLevelWithCustomImages; ++level) {
         for (size_t face = 0; face < mFacesCount; ++face) {
-            if (!ImageInfoAtFace(face, 0).mIsDefined) {
-                // In case of undefined texture image, we don't print any message because this is a very common
-                // and often legitimate case, for example when doing asynchronous texture loading.
-                // An extreme case of this is the photowall google demo.
-                // Exiting early here allows us to avoid making noise on valid webgl code.
-                mFakeBlackStatus = DoNeedFakeBlack;
-                return true;
+            hasUninitializedImageData |= (ImageInfoAtFace(face, level).mImageDataStatus == WebGLImageDataStatus::UninitializedImageData);
+        }
+    }
+
+    if (hasUninitializedImageData) {
+        bool hasAnyInitializedImageData = false;
+        for (size_t level = 0; level <= mMaxLevelWithCustomImages; ++level) {
+            for (size_t face = 0; face < mFacesCount; ++face) {
+                if (ImageInfoAtFace(face, level).mImageDataStatus == WebGLImageDataStatus::InitializedImageData) {
+                    hasAnyInitializedImageData = true;
+                    break;
+                }
+            }
+            if (hasAnyInitializedImageData) {
+                break;
             }
         }
 
-        const char *msg_rendering_as_black
-            = "A texture is going to be rendered as if it were black, as per the OpenGL ES 2.0.24 spec section 3.8.2, "
-              "because it";
-
-        if (mTarget == LOCAL_GL_TEXTURE_2D)
-        {
-            if (DoesMinFilterRequireMipmap())
-            {
-                if (!IsMipmapTexture2DComplete()) {
-                    mContext->GenerateWarning
-                        ("%s is a 2D texture, with a minification filter requiring a mipmap, "
-                         "and is not mipmap complete (as defined in section 3.7.10).", msg_rendering_as_black);
-                    mFakeBlackStatus = DoNeedFakeBlack;
-                } else if (!ImageInfoAt(mTarget, 0).IsPowerOfTwo()) {
-                    mContext->GenerateWarning
-                        ("%s is a 2D texture, with a minification filter requiring a mipmap, "
-                         "and either its width or height is not a power of two.", msg_rendering_as_black);
-                    mFakeBlackStatus = DoNeedFakeBlack;
-                }
-            }
-            else // no mipmap required
-            {
-                if (!ImageInfoAt(mTarget, 0).IsPositive()) {
-                    mContext->GenerateWarning
-                        ("%s is a 2D texture and its width or height is equal to zero.",
-                         msg_rendering_as_black);
-                    mFakeBlackStatus = DoNeedFakeBlack;
-                } else if (!AreBothWrapModesClampToEdge() && !ImageInfoAt(mTarget, 0).IsPowerOfTwo()) {
-                    mContext->GenerateWarning
-                        ("%s is a 2D texture, with a minification filter not requiring a mipmap, "
-                         "with its width or height not a power of two, and with a wrap mode "
-                         "different from CLAMP_TO_EDGE.", msg_rendering_as_black);
-                    mFakeBlackStatus = DoNeedFakeBlack;
+        if (hasAnyInitializedImageData) {
+            // The texture contains some initialized image data, and some uninitialized image data.
+            // In this case, we have no choice but to initialize all image data now. Fortunately,
+            // in this case we know that we can't be dealing with a depth texture per WEBGL_depth_texture
+            // and ANGLE_depth_texture (which allow only one image per texture) so we can assume that
+            // glTexImage2D is able to upload data to images.
+            for (size_t level = 0; level <= mMaxLevelWithCustomImages; ++level) {
+                for (size_t face = 0; face < mFacesCount; ++face) {
+                    GLenum imageTarget = mTarget == LOCAL_GL_TEXTURE_2D
+                                         ? LOCAL_GL_TEXTURE_2D
+                                         : LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X + face;
+                    const ImageInfo& imageInfo = ImageInfoAt(imageTarget, level);
+                    if (imageInfo.mImageDataStatus == WebGLImageDataStatus::UninitializedImageData) {
+                        DoDeferredImageInitialization(imageTarget, level);
+                    }
                 }
             }
+            mFakeBlackStatus = WebGLTextureFakeBlackStatus::NotNeeded;
+        } else {
+            // The texture only contains uninitialized image data. In this case,
+            // we can use a black texture for it.
+            mFakeBlackStatus = WebGLTextureFakeBlackStatus::UninitializedImageData;
         }
-        else // cube map
-        {
-            bool areAllLevel0ImagesPOT = true;
-            for (size_t face = 0; face < mFacesCount; ++face)
-                areAllLevel0ImagesPOT &= ImageInfoAtFace(face, 0).IsPowerOfTwo();
+    }
 
-            if (DoesMinFilterRequireMipmap())
-            {
-                if (!IsMipmapCubeComplete()) {
-                    mContext->GenerateWarning("%s is a cube map texture, with a minification filter requiring a mipmap, "
-                               "and is not mipmap cube complete (as defined in section 3.7.10).",
-                               msg_rendering_as_black);
-                    mFakeBlackStatus = DoNeedFakeBlack;
-                } else if (!areAllLevel0ImagesPOT) {
-                    mContext->GenerateWarning("%s is a cube map texture, with a minification filter requiring a mipmap, "
-                               "and either the width or the height of some level 0 image is not a power of two.",
-                               msg_rendering_as_black);
-                    mFakeBlackStatus = DoNeedFakeBlack;
-                }
-            }
-            else // no mipmap required
-            {
-                if (!IsCubeComplete()) {
-                    mContext->GenerateWarning("%s is a cube map texture, with a minification filter not requiring a mipmap, "
-                               "and is not cube complete (as defined in section 3.7.10).",
-                               msg_rendering_as_black);
-                    mFakeBlackStatus = DoNeedFakeBlack;
-                } else if (!AreBothWrapModesClampToEdge() && !areAllLevel0ImagesPOT) {
-                    mContext->GenerateWarning("%s is a cube map texture, with a minification filter not requiring a mipmap, "
-                               "with some level 0 image having width or height not a power of two, and with a wrap mode "
-                               "different from CLAMP_TO_EDGE.", msg_rendering_as_black);
-                    mFakeBlackStatus = DoNeedFakeBlack;
-                }
-            }
-        }
-
-        if (ImageInfoBase().mType == LOCAL_GL_FLOAT &&
-            !Context()->IsExtensionEnabled(WebGLContext::OES_texture_float_linear))
-        {
-            if (mMinFilter == LOCAL_GL_LINEAR ||
-                mMinFilter == LOCAL_GL_LINEAR_MIPMAP_LINEAR ||
-                mMinFilter == LOCAL_GL_LINEAR_MIPMAP_NEAREST ||
-                mMinFilter == LOCAL_GL_NEAREST_MIPMAP_LINEAR)
-            {
-                mContext->GenerateWarning("%s is a texture with a linear minification filter, "
-                                          "which is not compatible with gl.FLOAT by default. "
-                                          "Try enabling the OES_texture_float_linear extension if supported.", msg_rendering_as_black);
-                mFakeBlackStatus = DoNeedFakeBlack;
-            }
-            else if (mMagFilter == LOCAL_GL_LINEAR)
-            {
-                mContext->GenerateWarning("%s is a texture with a linear magnification filter, "
-                                          "which is not compatible with gl.FLOAT by default. "
-                                          "Try enabling the OES_texture_float_linear extension if supported.", msg_rendering_as_black);
-                mFakeBlackStatus = DoNeedFakeBlack;
-            }
-        }
-
-        // we have exhausted all cases where we do need fakeblack, so if the status is still unknown,
-        // that means that we do NOT need it.
-        if (mFakeBlackStatus == DontKnowIfNeedFakeBlack)
-            mFakeBlackStatus = DoNotNeedFakeBlack;
+    // we have exhausted all cases where we do need fakeblack, so if the status is still unknown,
+    // that means that we do NOT need it.
+    if (mFakeBlackStatus == WebGLTextureFakeBlackStatus::Unknown) {
+        mFakeBlackStatus = WebGLTextureFakeBlackStatus::NotNeeded;
     }
 
-    return mFakeBlackStatus == DoNeedFakeBlack;
+    MOZ_ASSERT(mFakeBlackStatus != WebGLTextureFakeBlackStatus::Unknown);
+    return mFakeBlackStatus;
+}
+
+void
+WebGLTexture::DoDeferredImageInitialization(GLenum imageTarget, GLint level)
+{
+    const ImageInfo& imageInfo = ImageInfoAt(imageTarget, level);
+    MOZ_ASSERT(imageInfo.mImageDataStatus == WebGLImageDataStatus::UninitializedImageData);
+
+    mContext->MakeContextCurrent();
+    gl::ScopedBindTexture autoBindTex(mContext->gl, GLName(), mTarget);
+
+    WebGLTexelFormat texelformat = GetWebGLTexelFormat(imageInfo.mFormat, imageInfo.mType);
+    uint32_t texelsize = WebGLTexelConversions::TexelBytesForFormat(texelformat);
+    CheckedUint32 checked_byteLength
+        = WebGLContext::GetImageSize(
+                        imageInfo.mHeight,
+                        imageInfo.mWidth,
+                        texelsize,
+                        mContext->mPixelStoreUnpackAlignment);
+    MOZ_ASSERT(checked_byteLength.isValid()); // should have been checked earlier
+    void *zeros = calloc(1, checked_byteLength.value());
+    GLenum error
+        = mContext->CheckedTexImage2D(imageTarget, level, imageInfo.mFormat,
+                                      imageInfo.mWidth, imageInfo.mHeight,
+                                      0, imageInfo.mFormat, imageInfo.mType,
+                                      zeros);
+
+    free(zeros);
+    SetImageDataStatus(imageTarget, level, WebGLImageDataStatus::InitializedImageData);
+
+    if (error) {
+      // Should only be OUT_OF_MEMORY. Anyway, there's no good way to recover from this here.
+      MOZ_CRASH(); // errors on texture upload have been related to video memory exposure in the past.
+      return;
+    }
 }
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WebGLTexture)
 
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLTexture, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WebGLTexture, Release)
--- a/content/canvas/src/WebGLTexture.h
+++ b/content/canvas/src/WebGLTexture.h
@@ -16,16 +16,25 @@
 namespace mozilla {
 
 // Zero is not an integer power of two.
 inline bool is_pot_assuming_nonnegative(GLsizei x)
 {
     return x && (x & (x-1)) == 0;
 }
 
+inline bool FormatHasAlpha(GLenum format)
+{
+    return format == LOCAL_GL_RGBA ||
+           format == LOCAL_GL_LUMINANCE_ALPHA ||
+           format == LOCAL_GL_ALPHA ||
+           format == LOCAL_GL_RGBA4 ||
+           format == LOCAL_GL_RGB5_A1;
+}
+
 // NOTE: When this class is switched to new DOM bindings, update the (then-slow)
 // WrapObject calls in GetParameter and GetFramebufferAttachmentParameter.
 class WebGLTexture MOZ_FINAL
     : public nsWrapperCache
     , public WebGLRefCountedObject<WebGLTexture>
     , public LinkedListElement<WebGLTexture>
     , public WebGLContextBoundObject
 {
@@ -61,58 +70,66 @@ protected:
     bool mHasEverBeenBound;
     GLuint mGLName;
 
     // we store information about the various images that are part of
     // this texture (cubemap faces, mipmap levels)
 
 public:
 
-    class ImageInfo : public WebGLRectangleObject {
+    class ImageInfo
+        : public WebGLRectangleObject
+    {
     public:
         ImageInfo()
             : mFormat(0)
             , mType(0)
-            , mIsDefined(false)
+            , mImageDataStatus(WebGLImageDataStatus::NoImageData)
         {}
 
         ImageInfo(GLsizei width, GLsizei height,
-                  GLenum format, GLenum type)
+                  GLenum format, GLenum type, WebGLImageDataStatus status)
             : WebGLRectangleObject(width, height)
             , mFormat(format)
             , mType(type)
-            , mIsDefined(true)
-        {}
+            , mImageDataStatus(status)
+        {
+            // shouldn't use this constructor to construct a null ImageInfo
+            MOZ_ASSERT(status != WebGLImageDataStatus::NoImageData);
+        }
 
         bool operator==(const ImageInfo& a) const {
-            return mIsDefined == a.mIsDefined &&
-                   mWidth     == a.mWidth &&
-                   mHeight    == a.mHeight &&
-                   mFormat    == a.mFormat &&
-                   mType      == a.mType;
+            return mImageDataStatus == a.mImageDataStatus &&
+                   mWidth  == a.mWidth &&
+                   mHeight == a.mHeight &&
+                   mFormat == a.mFormat &&
+                   mType   == a.mType;
         }
         bool operator!=(const ImageInfo& a) const {
             return !(*this == a);
         }
         bool IsSquare() const {
             return mWidth == mHeight;
         }
         bool IsPositive() const {
             return mWidth > 0 && mHeight > 0;
         }
         bool IsPowerOfTwo() const {
             return is_pot_assuming_nonnegative(mWidth) &&
                    is_pot_assuming_nonnegative(mHeight); // negative sizes should never happen (caught in texImage2D...)
         }
+        bool HasUninitializedImageData() const {
+            return mImageDataStatus == WebGLImageDataStatus::UninitializedImageData;
+        }
         int64_t MemoryUsage() const;
         GLenum Format() const { return mFormat; }
         GLenum Type() const { return mType; }
     protected:
         GLenum mFormat, mType;
-        bool mIsDefined;
+        WebGLImageDataStatus mImageDataStatus;
 
         friend class WebGLTexture;
     };
 
 private:
     static size_t FaceForTarget(GLenum target) {
         // Call this out explicitly:
         MOZ_ASSERT(target != LOCAL_GL_TEXTURE_CUBE_MAP);
@@ -144,44 +161,58 @@ public:
     }
 
     const ImageInfo& ImageInfoAt(GLenum imageTarget, GLint level) const {
         return const_cast<WebGLTexture*>(this)->ImageInfoAt(imageTarget, level);
     }
 
     bool HasImageInfoAt(GLenum imageTarget, GLint level) const {
         MOZ_ASSERT(imageTarget);
-        
+
         size_t face = FaceForTarget(imageTarget);
         CheckedUint32 checked_index = CheckedUint32(level) * mFacesCount + face;
         return checked_index.isValid() &&
                checked_index.value() < mImageInfos.Length() &&
-               ImageInfoAt(imageTarget, level).mIsDefined;
+               ImageInfoAt(imageTarget, level).mImageDataStatus != WebGLImageDataStatus::NoImageData;
     }
 
     ImageInfo& ImageInfoBase() {
         return ImageInfoAtFace(0, 0);
     }
 
     const ImageInfo& ImageInfoBase() const {
         return ImageInfoAtFace(0, 0);
     }
 
     int64_t MemoryUsage() const;
 
+    void SetImageDataStatus(GLenum imageTarget, GLint level, WebGLImageDataStatus newStatus) {
+        MOZ_ASSERT(HasImageInfoAt(imageTarget, level));
+        ImageInfo& imageInfo = ImageInfoAt(imageTarget, level);
+        // there is no way to go from having image data to not having any
+        MOZ_ASSERT(newStatus != WebGLImageDataStatus::NoImageData ||
+                   imageInfo.mImageDataStatus == WebGLImageDataStatus::NoImageData);
+        if (imageInfo.mImageDataStatus != newStatus) {
+            SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
+        }
+        imageInfo.mImageDataStatus = newStatus;
+    }
+
+    void DoDeferredImageInitialization(GLenum imageTarget, GLint level);
+
 protected:
 
     GLenum mTarget;
     GLenum mMinFilter, mMagFilter, mWrapS, mWrapT;
 
     size_t mFacesCount, mMaxLevelWithCustomImages;
     nsTArray<ImageInfo> mImageInfos;
 
     bool mHaveGeneratedMipmap;
-    FakeBlackStatus mFakeBlackStatus;
+    WebGLTextureFakeBlackStatus mFakeBlackStatus;
 
     void EnsureMaxLevelWithCustomImagesAtLeast(size_t aMaxLevelWithCustomImages) {
         mMaxLevelWithCustomImages = std::max(mMaxLevelWithCustomImages, aMaxLevelWithCustomImages);
         mImageInfos.EnsureLengthAtLeast((mMaxLevelWithCustomImages + 1) * mFacesCount);
     }
 
     bool CheckFloatTextureFilterParams() const {
         // Without OES_texture_float_linear, only NEAREST and NEAREST_MIMPAMP_NEAREST are supported
@@ -192,39 +223,37 @@ protected:
     bool AreBothWrapModesClampToEdge() const {
         return mWrapS == LOCAL_GL_CLAMP_TO_EDGE && mWrapT == LOCAL_GL_CLAMP_TO_EDGE;
     }
 
     bool DoesTexture2DMipmapHaveAllLevelsConsistentlyDefined(GLenum texImageTarget) const;
 
 public:
 
-    void SetDontKnowIfNeedFakeBlack();
-
     void Bind(GLenum aTarget);
 
     void SetImageInfo(GLenum aTarget, GLint aLevel,
                       GLsizei aWidth, GLsizei aHeight,
-                      GLenum aFormat, GLenum aType);
+                      GLenum aFormat, GLenum aType, WebGLImageDataStatus aStatus);
 
     void SetMinFilter(GLenum aMinFilter) {
         mMinFilter = aMinFilter;
-        SetDontKnowIfNeedFakeBlack();
+        SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
     }
     void SetMagFilter(GLenum aMagFilter) {
         mMagFilter = aMagFilter;
-        SetDontKnowIfNeedFakeBlack();
+        SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
     }
     void SetWrapS(GLenum aWrapS) {
         mWrapS = aWrapS;
-        SetDontKnowIfNeedFakeBlack();
+        SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
     }
     void SetWrapT(GLenum aWrapT) {
         mWrapT = aWrapT;
-        SetDontKnowIfNeedFakeBlack();
+        SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
     }
     GLenum MinFilter() const { return mMinFilter; }
 
     bool DoesMinFilterRequireMipmap() const {
         return !(mMinFilter == LOCAL_GL_NEAREST || mMinFilter == LOCAL_GL_LINEAR);
     }
 
     void SetGeneratedMipmap();
@@ -238,14 +267,20 @@ public:
     bool AreAllLevel0ImageInfosEqual() const;
 
     bool IsMipmapTexture2DComplete() const;
 
     bool IsCubeComplete() const;
 
     bool IsMipmapCubeComplete() const;
 
-    bool NeedFakeBlack();
+    void SetFakeBlackStatus(WebGLTextureFakeBlackStatus x) {
+        mFakeBlackStatus = x;
+        mContext->SetFakeBlackStatus(WebGLContextFakeBlackStatus::Unknown);
+    }
+    // Returns the current fake-black-status, except if it was Unknown,
+    // in which case this function resolves it first, so it never returns Unknown.
+    WebGLTextureFakeBlackStatus ResolvedFakeBlackStatus();
 };
 
 } // namespace mozilla
 
 #endif
--- a/content/canvas/src/WebGLTypes.h
+++ b/content/canvas/src/WebGLTypes.h
@@ -1,45 +1,106 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef WEBGLTYPES_H_
 #define WEBGLTYPES_H_
 
+#include "mozilla/TypedEnum.h"
+
 // Most WebIDL typedefs are identical to their OpenGL counterparts.
 #include "GLTypes.h"
 
 // Manual reflection of WebIDL typedefs that are different from their
 // OpenGL counterparts.
 typedef int64_t WebGLsizeiptr;
 typedef int64_t WebGLintptr;
 typedef bool WebGLboolean;
 
 namespace mozilla {
 
-enum FakeBlackStatus { DoNotNeedFakeBlack, DoNeedFakeBlack, DontKnowIfNeedFakeBlack };
+/*
+ * WebGLContextFakeBlackStatus and WebGLTextureFakeBlackStatus are enums to
+ * track what needs to use a dummy 1x1 black texture, which we refer to as a
+ * 'fake black' texture.
+ *
+ * There are generally two things that can cause us to use such 'fake black'
+ * textures:
+ *
+ *   (1) OpenGL ES rules on sampling incomplete textures specify that they
+ *       must be sampled as RGBA(0, 0, 0, 1) (opaque black). We have to implement these rules
+ *       ourselves, if only because we do not always run on OpenGL ES, and also
+ *       because this is dangerously close to the kind of case where we don't
+ *       want to trust the driver with corner cases of texture memory accesses.
+ *
+ *   (2) OpenGL has cases where a renderbuffer, or a texture image, can contain
+ *       uninitialized image data. See below the comment about WebGLImageDataStatus.
+ *       WebGL must never have access to uninitialized image data. The WebGL 1 spec,
+ *       section 4.1 'Resource Restrictions', specifies that in any such case, the
+ *       uninitialized image data must be exposed to WebGL as if it were filled
+ *       with zero bytes, which means it's either opaque or transparent black
+ *       depending on whether the image format has alpha.
+ *
+ * Why are there _two_ separate enums there, WebGLContextFakeBlackStatus
+ * and WebGLTextureFakeBlackStatus? That's because each texture must know the precise
+ * reason why it needs to be faked (incomplete texture vs. uninitialized image data),
+ * whereas the WebGL context can only know whether _any_ faking is currently needed at all.
+ */
+MOZ_BEGIN_ENUM_CLASS(WebGLContextFakeBlackStatus, int)
+  Unknown,
+  NotNeeded,
+  Needed
+MOZ_END_ENUM_CLASS(WebGLContextFakeBlackStatus)
 
-struct VertexAttrib0Status {
-    enum { Default, EmulatedUninitializedArray, EmulatedInitializedArray };
-};
+MOZ_BEGIN_ENUM_CLASS(WebGLTextureFakeBlackStatus, int)
+  Unknown,
+  NotNeeded,
+  IncompleteTexture,
+  UninitializedImageData
+MOZ_END_ENUM_CLASS(WebGLTextureFakeBlackStatus)
 
-namespace WebGLTexelConversions {
+/*
+ * Implementing WebGL (or OpenGL ES 2.0) on top of desktop OpenGL requires
+ * emulating the vertex attrib 0 array when it's not enabled. Indeed,
+ * OpenGL ES 2.0 allows drawing without vertex attrib 0 array enabled, but
+ * desktop OpenGL does not allow that.
+ */
+MOZ_BEGIN_ENUM_CLASS(WebGLVertexAttrib0Status, int)
+    Default, // default status - no emulation needed
+    EmulatedUninitializedArray, // need an artificial attrib 0 array, but contents may be left uninitialized
+    EmulatedInitializedArray // need an artificial attrib 0 array, and contents must be initialized
+MOZ_END_ENUM_CLASS(WebGLVertexAttrib0Status)
+
+/*
+ * Enum to track the status of image data (renderbuffer or texture image) presence
+ * and initialization.
+ *
+ * - NoImageData is the initial state before any image data is allocated.
+ * - InitializedImageData is the state after image data is allocated and initialized.
+ * - UninitializedImageData is an intermediate state where data is allocated but not
+ *   initialized. It is the state that renderbuffers are in after a renderbufferStorage call,
+ *   and it is the state that texture images are in after a texImage2D call with null data.
+ */
+MOZ_BEGIN_ENUM_CLASS(WebGLImageDataStatus, int)
+    NoImageData,
+    UninitializedImageData,
+    InitializedImageData
+MOZ_END_ENUM_CLASS(WebGLImageDataStatus)
 
 /*
  * The formats that may participate, either as source or destination formats,
  * in WebGL texture conversions. This includes:
  *  - all the formats accepted by WebGL.texImage2D, e.g. RGBA4444
  *  - additional formats provided by extensions, e.g. RGB32F
  *  - additional source formats, depending on browser details, used when uploading
  *    textures from DOM elements. See gfxImageSurface::Format().
  */
-enum WebGLTexelFormat
-{
+MOZ_BEGIN_ENUM_CLASS(WebGLTexelFormat, int)
     // dummy error code returned by GetWebGLTexelFormat in error cases,
     // after assertion failure (so this never happens in debug builds)
     BadFormat,
     // dummy pseudo-format meaning "use the other format".
     // For example, if SrcFormat=Auto and DstFormat=RGB8, then the source
     // is implicitly treated as being RGB8 itself.
     Auto,
     // 1-channel formats
@@ -59,15 +120,13 @@ enum WebGLTexelFormat
     RGB565,
     RGB32F, // used for OES_texture_float extension
     // 4-channel formats
     RGBA8,
     BGRA8, // used for DOM elements
     RGBA5551,
     RGBA4444,
     RGBA32F // used for OES_texture_float extension
-};
-
-} // end namespace WebGLTexelConversions
+MOZ_END_ENUM_CLASS(WebGLTexelFormat)
 
 } // namespace mozilla
 
 #endif
--- a/content/canvas/src/WebGLUniformInfo.h
+++ b/content/canvas/src/WebGLUniformInfo.h
@@ -39,17 +39,17 @@ struct WebGLUniformInfo {
             case SH_BOOL_VEC4:
             case SH_FLOAT_MAT2:
                 return 4;
             case SH_FLOAT_MAT3:
                 return 9;
             case SH_FLOAT_MAT4:
                 return 16;
             default:
-                NS_ABORT(); // should never get here
+                MOZ_ASSERT(false); // should never get here
                 return 0;
         }
     }
 };
 
 } // namespace mozilla
 
 #endif
--- a/content/canvas/src/WebGLVertexArray.cpp
+++ b/content/canvas/src/WebGLVertexArray.cpp
@@ -29,36 +29,36 @@ void WebGLVertexArray::Delete() {
         mBoundElementArrayBuffer = nullptr;
 
         mContext->MakeContextCurrent();
         mContext->gl->fDeleteVertexArrays(1, &mGLName);
         LinkedListElement<WebGLVertexArray>::removeFrom(mContext->mVertexArrays);
     }
 
     mBoundElementArrayBuffer = nullptr;
-    mAttribBuffers.Clear();
+    mAttribs.Clear();
 }
 
-bool WebGLVertexArray::EnsureAttribIndex(GLuint index, const char *info)
+bool WebGLVertexArray::EnsureAttrib(GLuint index, const char *info)
 {
     if (index >= GLuint(mContext->mGLMaxVertexAttribs)) {
         if (index == GLuint(-1)) {
             mContext->ErrorInvalidValue("%s: index -1 is invalid. That probably comes from a getAttribLocation() call, "
                                         "where this return value -1 means that the passed name didn't correspond to an active attribute in "
                                         "the specified program.", info);
         } else {
             mContext->ErrorInvalidValue("%s: index %d is out of range", info, index);
         }
         return false;
     }
-    else if (index >= mAttribBuffers.Length()) {
-        mAttribBuffers.SetLength(index + 1);
+    else if (index >= mAttribs.Length()) {
+        mAttribs.SetLength(index + 1);
     }
 
     return true;
 }
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_2(WebGLVertexArray,
-  mAttribBuffers,
+  mAttribs,
   mBoundElementArrayBuffer)
 
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLVertexArray, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WebGLVertexArray, Release)
--- a/content/canvas/src/WebGLVertexArray.h
+++ b/content/canvas/src/WebGLVertexArray.h
@@ -54,29 +54,35 @@ public:
 
     // -------------------------------------------------------------------------
     // MEMBER FUNCTIONS
 
     bool HasEverBeenBound() { return mHasEverBeenBound; }
     void SetHasEverBeenBound(bool x) { mHasEverBeenBound = x; }
     GLuint GLName() const { return mGLName; }
 
-    bool EnsureAttribIndex(GLuint index, const char *info);
+    bool EnsureAttrib(GLuint index, const char *info);
+    bool HasAttrib(GLuint index) {
+        return index < mAttribs.Length();
+    }
+    bool IsAttribArrayEnabled(GLuint index) {
+        return HasAttrib(index) && mAttribs[index].enabled;
+    }
 
 
 // -----------------------------------------------------------------------------
 // PRIVATE
 private:
 
     // -------------------------------------------------------------------------
     // MEMBERS
 
     GLuint mGLName;
     bool mHasEverBeenBound;
-    nsTArray<WebGLVertexAttribData> mAttribBuffers;
+    nsTArray<WebGLVertexAttribData> mAttribs;
     WebGLRefPtr<WebGLBuffer> mBoundElementArrayBuffer;
 
 
     // -------------------------------------------------------------------------
     // FRIENDSHIPS
 
     friend class WebGLContext;
 };
--- a/content/media/webaudio/AudioContext.cpp
+++ b/content/media/webaudio/AudioContext.cpp
@@ -603,10 +603,22 @@ AudioContext::Mute() const
 
 void
 AudioContext::Unmute() const
 {
   MOZ_ASSERT(!mIsOffline);
   mDestination->Unmute();
 }
 
+AudioChannel
+AudioContext::MozAudioChannelType() const
+{
+  return mDestination->MozAudioChannelType();
+}
+
+void
+AudioContext::SetMozAudioChannelType(AudioChannel aValue, ErrorResult& aRv)
+{
+  mDestination->SetMozAudioChannelType(aValue, aRv);
+}
+
 }
 }
--- a/content/media/webaudio/AudioContext.h
+++ b/content/media/webaudio/AudioContext.h
@@ -2,16 +2,17 @@
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef AudioContext_h_
 #define AudioContext_h_
 
+#include "mozilla/dom/AudioContextBinding.h"
 #include "EnableWebAudioCheck.h"
 #include "MediaBufferDecoder.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/TypedArray.h"
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsDOMEventTargetHelper.h"
@@ -233,16 +234,19 @@ public:
 
   uint32_t MaxChannelCount() const;
 
   void Mute() const;
   void Unmute() const;
 
   JSContext* GetJSContext() const;
 
+  AudioChannel MozAudioChannelType() const;
+  void SetMozAudioChannelType(AudioChannel aValue, ErrorResult& aRv);
+
 private:
   void RemoveFromDecodeQueue(WebAudioDecodeJob* aDecodeJob);
   void ShutdownDecoder();
 
   friend struct ::mozilla::WebAudioDecodeJob;
 
 private:
   // Note that it's important for mSampleRate to be initialized before
--- a/content/media/webaudio/AudioDestinationNode.cpp
+++ b/content/media/webaudio/AudioDestinationNode.cpp
@@ -9,17 +9,19 @@
 #include "mozilla/Preferences.h"
 #include "AudioChannelAgent.h"
 #include "AudioNodeEngine.h"
 #include "AudioNodeStream.h"
 #include "MediaStreamGraph.h"
 #include "OfflineAudioCompletionEvent.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIDocShell.h"
-#include "nsIDocument.h"
+#include "nsIPermissionManager.h"
+#include "nsIScriptObjectPrincipal.h"
+#include "nsServiceManagerUtils.h"
 
 namespace mozilla {
 namespace dom {
 
 class OfflineDestinationNodeEngine : public AudioNodeEngine
 {
 public:
   typedef AutoFallibleTArray<nsAutoArrayPtr<float>, 2> InputChannels;
@@ -239,49 +241,37 @@ AudioDestinationNode::AudioDestinationNo
                                            uint32_t aNumberOfChannels,
                                            uint32_t aLength,
                                            float aSampleRate)
   : AudioNode(aContext,
               aIsOffline ? aNumberOfChannels : 2,
               ChannelCountMode::Explicit,
               ChannelInterpretation::Speakers)
   , mFramesToProduce(aLength)
+  , mAudioChannel(AudioChannel::Normal)
 {
   MediaStreamGraph* graph = aIsOffline ?
                             MediaStreamGraph::CreateNonRealtimeInstance() :
                             MediaStreamGraph::GetInstance();
   AudioNodeEngine* engine = aIsOffline ?
                             new OfflineDestinationNodeEngine(this, aNumberOfChannels,
                                                              aLength, aSampleRate) :
                             static_cast<AudioNodeEngine*>(new DestinationNodeEngine(this));
 
   mStream = graph->CreateAudioNodeStream(engine, MediaStreamGraph::EXTERNAL_STREAM);
 
   if (!aIsOffline && UseAudioChannelService()) {
-    mAudioChannelAgent = new AudioChannelAgent();
-    mAudioChannelAgent->InitWithWeakCallback(nsIAudioChannelAgent::AUDIO_AGENT_CHANNEL_NORMAL,
-                                             this);
-
     nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(GetOwner());
     if (target) {
       target->AddSystemEventListener(NS_LITERAL_STRING("visibilitychange"), this,
                                      /* useCapture = */ true,
                                      /* wantsUntrusted = */ false);
     }
 
-    nsCOMPtr<nsIDocShell> docshell = do_GetInterface(GetOwner());
-    if (docshell) {
-      bool isActive = false;
-      docshell->GetIsActive(&isActive);
-      mAudioChannelAgent->SetVisibilityState(isActive);
-    }
-
-    int32_t state = 0;
-    mAudioChannelAgent->StartPlaying(&state);
-    SetCanPlay(state == AudioChannelState::AUDIO_CHANNEL_STATE_NORMAL);
+    CreateAudioChannelAgent();
   }
 }
 
 void
 AudioDestinationNode::DestroyMediaStream()
 {
   if (mAudioChannelAgent && !Context()->IsOffline()) {
     mAudioChannelAgent->StopPlaying();
@@ -386,10 +376,122 @@ AudioDestinationNode::HandleEvent(nsIDOM
 
 NS_IMETHODIMP
 AudioDestinationNode::CanPlayChanged(int32_t aCanPlay)
 {
   SetCanPlay(aCanPlay == AudioChannelState::AUDIO_CHANNEL_STATE_NORMAL);
   return NS_OK;
 }
 
+AudioChannel
+AudioDestinationNode::MozAudioChannelType() const
+{
+  return mAudioChannel;
+}
+
+void
+AudioDestinationNode::SetMozAudioChannelType(AudioChannel aValue, ErrorResult& aRv)
+{
+  if (Context()->IsOffline()) {
+    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+    return;
+  }
+
+  if (aValue != mAudioChannel &&
+      CheckAudioChannelPermissions(aValue)) {
+    mAudioChannel = aValue;
+
+    if (mAudioChannelAgent) {
+      CreateAudioChannelAgent();
+    }
+  }
+}
+
+bool
+AudioDestinationNode::CheckAudioChannelPermissions(AudioChannel aValue)
+{
+  if (!Preferences::GetBool("media.useAudioChannelService")) {
+    return true;
+  }
+
+  // Only normal channel doesn't need permission.
+  if (aValue == AudioChannel::Normal) {
+    return true;
+  }
+
+  nsCOMPtr<nsIPermissionManager> permissionManager =
+    do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
+  if (!permissionManager) {
+    return false;
+  }
+
+  nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(GetOwner());
+  NS_ASSERTION(sop, "Window didn't QI to nsIScriptObjectPrincipal!");
+  nsCOMPtr<nsIPrincipal> principal = sop->GetPrincipal();
+
+  uint32_t perm = nsIPermissionManager::UNKNOWN_ACTION;
+
+  nsCString channel;
+  channel.AssignASCII(AudioChannelValues::strings[uint32_t(aValue)].value,
+                      AudioChannelValues::strings[uint32_t(aValue)].length);
+  permissionManager->TestExactPermissionFromPrincipal(principal,
+    nsCString(NS_LITERAL_CSTRING("audio-channel-") + channel).get(),
+    &perm);
+
+  return perm == nsIPermissionManager::ALLOW_ACTION;
+}
+
+void
+AudioDestinationNode::CreateAudioChannelAgent()
+{
+  if (mAudioChannelAgent) {
+    mAudioChannelAgent->StopPlaying();
+  }
+
+  AudioChannelType type = AUDIO_CHANNEL_NORMAL;
+  switch(mAudioChannel) {
+    case AudioChannel::Normal:
+      type = AUDIO_CHANNEL_NORMAL;
+      break;
+
+    case AudioChannel::Content:
+      type = AUDIO_CHANNEL_CONTENT;
+      break;
+
+    case AudioChannel::Notification:
+      type = AUDIO_CHANNEL_NOTIFICATION;
+      break;
+
+    case AudioChannel::Alarm:
+      type = AUDIO_CHANNEL_ALARM;
+      break;
+
+    case AudioChannel::Telephony:
+      type = AUDIO_CHANNEL_TELEPHONY;
+      break;
+
+    case AudioChannel::Ringer:
+      type = AUDIO_CHANNEL_RINGER;
+      break;
+
+    case AudioChannel::Publicnotification:
+      type = AUDIO_CHANNEL_PUBLICNOTIFICATION;
+      break;
+
+  }
+
+  mAudioChannelAgent = new AudioChannelAgent();
+  mAudioChannelAgent->InitWithWeakCallback(type, this);
+
+  nsCOMPtr<nsIDocShell> docshell = do_GetInterface(GetOwner());
+  if (docshell) {
+    bool isActive = false;
+    docshell->GetIsActive(&isActive);
+    mAudioChannelAgent->SetVisibilityState(isActive);
+  }
+
+  int32_t state = 0;
+  mAudioChannelAgent->StartPlaying(&state);
+  SetCanPlay(state == AudioChannelState::AUDIO_CHANNEL_STATE_NORMAL);
 }
 }
+
+}
--- a/content/media/webaudio/AudioDestinationNode.h
+++ b/content/media/webaudio/AudioDestinationNode.h
@@ -2,19 +2,21 @@
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef AudioDestinationNode_h_
 #define AudioDestinationNode_h_
 
+#include "mozilla/dom/AudioContextBinding.h"
 #include "AudioNode.h"
 #include "nsIDOMEventListener.h"
 #include "nsIAudioChannelAgent.h"
+#include "AudioChannelCommon.h"
 
 namespace mozilla {
 namespace dom {
 
 class AudioContext;
 
 class AudioDestinationNode : public AudioNode
                            , public nsIDOMEventListener
@@ -54,22 +56,31 @@ public:
   void OfflineShutdown();
 
   // nsIDOMEventListener
   NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
 
   // nsIAudioChannelAgentCallback
   NS_IMETHOD CanPlayChanged(int32_t aCanPlay);
 
+  AudioChannel MozAudioChannelType() const;
+  void SetMozAudioChannelType(AudioChannel aValue, ErrorResult& aRv);
+
 private:
+  bool CheckAudioChannelPermissions(AudioChannel aValue);
+  void CreateAudioChannelAgent();
+
   void SetCanPlay(bool aCanPlay);
 
   SelfReference<AudioDestinationNode> mOfflineRenderingRef;
   uint32_t mFramesToProduce;
 
   nsCOMPtr<nsIAudioChannelAgent> mAudioChannelAgent;
+
+  // Audio Channel Type.
+  AudioChannel mAudioChannel;
 };
 
 }
 }
 
 #endif
 
--- a/content/media/webaudio/test/mochitest.ini
+++ b/content/media/webaudio/test/mochitest.ini
@@ -105,8 +105,9 @@ support-files =
 [test_scriptProcessorNode.html]
 [test_scriptProcessorNodeChannelCount.html]
 [test_scriptProcessorNodeZeroInputOutput.html]
 [test_singleSourceDest.html]
 [test_waveShaper.html]
 [test_waveShaperNoCurve.html]
 [test_waveShaperZeroLengthCurve.html]
 [test_audioDestinationNode.html]
+[test_mozaudiochannel.html]
new file mode 100644
--- /dev/null
+++ b/content/media/webaudio/test/test_mozaudiochannel.html
@@ -0,0 +1,90 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for mozaudiochannel</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<pre id="test">
+<script type="application/javascript">
+
+function test_basic() {
+  var ac = new AudioContext();
+  ok(ac, "AudioContext created");
+
+  // Default
+  is(ac.mozAudioChannelType, "normal", "Default ac channel == 'normal'");
+
+  // random wrong channel
+  ac.mozAudioChannelType = "foo";
+  is(ac.mozAudioChannelType, "normal", "Default ac channel == 'normal'");
+
+  // Unpermitted channels
+  ac.mozAudioChannelType = "content";
+  is(ac.mozAudioChannelType, "normal", "Default ac channel == 'normal'");
+
+  ac.mozAudioChannelType = "notification";
+  is(ac.mozAudioChannelType, "normal", "Default ac channel == 'normal'");
+
+  ac.mozAudioChannelType = "alarm";
+  is(ac.mozAudioChannelType, "normal", "Default ac channel == 'normal'");
+
+  ac.mozAudioChannelType = "telephony";
+  is(ac.mozAudioChannelType, "normal", "Default ac channel == 'normal'");
+
+  ac.mozAudioChannelType = "ringer";
+  is(ac.mozAudioChannelType, "normal", "Default ac channel == 'normal'");
+
+  ac.mozAudioChannelType = "publicnotification";
+  is(ac.mozAudioChannelType, "normal", "Default ac channel == 'normal'");
+
+  runTest();
+}
+
+function test_permission(aChannel) {
+  var ac = new AudioContext();
+  ok(ac, "AudioContext created");
+
+  is(ac.mozAudioChannelType, "normal", "Default ac channel == 'normal'");
+
+  SpecialPowers.pushPermissions(
+    [{ "type": "audio-channel-" + aChannel, "allow": 1, "context": document }],
+    function() {
+      ac.mozAudioChannelType = aChannel;
+      is(ac.mozAudioChannelType, aChannel, "Default ac channel == '" + aChannel + "'");
+      runTest();
+    }
+  );
+}
+
+var tests = [
+  test_basic,
+
+  function() { test_permission("content"); },
+  function() { test_permission("notification"); },
+  function() { test_permission("alarm"); },
+  function() { test_permission("telephony"); },
+  function() { test_permission("ringer"); },
+  function() { test_permission("publicnotification"); }
+];
+
+function runTest() {
+  if (!tests.length) {
+    SimpleTest.finish();
+    return;
+  }
+
+  var test = tests.shift();
+  test();
+}
+
+SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelService", true ]]}, runTest);
+SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+</body>
+</html>
--- a/dom/webidl/AudioContext.webidl
+++ b/dom/webidl/AudioContext.webidl
@@ -93,9 +93,24 @@ partial interface AudioContext {
 
     // Same as createScriptProcessor()
     [Creator, Throws, Pref="media.webaudio.legacy.AudioContext"]
     ScriptProcessorNode createJavaScriptNode(optional unsigned long bufferSize = 0,
                                              optional unsigned long numberOfInputChannels = 2,
                                              optional unsigned long numberOfOutputChannels = 2);
 };
 
+enum AudioChannel {
+  "normal",
+  "content",
+  "notification",
+  "alarm",
+  "telephony",
+  "ringer",
+  "publicnotification",
+};
 
+// Mozilla extensions
+partial interface AudioContext {
+  // Read HTMLMediaElement.webidl for more information about this attribute.
+  [Pref="media.useAudioChannelService", SetterThrows]
+  attribute AudioChannel mozAudioChannelType;
+};
--- a/gfx/2d/DrawTargetCG.cpp
+++ b/gfx/2d/DrawTargetCG.cpp
@@ -376,50 +376,107 @@ class GradientStopsCG : public GradientS
 
 TemporaryRef<GradientStops>
 DrawTargetCG::CreateGradientStops(GradientStop *aStops, uint32_t aNumStops,
                                   ExtendMode aExtendMode) const
 {
   return new GradientStopsCG(aStops, aNumStops, aExtendMode);
 }
 
+static void
+UpdateLinearParametersToIncludePoint(double *min_t, double *max_t,
+                                     CGPoint *start,
+                                     double dx, double dy,
+                                     double x, double y)
+{
+  /**
+   * Compute a parameter t such that a line perpendicular to the (dx,dy)
+   * vector, passing through (start->x + dx*t, start->y + dy*t), also
+   * passes through (x,y).
+   *
+   * Let px = x - start->x, py = y - start->y.
+   * t is given by
+   *   (px - dx*t)*dx + (py - dy*t)*dy = 0
+   *
+   * Solving for t we get
+   *   numerator = dx*px + dy*py
+   *   denominator = dx^2 + dy^2
+   *   t = numerator/denominator
+   *
+   * In CalculateRepeatingGradientParams we know the length of (dx,dy)
+   * is not zero. (This is checked in DrawLinearRepeatingGradient.)
+   */
+  double px = x - start->x;
+  double py = y - start->y;
+  double numerator = dx * px + dy * py;
+  double denominator = dx * dx + dy * dy;
+  double t = numerator / denominator;
+
+  if (*min_t > t) {
+    *min_t = t;
+  }
+  if (*max_t < t) {
+    *max_t = t;
+  }
+}
+
+/**
+ * Repeat the gradient line such that lines extended perpendicular to the
+ * gradient line at both start and end would completely enclose the drawing
+ * extents.
+ */
+static void
+CalculateRepeatingGradientParams(CGPoint *aStart, CGPoint *aEnd,
+                                 CGRect aExtents, int *aRepeatCount)
+{
+  double t_min = 0.;
+  double t_max = 0.;
+  double dx = aEnd->x - aStart->x;
+  double dy = aEnd->y - aStart->y;
+
+  double bounds_x1 = aExtents.origin.x;
+  double bounds_y1 = aExtents.origin.y;
+  double bounds_x2 = aExtents.origin.x + aExtents.size.width;
+  double bounds_y2 = aExtents.origin.y + aExtents.size.height;
+
+  UpdateLinearParametersToIncludePoint(&t_min, &t_max, aStart, dx, dy,
+                                       bounds_x1, bounds_y1);
+  UpdateLinearParametersToIncludePoint(&t_min, &t_max, aStart, dx, dy,
+                                       bounds_x2, bounds_y1);
+  UpdateLinearParametersToIncludePoint(&t_min, &t_max, aStart, dx, dy,
+                                       bounds_x2, bounds_y2);
+  UpdateLinearParametersToIncludePoint(&t_min, &t_max, aStart, dx, dy,
+                                       bounds_x1, bounds_y2);
+
+  // Move t_min and t_max to the nearest usable integer to try to avoid
+  // subtle variations due to numerical instability, especially accidentally
+  // cutting off a pixel. Extending the gradient repetitions is always safe.
+  t_min = floor (t_min);
+  t_max = ceil (t_max);
+  aEnd->x = aStart->x + dx * t_max;
+  aEnd->y = aStart->y + dy * t_max;
+  aStart->x = aStart->x + dx * t_min;
+  aStart->y = aStart->y + dy * t_min;
+
+  *aRepeatCount = t_max - t_min;
+}
 
 static void
 DrawLinearRepeatingGradient(CGContextRef cg, const LinearGradientPattern &aPattern, const CGRect &aExtents)
 {
   GradientStopsCG *stops = static_cast<GradientStopsCG*>(aPattern.mStops.get());
   CGPoint startPoint = { aPattern.mBegin.x, aPattern.mBegin.y };
   CGPoint endPoint = { aPattern.mEnd.x, aPattern.mEnd.y };
 
-  // extend the gradient line in multiples of the existing length in both
-  // directions until it crosses an edge of the extents box.
-  double xDiff = aPattern.mEnd.x - aPattern.mBegin.x;
-  double yDiff = aPattern.mEnd.y - aPattern.mBegin.y;
-
   int repeatCount = 1;
   // if we don't have a line then we can't extend it
-  if (xDiff || yDiff) {
-    while (startPoint.x > aExtents.origin.x
-           && startPoint.y > aExtents.origin.y
-           && startPoint.x < (aExtents.origin.x+aExtents.size.width)
-           && startPoint.y < (aExtents.origin.y+aExtents.size.height))
-    {
-      startPoint.x -= xDiff;
-      startPoint.y -= yDiff;
-      repeatCount++;
-    }
-    while (endPoint.x > aExtents.origin.x
-           && endPoint.y > aExtents.origin.y
-           && endPoint.x < (aExtents.origin.x+aExtents.size.width)
-           && endPoint.y < (aExtents.origin.y+aExtents.size.height))
-    {
-      endPoint.x += xDiff;
-      endPoint.y += yDiff;
-      repeatCount++;
-    }
+  if (aPattern.mEnd.x != aPattern.mBegin.x ||
+      aPattern.mEnd.y != aPattern.mBegin.y) {
+    CalculateRepeatingGradientParams(&startPoint, &endPoint, aExtents,
+                                     &repeatCount);
   }
 
   double scale = 1./repeatCount;
 
   std::vector<CGFloat> colors;
   std::vector<CGFloat> offsets;
   colors.reserve(stops->mStops.size()*repeatCount*4);
   offsets.reserve(stops->mStops.size()*repeatCount);
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -2489,17 +2489,16 @@ public:
                                    GraphicsFilter aFilter);
 
     virtual bool BindExternalBuffer(GLuint texture, void* buffer) { return false; }
     virtual bool UnbindExternalBuffer(GLuint texture) { return false; }
 
 #ifdef MOZ_WIDGET_GONK
     virtual EGLImage CreateEGLImageForNativeBuffer(void* buffer) = 0;
     virtual void DestroyEGLImage(EGLImage image) = 0;
-    virtual EGLImage GetNullEGLImage() = 0;
 #endif
 
     virtual already_AddRefed<TextureImage>
     CreateDirectTextureImage(android::GraphicBuffer* aBuffer, GLenum aWrapMode)
     { return nullptr; }
 
     // Before reads from offscreen texture
     void GuaranteeResolve();
@@ -3574,23 +3573,23 @@ struct ScopedBindTexture
     friend struct ScopedGLWrapper<ScopedBindTexture>;
 
 protected:
     GLuint mOldTex;
     GLenum mTarget;
 
 private:
     void Init(GLenum target) {
-        MOZ_ASSERT(target == LOCAL_GL_TEXTURE_2D ||
-                   target == LOCAL_GL_TEXTURE_RECTANGLE_ARB);
         mTarget = target;
         mOldTex = 0;
-        GLenum bindingTarget = (target == LOCAL_GL_TEXTURE_2D) ?
-                               LOCAL_GL_TEXTURE_BINDING_2D :
-                               LOCAL_GL_TEXTURE_BINDING_RECTANGLE_ARB;
+        GLenum bindingTarget = (target == LOCAL_GL_TEXTURE_2D) ? LOCAL_GL_TEXTURE_BINDING_2D
+                             : (target == LOCAL_GL_TEXTURE_RECTANGLE_ARB) ? LOCAL_GL_TEXTURE_BINDING_RECTANGLE_ARB
+                             : (target == LOCAL_GL_TEXTURE_CUBE_MAP) ? LOCAL_GL_TEXTURE_BINDING_CUBE_MAP
+                             : LOCAL_GL_NONE;
+        MOZ_ASSERT(bindingTarget != LOCAL_GL_NONE);
         mGL->GetUIntegerv(bindingTarget, &mOldTex);
     }
 
 public:
     ScopedBindTexture(GLContext* gl, GLuint newTex, GLenum target = LOCAL_GL_TEXTURE_2D)
         : ScopedGLWrapper<ScopedBindTexture>(gl)
     {
         Init(target);
--- a/gfx/gl/GLContextProviderEGL.cpp
+++ b/gfx/gl/GLContextProviderEGL.cpp
@@ -1,41 +1,28 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "GLContext.h"
 #include "mozilla/Util.h"
-// please add new includes below Qt, otherwise it break Qt build due malloc wrapper conflicts
 
 #if defined(XP_UNIX)
 
 #ifdef MOZ_WIDGET_GTK
 #include <gdk/gdkx.h>
 // we're using default display for now
 #define GET_NATIVE_WINDOW(aWidget) (EGLNativeWindowType)GDK_WINDOW_XID((GdkWindow *) aWidget->GetNativeData(NS_NATIVE_WINDOW))
-#elif defined(MOZ_WIDGET_QT)
-#include <QtOpenGL/QGLContext>
-#define GLdouble_defined 1
-// we're using default display for now
-#define GET_NATIVE_WINDOW(aWidget) (EGLNativeWindowType)static_cast<QWidget*>(aWidget->GetNativeData(NS_NATIVE_SHELLWIDGET))->winId()
 #elif defined(MOZ_WIDGET_GONK)
 #define GET_NATIVE_WINDOW(aWidget) ((EGLNativeWindowType)aWidget->GetNativeData(NS_NATIVE_WINDOW))
 #include "HwcComposer2D.h"
 #include "libdisplay/GonkDisplay.h"
 #endif
 
-#if defined(MOZ_X11)
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include "mozilla/X11Util.h"
-#include "gfxXlibSurface.h"
-#endif
-
 #if defined(ANDROID)
 /* from widget */
 #if defined(MOZ_WIDGET_ANDROID)
 #include "AndroidBridge.h"
 #include "nsSurfaceTexture.h"
 #endif
 
 #include <android/log.h>
@@ -109,63 +96,49 @@ public:
 #include "mozilla/Preferences.h"
 #include "gfxUtils.h"
 #include "gfxFailure.h"
 #include "gfxASurface.h"
 #include "gfxImageSurface.h"
 #include "gfxPlatform.h"
 #include "GLContextProvider.h"
 #include "GLLibraryEGL.h"
+#include "TextureImageEGL.h"
 #include "nsDebug.h"
 #include "nsThreadUtils.h"
 
 #include "nsIWidget.h"
 
 #include "gfxCrashReporterUtils.h"
 
 using namespace mozilla::gfx;
 
-#if defined(MOZ_WIDGET_GONK)
-static bool gUseBackingSurface = true;
-#else
-static bool gUseBackingSurface = false;
-#endif
-
 #ifdef MOZ_WIDGET_GONK
 extern nsIntRect gScreenBounds;
 #endif
 
-#define EGL_DISPLAY()        sEGLLibrary.Display()
-
 namespace mozilla {
 namespace gl {
 
-static GLLibraryEGL sEGLLibrary;
-
 #define ADD_ATTR_2(_array, _k, _v) do {         \
     (_array).AppendElement(_k);                 \
     (_array).AppendElement(_v);                 \
 } while (0)
 
 #define ADD_ATTR_1(_array, _k) do {             \
     (_array).AppendElement(_k);                 \
 } while (0)
 
 #ifndef MOZ_ANDROID_OMTC
 static EGLSurface
 CreateSurfaceForWindow(nsIWidget *aWidget, EGLConfig config);
 #endif
 
 static bool
 CreateConfig(EGLConfig* aConfig);
-#ifdef MOZ_X11
-
-static EGLConfig
-CreateEGLSurfaceForXSurface(gfxASurface* aSurface, EGLConfig* aConfig = nullptr);
-#endif
 
 static EGLint gContextAttribs[] = {
     LOCAL_EGL_CONTEXT_CLIENT_VERSION, 2,
     LOCAL_EGL_NONE
 };
 
 static EGLint gContextAttribsRobustness[] = {
     LOCAL_EGL_CONTEXT_CLIENT_VERSION, 2,
@@ -331,23 +304,16 @@ public:
 #if defined(XP_UNIX)
                 if (!OpenLibrary(GLES2_LIB2)) {
                     NS_WARNING("Couldn't load GLES2 LIB.");
                     return false;
                 }
 #endif
             }
 
-#ifdef MOZ_WIDGET_GONK
-        char propValue[PROPERTY_VALUE_MAX];
-        property_get("ro.build.version.sdk", propValue, "0");
-        if (atoi(propValue) < 15)
-            gUseBackingSurface = false;
-#endif
-
         bool current = MakeCurrent();
         if (!current) {
             gfx::LogFailure(NS_LITERAL_CSTRING(
                 "Couldn't get device attachments for device."));
             return false;
         }
 
         SetupLookupFunction();
@@ -439,36 +405,16 @@ public:
                                         LOCAL_EGL_NATIVE_BUFFER_ANDROID,
                                         buffer, attrs);
     }
 
     void DestroyEGLImage(EGLImage image) MOZ_OVERRIDE
     {
         sEGLLibrary.fDestroyImage(EGL_DISPLAY(), image);
     }
-
-    EGLImage GetNullEGLImage() MOZ_OVERRIDE
-    {
-        if (!mNullGraphicBuffer.get()) {
-            mNullGraphicBuffer
-              = new android::GraphicBuffer(
-                  1, 1,
-                  PIXEL_FORMAT_RGB_565,
-                  GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_NEVER);
-            EGLint attrs[] = {
-                LOCAL_EGL_NONE, LOCAL_EGL_NONE
-            };
-            mNullEGLImage = sEGLLibrary.fCreateImage(EGL_DISPLAY(),
-                                                     EGL_NO_CONTEXT,
-                                                     LOCAL_EGL_NATIVE_BUFFER_ANDROID,
-                                                     mNullGraphicBuffer->getNativeBuffer(),
-                                                     attrs);
-        }
-        return mNullEGLImage;
-    }
 #endif
 
     virtual void MakeCurrent_EGLSurface(void* surf) {
         EGLSurface eglSurface = (EGLSurface)surf;
         if (!eglSurface)
             eglSurface = mSurface;
 
         if (eglSurface == mCurSurface)
@@ -489,42 +435,17 @@ public:
     }
 
     bool MakeCurrentImpl(bool aForce = false) {
         bool succeeded = true;
 
         // Assume that EGL has the same problem as WGL does,
         // where MakeCurrent with an already-current context is
         // still expensive.
-#ifndef MOZ_WIDGET_QT
-        if (!mSurface) {
-            // We need to be able to bind NO_SURFACE when we don't
-            // have access to a surface. We won't be drawing to the screen
-            // but we will be able to do things like resource releases.
-            succeeded = sEGLLibrary.fMakeCurrent(EGL_DISPLAY(),
-                                                 EGL_NO_SURFACE, EGL_NO_SURFACE,
-                                                 EGL_NO_CONTEXT);
-            if (!succeeded && sEGLLibrary.fGetError() == LOCAL_EGL_CONTEXT_LOST) {
-                mContextLost = true;
-                NS_WARNING("EGL context has been lost.");
-            }
-            NS_ASSERTION(succeeded, "Failed to make GL context current!");
-            return succeeded;
-        }
-#endif
         if (aForce || sEGLLibrary.fGetCurrentContext() != mContext) {
-#ifdef MOZ_WIDGET_QT
-            // Shared Qt GL context need to be informed about context switch
-            if (mSharedContext) {
-                QGLContext* qglCtx = static_cast<QGLContext*>(static_cast<GLContextEGL*>(mSharedContext.get())->mPlatformContext);
-                if (qglCtx) {
-                    qglCtx->doneCurrent();
-                }
-            }
-#endif
             succeeded = sEGLLibrary.fMakeCurrent(EGL_DISPLAY(),
                                                  mCurSurface, mCurSurface,
                                                  mContext);
             
             int eglError = sEGLLibrary.fGetError();
             if (!succeeded) {
                 if (eglError == LOCAL_EGL_CONTEXT_LOST) {
                     mContextLost = true;
@@ -540,23 +461,16 @@ public:
 
         return succeeded;
     }
 
     virtual bool IsCurrent() {
         return sEGLLibrary.fGetCurrentContext() == mContext;
     }
 
-#ifdef MOZ_WIDGET_QT
-    virtual bool
-    RenewSurface() {
-        /* We don't support renewing on QT because we don't create the surface ourselves */
-        return false;
-    }
-#else
     virtual bool
     RenewSurface() {
         sEGLLibrary.fMakeCurrent(EGL_DISPLAY(), EGL_NO_SURFACE, EGL_NO_SURFACE,
                                  EGL_NO_CONTEXT);
         if (!mSurface) {
 #ifdef MOZ_ANDROID_OMTC
             mSurface = mozilla::AndroidBridge::Bridge()->ProvideEGLSurface();
             if (!mSurface) {
@@ -567,17 +481,16 @@ public:
             CreateConfig(&config);
             mSurface = CreateSurfaceForWindow(nullptr, config);
 #endif
         }
         return sEGLLibrary.fMakeCurrent(EGL_DISPLAY(),
                                         mSurface, mSurface,
                                         mContext);
     }
-#endif
 
     virtual void
     ReleaseSurface() {
         if (mSurface && !mPlatformContext) {
             sEGLLibrary.fMakeCurrent(EGL_DISPLAY(), EGL_NO_SURFACE, EGL_NO_SURFACE,
                                      EGL_NO_CONTEXT);
             sEGLLibrary.fDestroySurface(EGL_DISPLAY(), mSurface);
             mSurface = nullptr;
@@ -682,28 +595,16 @@ protected:
     bool mBound;
 
     bool mIsPBuffer;
     bool mIsDoubleBuffered;
     bool mCanBindToTexture;
     bool mShareWithEGLImage;
 #ifdef MOZ_WIDGET_GONK
     nsRefPtr<HwcComposer2D> mHwc;
-
-    /* mNullEGLImage and mNullGraphicBuffer are a hack to unattach a gralloc buffer
-     * from a texture, which we don't know how to do otherwise (at least in the
-     * TEXTURE_EXTERNAL case --- in the TEXTURE_2D case we could also use TexImage2D).
-     *
-     * So mNullGraphicBuffer will be initialized once to be a 1x1 gralloc buffer,
-     * and mNullEGLImage will be initialized once to be an EGLImage wrapping it.
-     *
-     * This happens in GetNullEGLImage().
-     */
-    EGLImage mNullEGLImage;
-    android::sp<android::GraphicBuffer> mNullGraphicBuffer;
 #endif
 
     // A dummy texture ID that can be used when we need a texture object whose
     // images we're going to define with EGLImageTargetTexture2D.
     GLuint mTemporaryEGLImageTexture;
 
     static EGLSurface CreatePBufferSurfaceTryingPowerOfTwo(EGLConfig config,
                                                            EGLenum bindToTextureFormat,
@@ -1063,492 +964,16 @@ bool GLContextEGL::AttachSharedHandle(Sh
 }
 
 bool
 GLContextEGL::ResizeOffscreen(const gfxIntSize& aNewSize)
 {
 	return ResizeScreenBuffer(aNewSize);
 }
 
-
-static GLContextEGL *
-GetGlobalContextEGL()
-{
-    return static_cast<GLContextEGL*>(GLContextProviderEGL::GetGlobalContext());
-}
-
-static GLenum
-GLFormatForImage(gfxImageFormat aFormat)
-{
-    switch (aFormat) {
-    case gfxImageFormatARGB32:
-    case gfxImageFormatRGB24:
-        // Thebes only supports RGBX, not packed RGB.
-        return LOCAL_GL_RGBA;
-    case gfxImageFormatRGB16_565:
-        return LOCAL_GL_RGB;
-    case gfxImageFormatA8:
-        return LOCAL_GL_LUMINANCE;
-    default:
-        NS_WARNING("Unknown GL format for Image format");
-    }
-    return 0;
-}
-
-static GLenum
-GLTypeForImage(gfxImageFormat aFormat)
-{
-    switch (aFormat) {
-    case gfxImageFormatARGB32:
-    case gfxImageFormatRGB24:
-    case gfxImageFormatA8:
-        return LOCAL_GL_UNSIGNED_BYTE;
-    case gfxImageFormatRGB16_565:
-        return LOCAL_GL_UNSIGNED_SHORT_5_6_5;
-    default:
-        NS_WARNING("Unknown GL format for Image format");
-    }
-    return 0;
-}
-
-class TextureImageEGL
-    : public TextureImage
-{
-public:
-    TextureImageEGL(GLuint aTexture,
-                    const nsIntSize& aSize,
-                    GLenum aWrapMode,
-                    ContentType aContentType,
-                    GLContext* aContext,
-                    Flags aFlags = TextureImage::NoFlags,
-                    TextureState aTextureState = Created,
-                    TextureImage::ImageFormat aImageFormat = gfxImageFormatUnknown)
-        : TextureImage(aSize, aWrapMode, aContentType, aFlags)
-        , mGLContext(aContext)
-        , mUpdateFormat(aImageFormat)
-        , mEGLImage(nullptr)
-        , mTexture(aTexture)
-        , mSurface(nullptr)
-        , mConfig(nullptr)
-        , mTextureState(aTextureState)
-        , mBound(false)
-    {
-        if (mUpdateFormat == gfxImageFormatUnknown) {
-            mUpdateFormat = gfxPlatform::GetPlatform()->OptimalFormatForContent(GetContentType());
-        }
-
-        if (gUseBackingSurface) {
-            if (mUpdateFormat != gfxImageFormatARGB32) {
-                mTextureFormat = FORMAT_R8G8B8X8;
-            } else {
-                mTextureFormat = FORMAT_R8G8B8A8;
-            }
-            Resize(aSize);
-        } else {
-            if (mUpdateFormat == gfxImageFormatRGB16_565) {
-                mTextureFormat = FORMAT_R8G8B8X8;
-            } else if (mUpdateFormat == gfxImageFormatRGB24) {
-                // RGB24 means really RGBX for Thebes, which means we have to
-                // use the right shader and ignore the uninitialized alpha
-                // value.
-                mTextureFormat = FORMAT_B8G8R8X8;
-            } else {
-                mTextureFormat = FORMAT_B8G8R8A8;
-            }
-        }
-    }
-
-    virtual ~TextureImageEGL()
-    {
-        GLContext *ctx = mGLContext;
-        if (ctx->IsDestroyed() || !ctx->IsOwningThreadCurrent()) {
-            ctx = ctx->GetSharedContext();
-        }
-
-        // If we have a context, then we need to delete the texture;
-        // if we don't have a context (either real or shared),
-        // then they went away when the contex was deleted, because it
-        // was the only one that had access to it.
-        if (ctx && !ctx->IsDestroyed()) {
-            ctx->MakeCurrent();
-            ctx->fDeleteTextures(1, &mTexture);
-            ReleaseTexImage();
-            DestroyEGLSurface();
-        }
-    }
-
-    bool UsingDirectTexture()
-    {
-        return !!mBackingSurface;
-    }
-
-    virtual void GetUpdateRegion(nsIntRegion& aForRegion)
-    {
-        if (mTextureState != Valid) {
-            // if the texture hasn't been initialized yet, force the
-            // client to paint everything
-            aForRegion = nsIntRect(nsIntPoint(0, 0), mSize);
-        }
-
-        if (UsingDirectTexture()) {
-            return;
-        }
-
-        // We can only draw a rectangle, not subregions due to
-        // the way that our texture upload functions work.  If
-        // needed, we /could/ do multiple texture uploads if we have
-        // non-overlapping rects, but that's a tradeoff.
-        aForRegion = nsIntRegion(aForRegion.GetBounds());
-    }
-
-    virtual gfxASurface* BeginUpdate(nsIntRegion& aRegion)
-    {
-        NS_ASSERTION(!mUpdateSurface, "BeginUpdate() without EndUpdate()?");
-
-        // determine the region the client will need to repaint
-        GetUpdateRegion(aRegion);
-        mUpdateRect = aRegion.GetBounds();
-
-        //printf_stderr("BeginUpdate with updateRect [%d %d %d %d]\n", mUpdateRect.x, mUpdateRect.y, mUpdateRect.width, mUpdateRect.height);
-        if (!nsIntRect(nsIntPoint(0, 0), mSize).Contains(mUpdateRect)) {
-            NS_ERROR("update outside of image");
-            return nullptr;
-        }
-
-        if (mBackingSurface) {
-            mUpdateSurface = mBackingSurface;
-            return mUpdateSurface;
-        }
-
-        //printf_stderr("creating image surface %dx%d format %d\n", mUpdateRect.width, mUpdateRect.height, mUpdateFormat);
-
-        mUpdateSurface =
-            new gfxImageSurface(gfxIntSize(mUpdateRect.width, mUpdateRect.height),
-                                mUpdateFormat);
-
-        mUpdateSurface->SetDeviceOffset(gfxPoint(-mUpdateRect.x, -mUpdateRect.y));
-
-        return mUpdateSurface;
-    }
-
-    virtual void EndUpdate()
-    {
-        NS_ASSERTION(!!mUpdateSurface, "EndUpdate() without BeginUpdate()?");
-
-        if (mBackingSurface && mUpdateSurface == mBackingSurface) {
-#ifdef MOZ_X11
-            if (mBackingSurface->GetType() == gfxSurfaceTypeXlib) {
-                FinishX(DefaultXDisplay());
-            }
-#endif
-
-            mBackingSurface->SetDeviceOffset(gfxPoint(0, 0));
-            mTextureState = Valid;
-            mUpdateSurface = nullptr;
-            return;
-        }
-
-        //printf_stderr("EndUpdate: slow path");
-
-        // This is the slower path -- we didn't have any way to set up
-        // a fast mapping between our cairo target surface and the GL
-        // texture, so we have to upload data.
-
-        // Undo the device offset that BeginUpdate set; doesn't much
-        // matter for us here, but important if we ever do anything
-        // directly with the surface.
-        mUpdateSurface->SetDeviceOffset(gfxPoint(0, 0));
-
-        nsRefPtr<gfxImageSurface> uploadImage = nullptr;
-        gfxIntSize updateSize(mUpdateRect.width, mUpdateRect.height);
-
-        NS_ASSERTION(mUpdateSurface->GetType() == gfxSurfaceTypeImage &&
-                     mUpdateSurface->GetSize() == updateSize,
-                     "Upload image isn't an image surface when one is expected, or is wrong size!");
-
-        uploadImage = static_cast<gfxImageSurface*>(mUpdateSurface.get());
-
-        if (!uploadImage) {
-            return;
-        }
-
-        mGLContext->MakeCurrent();
-        mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
-
-        if (mTextureState != Valid) {
-            NS_ASSERTION(mUpdateRect.x == 0 && mUpdateRect.y == 0 &&
-                         mUpdateRect.Size() == mSize,
-                         "Bad initial update on non-created texture!");
-
-            mGLContext->fTexImage2D(LOCAL_GL_TEXTURE_2D,
-                                    0,
-                                    GLFormatForImage(mUpdateFormat),
-                                    mUpdateRect.width,
-                                    mUpdateRect.height,
-                                    0,
-                                    GLFormatForImage(uploadImage->Format()),
-                                    GLTypeForImage(uploadImage->Format()),
-                                    uploadImage->Data());
-        } else {
-            mGLContext->fTexSubImage2D(LOCAL_GL_TEXTURE_2D,
-                                       0,
-                                       mUpdateRect.x,
-                                       mUpdateRect.y,
-                                       mUpdateRect.width,
-                                       mUpdateRect.height,
-                                       GLFormatForImage(uploadImage->Format()),
-                                       GLTypeForImage(uploadImage->Format()),
-                                       uploadImage->Data());
-        }
-
-        mUpdateSurface = nullptr;
-        mTextureState = Valid;
-        return;         // mTexture is bound
-    }
-
-    virtual bool DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom /* = nsIntPoint(0, 0) */)
-    {
-        nsIntRect bounds = aRegion.GetBounds();
-
-        nsIntRegion region;
-        if (mTextureState != Valid) {
-            bounds = nsIntRect(0, 0, mSize.width, mSize.height);
-            region = nsIntRegion(bounds);
-        } else {
-            region = aRegion;
-        }
-
-        mTextureFormat =
-          mGLContext->UploadSurfaceToTexture(aSurf,
-                                              region,
-                                              mTexture,
-                                              mTextureState == Created,
-                                              bounds.TopLeft() + aFrom,
-                                              false);
-
-        mTextureState = Valid;
-        return true;
-    }
-
-    virtual void BindTexture(GLenum aTextureUnit)
-    {
-        // Ensure the texture is allocated before it is used.
-        if (mTextureState == Created) {
-            Resize(mSize);
-        }
-
-        mGLContext->fActiveTexture(aTextureUnit);
-        mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
-        mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0);
-    }
-
-    virtual GLuint GetTextureID() 
-    {
-        // Ensure the texture is allocated before it is used.
-        if (mTextureState == Created) {
-            Resize(mSize);
-        }
-        return mTexture;
-    };
-
-    virtual bool InUpdate() const { return !!mUpdateSurface; }
-
-    virtual void Resize(const nsIntSize& aSize)
-    {
-        NS_ASSERTION(!mUpdateSurface, "Resize() while in update?");
-
-        if (mSize == aSize && mTextureState != Created)
-            return;
-
-        mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
-    
-        // Try to generate a backin surface first if we have the ability
-        if (gUseBackingSurface) {
-            CreateBackingSurface(gfxIntSize(aSize.width, aSize.height));
-        }
-
-        if (!UsingDirectTexture()) {
-            // If we don't have a backing surface or failed to obtain one,
-            // use the GL Texture failsafe
-            mGLContext->fTexImage2D(LOCAL_GL_TEXTURE_2D,
-                                    0,
-                                    GLFormatForImage(mUpdateFormat),
-                                    aSize.width,
-                                    aSize.height,
-                                    0,
-                                    GLFormatForImage(mUpdateFormat),
-                                    GLTypeForImage(mUpdateFormat),
-                                    nullptr);
-        }
-
-        mTextureState = Allocated;
-        mSize = aSize;
-    }
-
-    bool BindTexImage()
-    {
-        if (mBound && !ReleaseTexImage())
-            return false;
-
-        EGLBoolean success =
-            sEGLLibrary.fBindTexImage(EGL_DISPLAY(),
-                                      (EGLSurface)mSurface,
-                                      LOCAL_EGL_BACK_BUFFER);
-
-        if (success == LOCAL_EGL_FALSE)
-            return false;
-
-        mBound = true;
-        return true;
-    }
-
-    bool ReleaseTexImage()
-    {
-        if (!mBound)
-            return true;
-
-        EGLBoolean success =
-            sEGLLibrary.fReleaseTexImage(EGL_DISPLAY(),
-                                         (EGLSurface)mSurface,
-                                         LOCAL_EGL_BACK_BUFFER);
-
-        if (success == LOCAL_EGL_FALSE)
-            return false;
-
-        mBound = false;
-        return true;
-    }
-
-    virtual already_AddRefed<gfxASurface> GetBackingSurface()
-    {
-        nsRefPtr<gfxASurface> copy = mBackingSurface;
-        return copy.forget();
-    }
-
-    virtual bool CreateEGLSurface(gfxASurface* aSurface)
-    {
-#ifdef MOZ_X11
-        if (!aSurface) {
-            NS_WARNING("no surface");
-            return false;
-        }
-
-        if (aSurface->GetType() != gfxSurfaceTypeXlib) {
-            NS_WARNING("wrong surface type, must be xlib");
-            return false;
-        }
-
-        if (mSurface) {
-            return true;
-        }
-
-        EGLSurface surface = CreateEGLSurfaceForXSurface(aSurface, &mConfig);
-
-        if (!surface) {
-            NS_WARNING("couldn't find X config for surface");
-            return false;
-        }
-
-        mSurface = surface;
-        return true;
-#else
-        return false;
-#endif
-    }
-
-    virtual void DestroyEGLSurface(void)
-    {
-        if (!mSurface)
-            return;
-
-        sEGLLibrary.fDestroySurface(EGL_DISPLAY(), mSurface);
-        mSurface = nullptr;
-    }
-
-    virtual bool CreateBackingSurface(const gfxIntSize& aSize)
-    {
-        ReleaseTexImage();
-        DestroyEGLSurface();
-        mBackingSurface = nullptr;
-
-#ifdef MOZ_X11
-        Display* dpy = DefaultXDisplay();
-        XRenderPictFormat* renderFMT =
-            gfxXlibSurface::FindRenderFormat(dpy, mUpdateFormat);
-
-        nsRefPtr<gfxXlibSurface> xsurface =
-            gfxXlibSurface::Create(DefaultScreenOfDisplay(dpy),
-                                   renderFMT,
-                                   gfxIntSize(aSize.width, aSize.height));
-
-        XSync(dpy, False);
-        mConfig = nullptr;
-
-        if (sEGLLibrary.HasKHRImagePixmap() &&
-            mGLContext->IsExtensionSupported(GLContext::OES_EGL_image))
-        {
-            mEGLImage =
-                sEGLLibrary.fCreateImage(EGL_DISPLAY(),
-                                         EGL_NO_CONTEXT,
-                                         LOCAL_EGL_NATIVE_PIXMAP,
-                                         (EGLClientBuffer)xsurface->XDrawable(),
-                                         nullptr);
-
-            if (!mEGLImage) {
-                printf_stderr("couldn't create EGL image: ERROR (0x%04x)\n", sEGLLibrary.fGetError());
-                return false;
-            }
-            mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
-            mGLContext->fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_2D, mEGLImage);
-            sEGLLibrary.fDestroyImage(EGL_DISPLAY(), mEGLImage);
-            mEGLImage = nullptr;
-        } else {
-            if (!CreateEGLSurface(xsurface)) {
-                printf_stderr("ProviderEGL Failed create EGL surface: ERROR (0x%04x)\n", sEGLLibrary.fGetError());
-                return false;
-            }
-
-            if (!BindTexImage()) {
-                printf_stderr("ProviderEGL Failed to bind teximage: ERROR (0x%04x)\n", sEGLLibrary.fGetError());
-                return false;
-            }
-        }
-
-        mBackingSurface = xsurface;
-
-        return mBackingSurface != nullptr;
-#endif
-
-        return mBackingSurface != nullptr;
-    }
-
-protected:
-    typedef gfxImageFormat ImageFormat;
-
-    GLContext* mGLContext;
-
-    nsIntRect mUpdateRect;
-    ImageFormat mUpdateFormat;
-    bool mUsingDirectTexture;
-    nsRefPtr<gfxASurface> mBackingSurface;
-    nsRefPtr<gfxASurface> mUpdateSurface;
-    EGLImage mEGLImage;
-    GLuint mTexture;
-    EGLSurface mSurface;
-    EGLConfig mConfig;
-    TextureState mTextureState;
-
-    bool mBound;
-
-    virtual void ApplyFilter()
-    {
-        mGLContext->ApplyFilterToBoundTexture(mFilter);
-    }
-};
-
 already_AddRefed<TextureImage>
 GLContextEGL::CreateTextureImage(const nsIntSize& aSize,
                                  TextureImage::ContentType aContentType,
                                  GLenum aWrapMode,
                                  TextureImage::Flags aFlags,
                                  TextureImage::ImageFormat aImageFormat)
 {
     nsRefPtr<TextureImage> t = new gl::TiledTextureImage(this, aSize, aContentType, aFlags, aImageFormat);
@@ -1576,18 +1001,16 @@ GLContextEGL::TileGenFunc(const nsIntSiz
   fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, texfilter);
   fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, texfilter);
   fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
   fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
 
   return teximage.forget();
 }
 
-static nsRefPtr<GLContext> gGlobalContext;
-
 static const EGLint kEGLConfigAttribsOffscreenPBuffer[] = {
     LOCAL_EGL_SURFACE_TYPE,    LOCAL_EGL_PBUFFER_BIT,
     LOCAL_EGL_RENDERABLE_TYPE, LOCAL_EGL_OPENGL_ES2_BIT,
     LOCAL_EGL_NONE
 };
 
 static const EGLint kEGLConfigAttribsRGB16[] = {
     LOCAL_EGL_SURFACE_TYPE,    LOCAL_EGL_WINDOW_BIT,
@@ -1732,48 +1155,30 @@ GLContextProviderEGL::CreateForWindow(ns
 
     bool doubleBuffered = true;
 
     bool hasNativeContext = aWidget->HasGLContext();
     EGLContext eglContext = sEGLLibrary.fGetCurrentContext();
     if (hasNativeContext && eglContext) {
         void* platformContext = eglContext;
         SurfaceCaps caps = SurfaceCaps::Any();
-#ifdef MOZ_WIDGET_QT
-        int depth = gfxPlatform::GetPlatform()->GetScreenDepth();
-        QGLContext* context = const_cast<QGLContext*>(QGLContext::currentContext());
-        if (context && context->device()) {
-            depth = context->device()->depth();
-        }
-        const QGLFormat& format = context->format();
-        doubleBuffered = format.doubleBuffer();
-        platformContext = context;
-        caps.bpp16 = depth == 16 ? true : false;
-        caps.alpha = format.rgba();
-        caps.depth = format.depth();
-        caps.stencil = format.stencil();
-#endif
         EGLConfig config = EGL_NO_CONFIG;
         EGLSurface surface = sEGLLibrary.fGetCurrentSurface(LOCAL_EGL_DRAW);
         nsRefPtr<GLContextEGL> glContext =
             new GLContextEGL(caps,
-                             gGlobalContext, false,
+                             nullptr, false,
                              config, surface, eglContext);
 
         if (!glContext->Init())
             return nullptr;
 
         glContext->MakeCurrent();
         glContext->SetIsDoubleBuffered(doubleBuffered);
         glContext->SetPlatformContext(platformContext);
 
-        if (!gGlobalContext) {
-            gGlobalContext = glContext;
-        }
-
         return glContext.forget();
     }
 
     EGLConfig config;
     if (!CreateConfig(&config)) {
         printf_stderr("Failed to create EGL config!\n");
         return nullptr;
     }
@@ -1785,21 +1190,20 @@ GLContextProviderEGL::CreateForWindow(ns
     EGLSurface surface = CreateSurfaceForWindow(aWidget, config);
 #endif
 
     if (!surface) {
         printf_stderr("Failed to create EGLSurface!\n");
         return nullptr;
     }
 
-    GLContextEGL* shareContext = GetGlobalContextEGL();
     SurfaceCaps caps = SurfaceCaps::Any();
     nsRefPtr<GLContextEGL> glContext =
         GLContextEGL::CreateGLContext(caps,
-                                      shareContext, false,
+                                      nullptr, false,
                                       config, surface);
 
     if (!glContext) {
         sEGLLibrary.fDestroySurface(EGL_DISPLAY(), surface);
         return nullptr;
     }
 
     glContext->MakeCurrent();
@@ -1836,161 +1240,58 @@ GLContextEGL::CreateEGLPBufferOffscreenC
     surface = GLContextEGL::CreatePBufferSurfaceTryingPowerOfTwo(config,
                                                                  LOCAL_EGL_NONE,
                                                                  pbSize);
     if (!surface) {
         NS_WARNING("Failed to create PBuffer for context!");
         return nullptr;
     }
 
-    GLContextEGL* shareContext = GetGlobalContextEGL();
     SurfaceCaps dummyCaps = SurfaceCaps::Any();
     nsRefPtr<GLContextEGL> glContext =
         GLContextEGL::CreateGLContext(dummyCaps,
-                                      shareContext, true,
+                                      nullptr, true,
                                       config, surface);
     if (!glContext) {
         NS_WARNING("Failed to create GLContext from PBuffer");
         sEGLLibrary.fDestroySurface(EGL_DISPLAY(), surface);
         return nullptr;
     }
 
     if (!glContext->Init()) {
         NS_WARNING("Failed to initialize GLContext!");
         // GLContextEGL::dtor will destroy |surface| for us.
         return nullptr;
     }
 
     return glContext.forget();
 }
 
-#ifdef MOZ_X11
-EGLSurface
-CreateEGLSurfaceForXSurface(gfxASurface* aSurface, EGLConfig* aConfig)
-{
-    gfxXlibSurface* xsurface = static_cast<gfxXlibSurface*>(aSurface);
-    bool opaque =
-        aSurface->GetContentType() == GFX_CONTENT_COLOR;
-
-    static EGLint pixmap_config_rgb[] = {
-        LOCAL_EGL_TEXTURE_TARGET,       LOCAL_EGL_TEXTURE_2D,
-        LOCAL_EGL_TEXTURE_FORMAT,       LOCAL_EGL_TEXTURE_RGB,
-        LOCAL_EGL_NONE
-    };
-
-    static EGLint pixmap_config_rgba[] = {
-        LOCAL_EGL_TEXTURE_TARGET,       LOCAL_EGL_TEXTURE_2D,
-        LOCAL_EGL_TEXTURE_FORMAT,       LOCAL_EGL_TEXTURE_RGBA,
-        LOCAL_EGL_NONE
-    };
-
-    EGLSurface surface = nullptr;
-    if (aConfig && *aConfig) {
-        if (opaque)
-            surface = sEGLLibrary.fCreatePixmapSurface(EGL_DISPLAY(), *aConfig,
-                                                       (EGLNativePixmapType)xsurface->XDrawable(),
-                                                       pixmap_config_rgb);
-        else
-            surface = sEGLLibrary.fCreatePixmapSurface(EGL_DISPLAY(), *aConfig,
-                                                       (EGLNativePixmapType)xsurface->XDrawable(),
-                                                       pixmap_config_rgba);
-
-        if (surface != EGL_NO_SURFACE)
-            return surface;
-    }
-
-    EGLConfig configs[32];
-    int numConfigs = 32;
-
-    static EGLint pixmap_config[] = {
-        LOCAL_EGL_SURFACE_TYPE,         LOCAL_EGL_PIXMAP_BIT,
-        LOCAL_EGL_RENDERABLE_TYPE,      LOCAL_EGL_OPENGL_ES2_BIT,
-        LOCAL_EGL_DEPTH_SIZE,           0,
-        LOCAL_EGL_BIND_TO_TEXTURE_RGB,  LOCAL_EGL_TRUE,
-        LOCAL_EGL_NONE
-    };
-
-    if (!sEGLLibrary.fChooseConfig(EGL_DISPLAY(),
-                                   pixmap_config,
-                                   configs, numConfigs, &numConfigs)
-        || numConfigs == 0)
-    {
-        NS_WARNING("No EGL Config for pixmap!");
-        return nullptr;
-    }
-
-    int i = 0;
-    for (i = 0; i < numConfigs; ++i) {
-        if (opaque)
-            surface = sEGLLibrary.fCreatePixmapSurface(EGL_DISPLAY(), configs[i],
-                                                       (EGLNativePixmapType)xsurface->XDrawable(),
-                                                       pixmap_config_rgb);
-        else
-            surface = sEGLLibrary.fCreatePixmapSurface(EGL_DISPLAY(), configs[i],
-                                                       (EGLNativePixmapType)xsurface->XDrawable(),
-                                                       pixmap_config_rgba);
-
-        if (surface != EGL_NO_SURFACE)
-            break;
-    }
-
-    if (!surface) {
-        NS_WARNING("Failed to CreatePixmapSurface!");
-        return nullptr;
-    }
-
-    if (aConfig)
-        *aConfig = configs[i];
-
-    return surface;
-}
-#endif
-
 already_AddRefed<GLContextEGL>
 GLContextEGL::CreateEGLPixmapOffscreenContext(const gfxIntSize& size)
 {
     gfxASurface *thebesSurface = nullptr;
     EGLNativePixmapType pixmap = 0;
 
-#ifdef MOZ_X11
-    nsRefPtr<gfxXlibSurface> xsurface =
-        gfxXlibSurface::Create(DefaultScreenOfDisplay(DefaultXDisplay()),
-                               gfxXlibSurface::FindRenderFormat(DefaultXDisplay(),
-                                                                gfxImageFormatRGB24),
-                               size);
-
-    // XSync required after gfxXlibSurface::Create, otherwise EGL will fail with BadDrawable error
-    XSync(DefaultXDisplay(), False);
-    if (xsurface->CairoStatus() != 0)
-        return nullptr;
-
-    thebesSurface = xsurface;
-    pixmap = (EGLNativePixmapType)xsurface->XDrawable();
-#endif
-
     if (!pixmap) {
         return nullptr;
     }
 
     EGLSurface surface = 0;
     EGLConfig config = 0;
 
-#ifdef MOZ_X11
-    surface = CreateEGLSurfaceForXSurface(thebesSurface, &config);
-#endif
     if (!config) {
         return nullptr;
     }
     MOZ_ASSERT(surface);
 
-    GLContextEGL* shareContext = GetGlobalContextEGL();
     SurfaceCaps dummyCaps = SurfaceCaps::Any();
     nsRefPtr<GLContextEGL> glContext =
         GLContextEGL::CreateGLContext(dummyCaps,
-                                      shareContext, true,
+                                      nullptr, true,
                                       config, surface);
     if (!glContext) {
         NS_WARNING("Failed to create GLContext from XSurface");
         sEGLLibrary.fDestroySurface(EGL_DISPLAY(), surface);
         return nullptr;
     }
 
     if (!glContext->Init()) {
@@ -2012,28 +1313,21 @@ GLContextProviderEGL::CreateOffscreen(co
                                       ContextFlags flags)
 {
     if (!sEGLLibrary.EnsureInitialized()) {
         return nullptr;
     }
 
     gfxIntSize dummySize = gfxIntSize(16, 16);
     nsRefPtr<GLContextEGL> glContext;
-#if defined(MOZ_X11)
-    glContext = GLContextEGL::CreateEGLPixmapOffscreenContext(dummySize);
-#else
     glContext = GLContextEGL::CreateEGLPBufferOffscreenContext(dummySize);
-#endif
 
     if (!glContext)
         return nullptr;
 
-    if (flags & ContextFlagsGlobal)
-        return glContext.forget();
-
     if (!glContext->InitOffscreen(size, caps))
         return nullptr;
 
     return glContext.forget();
 }
 
 SharedTextureHandle
 GLContextProviderEGL::CreateSharedHandle(SharedTextureShareType shareType,
@@ -2057,14 +1351,13 @@ GLContext *
 GLContextProviderEGL::GetGlobalContext(const ContextFlags)
 {
     return nullptr;
 }
 
 void
 GLContextProviderEGL::Shutdown()
 {
-    gGlobalContext = nullptr;
 }
 
 } /* namespace gl */
 } /* namespace mozilla */
 
--- a/gfx/gl/GLLibraryEGL.cpp
+++ b/gfx/gl/GLLibraryEGL.cpp
@@ -10,16 +10,18 @@
 #include "nsDirectoryServiceUtils.h"
 #include "nsPrintfCString.h"
 #include "prenv.h"
 #include "GLContext.h"
 
 namespace mozilla {
 namespace gl {
 
+GLLibraryEGL sEGLLibrary;
+
 // should match the order of EGLExtensions, and be null-terminated.
 static const char *sExtensionNames[] = {
     "EGL_KHR_image_base",
     "EGL_KHR_image_pixmap",
     "EGL_KHR_gl_texture_2D_image",
     "EGL_KHR_lock_surface",
     "EGL_ANGLE_surface_d3d_texture_2d_share_handle",
     "EGL_EXT_create_context_robustness",
--- a/gfx/gl/GLLibraryEGL.h
+++ b/gfx/gl/GLLibraryEGL.h
@@ -525,13 +525,16 @@ public:
 private:
     bool mInitialized;
     PRLibrary* mEGLLibrary;
     EGLDisplay mEGLDisplay;
 
     bool mIsANGLE;
 };
 
+extern GLLibraryEGL sEGLLibrary;
+#define EGL_DISPLAY()        sEGLLibrary.Display()
+
 } /* namespace gl */
 } /* namespace mozilla */
 
 #endif /* GLLIBRARYEGL_H_ */
 
new file mode 100644
--- /dev/null
+++ b/gfx/gl/TextureImageEGL.cpp
@@ -0,0 +1,319 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "TextureImageEGL.h"
+#include "GLLibraryEGL.h"
+#include "GLContext.h"
+#include "gfxPlatform.h"
+#include "mozilla/gfx/Types.h"
+
+namespace mozilla {
+namespace gl {
+
+static GLenum
+GLFormatForImage(gfxImageFormat aFormat)
+{
+    switch (aFormat) {
+    case gfxImageFormatARGB32:
+    case gfxImageFormatRGB24:
+        // Thebes only supports RGBX, not packed RGB.
+        return LOCAL_GL_RGBA;
+    case gfxImageFormatRGB16_565:
+        return LOCAL_GL_RGB;
+    case gfxImageFormatA8:
+        return LOCAL_GL_LUMINANCE;
+    default:
+        NS_WARNING("Unknown GL format for Image format");
+    }
+    return 0;
+}
+
+static GLenum
+GLTypeForImage(gfxImageFormat aFormat)
+{
+    switch (aFormat) {
+    case gfxImageFormatARGB32:
+    case gfxImageFormatRGB24:
+    case gfxImageFormatA8:
+        return LOCAL_GL_UNSIGNED_BYTE;
+    case gfxImageFormatRGB16_565:
+        return LOCAL_GL_UNSIGNED_SHORT_5_6_5;
+    default:
+        NS_WARNING("Unknown GL format for Image format");
+    }
+    return 0;
+}
+
+TextureImageEGL::TextureImageEGL(GLuint aTexture,
+                                 const nsIntSize& aSize,
+                                 GLenum aWrapMode,
+                                 ContentType aContentType,
+                                 GLContext* aContext,
+                                 Flags aFlags,
+                                 TextureState aTextureState,
+                                 TextureImage::ImageFormat aImageFormat)
+    : TextureImage(aSize, aWrapMode, aContentType, aFlags)
+    , mGLContext(aContext)
+    , mUpdateFormat(aImageFormat)
+    , mEGLImage(nullptr)
+    , mTexture(aTexture)
+    , mSurface(nullptr)
+    , mConfig(nullptr)
+    , mTextureState(aTextureState)
+    , mBound(false)
+{
+    if (mUpdateFormat == gfxImageFormatUnknown) {
+        mUpdateFormat = gfxPlatform::GetPlatform()->OptimalFormatForContent(GetContentType());
+    }
+
+    if (mUpdateFormat == gfxImageFormatRGB16_565) {
+        mTextureFormat = gfx::FORMAT_R8G8B8X8;
+    } else if (mUpdateFormat == gfxImageFormatRGB24) {
+        // RGB24 means really RGBX for Thebes, which means we have to
+        // use the right shader and ignore the uninitialized alpha
+        // value.
+        mTextureFormat = gfx::FORMAT_B8G8R8X8;
+    } else {
+        mTextureFormat = gfx::FORMAT_B8G8R8A8;
+    }
+}
+
+TextureImageEGL::~TextureImageEGL()
+{
+    if (mGLContext->IsDestroyed() || !mGLContext->IsOwningThreadCurrent()) {
+        return;
+    }
+
+    // If we have a context, then we need to delete the texture;
+    // if we don't have a context (either real or shared),
+    // then they went away when the contex was deleted, because it
+    // was the only one that had access to it.
+    mGLContext->MakeCurrent();
+    mGLContext->fDeleteTextures(1, &mTexture);
+    ReleaseTexImage();
+    DestroyEGLSurface();
+}
+
+void
+TextureImageEGL::GetUpdateRegion(nsIntRegion& aForRegion)
+{
+    if (mTextureState != Valid) {
+        // if the texture hasn't been initialized yet, force the
+        // client to paint everything
+        aForRegion = nsIntRect(nsIntPoint(0, 0), mSize);
+    }
+
+    // We can only draw a rectangle, not subregions due to
+    // the way that our texture upload functions work.  If
+    // needed, we /could/ do multiple texture uploads if we have
+    // non-overlapping rects, but that's a tradeoff.
+    aForRegion = nsIntRegion(aForRegion.GetBounds());
+}
+
+gfxASurface*
+TextureImageEGL::BeginUpdate(nsIntRegion& aRegion)
+{
+    NS_ASSERTION(!mUpdateSurface, "BeginUpdate() without EndUpdate()?");
+
+    // determine the region the client will need to repaint
+    GetUpdateRegion(aRegion);
+    mUpdateRect = aRegion.GetBounds();
+
+    //printf_stderr("BeginUpdate with updateRect [%d %d %d %d]\n", mUpdateRect.x, mUpdateRect.y, mUpdateRect.width, mUpdateRect.height);
+    if (!nsIntRect(nsIntPoint(0, 0), mSize).Contains(mUpdateRect)) {
+        NS_ERROR("update outside of image");
+        return nullptr;
+    }
+
+    //printf_stderr("creating image surface %dx%d format %d\n", mUpdateRect.width, mUpdateRect.height, mUpdateFormat);
+
+    mUpdateSurface =
+        new gfxImageSurface(gfxIntSize(mUpdateRect.width, mUpdateRect.height),
+                            mUpdateFormat);
+
+    mUpdateSurface->SetDeviceOffset(gfxPoint(-mUpdateRect.x, -mUpdateRect.y));
+
+    return mUpdateSurface;
+}
+
+void
+TextureImageEGL::EndUpdate()
+{
+    NS_ASSERTION(!!mUpdateSurface, "EndUpdate() without BeginUpdate()?");
+
+    //printf_stderr("EndUpdate: slow path");
+
+    // This is the slower path -- we didn't have any way to set up
+    // a fast mapping between our cairo target surface and the GL
+    // texture, so we have to upload data.
+
+    // Undo the device offset that BeginUpdate set; doesn't much
+    // matter for us here, but important if we ever do anything
+    // directly with the surface.
+    mUpdateSurface->SetDeviceOffset(gfxPoint(0, 0));
+
+    nsRefPtr<gfxImageSurface> uploadImage = nullptr;
+    gfxIntSize updateSize(mUpdateRect.width, mUpdateRect.height);
+
+    NS_ASSERTION(mUpdateSurface->GetType() == gfxSurfaceTypeImage &&
+                  mUpdateSurface->GetSize() == updateSize,
+                  "Upload image isn't an image surface when one is expected, or is wrong size!");
+
+    uploadImage = static_cast<gfxImageSurface*>(mUpdateSurface.get());
+
+    if (!uploadImage) {
+        return;
+    }
+
+    mGLContext->MakeCurrent();
+    mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
+
+    if (mTextureState != Valid) {
+        NS_ASSERTION(mUpdateRect.x == 0 && mUpdateRect.y == 0 &&
+                      mUpdateRect.Size() == mSize,
+                      "Bad initial update on non-created texture!");
+
+        mGLContext->fTexImage2D(LOCAL_GL_TEXTURE_2D,
+                                0,
+                                GLFormatForImage(mUpdateFormat),
+                                mUpdateRect.width,
+                                mUpdateRect.height,
+                                0,
+                                GLFormatForImage(uploadImage->Format()),
+                                GLTypeForImage(uploadImage->Format()),
+                                uploadImage->Data());
+    } else {
+        mGLContext->fTexSubImage2D(LOCAL_GL_TEXTURE_2D,
+                                    0,
+                                    mUpdateRect.x,
+                                    mUpdateRect.y,
+                                    mUpdateRect.width,
+                                    mUpdateRect.height,
+                                    GLFormatForImage(uploadImage->Format()),
+                                    GLTypeForImage(uploadImage->Format()),
+                                    uploadImage->Data());
+    }
+
+    mUpdateSurface = nullptr;
+    mTextureState = Valid;
+    return;         // mTexture is bound
+}
+
+bool
+TextureImageEGL::DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom /* = nsIntPoint(0, 0) */)
+{
+    nsIntRect bounds = aRegion.GetBounds();
+
+    nsIntRegion region;
+    if (mTextureState != Valid) {
+        bounds = nsIntRect(0, 0, mSize.width, mSize.height);
+        region = nsIntRegion(bounds);
+    } else {
+        region = aRegion;
+    }
+
+    mTextureFormat =
+      mGLContext->UploadSurfaceToTexture(aSurf,
+                                          region,
+                                          mTexture,
+                                          mTextureState == Created,
+                                          bounds.TopLeft() + aFrom,
+                                          false);
+
+    mTextureState = Valid;
+    return true;
+}
+
+void
+TextureImageEGL::BindTexture(GLenum aTextureUnit)
+{
+    // Ensure the texture is allocated before it is used.
+    if (mTextureState == Created) {
+        Resize(mSize);
+    }
+
+    mGLContext->fActiveTexture(aTextureUnit);
+    mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
+    mGLContext->fActiveTexture(LOCAL_GL_TEXTURE0);
+}
+
+void
+TextureImageEGL::Resize(const nsIntSize& aSize)
+{
+    NS_ASSERTION(!mUpdateSurface, "Resize() while in update?");
+
+    if (mSize == aSize && mTextureState != Created)
+        return;
+
+    mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, mTexture);
+
+    mGLContext->fTexImage2D(LOCAL_GL_TEXTURE_2D,
+                            0,
+                            GLFormatForImage(mUpdateFormat),
+                            aSize.width,
+                            aSize.height,
+                            0,
+                            GLFormatForImage(mUpdateFormat),
+                            GLTypeForImage(mUpdateFormat),
+                            nullptr);
+
+    mTextureState = Allocated;
+    mSize = aSize;
+}
+
+bool
+TextureImageEGL::BindTexImage()
+{
+    if (mBound && !ReleaseTexImage())
+        return false;
+
+    EGLBoolean success =
+        sEGLLibrary.fBindTexImage(EGL_DISPLAY(),
+                                  (EGLSurface)mSurface,
+                                  LOCAL_EGL_BACK_BUFFER);
+
+    if (success == LOCAL_EGL_FALSE)
+        return false;
+
+    mBound = true;
+    return true;
+}
+
+bool
+TextureImageEGL::ReleaseTexImage()
+{
+    if (!mBound)
+        return true;
+
+    EGLBoolean success =
+        sEGLLibrary.fReleaseTexImage(EGL_DISPLAY(),
+                                      (EGLSurface)mSurface,
+                                      LOCAL_EGL_BACK_BUFFER);
+
+    if (success == LOCAL_EGL_FALSE)
+        return false;
+
+    mBound = false;
+    return true;
+}
+
+void
+TextureImageEGL::DestroyEGLSurface(void)
+{
+    if (!mSurface)
+        return;
+
+    sEGLLibrary.fDestroySurface(EGL_DISPLAY(), mSurface);
+    mSurface = nullptr;
+}
+
+void
+TextureImageEGL::ApplyFilter()
+{
+    mGLContext->ApplyFilterToBoundTexture(mFilter);
+}
+
+}
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/gfx/gl/TextureImageEGL.h
@@ -0,0 +1,86 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef TEXTUREIMAGEEGL_H_
+#define TEXTUREIMAGEEGL_H_
+
+#include "GLTextureImage.h"
+
+namespace mozilla {
+namespace gl {
+
+class TextureImageEGL
+    : public TextureImage
+{
+public:
+    TextureImageEGL(GLuint aTexture,
+                    const nsIntSize& aSize,
+                    GLenum aWrapMode,
+                    ContentType aContentType,
+                    GLContext* aContext,
+                    Flags aFlags = TextureImage::NoFlags,
+                    TextureState aTextureState = Created,
+                    TextureImage::ImageFormat aImageFormat = gfxImageFormatUnknown);
+
+    virtual ~TextureImageEGL();
+
+    virtual void GetUpdateRegion(nsIntRegion& aForRegion);
+
+    virtual gfxASurface* BeginUpdate(nsIntRegion& aRegion);
+
+    virtual void EndUpdate();
+
+    virtual bool DirectUpdate(gfxASurface* aSurf, const nsIntRegion& aRegion, const nsIntPoint& aFrom /* = nsIntPoint(0, 0) */);
+
+    virtual void BindTexture(GLenum aTextureUnit);
+
+    virtual GLuint GetTextureID()
+    {
+        // Ensure the texture is allocated before it is used.
+        if (mTextureState == Created) {
+            Resize(mSize);
+        }
+        return mTexture;
+    };
+
+    virtual bool InUpdate() const { return !!mUpdateSurface; }
+
+    virtual void Resize(const nsIntSize& aSize);
+
+    bool BindTexImage();
+
+    bool ReleaseTexImage();
+
+    virtual bool CreateEGLSurface(gfxASurface* aSurface)
+    {
+        return false;
+    }
+
+    virtual void DestroyEGLSurface(void);
+
+protected:
+    typedef gfxImageFormat ImageFormat;
+
+    GLContext* mGLContext;
+
+    nsIntRect mUpdateRect;
+    ImageFormat mUpdateFormat;
+    nsRefPtr<gfxASurface> mUpdateSurface;
+    EGLImage mEGLImage;
+    GLuint mTexture;
+    EGLSurface mSurface;
+    EGLConfig mConfig;
+    TextureState mTextureState;
+
+    bool mBound;
+
+    virtual void ApplyFilter();
+};
+
+
+}
+}
+
+#endif // TEXTUREIMAGEEGL_H_
\ No newline at end of file
--- a/gfx/gl/moz.build
+++ b/gfx/gl/moz.build
@@ -97,16 +97,17 @@ CPP_SOURCES += [
     'GLContextUtils.cpp',
     'GLLibraryLoader.cpp',
     'GLScreenBuffer.cpp',
     'GLTextureImage.cpp',
     'GfxTexturesReporter.cpp',
     'SharedSurface.cpp',
     'GLLibraryEGL.cpp',
     'SharedSurfaceEGL.cpp',
+    'TextureImageEGL.cpp',
     'SharedSurfaceGL.cpp',
     'SurfaceFactory.cpp',
     'SurfaceStream.cpp',
     'VBOArena.cpp',
     'TextureGarbageBin.cpp',
 ]
 
 FAIL_ON_WARNINGS = True
--- a/gfx/layers/opengl/CompositorOGL.cpp
+++ b/gfx/layers/opengl/CompositorOGL.cpp
@@ -700,16 +700,24 @@ CompositorOGL::CreateRenderTargetFromSou
 
 void
 CompositorOGL::SetRenderTarget(CompositingRenderTarget *aSurface)
 {
   MOZ_ASSERT(aSurface);
   CompositingRenderTargetOGL* surface
     = static_cast<CompositingRenderTargetOGL*>(aSurface);
   if (mCurrentRenderTarget != surface) {
+    // Restore the scissor rect that was active before we set the current
+    // render target.
+    mGLContext->PopScissorRect();
+
+    // Save the current scissor rect so that we can pop back to it when
+    // changing the render target again.
+    mGLContext->PushScissorRect();
+
     surface->BindRenderTarget();
     mCurrentRenderTarget = surface;
   }
 }
 
 CompositingRenderTarget*
 CompositorOGL::GetCurrentRenderTarget()
 {
@@ -823,16 +831,19 @@ CompositorOGL::BeginFrame(const Rect *aC
     mGLContext->fScissor(0, 0, width, height);
     if (aClipRectOut) {
       aClipRectOut->SetRect(0, 0, width, height);
     }
   } else {
     mGLContext->fScissor(aClipRectIn->x, aClipRectIn->y, aClipRectIn->width, aClipRectIn->height);
   }
 
+  // Save the current scissor rect so that SetRenderTarget can pop back to it.
+  mGLContext->PushScissorRect();
+
   // If the Android compositor is being used, this clear will be done in
   // DrawWindowUnderlay. Make sure the bits used here match up with those used
   // in mobile/android/base/gfx/LayerRenderer.java
 #ifndef MOZ_ANDROID_OMTC
   mGLContext->fClearColor(0.0, 0.0, 0.0, 0.0);
   mGLContext->fClear(LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT);
 #endif
 }
@@ -1276,16 +1287,19 @@ CompositorOGL::EndFrame()
 
   if (mTarget) {
     CopyToTarget(mTarget, mCurrentRenderTarget->GetTransform());
     mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
     mCurrentRenderTarget = nullptr;
     return;
   }
 
+  // Restore the scissor rect that we saved in BeginFrame.
+  mGLContext->PopScissorRect();
+
   mCurrentRenderTarget = nullptr;
 
   if (sDrawFPS && !mFPS) {
     mFPS = new FPSState();
   } else if (!sDrawFPS && mFPS) {
     mFPS = nullptr;
   }
 
--- a/js/src/config/makefiles/target_libs.mk
+++ b/js/src/config/makefiles/target_libs.mk
@@ -20,18 +20,18 @@ endif # EXPORT_LIBRARY
 
 binaries libs:: $(SUBMAKEFILES) $(TARGETS)
 ifndef NO_DIST_INSTALL
 ifdef SHARED_LIBRARY
 ifdef IS_COMPONENT
 	$(INSTALL) $(IFLAGS2) $(SHARED_LIBRARY) $(FINAL_TARGET)/components
 	$(ELF_DYNSTR_GC) $(FINAL_TARGET)/components/$(SHARED_LIBRARY)
 ifndef NO_COMPONENTS_MANIFEST
-	@$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/chrome.manifest "manifest components/components.manifest"
-	@$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/components/components.manifest "binary-component $(SHARED_LIBRARY)"
+	$(call py_action,buildlist,$(FINAL_TARGET)/chrome.manifest "manifest components/components.manifest")
+	$(call py_action,buildlist,$(FINAL_TARGET)/components/components.manifest "binary-component $(SHARED_LIBRARY)")
 endif
 endif # IS_COMPONENT
 endif # SHARED_LIBRARY
 endif # !NO_DIST_INSTALL
 
 ifndef NO_DIST_INSTALL
 
 ifneq (,$(strip $(PROGRAM)$(SIMPLE_PROGRAMS)))
--- a/js/src/config/rules.mk
+++ b/js/src/config/rules.mk
@@ -1309,18 +1309,18 @@ ifdef XPT_NAME #{
 
 ifndef NO_DIST_INSTALL
 _XPT_NAME_FILES := $(DEPTH)/config/makefiles/xpidl/xpt/$(XPT_NAME)
 _XPT_NAME_DEST := $(FINAL_TARGET)/components
 INSTALL_TARGETS += _XPT_NAME
 
 ifndef NO_INTERFACES_MANIFEST
 libs:: $(call mkdir_deps,$(FINAL_TARGET)/components)
-	@$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/components/interfaces.manifest "interfaces $(XPT_NAME)"
-	@$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/chrome.manifest "manifest components/interfaces.manifest"
+	$(call py_action,buildlist,$(FINAL_TARGET)/components/interfaces.manifest "interfaces $(XPT_NAME)")
+	$(call py_action,buildlist,$(FINAL_TARGET)/chrome.manifest "manifest components/interfaces.manifest")
 endif
 endif
 
 endif #} XPT_NAME
 
 ################################################################################
 # Copy each element of EXTRA_COMPONENTS to $(FINAL_TARGET)/components
 ifneq (,$(filter %.js,$(EXTRA_COMPONENTS) $(EXTRA_PP_COMPONENTS)))
@@ -1346,17 +1346,17 @@ ifndef NO_DIST_INSTALL
 EXTRA_PP_COMPONENTS_PATH := $(FINAL_TARGET)/components
 PP_TARGETS += EXTRA_PP_COMPONENTS
 endif
 endif
 
 EXTRA_MANIFESTS = $(filter %.manifest,$(EXTRA_COMPONENTS) $(EXTRA_PP_COMPONENTS))
 ifneq (,$(EXTRA_MANIFESTS))
 libs:: $(call mkdir_deps,$(FINAL_TARGET))
-	$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/chrome.manifest $(patsubst %,"manifest components/%",$(notdir $(EXTRA_MANIFESTS)))
+	$(call py_action,buildlist,$(FINAL_TARGET)/chrome.manifest $(patsubst %,"manifest components/%",$(notdir $(EXTRA_MANIFESTS))))
 endif
 
 ################################################################################
 # Copy each element of EXTRA_JS_MODULES to
 # $(FINAL_TARGET)/$(JS_MODULES_PATH). JS_MODULES_PATH defaults to "modules"
 # if it is undefined.
 JS_MODULES_PATH ?= modules
 FINAL_JS_MODULES_PATH := $(FINAL_TARGET)/$(JS_MODULES_PATH)
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -2144,80 +2144,18 @@ if test "$ac_cv_header_machine_endian_h"
     AC_DEFINE(JS_HAVE_MACHINE_ENDIAN_H)
 fi
 
 MOZ_CHECK_HEADERS(sys/isa_defs.h)
 if test "$ac_cv_header_sys_isa_defs_h" = yes; then
     AC_DEFINE(JS_HAVE_SYS_ISA_DEFS_H)
 fi
 
-dnl Check for uint and uint_t.
-dnl ========================================================
-AC_MSG_CHECKING(for uint)
-AC_CACHE_VAL(ac_cv_uint,
- [AC_TRY_COMPILE([#include <stdio.h>
-                  #include <sys/types.h>],
-                 [uint foo = 0;],
-                 [ac_cv_uint=true],
-                 [ac_cv_uint=false])])
-if test "$ac_cv_uint" = true ; then
-  AC_DEFINE(HAVE_UINT)
-  AC_MSG_RESULT(yes)
-else
-  AC_MSG_RESULT(no)
-fi
-AC_MSG_CHECKING(for uint_t)
-AC_CACHE_VAL(ac_cv_uint_t,
- [AC_TRY_COMPILE([#include <stdio.h>
-                  #include <sys/types.h>],
-                 [uint_t foo = 0;],
-                 [ac_cv_uint_t=true],
-                 [ac_cv_uint_t=false])])
-if test "$ac_cv_uint_t" = true ; then
-  AC_DEFINE(HAVE_UINT_T)
-  AC_MSG_RESULT(yes)
-else
-  AC_MSG_RESULT(no)
-fi
-
-dnl On the gcc trunk (as of 2001-02-09) _GNU_SOURCE, and thus __USE_GNU,
-dnl are defined when compiling C++ but not C.  Since the result of this
-dnl test is used only in C++, do it in C++.
 AC_LANG_CPLUSPLUS
 
-AC_MSG_CHECKING(for uname.domainname)
-AC_CACHE_VAL(ac_cv_have_uname_domainname_field,
-    [AC_TRY_COMPILE([#include <sys/utsname.h>],
-        [ struct utsname *res; char *domain;
-            (void)uname(res);  if (res != 0) { domain = res->domainname; } ],
-        [ac_cv_have_uname_domainname_field=true],
-        [ac_cv_have_uname_domainname_field=false])])
-
-if test "$ac_cv_have_uname_domainname_field" = "true"; then
-    AC_DEFINE(HAVE_UNAME_DOMAINNAME_FIELD)
-    AC_MSG_RESULT(yes)
-else
-    AC_MSG_RESULT(no)
-fi
-
-AC_MSG_CHECKING(for uname.__domainname)
-AC_CACHE_VAL(ac_cv_have_uname_us_domainname_field,
-    [AC_TRY_COMPILE([#include <sys/utsname.h>],
-        [ struct utsname *res; char *domain;
-            (void)uname(res);  if (res != 0) { domain = res->__domainname; } ],
-        [ac_cv_have_uname_us_domainname_field=true],
-        [ac_cv_have_uname_us_domainname_field=false])])
-
-if test "$ac_cv_have_uname_us_domainname_field" = "true"; then
-    AC_DEFINE(HAVE_UNAME_US_DOMAINNAME_FIELD)
-    AC_MSG_RESULT(yes)
-else
-    AC_MSG_RESULT(no)
-fi
-
 MOZ_CXX11
 
 dnl Check for .hidden assembler directive and visibility attribute.
 dnl Borrowed from glibc configure.in
 dnl ===============================================================
 if test "$GNU_CC"; then
   AC_CACHE_CHECK(for visibility(hidden) attribute,
                  ac_cv_visibility_hidden,
@@ -2623,34 +2561,16 @@ AC_CACHE_CHECK(
 if test "$ac_cv_func_res_ninit" = "yes"; then
     AC_DEFINE(HAVE_RES_NINIT)
 dnl must add the link line we do something as foolish as this... dougt
 dnl else
 dnl    AC_CHECK_LIB(bind, res_ninit, AC_DEFINE(HAVE_RES_NINIT),
 dnl        AC_CHECK_LIB(resolv, res_ninit, AC_DEFINE(HAVE_RES_NINIT)))
 fi
 
-AC_LANG_CPLUSPLUS
-AC_CACHE_CHECK(
-    [for gnu_get_libc_version()],
-    ac_cv_func_gnu_get_libc_version,
-    [AC_TRY_LINK([
-        #ifdef HAVE_GNU_LIBC_VERSION_H
-        #include <gnu/libc-version.h>
-        #endif
-        ],
-        [const char *glibc_version = gnu_get_libc_version();],
-        [ac_cv_func_gnu_get_libc_version=yes],
-        [ac_cv_func_gnu_get_libc_version=no]
-        )]
-    )
-
-if test "$ac_cv_func_gnu_get_libc_version" = "yes"; then
-    AC_DEFINE(HAVE_GNU_GET_LIBC_VERSION)
-fi
 AC_LANG_C
 
 dnl **********************
 dnl *** va_copy checks ***
 dnl **********************
 dnl we currently check for all three va_copy possibilities, so we get
 dnl all results in config.log for bug reports.
 AC_MSG_CHECKING(for an implementation of va_copy())
@@ -3286,39 +3206,16 @@ MOZ_ARG_ENABLE_BOOL(jemalloc,
     MOZ_MEMORY=1,
     MOZ_MEMORY=)
 
 if test "$NS_TRACE_MALLOC"; then
     MOZ_MEMORY=
 fi
 
 if test "$MOZ_MEMORY"; then
-
-  dnl Don't try to run compiler tests on Windows
-  if test "$OS_ARCH" = "WINNT"; then
-    if test -z "$HAVE_64BIT_OS"; then
-      AC_DEFINE_UNQUOTED([MOZ_MEMORY_SIZEOF_PTR_2POW], 2)
-    else
-      AC_DEFINE_UNQUOTED([MOZ_MEMORY_SIZEOF_PTR_2POW], 3)
-    fi
-  else
-    AC_CHECK_SIZEOF([int *], [4])
-    case "${ac_cv_sizeof_int_p}" in
-    4)
-      AC_DEFINE_UNQUOTED([MOZ_MEMORY_SIZEOF_PTR_2POW], 2)
-      ;;
-    8)
-      AC_DEFINE_UNQUOTED([MOZ_MEMORY_SIZEOF_PTR_2POW], 3)
-      ;;
-    *)
-      AC_MSG_ERROR([Unexpected pointer size])
-      ;;
-    esac
-  fi
-
   AC_DEFINE(MOZ_MEMORY)
   if test "x$MOZ_DEBUG" = "x1"; then
     AC_DEFINE(MOZ_MEMORY_DEBUG)
   fi
   dnl The generic feature tests that determine how to compute ncpus are long and
   dnl complicated.  Therefore, simply define special cpp variables for the
   dnl platforms we have special knowledge of.
   case "${target}" in
--- a/js/src/gc/Barrier.h
+++ b/js/src/gc/Barrier.h
@@ -415,41 +415,41 @@ class RelocatablePtr : public Encapsulat
     }
     RelocatablePtr(const RelocatablePtr<T> &v) : EncapsulatedPtr<T>(v) {
         if (this->value)
             post();
     }
 
     ~RelocatablePtr() {
         if (this->value)
-            relocate(this->value->runtimeFromMainThread());
+            relocate(this->value->runtimeFromAnyThread());
     }
 
     RelocatablePtr<T> &operator=(T *v) {
         this->pre();
         JS_ASSERT(!IsPoisonedPtr<T>(v));
         if (v) {
             this->value = v;
             post();
         } else if (this->value) {
-            JSRuntime *rt = this->value->runtimeFromMainThread();
+            JSRuntime *rt = this->value->runtimeFromAnyThread();
             this->value = v;
             relocate(rt);
         }
         return *this;
     }
 
     RelocatablePtr<T> &operator=(const RelocatablePtr<T> &v) {
         this->pre();
         JS_ASSERT(!IsPoisonedPtr<T>(v.value));
         if (v.value) {
             this->value = v.value;
             post();
         } else if (this->value) {
-            JSRuntime *rt = this->value->runtimeFromMainThread();
+            JSRuntime *rt = this->value->runtimeFromAnyThread();
             this->value = v;
             relocate(rt);
         }
         return *this;
     }
 
   protected:
     void post() {
@@ -707,17 +707,17 @@ class HeapValue : public EncapsulatedVal
         JS_ASSERT(!IsPoisonedValue(v));
         value = v;
         post(shadowZone->runtimeFromAnyThread());
     }
 
     static void writeBarrierPost(const Value &value, Value *addr) {
 #ifdef JSGC_GENERATIONAL
         if (value.isMarkable())
-            shadowRuntimeFromMainThread(value)->gcStoreBufferPtr()->putValue(addr);
+            shadowRuntimeFromAnyThread(value)->gcStoreBufferPtr()->putValue(addr);
 #endif
     }
 
     static void writeBarrierPost(JSRuntime *rt, const Value &value, Value *addr) {
 #ifdef JSGC_GENERATIONAL
         if (value.isMarkable()) {
             JS::shadow::Runtime *shadowRuntime = JS::shadow::Runtime::asShadowRuntime(rt);
             shadowRuntime->gcStoreBufferPtr()->putValue(addr);
@@ -756,56 +756,56 @@ class RelocatableValue : public Encapsul
         JS_ASSERT(!IsPoisonedValue(v.value));
         if (v.value.isMarkable())
             post();
     }
 
     ~RelocatableValue()
     {
         if (value.isMarkable())
-            relocate(runtimeFromMainThread(value));
+            relocate(runtimeFromAnyThread(value));
     }
 
     RelocatableValue &operator=(const Value &v) {
         pre();
         JS_ASSERT(!IsPoisonedValue(v));
         if (v.isMarkable()) {
             value = v;
             post();
         } else if (value.isMarkable()) {
-            JSRuntime *rt = runtimeFromMainThread(value);
+            JSRuntime *rt = runtimeFromAnyThread(value);
             relocate(rt);
             value = v;
         } else {
             value = v;
         }
         return *this;
     }
 
     RelocatableValue &operator=(const RelocatableValue &v) {
         pre();
         JS_ASSERT(!IsPoisonedValue(v.value));
         if (v.value.isMarkable()) {
             value = v.value;
             post();
         } else if (value.isMarkable()) {
-            JSRuntime *rt = runtimeFromMainThread(value);
+            JSRuntime *rt = runtimeFromAnyThread(value);
             relocate(rt);
             value = v.value;
         } else {
             value = v.value;
         }
         return *this;
     }
 
   private:
     void post() {
 #ifdef JSGC_GENERATIONAL
         JS_ASSERT(value.isMarkable());
-        shadowRuntimeFromMainThread(value)->gcStoreBufferPtr()->putRelocatableValue(&value);
+        shadowRuntimeFromAnyThread(value)->gcStoreBufferPtr()->putRelocatableValue(&value);
 #endif
     }
 
     void relocate(JSRuntime *rt) {
 #ifdef JSGC_GENERATIONAL
         JS::shadow::Runtime *shadowRuntime = JS::shadow::Runtime::asShadowRuntime(rt);
         shadowRuntime->gcStoreBufferPtr()->removeRelocatableValue(&value);
 #endif
--- a/memory/mozjemalloc/jemalloc.c
+++ b/memory/mozjemalloc/jemalloc.c
@@ -294,17 +294,17 @@ getenv(const char *name)
 
 	return (NULL);
 }
 
 typedef unsigned char uint8_t;
 typedef unsigned uint32_t;
 typedef unsigned long long uint64_t;
 typedef unsigned long long uintmax_t;
-#if defined(MOZ_MEMORY_SIZEOF_PTR_2POW) && (MOZ_MEMORY_SIZEOF_PTR_2POW == 3)
+#if defined(_WIN64)
 typedef long long ssize_t;
 #else
 typedef long ssize_t;
 #endif
 
 #define	MALLOC_DECOMMIT
 #endif
 
@@ -464,18 +464,18 @@ static const bool isthreaded = true;
 #  define inline
 #endif
 
 /* Size of stack-allocated buffer passed to strerror_r(). */
 #define	STRERROR_BUF		64
 
 /* Minimum alignment of non-tiny allocations is 2^QUANTUM_2POW_MIN bytes. */
 #  define QUANTUM_2POW_MIN      4
-#ifdef MOZ_MEMORY_SIZEOF_PTR_2POW
-#  define SIZEOF_PTR_2POW		MOZ_MEMORY_SIZEOF_PTR_2POW
+#if defined(_WIN64) || defined(__LP64__)
+#  define SIZEOF_PTR_2POW       3
 #else
 #  define SIZEOF_PTR_2POW       2
 #endif
 #define PIC
 #ifndef MOZ_MEMORY_DARWIN
 static const bool isthreaded = true;
 #else
 #  define NO_TLS
--- a/netwerk/build/nsNetModule.cpp
+++ b/netwerk/build/nsNetModule.cpp
@@ -37,21 +37,17 @@
 #include "nsCategoryCache.h"
 #include "nsIContentSniffer.h"
 #include "nsNetUtil.h"
 #include "nsIThreadPool.h"
 #include "mozilla/net/NeckoChild.h"
 
 #include "nsNetCID.h"
 
-#if defined(XP_MACOSX)
-#if !defined(__LP64__)
-#define BUILD_APPLEFILE_DECODER 1
-#endif
-#else
+#ifndef XP_MACOSX
 #define BUILD_BINHEX_DECODER 1
 #endif
 
 typedef nsCategoryCache<nsIContentSniffer> ContentSnifferCache;
 NS_HIDDEN_(ContentSnifferCache*) gNetSniffers = nullptr;
 NS_HIDDEN_(ContentSnifferCache*) gDataSniffers = nullptr;
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -138,25 +134,16 @@ net_NewIncrementalDownload(nsISupports *
     0xa62af1ba,                                      \
     0x79b3,                                          \
     0x4896,                                          \
     {0x8a, 0xaf, 0xb1, 0x48, 0xbf, 0xce, 0x42, 0x80} \
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 
-#include "nsStreamConverterService.h"
-
-#ifdef BUILD_APPLEFILE_DECODER
-#include "nsAppleFileDecoder.h"
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsAppleFileDecoder)
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-
 #include "nsMIMEHeaderParamImpl.h"
 
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsMIMEHeaderParamImpl)
 ///////////////////////////////////////////////////////////////////////////////
 
 #include "nsRequestObserverProxy.h"
 #include "nsSimpleStreamListener.h"
 #include "nsDirIndexParser.h"
@@ -371,16 +358,17 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsAndroid
 
 ///////////////////////////////////////////////////////////////////////////////
 
 #ifdef NECKO_PROTOCOL_ftp
 #include "nsFTPDirListingConv.h"
 nsresult NS_NewFTPDirListingConv(nsFTPDirListingConv** result);
 #endif
 
+#include "nsStreamConverterService.h"
 #include "nsMultiMixedConv.h"
 #include "nsHTTPCompressConv.h"
 #include "mozTXTToHTMLConv.h"
 #include "nsUnknownDecoder.h"
 #include "nsTXTToHTMLConv.h"
 #include "nsIndexedToHTML.h"
 #ifdef BUILD_BINHEX_DECODER
 #include "nsBinHexDecoder.h"
@@ -716,19 +704,16 @@ NS_DEFINE_NAMED_CID(NS_AUTHURLPARSER_CID
 NS_DEFINE_NAMED_CID(NS_STANDARDURL_CID);
 NS_DEFINE_NAMED_CID(NS_ARRAYBUFFERINPUTSTREAM_CID);
 NS_DEFINE_NAMED_CID(NS_BUFFEREDINPUTSTREAM_CID);
 NS_DEFINE_NAMED_CID(NS_BUFFEREDOUTPUTSTREAM_CID);
 NS_DEFINE_NAMED_CID(NS_MIMEINPUTSTREAM_CID);
 NS_DEFINE_NAMED_CID(NS_PROTOCOLPROXYSERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_STREAMCONVERTERSERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_DASHBOARD_CID);
-#ifdef BUILD_APPLEFILE_DECODER
-NS_DEFINE_NAMED_CID(NS_APPLEFILEDECODER_CID);
-#endif
 #ifdef NECKO_PROTOCOL_ftp
 NS_DEFINE_NAMED_CID(NS_FTPDIRLISTINGCONVERTER_CID);
 #endif
 NS_DEFINE_NAMED_CID(NS_NSINDEXEDTOHTMLCONVERTER_CID);
 NS_DEFINE_NAMED_CID(NS_DIRINDEXPARSER_CID);
 NS_DEFINE_NAMED_CID(NS_MULTIMIXEDCONVERTER_CID);
 NS_DEFINE_NAMED_CID(NS_UNKNOWNDECODER_CID);
 NS_DEFINE_NAMED_CID(NS_BINARYDETECTOR_CID);
@@ -854,19 +839,16 @@ static const mozilla::Module::CIDEntry k
     { &kNS_STANDARDURL_CID, false, nullptr, nsStandardURLConstructor },
     { &kNS_ARRAYBUFFERINPUTSTREAM_CID, false, nullptr, ArrayBufferInputStreamConstructor },
     { &kNS_BUFFEREDINPUTSTREAM_CID, false, nullptr, nsBufferedInputStream::Create },
     { &kNS_BUFFEREDOUTPUTSTREAM_CID, false, nullptr, nsBufferedOutputStream::Create },
     { &kNS_MIMEINPUTSTREAM_CID, false, nullptr, nsMIMEInputStreamConstructor },
     { &kNS_PROTOCOLPROXYSERVICE_CID, true, nullptr, nsProtocolProxyServiceConstructor },
     { &kNS_STREAMCONVERTERSERVICE_CID, false, nullptr, CreateNewStreamConvServiceFactory },
     { &kNS_DASHBOARD_CID, false, nullptr, mozilla::net::DashboardConstructor },
-#ifdef BUILD_APPLEFILE_DECODER
-    { &kNS_APPLEFILEDECODER_CID, false, nullptr, nsAppleFileDecoderConstructor },
-#endif
 #ifdef NECKO_PROTOCOL_ftp
     { &kNS_FTPDIRLISTINGCONVERTER_CID, false, nullptr, CreateNewFTPDirListingConv },
 #endif
     { &kNS_NSINDEXEDTOHTMLCONVERTER_CID, false, nullptr, nsIndexedToHTML::Create },
     { &kNS_DIRINDEXPARSER_CID, false, nullptr, nsDirIndexParserConstructor },
     { &kNS_MULTIMIXEDCONVERTER_CID, false, nullptr, CreateNewMultiMixedConvFactory },
     { &kNS_UNKNOWNDECODER_CID, false, nullptr, CreateNewUnknownDecoderFactory },
     { &kNS_BINARYDETECTOR_CID, false, nullptr, CreateNewBinaryDetectorFactory },
@@ -994,19 +976,16 @@ static const mozilla::Module::ContractID
     { NS_STANDARDURL_CONTRACTID, &kNS_STANDARDURL_CID },
     { NS_ARRAYBUFFERINPUTSTREAM_CONTRACTID, &kNS_ARRAYBUFFERINPUTSTREAM_CID },
     { NS_BUFFEREDINPUTSTREAM_CONTRACTID, &kNS_BUFFEREDINPUTSTREAM_CID },
     { NS_BUFFEREDOUTPUTSTREAM_CONTRACTID, &kNS_BUFFEREDOUTPUTSTREAM_CID },
     { NS_MIMEINPUTSTREAM_CONTRACTID, &kNS_MIMEINPUTSTREAM_CID },
     { NS_PROTOCOLPROXYSERVICE_CONTRACTID, &kNS_PROTOCOLPROXYSERVICE_CID },
     { NS_STREAMCONVERTERSERVICE_CONTRACTID, &kNS_STREAMCONVERTERSERVICE_CID },
     { NS_DASHBOARD_CONTRACTID, &kNS_DASHBOARD_CID },
-#ifdef BUILD_APPLEFILE_DECODER
-    { NS_IAPPLEFILEDECODER_CONTRACTID, &kNS_APPLEFILEDECODER_CID },
-#endif
 #ifdef NECKO_PROTOCOL_ftp
     { NS_ISTREAMCONVERTER_KEY FTP_TO_INDEX, &kNS_FTPDIRLISTINGCONVERTER_CID },
 #endif
     { NS_ISTREAMCONVERTER_KEY INDEX_TO_HTML, &kNS_NSINDEXEDTOHTMLCONVERTER_CID },
     { NS_DIRINDEXPARSER_CONTRACTID, &kNS_DIRINDEXPARSER_CID },
     { NS_ISTREAMCONVERTER_KEY MULTI_MIXED_X, &kNS_MULTIMIXEDCONVERTER_CID },
     { NS_ISTREAMCONVERTER_KEY MULTI_BYTERANGES, &kNS_MULTIMIXEDCONVERTER_CID },
     { NS_ISTREAMCONVERTER_KEY MULTI_MIXED, &kNS_MULTIMIXEDCONVERTER_CID },
--- a/netwerk/streamconv/public/moz.build
+++ b/netwerk/streamconv/public/moz.build
@@ -8,19 +8,14 @@ XPIDL_SOURCES += [
     'mozITXTToHTMLConv.idl',
     'nsIDirIndex.idl',
     'nsIDirIndexListener.idl',
     'nsIStreamConverter.idl',
     'nsIStreamConverterService.idl',
     'nsITXTToHTMLConv.idl',
 ]
 
-if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
-    XPIDL_SOURCES += [
-        'nsIAppleFileDecoder.idl',
-    ]
-
 XPIDL_MODULE = 'necko_strconv'
 
 MODULE = 'necko'
 
 FAIL_ON_WARNINGS = True
 
deleted file mode 100644
--- a/netwerk/streamconv/public/nsIAppleFileDecoder.idl
+++ /dev/null
@@ -1,33 +0,0 @@
-/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsIOutputStream.idl"
-
-interface nsIFile;
-
-%{C++
-#define NS_APPLEFILEDECODER_CID                      \
-{ /* 3a2bb281-64b8-11d5-9daa-bb433143c53c */         \
-    0x3a2bb281,                                      \
-    0x64b8,                                          \
-    0x11d5,                                          \
-    {0x9d, 0xaa, 0xbb, 0x43, 0x31, 0x43, 0xc5, 0x3c} \
-}
-
-#define NS_IAPPLEFILEDECODER_CONTRACTID     "@mozilla.org/applefiledecoder;1"
-%}
-
-
-[scriptable, uuid(3a2bb280-64b8-11d5-9daa-bb433143c53c)]
-interface nsIAppleFileDecoder : nsIOutputStream {
-
-    /**
-     * Initialize the Apple File Decoder Output stream.
-     *
-     * @param outputStream     The output stream which the AppleFile Decoder will write to the data fork.
-     * @param outputFile       The output file which the AppleFile Decoder will write to the resource fork.
-     */
-    void Initialize(in nsIOutputStream outputStream, in nsIFile outputFile);
-};
--- a/netwerk/streamconv/src/moz.build
+++ b/netwerk/streamconv/src/moz.build
@@ -7,21 +7,14 @@
 MODULE = 'necko'
 
 FAIL_ON_WARNINGS = True
 
 CPP_SOURCES += [
     'nsStreamConverterService.cpp',
 ]
 
-if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa' and CONFIG['OS_TEST'] != 'x86_64':
-    # nsAppleFileDecoder.cpp has warnings I don't understand.
-    FAIL_ON_WARNINGS = False
-    CPP_SOURCES += [
-        'nsAppleFileDecoder.cpp',
-    ]
-
 LIBRARY_NAME = 'nkconv_s'
 
 LIBXUL_LIBRARY = True
 
 MSVC_ENABLE_PGO = True
 
deleted file mode 100644
--- a/netwerk/streamconv/src/nsAppleFileDecoder.cpp
+++ /dev/null
@@ -1,440 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- 
-#include "nsAppleFileDecoder.h"
-#include "prmem.h"
-#include "prnetdb.h"
-#include "nsCRT.h"
-
-
-NS_IMPL_ISUPPORTS2(nsAppleFileDecoder, nsIAppleFileDecoder, nsIOutputStream)
-
-nsAppleFileDecoder::nsAppleFileDecoder()
-{
-  m_state = parseHeaders;
-  m_dataBufferLength = 0;
-  m_dataBuffer = (unsigned char*) PR_MALLOC(MAX_BUFFERSIZE);
-  m_entries = nullptr;
-  m_rfRefNum = -1;
-  m_totalDataForkWritten = 0;
-  m_totalResourceForkWritten = 0;
-  m_headerOk = false;
-  
-  m_comment[0] = 0;
-  memset(&m_dates, 0, sizeof(m_dates));
-  memset(&m_finderInfo, 0, sizeof(m_dates));
-  memset(&m_finderExtraInfo, 0, sizeof(m_dates));
-}
-
-nsAppleFileDecoder::~nsAppleFileDecoder()
-{
-  if (m_output)
-    Close();
-
-  PR_FREEIF(m_dataBuffer);
-  if (m_entries)
-    delete [] m_entries;
-}
-
-NS_IMETHODIMP nsAppleFileDecoder::Initialize(nsIOutputStream *outputStream, nsIFile *outputFile)
-{
-  m_output = outputStream;
-  
-  nsCOMPtr<nsILocalFileMac> macFile = do_QueryInterface(outputFile);
-  bool saveFollowLinks;
-  macFile->GetFollowLinks(&saveFollowLinks);
-  macFile->SetFollowLinks(true);
-  macFile->GetFSSpec(&m_fsFileSpec);
-  macFile->SetFollowLinks(saveFollowLinks);
-
-  m_offset = 0;
-  m_dataForkOffset = 0;
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP nsAppleFileDecoder::Close(void)
-{
-  nsresult rv;
-  rv = m_output->Close();
-
-  int32_t i;
-
-  if (m_rfRefNum != -1)
-    FSClose(m_rfRefNum);
-    
-  /* Check if the file is complete and if it's the case, write file attributes */
-  if (m_headerOk)
-  {
-    bool dataOk = true; /* It's ok if the file doesn't have a datafork, therefore set it to true by default. */
-    if (m_headers.magic == APPLESINGLE_MAGIC)
-    {
-      for (i = 0; i < m_headers.entriesCount; i ++)
-        if (ENT_DFORK == m_entries[i].id)
-        {
-          dataOk = (bool)(m_totalDataForkWritten == m_entries[i].length);
-          break;
-        }
-    }
-
-    bool resourceOk = FALSE;
-    for (i = 0; i < m_headers.entriesCount; i ++)
-      if (ENT_RFORK == m_entries[i].id)
-      {
-        resourceOk = (bool)(m_totalResourceForkWritten == m_entries[i].length);
-        break;
-      }
-      
-    if (dataOk && resourceOk)
-    {
-      HFileInfo *fpb;
-      CInfoPBRec cipbr;
-      
-      fpb = (HFileInfo *) &cipbr;
-      fpb->ioVRefNum = m_fsFileSpec.vRefNum;
-      fpb->ioDirID   = m_fsFileSpec.parID;
-      fpb->ioNamePtr = m_fsFileSpec.name;
-      fpb->ioFDirIndex = 0;
-      PBGetCatInfoSync(&cipbr);
-
-      /* set finder info */
-      memcpy(&fpb->ioFlFndrInfo, &m_finderInfo, sizeof (FInfo));
-      memcpy(&fpb->ioFlXFndrInfo, &m_finderExtraInfo, sizeof (FXInfo));
-      fpb->ioFlFndrInfo.fdFlags &= 0xfc00; /* clear flags maintained by finder */
-      
-      /* set file dates */
-      fpb->ioFlCrDat = m_dates.create - CONVERT_TIME;
-      fpb->ioFlMdDat = m_dates.modify - CONVERT_TIME;
-      fpb->ioFlBkDat = m_dates.backup - CONVERT_TIME;
-    
-      /* update file info */
-      fpb->ioDirID = fpb->ioFlParID;
-      PBSetCatInfoSync(&cipbr);
-      
-      /* set comment */
-      IOParam vinfo;
-      GetVolParmsInfoBuffer vp;
-      DTPBRec dtp;
-
-      memset((void *) &vinfo, 0, sizeof (vinfo));
-      vinfo.ioVRefNum = fpb->ioVRefNum;
-      vinfo.ioBuffer  = (Ptr) &vp;
-      vinfo.ioReqCount = sizeof (vp);
-      if (PBHGetVolParmsSync((HParmBlkPtr) &vinfo) == noErr && ((vp.vMAttrib >> bHasDesktopMgr) & 1)) 
-      {
-        memset((void *) &dtp, 0, sizeof (dtp));
-        dtp.ioVRefNum = fpb->ioVRefNum;
-        if (PBDTGetPath(&dtp) == noErr) 
-        {
-          dtp.ioDTBuffer = (Ptr) &m_comment[1];
-          dtp.ioNamePtr  = fpb->ioNamePtr;
-          dtp.ioDirID    = fpb->ioDirID;
-          dtp.ioDTReqCount = m_comment[0];
-          if (PBDTSetCommentSync(&dtp) == noErr) 
-            PBDTFlushSync(&dtp);
-        }
-      }
-    }
-  }
-  
-  /* setting m_headerOk to false will prevent us to reprocess the header in case the Close function is called several time*/
-  m_headerOk = false;
-
-  return rv;
-}
-
-NS_IMETHODIMP nsAppleFileDecoder::Flush(void)
-{
-  return m_output->Flush();
-} 
-
-NS_IMETHODIMP nsAppleFileDecoder::WriteFrom(nsIInputStream *inStr, uint32_t count, uint32_t *_retval)
-{
-  return m_output->WriteFrom(inStr, count, _retval);
-}
-
-NS_IMETHODIMP nsAppleFileDecoder::WriteSegments(nsReadSegmentFun reader, void * closure, uint32_t count, uint32_t *_retval)
-{
-  return m_output->WriteSegments(reader, closure, count, _retval);
-}
-
-NS_IMETHODIMP nsAppleFileDecoder::IsNonBlocking(bool *aNonBlocking)
-{
-  return m_output->IsNonBlocking(aNonBlocking);
-}
-
-NS_IMETHODIMP nsAppleFileDecoder::Write(const char *buffer, uint32_t bufferSize, uint32_t* writeCount)
-{
-  /* WARNING: to simplify my life, I presume that I should get all appledouble headers in the first block,
-              else I would have to implement a buffer */
-
-  const char * buffPtr = buffer;
-  uint32_t dataCount;
-  int32_t i;
-  nsresult rv = NS_OK;
-
-  *writeCount = 0;
-  
-  while (bufferSize > 0 && NS_SUCCEEDED(rv))
-  {
-    switch (m_state)
-    {
-      case parseHeaders :
-        dataCount = sizeof(ap_header) - m_dataBufferLength;
-        if (dataCount > bufferSize)
-          dataCount = bufferSize;
-        memcpy(&m_dataBuffer[m_dataBufferLength], buffPtr, dataCount);
-        m_dataBufferLength += dataCount;
-        
-        if (m_dataBufferLength == sizeof(ap_header))
-        {
-          memcpy(&m_headers, m_dataBuffer, sizeof(ap_header));
-          m_headers.magic   = (int32_t)PR_ntohl((uint32_t)m_headers.magic);
-          m_headers.version = (int32_t)PR_ntohl((uint32_t)m_headers.version);
-          // m_headers.fill is required to be all zeroes; no endian issues
-          m_headers.entriesCount =
-            (int16_t)PR_ntohs((uint16_t)m_headers.entriesCount);
-
-          /* Check header to be sure we are dealing with the right kind of data, else just write it to the data fork. */
-          if ((m_headers.magic == APPLEDOUBLE_MAGIC || m_headers.magic == APPLESINGLE_MAGIC) && 
-              m_headers.version == VERSION && m_headers.entriesCount)
-          {
-            /* Just to be sure, the filler must contains only 0 */
-            for (i = 0; i < 4 && m_headers.fill[i] == 0L; i ++)
-              ;
-            if (i == 4)
-              m_state = parseEntries;
-          }
-          m_dataBufferLength = 0;
-          
-          if (m_state == parseHeaders)
-          {
-            dataCount = 0;
-            m_state = parseWriteThrough;
-          }
-        }
-        break;
-      
-      case parseEntries :
-        {
-        if (!m_entries)
-        {
-          m_entries = new ap_entry[m_headers.entriesCount];
-          if (!m_entries)
-            return NS_ERROR_OUT_OF_MEMORY;
-        }
-        uint32_t entriesSize = sizeof(ap_entry) * m_headers.entriesCount;
-        dataCount = entriesSize - m_dataBufferLength;
-        if (dataCount > bufferSize)
-          dataCount = bufferSize;
-        memcpy(&m_dataBuffer[m_dataBufferLength], buffPtr, dataCount);
-        m_dataBufferLength += dataCount;
-
-        if (m_dataBufferLength == entriesSize)
-        {
-          for (i = 0; i < m_headers.entriesCount; i ++)
-          {
-            memcpy(&m_entries[i], &m_dataBuffer[i * sizeof(ap_entry)], sizeof(ap_entry));
-            m_entries[i].id     = (int32_t)PR_ntohl((uint32_t)m_entries[i].id);
-            m_entries[i].offset =
-              (int32_t)PR_ntohl((uint32_t)m_entries[i].offset);
-            m_entries[i].length =
-              (int32_t)PR_ntohl((uint32_t)m_entries[i].length);
-            if (m_headers.magic == APPLEDOUBLE_MAGIC)
-            {
-              uint32_t offset = m_entries[i].offset + m_entries[i].length;
-              if (offset > m_dataForkOffset)
-                m_dataForkOffset = offset;
-            }
-          }
-          m_headerOk = true;          
-          m_state = parseLookupPart;
-        }
-        }
-        break;
-      
-      case parseLookupPart :
-        /* which part are we parsing? */
-        m_currentPartID = -1;
-        for (i = 0; i < m_headers.entriesCount; i ++)
-          if (m_offset == m_entries[i].offset && m_entries[i].length)
-          {
-              m_currentPartID = m_entries[i].id;
-              m_currentPartLength = m_entries[i].length;
-              m_currentPartCount = 0;
-
-              switch (m_currentPartID)
-              {
-                case ENT_DFORK    : m_state = parseDataFork;           break;
-                case ENT_RFORK    : m_state = parseResourceFork;       break;
-
-                case ENT_COMMENT  :
-                case ENT_DATES    :
-                case ENT_FINFO    :
-                  m_dataBufferLength = 0;
-                  m_state = parsePart;
-                  break;
-                
-                default           : m_state = parseSkipPart;           break;
-              }
-              break;
-          }
-          
-        if (m_currentPartID == -1)
-        {
-          /* maybe is the datafork of an appledouble file? */
-          if (m_offset == m_dataForkOffset)
-          {
-              m_currentPartID = ENT_DFORK;
-              m_currentPartLength = -1;
-              m_currentPartCount = 0;
-              m_state = parseDataFork;
-          }
-          else
-            dataCount = 1;
-        }        
-        break;
-      
-      case parsePart :
-        dataCount = m_currentPartLength - m_dataBufferLength;
-        if (dataCount > bufferSize)
-          dataCount = bufferSize;
-        memcpy(&m_dataBuffer[m_dataBufferLength], buffPtr, dataCount);
-        m_dataBufferLength += dataCount;
-        
-        if (m_dataBufferLength == m_currentPartLength)
-        {
-          switch (m_currentPartID)
-          {
-            case ENT_COMMENT  :
-              m_comment[0] = m_currentPartLength > 255 ? 255 : m_currentPartLength;
-              memcpy(&m_comment[1], buffPtr, m_comment[0]);
-              break;
-            case ENT_DATES    :
-              if (m_currentPartLength == sizeof(m_dates)) {
-                memcpy(&m_dates, buffPtr, m_currentPartLength);
-                m_dates.create = (int32_t)PR_ntohl((uint32_t)m_dates.create);
-                m_dates.modify = (int32_t)PR_ntohl((uint32_t)m_dates.modify);
-                m_dates.backup = (int32_t)PR_ntohl((uint32_t)m_dates.backup);
-                m_dates.access = (int32_t)PR_ntohl((uint32_t)m_dates.access);
-              }
-              break;
-            case ENT_FINFO    :
-              if (m_currentPartLength == (sizeof(m_finderInfo) + sizeof(m_finderExtraInfo)))
-              {
-                memcpy(&m_finderInfo, buffPtr, sizeof(m_finderInfo));
-                // OSType (four character codes) are still integers; swap them.
-                m_finderInfo.fdType =
-                  (OSType)PR_ntohl((uint32_t)m_finderInfo.fdType);
-                m_finderInfo.fdCreator =
-                  (OSType)PR_ntohl((uint32_t)m_finderInfo.fdCreator);
-                m_finderInfo.fdFlags =
-                  (UInt16)PR_ntohs((uint16_t)m_finderInfo.fdFlags);
-                m_finderInfo.fdLocation.v =
-                  (short)PR_ntohs((uint16_t)m_finderInfo.fdLocation.v);
-                m_finderInfo.fdLocation.h =
-                  (short)PR_ntohs((uint16_t)m_finderInfo.fdLocation.h);
-                m_finderInfo.fdFldr =
-                  (SInt16)PR_ntohs((uint16_t)m_finderInfo.fdFldr);
-
-                memcpy(&m_finderExtraInfo, buffPtr + sizeof(m_finderInfo), sizeof(m_finderExtraInfo));
-                m_finderExtraInfo.fdIconID =
-                  (SInt16)PR_ntohs((uint16_t)m_finderExtraInfo.fdIconID);
-                m_finderExtraInfo.fdReserved[0] =
-                  (SInt16)PR_ntohs((uint16_t)m_finderExtraInfo.fdReserved[0]);
-                m_finderExtraInfo.fdReserved[1] =
-                  (SInt16)PR_ntohs((uint16_t)m_finderExtraInfo.fdReserved[1]);
-                m_finderExtraInfo.fdReserved[2] =
-                  (SInt16)PR_ntohs((uint16_t)m_finderExtraInfo.fdReserved[2]);
-                // fdScript is a byte
-                // fdXFlags is a byte
-                m_finderExtraInfo.fdComment =
-                  (SInt16)PR_ntohs((uint16_t)m_finderExtraInfo.fdComment);
-                m_finderExtraInfo.fdPutAway =
-                  (SInt32)PR_ntohl((uint32_t)m_finderExtraInfo.fdPutAway);
-              }
-              break;
-          }
-          m_state = parseLookupPart;
-        }
-        break;
-      
-      case parseSkipPart :
-        dataCount = m_currentPartLength - m_currentPartCount;
-        if (dataCount > bufferSize)
-          dataCount = bufferSize;
-        else
-          m_state = parseLookupPart;
-        break;
-      
-      case parseDataFork :
-        if (m_headers.magic == APPLEDOUBLE_MAGIC)
-          dataCount = bufferSize;
-        else
-        {
-          dataCount = m_currentPartLength - m_currentPartCount;
-          if (dataCount > bufferSize)
-            dataCount = bufferSize;
-          else
-            m_state = parseLookupPart;
-        }
-        
-        if (m_output)
-        {
-          uint32_t writeCount;
-          rv = m_output->Write((const char *)buffPtr, dataCount, &writeCount);
-          if (dataCount != writeCount)
-            rv = NS_ERROR_FAILURE;
-          m_totalDataForkWritten += dataCount;
-        }
-        
-        break;
-      
-      case parseResourceFork :
-        {
-        dataCount = m_currentPartLength - m_currentPartCount;
-        if (dataCount > bufferSize)
-          dataCount = bufferSize;
-        else
-          m_state = parseLookupPart;
-        
-        if (m_rfRefNum == -1)
-        {
-          if (noErr != FSpOpenRF(&m_fsFileSpec, fsWrPerm, &m_rfRefNum))
-            return NS_ERROR_FAILURE;
-        }
-        
-        long count = dataCount;
-        if (noErr != FSWrite(m_rfRefNum, &count, buffPtr) || count != dataCount)
-            return NS_ERROR_FAILURE;
-        m_totalResourceForkWritten += dataCount;
-        }
-        break;
-      
-      case parseWriteThrough :
-        dataCount = bufferSize;
-        if (m_output)
-        {
-          uint32_t writeCount;
-          rv = m_output->Write((const char *)buffPtr, dataCount, &writeCount);
-          if (dataCount != writeCount)
-            rv = NS_ERROR_FAILURE;
-        }
-        break;
-    }
-
-    if (dataCount)
-    {
-      *writeCount += dataCount;
-      bufferSize -= dataCount;
-      buffPtr += dataCount;
-      m_currentPartCount += dataCount;
-      m_offset += dataCount;
-      dataCount = 0;
-    }
-  }
-
-  return rv;
-}
deleted file mode 100644
--- a/netwerk/streamconv/src/nsAppleFileDecoder.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef nsAppleFileDecoder_h__
-#define nsAppleFileDecoder_h__
-
-#include "nsIAppleFileDecoder.h"
-#include "nsILocalFileMac.h"
-
-/*
-** applefile definitions used 
-*/
-#if PRAGMA_STRUCT_ALIGN
-  #pragma options align=mac68k
-#endif
-
-#define APPLESINGLE_MAGIC   0x00051600L
-#define APPLEDOUBLE_MAGIC 	0x00051607L
-#define VERSION             0x00020000
-
-#define NUM_ENTRIES 		6
-
-#define ENT_DFORK   		1L
-#define ENT_RFORK   		2L
-#define ENT_NAME    		3L
-#define ENT_COMMENT 		4L
-#define ENT_DATES   		8L
-#define ENT_FINFO   		9L
-
-#define CONVERT_TIME 		1265437696L
-
-/*
-** data type used in the header decoder.
-*/
-typedef struct ap_header 
-{
-	int32_t 	magic;
-	int32_t   version;
-	int32_t 	fill[4];
-	int16_t 	entriesCount;
-
-} ap_header;
-
-typedef struct ap_entry 
-{
-	int32_t   id;
-	int32_t	  offset;
-	int32_t	  length;
-	
-} ap_entry;
-
-typedef struct ap_dates 
-{
-	int32_t create, modify, backup, access;
-
-} ap_dates;
-
-#if PRAGMA_STRUCT_ALIGN
-  #pragma options align=reset
-#endif
-
-/*
-**Error codes
-*/
-enum {
-  errADNotEnoughData = -12099,
-  errADNotSupported,
-  errADBadVersion
-};
-
-
-class nsAppleFileDecoder : public nsIAppleFileDecoder
-{
-public:
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIOUTPUTSTREAM
-  NS_DECL_NSIAPPLEFILEDECODER 
-   
-  nsAppleFileDecoder();
-  virtual ~nsAppleFileDecoder();
-  
-private:
-  #define MAX_BUFFERSIZE    1024
-  enum ParserState {parseHeaders, parseEntries, parseLookupPart, parsePart, parseSkipPart,
-                    parseDataFork, parseResourceFork, parseWriteThrough};
-  
-  nsCOMPtr<nsIOutputStream> m_output;
-  FSSpec            m_fsFileSpec;
-  SInt16            m_rfRefNum;
-  
-  unsigned char *   m_dataBuffer;
-  int32_t           m_dataBufferLength;
-  ParserState       m_state;
-  ap_header         m_headers;
-  ap_entry *        m_entries;
-  int32_t           m_offset;
-  int32_t           m_dataForkOffset;
-  int32_t           m_totalDataForkWritten;
-  int32_t           m_totalResourceForkWritten;
-  bool              m_headerOk;
-  
-  int32_t           m_currentPartID;
-  int32_t           m_currentPartLength;
-  int32_t           m_currentPartCount;
-  
-  Str255            m_comment;
-  ap_dates          m_dates;
-  FInfo             m_finderInfo;
-  FXInfo            m_finderExtraInfo;
-};
-
-#endif
--- a/python/Makefile.in
+++ b/python/Makefile.in
@@ -1,14 +1,15 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 test_dirs := \
   mozbuild/mozbuild/test \
+  mozbuild/mozbuild/test/action \
   mozbuild/mozbuild/test/backend \
   mozbuild/mozbuild/test/controller \
   mozbuild/mozbuild/test/compilation \
   mozbuild/mozbuild/test/frontend \
   mozbuild/mozpack/test \
   mozbuild/dumbmake/test \
   $(NULL)
 
rename from config/buildlist.py
rename to python/mozbuild/mozbuild/action/buildlist.py
--- a/config/buildlist.py
+++ b/python/mozbuild/mozbuild/action/buildlist.py
@@ -1,42 +1,49 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-'''A generic script to add entries to a file 
-if the entry does not already exist.
-
-Usage: buildlist.py <filename> <entry> [<entry> ...]
-'''
-from __future__ import print_function
-
-import sys
-import os
-from utils import lockFile
-
-def addEntriesToListFile(listFile, entries):
-  """Given a file |listFile| containing one entry per line,
-  add each entry in |entries| to the file, unless it is already
-  present."""
-  lock = lockFile(listFile + ".lck")
-  try:
-    if os.path.exists(listFile):
-      f = open(listFile)
-      existing = set(x.strip() for x in f.readlines())
-      f.close()
-    else:
-      existing = set()
-    f = open(listFile, 'a')
-    for e in entries:
-      if e not in existing:
-        f.write("{0}\n".format(e))
-        existing.add(e)
-    f.close()
-  finally:
-    lock = None
-
-if __name__ == '__main__':
-  if len(sys.argv) < 3:
-    print("Usage: buildlist.py <list file> <entry> [<entry> ...]",
-          file=sys.stderr)
-    sys.exit(1)
-  addEntriesToListFile(sys.argv[1], sys.argv[2:])
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+'''A generic script to add entries to a file
+if the entry does not already exist.
+
+Usage: buildlist.py <filename> <entry> [<entry> ...]
+'''
+from __future__ import print_function
+
+import sys
+import os
+
+from mozbuild.util import lock_file
+
+def addEntriesToListFile(listFile, entries):
+  """Given a file |listFile| containing one entry per line,
+  add each entry in |entries| to the file, unless it is already
+  present."""
+  lock = lock_file(listFile + ".lck")
+  try:
+    if os.path.exists(listFile):
+      f = open(listFile)
+      existing = set(x.strip() for x in f.readlines())
+      f.close()
+    else:
+      existing = set()
+    f = open(listFile, 'a')
+    for e in entries:
+      if e not in existing:
+        f.write("{0}\n".format(e))
+        existing.add(e)
+    f.close()
+  finally:
+    lock = None
+
+
+def main(args):
+    if len(args) < 2:
+        print("Usage: buildlist.py <list file> <entry> [<entry> ...]",
+            file=sys.stderr)
+        return 1
+
+    return addEntriesToListFile(args[0], args[1:])
+
+
+if __name__ == '__main__':
+    sys.exit(main(sys.argv[1:]))
rename from config/tests/unit-buildlist.py
rename to python/mozbuild/mozbuild/test/action/test_buildlist.py
--- a/config/tests/unit-buildlist.py
+++ b/python/mozbuild/mozbuild/test/action/test_buildlist.py
@@ -1,16 +1,21 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
 import unittest
 
 import os, sys, os.path, time
 from tempfile import mkdtemp
 from shutil import rmtree
 import mozunit
 
-from buildlist import addEntriesToListFile
+from mozbuild.action.buildlist import addEntriesToListFile
+
 
 class TestBuildList(unittest.TestCase):
   """
   Unit tests for buildlist.py
   """
   def setUp(self):
     self.tmpdir = mkdtemp()
 
--- a/python/mozbuild/mozbuild/util.py
+++ b/python/mozbuild/mozbuild/util.py
@@ -6,20 +6,23 @@
 # in particular.
 
 from __future__ import unicode_literals
 
 import copy
 import errno
 import hashlib
 import os
+import stat
 import sys
+import time
 
 from StringIO import StringIO
 
+
 if sys.version_info[0] == 3:
     str_type = str
 else:
     str_type = basestring
 
 def hash_file(path):
     """Hashes a file specified by the path given and returns the hex digest."""
 
@@ -365,8 +368,125 @@ class HierarchicalStringList(object):
 
     def _check_list(self, value):
         if not isinstance(value, list):
             raise ValueError('Expected a list of strings, not %s' % type(value))
         for v in value:
             if not isinstance(v, str_type):
                 raise ValueError(
                     'Expected a list of strings, not an element of %s' % type(v))
+
+
+class LockFile(object):
+    """LockFile is used by the lock_file method to hold the lock.
+
+    This object should not be used directly, but only through
+    the lock_file method below.
+    """
+
+    def __init__(self, lockfile):
+        self.lockfile = lockfile
+
+    def __del__(self):
+        while True:
+            try:
+                os.remove(self.lockfile)
+                break
+            except OSError as e:
+                if e.errno == errno.EACCES:
+                    # Another process probably has the file open, we'll retry.
+                    # Just a short sleep since we want to drop the lock ASAP
+                    # (but we need to let some other process close the file
+                    # first).
+                    time.sleep(0.1)
+            else:
+                # Re-raise unknown errors
+                raise
+
+
+def lock_file(lockfile, max_wait = 600):
+    """Create and hold a lockfile of the given name, with the given timeout.
+
+    To release the lock, delete the returned object.
+    """
+
+    # FUTURE This function and object could be written as a context manager.
+
+    while True:
+        try:
+            fd = os.open(lockfile, os.O_EXCL | os.O_RDWR | os.O_CREAT)
+            # We created the lockfile, so we're the owner
+            break
+        except OSError as e:
+            if (e.errno == errno.EEXIST or
+                (sys.platform == "win32" and e.errno == errno.EACCES)):
+                pass
+            else:
+                # Should not occur
+                raise
+
+        try:
+            # The lock file exists, try to stat it to get its age
+            # and read its contents to report the owner PID
+            f = open(lockfile, 'r')
+            s = os.stat(lockfile)
+        except EnvironmentError as e:
+            if e.errno == errno.ENOENT or e.errno == errno.EACCES:
+            # We didn't create the lockfile, so it did exist, but it's
+            # gone now. Just try again
+                continue
+
+            raise Exception('{0} exists but stat() failed: {1}'.format(
+                lockfile, e.strerror))
+
+        # We didn't create the lockfile and it's still there, check
+        # its age
+        now = int(time.time())
+        if now - s[stat.ST_MTIME] > max_wait:
+            pid = f.readline().rstrip()
+            raise Exception('{0} has been locked for more than '
+                '{1} seconds (PID {2})'.format(lockfile, max_wait, pid))
+
+        # It's not been locked too long, wait a while and retry
+        f.close()
+        time.sleep(1)
+
+    # if we get here. we have the lockfile. Convert the os.open file
+    # descriptor into a Python file object and record our PID in it
+    f = os.fdopen(fd, 'w')
+    f.write('{0}\n'.format(os.getpid()))
+    f.close()
+
+    return LockFile(lockfile)
+
+
+class PushbackIter(object):
+    '''Utility iterator that can deal with pushed back elements.
+
+    This behaves like a regular iterable, just that you can call
+    iter.pushback(item) to get the given item as next item in the
+    iteration.
+    '''
+    def __init__(self, iterable):
+        self.it = iter(iterable)
+        self.pushed_back = []
+
+    def __iter__(self):
+        return self
+
+    def __nonzero__(self):
+        if self.pushed_back:
+            return True
+
+        try:
+            self.pushed_back.insert(0, self.it.next())
+        except StopIteration:
+            return False
+        else:
+            return True
+
+    def next(self):
+        if self.pushed_back:
+            return self.pushed_back.pop()
+        return self.it.next()
+
+    def pushback(self, item):
+        self.pushed_back.append(item)
--- a/toolkit/components/startup/nsUserInfoUnix.cpp
+++ b/toolkit/components/startup/nsUserInfoUnix.cpp
@@ -105,20 +105,18 @@ nsUserInfo::GetDomain(char * *aDomain)
     struct utsname buf;
     char *domainname = nullptr;
 
     // is this portable?  that is a POSIX compliant call, but I need to check
     if (uname(&buf)) { 
         return rv;
     }
 
-#if defined(HAVE_UNAME_DOMAINNAME_FIELD)
+#if defined(__linux__)
     domainname = buf.domainname;
-#elif defined(HAVE_UNAME_US_DOMAINNAME_FIELD)
-    domainname = buf.__domainname;
 #endif
 
     if (domainname && domainname[0]) {   
         *aDomain = strdup(domainname);
         rv = NS_OK;
     }
     else {
         // try to get the hostname from the nodename
--- a/toolkit/crashreporter/client/crashreporter.cpp
+++ b/toolkit/crashreporter/client/crashreporter.cpp
@@ -11,16 +11,17 @@
 #endif
 
 #include <fstream>
 #include <sstream>
 #include <memory>
 #include <time.h>
 #include <stdlib.h>
 #include <string.h>
+#include "mozilla/NullPtr.h"
 
 using std::string;
 using std::istream;
 using std::ifstream;
 using std::istringstream;
 using std::ostringstream;
 using std::ostream;
 using std::ofstream;
--- a/toolkit/crashreporter/client/crashreporter_gtk_common.cpp
+++ b/toolkit/crashreporter/client/crashreporter_gtk_common.cpp
@@ -17,16 +17,17 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 
 #include <algorithm>
 #include <string>
 #include <vector>
 
+#include "mozilla/NullPtr.h"
 #include "common/linux/http_upload.h"
 #include "crashreporter.h"
 #include "crashreporter_gtk_common.h"
 
 using std::string;
 using std::vector;
 
 using namespace CrashReporter;
--- a/toolkit/crashreporter/client/crashreporter_linux.cpp
+++ b/toolkit/crashreporter/client/crashreporter_linux.cpp
@@ -6,16 +6,17 @@
 #include <dlfcn.h>
 #include <fcntl.h>
 #include <glib.h>
 #include <gtk/gtk.h>
 #include <string.h>
 
 #include <cctype>
 
+#include "mozilla/NullPtr.h"
 #include "crashreporter.h"
 #include "crashreporter_gtk_common.h"
 
 using std::string;
 using std::vector;
 
 using namespace CrashReporter;
 
--- a/uriloader/exthandler/nsExternalHelperAppService.cpp
+++ b/uriloader/exthandler/nsExternalHelperAppService.cpp
@@ -65,19 +65,16 @@
 #include "nsIEncodedChannel.h"
 #include "nsIMultiPartChannel.h"
 #include "nsIFileChannel.h"
 #include "nsIObserverService.h" // so we can be a profile change observer
 #include "nsIPropertyBag2.h" // for the 64-bit content length
 
 #ifdef XP_MACOSX
 #include "nsILocalFileMac.h"
-#ifndef __LP64__
-#include "nsIAppleFileDecoder.h"
-#endif
 #elif defined(XP_OS2)
 #include "nsILocalFileOS2.h"
 #endif
 
 #include "nsIPluginHost.h" // XXX needed for ext->type mapping (bug 233289)
 #include "nsPluginHost.h"
 #include "nsEscape.h"
 
--- a/webapprt/Makefile.in
+++ b/webapprt/Makefile.in
@@ -17,17 +17,17 @@ ifdef MOZ_DEBUG
 DEFINES += -DMOZ_DEBUG=1
 endif
 
 ifdef MOZILLA_OFFICIAL
 DEFINES += -DMOZILLA_OFFICIAL
 endif
 
 libs:: $(call mkdir_deps,$(FINAL_TARGET))
-	$(PYTHON) $(MOZILLA_DIR)/config/buildlist.py $(FINAL_TARGET)/chrome.manifest "resource webapprt ./"
+	$(call py_action,buildlist,$(FINAL_TARGET)/chrome.manifest "resource webapprt ./")
 
 GRE_MILESTONE := $(shell tail -n 1 $(topsrcdir)/config/milestone.txt 2>/dev/null || tail -1 $(topsrcdir)/config/milestone.txt)
 GRE_BUILDID := $(shell cat $(DEPTH)/config/buildid)
 DEFINES += -DGRE_MILESTONE=$(GRE_MILESTONE) \
            -DGRE_BUILDID=$(GRE_BUILDID) \
            -DMOZ_APP_BASENAME=$(MOZ_APP_BASENAME) \
            $(NULL)
 
--- a/widget/nsIWinMetroUtils.idl
+++ b/widget/nsIWinMetroUtils.idl
@@ -7,17 +7,17 @@
 
 /**
  * Integration with the "Metro"/"Modern" UI environment in Windows 8.
  *
  * Note: browser/metro/base/content/browser-scripts.js contains a stub
  * implementation of this interface for non-Windows systems, for testing and
  * development purposes only.
  */
-[scriptable, uuid(fa6750a2-f0fe-411c-af23-1cd6d2fdeceb)]
+[scriptable, uuid(25524bde-8b30-4b49-8d67-7070c790aada)]
 interface nsIWinMetroUtils : nsISupports
 {
   /* return constants for the handPreference property */
   const long handPreferenceLeft = 0;
   const long handPreferenceRight = 1;
 
   /**
    * Determine if the current browser is running in the metro immersive
@@ -44,17 +44,17 @@ interface nsIWinMetroUtils : nsISupports
    * Launches the specified application with the specified arguments and
    * switches to Desktop mode if in metro mode.
    */
    void launchInDesktop(in AString aPath, in AString aArguments); 
 
   /**
    * Displays a native Windows 8 toast.
    */
-   void showNativeToast(in AString aTitle, in AString aMessage, in AString anImage);
+   void showNativeToast(in AString aTitle, in AString aMessage, in AString anImage, in AString aCookie);
 
   /**
    * Secondary tiles are a Windows 8 specific feature for pinning new tiles
    * to the start screen.   Tiles can later be activated whether the browser is
    * already opened or not. 
    */
 
   /**
--- a/widget/windows/winrt/ToastNotificationHandler.cpp
+++ b/widget/windows/winrt/ToastNotificationHandler.cpp
@@ -11,18 +11,26 @@
 using namespace ABI::Windows::Foundation;
 using namespace ABI::Windows::Data::Xml::Dom;
 using namespace Microsoft::WRL;
 using namespace Microsoft::WRL::Wrappers;
 using namespace mozilla;
 using namespace ABI::Windows::UI::Notifications;
 
 typedef __FITypedEventHandler_2_Windows__CUI__CNotifications__CToastNotification_IInspectable_t ToastActivationHandler;
+typedef __FITypedEventHandler_2_Windows__CUI__CNotifications__CToastNotification_Windows__CUI__CNotifications__CToastDismissedEventArgs ToastDismissHandler;
 
-void ToastNotificationHandler::DisplayNotification(HSTRING title, HSTRING msg, HSTRING imagePath) {
+void
+ToastNotificationHandler::DisplayNotification(HSTRING title,
+                                              HSTRING msg,
+                                              HSTRING imagePath,
+                                              const nsAString& aCookie)
+{
+  mCookie = aCookie;
+
   ComPtr<IToastNotificationManagerStatics> toastNotificationManagerStatics;
   AssertHRESULT(GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_Notifications_ToastNotificationManager).Get(),
                                     toastNotificationManagerStatics.GetAddressOf()));
 
   ComPtr<IXmlDocument> toastXml;
   toastNotificationManagerStatics->GetTemplateContent(ToastTemplateType::ToastTemplateType_ToastImageAndText03, &toastXml);
 
   ComPtr<IXmlNodeList> toastTextElements, toastImageElements;
@@ -52,27 +60,40 @@ void ToastNotificationHandler::DisplayNo
   ComPtr<IToastNotificationFactory> factory;
   AssertHRESULT(GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_Notifications_ToastNotification).Get(),
                 factory.GetAddressOf()));
   AssertHRESULT(factory->CreateToastNotification(toastXml.Get(), &notification));
 
   EventRegistrationToken activatedToken;
   AssertHRESULT(notification->add_Activated(Callback<ToastActivationHandler>(this,
       &ToastNotificationHandler::OnActivate).Get(), &activatedToken));
+  EventRegistrationToken dismissedToken;
+  AssertHRESULT(notification->add_Dismissed(Callback<ToastDismissHandler>(this,
+      &ToastNotificationHandler::OnDismiss).Get(), &dismissedToken));
 
   ComPtr<IToastNotifier> notifier;
   toastNotificationManagerStatics->CreateToastNotifier(&notifier);
   notifier->Show(notification.Get());
+
+  MetroUtils::FireObserver("metro_native_toast_shown", mCookie.get());
 }
 
 void ToastNotificationHandler::SetNodeValueString(HSTRING inputString, ComPtr<IXmlNode> node, ComPtr<IXmlDocument> xml) { 
   ComPtr<IXmlText> inputText;
   ComPtr<IXmlNode> inputTextNode, pAppendedChild;
 
   AssertHRESULT(xml->CreateTextNode(inputString, &inputText));
   AssertHRESULT(inputText.As(&inputTextNode));
   AssertHRESULT(node->AppendChild(inputTextNode.Get(), &pAppendedChild));
 }
 
 HRESULT ToastNotificationHandler::OnActivate(IToastNotification *notification, IInspectable *inspectable) {
-  MetroUtils::FireObserver("metro_native_toast_clicked");
+  MetroUtils::FireObserver("metro_native_toast_clicked", mCookie.get());
   return S_OK;
 }
+
+HRESULT
+ToastNotificationHandler::OnDismiss(IToastNotification *notification,
+                                    IToastDismissedEventArgs* aArgs)
+{
+  MetroUtils::FireObserver("metro_native_toast_dismissed", mCookie.get());
+  return S_OK;
+}
--- a/widget/windows/winrt/ToastNotificationHandler.h
+++ b/widget/windows/winrt/ToastNotificationHandler.h
@@ -3,24 +3,31 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #pragma once
 
 #include <windows.ui.notifications.h>
 #include <windows.data.xml.dom.h>
 #include "mozwrlbase.h"
+#include "nsString.h"
 
 using namespace Microsoft::WRL;
 
 class ToastNotificationHandler {
     typedef ABI::Windows::UI::Notifications::IToastNotification IToastNotification;
+    typedef ABI::Windows::UI::Notifications::IToastDismissedEventArgs IToastDismissedEventArgs;
     typedef ABI::Windows::Data::Xml::Dom::IXmlNode IXmlNode;
     typedef ABI::Windows::Data::Xml::Dom::IXmlDocument IXmlDocument;
 
     void SetNodeValueString(HSTRING inputString, ComPtr<IXmlNode> node, ComPtr<IXmlDocument> xml);
   public:
     ToastNotificationHandler() {};
     ~ToastNotificationHandler() {};
 
-    void DisplayNotification(HSTRING title, HSTRING msg, HSTRING imagePath);
+    void DisplayNotification(HSTRING title, HSTRING msg, HSTRING imagePath, const nsAString& aCookie);
     HRESULT OnActivate(IToastNotification *notification, IInspectable *inspectable);
+    HRESULT OnDismiss(IToastNotification *notification,
+                      IToastDismissedEventArgs* aArgs);
+
+  private:
+    nsString mCookie;
 };
--- a/widget/windows/winrt/nsWinMetroUtils.cpp
+++ b/widget/windows/winrt/nsWinMetroUtils.cpp
@@ -340,30 +340,31 @@ nsWinMetroUtils::LaunchInDesktop(const n
   if (!ShellExecuteEx(&sinfo)) {
     return NS_ERROR_FAILURE;
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsWinMetroUtils::ShowNativeToast(const nsAString &aTitle,
-  const nsAString &aMessage, const nsAString &anImage)
+  const nsAString &aMessage, const nsAString &anImage,
+  const nsAString &aCookie)
 {
   // Firefox is in the foreground, no need for a notification.
   if (::GetActiveWindow() == ::GetForegroundWindow()) {
     return NS_OK;
   }
 
   ToastNotificationHandler* notification_handler =
       new ToastNotificationHandler;
 
   HSTRING title = HStringReference(aTitle.BeginReading()).Get();
   HSTRING msg = HStringReference(aMessage.BeginReading()).Get();
   HSTRING imagePath = HStringReference(anImage.BeginReading()).Get();
-  notification_handler->DisplayNotification(title, msg, imagePath);
+  notification_handler->DisplayNotification(title, msg, imagePath, aCookie);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsWinMetroUtils::ShowSettingsFlyout()
 {
   if (XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Desktop) {
--- a/xpcom/glue/FileUtils.cpp
+++ b/xpcom/glue/FileUtils.cpp
@@ -246,17 +246,17 @@ static const uint32_t CPU_TYPE = CPU_TYP
 #elif defined(__ppc__)
 static const uint32_t CPU_TYPE = CPU_TYPE_POWERPC;
 #elif defined(__ppc64__)
 static const uint32_t CPU_TYPE = CPU_TYPE_POWERPC64;
 #else
 #error Unsupported CPU type
 #endif
 
-#ifdef HAVE_64BIT_OS
+#ifdef __LP64__
 #undef LC_SEGMENT
 #define LC_SEGMENT LC_SEGMENT_64
 #undef MH_MAGIC
 #define MH_MAGIC MH_MAGIC_64
 #define cpu_mach_header mach_header_64
 #define segment_command segment_command_64
 #else
 #define cpu_mach_header mach_header
--- a/xpcom/xpidl/Makefile.in
+++ b/xpcom/xpidl/Makefile.in
@@ -1,8 +1,11 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 export::
 	$(call SUBMAKE,xpidl-parser,$(DEPTH)/xpcom/idl-parser)
 	$(call py_action,process_install_manifest,$(DIST)/idl $(DEPTH)/_build_manifests/install/dist_idl)
 	$(call SUBMAKE,xpidl,$(DEPTH)/config/makefiles/xpidl)
+
+clean clobber realclean clobber_all distclean::
+	$(call SUBMAKE,$@,$(DEPTH)/config/makefiles/xpidl)