Backed out 13 changesets (bug 709490) for android webgl-color-test.html failures
authorWes Kocher <wkocher@mozilla.com>
Tue, 29 Sep 2015 08:57:36 -0700
changeset 264987 c4f66a050ed0fd985658e458b90ef1be481b6fc0
parent 264986 1c51a59d7233a0220d6f22bba46dee7190bb93de
child 264988 447b0d81725655a8dd301e350ace6f1eabf6d9b0
push id65809
push userkwierso@gmail.com
push dateTue, 29 Sep 2015 15:57:46 +0000
treeherdermozilla-inbound@c4f66a050ed0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs709490
milestone44.0a1
backs out5be7514914b6d98482a244d0faf8e3cc8167012f
04b6f94fbe8aa09125271dbf752a8bef1bc93793
00c0e85dd8cd5093f2363c6120b9cc019330c401
221385b7b81a520ecc07b2cb54558bd413a55567
ecc38c18734fcb287a7831912906237fdbfb0e6e
22878c936384d27e9429a8481061fa2f15c6c267
0edcbb60eee3914e07e8a85e959f209fbaaf323f
5feceec2014b271775946f1485c9a7dd27a22aa3
835b655cb8731208602bcf21ff0782e16dc3f2c9
6fbb4a3f8cf7ed027ec13e7a5556a8daea5dd33b
a5f8646fa1569c2480575b5d5d6cc82c9a8aea7b
2ae1386916b3fe46a30ffcc45bb67c6dc2a48905
6b29a2a0a8fb4a385504ab0507ad34ee986d6c7f
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 13 changesets (bug 709490) for android webgl-color-test.html failures Backed out changeset 5be7514914b6 (bug 709490) Backed out changeset 04b6f94fbe8a (bug 709490) Backed out changeset 00c0e85dd8cd (bug 709490) Backed out changeset 221385b7b81a (bug 709490) Backed out changeset ecc38c18734f (bug 709490) Backed out changeset 22878c936384 (bug 709490) Backed out changeset 0edcbb60eee3 (bug 709490) Backed out changeset 5feceec2014b (bug 709490) Backed out changeset 835b655cb873 (bug 709490) Backed out changeset 6fbb4a3f8cf7 (bug 709490) Backed out changeset a5f8646fa156 (bug 709490) Backed out changeset 2ae1386916b3 (bug 709490) Backed out changeset 6b29a2a0a8fb (bug 709490)
dom/base/ImageEncoder.cpp
dom/base/ImageEncoder.h
dom/base/StructuredCloneHelper.cpp
dom/base/StructuredCloneTags.h
dom/canvas/CanvasRenderingContextHelper.cpp
dom/canvas/CanvasRenderingContextHelper.h
dom/canvas/CanvasUtils.cpp
dom/canvas/CanvasUtils.h
dom/canvas/OffscreenCanvas.cpp
dom/canvas/OffscreenCanvas.h
dom/canvas/WebGLContext.cpp
dom/canvas/WebGLContext.h
dom/canvas/WebGLContextExtensions.cpp
dom/canvas/WebGLContextGL.cpp
dom/canvas/WebGLContextLossHandler.cpp
dom/canvas/WebGLContextLossHandler.h
dom/canvas/WebGLContextReporter.cpp
dom/canvas/WebGLContextValidate.cpp
dom/canvas/WebGLMemoryTracker.cpp
dom/canvas/WebGLShaderValidator.cpp
dom/canvas/moz.build
dom/canvas/nsICanvasRenderingContextInternal.h
dom/canvas/test/mochitest.ini
dom/canvas/test/offscreencanvas.js
dom/canvas/test/offscreencanvas_mask.svg
dom/canvas/test/offscreencanvas_neuter.js
dom/canvas/test/offscreencanvas_serviceworker_inner.html
dom/canvas/test/test_offscreencanvas_basic_webgl.html
dom/canvas/test/test_offscreencanvas_dynamic_fallback.html
dom/canvas/test/test_offscreencanvas_many.html
dom/canvas/test/test_offscreencanvas_neuter.html
dom/canvas/test/test_offscreencanvas_serviceworker.html
dom/canvas/test/test_offscreencanvas_sharedworker.html
dom/canvas/test/test_offscreencanvas_sizechange.html
dom/canvas/test/test_offscreencanvas_subworker.html
dom/html/HTMLCanvasElement.cpp
dom/html/HTMLCanvasElement.h
dom/tests/mochitest/general/test_interfaces.html
dom/webidl/HTMLCanvasElement.webidl
dom/webidl/OffscreenCanvas.webidl
dom/webidl/WebGLRenderingContext.webidl
dom/webidl/moz.build
dom/workers/RuntimeService.cpp
dom/workers/WorkerPrivate.h
dom/workers/Workers.h
dom/workers/test/test_worker_interfaces.js
gfx/gl/GLContext.cpp
gfx/gl/GLLibraryEGL.cpp
gfx/gl/GLLibraryEGL.h
gfx/gl/GLReadTexImageHelper.cpp
gfx/gl/GLReadTexImageHelper.h
gfx/gl/GLScreenBuffer.cpp
gfx/gl/GLScreenBuffer.h
gfx/gl/SharedSurface.cpp
gfx/gl/SharedSurface.h
gfx/gl/SharedSurfaceANGLE.cpp
gfx/gl/SharedSurfaceANGLE.h
gfx/gl/SharedSurfaceEGL.cpp
gfx/gl/SharedSurfaceEGL.h
gfx/gl/SharedSurfaceGLX.cpp
gfx/gl/SharedSurfaceGLX.h
gfx/gl/SharedSurfaceGralloc.cpp
gfx/gl/SharedSurfaceGralloc.h
gfx/gl/SharedSurfaceIO.cpp
gfx/gl/SharedSurfaceIO.h
gfx/layers/AsyncCanvasRenderer.cpp
gfx/layers/AsyncCanvasRenderer.h
gfx/layers/CopyableCanvasLayer.cpp
gfx/layers/LayerTreeInvalidation.cpp
gfx/layers/Layers.cpp
gfx/layers/Layers.h
gfx/layers/basic/BasicCanvasLayer.cpp
gfx/layers/client/CanvasClient.cpp
gfx/layers/client/CanvasClient.h
gfx/layers/client/ClientCanvasLayer.cpp
gfx/layers/client/ClientCanvasLayer.h
gfx/layers/client/TextureClient.cpp
gfx/layers/ipc/ImageBridgeChild.cpp
gfx/layers/ipc/ImageBridgeChild.h
gfx/layers/ipc/PImageBridge.ipdl
gfx/layers/moz.build
gfx/src/gfxCrashReporterUtils.cpp
gfx/thebes/gfxPrefs.h
gfx/thebes/gfxUtils.cpp
gfx/thebes/gfxUtils.h
gfx/thebes/moz.build
js/public/StructuredClone.h
js/src/vm/StructuredClone.cpp
modules/libpref/init/all.js
--- a/dom/base/ImageEncoder.cpp
+++ b/dom/base/ImageEncoder.cpp
@@ -3,17 +3,16 @@
 /* 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 "ImageEncoder.h"
 #include "mozilla/dom/CanvasRenderingContext2D.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/gfx/DataSurfaceHelpers.h"
-#include "mozilla/layers/AsyncCanvasRenderer.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/SyncRunnable.h"
 #include "mozilla/unused.h"
 #include "gfxUtils.h"
 #include "nsNetUtil.h"
 
 using namespace mozilla::gfx;
 
@@ -161,31 +160,29 @@ public:
     nsCOMPtr<nsIInputStream> stream;
     nsresult rv = ImageEncoder::ExtractDataInternal(mType,
                                                     mOptions,
                                                     mImageBuffer,
                                                     mFormat,
                                                     mSize,
                                                     mImage,
                                                     nullptr,
-                                                    nullptr,
                                                     getter_AddRefs(stream),
                                                     mEncoder);
 
     // If there are unrecognized custom parse options, we should fall back to
     // the default values for the encoder without any options at all.
     if (rv == NS_ERROR_INVALID_ARG && mUsingCustomOptions) {
       rv = ImageEncoder::ExtractDataInternal(mType,
                                              EmptyString(),
                                              mImageBuffer,
                                              mFormat,
                                              mSize,
                                              mImage,
                                              nullptr,
-                                             nullptr,
                                              getter_AddRefs(stream),
                                              mEncoder);
     }
     NS_ENSURE_SUCCESS(rv, rv);
 
     rv = stream->Available(aImgSize);
     NS_ENSURE_SUCCESS(rv, rv);
     NS_ENSURE_TRUE(*aImgSize <= UINT32_MAX, NS_ERROR_FILE_TOO_BIG);
@@ -232,28 +229,28 @@ private:
 NS_IMPL_ISUPPORTS_INHERITED0(EncodingRunnable, nsRunnable);
 
 /* static */
 nsresult
 ImageEncoder::ExtractData(nsAString& aType,
                           const nsAString& aOptions,
                           const nsIntSize aSize,
                           nsICanvasRenderingContextInternal* aContext,
-                          layers::AsyncCanvasRenderer* aRenderer,
                           nsIInputStream** aStream)
 {
   nsCOMPtr<imgIEncoder> encoder = ImageEncoder::GetImageEncoder(aType);
   if (!encoder) {
     return NS_IMAGELIB_ERROR_NO_ENCODER;
   }
 
   return ExtractDataInternal(aType, aOptions, nullptr, 0, aSize, nullptr,
-                             aContext, aRenderer, aStream, encoder);
+                             aContext, aStream, encoder);
 }
 
+
 /* static */
 nsresult
 ImageEncoder::ExtractDataFromLayersImageAsync(nsAString& aType,
                                               const nsAString& aOptions,
                                               bool aUsingCustomOptions,
                                               layers::Image* aImage,
                                               EncodeCompleteCallback* aEncodeCallback)
 {
@@ -339,17 +336,16 @@ ImageEncoder::GetInputStream(int32_t aWi
 nsresult
 ImageEncoder::ExtractDataInternal(const nsAString& aType,
                                   const nsAString& aOptions,
                                   uint8_t* aImageBuffer,
                                   int32_t aFormat,
                                   const nsIntSize aSize,
                                   layers::Image* aImage,
                                   nsICanvasRenderingContextInternal* aContext,
-                                  layers::AsyncCanvasRenderer* aRenderer,
                                   nsIInputStream** aStream,
                                   imgIEncoder* aEncoder)
 {
   if (aSize.IsEmpty()) {
     return NS_ERROR_INVALID_ARG;
   }
 
   nsCOMPtr<nsIInputStream> imgStream;
@@ -365,21 +361,16 @@ ImageEncoder::ExtractDataInternal(const 
       aEncoder,
       nsPromiseFlatString(aOptions).get(),
       getter_AddRefs(imgStream));
   } else if (aContext) {
     NS_ConvertUTF16toUTF8 encoderType(aType);
     rv = aContext->GetInputStream(encoderType.get(),
                                   nsPromiseFlatString(aOptions).get(),
                                   getter_AddRefs(imgStream));
-  } else if (aRenderer) {
-    NS_ConvertUTF16toUTF8 encoderType(aType);
-    rv = aRenderer->GetInputStream(encoderType.get(),
-                                   nsPromiseFlatString(aOptions).get(),
-                                   getter_AddRefs(imgStream));
   } else if (aImage) {
     // It is safe to convert PlanarYCbCr format from YUV to RGB off-main-thread.
     // Other image formats could have problem to convert format off-main-thread.
     // So here it uses a help function GetBRGADataSourceSurfaceSync() to convert
     // format on main thread.
     if (aImage->GetFormat() == ImageFormat::PLANAR_YCBCR) {
       nsTArray<uint8_t> data;
       layers::PlanarYCbCrImage* ycbcrImage = static_cast<layers::PlanarYCbCrImage*> (aImage);
--- a/dom/base/ImageEncoder.h
+++ b/dom/base/ImageEncoder.h
@@ -14,17 +14,16 @@
 #include "nsLayoutUtils.h"
 #include "nsSize.h"
 
 class nsICanvasRenderingContextInternal;
 
 namespace mozilla {
 
 namespace layers {
-class AsyncCanvasRenderer;
 class Image;
 } // namespace layers
 
 namespace dom {
 
 class EncodeCompleteCallback;
 class EncodingRunnable;
 
@@ -36,17 +35,16 @@ public:
   // back to a PNG encoder. A return value of NS_OK implies successful data
   // extraction. If there are any unrecognized custom parse options in
   // aOptions, NS_ERROR_INVALID_ARG will be returned. When encountering this
   // error it is usual to call this function again without any options at all.
   static nsresult ExtractData(nsAString& aType,
                               const nsAString& aOptions,
                               const nsIntSize aSize,
                               nsICanvasRenderingContextInternal* aContext,
-                              layers::AsyncCanvasRenderer* aRenderer,
                               nsIInputStream** aStream);
 
   // Extracts data asynchronously. aType may change to "image/png" if we had to
   // fall back to a PNG encoder. aOptions are the options to be passed to the
   // encoder and aUsingCustomOptions specifies whether custom parse options were
   // used (i.e. by using -moz-parse-options). If there are any unrecognized
   // custom parse options, we fall back to the default values for the encoder
   // without any options at all. A return value of NS_OK only implies
@@ -81,26 +79,25 @@ public:
                                  int32_t aHeight,
                                  uint8_t* aImageBuffer,
                                  int32_t aFormat,
                                  imgIEncoder* aEncoder,
                                  const char16_t* aEncoderOptions,
                                  nsIInputStream** aStream);
 
 private:
-  // When called asynchronously, aContext and aRenderer are null.
+  // When called asynchronously, aContext is null.
   static nsresult
   ExtractDataInternal(const nsAString& aType,
                       const nsAString& aOptions,
                       uint8_t* aImageBuffer,
                       int32_t aFormat,
                       const nsIntSize aSize,
                       layers::Image* aImage,
                       nsICanvasRenderingContextInternal* aContext,
-                      layers::AsyncCanvasRenderer* aRenderer,
                       nsIInputStream** aStream,
                       imgIEncoder* aEncoder);
 
   // Creates and returns an encoder instance of the type specified in aType.
   // aType may change to "image/png" if no instance of the original type could
   // be created and we had to fall back to a PNG encoder. A null return value
   // should be interpreted as NS_IMAGELIB_ERROR_NO_ENCODER and aType is
   // undefined in this case.
--- a/dom/base/StructuredCloneHelper.cpp
+++ b/dom/base/StructuredCloneHelper.cpp
@@ -16,18 +16,16 @@
 #include "mozilla/dom/ImageBitmap.h"
 #include "mozilla/dom/ImageBitmapBinding.h"
 #include "mozilla/dom/ImageData.h"
 #include "mozilla/dom/ImageDataBinding.h"
 #include "mozilla/dom/ipc/BlobChild.h"
 #include "mozilla/dom/StructuredClone.h"
 #include "mozilla/dom/MessagePort.h"
 #include "mozilla/dom/MessagePortBinding.h"
-#include "mozilla/dom/OffscreenCanvas.h"
-#include "mozilla/dom/OffscreenCanvasBinding.h"
 #include "mozilla/dom/PMessagePort.h"
 #include "mozilla/dom/StructuredCloneTags.h"
 #include "mozilla/dom/SubtleCryptoBinding.h"
 #include "mozilla/dom/ToJSValue.h"
 #include "mozilla/dom/WebCryptoCommon.h"
 #include "mozilla/ipc/BackgroundChild.h"
 #include "mozilla/ipc/BackgroundUtils.h"
 #include "mozilla/ipc/PBackgroundSharedTypes.h"
@@ -1059,35 +1057,16 @@ StructuredCloneHelper::ReadTransferCallb
       JS_ClearPendingException(aCx);
       return false;
     }
 
     aReturnObject.set(&value.toObject());
     return true;
   }
 
-  if (aTag == SCTAG_DOM_CANVAS) {
-    MOZ_ASSERT(mContext == SameProcessSameThread ||
-               mContext == SameProcessDifferentThread);
-    MOZ_ASSERT(aContent);
-    OffscreenCanvasCloneData* data =
-      static_cast<OffscreenCanvasCloneData*>(aContent);
-    nsRefPtr<OffscreenCanvas> canvas = OffscreenCanvas::CreateFromCloneData(data);
-    delete data;
-
-    JS::Rooted<JS::Value> value(aCx);
-    if (!GetOrCreateDOMReflector(aCx, canvas, &value)) {
-      JS_ClearPendingException(aCx);
-      return false;
-    }
-
-    aReturnObject.set(&value.toObject());
-    return true;
-  }
-
   return false;
 }
 
 bool
 StructuredCloneHelper::WriteTransferCallback(JSContext* aCx,
                                              JS::Handle<JSObject*> aObj,
                                              uint32_t* aTag,
                                              JS::TransferableOwnership* aOwnership,
@@ -1109,34 +1088,16 @@ StructuredCloneHelper::WriteTransferCall
       port->CloneAndDisentangle(*identifier);
 
       *aTag = SCTAG_DOM_MAP_MESSAGEPORT;
       *aOwnership = JS::SCTAG_TMO_CUSTOM;
       *aContent = nullptr;
 
       return true;
     }
-
-    if (mContext == SameProcessSameThread ||
-        mContext == SameProcessDifferentThread) {
-      OffscreenCanvas* canvas = nullptr;
-      rv = UNWRAP_OBJECT(OffscreenCanvas, aObj, canvas);
-      if (NS_SUCCEEDED(rv)) {
-        MOZ_ASSERT(canvas);
-
-        *aExtraData = 0;
-        *aTag = SCTAG_DOM_CANVAS;
-        *aOwnership = JS::SCTAG_TMO_CUSTOM;
-        *aContent = canvas->ToCloneData();
-        MOZ_ASSERT(*aContent);
-        canvas->SetNeutered();
-
-        return true;
-      }
-    }
   }
 
   return false;
 }
 
 void
 StructuredCloneHelper::FreeTransferCallback(uint32_t aTag,
                                             JS::TransferableOwnership aOwnership,
@@ -1144,24 +1105,13 @@ StructuredCloneHelper::FreeTransferCallb
                                             uint64_t aExtraData)
 {
   MOZ_ASSERT(mSupportsTransferring);
 
   if (aTag == SCTAG_DOM_MAP_MESSAGEPORT) {
     MOZ_ASSERT(!aContent);
     MOZ_ASSERT(aExtraData < mPortIdentifiers.Length());
     MessagePort::ForceClose(mPortIdentifiers[aExtraData]);
-    return;
-  }
-
-  if (aTag == SCTAG_DOM_CANVAS) {
-    MOZ_ASSERT(mContext == SameProcessSameThread ||
-               mContext == SameProcessDifferentThread);
-    MOZ_ASSERT(aContent);
-    OffscreenCanvasCloneData* data =
-      static_cast<OffscreenCanvasCloneData*>(aContent);
-    delete data;
-    return;
   }
 }
 
 } // dom namespace
 } // mozilla namespace
--- a/dom/base/StructuredCloneTags.h
+++ b/dom/base/StructuredCloneTags.h
@@ -43,18 +43,15 @@ enum StructuredCloneTags {
 
   SCTAG_DOM_NFC_NDEF,
   SCTAG_DOM_IMAGEBITMAP,
 
   SCTAG_DOM_RTC_CERTIFICATE,
 
   SCTAG_DOM_FORMDATA,
 
-  // This tag is for OffscreenCanvas.
-  SCTAG_DOM_CANVAS,
-
   SCTAG_DOM_MAX
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // StructuredCloneTags_h__
deleted file mode 100644
--- a/dom/canvas/CanvasRenderingContextHelper.cpp
+++ /dev/null
@@ -1,264 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 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/. */
-
-#include "CanvasRenderingContextHelper.h"
-#include "ImageEncoder.h"
-#include "mozilla/dom/CanvasRenderingContext2D.h"
-#include "mozilla/Telemetry.h"
-#include "nsContentUtils.h"
-#include "nsDOMJSUtils.h"
-#include "nsIScriptContext.h"
-#include "nsJSUtils.h"
-#include "WebGL1Context.h"
-#include "WebGL2Context.h"
-
-namespace mozilla {
-namespace dom {
-
-void
-CanvasRenderingContextHelper::ToBlob(JSContext* aCx,
-                                     nsIGlobalObject* aGlobal,
-                                     FileCallback& aCallback,
-                                     const nsAString& aType,
-                                     JS::Handle<JS::Value> aParams,
-                                     ErrorResult& aRv)
-{
-  nsAutoString type;
-  nsContentUtils::ASCIIToLower(aType, type);
-
-  nsAutoString params;
-  bool usingCustomParseOptions;
-  aRv = ParseParams(aCx, type, aParams, params, &usingCustomParseOptions);
-  if (aRv.Failed()) {
-    return;
-  }
-
-#ifdef DEBUG
-  if (mCurrentContext) {
-    // We disallow canvases of width or height zero, and set them to 1, so
-    // we will have a discrepancy with the sizes of the canvas and the context.
-    // That discrepancy is OK, the rest are not.
-    nsIntSize elementSize = GetWidthHeight();
-    MOZ_ASSERT(elementSize.width == mCurrentContext->GetWidth() ||
-               (elementSize.width == 0 && mCurrentContext->GetWidth() == 1));
-    MOZ_ASSERT(elementSize.height == mCurrentContext->GetHeight() ||
-               (elementSize.height == 0 && mCurrentContext->GetHeight() == 1));
-  }
-#endif
-
-  uint8_t* imageBuffer = nullptr;
-  int32_t format = 0;
-  if (mCurrentContext) {
-    mCurrentContext->GetImageBuffer(&imageBuffer, &format);
-  }
-
-  // Encoder callback when encoding is complete.
-  class EncodeCallback : public EncodeCompleteCallback
-  {
-  public:
-    EncodeCallback(nsIGlobalObject* aGlobal, FileCallback* aCallback)
-      : mGlobal(aGlobal)
-      , mFileCallback(aCallback) {}
-
-    // This is called on main thread.
-    nsresult ReceiveBlob(already_AddRefed<Blob> aBlob)
-    {
-      nsRefPtr<Blob> blob = aBlob;
-
-      ErrorResult rv;
-      uint64_t size = blob->GetSize(rv);
-      if (rv.Failed()) {
-        rv.SuppressException();
-      } else {
-        AutoJSAPI jsapi;
-        if (jsapi.Init(mGlobal)) {
-          JS_updateMallocCounter(jsapi.cx(), size);
-        }
-      }
-
-      nsRefPtr<Blob> newBlob = Blob::Create(mGlobal, blob->Impl());
-
-      mFileCallback->Call(*newBlob, rv);
-
-      mGlobal = nullptr;
-      mFileCallback = nullptr;
-
-      return rv.StealNSResult();
-    }
-
-    nsCOMPtr<nsIGlobalObject> mGlobal;
-    nsRefPtr<FileCallback> mFileCallback;
-  };
-
-  nsRefPtr<EncodeCompleteCallback> callback =
-    new EncodeCallback(aGlobal, &aCallback);
-
-  aRv = ImageEncoder::ExtractDataAsync(type,
-                                       params,
-                                       usingCustomParseOptions,
-                                       imageBuffer,
-                                       format,
-                                       GetWidthHeight(),
-                                       callback);
-}
-
-already_AddRefed<nsICanvasRenderingContextInternal>
-CanvasRenderingContextHelper::CreateContext(CanvasContextType aContextType)
-{
-  MOZ_ASSERT(aContextType != CanvasContextType::NoContext);
-  nsRefPtr<nsICanvasRenderingContextInternal> ret;
-
-  switch (aContextType) {
-  case CanvasContextType::NoContext:
-    break;
-
-  case CanvasContextType::Canvas2D:
-    Telemetry::Accumulate(Telemetry::CANVAS_2D_USED, 1);
-    ret = new CanvasRenderingContext2D();
-    break;
-
-  case CanvasContextType::WebGL1:
-    Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_USED, 1);
-
-    ret = WebGL1Context::Create();
-    if (!ret)
-      return nullptr;
-
-    break;
-
-  case CanvasContextType::WebGL2:
-    Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_USED, 1);
-
-    ret = WebGL2Context::Create();
-    if (!ret)
-      return nullptr;
-
-    break;
-  }
-  MOZ_ASSERT(ret);
-
-  return ret.forget();
-}
-
-already_AddRefed<nsISupports>
-CanvasRenderingContextHelper::GetContext(JSContext* aCx,
-                                         const nsAString& aContextId,
-                                         JS::Handle<JS::Value> aContextOptions,
-                                         ErrorResult& aRv)
-{
-  CanvasContextType contextType;
-  if (!CanvasUtils::GetCanvasContextType(aContextId, &contextType))
-    return nullptr;
-
-  if (!mCurrentContext) {
-    // This canvas doesn't have a context yet.
-    nsRefPtr<nsICanvasRenderingContextInternal> context;
-    context = CreateContext(contextType);
-    if (!context) {
-      return nullptr;
-    }
-
-    // Ensure that the context participates in CC.  Note that returning a
-    // CC participant from QI doesn't addref.
-    nsXPCOMCycleCollectionParticipant* cp = nullptr;
-    CallQueryInterface(context, &cp);
-    if (!cp) {
-      aRv.Throw(NS_ERROR_FAILURE);
-      return nullptr;
-    }
-
-    mCurrentContext = context.forget();
-    mCurrentContextType = contextType;
-
-    aRv = UpdateContext(aCx, aContextOptions);
-    if (aRv.Failed()) {
-      aRv = NS_OK; // See bug 645792
-      return nullptr;
-    }
-  } else {
-    // We already have a context of some type.
-    if (contextType != mCurrentContextType)
-      return nullptr;
-  }
-
-  nsCOMPtr<nsICanvasRenderingContextInternal> context = mCurrentContext;
-  return context.forget();
-}
-
-nsresult
-CanvasRenderingContextHelper::UpdateContext(JSContext* aCx,
-                                            JS::Handle<JS::Value> aNewContextOptions)
-{
-  if (!mCurrentContext)
-    return NS_OK;
-
-  nsIntSize sz = GetWidthHeight();
-
-  nsCOMPtr<nsICanvasRenderingContextInternal> currentContext = mCurrentContext;
-
-  nsresult rv = currentContext->SetIsOpaque(GetOpaqueAttr());
-  if (NS_FAILED(rv)) {
-    mCurrentContext = nullptr;
-    return rv;
-  }
-
-  rv = currentContext->SetContextOptions(aCx, aNewContextOptions);
-  if (NS_FAILED(rv)) {
-    mCurrentContext = nullptr;
-    return rv;
-  }
-
-  rv = currentContext->SetDimensions(sz.width, sz.height);
-  if (NS_FAILED(rv)) {
-    mCurrentContext = nullptr;
-  }
-
-  return rv;
-}
-
-nsresult
-CanvasRenderingContextHelper::ParseParams(JSContext* aCx,
-                                          const nsAString& aType,
-                                          const JS::Value& aEncoderOptions,
-                                          nsAString& outParams,
-                                          bool* const outUsingCustomParseOptions)
-{
-  // Quality parameter is only valid for the image/jpeg MIME type
-  if (aType.EqualsLiteral("image/jpeg")) {
-    if (aEncoderOptions.isNumber()) {
-      double quality = aEncoderOptions.toNumber();
-      // Quality must be between 0.0 and 1.0, inclusive
-      if (quality >= 0.0 && quality <= 1.0) {
-        outParams.AppendLiteral("quality=");
-        outParams.AppendInt(NS_lround(quality * 100.0));
-      }
-    }
-  }
-
-  // If we haven't parsed the aParams check for proprietary options.
-  // The proprietary option -moz-parse-options will take a image lib encoder
-  // parse options string as is and pass it to the encoder.
-  *outUsingCustomParseOptions = false;
-  if (outParams.Length() == 0 && aEncoderOptions.isString()) {
-    NS_NAMED_LITERAL_STRING(mozParseOptions, "-moz-parse-options:");
-    nsAutoJSString paramString;
-    if (!paramString.init(aCx, aEncoderOptions.toString())) {
-      return NS_ERROR_FAILURE;
-    }
-    if (StringBeginsWith(paramString, mozParseOptions)) {
-      nsDependentSubstring parseOptions = Substring(paramString,
-                                                    mozParseOptions.Length(),
-                                                    paramString.Length() -
-                                                    mozParseOptions.Length());
-      outParams.Append(parseOptions);
-      *outUsingCustomParseOptions = true;
-    }
-  }
-
-  return NS_OK;
-}
-
-} // namespace dom
-} // namespace mozilla
deleted file mode 100644
--- a/dom/canvas/CanvasRenderingContextHelper.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 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/. */
-
-#ifndef MOZILLA_DOM_CANVASRENDERINGCONTEXTHELPER_H_
-#define MOZILLA_DOM_CANVASRENDERINGCONTEXTHELPER_H_
-
-#include "mozilla/dom/BindingDeclarations.h"
-#include "nsSize.h"
-
-class nsICanvasRenderingContextInternal;
-class nsIGlobalObject;
-
-namespace mozilla {
-
-class ErrorResult;
-
-namespace dom {
-
-class FileCallback;
-
-enum class CanvasContextType : uint8_t {
-  NoContext,
-  Canvas2D,
-  WebGL1,
-  WebGL2
-};
-
-/**
- * Povides common RenderingContext functionality used by both OffscreenCanvas
- * and HTMLCanvasElement.
- */
-class CanvasRenderingContextHelper
-{
-public:
-  virtual already_AddRefed<nsISupports>
-  GetContext(JSContext* aCx,
-             const nsAString& aContextId,
-             JS::Handle<JS::Value> aContextOptions,
-             ErrorResult& aRv);
-
-  virtual bool GetOpaqueAttr() = 0;
-
-protected:
-  virtual nsresult UpdateContext(JSContext* aCx,
-                                 JS::Handle<JS::Value> aNewContextOptions);
-
-  virtual nsresult ParseParams(JSContext* aCx,
-                               const nsAString& aType,
-                               const JS::Value& aEncoderOptions,
-                               nsAString& outParams,
-                               bool* const outCustomParseOptions);
-
-  void ToBlob(JSContext* aCx, nsIGlobalObject* global, FileCallback& aCallback,
-              const nsAString& aType, JS::Handle<JS::Value> aParams,
-              ErrorResult& aRv);
-
-  virtual already_AddRefed<nsICanvasRenderingContextInternal>
-  CreateContext(CanvasContextType aContextType);
-
-  virtual nsIntSize GetWidthHeight() = 0;
-
-  CanvasContextType mCurrentContextType;
-  nsCOMPtr<nsICanvasRenderingContextInternal> mCurrentContext;
-};
-
-} // namespace dom
-} // namespace mozilla
-
-#endif // MOZILLA_DOM_CANVASRENDERINGCONTEXTHELPER_H_
--- a/dom/canvas/CanvasUtils.cpp
+++ b/dom/canvas/CanvasUtils.cpp
@@ -18,57 +18,22 @@
 #include "nsIPrincipal.h"
 
 #include "nsGfxCIID.h"
 
 #include "nsTArray.h"
 
 #include "CanvasUtils.h"
 #include "mozilla/gfx/Matrix.h"
-#include "WebGL2Context.h"
 
 using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace CanvasUtils {
 
-bool
-GetCanvasContextType(const nsAString& str, dom::CanvasContextType* const out_type)
-{
-  if (str.EqualsLiteral("2d")) {
-    *out_type = dom::CanvasContextType::Canvas2D;
-    return true;
-  }
-
-  if (str.EqualsLiteral("experimental-webgl")) {
-    *out_type = dom::CanvasContextType::WebGL1;
-    return true;
-  }
-
-#ifdef MOZ_WEBGL_CONFORMANT
-  if (str.EqualsLiteral("webgl")) {
-    /* WebGL 1.0, $2.1 "Context Creation":
-     *   If the user agent supports both the webgl and experimental-webgl
-     *   canvas context types, they shall be treated as aliases.
-     */
-    *out_type = dom::CanvasContextType::WebGL1;
-    return true;
-  }
-#endif
-
-  if (WebGL2Context::IsSupported()) {
-    if (str.EqualsLiteral("webgl2")) {
-      *out_type = dom::CanvasContextType::WebGL2;
-      return true;
-    }
-  }
-
-  return false;
-}
-
 /**
  * This security check utility might be called from an source that never taints
  * others. For example, while painting a CanvasPattern, which is created from an
  * ImageBitmap, onto a canvas. In this case, the caller could set the CORSUsed
  * true in order to pass this check and leave the aPrincipal to be a nullptr
  * since the aPrincipal is not going to be used.
  */
 void
--- a/dom/canvas/CanvasUtils.h
+++ b/dom/canvas/CanvasUtils.h
@@ -16,17 +16,16 @@ class nsIPrincipal;
 namespace mozilla {
 
 namespace dom {
 class HTMLCanvasElement;
 } // namespace dom
 
 namespace CanvasUtils {
 
-bool GetCanvasContextType(const nsAString& str, dom::CanvasContextType* const out_type);
 
 // Check that the rectangle [x,y,w,h] is a subrectangle of [0,0,realWidth,realHeight]
 
 inline bool CheckSaneSubrectSize(int32_t x, int32_t y, int32_t w, int32_t h,
                             int32_t realWidth, int32_t realHeight) {
     CheckedInt32 checked_xmost  = CheckedInt32(x) + w;
     CheckedInt32 checked_ymost  = CheckedInt32(y) + h;
 
deleted file mode 100644
--- a/dom/canvas/OffscreenCanvas.cpp
+++ /dev/null
@@ -1,242 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* 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/. */
-
-#include "OffscreenCanvas.h"
-
-#include "mozilla/dom/OffscreenCanvasBinding.h"
-#include "mozilla/dom/WorkerPrivate.h"
-#include "mozilla/layers/AsyncCanvasRenderer.h"
-#include "mozilla/layers/CanvasClient.h"
-#include "mozilla/layers/ImageBridgeChild.h"
-#include "mozilla/Telemetry.h"
-#include "CanvasRenderingContext2D.h"
-#include "CanvasUtils.h"
-#include "GLScreenBuffer.h"
-#include "WebGL1Context.h"
-#include "WebGL2Context.h"
-
-namespace mozilla {
-namespace dom {
-
-OffscreenCanvasCloneData::OffscreenCanvasCloneData(layers::AsyncCanvasRenderer* aRenderer,
-                                                   uint32_t aWidth, uint32_t aHeight,
-                                                   layers::LayersBackend aCompositorBackend,
-                                                   bool aNeutered)
-  : mRenderer(aRenderer)
-  , mWidth(aWidth)
-  , mHeight(aHeight)
-  , mCompositorBackendType(aCompositorBackend)
-  , mNeutered(aNeutered)
-{
-}
-
-OffscreenCanvasCloneData::~OffscreenCanvasCloneData()
-{
-}
-
-OffscreenCanvas::OffscreenCanvas(uint32_t aWidth,
-                                 uint32_t aHeight,
-                                 layers::LayersBackend aCompositorBackend,
-                                 layers::AsyncCanvasRenderer* aRenderer)
-  : mAttrDirty(false)
-  , mNeutered(false)
-  , mWidth(aWidth)
-  , mHeight(aHeight)
-  , mCompositorBackendType(aCompositorBackend)
-  , mCanvasClient(nullptr)
-  , mCanvasRenderer(aRenderer)
-{}
-
-OffscreenCanvas::~OffscreenCanvas()
-{
-  ClearResources();
-}
-
-OffscreenCanvas*
-OffscreenCanvas::GetParentObject() const
-{
-  return nullptr;
-}
-
-JSObject*
-OffscreenCanvas::WrapObject(JSContext* aCx,
-                            JS::Handle<JSObject*> aGivenProto)
-{
-  return OffscreenCanvasBinding::Wrap(aCx, this, aGivenProto);
-}
-
-void
-OffscreenCanvas::ClearResources()
-{
-  if (mCanvasClient) {
-    mCanvasClient->Clear();
-    ImageBridgeChild::DispatchReleaseCanvasClient(mCanvasClient);
-    mCanvasClient = nullptr;
-
-    if (mCanvasRenderer) {
-      nsCOMPtr<nsIThread> activeThread = mCanvasRenderer->GetActiveThread();
-      MOZ_RELEASE_ASSERT(activeThread);
-      MOZ_RELEASE_ASSERT(activeThread == NS_GetCurrentThread());
-      mCanvasRenderer->SetCanvasClient(nullptr);
-      mCanvasRenderer->mContext = nullptr;
-      mCanvasRenderer->mGLContext = nullptr;
-      mCanvasRenderer->ResetActiveThread();
-    }
-  }
-}
-
-already_AddRefed<nsISupports>
-OffscreenCanvas::GetContext(JSContext* aCx,
-                            const nsAString& aContextId,
-                            JS::Handle<JS::Value> aContextOptions,
-                            ErrorResult& aRv)
-{
-  if (mNeutered) {
-    aRv.Throw(NS_ERROR_FAILURE);
-    return nullptr;
-  }
-
-  // We only support WebGL in workers for now
-  CanvasContextType contextType;
-  if (!CanvasUtils::GetCanvasContextType(aContextId, &contextType)) {
-    aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
-    return nullptr;
-  }
-
-  if (!(contextType == CanvasContextType::WebGL1 ||
-        contextType == CanvasContextType::WebGL2))
-  {
-    aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
-    return nullptr;
-  }
-
-  already_AddRefed<nsISupports> result =
-    CanvasRenderingContextHelper::GetContext(aCx,
-                                             aContextId,
-                                             aContextOptions,
-                                             aRv);
-
-  if (!mCurrentContext) {
-    return nullptr;
-  }
-
-  if (mCanvasRenderer) {
-    WebGLContext* webGL = static_cast<WebGLContext*>(mCurrentContext.get());
-    gl::GLContext* gl = webGL->GL();
-    mCanvasRenderer->mContext = mCurrentContext;
-    mCanvasRenderer->SetActiveThread();
-    mCanvasRenderer->mGLContext = gl;
-    mCanvasRenderer->SetIsAlphaPremultiplied(webGL->IsPremultAlpha() || !gl->Caps().alpha);
-
-    if (ImageBridgeChild::IsCreated()) {
-      TextureFlags flags = TextureFlags::ORIGIN_BOTTOM_LEFT;
-      mCanvasClient = ImageBridgeChild::GetSingleton()->
-        CreateCanvasClient(CanvasClient::CanvasClientTypeShSurf, flags).take();
-      mCanvasRenderer->SetCanvasClient(mCanvasClient);
-
-      gl::GLScreenBuffer* screen = gl->Screen();
-      gl::SurfaceCaps caps = screen->mCaps;
-      auto forwarder = mCanvasClient->GetForwarder();
-
-      UniquePtr<gl::SurfaceFactory> factory =
-        gl::GLScreenBuffer::CreateFactory(gl, caps, forwarder, flags);
-
-      if (factory)
-        screen->Morph(Move(factory));
-    }
-  }
-
-  return result;
-}
-
-already_AddRefed<nsICanvasRenderingContextInternal>
-OffscreenCanvas::CreateContext(CanvasContextType aContextType)
-{
-  nsRefPtr<nsICanvasRenderingContextInternal> ret =
-    CanvasRenderingContextHelper::CreateContext(aContextType);
-
-  ret->SetOffscreenCanvas(this);
-  return ret.forget();
-}
-
-void
-OffscreenCanvas::CommitFrameToCompositor()
-{
-  // The attributes has changed, we have to notify main
-  // thread to change canvas size.
-  if (mAttrDirty) {
-    if (mCanvasRenderer) {
-      mCanvasRenderer->SetWidth(mWidth);
-      mCanvasRenderer->SetHeight(mHeight);
-      mCanvasRenderer->NotifyElementAboutAttributesChanged();
-    }
-    mAttrDirty = false;
-  }
-
-  if (mCurrentContext) {
-    static_cast<WebGLContext*>(mCurrentContext.get())->PresentScreenBuffer();
-  }
-
-  if (mCanvasRenderer && mCanvasRenderer->mGLContext) {
-    mCanvasRenderer->NotifyElementAboutInvalidation();
-    ImageBridgeChild::GetSingleton()->
-      UpdateAsyncCanvasRenderer(mCanvasRenderer);
-  }
-}
-
-OffscreenCanvasCloneData*
-OffscreenCanvas::ToCloneData()
-{
-  return new OffscreenCanvasCloneData(mCanvasRenderer, mWidth, mHeight,
-                                      mCompositorBackendType, mNeutered);
-}
-
-/* static */ already_AddRefed<OffscreenCanvas>
-OffscreenCanvas::CreateFromCloneData(OffscreenCanvasCloneData* aData)
-{
-  MOZ_ASSERT(aData);
-  nsRefPtr<OffscreenCanvas> wc =
-    new OffscreenCanvas(aData->mWidth, aData->mHeight,
-                        aData->mCompositorBackendType, aData->mRenderer);
-  if (aData->mNeutered) {
-    wc->SetNeutered();
-  }
-  return wc.forget();
-}
-
-/* static */ bool
-OffscreenCanvas::PrefEnabled(JSContext* aCx, JSObject* aObj)
-{
-  if (NS_IsMainThread()) {
-    return Preferences::GetBool("gfx.offscreencanvas.enabled");
-  } else {
-    WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
-    MOZ_ASSERT(workerPrivate);
-    return workerPrivate->OffscreenCanvasEnabled();
-  }
-}
-
-/* static */ bool
-OffscreenCanvas::PrefEnabledOnWorkerThread(JSContext* aCx, JSObject* aObj)
-{
-  if (NS_IsMainThread()) {
-    return true;
-  }
-
-  return PrefEnabled(aCx, aObj);
-}
-
-NS_IMPL_CYCLE_COLLECTION_INHERITED(OffscreenCanvas, DOMEventTargetHelper, mCurrentContext)
-
-NS_IMPL_ADDREF_INHERITED(OffscreenCanvas, DOMEventTargetHelper)
-NS_IMPL_RELEASE_INHERITED(OffscreenCanvas, DOMEventTargetHelper)
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(OffscreenCanvas)
-  NS_INTERFACE_MAP_ENTRY(nsISupports)
-NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
-
-} // namespace dom
-} // namespace mozilla
deleted file mode 100644
--- a/dom/canvas/OffscreenCanvas.h
+++ /dev/null
@@ -1,179 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* 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 MOZILLA_DOM_OFFSCREENCANVAS_H_
-#define MOZILLA_DOM_OFFSCREENCANVAS_H_
-
-#include "mozilla/DOMEventTargetHelper.h"
-#include "mozilla/layers/LayersTypes.h"
-#include "mozilla/RefPtr.h"
-#include "CanvasRenderingContextHelper.h"
-#include "nsCycleCollectionParticipant.h"
-
-struct JSContext;
-
-namespace mozilla {
-
-class ErrorResult;
-
-namespace layers {
-class AsyncCanvasRenderer;
-class CanvasClient;
-} // namespace layers
-
-namespace dom {
-
-// This is helper class for transferring OffscreenCanvas to worker thread.
-// Because OffscreenCanvas is not thread-safe. So we cannot pass Offscreen-
-// Canvas to worker thread directly. Thus, we create this helper class and
-// store necessary data in it then pass it to worker thread.
-struct OffscreenCanvasCloneData final
-{
-  OffscreenCanvasCloneData(layers::AsyncCanvasRenderer* aRenderer,
-                           uint32_t aWidth, uint32_t aHeight,
-                           layers::LayersBackend aCompositorBackend,
-                           bool aNeutered);
-  ~OffscreenCanvasCloneData();
-
-  RefPtr<layers::AsyncCanvasRenderer> mRenderer;
-  uint32_t mWidth;
-  uint32_t mHeight;
-  layers::LayersBackend mCompositorBackendType;
-  bool mNeutered;
-};
-
-class OffscreenCanvas final : public DOMEventTargetHelper
-                            , public CanvasRenderingContextHelper
-{
-public:
-  NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(OffscreenCanvas, DOMEventTargetHelper)
-
-  OffscreenCanvas(uint32_t aWidth,
-                  uint32_t aHeight,
-                  layers::LayersBackend aCompositorBackend,
-                  layers::AsyncCanvasRenderer* aRenderer);
-
-  OffscreenCanvas* GetParentObject() const;
-
-  virtual JSObject* WrapObject(JSContext* aCx,
-                               JS::Handle<JSObject*> aGivenProto) override;
-
-  void ClearResources();
-
-  uint32_t Width() const
-  {
-    return mWidth;
-  }
-
-  uint32_t Height() const
-  {
-    return mHeight;
-  }
-
-  void SetWidth(uint32_t aWidth, ErrorResult& aRv)
-  {
-    if (mNeutered) {
-      aRv.Throw(NS_ERROR_FAILURE);
-      return;
-    }
-
-    if (mWidth != aWidth) {
-      mWidth = aWidth;
-      CanvasAttrChanged();
-    }
-  }
-
-  void SetHeight(uint32_t aHeight, ErrorResult& aRv)
-  {
-    if (mNeutered) {
-      aRv.Throw(NS_ERROR_FAILURE);
-      return;
-    }
-
-    if (mHeight != aHeight) {
-      mHeight = aHeight;
-      CanvasAttrChanged();
-    }
-  }
-
-  nsICanvasRenderingContextInternal* GetContext() const
-  {
-    return mCurrentContext;
-  }
-
-  static already_AddRefed<OffscreenCanvas>
-  CreateFromCloneData(OffscreenCanvasCloneData* aData);
-
-  static bool PrefEnabled(JSContext* aCx, JSObject* aObj);
-
-  // Return true on main-thread, and return gfx.offscreencanvas.enabled
-  // on worker thread.
-  static bool PrefEnabledOnWorkerThread(JSContext* aCx, JSObject* aObj);
-
-  OffscreenCanvasCloneData* ToCloneData();
-
-  void CommitFrameToCompositor();
-
-  virtual bool GetOpaqueAttr() override
-  {
-    return false;
-  }
-
-  virtual nsIntSize GetWidthHeight() override
-  {
-    return nsIntSize(mWidth, mHeight);
-  }
-
-  virtual already_AddRefed<nsICanvasRenderingContextInternal>
-  CreateContext(CanvasContextType aContextType) override;
-
-  virtual already_AddRefed<nsISupports>
-  GetContext(JSContext* aCx,
-             const nsAString& aContextId,
-             JS::Handle<JS::Value> aContextOptions,
-             ErrorResult& aRv) override;
-
-  void SetNeutered()
-  {
-    mNeutered = true;
-  }
-
-  bool IsNeutered() const
-  {
-    return mNeutered;
-  }
-
-  layers::LayersBackend GetCompositorBackendType() const
-  {
-    return mCompositorBackendType;
-  }
-
-private:
-  ~OffscreenCanvas();
-
-  void CanvasAttrChanged()
-  {
-    mAttrDirty = true;
-    UpdateContext(nullptr, JS::NullHandleValue);
-  }
-
-  bool mAttrDirty;
-  bool mNeutered;
-
-  uint32_t mWidth;
-  uint32_t mHeight;
-
-  layers::LayersBackend mCompositorBackendType;
-
-  layers::CanvasClient* mCanvasClient;
-  RefPtr<layers::AsyncCanvasRenderer> mCanvasRenderer;
-};
-
-} // namespace dom
-} // namespace mozilla
-
-#endif // MOZILLA_DOM_OFFSCREENCANVAS_H_
--- a/dom/canvas/WebGLContext.cpp
+++ b/dom/canvas/WebGLContext.cpp
@@ -17,17 +17,16 @@
 #include "GLContext.h"
 #include "GLContextProvider.h"
 #include "GLReadTexImageHelper.h"
 #include "GLScreenBuffer.h"
 #include "ImageContainer.h"
 #include "ImageEncoder.h"
 #include "Layers.h"
 #include "mozilla/dom/BindingUtils.h"
-#include "mozilla/dom/Event.h"
 #include "mozilla/dom/HTMLVideoElement.h"
 #include "mozilla/dom/ImageData.h"
 #include "mozilla/EnumeratedArrayCycleCollection.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/ProcessPriorityManager.h"
 #include "mozilla/Services.h"
 #include "mozilla/Telemetry.h"
 #include "nsContentUtils.h"
@@ -75,27 +74,146 @@
 
 namespace mozilla {
 
 using namespace mozilla::dom;
 using namespace mozilla::gfx;
 using namespace mozilla::gl;
 using namespace mozilla::layers;
 
+WebGLObserver::WebGLObserver(WebGLContext* webgl)
+    : mWebGL(webgl)
+{
+}
+
+WebGLObserver::~WebGLObserver()
+{
+}
+
+void
+WebGLObserver::Destroy()
+{
+    UnregisterMemoryPressureEvent();
+    UnregisterVisibilityChangeEvent();
+    mWebGL = nullptr;
+}
+
+void
+WebGLObserver::RegisterVisibilityChangeEvent()
+{
+    if (!mWebGL)
+        return;
+
+    HTMLCanvasElement* canvas = mWebGL->GetCanvas();
+    MOZ_ASSERT(canvas);
+
+    if (canvas) {
+        nsIDocument* document = canvas->OwnerDoc();
+
+        document->AddSystemEventListener(NS_LITERAL_STRING("visibilitychange"),
+                                         this, true, false);
+    }
+}
+
+void
+WebGLObserver::UnregisterVisibilityChangeEvent()
+{
+    if (!mWebGL)
+        return;
+
+    HTMLCanvasElement* canvas = mWebGL->GetCanvas();
+
+    if (canvas) {
+        nsIDocument* document = canvas->OwnerDoc();
+
+        document->RemoveSystemEventListener(NS_LITERAL_STRING("visibilitychange"),
+                                            this, true);
+    }
+}
+
+void
+WebGLObserver::RegisterMemoryPressureEvent()
+{
+    if (!mWebGL)
+        return;
+
+    nsCOMPtr<nsIObserverService> observerService =
+        mozilla::services::GetObserverService();
+
+    MOZ_ASSERT(observerService);
+
+    if (observerService)
+        observerService->AddObserver(this, "memory-pressure", false);
+}
+
+void
+WebGLObserver::UnregisterMemoryPressureEvent()
+{
+    if (!mWebGL)
+        return;
+
+    nsCOMPtr<nsIObserverService> observerService =
+        mozilla::services::GetObserverService();
+
+    // Do not assert on observerService here. This might be triggered by
+    // the cycle collector at a late enough time, that XPCOM services are
+    // no longer available. See bug 1029504.
+    if (observerService)
+        observerService->RemoveObserver(this, "memory-pressure");
+}
+
+NS_IMETHODIMP
+WebGLObserver::Observe(nsISupports*, const char* topic, const char16_t*)
+{
+    if (!mWebGL || strcmp(topic, "memory-pressure")) {
+        return NS_OK;
+    }
+
+    bool wantToLoseContext = mWebGL->mLoseContextOnMemoryPressure;
+
+    if (!mWebGL->mCanLoseContextInForeground &&
+        ProcessPriorityManager::CurrentProcessIsForeground())
+    {
+        wantToLoseContext = false;
+    }
+
+    if (wantToLoseContext)
+        mWebGL->ForceLoseContext();
+
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+WebGLObserver::HandleEvent(nsIDOMEvent* event)
+{
+    nsAutoString type;
+    event->GetType(type);
+    if (!mWebGL || !type.EqualsLiteral("visibilitychange"))
+        return NS_OK;
+
+    HTMLCanvasElement* canvas = mWebGL->GetCanvas();
+    MOZ_ASSERT(canvas);
+
+    if (canvas && !canvas->OwnerDoc()->Hidden())
+        mWebGL->ForceRestoreContext();
+
+    return NS_OK;
+}
+
 WebGLContextOptions::WebGLContextOptions()
     : alpha(true)
     , depth(true)
     , stencil(false)
     , premultipliedAlpha(true)
     , antialias(true)
     , preserveDrawingBuffer(false)
     , failIfMajorPerformanceCaveat(false)
 {
     // Set default alpha state based on preference.
-    if (gfxPrefs::WebGLDefaultNoAlpha())
+    if (Preferences::GetBool("webgl.default-no-alpha", false))
         alpha = false;
 }
 
 WebGLContext::WebGLContext()
     : WebGLContextUnchecked(nullptr)
     , mBypassShaderValidation(false)
     , mGLMaxSamples(1)
     , mNeedsFakeNoAlpha(false)
@@ -159,67 +277,67 @@ WebGLContext::WebGLContext()
     mGLMaxUniformBufferBindings = 0;
     mGLMax3DTextureSize = 0;
     mGLMaxArrayTextureLayers = 0;
 
     // See OpenGL ES 2.0.25 spec, 6.2 State Tables, table 6.13
     mPixelStorePackAlignment = 4;
     mPixelStoreUnpackAlignment = 4;
 
-    if (NS_IsMainThread()) {
-        // XXX mtseng: bug 709490, not thread safe
-        WebGLMemoryTracker::AddWebGLContext(this);
-    }
+    WebGLMemoryTracker::AddWebGLContext(this);
 
     mAllowContextRestore = true;
     mLastLossWasSimulated = false;
     mContextLossHandler = new WebGLContextLossHandler(this);
     mContextStatus = ContextNotLost;
     mLoseContextOnMemoryPressure = false;
     mCanLoseContextInForeground = true;
     mRestoreWhenVisible = false;
 
     mAlreadyGeneratedWarnings = 0;
     mAlreadyWarnedAboutFakeVertexAttrib0 = false;
     mAlreadyWarnedAboutViewportLargerThanDest = false;
 
-    mMaxWarnings = gfxPrefs::WebGLMaxWarningsPerContext();
+    mMaxWarnings = Preferences::GetInt("webgl.max-warnings-per-context", 32);
     if (mMaxWarnings < -1) {
         GenerateWarning("webgl.max-warnings-per-context size is too large (seems like a negative value wrapped)");
         mMaxWarnings = 0;
     }
 
+    mContextObserver = new WebGLObserver(this);
+    MOZ_RELEASE_ASSERT(mContextObserver, "Can't alloc WebGLContextObserver");
+
     mLastUseIndex = 0;
 
     InvalidateBufferFetching();
 
     mBackbufferNeedsClear = true;
 
     mDisableFragHighP = false;
 
     mDrawCallsSinceLastFlush = 0;
 }
 
 WebGLContext::~WebGLContext()
 {
     RemovePostRefreshObserver();
+    mContextObserver->Destroy();
 
     DestroyResourcesAndContext();
-    if (NS_IsMainThread()) {
-        // XXX mtseng: bug 709490, not thread safe
-        WebGLMemoryTracker::RemoveWebGLContext(this);
-    }
+    WebGLMemoryTracker::RemoveWebGLContext(this);
 
     mContextLossHandler->DisableTimer();
     mContextLossHandler = nullptr;
 }
 
 void
 WebGLContext::DestroyResourcesAndContext()
 {
+    mContextObserver->UnregisterMemoryPressureEvent();
+
     if (!gl)
         return;
 
     gl->MakeCurrent();
 
     mBound2DTextures.Clear();
     mBoundCubeMapTextures.Clear();
     mBound3DTextures.Clear();
@@ -308,45 +426,16 @@ WebGLContext::Invalidate()
         return;
 
     nsSVGEffects::InvalidateDirectRenderingObservers(mCanvasElement);
 
     mInvalidated = true;
     mCanvasElement->InvalidateCanvasContent(nullptr);
 }
 
-void
-WebGLContext::OnVisibilityChange()
-{
-    if (!IsContextLost()) {
-        return;
-    }
-
-    if (!mRestoreWhenVisible || mLastLossWasSimulated) {
-        return;
-    }
-
-    ForceRestoreContext();
-}
-
-void
-WebGLContext::OnMemoryPressure()
-{
-    bool shouldLoseContext = mLoseContextOnMemoryPressure;
-
-    if (!mCanLoseContextInForeground &&
-        ProcessPriorityManager::CurrentProcessIsForeground())
-    {
-        shouldLoseContext = false;
-    }
-
-    if (shouldLoseContext)
-        ForceLoseContext();
-}
-
 //
 // nsICanvasRenderingContextInternal
 //
 
 NS_IMETHODIMP
 WebGLContext::SetContextOptions(JSContext* cx, JS::Handle<JS::Value> options)
 {
     if (options.isNullOrUndefined() && mOptionsFrozen)
@@ -421,50 +510,40 @@ WebGLContext::GetHeight() const
  * caps. Finally, resize the backbuffer to an acceptable size given the
  * requested size.
  */
 
 static bool
 IsFeatureInBlacklist(const nsCOMPtr<nsIGfxInfo>& gfxInfo, int32_t feature)
 {
     int32_t status;
-    if (!NS_SUCCEEDED(gfxUtils::ThreadSafeGetFeatureStatus(gfxInfo, feature, &status)))
+    if (!NS_SUCCEEDED(gfxInfo->GetFeatureStatus(feature, &status)))
         return false;
 
     return status != nsIGfxInfo::FEATURE_STATUS_OK;
 }
 
 static bool
 HasAcceleratedLayers(const nsCOMPtr<nsIGfxInfo>& gfxInfo)
 {
     int32_t status;
 
-    gfxUtils::ThreadSafeGetFeatureStatus(gfxInfo,
-                                         nsIGfxInfo::FEATURE_DIRECT3D_9_LAYERS,
-                                         &status);
+    gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT3D_9_LAYERS, &status);
     if (status)
         return true;
-    gfxUtils::ThreadSafeGetFeatureStatus(gfxInfo,
-                                         nsIGfxInfo::FEATURE_DIRECT3D_10_LAYERS,
-                                         &status);
+    gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT3D_10_LAYERS, &status);
     if (status)
         return true;
-    gfxUtils::ThreadSafeGetFeatureStatus(gfxInfo,
-                                         nsIGfxInfo::FEATURE_DIRECT3D_10_1_LAYERS,
-                                         &status);
+    gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT3D_10_1_LAYERS, &status);
     if (status)
         return true;
-    gfxUtils::ThreadSafeGetFeatureStatus(gfxInfo,
-                                         nsIGfxInfo::FEATURE_DIRECT3D_11_LAYERS,
-                                         &status);
+    gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT3D_11_LAYERS, &status);
     if (status)
         return true;
-    gfxUtils::ThreadSafeGetFeatureStatus(gfxInfo,
-                                         nsIGfxInfo::FEATURE_OPENGL_LAYERS,
-                                         &status);
+    gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_OPENGL_LAYERS, &status);
     if (status)
         return true;
 
     return false;
 }
 
 static void
 PopulateCapFallbackQueue(const gl::SurfaceCaps& baseCaps,
@@ -511,24 +590,21 @@ BaseCaps(const WebGLContextOptions& opti
     baseCaps.stencil = options.stencil;
 
     if (!baseCaps.alpha)
         baseCaps.premultAlpha = true;
 
     // we should really have this behind a
     // |gfxPlatform::GetPlatform()->GetScreenDepth() == 16| check, but
     // for now it's just behind a pref for testing/evaluation.
-    baseCaps.bpp16 = gfxPrefs::WebGLPrefer16bpp();
+    baseCaps.bpp16 = Preferences::GetBool("webgl.prefer-16bpp", false);
 
 #ifdef MOZ_WIDGET_GONK
     do {
         auto canvasElement = webgl->GetCanvas();
-        if (!canvasElement)
-            break;
-
         auto ownerDoc = canvasElement->OwnerDoc();
         nsIWidget* docWidget = nsContentUtils::WidgetForDocument(ownerDoc);
         if (!docWidget)
             break;
 
         layers::LayerManager* layerManager = docWidget->GetLayerManager();
         if (!layerManager)
             break;
@@ -539,17 +615,17 @@ BaseCaps(const WebGLContextOptions& opti
             break;
 
         baseCaps.surfaceAllocator = static_cast<layers::ISurfaceAllocator*>(forwarder);
     } while (false);
 #endif
 
     // Done with baseCaps construction.
 
-    bool forceAllowAA = gfxPrefs::WebGLForceMSAA();
+    bool forceAllowAA = Preferences::GetBool("webgl.msaa-force", false);
     nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
     if (!forceAllowAA &&
         IsFeatureInBlacklist(gfxInfo, nsIGfxInfo::FEATURE_WEBGL_MSAA))
     {
         webgl->GenerateWarning("Disallowing antialiased backbuffers due"
                                " to blacklisting.");
         baseCaps.antialias = false;
     }
@@ -659,17 +735,17 @@ WebGLContext::CreateAndInitGLWith(FnCrea
 
     return true;
 }
 
 bool
 WebGLContext::CreateAndInitGL(bool forceEnabled)
 {
     bool preferEGL = PR_GetEnv("MOZ_WEBGL_PREFER_EGL");
-    bool disableANGLE = gfxPrefs::WebGLDisableANGLE();
+    bool disableANGLE = Preferences::GetBool("webgl.disable-angle", false);
 
     if (PR_GetEnv("MOZ_WEBGL_FORCE_OPENGL"))
         disableANGLE = true;
 
     gl::CreateContextFlags flags = gl::CreateContextFlags::NONE;
     if (forceEnabled) flags |= gl::CreateContextFlags::FORCE_ENABLE_HARDWARE;
     if (!IsWebGL2())  flags |= gl::CreateContextFlags::REQUIRE_COMPAT_PROFILE;
 
@@ -740,29 +816,30 @@ WebGLContext::ResizeBackbuffer(uint32_t 
                         width, height);
     }
     return true;
 }
 
 NS_IMETHODIMP
 WebGLContext::SetDimensions(int32_t signedWidth, int32_t signedHeight)
 {
+    // Early error return cases
+    if (!GetCanvas())
+        return NS_ERROR_FAILURE;
+
     if (signedWidth < 0 || signedHeight < 0) {
         GenerateWarning("Canvas size is too large (seems like a negative value wrapped)");
         return NS_ERROR_OUT_OF_MEMORY;
     }
 
     uint32_t width = signedWidth;
     uint32_t height = signedHeight;
 
     // Early success return cases
-
-    // May have a OffscreenCanvas instead of an HTMLCanvasElement
-    if (GetCanvas())
-        GetCanvas()->InvalidateCanvas();
+    GetCanvas()->InvalidateCanvas();
 
     // Zero-sized surfaces can cause problems.
     if (width == 0)
         width = 1;
 
     if (height == 0)
         height = 1;
 
@@ -825,17 +902,20 @@ WebGLContext::SetDimensions(int32_t sign
         return NS_ERROR_FAILURE; // exit without changing the value of mGeneration
     }
 
     // increment the generation number - Do this early because later
     // in CreateOffscreenGL(), "default" objects are created that will
     // pick up the old generation.
     ++mGeneration;
 
-    bool disabled = gfxPrefs::WebGLDisabled();
+    // Get some prefs for some preferred/overriden things
+    NS_ENSURE_TRUE(Preferences::GetRootBranch(), NS_ERROR_FAILURE);
+
+    bool disabled = Preferences::GetBool("webgl.disabled", false);
 
     // TODO: When we have software webgl support we should use that instead.
     disabled |= gfxPlatform::InSafeMode();
 
     if (disabled) {
         GenerateWarning("WebGL creation is disabled, and so disallowed here.");
         return NS_ERROR_FAILURE;
     }
@@ -848,17 +928,17 @@ WebGLContext::SetDimensions(int32_t sign
         dom::Nullable<dom::WebGLContextAttributes> contextAttributes;
         this->GetContextAttributes(contextAttributes);
         if (contextAttributes.Value().mFailIfMajorPerformanceCaveat) {
             return NS_ERROR_FAILURE;
         }
     }
 
     // Alright, now let's start trying.
-    bool forceEnabled = gfxPrefs::WebGLForceEnabled();
+    bool forceEnabled = Preferences::GetBool("webgl.force-enabled", false);
     ScopedGfxFeatureReporter reporter("WebGL", forceEnabled);
 
     MOZ_ASSERT(!gl);
     if (!CreateAndInitGL(forceEnabled)) {
         GenerateWarning("WebGL creation failed.");
         return NS_ERROR_FAILURE;
     }
     MOZ_ASSERT(gl);
@@ -969,21 +1049,16 @@ WebGLContext::LoseOldestWebGLContextIfLi
     const size_t kMaxWebGLContextsPerPrincipal = 2;
     const size_t kMaxWebGLContexts             = 4;
 #else
     const size_t kMaxWebGLContextsPerPrincipal = 16;
     const size_t kMaxWebGLContexts             = 32;
 #endif
     MOZ_ASSERT(kMaxWebGLContextsPerPrincipal < kMaxWebGLContexts);
 
-    if (!NS_IsMainThread()) {
-        // XXX mtseng: bug 709490, WebGLMemoryTracker is not thread safe.
-        return;
-    }
-
     // it's important to update the index on a new context before losing old contexts,
     // otherwise new unused contexts would all have index 0 and we couldn't distinguish older ones
     // when choosing which one to lose first.
     UpdateLastUseIndex();
 
     WebGLMemoryTracker::ContextsArrayType& contexts = WebGLMemoryTracker::Contexts();
 
     // quick exit path, should cover a majority of cases
@@ -1061,41 +1136,67 @@ WebGLContext::GetImageBuffer(uint8_t** o
       GetSurfaceSnapshot(mOptions.premultipliedAlpha ? nullptr : &premult);
     if (!snapshot)
         return;
 
     MOZ_ASSERT(mOptions.premultipliedAlpha || !premult, "We must get unpremult when we ask for it!");
 
     RefPtr<DataSourceSurface> dataSurface = snapshot->GetDataSurface();
 
-    return gfxUtils::GetImageBuffer(dataSurface, mOptions.premultipliedAlpha,
-                                    out_imageBuffer, out_format);
+    DataSourceSurface::MappedSurface map;
+    if (!dataSurface->Map(DataSourceSurface::MapType::READ, &map))
+        return;
+
+    uint8_t* imageBuffer = new (fallible) uint8_t[mWidth * mHeight * 4];
+    if (!imageBuffer) {
+        dataSurface->Unmap();
+        return;
+    }
+    memcpy(imageBuffer, map.mData, mWidth * mHeight * 4);
+
+    dataSurface->Unmap();
+
+    int32_t format = imgIEncoder::INPUT_FORMAT_HOSTARGB;
+    if (!mOptions.premultipliedAlpha) {
+        // We need to convert to INPUT_FORMAT_RGBA, otherwise
+        // we are automatically considered premult, and unpremult'd.
+        // Yes, it is THAT silly.
+        // Except for different lossy conversions by color,
+        // we could probably just change the label, and not change the data.
+        gfxUtils::ConvertBGRAtoRGBA(imageBuffer, mWidth * mHeight * 4);
+        format = imgIEncoder::INPUT_FORMAT_RGBA;
+    }
+
+    *out_imageBuffer = imageBuffer;
+    *out_format = format;
 }
 
 NS_IMETHODIMP
 WebGLContext::GetInputStream(const char* mimeType,
                              const char16_t* encoderOptions,
                              nsIInputStream** out_stream)
 {
     NS_ASSERTION(gl, "GetInputStream on invalid context?");
     if (!gl)
         return NS_ERROR_FAILURE;
 
-    // Use GetSurfaceSnapshot() to make sure that appropriate y-flip gets applied
-    bool premult;
-    RefPtr<SourceSurface> snapshot =
-      GetSurfaceSnapshot(mOptions.premultipliedAlpha ? nullptr : &premult);
-    if (!snapshot)
+    nsCString enccid("@mozilla.org/image/encoder;2?type=");
+    enccid += mimeType;
+    nsCOMPtr<imgIEncoder> encoder = do_CreateInstance(enccid.get());
+    if (!encoder)
         return NS_ERROR_FAILURE;
 
-    MOZ_ASSERT(mOptions.premultipliedAlpha || !premult, "We must get unpremult when we ask for it!");
+    nsAutoArrayPtr<uint8_t> imageBuffer;
+    int32_t format = 0;
+    GetImageBuffer(getter_Transfers(imageBuffer), &format);
+    if (!imageBuffer)
+        return NS_ERROR_FAILURE;
 
-    RefPtr<DataSourceSurface> dataSurface = snapshot->GetDataSurface();
-    return gfxUtils::GetInputStream(dataSurface, mOptions.premultipliedAlpha, mimeType,
-                                    encoderOptions, out_stream);
+    return ImageEncoder::GetInputStream(mWidth, mHeight, imageBuffer, format,
+                                        encoder, encoderOptions, out_stream);
 }
 
 void
 WebGLContext::UpdateLastUseIndex()
 {
     static CheckedInt<uint64_t> sIndex = 0;
 
     sIndex++;
@@ -1164,36 +1265,35 @@ WebGLContext::GetCanvasLayer(nsDisplayLi
 
     nsRefPtr<CanvasLayer> canvasLayer = manager->CreateCanvasLayer();
     if (!canvasLayer) {
         NS_WARNING("CreateCanvasLayer returned null!");
         return nullptr;
     }
 
     WebGLContextUserData* userData = nullptr;
-    if (builder->IsPaintingToWindow() && mCanvasElement) {
-        // Make the layer tell us whenever a transaction finishes (including
-        // the current transaction), so we can clear our invalidation state and
-        // start invalidating again. We need to do this for the layer that is
-        // being painted to a window (there shouldn't be more than one at a time,
-        // and if there is, flushing the invalidation state more often than
-        // necessary is harmless).
+    if (builder->IsPaintingToWindow()) {
+      // Make the layer tell us whenever a transaction finishes (including
+      // the current transaction), so we can clear our invalidation state and
+      // start invalidating again. We need to do this for the layer that is
+      // being painted to a window (there shouldn't be more than one at a time,
+      // and if there is, flushing the invalidation state more often than
+      // necessary is harmless).
 
-        // The layer will be destroyed when we tear down the presentation
-        // (at the latest), at which time this userData will be destroyed,
-        // releasing the reference to the element.
-        // The userData will receive DidTransactionCallbacks, which flush the
-        // the invalidation state to indicate that the canvas is up to date.
-        userData = new WebGLContextUserData(mCanvasElement);
-        canvasLayer->SetDidTransactionCallback(
-            WebGLContextUserData::DidTransactionCallback, userData);
-        canvasLayer->SetPreTransactionCallback(
-            WebGLContextUserData::PreTransactionCallback, userData);
+      // The layer will be destroyed when we tear down the presentation
+      // (at the latest), at which time this userData will be destroyed,
+      // releasing the reference to the element.
+      // The userData will receive DidTransactionCallbacks, which flush the
+      // the invalidation state to indicate that the canvas is up to date.
+      userData = new WebGLContextUserData(mCanvasElement);
+      canvasLayer->SetDidTransactionCallback(
+              WebGLContextUserData::DidTransactionCallback, userData);
+      canvasLayer->SetPreTransactionCallback(
+              WebGLContextUserData::PreTransactionCallback, userData);
     }
-
     canvasLayer->SetUserData(&gWebGLLayerUserData, userData);
 
     CanvasLayer::Data data;
     data.mGLContext = gl;
     data.mSize = nsIntSize(mWidth, mHeight);
     data.mHasAlpha = gl->Caps().alpha;
     data.mIsGLAlphaPremult = IsPremultAlpha() || !data.mHasAlpha;
 
@@ -1205,47 +1305,25 @@ WebGLContext::GetCanvasLayer(nsDisplayLi
     mResetLayer = false;
 
     return canvasLayer.forget();
 }
 
 layers::LayersBackend
 WebGLContext::GetCompositorBackendType() const
 {
-    if (mCanvasElement) {
-        return mCanvasElement->GetCompositorBackendType();
-    } else if (mOffscreenCanvas) {
-        return mOffscreenCanvas->GetCompositorBackendType();
+    nsIWidget* docWidget = nsContentUtils::WidgetForDocument(mCanvasElement->OwnerDoc());
+    if (docWidget) {
+        layers::LayerManager* layerManager = docWidget->GetLayerManager();
+        return layerManager->GetCompositorBackendType();
     }
-
     return LayersBackend::LAYERS_NONE;
 }
 
 void
-WebGLContext::Commit()
-{
-    if (mOffscreenCanvas) {
-        mOffscreenCanvas->CommitFrameToCompositor();
-    }
-}
-
-void
-WebGLContext::GetCanvas(Nullable<dom::OwningHTMLCanvasElementOrOffscreenCanvas>& retval)
-{
-    if (mCanvasElement) {
-        MOZ_RELEASE_ASSERT(!mOffscreenCanvas);
-        retval.SetValue().SetAsHTMLCanvasElement() = mCanvasElement;
-    } else if (mOffscreenCanvas) {
-        retval.SetValue().SetAsOffscreenCanvas() = mOffscreenCanvas;
-    } else {
-        retval.SetNull();
-    }
-}
-
-void
 WebGLContext::GetContextAttributes(dom::Nullable<dom::WebGLContextAttributes>& retval)
 {
     retval.SetNull();
     if (IsContextLost())
         return;
 
     dom::WebGLContextAttributes& result = retval.SetValue();
 
@@ -1543,37 +1621,31 @@ WebGLContext::TryToRestoreContext()
 }
 
 void
 WebGLContext::RunContextLossTimer()
 {
     mContextLossHandler->RunTimer();
 }
 
-class UpdateContextLossStatusTask : public nsCancelableRunnable
+class UpdateContextLossStatusTask : public nsRunnable
 {
     nsRefPtr<WebGLContext> mWebGL;
 
 public:
     explicit UpdateContextLossStatusTask(WebGLContext* webgl)
         : mWebGL(webgl)
     {
     }
 
     NS_IMETHOD Run() {
-        if (mWebGL)
-            mWebGL->UpdateContextLossStatus();
+        mWebGL->UpdateContextLossStatus();
 
         return NS_OK;
     }
-
-    NS_IMETHOD Cancel() {
-        mWebGL = nullptr;
-        return NS_OK;
-    }
 };
 
 void
 WebGLContext::EnqueueUpdateContextLossStatus()
 {
     nsCOMPtr<nsIRunnable> task = new UpdateContextLossStatusTask(this);
     NS_DispatchToCurrentThread(task);
 }
@@ -1590,17 +1662,17 @@ WebGLContext::EnqueueUpdateContextLossSt
 // fires.
 // Note that this timer mechanism is not used unless one of these 3 criteria
 // are met.
 // At a bare minimum, from context lost to context restores, it would take 3
 // full timer iterations: detection, webglcontextlost, webglcontextrestored.
 void
 WebGLContext::UpdateContextLossStatus()
 {
-    if (!mCanvasElement && !mOffscreenCanvas) {
+    if (!mCanvasElement) {
         // the canvas is gone. That happens when the page was closed before we got
         // this timer event. In this case, there's nothing to do here, just don't crash.
         return;
     }
     if (mContextStatus == ContextNotLost) {
         // We don't know that we're lost, but we might be, so we need to
         // check. If we're guilty, don't allow restores, though.
 
@@ -1618,33 +1690,22 @@ WebGLContext::UpdateContextLossStatus()
         // Fall through.
     }
 
     if (mContextStatus == ContextLostAwaitingEvent) {
         // The context has been lost and we haven't yet triggered the
         // callback, so do that now.
 
         bool useDefaultHandler;
-
-        if (mCanvasElement) {
-            nsContentUtils::DispatchTrustedEvent(
-                mCanvasElement->OwnerDoc(),
-                static_cast<nsIDOMHTMLCanvasElement*>(mCanvasElement),
-                NS_LITERAL_STRING("webglcontextlost"),
-                true,
-                true,
-                &useDefaultHandler);
-        } else {
-            // OffscreenCanvas case
-            nsRefPtr<Event> event = new Event(mOffscreenCanvas, nullptr, nullptr);
-            event->InitEvent(NS_LITERAL_STRING("webglcontextlost"), true, true);
-            event->SetTrusted(true);
-            mOffscreenCanvas->DispatchEvent(event, &useDefaultHandler);
-        }
-
+        nsContentUtils::DispatchTrustedEvent(mCanvasElement->OwnerDoc(),
+                                             static_cast<nsIDOMHTMLCanvasElement*>(mCanvasElement),
+                                             NS_LITERAL_STRING("webglcontextlost"),
+                                             true,
+                                             true,
+                                             &useDefaultHandler);
         // We sent the callback, so we're just 'regular lost' now.
         mContextStatus = ContextLost;
         // If we're told to use the default handler, it means the script
         // didn't bother to handle the event. In this case, we shouldn't
         // auto-restore the context.
         if (useDefaultHandler)
             mAllowContextRestore = false;
 
@@ -1686,32 +1747,21 @@ WebGLContext::UpdateContextLossStatus()
         if (!TryToRestoreContext()) {
             // Failed to restore. Try again later.
             mContextLossHandler->RunTimer();
             return;
         }
 
         // Revival!
         mContextStatus = ContextNotLost;
-
-        if (mCanvasElement) {
-            nsContentUtils::DispatchTrustedEvent(
-                mCanvasElement->OwnerDoc(),
-                static_cast<nsIDOMHTMLCanvasElement*>(mCanvasElement),
-                NS_LITERAL_STRING("webglcontextrestored"),
-                true,
-                true);
-        } else {
-            nsRefPtr<Event> event = new Event(mOffscreenCanvas, nullptr, nullptr);
-            event->InitEvent(NS_LITERAL_STRING("webglcontextrestored"), true, true);
-            event->SetTrusted(true);
-            bool unused;
-            mOffscreenCanvas->DispatchEvent(event, &unused);
-        }
-
+        nsContentUtils::DispatchTrustedEvent(mCanvasElement->OwnerDoc(),
+                                             static_cast<nsIDOMHTMLCanvasElement*>(mCanvasElement),
+                                             NS_LITERAL_STRING("webglcontextrestored"),
+                                             true,
+                                             true);
         mEmitContextLostErrorOnce = true;
         return;
     }
 }
 
 void
 WebGLContext::ForceLoseContext(bool simulateLosing)
 {
@@ -1719,27 +1769,35 @@ WebGLContext::ForceLoseContext(bool simu
     MOZ_ASSERT(!IsContextLost());
     mContextStatus = ContextLostAwaitingEvent;
     mContextLostErrorSet = false;
 
     // Burn it all!
     DestroyResourcesAndContext();
     mLastLossWasSimulated = simulateLosing;
 
+    // Register visibility change observer to defer the context restoring.
+    // Restore the context when the app is visible.
+    if (mRestoreWhenVisible && !mLastLossWasSimulated) {
+        mContextObserver->RegisterVisibilityChangeEvent();
+    }
+
     // Queue up a task, since we know the status changed.
     EnqueueUpdateContextLossStatus();
 }
 
 void
 WebGLContext::ForceRestoreContext()
 {
     printf_stderr("WebGL(%p)::ForceRestoreContext\n", this);
     mContextStatus = ContextLostAwaitingRestore;
     mAllowContextRestore = true; // Hey, you did say 'force'.
 
+    mContextObserver->UnregisterVisibilityChangeEvent();
+
     // Queue up a task, since we know the status changed.
     EnqueueUpdateContextLossStatus();
 }
 
 void
 WebGLContext::MakeContextCurrent() const
 {
     gl->MakeCurrent();
@@ -1864,17 +1922,16 @@ WebGLContext::ScopedMaskWorkaround::~Sco
 ////////////////////////////////////////////////////////////////////////////////
 // XPCOM goop
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(WebGLContext)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(WebGLContext)
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(WebGLContext,
   mCanvasElement,
-  mOffscreenCanvas,
   mExtensions,
   mBound2DTextures,
   mBoundCubeMapTextures,
   mBound3DTextures,
   mBoundSamplers,
   mBoundArrayBuffer,
   mBoundCopyReadBuffer,
   mBoundCopyWriteBuffer,
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -35,21 +35,17 @@
 #include "WebGLContextUnchecked.h"
 #include "WebGLFormats.h"
 #include "WebGLObjectModel.h"
 #include "WebGLStrongTypes.h"
 
 // Generated
 #include "nsIDOMEventListener.h"
 #include "nsIDOMWebGLRenderingContext.h"
-#include "nsICanvasRenderingContextInternal.h"
 #include "nsIObserver.h"
-#include "mozilla/dom/HTMLCanvasElement.h"
-#include "nsWrapperCache.h"
-#include "nsLayoutUtils.h"
 
 
 class nsIDocShell;
 
 /*
  * Minimum value constants defined in 6.2 State Tables of OpenGL ES - 2.0.25
  *   https://bugzilla.mozilla.org/show_bug.cgi?id=686732
  *
@@ -79,31 +75,31 @@ class nsIDocShell;
 
 namespace mozilla {
 
 class WebGLActiveInfo;
 class WebGLContextLossHandler;
 class WebGLBuffer;
 class WebGLExtensionBase;
 class WebGLFramebuffer;
+class WebGLObserver;
 class WebGLProgram;
 class WebGLQuery;
 class WebGLRenderbuffer;
 class WebGLSampler;
 class WebGLShader;
 class WebGLShaderPrecisionFormat;
 class WebGLTexture;
 class WebGLTransformFeedback;
 class WebGLUniformLocation;
 class WebGLVertexArray;
 
 namespace dom {
 class Element;
 class ImageData;
-class OwningHTMLCanvasElementOrOffscreenCanvas;
 struct WebGLContextAttributes;
 template<typename> struct Nullable;
 } // namespace dom
 
 namespace gfx {
 class SourceSurface;
 } // namespace gfx
 
@@ -183,16 +179,17 @@ class WebGLContext
     friend class WebGLExtensionCompressedTexturePVRTC;
     friend class WebGLExtensionCompressedTextureS3TC;
     friend class WebGLExtensionDepthTexture;
     friend class WebGLExtensionDisjointTimerQuery;
     friend class WebGLExtensionDrawBuffers;
     friend class WebGLExtensionLoseContext;
     friend class WebGLExtensionVertexArray;
     friend class WebGLMemoryTracker;
+    friend class WebGLObserver;
 
     enum {
         UNPACK_FLIP_Y_WEBGL = 0x9240,
         UNPACK_PREMULTIPLY_ALPHA_WEBGL = 0x9241,
         CONTEXT_LOST_WEBGL = 0x9242,
         UNPACK_COLORSPACE_CONVERSION_WEBGL = 0x9243,
         BROWSER_DEFAULT_WEBGL = 0x9244,
         UNMASKED_VENDOR_WEBGL = 0x9245,
@@ -212,19 +209,16 @@ public:
 
     NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(WebGLContext,
                                                            nsIDOMWebGLRenderingContext)
 
     virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto) override = 0;
 
     NS_DECL_NSIDOMWEBGLRENDERINGCONTEXT
 
-    virtual void OnVisibilityChange() override;
-    virtual void OnMemoryPressure() override;
-
     // nsICanvasRenderingContextInternal
 #ifdef DEBUG
     virtual int32_t GetWidth() const override;
     virtual int32_t GetHeight() const override;
 #endif
     NS_IMETHOD SetDimensions(int32_t width, int32_t height) override;
     NS_IMETHOD InitializeWithSurface(nsIDocShell*, gfxASurface*, int32_t,
                                      int32_t) override
@@ -363,21 +357,18 @@ public:
     void UpdateContextLossStatus();
     void EnqueueUpdateContextLossStatus();
 
     bool TryToRestoreContext();
 
     void AssertCachedBindings();
     void AssertCachedState();
 
+    // WebIDL WebGLRenderingContext API
     dom::HTMLCanvasElement* GetCanvas() const { return mCanvasElement; }
-
-    // WebIDL WebGLRenderingContext API
-    void Commit();
-    void GetCanvas(Nullable<dom::OwningHTMLCanvasElementOrOffscreenCanvas>& retval);
     GLsizei DrawingBufferWidth() const { return IsContextLost() ? 0 : mWidth; }
     GLsizei DrawingBufferHeight() const {
         return IsContextLost() ? 0 : mHeight;
     }
 
     layers::LayersBackend GetCompositorBackendType() const;
 
     void
@@ -1513,16 +1504,18 @@ protected:
     // see bug 713305. This RAII helper guarantees that we're on the discrete GPU, during its lifetime
     // Debouncing note: we don't want to switch GPUs too frequently, so try to not create and destroy
     // these objects at high frequency. Having WebGLContext's hold one such object seems fine,
     // because WebGLContext objects only go away during GC, which shouldn't happen too frequently.
     // If in the future GC becomes much more frequent, we may have to revisit then (maybe use a timer).
     ForceDiscreteGPUHelperCGL mForceDiscreteGPUHelper;
 #endif
 
+    nsRefPtr<WebGLObserver> mContextObserver;
+
 public:
     // console logging helpers
     void GenerateWarning(const char* fmt, ...);
     void GenerateWarning(const char* fmt, va_list ap);
 
 public:
     UniquePtr<webgl::FormatUsageAuthority> mFormatUsage;
     virtual UniquePtr<webgl::FormatUsageAuthority> CreateFormatUsage() const = 0;
@@ -1617,16 +1610,42 @@ WebGLContext::ValidateObject(const char*
     if (!object) {
         ErrorInvalidValue("%s: null object passed as argument", info);
         return false;
     }
 
     return ValidateObjectAssumeNonNull(info, object);
 }
 
+// Listen visibilitychange and memory-pressure event for context lose/restore
+class WebGLObserver final
+    : public nsIObserver
+    , public nsIDOMEventListener
+{
+public:
+    NS_DECL_ISUPPORTS
+    NS_DECL_NSIOBSERVER
+    NS_DECL_NSIDOMEVENTLISTENER
+
+    explicit WebGLObserver(WebGLContext* webgl);
+
+    void Destroy();
+
+    void RegisterVisibilityChangeEvent();
+    void UnregisterVisibilityChangeEvent();
+
+    void RegisterMemoryPressureEvent();
+    void UnregisterMemoryPressureEvent();
+
+private:
+    ~WebGLObserver();
+
+    WebGLContext* mWebGL;
+};
+
 size_t RoundUpToMultipleOf(size_t value, size_t multiple);
 
 bool
 ValidateTexTarget(WebGLContext* webgl, GLenum rawTexTarget, const char* funcName,
                   TexTarget* const out_texTarget, WebGLTexture** const out_tex);
 bool
 ValidateTexImageTarget(WebGLContext* webgl, GLenum rawTexImageTarget,
                        const char* funcName, TexImageTarget* const out_texImageTarget,
--- a/dom/canvas/WebGLContextExtensions.cpp
+++ b/dom/canvas/WebGLContextExtensions.cpp
@@ -1,17 +1,16 @@
 /* -*- 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 "WebGLContext.h"
 #include "WebGLContextUtils.h"
 #include "WebGLExtensions.h"
-#include "gfxPrefs.h"
 #include "GLContext.h"
 
 #include "nsString.h"
 #include "mozilla/Preferences.h"
 #include "AccessCheck.h"
 
 namespace mozilla {
 
@@ -70,25 +69,22 @@ WebGLContext::IsExtensionEnabled(WebGLEx
 
 bool WebGLContext::IsExtensionSupported(JSContext* cx,
                                         WebGLExtensionID ext) const
 {
     bool allowPrivilegedExts = false;
 
     // Chrome contexts need access to debug information even when
     // webgl.disable-extensions is set. This is used in the graphics
-    // section of about:support
-    if (NS_IsMainThread() &&
-        xpc::AccessCheck::isChrome(js::GetContextCompartment(cx))) {
+    // section of about:support.
+    if (xpc::AccessCheck::isChrome(js::GetContextCompartment(cx)))
         allowPrivilegedExts = true;
-    }
 
-    if (gfxPrefs::WebGLPrivilegedExtensionsEnabled()) {
+    if (Preferences::GetBool("webgl.enable-privileged-extensions", false))
         allowPrivilegedExts = true;
-    }
 
     if (allowPrivilegedExts) {
         switch (ext) {
         case WebGLExtensionID::WEBGL_debug_renderer_info:
             return true;
         case WebGLExtensionID::WEBGL_debug_shaders:
             return true;
         default:
@@ -180,17 +176,19 @@ WebGLContext::IsExtensionSupported(WebGL
         // We always support this extension.
         return true;
 
     default:
         // For warnings-as-errors.
         break;
     }
 
-    if (gfxPrefs::WebGLDraftExtensionsEnabled() || IsWebGL2()) {
+    if (Preferences::GetBool("webgl.enable-draft-extensions", false) ||
+        IsWebGL2())
+    {
         switch (ext) {
         case WebGLExtensionID::EXT_disjoint_timer_query:
             return WebGLExtensionDisjointTimerQuery::IsSupported(this);
         default:
             // For warnings-as-errors.
             break;
         }
     }
--- a/dom/canvas/WebGLContextGL.cpp
+++ b/dom/canvas/WebGLContextGL.cpp
@@ -1385,20 +1385,17 @@ void
 WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width,
                          GLsizei height, GLenum format,
                          GLenum type, const dom::Nullable<dom::ArrayBufferView>& pixels,
                          ErrorResult& rv)
 {
     if (IsContextLost())
         return;
 
-    if (mCanvasElement &&
-        mCanvasElement->IsWriteOnly() &&
-        !nsContentUtils::IsCallerChrome())
-    {
+    if (mCanvasElement->IsWriteOnly() && !nsContentUtils::IsCallerChrome()) {
         GenerateWarning("readPixels: Not allowed");
         return rv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     }
 
     if (width < 0 || height < 0)
         return ErrorInvalidValue("readPixels: negative size passed");
 
     if (pixels.IsNull())
--- a/dom/canvas/WebGLContextLossHandler.cpp
+++ b/dom/canvas/WebGLContextLossHandler.cpp
@@ -3,113 +3,25 @@
  * 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 "WebGLContextLossHandler.h"
 
 #include "nsITimer.h"
 #include "nsThreadUtils.h"
 #include "WebGLContext.h"
-#include "mozilla/dom/WorkerPrivate.h"
 
 namespace mozilla {
 
-// -------------------------------------------------------------------
-// Begin worker specific code
-// -------------------------------------------------------------------
-
-// On workers we can only dispatch CancelableRunnables, so we have to wrap the
-// timer's EventTarget to use our own cancelable runnable
-
-class ContextLossWorkerEventTarget final : public nsIEventTarget
-{
-public:
-    explicit ContextLossWorkerEventTarget(nsIEventTarget* aEventTarget)
-        : mEventTarget(aEventTarget)
-    {
-        MOZ_ASSERT(aEventTarget);
-    }
-
-    NS_DECL_NSIEVENTTARGET
-    NS_DECL_THREADSAFE_ISUPPORTS
-
-protected:
-    ~ContextLossWorkerEventTarget() {}
-
-private:
-    nsCOMPtr<nsIEventTarget> mEventTarget;
-};
-
-class ContextLossWorkerRunnable final : public nsICancelableRunnable
-{
-public:
-    explicit ContextLossWorkerRunnable(nsIRunnable* aRunnable)
-        : mRunnable(aRunnable)
-    {
-    }
-
-    NS_DECL_NSICANCELABLERUNNABLE
-    NS_DECL_THREADSAFE_ISUPPORTS
-
-    NS_FORWARD_NSIRUNNABLE(mRunnable->)
-
-protected:
-    ~ContextLossWorkerRunnable() {}
-
-private:
-    nsCOMPtr<nsIRunnable> mRunnable;
-};
-
-NS_IMPL_ISUPPORTS(ContextLossWorkerEventTarget, nsIEventTarget,
-                  nsISupports)
-
-NS_IMETHODIMP
-ContextLossWorkerEventTarget::DispatchFromScript(nsIRunnable* aEvent, uint32_t aFlags)
-{
-    nsCOMPtr<nsIRunnable> event(aEvent);
-    return Dispatch(event.forget(), aFlags);
-}
-
-NS_IMETHODIMP
-ContextLossWorkerEventTarget::Dispatch(already_AddRefed<nsIRunnable>&& aEvent,
-                                       uint32_t aFlags)
-{
-    nsCOMPtr<nsIRunnable> eventRef(aEvent);
-    nsRefPtr<ContextLossWorkerRunnable> wrappedEvent =
-        new ContextLossWorkerRunnable(eventRef);
-    return mEventTarget->Dispatch(wrappedEvent, aFlags);
-}
-
-NS_IMETHODIMP
-ContextLossWorkerEventTarget::IsOnCurrentThread(bool* aResult)
-{
-    return mEventTarget->IsOnCurrentThread(aResult);
-}
-
-NS_IMPL_ISUPPORTS(ContextLossWorkerRunnable, nsICancelableRunnable,
-                  nsIRunnable)
-
-NS_IMETHODIMP
-ContextLossWorkerRunnable::Cancel()
-{
-    mRunnable = nullptr;
-    return NS_OK;
-}
-
-// -------------------------------------------------------------------
-// End worker-specific code
-// -------------------------------------------------------------------
-
 WebGLContextLossHandler::WebGLContextLossHandler(WebGLContext* webgl)
     : mWeakWebGL(webgl)
     , mTimer(do_CreateInstance(NS_TIMER_CONTRACTID))
     , mIsTimerRunning(false)
     , mShouldRunTimerAgain(false)
     , mIsDisabled(false)
-    , mFeatureAdded(false)
 #ifdef DEBUG
     , mThread(NS_GetCurrentThread())
 #endif
 {
 }
 
 WebGLContextLossHandler::~WebGLContextLossHandler()
 {
@@ -173,66 +85,35 @@ WebGLContextLossHandler::RunTimer()
     // wait until the previous call is done, then fire it one more time.
     // This is an optimization to prevent unnecessary
     // cross-communication between threads.
     if (mIsTimerRunning) {
         mShouldRunTimerAgain = true;
         return;
     }
 
-    if (!NS_IsMainThread()) {
-        dom::workers::WorkerPrivate* workerPrivate =
-            dom::workers::GetCurrentThreadWorkerPrivate();
-        nsCOMPtr<nsIEventTarget> target = workerPrivate->GetEventTarget();
-        mTimer->SetTarget(new ContextLossWorkerEventTarget(target));
-        if (!mFeatureAdded) {
-            workerPrivate->AddFeature(workerPrivate->GetJSContext(), this);
-            mFeatureAdded = true;
-        }
-    }
-
     StartTimer(1000);
 
     mIsTimerRunning = true;
     mShouldRunTimerAgain = false;
 }
 
 void
 WebGLContextLossHandler::DisableTimer()
 {
     if (mIsDisabled)
         return;
 
     mIsDisabled = true;
 
-    if (mFeatureAdded) {
-        dom::workers::WorkerPrivate* workerPrivate =
-            dom::workers::GetCurrentThreadWorkerPrivate();
-        MOZ_RELEASE_ASSERT(workerPrivate);
-        workerPrivate->RemoveFeature(workerPrivate->GetJSContext(), this);
-        mFeatureAdded = false;
-    }
-
     // We can't just Cancel() the timer, as sometimes we end up
     // receiving a callback after calling Cancel(). This could cause us
     // to receive the callback after object destruction.
 
     // Instead, we let the timer finish, but ignore it.
 
     if (!mIsTimerRunning)
         return;
 
     mTimer->SetDelay(0);
 }
 
-bool
-WebGLContextLossHandler::Notify(JSContext* aCx, dom::workers::Status aStatus)
-{
-    bool isWorkerRunning = aStatus < dom::workers::Closing;
-    if (!isWorkerRunning && mIsTimerRunning) {
-        mIsTimerRunning = false;
-        this->Release();
-    }
-
-    return true;
-}
-
 } // namespace mozilla
--- a/dom/canvas/WebGLContextLossHandler.h
+++ b/dom/canvas/WebGLContextLossHandler.h
@@ -5,42 +5,39 @@
 
 #ifndef WEBGL_CONTEXT_LOSS_HANDLER_H_
 #define WEBGL_CONTEXT_LOSS_HANDLER_H_
 
 #include "mozilla/DebugOnly.h"
 #include "mozilla/WeakPtr.h"
 #include "nsCOMPtr.h"
 #include "nsISupportsImpl.h"
-#include "WorkerFeature.h"
 
 class nsIThread;
 class nsITimer;
 
 namespace mozilla {
 class WebGLContext;
 
-class WebGLContextLossHandler : public dom::workers::WorkerFeature
+class WebGLContextLossHandler
 {
     WeakPtr<WebGLContext> mWeakWebGL;
     nsCOMPtr<nsITimer> mTimer;
     bool mIsTimerRunning;
     bool mShouldRunTimerAgain;
     bool mIsDisabled;
-    bool mFeatureAdded;
     DebugOnly<nsIThread*> mThread;
 
 public:
     NS_INLINE_DECL_REFCOUNTING(WebGLContextLossHandler)
 
     explicit WebGLContextLossHandler(WebGLContext* webgl);
 
     void RunTimer();
     void DisableTimer();
-    bool Notify(JSContext* aCx, dom::workers::Status aStatus) override;
 
 protected:
     ~WebGLContextLossHandler();
 
     void StartTimer(unsigned long delayMS);
     static void StaticTimerCallback(nsITimer*, void* tempRefForTimer);
     void TimerCallback();
 };
--- a/dom/canvas/WebGLContextReporter.cpp
+++ b/dom/canvas/WebGLContextReporter.cpp
@@ -4,16 +4,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "WebGLBuffer.h"
 #include "WebGLContext.h"
 #include "WebGLMemoryTracker.h"
 
 namespace mozilla {
 
+NS_IMPL_ISUPPORTS(WebGLObserver, nsIObserver)
+
 NS_IMETHODIMP
 WebGLMemoryTracker::CollectReports(nsIHandleReportCallback* handleReport,
                                    nsISupports* data, bool)
 {
 #define REPORT(_path, _kind, _units, _amount, _desc)                         \
     do {                                                                     \
       nsresult rv;                                                           \
       rv = handleReport->Callback(EmptyCString(), NS_LITERAL_CSTRING(_path), \
--- a/dom/canvas/WebGLContextValidate.cpp
+++ b/dom/canvas/WebGLContextValidate.cpp
@@ -3,17 +3,16 @@
  * 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 <algorithm>
 #include "angle/ShaderLang.h"
 #include "CanvasUtils.h"
-#include "gfxPrefs.h"
 #include "GLContext.h"
 #include "jsfriendapi.h"
 #include "mozilla/CheckedInt.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 #include "nsIObserverService.h"
 #include "WebGLActiveInfo.h"
 #include "WebGLBuffer.h"
@@ -1661,21 +1660,21 @@ WebGLContext::InitAndValidateGL()
 
     GLenum error = gl->fGetError();
     if (error != LOCAL_GL_NO_ERROR) {
         GenerateWarning("GL error 0x%x occurred during OpenGL context"
                         " initialization, before WebGL initialization!", error);
         return false;
     }
 
-    mMinCapability = gfxPrefs::WebGLMinCapabilityMode();
-    mDisableExtensions = gfxPrefs::WebGLDisableExtensions();
-    mLoseContextOnMemoryPressure = gfxPrefs::WebGLLoseContextOnMemoryPressure();
-    mCanLoseContextInForeground = gfxPrefs::WebGLCanLoseContextInForeground();
-    mRestoreWhenVisible = gfxPrefs::WebGLRestoreWhenVisible();
+    mMinCapability = Preferences::GetBool("webgl.min_capability_mode", false);
+    mDisableExtensions = Preferences::GetBool("webgl.disable-extensions", false);
+    mLoseContextOnMemoryPressure = Preferences::GetBool("webgl.lose-context-on-memory-pressure", false);
+    mCanLoseContextInForeground = Preferences::GetBool("webgl.can-lose-context-in-foreground", true);
+    mRestoreWhenVisible = Preferences::GetBool("webgl.restore-context-when-visible", true);
 
     if (MinCapabilityMode())
         mDisableFragHighP = true;
 
     // These are the default values, see 6.2 State tables in the
     // OpenGL ES 2.0.25 spec.
     mColorWriteMask[0] = 1;
     mColorWriteMask[1] = 1;
@@ -1874,17 +1873,20 @@ WebGLContext::InitAndValidateGL()
         // The Mac ATI driver, in all known OSX version up to and including
         // 10.8, renders points sprites upside-down. (Apple bug 11778921)
         gl->fPointParameterf(LOCAL_GL_POINT_SPRITE_COORD_ORIGIN,
                              LOCAL_GL_LOWER_LEFT);
     }
 #endif
 
     // Check the shader validator pref
-    mBypassShaderValidation = gfxPrefs::WebGLBypassShaderValidator();
+    NS_ENSURE_TRUE(Preferences::GetRootBranch(), false);
+
+    mBypassShaderValidation = Preferences::GetBool("webgl.bypass-shader-validation",
+                                                   mBypassShaderValidation);
 
     // initialize shader translator
     if (!ShInitialize()) {
         GenerateWarning("GLSL translator initialization failed!");
         return false;
     }
 
     // Mesa can only be detected with the GL_VERSION string, of the form
@@ -1930,16 +1932,19 @@ WebGLContext::InitAndValidateGL()
     // vertex array object (the name zero) is also deprecated. [...]"
 
     if (gl->IsCoreProfile()) {
         MakeContextCurrent();
         mDefaultVertexArray->GenVertexArray();
         mDefaultVertexArray->BindVertexArray();
     }
 
+    if (mLoseContextOnMemoryPressure)
+        mContextObserver->RegisterMemoryPressureEvent();
+
     return true;
 }
 
 bool
 WebGLContext::ValidateFramebufferTarget(GLenum target,
                                         const char* const info)
 {
     bool isValid = true;
--- a/dom/canvas/WebGLMemoryTracker.cpp
+++ b/dom/canvas/WebGLMemoryTracker.cpp
@@ -11,16 +11,18 @@
 #include "WebGLProgram.h"
 #include "WebGLRenderbuffer.h"
 #include "WebGLShader.h"
 #include "WebGLTexture.h"
 #include "WebGLUniformLocation.h"
 
 namespace mozilla {
 
+NS_IMPL_ISUPPORTS(WebGLObserver, nsIObserver)
+
 NS_IMETHODIMP
 WebGLMemoryTracker::CollectReports(nsIHandleReportCallback* handleReport,
                                    nsISupports* data, bool)
 {
 #define REPORT(_path, _kind, _units, _amount, _desc)                         \
     do {                                                                     \
       nsresult rv;                                                           \
       rv = handleReport->Callback(EmptyCString(), NS_LITERAL_CSTRING(_path), \
--- a/dom/canvas/WebGLShaderValidator.cpp
+++ b/dom/canvas/WebGLShaderValidator.cpp
@@ -1,17 +1,16 @@
 /* -*- 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 "WebGLShaderValidator.h"
 
 #include "angle/ShaderLang.h"
-#include "gfxPrefs.h"
 #include "GLContext.h"
 #include "mozilla/Preferences.h"
 #include "MurmurHash3.h"
 #include "nsPrintfCString.h"
 #include "nsTArray.h"
 #include <string>
 #include <vector>
 #include "WebGLContext.h"
@@ -39,17 +38,17 @@ ChooseValidatorCompileOptions(const ShBu
                   SH_OBJECT_CODE |
                   SH_LIMIT_CALL_STACK_DEPTH |
                   SH_INIT_GL_POSITION;
 
     if (resources.MaxExpressionComplexity > 0) {
         options |= SH_LIMIT_EXPRESSION_COMPLEXITY;
     }
 
-    if (gfxPrefs::WebGLAllANGLEOptions()) {
+    if (Preferences::GetBool("webgl.all-angle-options", false)) {
         return options |
                SH_VALIDATE_LOOP_INDEXING |
                SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX |
                SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX |
                SH_EMULATE_BUILT_IN_FUNCTIONS |
                SH_CLAMP_INDIRECT_ARRAY_BOUNDS |
                SH_UNFOLD_SHORT_CIRCUIT |
                SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS |
--- a/dom/canvas/moz.build
+++ b/dom/canvas/moz.build
@@ -23,37 +23,33 @@ EXPORTS.mozilla.ipc += [
     'DocumentRendererParent.h',
 ]
 
 EXPORTS.mozilla.dom += [
     'CanvasGradient.h',
     'CanvasPath.h',
     'CanvasPattern.h',
     'CanvasRenderingContext2D.h',
-    'CanvasRenderingContextHelper.h',
     'CanvasUtils.h',
     'ImageBitmap.h',
     'ImageBitmapSource.h',
     'ImageData.h',
-    'OffscreenCanvas.h',
     'TextMetrics.h',
     'WebGLVertexArrayObject.h',
 ]
 
 # Canvas 2D and common sources
 UNIFIED_SOURCES += [
     'CanvasImageCache.cpp',
     'CanvasRenderingContext2D.cpp',
-    'CanvasRenderingContextHelper.cpp',
     'CanvasUtils.cpp',
     'DocumentRendererChild.cpp',
     'DocumentRendererParent.cpp',
     'ImageBitmap.cpp',
     'ImageData.cpp',
-    'OffscreenCanvas.cpp',
 ]
 
 # WebGL Sources
 UNIFIED_SOURCES += [
     'MurmurHash3.cpp',
     'WebGL1Context.cpp',
     'WebGL1ContextBuffers.cpp',
     'WebGL1ContextUniforms.cpp',
@@ -149,17 +145,16 @@ LOCAL_INCLUDES += [
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '../workers',
     '/dom/base',
     '/dom/html',
     '/dom/svg',
-    '/dom/workers',
     '/dom/xul',
     '/gfx/gl',
     '/image',
     '/js/xpconnect/src',
     '/layout/generic',
     '/layout/style',
     '/layout/xul',
     '/media/libyuv/include',
--- a/dom/canvas/nsICanvasRenderingContextInternal.h
+++ b/dom/canvas/nsICanvasRenderingContextInternal.h
@@ -7,23 +7,22 @@
 #define nsICanvasRenderingContextInternal_h___
 
 #include "mozilla/gfx/2D.h"
 #include "nsISupports.h"
 #include "nsIInputStream.h"
 #include "nsIDocShell.h"
 #include "nsRefreshDriver.h"
 #include "mozilla/dom/HTMLCanvasElement.h"
-#include "mozilla/dom/OffscreenCanvas.h"
 #include "GraphicsFilter.h"
 #include "mozilla/RefPtr.h"
 
 #define NS_ICANVASRENDERINGCONTEXTINTERNAL_IID \
-{ 0xb84f2fed, 0x9d4b, 0x430b, \
-  { 0xbd, 0xfb, 0x85, 0x57, 0x8a, 0xc2, 0xb4, 0x4b } }
+{ 0x3cc9e801, 0x1806, 0x4ff6, \
+  { 0x86, 0x14, 0xf9, 0xd0, 0xf4, 0xfb, 0x3b, 0x08 } }
 
 class gfxASurface;
 class nsDisplayListBuilder;
 
 namespace mozilla {
 namespace layers {
 class CanvasLayer;
 class LayerManager;
@@ -76,21 +75,16 @@ public:
     mRefreshDriver->AddPostRefreshObserver(this);
   }
 
   mozilla::dom::HTMLCanvasElement* GetParentObject() const
   {
     return mCanvasElement;
   }
 
-  void SetOffscreenCanvas(mozilla::dom::OffscreenCanvas* aOffscreenCanvas)
-  {
-    mOffscreenCanvas = aOffscreenCanvas;
-  }
-
 #ifdef DEBUG
     // Useful for testing
     virtual int32_t GetWidth() const = 0;
     virtual int32_t GetHeight() const = 0;
 #endif
 
   // Sets the dimensions of the canvas, in pixels.  Called
   // whenever the size of the element changes.
@@ -155,32 +149,27 @@ public:
   NS_IMETHOD SetContextOptions(JSContext* cx, JS::Handle<JS::Value> options) { return NS_OK; }
 
   // return true and fills in the bounding rect if elementis a child and has a hit region.
   virtual bool GetHitRegionRect(mozilla::dom::Element* element, nsRect& rect) { return false; }
 
   // Given a point, return hit region ID if it exists or an empty string if it doesn't
   virtual nsString GetHitRegion(const mozilla::gfx::Point& point) { return nsString(); }
 
-  virtual void OnVisibilityChange() {}
-
-  virtual void OnMemoryPressure() {}
-
   //
   // shmem support
   //
 
   // If this context can be set to use Mozilla's Shmem segments as its backing
   // store, this will set it to that state. Note that if you have drawn
   // anything into this canvas before changing the shmem state, it will be
   // lost.
   NS_IMETHOD SetIsIPC(bool isIPC) = 0;
 
 protected:
   nsRefPtr<mozilla::dom::HTMLCanvasElement> mCanvasElement;
-  nsRefPtr<mozilla::dom::OffscreenCanvas> mOffscreenCanvas;
   nsRefPtr<nsRefreshDriver> mRefreshDriver;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsICanvasRenderingContextInternal,
                               NS_ICANVASRENDERINGCONTEXTINTERNAL_IID)
 
 #endif /* nsICanvasRenderingContextInternal_h___ */
--- a/dom/canvas/test/mochitest.ini
+++ b/dom/canvas/test/mochitest.ini
@@ -22,20 +22,16 @@ support-files =
   image_rrgg-256x256.png
   image_transparent.png
   image_transparent50.png
   image_yellow.png
   image_yellow75.png
   imagebitmap_on_worker.js
   imagebitmap_structuredclone.js
   imagebitmap_structuredclone_iframe.html
-  offscreencanvas.js
-  offscreencanvas_mask.svg
-  offscreencanvas_neuter.js
-  offscreencanvas_serviceworker_inner.html
 
 [test_2d.clearRect.image.offscreen.html]
 [test_2d.clip.winding.html]
 [test_2d.composite.canvas.color-burn.html]
 skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
 [test_2d.composite.canvas.color-dodge.html]
 skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 913662
 [test_2d.composite.canvas.color.html]
@@ -260,27 +256,8 @@ skip-if = buildapp == 'mulet' || (builda
 [test_toDataURL_parameters.html]
 [test_windingRuleUndefined.html]
 [test_2d.fillText.gradient.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # bug 1040965
 [test_2d_composite_canvaspattern_setTransform.html]
 [test_createPattern_broken.html]
 [test_setlinedash.html]
 [test_filter.html]
-[test_offscreencanvas_basic_webgl.html]
-tags = offscreencanvas
-[test_offscreencanvas_dynamic_fallback.html]
-tags = offscreencanvas
-[test_offscreencanvas_sharedworker.html]
-tags = offscreencanvas
-[test_offscreencanvas_serviceworker.html]
-tags = offscreencanvas
-skip-if = buildapp == 'b2g'
-[test_offscreencanvas_neuter.html]
-tags = offscreencanvas
-[test_offscreencanvas_many.html]
-tags = offscreencanvas
-skip-if = (toolkit == 'android' || toolkit == 'gonk' || toolkit == 'windows' || toolkit == 'gtk2' || toolkit == 'gtk3')
-[test_offscreencanvas_sizechange.html]
-tags = offscreencanvas
-[test_offscreencanvas_subworker.html]
-tags = offscreencanvas
-skip-if = (toolkit == 'android' || toolkit == 'gonk' || toolkit == 'windows' || toolkit == 'gtk2' || toolkit == 'gtk3')
deleted file mode 100644
--- a/dom/canvas/test/offscreencanvas.js
+++ /dev/null
@@ -1,299 +0,0 @@
-/* WebWorker for test_offscreencanvas_*.html */
-var port = null;
-
-function ok(expect, msg) {
-  if (port) {
-    port.postMessage({type: "test", result: !!expect, name: msg});
-  } else {
-    postMessage({type: "test", result: !!expect, name: msg});
-  }
-}
-
-function finish() {
-  if (port) {
-    port.postMessage({type: "finish"});
-  } else {
-    postMessage({type: "finish"});
-  }
-}
-
-function drawCount(count) {
-  if (port) {
-    port.postMessage({type: "draw", count: count});
-  } else {
-    postMessage({type: "draw", count: count});
-  }
-}
-
-//--------------------------------------------------------------------
-// WebGL Drawing Functions
-//--------------------------------------------------------------------
-function createDrawFunc(canvas) {
-  var gl;
-
-  try {
-    gl = canvas.getContext("experimental-webgl");
-  } catch (e) {}
-
-  if (!gl) {
-    ok(false, "WebGL is unavailable");
-    return null;
-  }
-
-  var vertSrc = "attribute vec2 position; \
-                 void main(void) { \
-                   gl_Position = vec4(position, 0.0, 1.0); \
-                 }";
-
-  var fragSrc = "precision mediump float; \
-                 void main(void) { \
-                   gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); \
-                 }";
-
-  // Returns a valid shader, or null on errors.
-  var createShader = function(src, t) {
-    var shader = gl.createShader(t);
-
-    gl.shaderSource(shader, src);
-    gl.compileShader(shader);
-
-    return shader;
-  };
-
-  var createProgram = function(vsSrc, fsSrc) {
-    var vs = createShader(vsSrc, gl.VERTEX_SHADER);
-    var fs = createShader(fsSrc, gl.FRAGMENT_SHADER);
-
-    var prog = gl.createProgram();
-    gl.attachShader(prog, vs);
-    gl.attachShader(prog, fs);
-    gl.linkProgram(prog);
-
-    if (!gl.getProgramParameter(prog, gl.LINK_STATUS)) {
-      var str = "Shader program linking failed:";
-      str += "\nShader program info log:\n" + gl.getProgramInfoLog(prog);
-      str += "\n\nVert shader log:\n" + gl.getShaderInfoLog(vs);
-      str += "\n\nFrag shader log:\n" + gl.getShaderInfoLog(fs);
-      console.log(str);
-      ok(false, "Shader program linking failed");
-      return null;
-    }
-
-    return prog;
-  };
-
-  gl.disable(gl.DEPTH_TEST);
-
-  var program = createProgram(vertSrc, fragSrc);
-  ok(program, "Creating shader program");
-
-  program.positionAttr = gl.getAttribLocation(program, "position");
-  ok(program.positionAttr >= 0, "position attribute should be valid");
-
-  var vertCoordArr = new Float32Array([
-    -1, -1,
-     1, -1,
-    -1,  1,
-     1,  1,
-  ]);
-  var vertCoordBuff = gl.createBuffer();
-  gl.bindBuffer(gl.ARRAY_BUFFER, vertCoordBuff);
-  gl.bufferData(gl.ARRAY_BUFFER, vertCoordArr, gl.STATIC_DRAW);
-
-  var checkGLError = function(prefix, refValue) {
-    if (!refValue) {
-      refValue = 0;
-    }
-
-    var error = gl.getError();
-    ok(error == refValue,
-         prefix + 'gl.getError should be 0x' + refValue.toString(16) +
-         ', was 0x' + error.toString(16) + '.');
-  };
-
-  var testPixel = function(x, y, refData, infoString) {
-    var pixel = new Uint8Array(4);
-    gl.readPixels(x, y, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
-
-    var pixelMatches = pixel[0] == refData[0] &&
-                       pixel[1] == refData[1] &&
-                       pixel[2] == refData[2] &&
-                       pixel[3] == refData[3];
-    ok(pixelMatches, infoString);
-  };
-
-  var preDraw = function(prefix) {
-    gl.clearColor(1.0, 0.0, 0.0, 1.0);
-    gl.clear(gl.COLOR_BUFFER_BIT);
-
-    testPixel(0, 0, [255, 0, 0, 255], prefix + 'Should be red before drawing.');
-  };
-
-  var postDraw = function(prefix) {
-    testPixel(0, 0, [0, 255, 0, 255], prefix + 'Should be green after drawing.');
-  };
-
-  gl.useProgram(program);
-  gl.enableVertexAttribArray(program.position);
-  gl.vertexAttribPointer(program.position, 2, gl.FLOAT, false, 0, 0);
-
-  // Start drawing
-  checkGLError('after setup');
-
-  return function(prefix) {
-    if (prefix) {
-      prefix = "[" + prefix + "] ";
-    } else {
-      prefix = "";
-    }
-
-    gl.viewport(0, 0, canvas.width, canvas.height);
-
-    preDraw(prefix);
-    gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
-    postDraw(prefix);
-    gl.commit();
-    checkGLError(prefix);
-  };
-}
-
-/* entry point */
-function entryFunction(testStr, subtests, offscreenCanvas) {
-  var test = testStr;
-  var canvas = offscreenCanvas;
-
-  if (test != "subworker") {
-    ok(canvas, "Canvas successfully transfered to worker");
-    ok(canvas.getContext, "Canvas has getContext");
-
-    ok(canvas.width == 64, "OffscreenCanvas width should be 64");
-    ok(canvas.height == 64, "OffscreenCanvas height should be 64");
-  }
-
-  var draw;
-
-  //------------------------------------------------------------------------
-  // Basic WebGL test
-  //------------------------------------------------------------------------
-  if (test == "webgl") {
-    draw = createDrawFunc(canvas);
-    if (!draw) {
-      finish();
-      return;
-    }
-
-    var count = 0;
-    var iid = setInterval(function() {
-      if (count++ > 20) {
-        clearInterval(iid);
-        ok(true, "Worker is done");
-        finish();
-        return;
-      }
-      draw("loop " +count);
-    }, 0);
-  }
-  //------------------------------------------------------------------------
-  // Test dynamic fallback
-  //------------------------------------------------------------------------
-  else if (test == "webgl_fallback") {
-    draw = createDrawFunc(canvas);
-    if (!draw) {
-      return;
-    }
-
-    var count = 0;
-    var iid = setInterval(function() {
-      ++count;
-      draw("loop " + count);
-      drawCount(count);
-    }, 0);
-  }
-  //------------------------------------------------------------------------
-  // Canvas Size Change from Worker
-  //------------------------------------------------------------------------
-  else if (test == "webgl_changesize") {
-    draw = createDrawFunc(canvas);
-    if (!draw) {
-      finish();
-      return;
-    }
-
-    draw("64x64");
-
-    setTimeout(function() {
-      canvas.width = 128;
-      canvas.height = 128;
-      draw("Increased to 128x128");
-
-      setTimeout(function() {
-        canvas.width = 32;
-        canvas.width = 32;
-        draw("Decreased to 32x32");
-
-        setTimeout(function() {
-          canvas.width = 64;
-          canvas.height = 64;
-          draw("Increased to 64x64");
-
-          ok(true, "Worker is done");
-          finish();
-        }, 0);
-      }, 0);
-    }, 0);
-  }
-  //------------------------------------------------------------------------
-  // Using OffscreenCanvas from sub workers
-  //------------------------------------------------------------------------
-  else if (test == "subworker") {
-    /* subworker tests take a list of tests to run on children */
-    var stillRunning = 0;
-    subtests.forEach(function (subtest) {
-      ++stillRunning;
-      var subworker = new Worker('offscreencanvas.js');
-      subworker.onmessage = function(evt) {
-        /* report finish to parent when all children are finished */
-        if (evt.data.type == "finish") {
-          subworker.terminate();
-          if (--stillRunning == 0) {
-            ok(true, "Worker is done");
-            finish();
-          }
-          return;
-        }
-        /* relay all other messages to parent */
-        postMessage(evt.data);
-      };
-
-      var findTransferables = function(t) {
-        if (t.test == "subworker") {
-          var result = [];
-          t.subtests.forEach(function(test) {
-            result = result.concat(findTransferables(test));
-          });
-
-          return result;
-        } else {
-          return [t.canvas];
-        }
-      };
-
-      subworker.postMessage(subtest, findTransferables(subtest));
-    });
-  }
-};
-
-onmessage = function(evt) {
-  port = evt.ports[0];
-  entryFunction(evt.data.test, evt.data.subtests, evt.data.canvas);
-};
-
-onconnect = function(evt) {
-  port = evt.ports[0];
-
-  port.addEventListener('message', function(evt) {
-    entryFunction(evt.data.test, evt.data.subtests, evt.data.canvas);
-  });
-
-  port.start();
-};
deleted file mode 100644
--- a/dom/canvas/test/offscreencanvas_mask.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
-  <mask id="fade_mask_both" maskUnits="objectBoundingBox" maskContentUnits="objectBoundingBox">
-    <linearGradient id="fade_gradient_both" gradientUnits="objectBoundingBox" x2="0" y2="1">
-      <stop stop-color="white" stop-opacity="0" offset="0"></stop>
-      <stop stop-color="white" stop-opacity="1" offset="0.2"></stop>
-      <stop stop-color="white" stop-opacity="1" offset="0.8"></stop>
-      <stop stop-color="white" stop-opacity="0" offset="1"></stop>
-    </linearGradient>
-    <rect x="0" y="0" width="1" height="1" fill="url(#fade_gradient_both)"></rect>
-  </mask>
-</svg>
deleted file mode 100644
--- a/dom/canvas/test/offscreencanvas_neuter.js
+++ /dev/null
@@ -1,1 +0,0 @@
-/* empty worker for test_offscreencanvas_disable.html */
deleted file mode 100644
--- a/dom/canvas/test/offscreencanvas_serviceworker_inner.html
+++ /dev/null
@@ -1,32 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-<title>WebGL in OffscreenCanvas</title>
-</head>
-<body>
-<canvas id="c" width="64" height="64"></canvas>
-<script>
-function ok(expect, msg) {
-  parent.postMessage({type: "test", result: !!expect, name: msg}, "*");
-}
-
-var htmlCanvas = document.getElementById("c");
-
-ok(htmlCanvas, "Should have HTML canvas element");
-
-var messageChannel = new MessageChannel();
-messageChannel.port1.onmessage = function(evt) {
-  parent.postMessage(evt.data, "*");
-}
-
-ok(htmlCanvas.transferControlToOffscreen, "HTMLCanvasElement has transferControlToOffscreen function");
-
-var offscreenCanvas = htmlCanvas.transferControlToOffscreen();
-ok(offscreenCanvas, "Expected transferControlToOffscreen to succeed");
-
-navigator.serviceWorker.ready.then(function() {
-  navigator.serviceWorker.controller.postMessage({test: 'webgl', canvas: offscreenCanvas}, [offscreenCanvas, messageChannel.port2]);
-});
-</script>
-</body>
-</html>
deleted file mode 100644
--- a/dom/canvas/test/test_offscreencanvas_basic_webgl.html
+++ /dev/null
@@ -1,62 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-<title>WebGL in OffscreenCanvas</title>
-<script src="/tests/SimpleTest/SimpleTest.js"></script>
-<link rel="stylesheet" href="/tests/SimpleTest/test.css">
-</head>
-<body>
-<canvas id="c" width="64" height="64"></canvas>
-<canvas id="c-ref" width="64" height="64"></canvas>
-<script>
-
-SimpleTest.waitForExplicitFinish();
-
-function testToDataURL() {
-  // testing toDataURL
-  // Fill c-ref with green color.
-  var c = document.getElementById("c-ref");
-  var ctx = c.getContext("2d");
-  ctx.rect(0, 0, 64, 64);
-  ctx.fillStyle = "#00FF00";
-  ctx.fill();
-  var htmlCanvas = document.getElementById("c");
-  ok(c.toDataURL() == htmlCanvas.toDataURL(), "toDataURL should return a 64x64 green square");
-}
-
-function runTest() {
-
-  var htmlCanvas = document.getElementById("c");
-  var worker = new Worker("offscreencanvas.js");
-
-  ok(htmlCanvas, "Should have HTML canvas element");
-  ok(worker, "Web worker successfully created");
-
-  worker.onmessage = function(evt) {
-    var msg = evt.data || {};
-    if (msg.type == "test") {
-      ok(msg.result, msg.name);
-    }
-    if (msg.type == "finish") {
-      testToDataURL();
-      worker.terminate();
-      SimpleTest.finish();
-    }
-  }
-
-  ok(htmlCanvas.transferControlToOffscreen, "HTMLCanvasElement has transferControlToOffscreen function");
-
-  var offscreenCanvas = htmlCanvas.transferControlToOffscreen();
-  ok(offscreenCanvas, "Expected transferControlToOffscreen to succeed");
-
-  worker.postMessage({test: 'webgl', canvas: offscreenCanvas}, [offscreenCanvas]);
-}
-
-SpecialPowers.pushPrefEnv({'set': [
-  ['gfx.offscreencanvas.enabled', true],
-  ['webgl.force-enabled', true],
-]}, runTest);
-
-</script>
-</body>
-</html>
deleted file mode 100644
--- a/dom/canvas/test/test_offscreencanvas_dynamic_fallback.html
+++ /dev/null
@@ -1,80 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-<title>WebGL in OffscreenCanvas</title>
-<script src="/tests/SimpleTest/SimpleTest.js"></script>
-<script src="/tests/SimpleTest/WindowSnapshot.js"></script>
-<link rel="stylesheet" href="/tests/SimpleTest/test.css">
-</head>
-<body>
-<script>
-
-SimpleTest.waitForExplicitFinish();
-
-function createCanvas(initWithMask) {
-  var canvas = document.createElement("canvas");
-  canvas.width = 64;
-  canvas.height = 64;
-  document.body.appendChild(canvas);
-  if (initWithMask) {
-    canvas.style.mask = "url('offscreencanvas_mask.svg#fade_mask_both')";
-  }
-
-  return canvas;
-}
-
-function getRefSnapshot(initWithMask) {
-  var refCanvas = createCanvas(!initWithMask);
-  var ctx = refCanvas.getContext("2d");
-  ctx.rect(0, 0, 64, 64);
-  ctx.fillStyle = "#00FF00";
-  ctx.fill();
-  var result = snapshotWindow(window);
-  document.body.removeChild(refCanvas);
-  return result;
-}
-
-function runTest(initWithMask) {
-  var htmlCanvas = createCanvas(initWithMask);
-  var worker = new Worker("offscreencanvas.js");
-
-  worker.onmessage = function(evt) {
-    var msg = evt.data || {};
-    if (msg.type == "draw") {
-      if (msg.count === 10) {
-        // Change the fallback state dynamically when drawing count reaches 10.
-        if (initWithMask) {
-          htmlCanvas.style.mask = "";
-        } else {
-          htmlCanvas.style.mask = "url('offscreencanvas_mask.svg#fade_mask_both')";
-        }
-      } else if (msg.count === 20) {
-        var snapshotFallback = snapshotWindow(window);
-        worker.terminate();
-        document.body.removeChild(htmlCanvas);
-
-        var results = compareSnapshots(snapshotFallback, getRefSnapshot(initWithMask), true);
-        ok(results[0], "after dynamic fallback, screenshots should be the same");
-
-        if (initWithMask) {
-          SimpleTest.finish();
-        } else {
-          runTest(true);
-        }
-      }
-    }
-  }
-
-  var offscreenCanvas = htmlCanvas.transferControlToOffscreen();
-
-  worker.postMessage({test: 'webgl_fallback', canvas: offscreenCanvas}, [offscreenCanvas]);
-}
-
-SpecialPowers.pushPrefEnv({'set': [
-  ['gfx.offscreencanvas.enabled', true],
-  ['webgl.force-enabled', true],
-]}, runTest.bind(false));
-
-</script>
-</body>
-</html>
deleted file mode 100644
--- a/dom/canvas/test/test_offscreencanvas_many.html
+++ /dev/null
@@ -1,67 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-<title>WebGL in OffscreenCanvas</title>
-<script src="/tests/SimpleTest/SimpleTest.js"></script>
-<link rel="stylesheet" href="/tests/SimpleTest/test.css">
-</head>
-<body>
-<!--
-  This test needs several workers run offscreen canvas simultaneously.
-  So we choose 8 workers, 4 of them run basic webgl drawing test and
-  others run size changing test.
--->
-<script>
-
-SimpleTest.waitForExplicitFinish();
-
-function createCanvas() {
-  var htmlCanvas = document.createElement('canvas');
-  htmlCanvas.width = 64;
-  htmlCanvas.height = 64;
-  document.body.appendChild(htmlCanvas);
-  return htmlCanvas;
-}
-
-function runTest() {
-  var stillRunning = 0;
-
-  var startWorker = function(canvas, test) {
-    stillRunning++;
-    var worker = new Worker("offscreencanvas.js");
-
-    worker.onmessage = function(evt) {
-      var msg = evt.data || {};
-      if (msg.type == "test") {
-        ok(msg.result, msg.name);
-      }
-      if (msg.type == "finish") {
-        worker.terminate();
-        if (--stillRunning == 0)
-          SimpleTest.finish();
-      }
-    }
-
-    var offscreenCanvas = canvas.transferControlToOffscreen();
-    worker.postMessage({test: test, canvas: offscreenCanvas}, [offscreenCanvas]);
-  }
-
-  /* create 4 workers that do the regular drawing test and 4 workers
-     that do the size change test */
-  for (var i = 0; i < 4; i++) {
-    startWorker(createCanvas(), 'webgl');
-  }
-
-  for (var i = 0; i < 4; i++) {
-    startWorker(createCanvas(), 'webgl_changesize');
-  }
-}
-
-SpecialPowers.pushPrefEnv({'set': [
-  ['gfx.offscreencanvas.enabled', true],
-  ['webgl.force-enabled', true]
-]}, runTest);
-
-</script>
-</body>
-</html>
deleted file mode 100644
--- a/dom/canvas/test/test_offscreencanvas_neuter.html
+++ /dev/null
@@ -1,78 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-<title>OffscreenCanvas: Test neutering</title>
-<script src="/tests/SimpleTest/SimpleTest.js"></script>
-<link rel="stylesheet" href="/tests/SimpleTest/test.css">
-</head>
-<body>
-<canvas id="c" width="64" height="64"></canvas>
-<script>
-
-SimpleTest.waitForExplicitFinish();
-
-function runTest() {
-
-  var htmlCanvas = document.getElementById("c");
-  var worker = new Worker("offscreencanvas_neuter.js");
-
-  ok(htmlCanvas, "Should have HTML canvas element");
-  ok(worker, "Web worker successfully created");
-
-  ok(htmlCanvas.transferControlToOffscreen, "HTMLCanvasElement has transferControlToOffscreen function");
-
-  var offscreenCanvas = htmlCanvas.transferControlToOffscreen();
-  ok(offscreenCanvas, "Expected transferControlToOffscreen to succeed");
-
-  /* check html canvas is neuterd */
-  is(htmlCanvas.width, 64, "HTML canvas has correct width");
-  SimpleTest.doesThrow(
-    function() { htmlCanvas.width = 128; },
-    "Can't change html canvas' width after transferControlToOffscreen");
-
-  SimpleTest.doesThrow(
-    function() { htmlCanvas.height = 128; },
-    "Can't change html canvas' height after transferControlToOffscreen");
-
-  ok(!htmlCanvas.getContext("2d"), "Can't getContext after transferControlToOffscreen");
-  ok(!htmlCanvas.getContext("webgl"), "Can't getContext after transferControlToOffscreen");
-  ok(!htmlCanvas.getContext("webgl2"), "Can't getContext after transferControlToOffscreen");
-
-  worker.postMessage(offscreenCanvas, [offscreenCanvas]);
-
-  /* check parent offscreencanvas is neutered after being transfered */
-  SimpleTest.doesThrow(
-    function() { offscreenCanvas.width = 128; },
-    "Can't change transfered worker canvas width");
-
-  SimpleTest.doesThrow(
-    function() { offscreenCanvas.height = 128; },
-    "Can't change transfered worker canvas height");
-
-  SimpleTest.doesThrow(
-    function() { offscreenCanvas.getContext("2d") },
-    "Can't getContext on transfered worker canvas");
-
-  SimpleTest.doesThrow(
-    function() { offscreenCanvas.getContext("webgl") },
-    "Can't getContext on transfered worker canvas");
-
-  SimpleTest.doesThrow(
-    function() { offscreenCanvas.getContext("webgl2") },
-    "Can't getContext on transfered worker canvas");
-
-  // Transfer a neutered offscreencanvas should be ok.
-  worker.postMessage(offscreenCanvas, [offscreenCanvas]);
-
-  worker.terminate();
-  SimpleTest.finish();
-}
-
-SpecialPowers.pushPrefEnv({'set': [
-  ['gfx.offscreencanvas.enabled', true],
-  ['webgl.force-enabled', true],
-]}, runTest);
-
-</script>
-</body>
-</html>
deleted file mode 100644
--- a/dom/canvas/test/test_offscreencanvas_serviceworker.html
+++ /dev/null
@@ -1,46 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-<title>WebGL in OffscreenCanvas</title>
-<script src="/tests/SimpleTest/SimpleTest.js"></script>
-<link rel="stylesheet" href="/tests/SimpleTest/test.css">
-</head>
-<body>
-<script>
-
-SimpleTest.waitForExplicitFinish();
-
-function runTest() {
-  window.onmessage = function(evt) {
-    var msg = evt.data || {};
-    if (msg.type == "test") {
-      ok(msg.result, msg.name);
-    }
-    if (msg.type == "finish") {
-      SimpleTest.finish();
-    }
-  }
-
-  navigator.serviceWorker.register('offscreencanvas.js', { scope: "."})
-    // Wait until the service worker is active.
-    .then(navigator.serviceWorker.ready)
-    // ...and then show the interface for the commands once it's ready.
-    .then(function() {
-      iframe = document.createElement("iframe");
-      iframe.setAttribute('src', "offscreencanvas_serviceworker_inner.html");
-      document.body.appendChild(iframe);
-    })
-}
-
-SpecialPowers.pushPrefEnv({'set': [
-  ['gfx.offscreencanvas.enabled', true],
-  ['webgl.force-enabled', true],
-  ["dom.serviceWorkers.exemptFromPerDomainMax", true],
-  ["dom.serviceWorkers.interception.enabled", true],
-  ["dom.serviceWorkers.enabled", true],
-  ["dom.serviceWorkers.testing.enabled", true]
-]}, runTest);
-
-</script>
-</body>
-</html>
deleted file mode 100644
--- a/dom/canvas/test/test_offscreencanvas_sharedworker.html
+++ /dev/null
@@ -1,47 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-<title>WebGL in OffscreenCanvas</title>
-<script src="/tests/SimpleTest/SimpleTest.js"></script>
-<link rel="stylesheet" href="/tests/SimpleTest/test.css">
-</head>
-<body>
-<canvas id="c" width="64" height="64"></canvas>
-<script>
-
-SimpleTest.waitForExplicitFinish();
-
-function runTest() {
-
-  var htmlCanvas = document.getElementById("c");
-  var worker = new SharedWorker("offscreencanvas.js");
-
-  ok(htmlCanvas, "Should have HTML canvas element");
-  ok(worker, "Web worker successfully created");
-
-  ok(htmlCanvas.transferControlToOffscreen, "HTMLCanvasElement has transferControlToOffscreen function");
-
-  var offscreenCanvas = htmlCanvas.transferControlToOffscreen();
-  ok(offscreenCanvas, "Expected transferControlToOffscreen to succeed");
-
-  worker.port.start();
-
-  // We don't support transferring OffscreenCanvas via shared worker.
-  SimpleTest.doesThrow(
-    function() {
-      worker.port.postMessage({test: 'webgl', canvas: offscreenCanvas}, [offscreenCanvas]);
-    },
-    "OffscreenCanvas cannot transfer to shared worker"
-  );
-
-  SimpleTest.finish();
-}
-
-SpecialPowers.pushPrefEnv({'set': [
-  ['gfx.offscreencanvas.enabled', true],
-  ['webgl.force-enabled', true],
-]}, runTest);
-
-</script>
-</body>
-</html>
deleted file mode 100644
--- a/dom/canvas/test/test_offscreencanvas_sizechange.html
+++ /dev/null
@@ -1,41 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-<title>WebGL in OffscreenCanvas</title>
-<script src="/tests/SimpleTest/SimpleTest.js"></script>
-<link rel="stylesheet" href="/tests/SimpleTest/test.css">
-</head>
-<body>
-<canvas id="c" width="64" height="64"></canvas>
-<script>
-
-SimpleTest.waitForExplicitFinish();
-
-function runTest() {
-
-  var htmlCanvas = document.getElementById("c");
-  var worker = new Worker("offscreencanvas.js");
-
-  worker.onmessage = function(evt) {
-    var msg = evt.data || {};
-    if (msg.type == "test") {
-      ok(msg.result, msg.name);
-    }
-    if (msg.type == "finish") {
-      worker.terminate();
-      SimpleTest.finish();
-    }
-  }
-
-  var offscreenCanvas = htmlCanvas.transferControlToOffscreen();
-  worker.postMessage({test: 'webgl_changesize', canvas: offscreenCanvas}, [offscreenCanvas]);
-}
-
-SpecialPowers.pushPrefEnv({'set': [
-  ['gfx.offscreencanvas.enabled', true],
-  ['webgl.force-enabled', true],
-]}, runTest);
-
-</script>
-</body>
-</html>
deleted file mode 100644
--- a/dom/canvas/test/test_offscreencanvas_subworker.html
+++ /dev/null
@@ -1,90 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-<title>OffscreenCanvas: Test subworkers</title>
-<script src="/tests/SimpleTest/SimpleTest.js"></script>
-<link rel="stylesheet" href="/tests/SimpleTest/test.css">
-</head>
-<body>
-<!--
-  We want to test offscreen canvas works well when it running on worker
-  and nested worker simultaneously. So we create 10 canvas and dispatch
-  it to different workers and sub-workers.
--->
-<script>
-
-SimpleTest.waitForExplicitFinish();
-
-function createCanvas() {
-  var htmlCanvas = document.createElement('canvas');
-  htmlCanvas.width = 64;
-  htmlCanvas.height = 64;
-  document.body.appendChild(htmlCanvas);
-  return htmlCanvas.transferControlToOffscreen();
-}
-
-function runTest() {
-
-  var worker = new Worker("offscreencanvas.js");
-
-  worker.onmessage = function(evt) {
-    var msg = evt.data || {};
-    if (msg.type == "test") {
-      ok(msg.result, msg.name);
-    }
-    if (msg.type == "finish") {
-      worker.terminate();
-      SimpleTest.finish();
-    }
-  }
-
-  var findTransferables = function(t) {
-    if (t.test == "subworker") {
-      var result = [];
-      t.subtests.forEach(function(test) {
-        result = result.concat(findTransferables(test));
-      });
-
-      return result;
-    } else {
-      return [t.canvas];
-    }
-  };
-
-  var testData =
-    {test: 'subworker', subtests: [
-      {test: 'webgl', canvas: createCanvas()},
-      {test: 'subworker', subtests: [
-        {test: 'webgl', canvas: createCanvas()},
-        {test: 'webgl_changesize', canvas: createCanvas()},
-        {test: 'webgl', canvas: createCanvas()}
-      ]},
-      {test: 'subworker', subtests: [
-        {test: 'webgl', canvas: createCanvas()},
-        {test: 'webgl_changesize', canvas: createCanvas()},
-        {test: 'subworker', subtests: [
-          {test: 'webgl_changesize', canvas: createCanvas()},
-          {test: 'webgl', canvas: createCanvas()}
-        ]},
-        {test: 'subworker', subtests: [
-          {test: 'webgl_changesize', canvas: createCanvas()},
-          {test: 'subworker', subtests: [
-            {test: 'subworker', subtests: [
-              {test: 'webgl_changesize', canvas: createCanvas()}
-            ]}
-          ]}
-        ]},
-      ]}
-    ]};
-
-  worker.postMessage(testData, findTransferables(testData));
-}
-
-SpecialPowers.pushPrefEnv({'set': [
-  ['gfx.offscreencanvas.enabled', true],
-  ['webgl.force-enabled', true],
-]}, runTest);
-
-</script>
-</body>
-</html>
--- a/dom/html/HTMLCanvasElement.cpp
+++ b/dom/html/HTMLCanvasElement.cpp
@@ -14,20 +14,18 @@
 #include "mozilla/Assertions.h"
 #include "mozilla/Base64.h"
 #include "mozilla/CheckedInt.h"
 #include "mozilla/dom/CanvasCaptureMediaStream.h"
 #include "mozilla/dom/CanvasRenderingContext2D.h"
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/HTMLCanvasElementBinding.h"
 #include "mozilla/dom/MouseEvent.h"
-#include "mozilla/dom/OffscreenCanvas.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/gfx/Rect.h"
-#include "mozilla/layers/AsyncCanvasRenderer.h"
 #include "mozilla/MouseEvents.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Telemetry.h"
 #include "nsAttrValueInlines.h"
 #include "nsContentUtils.h"
 #include "nsDisplayList.h"
 #include "nsDOMJSUtils.h"
 #include "nsIScriptSecurityManager.h"
@@ -236,145 +234,28 @@ HTMLCanvasPrintState::NotifyDone()
   mPendingNotify = false;
   if (mCallback) {
     mCallback->Notify(nullptr);
   }
 }
 
 // ---------------------------------------------------------------------------
 
-HTMLCanvasElementObserver::HTMLCanvasElementObserver(HTMLCanvasElement* aElement)
-    : mElement(aElement)
-{
-  RegisterVisibilityChangeEvent();
-  RegisterMemoryPressureEvent();
-}
-
-HTMLCanvasElementObserver::~HTMLCanvasElementObserver()
-{
-  Destroy();
-}
-
-void
-HTMLCanvasElementObserver::Destroy()
-{
-  UnregisterMemoryPressureEvent();
-  UnregisterVisibilityChangeEvent();
-  mElement = nullptr;
-}
-
-void
-HTMLCanvasElementObserver::RegisterVisibilityChangeEvent()
-{
-  if (!mElement) {
-    return;
-  }
-
-  nsIDocument* document = mElement->OwnerDoc();
-  document->AddSystemEventListener(NS_LITERAL_STRING("visibilitychange"),
-                                   this, true, false);
-}
-
-void
-HTMLCanvasElementObserver::UnregisterVisibilityChangeEvent()
-{
-  if (!mElement) {
-    return;
-  }
-
-  nsIDocument* document = mElement->OwnerDoc();
-  document->RemoveSystemEventListener(NS_LITERAL_STRING("visibilitychange"),
-                                      this, true);
-}
-
-void
-HTMLCanvasElementObserver::RegisterMemoryPressureEvent()
-{
-  if (!mElement) {
-    return;
-  }
-
-  nsCOMPtr<nsIObserverService> observerService =
-    mozilla::services::GetObserverService();
-
-  MOZ_ASSERT(observerService);
-
-  if (observerService)
-    observerService->AddObserver(this, "memory-pressure", false);
-}
-
-void
-HTMLCanvasElementObserver::UnregisterMemoryPressureEvent()
-{
-  if (!mElement) {
-    return;
-  }
-
-  nsCOMPtr<nsIObserverService> observerService =
-    mozilla::services::GetObserverService();
-
-  // Do not assert on observerService here. This might be triggered by
-  // the cycle collector at a late enough time, that XPCOM services are
-  // no longer available. See bug 1029504.
-  if (observerService)
-    observerService->RemoveObserver(this, "memory-pressure");
-}
-
-NS_IMETHODIMP
-HTMLCanvasElementObserver::Observe(nsISupports*, const char* aTopic, const char16_t*)
-{
-  if (!mElement || strcmp(aTopic, "memory-pressure")) {
-    return NS_OK;
-  }
-
-  mElement->OnMemoryPressure();
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-HTMLCanvasElementObserver::HandleEvent(nsIDOMEvent* aEvent)
-{
-  nsAutoString type;
-  aEvent->GetType(type);
-  if (!mElement || !type.EqualsLiteral("visibilitychange")) {
-    return NS_OK;
-  }
-
-  mElement->OnVisibilityChange();
-
-  return NS_OK;
-}
-
-NS_IMPL_ISUPPORTS(HTMLCanvasElementObserver, nsIObserver)
-
-// ---------------------------------------------------------------------------
-
 HTMLCanvasElement::HTMLCanvasElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
   : nsGenericHTMLElement(aNodeInfo),
-    mResetLayer(true) ,
     mWriteOnly(false)
 {
 }
 
 HTMLCanvasElement::~HTMLCanvasElement()
 {
-  if (mContextObserver) {
-    mContextObserver->Destroy();
-    mContextObserver = nullptr;
-  }
-
   ResetPrintCallback();
   if (mRequestedFrameRefreshObserver) {
     mRequestedFrameRefreshObserver->DetachFromRefreshDriver();
   }
-
-  if (mAsyncCanvasRenderer) {
-    mAsyncCanvasRenderer->mHTMLCanvasElement = nullptr;
-  }
 }
 
 NS_IMPL_CYCLE_COLLECTION_INHERITED(HTMLCanvasElement, nsGenericHTMLElement,
                                    mCurrentContext, mPrintCallback,
                                    mPrintState, mOriginalCanvas)
 
 NS_IMPL_ADDREF_INHERITED(HTMLCanvasElement, Element)
 NS_IMPL_RELEASE_INHERITED(HTMLCanvasElement, Element)
@@ -386,32 +267,16 @@ NS_INTERFACE_TABLE_TAIL_INHERITING(nsGen
 NS_IMPL_ELEMENT_CLONE(HTMLCanvasElement)
 
 /* virtual */ JSObject*
 HTMLCanvasElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return HTMLCanvasElementBinding::Wrap(aCx, this, aGivenProto);
 }
 
-already_AddRefed<nsICanvasRenderingContextInternal>
-HTMLCanvasElement::CreateContext(CanvasContextType aContextType)
-{
-  nsRefPtr<nsICanvasRenderingContextInternal> ret =
-    CanvasRenderingContextHelper::CreateContext(aContextType);
-
-  // Add Observer for webgl canvas.
-  if (aContextType == CanvasContextType::WebGL1 ||
-      aContextType == CanvasContextType::WebGL2) {
-    mContextObserver = new HTMLCanvasElementObserver(this);
-  }
-
-  ret->SetCanvasElement(this);
-  return ret.forget();
-}
-
 nsIntSize
 HTMLCanvasElement::GetWidthHeight()
 {
   nsIntSize size(DEFAULT_CANVAS_WIDTH, DEFAULT_CANVAS_HEIGHT);
   const nsAttrValue* value;
 
   if ((value = GetParsedAttr(nsGkAtoms::width)) &&
       value->Type() == nsAttrValue::eInteger)
@@ -686,21 +551,62 @@ nsresult
 HTMLCanvasElement::ExtractData(nsAString& aType,
                                const nsAString& aOptions,
                                nsIInputStream** aStream)
 {
   return ImageEncoder::ExtractData(aType,
                                    aOptions,
                                    GetSize(),
                                    mCurrentContext,
-                                   mAsyncCanvasRenderer,
                                    aStream);
 }
 
 nsresult
+HTMLCanvasElement::ParseParams(JSContext* aCx,
+                               const nsAString& aType,
+                               const JS::Value& aEncoderOptions,
+                               nsAString& aParams,
+                               bool* usingCustomParseOptions)
+{
+  // Quality parameter is only valid for the image/jpeg MIME type
+  if (aType.EqualsLiteral("image/jpeg")) {
+    if (aEncoderOptions.isNumber()) {
+      double quality = aEncoderOptions.toNumber();
+      // Quality must be between 0.0 and 1.0, inclusive
+      if (quality >= 0.0 && quality <= 1.0) {
+        aParams.AppendLiteral("quality=");
+        aParams.AppendInt(NS_lround(quality * 100.0));
+      }
+    }
+  }
+
+  // If we haven't parsed the aParams check for proprietary options.
+  // The proprietary option -moz-parse-options will take a image lib encoder
+  // parse options string as is and pass it to the encoder.
+  *usingCustomParseOptions = false;
+  if (aParams.Length() == 0 && aEncoderOptions.isString()) {
+    NS_NAMED_LITERAL_STRING(mozParseOptions, "-moz-parse-options:");
+    nsAutoJSString paramString;
+    if (!paramString.init(aCx, aEncoderOptions.toString())) {
+      return NS_ERROR_FAILURE;
+    }
+    if (StringBeginsWith(paramString, mozParseOptions)) {
+      nsDependentSubstring parseOptions = Substring(paramString,
+                                                    mozParseOptions.Length(),
+                                                    paramString.Length() -
+                                                    mozParseOptions.Length());
+      aParams.Append(parseOptions);
+      *usingCustomParseOptions = true;
+    }
+  }
+
+  return NS_OK;
+}
+
+nsresult
 HTMLCanvasElement::ToDataURLImpl(JSContext* aCx,
                                  const nsAString& aMimeType,
                                  const JS::Value& aEncoderOptions,
                                  nsAString& aDataURL)
 {
   nsIntSize size = GetWidthHeight();
   if (size.height == 0 || size.width == 0) {
     aDataURL = NS_LITERAL_STRING("data:,");
@@ -748,48 +654,93 @@ HTMLCanvasElement::ToBlob(JSContext* aCx
                           ErrorResult& aRv)
 {
   // do a trust check if this is a write-only canvas
   if (mWriteOnly && !nsContentUtils::IsCallerChrome()) {
     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return;
   }
 
-  nsCOMPtr<nsIGlobalObject> global = OwnerDoc()->GetScopeObject();
-  MOZ_ASSERT(global);
+  nsAutoString type;
+  nsContentUtils::ASCIIToLower(aType, type);
 
-  CanvasRenderingContextHelper::ToBlob(aCx, global, aCallback, aType,
-                                       aParams, aRv);
+  nsAutoString params;
+  bool usingCustomParseOptions;
+  aRv = ParseParams(aCx, type, aParams, params, &usingCustomParseOptions);
+  if (aRv.Failed()) {
+    return;
+  }
 
-}
+#ifdef DEBUG
+  if (mCurrentContext) {
+    // We disallow canvases of width or height zero, and set them to 1, so
+    // we will have a discrepancy with the sizes of the canvas and the context.
+    // That discrepancy is OK, the rest are not.
+    nsIntSize elementSize = GetWidthHeight();
+    MOZ_ASSERT(elementSize.width == mCurrentContext->GetWidth() ||
+               (elementSize.width == 0 && mCurrentContext->GetWidth() == 1));
+    MOZ_ASSERT(elementSize.height == mCurrentContext->GetHeight() ||
+               (elementSize.height == 0 && mCurrentContext->GetHeight() == 1));
+  }
+#endif
 
-OffscreenCanvas*
-HTMLCanvasElement::TransferControlToOffscreen(ErrorResult& aRv)
-{
+  uint8_t* imageBuffer = nullptr;
+  int32_t format = 0;
   if (mCurrentContext) {
-    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
-    return nullptr;
+    mCurrentContext->GetImageBuffer(&imageBuffer, &format);
   }
 
-  if (!mOffscreenCanvas) {
-    nsIntSize sz = GetWidthHeight();
-    nsRefPtr<AsyncCanvasRenderer> renderer = GetAsyncCanvasRenderer();
-    renderer->SetWidth(sz.width);
-    renderer->SetHeight(sz.height);
+  // Encoder callback when encoding is complete.
+  class EncodeCallback : public EncodeCompleteCallback
+  {
+  public:
+    EncodeCallback(nsIGlobalObject* aGlobal, FileCallback* aCallback)
+      : mGlobal(aGlobal)
+      , mFileCallback(aCallback) {}
+
+    // This is called on main thread.
+    nsresult ReceiveBlob(already_AddRefed<Blob> aBlob)
+    {
+      nsRefPtr<Blob> blob = aBlob;
+
+      ErrorResult rv;
+      uint64_t size = blob->GetSize(rv);
+      if (rv.Failed()) {
+        rv.SuppressException();
+      } else {
+        AutoJSAPI jsapi;
+        if (jsapi.Init(mGlobal)) {
+          JS_updateMallocCounter(jsapi.cx(), size);
+        }
+      }
 
-    mOffscreenCanvas = new OffscreenCanvas(sz.width,
-                                           sz.height,
-                                           GetCompositorBackendType(),
-                                           renderer);
-    mContextObserver = new HTMLCanvasElementObserver(this);
-  } else {
-    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
-  }
+      nsRefPtr<Blob> newBlob = Blob::Create(mGlobal, blob->Impl());
+
+      mFileCallback->Call(*newBlob, rv);
+
+      mGlobal = nullptr;
+      mFileCallback = nullptr;
+
+      return rv.StealNSResult();
+    }
 
-  return mOffscreenCanvas;
+    nsCOMPtr<nsIGlobalObject> mGlobal;
+    nsRefPtr<FileCallback> mFileCallback;
+  };
+
+  nsCOMPtr<nsIGlobalObject> global = OwnerDoc()->GetScopeObject();
+  MOZ_ASSERT(global);
+  nsRefPtr<EncodeCompleteCallback> callback = new EncodeCallback(global, &aCallback);
+  aRv = ImageEncoder::ExtractDataAsync(type,
+                                       params,
+                                       usingCustomParseOptions,
+                                       imageBuffer,
+                                       format,
+                                       GetSize(),
+                                       callback);
 }
 
 already_AddRefed<File>
 HTMLCanvasElement::MozGetAsFile(const nsAString& aName,
                                 const nsAString& aType,
                                 ErrorResult& aRv)
 {
   nsCOMPtr<nsISupports> file;
@@ -850,37 +801,138 @@ HTMLCanvasElement::MozGetAsBlobImpl(cons
   nsCOMPtr<nsIDOMBlob> file =
     File::CreateMemoryFile(win, imgData, (uint32_t)imgSize, aName, type,
                            PR_Now());
 
   file.forget(aResult);
   return NS_OK;
 }
 
+static bool
+GetCanvasContextType(const nsAString& str, CanvasContextType* const out_type)
+{
+  if (str.EqualsLiteral("2d")) {
+    *out_type = CanvasContextType::Canvas2D;
+    return true;
+  }
+
+  if (str.EqualsLiteral("experimental-webgl")) {
+    *out_type = CanvasContextType::WebGL1;
+    return true;
+  }
+
+#ifdef MOZ_WEBGL_CONFORMANT
+  if (str.EqualsLiteral("webgl")) {
+    /* WebGL 1.0, $2.1 "Context Creation":
+     *   If the user agent supports both the webgl and experimental-webgl
+     *   canvas context types, they shall be treated as aliases.
+     */
+    *out_type = CanvasContextType::WebGL1;
+    return true;
+  }
+#endif
+
+  if (WebGL2Context::IsSupported()) {
+    if (str.EqualsLiteral("webgl2")) {
+      *out_type = CanvasContextType::WebGL2;
+      return true;
+    }
+  }
+
+  return false;
+}
+
+static already_AddRefed<nsICanvasRenderingContextInternal>
+CreateContextForCanvas(CanvasContextType contextType, HTMLCanvasElement* canvas)
+{
+  MOZ_ASSERT(contextType != CanvasContextType::NoContext);
+  nsRefPtr<nsICanvasRenderingContextInternal> ret;
+
+  switch (contextType) {
+  case CanvasContextType::NoContext:
+    break;
+  case CanvasContextType::Canvas2D:
+    Telemetry::Accumulate(Telemetry::CANVAS_2D_USED, 1);
+    ret = new CanvasRenderingContext2D();
+    break;
+
+  case CanvasContextType::WebGL1:
+    Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_USED, 1);
+
+    ret = WebGL1Context::Create();
+    if (!ret)
+      return nullptr;
+    break;
+
+  case CanvasContextType::WebGL2:
+    Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_USED, 1);
+
+    ret = WebGL2Context::Create();
+    if (!ret)
+      return nullptr;
+    break;
+  }
+  MOZ_ASSERT(ret);
+
+  ret->SetCanvasElement(canvas);
+  return ret.forget();
+}
+
 nsresult
 HTMLCanvasElement::GetContext(const nsAString& aContextId,
                               nsISupports** aContext)
 {
   ErrorResult rv;
   *aContext = GetContext(nullptr, aContextId, JS::NullHandleValue, rv).take();
   return rv.StealNSResult();
 }
 
 already_AddRefed<nsISupports>
 HTMLCanvasElement::GetContext(JSContext* aCx,
                               const nsAString& aContextId,
                               JS::Handle<JS::Value> aContextOptions,
-                              ErrorResult& aRv)
+                              ErrorResult& rv)
 {
-  if (mOffscreenCanvas) {
+  CanvasContextType contextType;
+  if (!GetCanvasContextType(aContextId, &contextType))
     return nullptr;
+
+  if (!mCurrentContext) {
+    // This canvas doesn't have a context yet.
+
+    nsRefPtr<nsICanvasRenderingContextInternal> context;
+    context = CreateContextForCanvas(contextType, this);
+    if (!context)
+      return nullptr;
+
+    // Ensure that the context participates in CC.  Note that returning a
+    // CC participant from QI doesn't addref.
+    nsXPCOMCycleCollectionParticipant* cp = nullptr;
+    CallQueryInterface(context, &cp);
+    if (!cp) {
+      rv.Throw(NS_ERROR_FAILURE);
+      return nullptr;
+    }
+
+    mCurrentContext = context.forget();
+    mCurrentContextType = contextType;
+
+    rv = UpdateContext(aCx, aContextOptions);
+    if (rv.Failed()) {
+      rv = NS_OK; // See bug 645792
+      return nullptr;
+    }
+  } else {
+    // We already have a context of some type.
+    if (contextType != mCurrentContextType)
+      return nullptr;
   }
 
-  return CanvasRenderingContextHelper::GetContext(aCx, aContextId,
-                                                  aContextOptions, aRv);
+  nsCOMPtr<nsICanvasRenderingContextInternal> context = mCurrentContext;
+  return context.forget();
 }
 
 NS_IMETHODIMP
 HTMLCanvasElement::MozGetIPCContext(const nsAString& aContextId,
                                     nsISupports **aContext)
 {
   if(!nsContentUtils::IsCallerChrome()) {
     // XXX ERRMSG we need to report an error to developers here! (bug 329026)
@@ -892,17 +944,17 @@ HTMLCanvasElement::MozGetIPCContext(cons
     return NS_ERROR_INVALID_ARG;
 
   CanvasContextType contextType = CanvasContextType::Canvas2D;
 
   if (!mCurrentContext) {
     // This canvas doesn't have a context yet.
 
     nsRefPtr<nsICanvasRenderingContextInternal> context;
-    context = CreateContext(contextType);
+    context = CreateContextForCanvas(contextType, this);
     if (!context) {
       *aContext = nullptr;
       return NS_OK;
     }
 
     mCurrentContext = context;
     mCurrentContext->SetIsIPC(true);
     mCurrentContextType = contextType;
@@ -914,16 +966,46 @@ HTMLCanvasElement::MozGetIPCContext(cons
     if (contextType != mCurrentContextType)
       return NS_ERROR_INVALID_ARG;
   }
 
   NS_ADDREF (*aContext = mCurrentContext);
   return NS_OK;
 }
 
+nsresult
+HTMLCanvasElement::UpdateContext(JSContext* aCx, JS::Handle<JS::Value> aNewContextOptions)
+{
+  if (!mCurrentContext)
+    return NS_OK;
+
+  nsIntSize sz = GetWidthHeight();
+
+  nsCOMPtr<nsICanvasRenderingContextInternal> currentContext = mCurrentContext;
+
+  nsresult rv = currentContext->SetIsOpaque(HasAttr(kNameSpaceID_None, nsGkAtoms::moz_opaque));
+  if (NS_FAILED(rv)) {
+    mCurrentContext = nullptr;
+    return rv;
+  }
+
+  rv = currentContext->SetContextOptions(aCx, aNewContextOptions);
+  if (NS_FAILED(rv)) {
+    mCurrentContext = nullptr;
+    return rv;
+  }
+
+  rv = currentContext->SetDimensions(sz.width, sz.height);
+  if (NS_FAILED(rv)) {
+    mCurrentContext = nullptr;
+    return rv;
+  }
+
+  return rv;
+}
 
 nsIntSize
 HTMLCanvasElement::GetSize()
 {
   return GetWidthHeight();
 }
 
 bool
@@ -1017,81 +1099,34 @@ HTMLCanvasElement::GetContextAtIndex(int
 
 bool
 HTMLCanvasElement::GetIsOpaque()
 {
   if (mCurrentContext) {
     return mCurrentContext->GetIsOpaque();
   }
 
-  return GetOpaqueAttr();
-}
-
-bool
-HTMLCanvasElement::GetOpaqueAttr()
-{
   return HasAttr(kNameSpaceID_None, nsGkAtoms::moz_opaque);
 }
 
 already_AddRefed<CanvasLayer>
 HTMLCanvasElement::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
                                   CanvasLayer *aOldLayer,
                                   LayerManager *aManager)
 {
-  // The address of sOffscreenCanvasLayerUserDataDummy is used as the user
-  // data key for retained LayerManagers managed by FrameLayerBuilder.
-  // We don't much care about what value in it, so just assign a dummy
-  // value for it.
-  static uint8_t sOffscreenCanvasLayerUserDataDummy = 0;
-
-  if (mCurrentContext) {
-    return mCurrentContext->GetCanvasLayer(aBuilder, aOldLayer, aManager);
-  }
-
-  if (mOffscreenCanvas) {
-    if (!mResetLayer &&
-        aOldLayer && aOldLayer->HasUserData(&sOffscreenCanvasLayerUserDataDummy)) {
-      nsRefPtr<CanvasLayer> ret = aOldLayer;
-      return ret.forget();
-    }
+  if (!mCurrentContext)
+    return nullptr;
 
-    nsRefPtr<CanvasLayer> layer = aManager->CreateCanvasLayer();
-    if (!layer) {
-      NS_WARNING("CreateCanvasLayer failed!");
-      return nullptr;
-    }
-
-    LayerUserData* userData = nullptr;
-    layer->SetUserData(&sOffscreenCanvasLayerUserDataDummy, userData);
-
-    CanvasLayer::Data data;
-    data.mRenderer = GetAsyncCanvasRenderer();
-    data.mSize = GetWidthHeight();
-    layer->Initialize(data);
-
-    layer->Updated();
-    return layer.forget();
-  }
-
-  return nullptr;
+  return mCurrentContext->GetCanvasLayer(aBuilder, aOldLayer, aManager);
 }
 
 bool
-HTMLCanvasElement::ShouldForceInactiveLayer(LayerManager* aManager)
+HTMLCanvasElement::ShouldForceInactiveLayer(LayerManager *aManager)
 {
-  if (mCurrentContext) {
-    return mCurrentContext->ShouldForceInactiveLayer(aManager);
-  }
-
-  if (mOffscreenCanvas) {
-    // TODO: We should handle offscreen canvas case.
-    return false;
-  }
-
-  return true;
+  return !mCurrentContext || mCurrentContext->ShouldForceInactiveLayer(aManager);
 }
 
 void
 HTMLCanvasElement::MarkContextClean()
 {
   if (!mCurrentContext)
     return;
 
@@ -1196,160 +1231,10 @@ already_AddRefed<SourceSurface>
 HTMLCanvasElement::GetSurfaceSnapshot(bool* aPremultAlpha)
 {
   if (!mCurrentContext)
     return nullptr;
 
   return mCurrentContext->GetSurfaceSnapshot(aPremultAlpha);
 }
 
-AsyncCanvasRenderer*
-HTMLCanvasElement::GetAsyncCanvasRenderer()
-{
-  if (!mAsyncCanvasRenderer) {
-    mAsyncCanvasRenderer = new AsyncCanvasRenderer();
-    mAsyncCanvasRenderer->mHTMLCanvasElement = this;
-  }
-
-  return mAsyncCanvasRenderer;
-}
-
-layers::LayersBackend
-HTMLCanvasElement::GetCompositorBackendType() const
-{
-  nsIWidget* docWidget = nsContentUtils::WidgetForDocument(OwnerDoc());
-  if (docWidget) {
-    layers::LayerManager* layerManager = docWidget->GetLayerManager();
-    return layerManager->GetCompositorBackendType();
-  }
-
-  return LayersBackend::LAYERS_NONE;
-}
-
-void
-HTMLCanvasElement::OnVisibilityChange()
-{
-  if (OwnerDoc()->Hidden()) {
-    return;
-  }
-
-  if (mOffscreenCanvas) {
-    class Runnable final : public nsCancelableRunnable
-    {
-    public:
-      explicit Runnable(AsyncCanvasRenderer* aRenderer)
-        : mRenderer(aRenderer)
-      {}
-
-      NS_IMETHOD Run()
-      {
-        if (mRenderer && mRenderer->mContext) {
-          mRenderer->mContext->OnVisibilityChange();
-        }
-
-        return NS_OK;
-      }
-
-      void Revoke()
-      {
-        mRenderer = nullptr;
-      }
-
-    private:
-      nsRefPtr<AsyncCanvasRenderer> mRenderer;
-    };
-
-    nsRefPtr<nsIRunnable> runnable = new Runnable(mAsyncCanvasRenderer);
-    nsCOMPtr<nsIThread> activeThread = mAsyncCanvasRenderer->GetActiveThread();
-    if (activeThread) {
-      activeThread->Dispatch(runnable, nsIThread::DISPATCH_NORMAL);
-    }
-    return;
-  }
-
-  if (mCurrentContext) {
-    mCurrentContext->OnVisibilityChange();
-  }
-}
-
-void
-HTMLCanvasElement::OnMemoryPressure()
-{
-  if (mOffscreenCanvas) {
-    class Runnable final : public nsCancelableRunnable
-    {
-    public:
-      explicit Runnable(AsyncCanvasRenderer* aRenderer)
-        : mRenderer(aRenderer)
-      {}
-
-      NS_IMETHOD Run()
-      {
-        if (mRenderer && mRenderer->mContext) {
-          mRenderer->mContext->OnMemoryPressure();
-        }
-
-        return NS_OK;
-      }
-
-      void Revoke()
-      {
-        mRenderer = nullptr;
-      }
-
-    private:
-      nsRefPtr<AsyncCanvasRenderer> mRenderer;
-    };
-
-    nsRefPtr<nsIRunnable> runnable = new Runnable(mAsyncCanvasRenderer);
-    nsCOMPtr<nsIThread> activeThread = mAsyncCanvasRenderer->GetActiveThread();
-    if (activeThread) {
-      activeThread->Dispatch(runnable, nsIThread::DISPATCH_NORMAL);
-    }
-    return;
-  }
-
-  if (mCurrentContext) {
-    mCurrentContext->OnMemoryPressure();
-  }
-}
-
-/* static */ void
-HTMLCanvasElement::SetAttrFromAsyncCanvasRenderer(AsyncCanvasRenderer *aRenderer)
-{
-  HTMLCanvasElement *element = aRenderer->mHTMLCanvasElement;
-  if (!element) {
-    return;
-  }
-
-  if (element->GetWidthHeight() == aRenderer->GetSize()) {
-    return;
-  }
-
-  gfx::IntSize asyncCanvasSize = aRenderer->GetSize();
-
-  ErrorResult rv;
-  element->SetUnsignedIntAttr(nsGkAtoms::width, asyncCanvasSize.width, rv);
-  if (rv.Failed()) {
-    NS_WARNING("Failed to set width attribute to a canvas element asynchronously.");
-  }
-
-  element->SetUnsignedIntAttr(nsGkAtoms::height, asyncCanvasSize.height, rv);
-  if (rv.Failed()) {
-    NS_WARNING("Failed to set height attribute to a canvas element asynchronously.");
-  }
-
-  element->mResetLayer = true;
-}
-
-/* static */ void
-HTMLCanvasElement::InvalidateFromAsyncCanvasRenderer(AsyncCanvasRenderer *aRenderer)
-{
-  HTMLCanvasElement *element = aRenderer->mHTMLCanvasElement;
-  if (!element) {
-    return;
-  }
-
-  element->InvalidateCanvasContent(nullptr);
-}
-
 } // namespace dom
 } // namespace mozilla
--- a/dom/html/HTMLCanvasElement.h
+++ b/dom/html/HTMLCanvasElement.h
@@ -3,77 +3,51 @@
 /* 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/. */
 #if !defined(mozilla_dom_HTMLCanvasElement_h)
 #define mozilla_dom_HTMLCanvasElement_h
 
 #include "mozilla/Attributes.h"
 #include "mozilla/WeakPtr.h"
-#include "nsIDOMEventListener.h"
 #include "nsIDOMHTMLCanvasElement.h"
-#include "nsIObserver.h"
 #include "nsGenericHTMLElement.h"
 #include "nsGkAtoms.h"
 #include "nsSize.h"
 #include "nsError.h"
 
-#include "mozilla/dom/CanvasRenderingContextHelper.h"
 #include "mozilla/gfx/Rect.h"
-#include "mozilla/layers/LayersTypes.h"
 
 class nsICanvasRenderingContextInternal;
 class nsITimerCallback;
 
 namespace mozilla {
 
-class WebGLContext;
-
 namespace layers {
-class AsyncCanvasRenderer;
 class CanvasLayer;
 class Image;
 class LayerManager;
 } // namespace layers
 namespace gfx {
 class SourceSurface;
 } // namespace gfx
 
 namespace dom {
 class CanvasCaptureMediaStream;
 class File;
 class FileCallback;
 class HTMLCanvasPrintState;
-class OffscreenCanvas;
 class PrintCallback;
 class RequestedFrameRefreshObserver;
 
-// Listen visibilitychange and memory-pressure event and inform
-// context when event is fired.
-class HTMLCanvasElementObserver final : public nsIObserver
-                                      , public nsIDOMEventListener
-{
-public:
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIOBSERVER
-  NS_DECL_NSIDOMEVENTLISTENER
-
-  explicit HTMLCanvasElementObserver(HTMLCanvasElement* aElement);
-  void Destroy();
-
-  void RegisterVisibilityChangeEvent();
-  void UnregisterVisibilityChangeEvent();
-
-  void RegisterMemoryPressureEvent();
-  void UnregisterMemoryPressureEvent();
-
-private:
-  ~HTMLCanvasElementObserver();
-
-  HTMLCanvasElement* mElement;
+enum class CanvasContextType : uint8_t {
+  NoContext,
+  Canvas2D,
+  WebGL1,
+  WebGL2
 };
 
 /*
  * FrameCaptureListener is used by captureStream() as a way of getting video
  * frames from the canvas. On a refresh driver tick after something has been
  * drawn to the canvas since the last such tick, all registered
  * FrameCaptureListeners whose `mFrameCaptureRequested` equals `true`,
  * will be given a copy of the just-painted canvas.
@@ -105,25 +79,23 @@ public:
 
 protected:
   virtual ~FrameCaptureListener() {}
 
   bool mFrameCaptureRequested;
 };
 
 class HTMLCanvasElement final : public nsGenericHTMLElement,
-                                public nsIDOMHTMLCanvasElement,
-                                public CanvasRenderingContextHelper
+                                public nsIDOMHTMLCanvasElement
 {
   enum {
     DEFAULT_CANVAS_WIDTH = 300,
     DEFAULT_CANVAS_HEIGHT = 150
   };
 
-  typedef layers::AsyncCanvasRenderer AsyncCanvasRenderer;
   typedef layers::CanvasLayer CanvasLayer;
   typedef layers::LayerManager LayerManager;
 
 public:
   explicit HTMLCanvasElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
 
   NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLCanvasElement, canvas)
 
@@ -139,68 +111,48 @@ public:
 
   // WebIDL
   uint32_t Height()
   {
     return GetUnsignedIntAttr(nsGkAtoms::height, DEFAULT_CANVAS_HEIGHT);
   }
   void SetHeight(uint32_t aHeight, ErrorResult& aRv)
   {
-    if (mOffscreenCanvas) {
-      aRv.Throw(NS_ERROR_FAILURE);
-      return;
-    }
-
     SetUnsignedIntAttr(nsGkAtoms::height, aHeight, aRv);
   }
   uint32_t Width()
   {
     return GetUnsignedIntAttr(nsGkAtoms::width, DEFAULT_CANVAS_WIDTH);
   }
   void SetWidth(uint32_t aWidth, ErrorResult& aRv)
   {
-    if (mOffscreenCanvas) {
-      aRv.Throw(NS_ERROR_FAILURE);
-      return;
-    }
-
     SetUnsignedIntAttr(nsGkAtoms::width, aWidth, aRv);
   }
-
-  virtual already_AddRefed<nsISupports>
+  already_AddRefed<nsISupports>
   GetContext(JSContext* aCx, const nsAString& aContextId,
              JS::Handle<JS::Value> aContextOptions,
-             ErrorResult& aRv) override;
-
+             ErrorResult& aRv);
   void ToDataURL(JSContext* aCx, const nsAString& aType,
                  JS::Handle<JS::Value> aParams,
                  nsAString& aDataURL, ErrorResult& aRv)
   {
     aRv = ToDataURL(aType, aParams, aCx, aDataURL);
   }
-
   void ToBlob(JSContext* aCx,
               FileCallback& aCallback,
               const nsAString& aType,
               JS::Handle<JS::Value> aParams,
               ErrorResult& aRv);
 
-  OffscreenCanvas* TransferControlToOffscreen(ErrorResult& aRv);
-
   bool MozOpaque() const
   {
     return GetBoolAttr(nsGkAtoms::moz_opaque);
   }
   void SetMozOpaque(bool aValue, ErrorResult& aRv)
   {
-    if (mOffscreenCanvas) {
-      aRv.Throw(NS_ERROR_FAILURE);
-      return;
-    }
-
     SetHTMLBoolAttr(nsGkAtoms::moz_opaque, aValue, aRv);
   }
   already_AddRefed<File> MozGetAsFile(const nsAString& aName,
                                       const nsAString& aType,
                                       ErrorResult& aRv);
   already_AddRefed<nsISupports> MozGetIPCContext(const nsAString& aContextId,
                                                  ErrorResult& aRv)
   {
@@ -247,17 +199,16 @@ public:
   int32_t CountContexts ();
   nsICanvasRenderingContextInternal *GetContextAtIndex (int32_t index);
 
   /*
    * Returns true if the canvas context content is guaranteed to be opaque
    * across its entire area.
    */
   bool GetIsOpaque();
-  virtual bool GetOpaqueAttr() override;
 
   virtual already_AddRefed<gfx::SourceSurface> GetSurfaceSnapshot(bool* aPremultAlpha = nullptr);
 
   /*
    * Register a FrameCaptureListener with this canvas.
    * The canvas hooks into the RefreshDriver while there are
    * FrameCaptureListeners registered.
    * The registered FrameCaptureListeners are stored as WeakPtrs, thus it's the
@@ -326,58 +277,48 @@ public:
   // copies for future frames when no drawing has occurred.
   void MarkContextCleanForFrameCapture();
 
   // Starts returning false when something is drawn.
   bool IsContextCleanForFrameCapture();
 
   nsresult GetContext(const nsAString& aContextId, nsISupports** aContext);
 
-  layers::LayersBackend GetCompositorBackendType() const;
-
-  void OnVisibilityChange();
-
-  void OnMemoryPressure();
-
-  static void SetAttrFromAsyncCanvasRenderer(AsyncCanvasRenderer *aRenderer);
-  static void InvalidateFromAsyncCanvasRenderer(AsyncCanvasRenderer *aRenderer);
-
 protected:
   virtual ~HTMLCanvasElement();
 
   virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
-  virtual nsIntSize GetWidthHeight() override;
+  nsIntSize GetWidthHeight();
 
-  virtual already_AddRefed<nsICanvasRenderingContextInternal>
-  CreateContext(CanvasContextType aContextType) override;
-
+  nsresult UpdateContext(JSContext* aCx, JS::Handle<JS::Value> options);
+  nsresult ParseParams(JSContext* aCx,
+                       const nsAString& aType,
+                       const JS::Value& aEncoderOptions,
+                       nsAString& aParams,
+                       bool* usingCustomParseOptions);
   nsresult ExtractData(nsAString& aType,
                        const nsAString& aOptions,
                        nsIInputStream** aStream);
   nsresult ToDataURLImpl(JSContext* aCx,
                          const nsAString& aMimeType,
                          const JS::Value& aEncoderOptions,
                          nsAString& aDataURL);
   nsresult MozGetAsBlobImpl(const nsAString& aName,
                             const nsAString& aType,
                             nsISupports** aResult);
   void CallPrintCallback();
 
-  AsyncCanvasRenderer* GetAsyncCanvasRenderer();
-
-  bool mResetLayer;
+  CanvasContextType mCurrentContextType;
   nsRefPtr<HTMLCanvasElement> mOriginalCanvas;
   nsRefPtr<PrintCallback> mPrintCallback;
+  nsCOMPtr<nsICanvasRenderingContextInternal> mCurrentContext;
   nsRefPtr<HTMLCanvasPrintState> mPrintState;
   nsTArray<WeakPtr<FrameCaptureListener>> mRequestedFrameListeners;
   nsRefPtr<RequestedFrameRefreshObserver> mRequestedFrameRefreshObserver;
-  nsRefPtr<AsyncCanvasRenderer> mAsyncCanvasRenderer;
-  nsRefPtr<OffscreenCanvas> mOffscreenCanvas;
-  nsRefPtr<HTMLCanvasElementObserver> mContextObserver;
 
 public:
   // Record whether this canvas should be write-only or not.
   // We set this when script paints an image from a different origin.
   // We also transitively set it when script paints a canvas which
   // is itself write-only.
   bool                     mWriteOnly;
 
--- a/dom/tests/mochitest/general/test_interfaces.html
+++ b/dom/tests/mochitest/general/test_interfaces.html
@@ -868,18 +868,16 @@ var interfaceNamesInGlobalScope =
     "NodeIterator",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "NodeList",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "Notification",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "NotifyPaintEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "OffscreenCanvas", disabled: true},
-// IMPORTANT: Do not change this list without review from a DOM peer!
     "OfflineAudioCompletionEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "OfflineAudioContext",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "OfflineResourceList",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "Option",
 // IMPORTANT: Do not change this list without review from a DOM peer!
--- a/dom/webidl/HTMLCanvasElement.webidl
+++ b/dom/webidl/HTMLCanvasElement.webidl
@@ -41,23 +41,16 @@ partial interface HTMLCanvasElement {
   [ChromeOnly, Throws]
   nsISupports? MozGetIPCContext(DOMString contextId);
            attribute PrintCallback? mozPrintCallback;
 
   [Throws, UnsafeInPrerendering, Pref="canvas.capturestream.enabled"]
   CanvasCaptureMediaStream captureStream(optional double frameRate);
 };
 
-// For OffscreenCanvas
-// Reference: https://wiki.whatwg.org/wiki/OffscreenCanvas
-partial interface HTMLCanvasElement {
-  [Pref="gfx.offscreencanvas.enabled", Throws]
-  OffscreenCanvas transferControlToOffscreen();
-};
-
 [ChromeOnly]
 interface MozCanvasPrintState
 {
   // A canvas rendering context.
   readonly attribute nsISupports context;
 
   // To be called when rendering to the context is done.
   void done();
deleted file mode 100644
--- a/dom/webidl/OffscreenCanvas.webidl
+++ /dev/null
@@ -1,28 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 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/.
- *
- * For more information on this interface, please see
- * https://wiki.whatwg.org/wiki/OffscreenCanvas
- *
- * Current implementation focus on transfer canvas from main thread to worker.
- * So there are some spec doesn't implement, such as [Constructor], toBlob() and
- * transferToImageBitmap in OffscreenCanvas. Bug 1172796 will implement
- * remaining spec.
- */
-
-[Exposed=(Window,Worker),
- Func="mozilla::dom::OffscreenCanvas::PrefEnabled"]
-interface OffscreenCanvas : EventTarget {
-  [Pure, SetterThrows]
-  attribute unsigned long width;
-  [Pure, SetterThrows]
-  attribute unsigned long height;
-
-  [Throws]
-  nsISupports? getContext(DOMString contextId,
-                          optional any contextOptions = null);
-};
-
-// OffscreenCanvas implements Transferable;
--- a/dom/webidl/WebGLRenderingContext.webidl
+++ b/dom/webidl/WebGLRenderingContext.webidl
@@ -40,73 +40,53 @@ dictionary WebGLContextAttributes {
     boolean depth = true;
     boolean stencil = false;
     boolean antialias = true;
     boolean premultipliedAlpha = true;
     boolean preserveDrawingBuffer = false;
     boolean failIfMajorPerformanceCaveat = false;
 };
 
-[Exposed=(Window,Worker),
- Func="mozilla::dom::OffscreenCanvas::PrefEnabledOnWorkerThread"]
 interface WebGLBuffer {
 };
 
-[Exposed=(Window,Worker),
- Func="mozilla::dom::OffscreenCanvas::PrefEnabledOnWorkerThread"]
 interface WebGLFramebuffer {
 };
 
-[Exposed=(Window,Worker),
- Func="mozilla::dom::OffscreenCanvas::PrefEnabledOnWorkerThread"]
 interface WebGLProgram {
 };
 
-[Exposed=(Window,Worker),
- Func="mozilla::dom::OffscreenCanvas::PrefEnabledOnWorkerThread"]
 interface WebGLRenderbuffer {
 };
 
-[Exposed=(Window,Worker),
- Func="mozilla::dom::OffscreenCanvas::PrefEnabledOnWorkerThread"]
 interface WebGLShader {
 };
 
-[Exposed=(Window,Worker),
- Func="mozilla::dom::OffscreenCanvas::PrefEnabledOnWorkerThread"]
 interface WebGLTexture {
 };
 
-[Exposed=(Window,Worker),
- Func="mozilla::dom::OffscreenCanvas::PrefEnabledOnWorkerThread"]
 interface WebGLUniformLocation {
 };
 
 [NoInterfaceObject]
 interface WebGLVertexArrayObjectOES {
 };
 
-[Exposed=(Window,Worker),
- Func="mozilla::dom::OffscreenCanvas::PrefEnabledOnWorkerThread"]
 interface WebGLActiveInfo {
     readonly attribute GLint size;
     readonly attribute GLenum type;
     readonly attribute DOMString name;
 };
 
-[Exposed=(Window,Worker),
- Func="mozilla::dom::OffscreenCanvas::PrefEnabledOnWorkerThread"]
 interface WebGLShaderPrecisionFormat {
     readonly attribute GLint rangeMin;
     readonly attribute GLint rangeMax;
     readonly attribute GLint precision;
 };
 
-[Exposed=(Window,Worker),
- Func="mozilla::dom::OffscreenCanvas::PrefEnabledOnWorkerThread"]
 interface WebGLRenderingContext {
 
     /* ClearBufferMask */
     const GLenum DEPTH_BUFFER_BIT               = 0x00000100;
     const GLenum STENCIL_BUFFER_BIT             = 0x00000400;
     const GLenum COLOR_BUFFER_BIT               = 0x00004000;
 
     /* BeginMode */
@@ -519,17 +499,17 @@ interface WebGLRenderingContext {
     /* WebGL-specific enums */
     const GLenum UNPACK_FLIP_Y_WEBGL            = 0x9240;
     const GLenum UNPACK_PREMULTIPLY_ALPHA_WEBGL = 0x9241;
     const GLenum CONTEXT_LOST_WEBGL             = 0x9242;
     const GLenum UNPACK_COLORSPACE_CONVERSION_WEBGL = 0x9243;
     const GLenum BROWSER_DEFAULT_WEBGL          = 0x9244;
 
     // The canvas might actually be null in some cases, apparently.
-    readonly attribute (HTMLCanvasElement or OffscreenCanvas)? canvas;
+    readonly attribute HTMLCanvasElement? canvas;
     readonly attribute GLsizei drawingBufferWidth;
     readonly attribute GLsizei drawingBufferHeight;
 
     [WebGLHandlesContextLoss] WebGLContextAttributes? getContextAttributes();
     [WebGLHandlesContextLoss] boolean isContextLost();
 
     sequence<DOMString>? getSupportedExtensions();
 
@@ -781,24 +761,16 @@ interface WebGLRenderingContext {
     void vertexAttrib4fv(GLuint indx, Float32Array values);
     void vertexAttrib4fv(GLuint indx, sequence<GLfloat> values);
     void vertexAttribPointer(GLuint indx, GLint size, GLenum type,
                              GLboolean normalized, GLsizei stride, GLintptr offset);
 
     void viewport(GLint x, GLint y, GLsizei width, GLsizei height);
 };
 
-// For OffscreenCanvas
-// Reference: https://wiki.whatwg.org/wiki/OffscreenCanvas
-[Exposed=(Window,Worker)]
-partial interface WebGLRenderingContext {
-  [Func="mozilla::dom::OffscreenCanvas::PrefEnabled"]
-  void commit();
-};
-
 /*[Constructor(DOMString type, optional WebGLContextEventInit eventInit)]
 interface WebGLContextEvent : Event {
     readonly attribute DOMString statusMessage;
     };*/
 
 // EventInit is defined in the DOM4 specification.
 /*dictionary WebGLContextEventInit : EventInit {
     DOMString statusMessage;
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -339,17 +339,16 @@ WEBIDL_FILES = [
     'NodeIterator.webidl',
     'NodeList.webidl',
     'Notification.webidl',
     'NotificationEvent.webidl',
     'NotifyPaintEvent.webidl',
     'OfflineAudioCompletionEvent.webidl',
     'OfflineAudioContext.webidl',
     'OfflineResourceList.webidl',
-    'OffscreenCanvas.webidl',
     'OscillatorNode.webidl',
     'PaintRequest.webidl',
     'PaintRequestList.webidl',
     'PannerNode.webidl',
     'ParentNode.webidl',
     'Performance.webidl',
     'PerformanceCompositeTiming.webidl',
     'PerformanceEntry.webidl',
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -165,17 +165,16 @@ static_assert(MAX_WORKERS_PER_DOMAIN >= 
 #define PREF_WORKERS_LATEST_JS_VERSION "dom.workers.latestJSVersion"
 #define PREF_INTL_ACCEPT_LANGUAGES     "intl.accept_languages"
 #define PREF_SERVICEWORKERS_ENABLED    "dom.serviceWorkers.enabled"
 #define PREF_SERVICEWORKERS_TESTING_ENABLED "dom.serviceWorkers.testing.enabled"
 #define PREF_INTERCEPTION_ENABLED      "dom.serviceWorkers.interception.enabled"
 #define PREF_INTERCEPTION_OPAQUE_ENABLED "dom.serviceWorkers.interception.opaque.enabled"
 #define PREF_PUSH_ENABLED              "dom.push.enabled"
 #define PREF_REQUESTCONTEXT_ENABLED    "dom.requestcontext.enabled"
-#define PREF_OFFSCREENCANVAS_ENABLED   "gfx.offscreencanvas.enabled"
 
 namespace {
 
 const uint32_t kNoIndex = uint32_t(-1);
 
 const JS::ContextOptions kRequiredContextOptions =
   JS::ContextOptions().setDontReportUncaught(true);
 
@@ -1966,20 +1965,16 @@ RuntimeService::Init()
       NS_FAILED(Preferences::RegisterCallbackAndCall(
                                   WorkerPrefChanged,
                                   PREF_PUSH_ENABLED,
                                   reinterpret_cast<void *>(WORKERPREF_PUSH))) ||
       NS_FAILED(Preferences::RegisterCallbackAndCall(
                                   WorkerPrefChanged,
                                   PREF_REQUESTCONTEXT_ENABLED,
                                   reinterpret_cast<void *>(WORKERPREF_REQUESTCONTEXT))) ||
-      NS_FAILED(Preferences::RegisterCallbackAndCall(
-                                  WorkerPrefChanged,
-                                  PREF_OFFSCREENCANVAS_ENABLED,
-                                  reinterpret_cast<void *>(WORKERPREF_OFFSCREENCANVAS))) ||
       NS_FAILED(Preferences::RegisterCallback(LoadRuntimeOptions,
                                               PREF_JS_OPTIONS_PREFIX,
                                               nullptr)) ||
       NS_FAILED(Preferences::RegisterCallbackAndCall(
                                                    LoadRuntimeOptions,
                                                    PREF_WORKERS_OPTIONS_PREFIX,
                                                    nullptr)) ||
       NS_FAILED(Preferences::RegisterCallbackAndCall(PrefLanguagesChanged,
@@ -2209,20 +2204,16 @@ RuntimeService::Cleanup()
         NS_FAILED(Preferences::UnregisterCallback(
                                   WorkerPrefChanged,
                                   PREF_PUSH_ENABLED,
                                   reinterpret_cast<void *>(WORKERPREF_PUSH))) ||
         NS_FAILED(Preferences::UnregisterCallback(
                                   WorkerPrefChanged,
                                   PREF_REQUESTCONTEXT_ENABLED,
                                   reinterpret_cast<void *>(WORKERPREF_REQUESTCONTEXT))) ||
-        NS_FAILED(Preferences::UnregisterCallback(
-                                  WorkerPrefChanged,
-                                  PREF_OFFSCREENCANVAS_ENABLED,
-                                  reinterpret_cast<void *>(WORKERPREF_OFFSCREENCANVAS))) ||
 #if DUMP_CONTROLLED_BY_PREF
         NS_FAILED(Preferences::UnregisterCallback(
                                   WorkerPrefChanged,
                                   PREF_DOM_WINDOW_DUMP_ENABLED,
                                   reinterpret_cast<void *>(WORKERPREF_DUMP))) ||
 #endif
 #ifdef JS_GC_ZEAL
         NS_FAILED(Preferences::UnregisterCallback(
@@ -2774,17 +2765,16 @@ RuntimeService::WorkerPrefChanged(const 
     case WORKERPREF_DUMP:
 #endif
     case WORKERPREF_INTERCEPTION_ENABLED:
     case WORKERPREF_INTERCEPTION_OPAQUE_ENABLED:
     case WORKERPREF_SERVICEWORKERS:
     case WORKERPREF_SERVICEWORKERS_TESTING:
     case WORKERPREF_PUSH:
     case WORKERPREF_REQUESTCONTEXT:
-    case WORKERPREF_OFFSCREENCANVAS:
       sDefaultPreferences[key] = Preferences::GetBool(aPrefName, false);
       break;
 
     default:
       MOZ_ASSERT_UNREACHABLE("Invalid pref key");
       break;
   }
 
--- a/dom/workers/WorkerPrivate.h
+++ b/dom/workers/WorkerPrivate.h
@@ -1309,23 +1309,16 @@ public:
   bool
   RequestContextEnabled() const
   {
     AssertIsOnWorkerThread();
     return mPreferences[WORKERPREF_REQUESTCONTEXT];
   }
 
   bool
-  OffscreenCanvasEnabled() const
-  {
-    AssertIsOnWorkerThread();
-    return mPreferences[WORKERPREF_OFFSCREENCANVAS];
-  }
-
-  bool
   OnLine() const
   {
     AssertIsOnWorkerThread();
     return mOnLine;
   }
 
   void
   StopSyncLoop(nsIEventTarget* aSyncLoopTarget, bool aResult);
--- a/dom/workers/Workers.h
+++ b/dom/workers/Workers.h
@@ -204,17 +204,16 @@ enum WorkerPreference
   WORKERPREF_DOM_WORKERNOTIFICATION, // dom.webnotifications.workers.enabled
   WORKERPREF_DOM_SERVICEWORKERNOTIFICATION, // dom.webnotifications.serviceworker.enabled
   WORKERPREF_DOM_CACHES_TESTING, // dom.caches.testing.enabled
   WORKERPREF_SERVICEWORKERS_TESTING, // dom.serviceWorkers.testing.enabled
   WORKERPREF_INTERCEPTION_OPAQUE_ENABLED, // dom.serviceWorkers.interception.opaque.enabled
   WORKERPREF_PERFORMANCE_LOGGING_ENABLED, // dom.performance.enable_user_timing_logging
   WORKERPREF_PUSH, // dom.push.enabled
   WORKERPREF_REQUESTCONTEXT, // dom.requestcontext.enabled
-  WORKERPREF_OFFSCREENCANVAS, // gfx.offscreencanvas.enabled
   WORKERPREF_COUNT
 };
 
 // Implemented in WorkerPrivate.cpp
 
 struct WorkerLoadInfo
 {
   // All of these should be released in WorkerPrivateParent::ForgetMainThreadObjects.
--- a/dom/workers/test/test_worker_interfaces.js
+++ b/dom/workers/test/test_worker_interfaces.js
@@ -151,18 +151,16 @@ var interfaceNamesInGlobalScope =
     "MessageChannel",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "MessageEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "MessagePort",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "Notification",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    { name: "OffscreenCanvas", disabled: true },
-// IMPORTANT: Do not change this list without review from a DOM peer!
     "Performance",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "PerformanceEntry",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "PerformanceMark",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "PerformanceMeasure",
 // IMPORTANT: Do not change this list without review from a DOM peer!
@@ -187,36 +185,16 @@ var interfaceNamesInGlobalScope =
     "XMLHttpRequestEventTarget",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "XMLHttpRequestUpload",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "URL",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "URLSearchParams",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    { name: "WebGLActiveInfo", disabled: true },
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    { name: "WebGLBuffer", disabled: true },
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    { name: "WebGLFramebuffer", disabled: true },
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    { name: "WebGLProgram", disabled: true },
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    { name: "WebGLRenderbuffer", disabled: true },
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    { name: "WebGLRenderingContext", disabled: true },
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    { name: "WebGLShader", disabled: true },
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    { name: "WebGLShaderPrecisionFormat", disabled: true },
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    { name: "WebGLTexture", disabled: true },
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    { name: "WebGLUniformLocation", disabled: true },
-// IMPORTANT: Do not change this list without review from a DOM peer!
     "WebSocket",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "Worker",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "WorkerGlobalScope",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "WorkerLocation",
 // IMPORTANT: Do not change this list without review from a DOM peer!
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -2645,17 +2645,16 @@ GLContext::Readback(SharedSurface* src, 
     const bool needsSwap = src != prev;
     if (needsSwap) {
         if (prev)
             prev->UnlockProd();
         src->LockProd();
     }
 
     GLuint tempFB = 0;
-    GLuint tempTex = 0;
 
     {
         ScopedBindFramebuffer autoFB(this);
 
         // We're consuming from the producer side, so which do we use?
         // Really, we just want a read-only lock, so ConsumerAcquire is the best match.
         src->ProducerReadAcquire();
 
@@ -2677,46 +2676,24 @@ GLContext::Readback(SharedSurface* src, 
             default:
                 MOZ_CRASH("bad `src->mAttachType`.");
             }
 
             DebugOnly<GLenum> status = fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
             MOZ_ASSERT(status == LOCAL_GL_FRAMEBUFFER_COMPLETE);
         }
 
-        if (src->NeedsIndirectReads()) {
-            fGenTextures(1, &tempTex);
-            {
-                ScopedBindTexture autoTex(this, tempTex);
-
-                GLenum format = src->mHasAlpha ? LOCAL_GL_RGBA
-                                               : LOCAL_GL_RGB;
-                auto width = src->mSize.width;
-                auto height = src->mSize.height;
-                fCopyTexImage2D(LOCAL_GL_TEXTURE_2D, 0, format, 0, 0, width,
-                                height, 0);
-            }
-
-            fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
-                                  LOCAL_GL_COLOR_ATTACHMENT0,
-                                  LOCAL_GL_TEXTURE_2D, tempTex, 0);
-        }
-
         ReadPixelsIntoDataSurface(this, dest);
 
         src->ProducerReadRelease();
     }
 
     if (tempFB)
         fDeleteFramebuffers(1, &tempFB);
 
-    if (tempTex) {
-        fDeleteTextures(1, &tempTex);
-    }
-
     if (needsSwap) {
         src->UnlockProd();
         if (prev)
             prev->LockProd();
     }
 }
 
 // Do whatever tear-down is necessary after drawing to our offscreen FBO,
--- a/gfx/gl/GLLibraryEGL.cpp
+++ b/gfx/gl/GLLibraryEGL.cpp
@@ -1,36 +1,31 @@
 /* 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 "GLLibraryEGL.h"
 
 #include "gfxCrashReporterUtils.h"
-#include "gfxUtils.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Assertions.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsDirectoryServiceUtils.h"
 #include "nsIGfxInfo.h"
 #include "nsPrintfCString.h"
 #ifdef XP_WIN
 #include "nsWindowsHelpers.h"
 #endif
-#include "OGLShaderProgram.h"
 #include "prenv.h"
 #include "GLContext.h"
-#include "GLContextProvider.h"
 #include "gfxPrefs.h"
-#include "ScopedGLHelpers.h"
 
 namespace mozilla {
 namespace gl {
 
-StaticMutex GLLibraryEGL::sMutex;
 GLLibraryEGL sEGLLibrary;
 #ifdef MOZ_B2G
 ThreadLocal<EGLContext> GLLibraryEGL::sCurrentContext;
 #endif
 
 // should match the order of EGLExtensions, and be null-terminated.
 static const char *sEGLExtensionNames[] = {
     "EGL_KHR_image_base",
@@ -128,19 +123,17 @@ GetAndInitWARPDisplay(GLLibraryEGL& egl,
 
     return display;
 }
 
 static bool
 IsAccelAngleSupported(const nsCOMPtr<nsIGfxInfo>& gfxInfo)
 {
     int32_t angleSupport;
-    gfxUtils::ThreadSafeGetFeatureStatus(gfxInfo,
-                                         nsIGfxInfo::FEATURE_WEBGL_ANGLE,
-                                         &angleSupport);
+    gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_WEBGL_ANGLE, &angleSupport);
     return (angleSupport == nsIGfxInfo::FEATURE_STATUS_OK);
 }
 
 static EGLDisplay
 GetAndInitDisplay(GLLibraryEGL& egl, void* displayType)
 {
     EGLDisplay display = egl.fGetDisplay(displayType);
     if (display == EGL_NO_DISPLAY)
@@ -148,42 +141,16 @@ GetAndInitDisplay(GLLibraryEGL& egl, voi
 
     if (!egl.fInitialize(display, nullptr, nullptr))
         return EGL_NO_DISPLAY;
 
     return display;
 }
 
 bool
-GLLibraryEGL::ReadbackEGLImage(EGLImage image, gfx::DataSourceSurface* out_surface)
-{
-    StaticMutexAutoUnlock lock(sMutex);
-    if (!mReadbackGL) {
-        mReadbackGL = gl::GLContextProvider::CreateHeadless(gl::CreateContextFlags::NONE);
-    }
-
-    ScopedTexture destTex(mReadbackGL);
-    const GLuint target = LOCAL_GL_TEXTURE_EXTERNAL;
-    ScopedBindTexture autoTex(mReadbackGL, destTex.Texture(), target);
-    mReadbackGL->fTexParameteri(target, LOCAL_GL_TEXTURE_WRAP_S, LOCAL_GL_CLAMP_TO_EDGE);
-    mReadbackGL->fTexParameteri(target, LOCAL_GL_TEXTURE_WRAP_T, LOCAL_GL_CLAMP_TO_EDGE);
-    mReadbackGL->fTexParameteri(target, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_NEAREST);
-    mReadbackGL->fTexParameteri(target, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_NEAREST);
-    mReadbackGL->fEGLImageTargetTexture2D(target, image);
-
-    ShaderConfigOGL config = ShaderConfigFromTargetAndFormat(target,
-                                                             out_surface->GetFormat());
-    int shaderConfig = config.mFeatures;
-    mReadbackGL->ReadTexImageHelper()->ReadTexImage(out_surface, 0, target,
-                                                    out_surface->GetSize(), shaderConfig);
-
-    return true;
-}
-
-bool
 GLLibraryEGL::EnsureInitialized(bool forceAccel)
 {
     if (mInitialized) {
         return true;
     }
 
     mozilla::ScopedGfxFeatureReporter reporter("EGL");
 
--- a/gfx/gl/GLLibraryEGL.h
+++ b/gfx/gl/GLLibraryEGL.h
@@ -5,17 +5,16 @@
 #ifndef GLLIBRARYEGL_H_
 #define GLLIBRARYEGL_H_
 
 #if defined(MOZ_X11)
 #include "mozilla/X11Util.h"
 #endif
 
 #include "GLLibraryLoader.h"
-#include "mozilla/StaticMutex.h"
 #include "mozilla/ThreadLocal.h"
 #include "nsIFile.h"
 #include "GeckoProfiler.h"
 
 #include <bitset>
 #include <vector>
 
 #ifdef XP_WIN
@@ -48,21 +47,16 @@
 
 #if defined(MOZ_X11)
 #define EGL_DEFAULT_DISPLAY  ((EGLNativeDisplayType)mozilla::DefaultXDisplay())
 #else
 #define EGL_DEFAULT_DISPLAY  ((EGLNativeDisplayType)0)
 #endif
 
 namespace mozilla {
-
-namespace gfx {
-class DataSourceSurface;
-}
-
 namespace gl {
 
 #undef BEFORE_GL_CALL
 #undef AFTER_GL_CALL
 
 #ifdef DEBUG
 
 #ifndef MOZ_FUNCTION_NAME
@@ -95,18 +89,16 @@ namespace gl {
 // Record the name of the GL call for better hang stacks on Android.
 #define BEFORE_GL_CALL PROFILER_LABEL_FUNC(js::ProfileEntry::Category::GRAPHICS)
 #else
 #define BEFORE_GL_CALL
 #endif
 #define AFTER_GL_CALL
 #endif
 
-class GLContext;
-
 class GLLibraryEGL
 {
 public:
     GLLibraryEGL()
         : mInitialized(false),
           mEGLLibrary(nullptr),
           mIsANGLE(false),
           mIsWARP(false)
@@ -481,18 +473,16 @@ public:
     bool HasANGLESurfaceD3DTexture2DShareHandle() {
         return IsExtensionSupported(ANGLE_surface_d3d_texture_2d_share_handle);
     }
 
     bool HasRobustness() const {
         return IsExtensionSupported(EXT_create_context_robustness);
     }
 
-    bool ReadbackEGLImage(EGLImage image, gfx::DataSourceSurface* out_surface);
-
     bool EnsureInitialized(bool forceAccel = false);
 
     void DumpEGLConfig(EGLConfig cfg);
     void DumpEGLConfigs();
 
     struct {
         typedef EGLDisplay (GLAPIENTRY * pfnGetDisplay)(void *display_id);
         pfnGetDisplay fGetDisplay;
@@ -608,21 +598,19 @@ public:
     void SetCachedCurrentContext(EGLContext aCtx) { }
     bool CachedCurrentContextMatches() { return true; }
 #endif
 
 private:
     bool mInitialized;
     PRLibrary* mEGLLibrary;
     EGLDisplay mEGLDisplay;
-    RefPtr<GLContext> mReadbackGL;
 
     bool mIsANGLE;
     bool mIsWARP;
-    static StaticMutex sMutex;
 };
 
 extern GLLibraryEGL sEGLLibrary;
 #define EGL_DISPLAY()        sEGLLibrary.Display()
 
 } /* namespace gl */
 } /* namespace mozilla */
 
--- a/gfx/gl/GLReadTexImageHelper.cpp
+++ b/gfx/gl/GLReadTexImageHelper.cpp
@@ -209,17 +209,17 @@ GetActualReadFormats(GLContext* gl,
         return false;
     } else {
         *out_readFormat = destFormat;
         *out_readType = destType;
         return true;
     }
 }
 
-void
+static void
 SwapRAndBComponents(DataSourceSurface* surf)
 {
     DataSourceSurface::MappedSurface map;
     if (!surf->Map(DataSourceSurface::MapType::READ_WRITE, &map)) {
         MOZ_ASSERT(false, "SwapRAndBComponents: Failed to map surface.");
         return;
     }
     MOZ_ASSERT(map.mStride >= 0);
@@ -528,18 +528,18 @@ ReadPixelsIntoDataSurface(GLContext* gl,
                     *itr |= alphaMask;
                 }
             }
         }
     }
 #endif
 }
 
-already_AddRefed<gfx::DataSourceSurface>
-YInvertImageSurface(gfx::DataSourceSurface* aSurf)
+static already_AddRefed<DataSourceSurface>
+YInvertImageSurface(DataSourceSurface* aSurf)
 {
     RefPtr<DataSourceSurface> temp =
       Factory::CreateDataSourceSurfaceWithStride(aSurf->GetSize(),
                                                  aSurf->GetFormat(),
                                                  aSurf->Stride());
     if (NS_WARN_IF(!temp)) {
         return nullptr;
     }
@@ -555,18 +555,18 @@ YInvertImageSurface(gfx::DataSourceSurfa
                                        temp->GetSize(),
                                        map.mStride,
                                        temp->GetFormat());
     if (!dt) {
         temp->Unmap();
         return nullptr;
     }
 
-    dt->SetTransform(Matrix::Scaling(1.0, -1.0) *
-                     Matrix::Translation(0.0, aSurf->GetSize().height));
+    dt->SetTransform(Matrix::Translation(0.0, aSurf->GetSize().height) *
+                     Matrix::Scaling(1.0, -1.0));
     Rect rect(0, 0, aSurf->GetSize().width, aSurf->GetSize().height);
     dt->DrawSurface(aSurf, rect, rect, DrawSurfaceOptions(),
                     DrawOptions(1.0, CompositionOp::OP_SOURCE, AntialiasMode::NONE));
     temp->Unmap();
     return temp.forget();
 }
 
 already_AddRefed<DataSourceSurface>
@@ -609,57 +609,43 @@ ReadBackSurface(GLContext* gl, GLuint aT
         surf = YInvertImageSurface(surf);
     }
 
     return surf.forget();
 }
 
 #define CLEANUP_IF_GLERROR_OCCURRED(x)                                      \
     if (DidGLErrorOccur(x)) {                                               \
-        return false;                                                       \
+        isurf = nullptr;                                                    \
+        break;                                                              \
     }
 
 already_AddRefed<DataSourceSurface>
 GLReadTexImageHelper::ReadTexImage(GLuint aTextureId,
                                    GLenum aTextureTarget,
                                    const gfx::IntSize& aSize,
     /* ShaderConfigOGL.mFeature */ int aConfig,
                                    bool aYInvert)
 {
-    /* Allocate resulting image surface */
-    int32_t stride = aSize.width * BytesPerPixel(SurfaceFormat::R8G8B8A8);
-    RefPtr<DataSourceSurface> isurf =
-        Factory::CreateDataSourceSurfaceWithStride(aSize,
-                                                   SurfaceFormat::R8G8B8A8,
-                                                   stride);
-    if (NS_WARN_IF(!isurf)) {
-        return nullptr;
-    }
-
-    if (!ReadTexImage(isurf, aTextureId, aTextureTarget, aSize, aConfig, aYInvert)) {
-        return nullptr;
-    }
-
-    return isurf.forget();
-}
-
-bool
-GLReadTexImageHelper::ReadTexImage(DataSourceSurface* aDest,
-                                   GLuint aTextureId,
-                                   GLenum aTextureTarget,
-                                   const gfx::IntSize& aSize,
-    /* ShaderConfigOGL.mFeature */ int aConfig,
-                                   bool aYInvert)
-{
     MOZ_ASSERT(aTextureTarget == LOCAL_GL_TEXTURE_2D ||
                aTextureTarget == LOCAL_GL_TEXTURE_EXTERNAL ||
                aTextureTarget == LOCAL_GL_TEXTURE_RECTANGLE_ARB);
 
     mGL->MakeCurrent();
 
+    /* Allocate resulting image surface */
+    int32_t stride = aSize.width * BytesPerPixel(SurfaceFormat::R8G8B8A8);
+    RefPtr<DataSourceSurface> isurf =
+        Factory::CreateDataSourceSurfaceWithStride(aSize,
+                                                   SurfaceFormat::R8G8B8A8,
+                                                   stride);
+    if (NS_WARN_IF(!isurf)) {
+        return nullptr;
+    }
+
     GLint oldrb, oldfb, oldprog, oldTexUnit, oldTex;
     GLuint rb, fb;
 
     do {
         mGL->fGetIntegerv(LOCAL_GL_RENDERBUFFER_BINDING, &oldrb);
         mGL->fGetIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, &oldfb);
         mGL->fGetIntegerv(LOCAL_GL_CURRENT_PROGRAM, &oldprog);
         mGL->fGetIntegerv(LOCAL_GL_ACTIVE_TEXTURE, &oldTexUnit);
@@ -746,17 +732,17 @@ GLReadTexImageHelper::ReadTexImage(DataS
         mGL->fClearColor(1.0f, 0.0f, 1.0f, 1.0f);
         mGL->fClear(LOCAL_GL_COLOR_BUFFER_BIT);
         CLEANUP_IF_GLERROR_OCCURRED("when clearing color buffer");
 
         mGL->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4);
         CLEANUP_IF_GLERROR_OCCURRED("when drawing texture");
 
         /* Read-back draw results */
-        ReadPixelsIntoDataSurface(mGL, aDest);
+        ReadPixelsIntoDataSurface(mGL, isurf);
         CLEANUP_IF_GLERROR_OCCURRED("when reading pixels into surface");
     } while (false);
 
     /* Restore GL state */
     mGL->fBindRenderbuffer(LOCAL_GL_RENDERBUFFER, oldrb);
     mGL->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, oldfb);
     mGL->fUseProgram(oldprog);
 
@@ -765,15 +751,15 @@ GLReadTexImageHelper::ReadTexImage(DataS
     mGL->fDeleteFramebuffers(1, &fb);
 
     if (aTextureId)
         mGL->fBindTexture(aTextureTarget, oldTex);
 
     if (oldTexUnit != LOCAL_GL_TEXTURE0)
         mGL->fActiveTexture(oldTexUnit);
 
-    return true;
+    return isurf.forget();
 }
 
 #undef CLEANUP_IF_GLERROR_OCCURRED
 
 } // namespace gl
 } // namespace mozilla
--- a/gfx/gl/GLReadTexImageHelper.h
+++ b/gfx/gl/GLReadTexImageHelper.h
@@ -29,22 +29,16 @@ bool GetActualReadFormats(GLContext* gl,
                           GLenum* out_readFormat, GLenum* out_readType);
 
 void ReadPixelsIntoDataSurface(GLContext* aGL,
                                gfx::DataSourceSurface* aSurface);
 
 already_AddRefed<gfx::DataSourceSurface>
 ReadBackSurface(GLContext* gl, GLuint aTexture, bool aYInvert, gfx::SurfaceFormat aFormat);
 
-already_AddRefed<gfx::DataSourceSurface>
-YInvertImageSurface(gfx::DataSourceSurface* aSurf);
-
-void
-SwapRAndBComponents(gfx::DataSourceSurface* surf);
-
 class GLReadTexImageHelper final
 {
     // The GLContext is the sole owner of the GLBlitHelper.
     GLContext* mGL;
 
     GLuint mPrograms[4];
 
     GLuint TextureImageProgramFor(GLenum aTextureTarget, int aShader);
@@ -66,25 +60,20 @@ public:
       * THIS IS EXPENSIVE.  It is ridiculously expensive.  Only do this
       * if you absolutely positively must, and never in any performance
       * critical path.
       *
       * NOTE: aShaderProgram is really mozilla::layers::ShaderProgramType. It is
       * passed as int to eliminate including LayerManagerOGLProgram.h here.
       */
     already_AddRefed<gfx::DataSourceSurface> ReadTexImage(GLuint aTextureId,
-                                                          GLenum aTextureTarget,
-                                                          const gfx::IntSize& aSize,
-                                  /* ShaderProgramType */ int aShaderProgram,
-                                                          bool aYInvert = false);
+                                                      GLenum aTextureTarget,
+                                                      const gfx::IntSize& aSize,
+                              /* ShaderProgramType */ int aShaderProgram,
+                                                      bool aYInvert = false);
 
-    bool ReadTexImage(gfx::DataSourceSurface* aDest,
-                      GLuint aTextureId,
-                      GLenum aTextureTarget,
-                      const gfx::IntSize& aSize,
-                      int aShaderProgram,
-                      bool aYInvert = false);
+
 };
 
 } // namespace gl
 } // namespace mozilla
 
 #endif
--- a/gfx/gl/GLScreenBuffer.cpp
+++ b/gfx/gl/GLScreenBuffer.cpp
@@ -5,42 +5,28 @@
 
 #include "GLScreenBuffer.h"
 
 #include <cstring>
 #include "CompositorTypes.h"
 #include "GLContext.h"
 #include "GLBlitHelper.h"
 #include "GLReadTexImageHelper.h"
-#include "SharedSurfaceEGL.h"
 #include "SharedSurfaceGL.h"
-#include "ScopedGLHelpers.h"
-#include "gfx2DGlue.h"
-#include "../layers/ipc/ShadowLayers.h"
-#include "mozilla/layers/CompositableForwarder.h"
-#include "mozilla/layers/TextureClientSharedSurface.h"
-
-#ifdef XP_WIN
-#include "SharedSurfaceANGLE.h"       // for SurfaceFactory_ANGLEShareHandle
-#include "gfxWindowsPlatform.h"
-#endif
-
 #ifdef MOZ_WIDGET_GONK
 #include "SharedSurfaceGralloc.h"
 #include "nsXULAppAPI.h"
 #endif
-
 #ifdef XP_MACOSX
 #include "SharedSurfaceIO.h"
 #endif
-
-#ifdef GL_PROVIDER_GLX
-#include "GLXLibrary.h"
-#include "SharedSurfaceGLX.h"
-#endif
+#include "ScopedGLHelpers.h"
+#include "gfx2DGlue.h"
+#include "../layers/ipc/ShadowLayers.h"
+#include "mozilla/layers/TextureClientSharedSurface.h"
 
 namespace mozilla {
 namespace gl {
 
 using gfx::SurfaceFormat;
 
 UniquePtr<GLScreenBuffer>
 GLScreenBuffer::Create(GLContext* gl,
@@ -60,63 +46,16 @@ GLScreenBuffer::Create(GLContext* gl,
     }
 
     UniquePtr<SurfaceFactory> factory = MakeUnique<SurfaceFactory_Basic>(gl, caps, flags);
 
     ret.reset( new GLScreenBuffer(gl, caps, Move(factory)) );
     return Move(ret);
 }
 
-/* static */ UniquePtr<SurfaceFactory>
-GLScreenBuffer::CreateFactory(GLContext* gl,
-                              const SurfaceCaps& caps,
-                              const RefPtr<layers::CompositableForwarder>& forwarder,
-                              const layers::TextureFlags& flags)
-{
-    UniquePtr<SurfaceFactory> factory = nullptr;
-    if (!gfxPrefs::WebGLForceLayersReadback()) {
-        switch (forwarder->GetCompositorBackendType()) {
-            case mozilla::layers::LayersBackend::LAYERS_OPENGL: {
-#if defined(XP_MACOSX)
-                factory = SurfaceFactory_IOSurface::Create(gl, caps, forwarder, flags);
-#elif defined(MOZ_WIDGET_GONK)
-                factory = MakeUnique<SurfaceFactory_Gralloc>(gl, caps, forwarder, flags);
-#elif defined(GL_PROVIDER_GLX)
-                if (sGLXLibrary.UseSurfaceSharing())
-                  factory = SurfaceFactory_GLXDrawable::Create(gl, caps, forwarder, flags);
-#else
-                if (gl->GetContextType() == GLContextType::EGL) {
-                    if (XRE_IsParentProcess()) {
-                        factory = SurfaceFactory_EGLImage::Create(gl, caps, forwarder, flags);
-                    }
-                }
-#endif
-                break;
-            }
-            case mozilla::layers::LayersBackend::LAYERS_D3D11: {
-#ifdef XP_WIN
-                // Enable surface sharing only if ANGLE and compositing devices
-                // are both WARP or both not WARP
-                if (gl->IsANGLE() &&
-                    (gl->IsWARP() == gfxWindowsPlatform::GetPlatform()->IsWARP()) &&
-                    gfxWindowsPlatform::GetPlatform()->CompositorD3D11TextureSharingWorks())
-                {
-                    factory = SurfaceFactory_ANGLEShareHandle::Create(gl, caps, forwarder, flags);
-                }
-#endif
-              break;
-            }
-            default:
-              break;
-        }
-    }
-
-    return factory;
-}
-
 GLScreenBuffer::GLScreenBuffer(GLContext* gl,
                                const SurfaceCaps& caps,
                                UniquePtr<SurfaceFactory> factory)
     : mGL(gl)
     , mCaps(caps)
     , mFactory(Move(factory))
     , mNeedsBlit(true)
     , mUserReadBufferMode(LOCAL_GL_BACK)
--- a/gfx/gl/GLScreenBuffer.h
+++ b/gfx/gl/GLScreenBuffer.h
@@ -20,17 +20,16 @@
 #include "mozilla/gfx/2D.h"
 #include "mozilla/gfx/Point.h"
 #include "mozilla/UniquePtr.h"
 #include "SharedSurface.h"
 #include "SurfaceTypes.h"
 
 namespace mozilla {
 namespace layers {
-class CompositableForwarder;
 class SharedSurfaceTextureClient;
 } // namespace layers
 
 namespace gl {
 
 class GLContext;
 class SharedSurface;
 class ShSurfHandle;
@@ -129,22 +128,16 @@ public:
 class GLScreenBuffer
 {
 public:
     // Infallible.
     static UniquePtr<GLScreenBuffer> Create(GLContext* gl,
                                             const gfx::IntSize& size,
                                             const SurfaceCaps& caps);
 
-    static UniquePtr<SurfaceFactory>
-    CreateFactory(GLContext* gl,
-                  const SurfaceCaps& caps,
-                  const RefPtr<layers::CompositableForwarder>& forwarder,
-                  const layers::TextureFlags& flags);
-
 protected:
     GLContext* const mGL; // Owns us.
 public:
     const SurfaceCaps mCaps;
 protected:
     UniquePtr<SurfaceFactory> mFactory;
 
     RefPtr<layers::SharedSurfaceTextureClient> mBack;
--- a/gfx/gl/SharedSurface.cpp
+++ b/gfx/gl/SharedSurface.cpp
@@ -306,17 +306,16 @@ SurfaceFactory::SurfaceFactory(SharedSur
                                const RefPtr<layers::ISurfaceAllocator>& allocator,
                                const layers::TextureFlags& flags)
     : mType(type)
     , mGL(gl)
     , mCaps(caps)
     , mAllocator(allocator)
     , mFlags(flags)
     , mFormats(gl->ChooseGLFormats(caps))
-    , mMutex("SurfaceFactor::mMutex")
 {
     ChooseBufferBits(mCaps, &mDrawCaps, &mReadCaps);
 }
 
 SurfaceFactory::~SurfaceFactory()
 {
     while (!mRecycleTotalPool.empty()) {
         StopRecycling(*mRecycleTotalPool.begin());
@@ -364,46 +363,47 @@ SurfaceFactory::StartRecycling(layers::S
     bool didInsert = mRecycleTotalPool.insert(tc);
     MOZ_RELEASE_ASSERT(didInsert);
     mozilla::unused << didInsert;
 }
 
 void
 SurfaceFactory::StopRecycling(layers::SharedSurfaceTextureClient* tc)
 {
-    MutexAutoLock autoLock(mMutex);
     // Must clear before releasing ref.
     tc->ClearRecycleCallback();
 
     bool didErase = mRecycleTotalPool.erase(tc);
     MOZ_RELEASE_ASSERT(didErase);
     mozilla::unused << didErase;
 }
 
 /*static*/ void
 SurfaceFactory::RecycleCallback(layers::TextureClient* rawTC, void* rawFactory)
 {
+    MOZ_ASSERT(NS_IsMainThread());
+
     RefPtr<layers::SharedSurfaceTextureClient> tc;
     tc = static_cast<layers::SharedSurfaceTextureClient*>(rawTC);
+
     SurfaceFactory* factory = static_cast<SurfaceFactory*>(rawFactory);
 
     if (tc->mSurf->mCanRecycle) {
         if (factory->Recycle(tc))
             return;
     }
 
     // Did not recover the tex client. End the (re)cycle!
     factory->StopRecycling(tc);
 }
 
 bool
 SurfaceFactory::Recycle(layers::SharedSurfaceTextureClient* texClient)
 {
     MOZ_ASSERT(texClient);
-    MutexAutoLock autoLock(mMutex);
 
     if (mRecycleFreePool.size() >= 2) {
         return false;
     }
 
     RefPtr<layers::SharedSurfaceTextureClient> texClientRef = texClient;
     mRecycleFreePool.push(texClientRef);
     return true;
--- a/gfx/gl/SharedSurface.h
+++ b/gfx/gl/SharedSurface.h
@@ -19,27 +19,25 @@
 #include <set>
 #include <stdint.h>
 
 #include "GLContextTypes.h"
 #include "GLDefs.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/gfx/Point.h"
-#include "mozilla/Mutex.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/WeakPtr.h"
 #include "ScopedGLHelpers.h"
 #include "SurfaceTypes.h"
 
 class nsIThread;
 
 namespace mozilla {
 namespace gfx {
-class DataSourceSurface;
 class DrawTarget;
 } // namespace gfx
 
 namespace layers {
 class ISurfaceAllocator;
 class SharedSurfaceTextureClient;
 enum class TextureFlags : uint32_t;
 class SurfaceDescriptor;
@@ -196,20 +194,16 @@ public:
         return false;
     }
 
     virtual bool NeedsIndirectReads() const {
         return false;
     }
 
     virtual bool ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) = 0;
-
-    virtual bool ReadbackBySharedHandle(gfx::DataSourceSurface* out_surface) {
-        return false;
-    }
 };
 
 template<typename T>
 class RefSet
 {
     std::set<T*> mSet;
 
 public:
@@ -299,17 +293,16 @@ public:
     MOZ_DECLARE_WEAKREFERENCE_TYPENAME(SurfaceFactory)
 
     const SharedSurfaceType mType;
     GLContext* const mGL;
     const SurfaceCaps mCaps;
     const RefPtr<layers::ISurfaceAllocator> mAllocator;
     const layers::TextureFlags mFlags;
     const GLFormats mFormats;
-    Mutex mMutex;
 protected:
     SurfaceCaps mDrawCaps;
     SurfaceCaps mReadCaps;
     RefQueue<layers::SharedSurfaceTextureClient> mRecycleFreePool;
     RefSet<layers::SharedSurfaceTextureClient> mRecycleTotalPool;
 
     SurfaceFactory(SharedSurfaceType type, GLContext* gl, const SurfaceCaps& caps,
                    const RefPtr<layers::ISurfaceAllocator>& allocator,
--- a/gfx/gl/SharedSurfaceANGLE.cpp
+++ b/gfx/gl/SharedSurfaceANGLE.cpp
@@ -268,148 +268,16 @@ SharedSurface_ANGLEShareHandle::ToSurfac
 {
     gfx::SurfaceFormat format = mHasAlpha ? gfx::SurfaceFormat::B8G8R8A8
                                           : gfx::SurfaceFormat::B8G8R8X8;
     *out_descriptor = layers::SurfaceDescriptorD3D10((WindowsHandle)mShareHandle, format,
                                                      mSize);
     return true;
 }
 
-class ScopedLockTexture final
-{
-public:
-    explicit ScopedLockTexture(ID3D11Texture2D* texture, bool* succeeded)
-      : mIsLocked(false)
-      , mTexture(texture)
-    {
-        MOZ_ASSERT(mTexture);
-        MOZ_ASSERT(succeeded);
-        *succeeded = false;
-
-        HRESULT hr;
-        mTexture->QueryInterface((IDXGIKeyedMutex**)byRef(mMutex));
-        if (mMutex) {
-            hr = mMutex->AcquireSync(0, 10000);
-            if (hr == WAIT_TIMEOUT) {
-                MOZ_CRASH();
-            }
-
-            if (FAILED(hr)) {
-                NS_WARNING("Failed to lock the texture");
-                return;
-            }
-        }
-
-        ID3D11Device* device = gfxWindowsPlatform::GetPlatform()->GetD3D11Device();
-        device->GetImmediateContext(byRef(mDeviceContext));
-
-        mTexture->GetDesc(&mDesc);
-        mDesc.BindFlags = 0;
-        mDesc.Usage = D3D11_USAGE_STAGING;
-        mDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
-        mDesc.MiscFlags = 0;
-
-        hr = device->CreateTexture2D(&mDesc, nullptr, byRef(mCopiedTexture));
-
-        if (FAILED(hr)) {
-            return;
-        }
-
-        mDeviceContext->CopyResource(mCopiedTexture, mTexture);
-
-        hr = mDeviceContext->Map(mCopiedTexture, 0, D3D11_MAP_READ, 0, &mSubresource);
-        if (FAILED(hr)) {
-            return;
-        }
-
-        *succeeded = true;
-        mIsLocked = true;
-    }
-
-    ~ScopedLockTexture()
-    {
-        mDeviceContext->Unmap(mCopiedTexture, 0);
-        if (mMutex) {
-            HRESULT hr = mMutex->ReleaseSync(0);
-            if (FAILED(hr)) {
-                NS_WARNING("Failed to unlock the texture");
-            }
-        }
-        mIsLocked = false;
-    }
-
-    bool mIsLocked;
-    RefPtr<ID3D11Texture2D> mTexture;
-    RefPtr<ID3D11Texture2D> mCopiedTexture;
-    RefPtr<IDXGIKeyedMutex> mMutex;
-    RefPtr<ID3D11DeviceContext> mDeviceContext;
-    D3D11_TEXTURE2D_DESC mDesc;
-    D3D11_MAPPED_SUBRESOURCE mSubresource;
-};
-
-bool
-SharedSurface_ANGLEShareHandle::ReadbackBySharedHandle(gfx::DataSourceSurface* out_surface)
-{
-    MOZ_ASSERT(out_surface);
-    RefPtr<ID3D11Texture2D> tex;
-    ID3D11Device* device = gfxWindowsPlatform::GetPlatform()->GetD3D11Device();
-    HRESULT hr = device->OpenSharedResource(mShareHandle,
-                                            __uuidof(ID3D11Texture2D),
-                                            (void**)(ID3D11Texture2D**)byRef(tex));
-
-    if (FAILED(hr)) {
-        return false;
-    }
-
-    bool succeeded = false;
-    ScopedLockTexture scopedLock(tex, &succeeded);
-    if (!succeeded) {
-        return false;
-    }
-
-    const uint8_t* data = reinterpret_cast<uint8_t*>(scopedLock.mSubresource.pData);
-    uint32_t srcStride = scopedLock.mSubresource.RowPitch;
-
-    gfx::DataSourceSurface::ScopedMap map(out_surface, gfx::DataSourceSurface::WRITE);
-    if (!map.IsMapped()) {
-        return false;
-    }
-
-    if (map.GetStride() == srcStride) {
-        memcpy(map.GetData(), data, out_surface->GetSize().height * map.GetStride());
-    } else {
-        const uint8_t bytesPerPixel = BytesPerPixel(out_surface->GetFormat());
-        for (int32_t i = 0; i < out_surface->GetSize().height; i++) {
-            memcpy(map.GetData() + i * map.GetStride(),
-                   data + i * srcStride,
-                   bytesPerPixel * out_surface->GetSize().width);
-        }
-    }
-
-    DXGI_FORMAT srcFormat = scopedLock.mDesc.Format;
-    MOZ_ASSERT(srcFormat == DXGI_FORMAT_B8G8R8A8_UNORM ||
-               srcFormat == DXGI_FORMAT_B8G8R8X8_UNORM ||
-               srcFormat == DXGI_FORMAT_R8G8B8A8_UNORM);
-    bool isSrcRGB = srcFormat == DXGI_FORMAT_R8G8B8A8_UNORM;
-
-    gfx::SurfaceFormat destFormat = out_surface->GetFormat();
-    MOZ_ASSERT(destFormat == gfx::SurfaceFormat::R8G8B8X8 ||
-               destFormat == gfx::SurfaceFormat::R8G8B8A8 ||
-               destFormat == gfx::SurfaceFormat::B8G8R8X8 ||
-               destFormat == gfx::SurfaceFormat::B8G8R8A8);
-    bool isDestRGB = destFormat == gfx::SurfaceFormat::R8G8B8X8 ||
-                     destFormat == gfx::SurfaceFormat::R8G8B8A8;
-
-    if (isSrcRGB != isDestRGB) {
-        SwapRAndBComponents(out_surface);
-    }
-
-    return true;
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // Factory
 
 /*static*/ UniquePtr<SurfaceFactory_ANGLEShareHandle>
 SurfaceFactory_ANGLEShareHandle::Create(GLContext* gl, const SurfaceCaps& caps,
                                         const RefPtr<layers::ISurfaceAllocator>& allocator,
                                         const layers::TextureFlags& flags)
 {
--- a/gfx/gl/SharedSurfaceANGLE.h
+++ b/gfx/gl/SharedSurfaceANGLE.h
@@ -76,18 +76,16 @@ public:
     virtual bool WaitSync_ContentThread_Impl() override;
     virtual bool PollSync_ContentThread_Impl() override;
 
     const RefPtr<ID3D11Texture2D>& GetConsumerTexture() const {
         return mConsumerTexture;
     }
 
     virtual bool ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) override;
-
-    virtual bool ReadbackBySharedHandle(gfx::DataSourceSurface* out_surface) override;
 };
 
 
 
 class SurfaceFactory_ANGLEShareHandle
     : public SurfaceFactory
 {
 protected:
--- a/gfx/gl/SharedSurfaceEGL.cpp
+++ b/gfx/gl/SharedSurfaceEGL.cpp
@@ -5,16 +5,17 @@
 
 #include "SharedSurfaceEGL.h"
 
 #include "GLBlitHelper.h"
 #include "GLContextEGL.h"
 #include "GLLibraryEGL.h"
 #include "GLReadTexImageHelper.h"
 #include "mozilla/layers/LayersSurfaces.h"  // for SurfaceDescriptor, etc
+#include "ScopedGLHelpers.h"
 #include "SharedSurface.h"
 #include "TextureGarbageBin.h"
 
 namespace mozilla {
 namespace gl {
 
 /*static*/ UniquePtr<SharedSurface_EGLImage>
 SharedSurface_EGLImage::Create(GLContext* prodGL,
@@ -207,24 +208,16 @@ SharedSurface_EGLImage::AcquireConsumerT
 bool
 SharedSurface_EGLImage::ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor)
 {
     *out_descriptor = layers::EGLImageDescriptor((uintptr_t)mImage, (uintptr_t)mSync,
                                                  mSize, mHasAlpha);
     return true;
 }
 
-bool
-SharedSurface_EGLImage::ReadbackBySharedHandle(gfx::DataSourceSurface* out_surface)
-{
-    MOZ_ASSERT(out_surface);
-    MOZ_ASSERT(NS_IsMainThread());
-    return sEGLLibrary.ReadbackEGLImage(mImage, out_surface);
-}
-
 ////////////////////////////////////////////////////////////////////////
 
 /*static*/ UniquePtr<SurfaceFactory_EGLImage>
 SurfaceFactory_EGLImage::Create(GLContext* prodGL, const SurfaceCaps& caps,
                                 const RefPtr<layers::ISurfaceAllocator>& allocator,
                                 const layers::TextureFlags& flags)
 {
     EGLContext context = GLContextEGL::Cast(prodGL)->mContext;
--- a/gfx/gl/SharedSurfaceEGL.h
+++ b/gfx/gl/SharedSurfaceEGL.h
@@ -74,18 +74,16 @@ public:
       return mProdTex;
     }
 
     // Implementation-specific functions below:
     // Returns texture and target
     void AcquireConsumerTexture(GLContext* consGL, GLuint* out_texture, GLuint* out_target);
 
     virtual bool ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) override;
-
-    virtual bool ReadbackBySharedHandle(gfx::DataSourceSurface* out_surface) override;
 };
 
 
 
 class SurfaceFactory_EGLImage
     : public SurfaceFactory
 {
 public:
--- a/gfx/gl/SharedSurfaceGLX.cpp
+++ b/gfx/gl/SharedSurfaceGLX.cpp
@@ -4,17 +4,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "SharedSurfaceGLX.h"
 #include "gfxXlibSurface.h"
 #include "GLXLibrary.h"
 #include "GLContextProvider.h"
 #include "GLContextGLX.h"
 #include "GLScreenBuffer.h"
-#include "mozilla/gfx/SourceSurfaceCairo.h"
 #include "mozilla/layers/LayersSurfaces.h"
 #include "mozilla/layers/ShadowLayerUtilsX11.h"
 #include "mozilla/layers/ISurfaceAllocator.h"
 #include "mozilla/X11Util.h"
 
 namespace mozilla {
 namespace gl {
 
@@ -79,48 +78,16 @@ SharedSurface_GLXDrawable::ToSurfaceDesc
 {
   if (!mXlibSurface)
       return false;
 
    *out_descriptor = layers::SurfaceDescriptorX11(mXlibSurface, mInSameProcess);
    return true;
 }
 
-bool
-SharedSurface_GLXDrawable::ReadbackBySharedHandle(gfx::DataSourceSurface* out_surface)
-{
-    MOZ_ASSERT(out_surface);
-    RefPtr<gfx::DataSourceSurface> dataSurf =
-        new gfx::DataSourceSurfaceCairo(mXlibSurface->CairoSurface());
-
-    gfx::DataSourceSurface::ScopedMap mapSrc(dataSurf, gfx::DataSourceSurface::READ);
-    if (!mapSrc.IsMapped()) {
-        return false;
-    }
-
-    gfx::DataSourceSurface::ScopedMap mapDest(out_surface, gfx::DataSourceSurface::WRITE);
-    if (!mapDest.IsMapped()) {
-        return false;
-    }
-
-    if (mapDest.GetStride() == mapSrc.GetStride()) {
-        memcpy(mapDest.GetData(),
-               mapSrc.GetData(),
-               out_surface->GetSize().height * mapDest.GetStride());
-    } else {
-        for (int32_t i = 0; i < dataSurf->GetSize().height; i++) {
-            memcpy(mapDest.GetData() + i * mapDest.GetStride(),
-                   mapSrc.GetData() + i * mapSrc.GetStride(),
-                   std::min(mapSrc.GetStride(), mapDest.GetStride()));
-        }
-    }
-
-    return true;
-}
-
 /* static */
 UniquePtr<SurfaceFactory_GLXDrawable>
 SurfaceFactory_GLXDrawable::Create(GLContext* prodGL,
                                    const SurfaceCaps& caps,
                                    const RefPtr<layers::ISurfaceAllocator>& allocator,
                                    const layers::TextureFlags& flags)
 {
     MOZ_ASSERT(caps.alpha, "GLX surfaces require an alpha channel!");
--- a/gfx/gl/SharedSurfaceGLX.h
+++ b/gfx/gl/SharedSurfaceGLX.h
@@ -27,18 +27,16 @@ public:
     virtual void Fence() override;
     virtual bool WaitSync() override { return true; }
     virtual bool PollSync() override { return true; }
 
     virtual void LockProdImpl() override;
     virtual void UnlockProdImpl() override;
 
     virtual bool ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) override;
-
-    virtual bool ReadbackBySharedHandle(gfx::DataSourceSurface* out_surface) override;
 private:
     SharedSurface_GLXDrawable(GLContext* gl,
                               const gfx::IntSize& size,
                               bool inSameProcess,
                               const RefPtr<gfxXlibSurface>& xlibSurface);
 
     RefPtr<gfxXlibSurface> mXlibSurface;
     bool mInSameProcess;
--- a/gfx/gl/SharedSurfaceGralloc.cpp
+++ b/gfx/gl/SharedSurfaceGralloc.cpp
@@ -278,63 +278,10 @@ SharedSurface_Gralloc::WaitForBufferOwne
 
 bool
 SharedSurface_Gralloc::ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor)
 {
     mTextureClient->MarkShared();
     return mTextureClient->ToSurfaceDescriptor(*out_descriptor);
 }
 
-bool
-SharedSurface_Gralloc::ReadbackBySharedHandle(gfx::DataSourceSurface* out_surface)
-{
-    MOZ_ASSERT(out_surface);
-    sp<GraphicBuffer> buffer = mTextureClient->GetGraphicBuffer();
-
-    const uint8_t* grallocData = nullptr;
-    auto result = buffer->lock(
-        GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_NEVER,
-        const_cast<void**>(reinterpret_cast<const void**>(&grallocData))
-    );
-
-    if (result == BAD_VALUE) {
-        return false;
-    }
-
-    gfx::DataSourceSurface::ScopedMap map(out_surface, gfx::DataSourceSurface::WRITE);
-    if (!map.IsMapped()) {
-        buffer->unlock();
-        return false;
-    }
-
-    uint32_t stride = buffer->getStride() * android::bytesPerPixel(buffer->getPixelFormat());
-    uint32_t height = buffer->getHeight();
-    uint32_t width = buffer->getWidth();
-    for (uint32_t i = 0; i < height; i++) {
-        memcpy(map.GetData() + i * map.GetStride(),
-               grallocData + i * stride, width * 4);
-    }
-
-    buffer->unlock();
-
-    android::PixelFormat srcFormat = buffer->getPixelFormat();
-    MOZ_ASSERT(srcFormat == PIXEL_FORMAT_RGBA_8888 ||
-               srcFormat == PIXEL_FORMAT_BGRA_8888 ||
-               srcFormat == PIXEL_FORMAT_RGBX_8888);
-    bool isSrcRGB = srcFormat == PIXEL_FORMAT_RGBA_8888 ||
-                    srcFormat == PIXEL_FORMAT_RGBX_8888;
-
-    gfx::SurfaceFormat destFormat = out_surface->GetFormat();
-    MOZ_ASSERT(destFormat == gfx::SurfaceFormat::R8G8B8X8 ||
-               destFormat == gfx::SurfaceFormat::R8G8B8A8 ||
-               destFormat == gfx::SurfaceFormat::B8G8R8X8 ||
-               destFormat == gfx::SurfaceFormat::B8G8R8A8);
-    bool isDestRGB = destFormat == gfx::SurfaceFormat::R8G8B8X8 ||
-                     destFormat == gfx::SurfaceFormat::R8G8B8A8;
-
-    if (isSrcRGB != isDestRGB) {
-        SwapRAndBComponents(out_surface);
-    }
-    return true;
-}
-
 } // namespace gl
 } // namespace mozilla
--- a/gfx/gl/SharedSurfaceGralloc.h
+++ b/gfx/gl/SharedSurfaceGralloc.h
@@ -70,18 +70,16 @@ public:
         return mProdTex;
     }
 
     layers::GrallocTextureClientOGL* GetTextureClient() {
         return mTextureClient;
     }
 
     virtual bool ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) override;
-
-    virtual bool ReadbackBySharedHandle(gfx::DataSourceSurface* out_surface) override;
 };
 
 class SurfaceFactory_Gralloc
     : public SurfaceFactory
 {
 public:
     SurfaceFactory_Gralloc(GLContext* prodGL, const SurfaceCaps& caps,
                            const RefPtr<layers::ISurfaceAllocator>& allocator,
--- a/gfx/gl/SharedSurfaceIO.cpp
+++ b/gfx/gl/SharedSurfaceIO.cpp
@@ -177,41 +177,16 @@ SharedSurface_IOSurface::ToSurfaceDescri
 {
     bool isOpaque = !mHasAlpha;
     *out_descriptor = layers::SurfaceDescriptorMacIOSurface(mIOSurf->GetIOSurfaceID(),
                                                             mIOSurf->GetContentsScaleFactor(),
                                                             isOpaque);
     return true;
 }
 
-bool
-SharedSurface_IOSurface::ReadbackBySharedHandle(gfx::DataSourceSurface* out_surface)
-{
-    MOZ_ASSERT(out_surface);
-    mIOSurf->Lock();
-    size_t bytesPerRow = mIOSurf->GetBytesPerRow();
-    size_t ioWidth = mIOSurf->GetDevicePixelWidth();
-    size_t ioHeight = mIOSurf->GetDevicePixelHeight();
-
-    const unsigned char* ioData = (unsigned char*)mIOSurf->GetBaseAddress();
-    gfx::DataSourceSurface::ScopedMap map(out_surface, gfx::DataSourceSurface::WRITE);
-    if (!map.IsMapped()) {
-        mIOSurf->Unlock();
-        return false;
-    }
-
-    for (size_t i = 0; i < ioHeight; i++) {
-        memcpy(map.GetData() + i * map.GetStride(),
-               ioData + i * bytesPerRow, ioWidth * 4);
-    }
-
-    mIOSurf->Unlock();
-    return true;
-}
-
 ////////////////////////////////////////////////////////////////////////
 // SurfaceFactory_IOSurface
 
 /*static*/ UniquePtr<SurfaceFactory_IOSurface>
 SurfaceFactory_IOSurface::Create(GLContext* gl, const SurfaceCaps& caps,
                                  const RefPtr<layers::ISurfaceAllocator>& allocator,
                                  const layers::TextureFlags& flags)
 {
--- a/gfx/gl/SharedSurfaceIO.h
+++ b/gfx/gl/SharedSurfaceIO.h
@@ -63,18 +63,16 @@ public:
         return mIOSurf;
     }
 
     virtual bool NeedsIndirectReads() const override {
         return true;
     }
 
     virtual bool ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) override;
-
-    virtual bool ReadbackBySharedHandle(gfx::DataSourceSurface* out_surface) override;
 };
 
 class SurfaceFactory_IOSurface : public SurfaceFactory
 {
 public:
     // Infallible.
     static UniquePtr<SurfaceFactory_IOSurface> Create(GLContext* gl,
                                                       const SurfaceCaps& caps,
deleted file mode 100644
--- a/gfx/layers/AsyncCanvasRenderer.cpp
+++ /dev/null
@@ -1,279 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* 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/. */
-
-#include "AsyncCanvasRenderer.h"
-
-#include "gfxUtils.h"
-#include "GLContext.h"
-#include "GLReadTexImageHelper.h"
-#include "GLScreenBuffer.h"
-#include "mozilla/dom/HTMLCanvasElement.h"
-#include "mozilla/layers/CanvasClient.h"
-#include "mozilla/layers/TextureClient.h"
-#include "mozilla/layers/TextureClientSharedSurface.h"
-#include "mozilla/ReentrantMonitor.h"
-#include "nsIRunnable.h"
-#include "nsThreadUtils.h"
-
-namespace mozilla {
-namespace layers {
-
-AsyncCanvasRenderer::AsyncCanvasRenderer()
-  : mHTMLCanvasElement(nullptr)
-  , mContext(nullptr)
-  , mGLContext(nullptr)
-  , mIsAlphaPremultiplied(true)
-  , mWidth(0)
-  , mHeight(0)
-  , mCanvasClientAsyncID(0)
-  , mCanvasClient(nullptr)
-  , mMutex("AsyncCanvasRenderer::mMutex")
-{
-  MOZ_COUNT_CTOR(AsyncCanvasRenderer);
-}
-
-AsyncCanvasRenderer::~AsyncCanvasRenderer()
-{
-  MOZ_COUNT_DTOR(AsyncCanvasRenderer);
-}
-
-void
-AsyncCanvasRenderer::NotifyElementAboutAttributesChanged()
-{
-  class Runnable final : public nsRunnable
-  {
-  public:
-    explicit Runnable(AsyncCanvasRenderer* aRenderer)
-      : mRenderer(aRenderer)
-    {}
-
-    NS_IMETHOD Run()
-    {
-      if (mRenderer) {
-        dom::HTMLCanvasElement::SetAttrFromAsyncCanvasRenderer(mRenderer);
-      }
-
-      return NS_OK;
-    }
-
-    void Revoke()
-    {
-      mRenderer = nullptr;
-    }
-
-  private:
-    nsRefPtr<AsyncCanvasRenderer> mRenderer;
-  };
-
-  nsRefPtr<nsRunnable> runnable = new Runnable(this);
-  nsresult rv = NS_DispatchToMainThread(runnable);
-  if (NS_FAILED(rv)) {
-    NS_WARNING("Failed to dispatch a runnable to the main-thread.");
-  }
-}
-
-void
-AsyncCanvasRenderer::NotifyElementAboutInvalidation()
-{
-  class Runnable final : public nsRunnable
-  {
-  public:
-    explicit Runnable(AsyncCanvasRenderer* aRenderer)
-      : mRenderer(aRenderer)
-    {}
-
-    NS_IMETHOD Run()
-    {
-      if (mRenderer) {
-        dom::HTMLCanvasElement::InvalidateFromAsyncCanvasRenderer(mRenderer);
-      }
-
-      return NS_OK;
-    }
-
-    void Revoke()
-    {
-      mRenderer = nullptr;
-    }
-
-  private:
-    nsRefPtr<AsyncCanvasRenderer> mRenderer;
-  };
-
-  nsRefPtr<nsRunnable> runnable = new Runnable(this);
-  nsresult rv = NS_DispatchToMainThread(runnable);
-  if (NS_FAILED(rv)) {
-    NS_WARNING("Failed to dispatch a runnable to the main-thread.");
-  }
-}
-
-void
-AsyncCanvasRenderer::SetCanvasClient(CanvasClient* aClient)
-{
-  mCanvasClient = aClient;
-  if (aClient) {
-    mCanvasClientAsyncID = aClient->GetAsyncID();
-  } else {
-    mCanvasClientAsyncID = 0;
-  }
-}
-
-void
-AsyncCanvasRenderer::SetActiveThread()
-{
-  MutexAutoLock lock(mMutex);
-  mActiveThread = NS_GetCurrentThread();
-}
-
-void
-AsyncCanvasRenderer::ResetActiveThread()
-{
-  MutexAutoLock lock(mMutex);
-  mActiveThread = nullptr;
-}
-
-already_AddRefed<nsIThread>
-AsyncCanvasRenderer::GetActiveThread()
-{
-  MutexAutoLock lock(mMutex);
-  nsCOMPtr<nsIThread> result = mActiveThread;
-  return result.forget();
-}
-
-void
-AsyncCanvasRenderer::CopyFromTextureClient(TextureClient* aTextureClient)
-{
-  MutexAutoLock lock(mMutex);
-  RefPtr<BufferTextureClient> buffer = static_cast<BufferTextureClient*>(aTextureClient);
-  if (!buffer->Lock(layers::OpenMode::OPEN_READ)) {
-    return;
-  }
-
-  const gfx::IntSize& size = aTextureClient->GetSize();
-  // This buffer would be used later for content rendering. So we choose
-  // B8G8R8A8 format here.
-  const gfx::SurfaceFormat format = gfx::SurfaceFormat::B8G8R8A8;
-  // Avoid to create buffer every time.
-  if (!mSurfaceForBasic ||
-      size != mSurfaceForBasic->GetSize() ||
-      format != mSurfaceForBasic->GetFormat())
-  {
-    uint32_t stride = gfx::GetAlignedStride<8>(size.width * BytesPerPixel(format));
-    mSurfaceForBasic = gfx::Factory::CreateDataSourceSurfaceWithStride(size, format, stride);
-  }
-
-  const uint8_t* lockedBytes = buffer->GetLockedData();
-  gfx::DataSourceSurface::ScopedMap map(mSurfaceForBasic,
-                                        gfx::DataSourceSurface::MapType::WRITE);
-  if (!map.IsMapped()) {
-    buffer->Unlock();
-    return;
-  }
-
-  memcpy(map.GetData(), lockedBytes, map.GetStride() * mSurfaceForBasic->GetSize().height);
-  buffer->Unlock();
-
-  if (mSurfaceForBasic->GetFormat() == gfx::SurfaceFormat::R8G8B8A8 ||
-      mSurfaceForBasic->GetFormat() == gfx::SurfaceFormat::R8G8B8X8) {
-    gl::SwapRAndBComponents(mSurfaceForBasic);
-  }
-}
-
-already_AddRefed<gfx::DataSourceSurface>
-AsyncCanvasRenderer::UpdateTarget()
-{
-  if (!mGLContext) {
-    return nullptr;
-  }
-
-  gl::SharedSurface* frontbuffer = nullptr;
-  gl::GLScreenBuffer* screen = mGLContext->Screen();
-  const auto& front = screen->Front();
-  if (front) {
-    frontbuffer = front->Surf();
-  }
-
-  if (!frontbuffer) {
-    return nullptr;
-  }
-
-  if (frontbuffer->mType == gl::SharedSurfaceType::Basic) {
-    return nullptr;
-  }
-
-  const gfx::IntSize& size = frontbuffer->mSize;
-  // This buffer would be used later for content rendering. So we choose
-  // B8G8R8A8 format here.
-  const gfx::SurfaceFormat format = gfx::SurfaceFormat::B8G8R8A8;
-  uint32_t stride = gfx::GetAlignedStride<8>(size.width * BytesPerPixel(format));
-  RefPtr<gfx::DataSourceSurface> surface =
-    gfx::Factory::CreateDataSourceSurfaceWithStride(size, format, stride);
-
-
-  if (NS_WARN_IF(!surface)) {
-    return nullptr;
-  }
-
-  if (!frontbuffer->ReadbackBySharedHandle(surface)) {
-    return nullptr;
-  }
-
-  bool needsPremult = frontbuffer->mHasAlpha && !mIsAlphaPremultiplied;
-  if (needsPremult) {
-    gfxUtils::PremultiplyDataSurface(surface, surface);
-  }
-
-  return surface.forget();
-}
-
-already_AddRefed<gfx::DataSourceSurface>
-AsyncCanvasRenderer::GetSurface()
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  MutexAutoLock lock(mMutex);
-  if (mSurfaceForBasic) {
-    // Since SourceSurface isn't thread-safe, we need copy to a new SourceSurface.
-    RefPtr<gfx::DataSourceSurface> result =
-      gfx::Factory::CreateDataSourceSurfaceWithStride(mSurfaceForBasic->GetSize(),
-                                                      mSurfaceForBasic->GetFormat(),
-                                                      mSurfaceForBasic->Stride());
-
-    gfx::DataSourceSurface::ScopedMap srcMap(mSurfaceForBasic, gfx::DataSourceSurface::READ);
-    gfx::DataSourceSurface::ScopedMap dstMap(result, gfx::DataSourceSurface::WRITE);
-
-    if (NS_WARN_IF(!srcMap.IsMapped()) ||
-        NS_WARN_IF(!dstMap.IsMapped())) {
-      return nullptr;
-    }
-
-    memcpy(dstMap.GetData(),
-           srcMap.GetData(),
-           srcMap.GetStride() * mSurfaceForBasic->GetSize().height);
-    return result.forget();
-  } else {
-    return UpdateTarget();
-  }
-}
-
-nsresult
-AsyncCanvasRenderer::GetInputStream(const char *aMimeType,
-                                    const char16_t *aEncoderOptions,
-                                    nsIInputStream **aStream)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  RefPtr<gfx::DataSourceSurface> surface = GetSurface();
-  if (!surface) {
-    return NS_ERROR_FAILURE;
-  }
-
-  // Handle y flip.
-  RefPtr<gfx::DataSourceSurface> dataSurf = gl::YInvertImageSurface(surface);
-
-  return gfxUtils::GetInputStream(dataSurf, false, aMimeType, aEncoderOptions, aStream);
-}
-
-} // namespace layers
-} // namespace mozilla
deleted file mode 100644
--- a/gfx/layers/AsyncCanvasRenderer.h
+++ /dev/null
@@ -1,169 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* 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 MOZILLA_LAYERS_ASYNCCANVASRENDERER_H_
-#define MOZILLA_LAYERS_ASYNCCANVASRENDERER_H_
-
-#include "LayersTypes.h"
-#include "mozilla/gfx/Point.h"          // for IntSize
-#include "mozilla/Mutex.h"
-#include "mozilla/RefPtr.h"             // for nsAutoPtr, nsRefPtr, etc
-#include "nsCOMPtr.h"                   // for nsCOMPtr
-
-class nsICanvasRenderingContextInternal;
-class nsIInputStream;
-class nsIThread;
-
-namespace mozilla {
-
-namespace gfx {
-class DataSourceSurface;
-}
-
-namespace gl {
-class GLContext;
-}
-
-namespace dom {
-class HTMLCanvasElement;
-}
-
-namespace layers {
-
-class CanvasClient;
-class TextureClient;
-
-/**
- * Since HTMLCanvasElement and OffscreenCanvas are not thread-safe, we create
- * AsyncCanvasRenderer which is thread-safe wrapper object for communicating
- * among main, worker and ImageBridgeChild threads.
- *
- * Each HTMLCanvasElement object is responsible for creating
- * AsyncCanvasRenderer object. Once Canvas is transfered to worker,
- * OffscreenCanvas will keep reference pointer of this object.
- *
- * Sometimes main thread needs AsyncCanvasRenderer's result, such as layers
- * fallback to BasicLayerManager or calling toDataURL in Javascript. Simply call
- * GetSurface() in main thread will readback the result to mSurface.
- *
- * If layers backend is LAYERS_CLIENT, this object will pass to ImageBridgeChild
- * for submitting frames to Compositor.
- */
-class AsyncCanvasRenderer final
-{
-  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AsyncCanvasRenderer)
-
-public:
-  AsyncCanvasRenderer();
-
-  void NotifyElementAboutAttributesChanged();
-  void NotifyElementAboutInvalidation();
-
-  void SetCanvasClient(CanvasClient* aClient);
-
-  void SetWidth(uint32_t aWidth)
-  {
-    mWidth = aWidth;
-  }
-
-  void SetHeight(uint32_t aHeight)
-  {
-    mHeight = aHeight;
-  }
-
-  void SetIsAlphaPremultiplied(bool aIsAlphaPremultiplied)
-  {
-    mIsAlphaPremultiplied = aIsAlphaPremultiplied;
-  }
-
-  // Active thread means the thread which spawns GLContext.
-  void SetActiveThread();
-  void ResetActiveThread();
-
-  // This will readback surface and return the surface
-  // in the DataSourceSurface.
-  // Can be called in main thread only.
-  already_AddRefed<gfx::DataSourceSurface> GetSurface();
-
-  // For SharedSurface_Basic case, before the frame sending to the compositor,
-  // we readback it to a texture client because SharedSurface_Basic cannot shared.
-  // We don't want to readback it again here, so just copy the content of that
-  // texture client here to avoid readback again.
-  void CopyFromTextureClient(TextureClient *aClient);
-
-  // Readback current WebGL's content and convert it to InputStream. This
-  // function called GetSurface implicitly and GetSurface handles only get
-  // called in the main thread. So this function can be called in main thread.
-  nsresult
-  GetInputStream(const char *aMimeType,
-                 const char16_t *aEncoderOptions,
-                 nsIInputStream **aStream);
-
-  gfx::IntSize GetSize() const
-  {
-    return gfx::IntSize(mWidth, mHeight);
-  }
-
-  uint64_t GetCanvasClientAsyncID() const
-  {
-    return mCanvasClientAsyncID;
-  }
-
-  CanvasClient* GetCanvasClient() const
-  {
-    return mCanvasClient;
-  }
-
-  already_AddRefed<nsIThread> GetActiveThread();
-
-  // The lifetime is controllered by HTMLCanvasElement.
-  // Only accessed in main thread.
-  dom::HTMLCanvasElement* mHTMLCanvasElement;
-
-  // Only accessed in active thread.
-  nsICanvasRenderingContextInternal* mContext;
-
-  // We need to keep a reference to the context around here, otherwise the
-  // canvas' surface texture destructor will deref and destroy it too early
-  // Only accessed in active thread.
-  RefPtr<gl::GLContext> mGLContext;
-private:
-
-  virtual ~AsyncCanvasRenderer();
-
-  // Readback current WebGL's content and return it as DataSourceSurface.
-  already_AddRefed<gfx::DataSourceSurface> UpdateTarget();
-
-  bool mIsAlphaPremultiplied;
-
-  uint32_t mWidth;
-  uint32_t mHeight;
-  uint64_t mCanvasClientAsyncID;
-
-  // The lifetime of this pointer is controlled by OffscreenCanvas
-  // Can be accessed in active thread and ImageBridge thread.
-  // But we never accessed it at the same time on both thread. So no
-  // need to protect this member.
-  CanvasClient* mCanvasClient;
-
-  // When backend is LAYER_BASIC and SharedSurface type is Basic.
-  // CanvasClient will readback the GLContext to a TextureClient
-  // in order to send frame to compositor. To avoid readback again,
-  // we copy from this TextureClient to this mSurfaceForBasic directly
-  // by calling CopyFromTextureClient().
-  RefPtr<gfx::DataSourceSurface> mSurfaceForBasic;
-
-  // Protect non thread-safe objects.
-  Mutex mMutex;
-
-  // Can be accessed in any thread, need protect by mutex.
-  nsCOMPtr<nsIThread> mActiveThread;
-};
-
-} // namespace layers
-} // namespace mozilla
-
-#endif // MOZILLA_LAYERS_ASYNCCANVASRENDERER_H_
--- a/gfx/layers/CopyableCanvasLayer.cpp
+++ b/gfx/layers/CopyableCanvasLayer.cpp
@@ -59,53 +59,48 @@ CopyableCanvasLayer::Initialize(const Da
 
     if (aData.mFrontbufferGLTex) {
       gfx::IntSize size(aData.mSize.width, aData.mSize.height);
       mGLFrontbuffer = SharedSurface_Basic::Wrap(aData.mGLContext, size, aData.mHasAlpha,
                                                  aData.mFrontbufferGLTex);
     }
   } else if (aData.mBufferProvider) {
     mBufferProvider = aData.mBufferProvider;
-  } else if (aData.mRenderer) {
-    mAsyncRenderer = aData.mRenderer;
-    mOriginPos = gl::OriginPos::BottomLeft;
   } else {
     MOZ_CRASH("CanvasLayer created without mSurface, mDrawTarget or mGLContext?");
   }
 
   mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height);
 }
 
 bool
 CopyableCanvasLayer::IsDataValid(const Data& aData)
 {
   return mGLContext == aData.mGLContext;
 }
 
 void
 CopyableCanvasLayer::UpdateTarget(DrawTarget* aDestTarget)
 {
-  if (mAsyncRenderer) {
-    mSurface = mAsyncRenderer->GetSurface();
-  } else if (mBufferProvider) {
+  if (mBufferProvider) {
     mSurface = mBufferProvider->GetSnapshot();
   }
 
   if (!mGLContext && aDestTarget) {
     NS_ASSERTION(mSurface, "Must have surface to draw!");
     if (mSurface) {
       aDestTarget->CopySurface(mSurface,
                                IntRect(0, 0, mBounds.width, mBounds.height),
                                IntPoint(0, 0));
       mSurface = nullptr;
     }
     return;
   }
 
-  if (mBufferProvider || mAsyncRenderer) {
+  if (mBufferProvider) {
     return;
   }
 
   MOZ_ASSERT(mGLContext);
 
   SharedSurface* frontbuffer = nullptr;
   if (mGLFrontbuffer) {
     frontbuffer = mGLFrontbuffer.get();
--- a/gfx/layers/LayerTreeInvalidation.cpp
+++ b/gfx/layers/LayerTreeInvalidation.cpp
@@ -380,17 +380,17 @@ struct ColorLayerProperties : public Lay
 
     return result;
   }
 
   Color mColor;
   IntRect mBounds;
 };
 
-static ImageHost* GetImageHost(Layer* aLayer)
+static ImageHost* GetImageHost(ImageLayer* aLayer)
 {
   LayerComposite* composite = aLayer->AsLayerComposite();
   if (composite) {
     return static_cast<ImageHost*>(composite->GetCompositableHost());
   }
   return nullptr;
 }
 
@@ -460,44 +460,16 @@ struct ImageLayerProperties : public Lay
   GraphicsFilter mFilter;
   gfx::IntSize mScaleToSize;
   ScaleMode mScaleMode;
   int32_t mLastProducerID;
   int32_t mLastFrameID;
   bool mIsMask;
 };
 
-struct CanvasLayerProperties : public LayerPropertiesBase
-{
-  explicit CanvasLayerProperties(CanvasLayer* aCanvas)
-    : LayerPropertiesBase(aCanvas)
-    , mImageHost(GetImageHost(aCanvas))
-  {
-    mFrameID = mImageHost ? mImageHost->GetFrameID() : -1;
-  }
-
-  virtual nsIntRegion ComputeChangeInternal(NotifySubDocInvalidationFunc aCallback,
-                                            bool& aGeometryChanged)
-  {
-    CanvasLayer* canvasLayer = static_cast<CanvasLayer*>(mLayer.get());
-
-    ImageHost* host = GetImageHost(canvasLayer);
-    if (host && host->GetFrameID() != mFrameID) {
-      aGeometryChanged = true;
-
-      return NewTransformedBounds();
-    }
-
-    return IntRect();
-  }
-
-  nsRefPtr<ImageHost> mImageHost;
-  int32_t mFrameID;
-};
-
 UniquePtr<LayerPropertiesBase>
 CloneLayerTreePropertiesInternal(Layer* aRoot, bool aIsMask /* = false */)
 {
   if (!aRoot) {
     return MakeUnique<LayerPropertiesBase>();
   }
 
   MOZ_ASSERT(!aIsMask || aRoot->GetType() == Layer::TYPE_IMAGE);
@@ -506,17 +478,16 @@ CloneLayerTreePropertiesInternal(Layer* 
     case Layer::TYPE_CONTAINER:
     case Layer::TYPE_REF:
       return MakeUnique<ContainerLayerProperties>(aRoot->AsContainerLayer());
     case Layer::TYPE_COLOR:
       return MakeUnique<ColorLayerProperties>(static_cast<ColorLayer*>(aRoot));
     case Layer::TYPE_IMAGE:
       return MakeUnique<ImageLayerProperties>(static_cast<ImageLayer*>(aRoot), aIsMask);
     case Layer::TYPE_CANVAS:
-      return MakeUnique<CanvasLayerProperties>(static_cast<CanvasLayer*>(aRoot));
     case Layer::TYPE_READBACK:
     case Layer::TYPE_SHADOW:
     case Layer::TYPE_PAINTED:
       return MakeUnique<LayerPropertiesBase>(aRoot);
   }
 
   MOZ_ASSERT_UNREACHABLE("Unexpected root layer type");
   return MakeUnique<LayerPropertiesBase>(aRoot);
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -20,17 +20,16 @@
 #include "gfxUtils.h"                   // for gfxUtils, etc
 #include "gfx2DGlue.h"
 #include "mozilla/DebugOnly.h"          // for DebugOnly
 #include "mozilla/Telemetry.h"          // for Accumulate
 #include "mozilla/dom/Animation.h"      // for ComputedTimingFunction
 #include "mozilla/gfx/2D.h"             // for DrawTarget
 #include "mozilla/gfx/BaseSize.h"       // for BaseSize
 #include "mozilla/gfx/Matrix.h"         // for Matrix4x4
-#include "mozilla/layers/AsyncCanvasRenderer.h"
 #include "mozilla/layers/Compositor.h"  // for Compositor
 #include "mozilla/layers/CompositorTypes.h"
 #include "mozilla/layers/LayerManagerComposite.h"  // for LayerComposite
 #include "mozilla/layers/LayerMetricsWrapper.h" // for LayerMetricsWrapper
 #include "mozilla/layers/LayersMessages.h"  // for TransformFunction, etc
 #include "mozilla/layers/PersistentBufferProvider.h"
 #include "nsAString.h"
 #include "nsCSSValue.h"                 // for nsCSSValue::Array, etc
@@ -2100,29 +2099,16 @@ ColorLayer::DumpPacket(layerscope::Layer
   Layer::DumpPacket(aPacket, aParent);
   // Get this layer data
   using namespace layerscope;
   LayersPacket::Layer* layer = aPacket->mutable_layer(aPacket->layer_size()-1);
   layer->set_type(LayersPacket::Layer::ColorLayer);
   layer->set_color(mColor.ToABGR());
 }
 
-CanvasLayer::CanvasLayer(LayerManager* aManager, void* aImplData)
-  : Layer(aManager, aImplData)
-  , mPreTransCallback(nullptr)
-  , mPreTransCallbackData(nullptr)
-  , mPostTransCallback(nullptr)
-  , mPostTransCallbackData(nullptr)
-  , mFilter(GraphicsFilter::FILTER_GOOD)
-  , mDirty(false)
-{}
-
-CanvasLayer::~CanvasLayer()
-{}
-
 void
 CanvasLayer::PrintInfo(std::stringstream& aStream, const char* aPrefix)
 {
   Layer::PrintInfo(aStream, aPrefix);
   if (mFilter != GraphicsFilter::FILTER_GOOD) {
     AppendToString(aStream, mFilter, " [filter=", "]");
   }
 }
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -69,17 +69,16 @@ class DrawTarget;
 namespace dom {
 class OverfillCallback;
 } // namespace dom
 
 namespace layers {
 
 class Animation;
 class AnimationData;
-class AsyncCanvasRenderer;
 class AsyncPanZoomController;
 class ClientLayerManager;
 class Layer;
 class LayerMetricsWrapper;
 class PaintedLayer;
 class ContainerLayer;
 class ImageLayer;
 class ColorLayer;
@@ -2264,27 +2263,25 @@ protected:
  * must not be modified during a layer transaction.
  */
 class CanvasLayer : public Layer {
 public:
   struct Data {
     Data()
       : mBufferProvider(nullptr)
       , mGLContext(nullptr)
-      , mRenderer(nullptr)
       , mFrontbufferGLTex(0)
       , mSize(0,0)
       , mHasAlpha(false)
       , mIsGLAlphaPremult(true)
     { }
 
-    // One of these three must be specified for Canvas2D, but never more than one
+    // One of these two must be specified for Canvas2D, but never both
     PersistentBufferProvider* mBufferProvider; // A BufferProvider for the Canvas contents
     mozilla::gl::GLContext* mGLContext; // or this, for GL.
-    AsyncCanvasRenderer* mRenderer; // or this, for OffscreenCanvas
 
     // Frontbuffer override
     uint32_t mFrontbufferGLTex;
 
     // The size of the canvas content
     gfx::IntSize mSize;
 
     // Whether the canvas drawingbuffer has an alpha channel.
@@ -2390,24 +2387,26 @@ public:
     // transform, then we'd snap again when compositing the PaintedLayer).
     mEffectiveTransform =
         SnapTransform(GetLocalTransform(), gfxRect(0, 0, mBounds.width, mBounds.height),
                       nullptr)*
         SnapTransformTranslation(aTransformToSurface, nullptr);
     ComputeEffectiveTransformForMaskLayers(aTransformToSurface);
   }
 
-  bool GetIsAsyncRenderer() const
-  {
-    return !!mAsyncRenderer;
-  }
-
 protected:
-  CanvasLayer(LayerManager* aManager, void* aImplData);
-  virtual ~CanvasLayer();
+  CanvasLayer(LayerManager* aManager, void* aImplData)
+    : Layer(aManager, aImplData)
+    , mPreTransCallback(nullptr)
+    , mPreTransCallbackData(nullptr)
+    , mPostTransCallback(nullptr)
+    , mPostTransCallbackData(nullptr)
+    , mFilter(GraphicsFilter::FILTER_GOOD)
+    , mDirty(false)
+  {}
 
   virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix) override;
 
   virtual void DumpPacket(layerscope::LayersPacket* aPacket, const void* aParent) override;
 
   void FireDidTransactionCallback()
   {
     if (mPostTransCallback) {
@@ -2419,17 +2418,16 @@ protected:
    * 0, 0, canvaswidth, canvasheight
    */
   gfx::IntRect mBounds;
   PreTransactionCallback* mPreTransCallback;
   void* mPreTransCallbackData;
   DidTransactionCallback mPostTransCallback;
   void* mPostTransCallbackData;
   GraphicsFilter mFilter;
-  nsRefPtr<AsyncCanvasRenderer> mAsyncRenderer;
 
 private:
   /**
    * Set to true in Updated(), cleared during a transaction.
    */
   bool mDirty;
 };
 
--- a/gfx/layers/basic/BasicCanvasLayer.cpp
+++ b/gfx/layers/basic/BasicCanvasLayer.cpp
@@ -1,15 +1,14 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 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/. */
 
 #include "BasicCanvasLayer.h"
-#include "AsyncCanvasRenderer.h"
 #include "basic/BasicLayers.h"          // for BasicLayerManager
 #include "basic/BasicLayersImpl.h"      // for GetEffectiveOperator
 #include "mozilla/mozalloc.h"           // for operator new
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsCOMPtr.h"                   // for already_AddRefed
 #include "nsISupportsImpl.h"            // for Layer::AddRef, etc
 #include "gfx2DGlue.h"
 
--- a/gfx/layers/client/CanvasClient.cpp
+++ b/gfx/layers/client/CanvasClient.cpp
@@ -8,17 +8,16 @@
 #include "ClientCanvasLayer.h"          // for ClientCanvasLayer
 #include "GLContext.h"                  // for GLContext
 #include "GLScreenBuffer.h"             // for GLScreenBuffer
 #include "ScopedGLHelpers.h"
 #include "gfx2DGlue.h"                  // for ImageFormatToSurfaceFormat
 #include "gfxPlatform.h"                // for gfxPlatform
 #include "GLReadTexImageHelper.h"
 #include "mozilla/gfx/BaseSize.h"       // for BaseSize
-#include "mozilla/layers/AsyncCanvasRenderer.h"
 #include "mozilla/layers/CompositableForwarder.h"
 #include "mozilla/layers/CompositorChild.h" // for CompositorChild
 #include "mozilla/layers/GrallocTextureClient.h"
 #include "mozilla/layers/LayersTypes.h"
 #include "mozilla/layers/TextureClient.h"  // for TextureClient, etc
 #include "mozilla/layers/TextureClientOGL.h"
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsDebug.h"                    // for printf_stderr, NS_ASSERTION
@@ -34,43 +33,25 @@ namespace layers {
 /* static */ already_AddRefed<CanvasClient>
 CanvasClient::CreateCanvasClient(CanvasClientType aType,
                                  CompositableForwarder* aForwarder,
                                  TextureFlags aFlags)
 {
   switch (aType) {
   case CanvasClientTypeShSurf:
     return MakeAndAddRef<CanvasClientSharedSurface>(aForwarder, aFlags);
-  case CanvasClientAsync:
-    return MakeAndAddRef<CanvasClientBridge>(aForwarder, aFlags);
+    break;
+
   default:
     return MakeAndAddRef<CanvasClient2D>(aForwarder, aFlags);
     break;
   }
 }
 
 void
-CanvasClientBridge::UpdateAsync(AsyncCanvasRenderer* aRenderer)
-{
-  if (!GetForwarder() || !mLayer || !aRenderer ||
-      !aRenderer->GetCanvasClient()) {
-    return;
-  }
-
-  uint64_t asyncID = aRenderer->GetCanvasClientAsyncID();
-  if (asyncID == 0 || mAsyncID == asyncID) {
-    return;
-  }
-
-  static_cast<ShadowLayerForwarder*>(GetForwarder())
-    ->AttachAsyncCompositable(asyncID, mLayer);
-  mAsyncID = asyncID;
-}
-
-void
 CanvasClient2D::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
 {
   AutoRemoveTexture autoRemove(this);
   if (mBuffer &&
       (mBuffer->IsImmutable() || mBuffer->GetSize() != aSize)) {
     autoRemove.mTexture = mBuffer;
     mBuffer = nullptr;
   }
@@ -120,17 +101,16 @@ CanvasClient2D::Update(gfx::IntSize aSiz
     return;
   }
 
   if (updated) {
     nsAutoTArray<CompositableForwarder::TimedTextureClient,1> textures;
     CompositableForwarder::TimedTextureClient* t = textures.AppendElement();
     t->mTextureClient = mBuffer;
     t->mPictureRect = nsIntRect(nsIntPoint(0, 0), mBuffer->GetSize());
-    t->mFrameID = mFrameID;
     GetForwarder()->UseTextures(this, textures);
     mBuffer->SyncWithObject(GetForwarder()->GetSyncObject());
   }
 }
 
 already_AddRefed<TextureClient>
 CanvasClient2D::CreateTextureClientForCanvas(gfx::SurfaceFormat aFormat,
                                              gfx::IntSize aSize,
@@ -336,48 +316,23 @@ CloneSurface(gl::SharedSurface* src, gl:
     SharedSurface::ProdCopy(src, dest->Surf(), factory);
     dest->Surf()->Fence();
     return dest.forget();
 }
 
 void
 CanvasClientSharedSurface::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
 {
-  Renderer renderer;
-  renderer.construct<ClientCanvasLayer*>(aLayer);
-  UpdateRenderer(aSize, renderer);
-}
-
-void
-CanvasClientSharedSurface::UpdateAsync(AsyncCanvasRenderer* aRenderer)
-{
-  Renderer renderer;
-  renderer.construct<AsyncCanvasRenderer*>(aRenderer);
-  UpdateRenderer(aRenderer->GetSize(), renderer);
-}
-
-void
-CanvasClientSharedSurface::UpdateRenderer(gfx::IntSize aSize, Renderer& aRenderer)
-{
-  GLContext* gl = nullptr;
-  ClientCanvasLayer* layer = nullptr;
-  AsyncCanvasRenderer* asyncRenderer = nullptr;
-  if (aRenderer.constructed<ClientCanvasLayer*>()) {
-    layer = aRenderer.ref<ClientCanvasLayer*>();
-    gl = layer->mGLContext;
-  } else {
-    asyncRenderer = aRenderer.ref<AsyncCanvasRenderer*>();
-    gl = asyncRenderer->mGLContext;
-  }
+  auto gl = aLayer->mGLContext;
   gl->MakeCurrent();
 
   RefPtr<TextureClient> newFront;
 
-  if (layer && layer->mGLFrontbuffer) {
-    mShSurfClient = CloneSurface(layer->mGLFrontbuffer.get(), layer->mFactory.get());
+  if (aLayer->mGLFrontbuffer) {
+    mShSurfClient = CloneSurface(aLayer->mGLFrontbuffer.get(), aLayer->mFactory.get());
     if (!mShSurfClient) {
       gfxCriticalError() << "Invalid canvas front buffer";
       return;
     }
   } else {
     mShSurfClient = gl->Screen()->Front();
     if (!mShSurfClient) {
       return;
@@ -391,96 +346,69 @@ CanvasClientSharedSurface::UpdateRendere
 
   // Readback if needed.
   mReadbackClient = nullptr;
 
   auto forwarder = GetForwarder();
 
   bool needsReadback = (surf->mType == SharedSurfaceType::Basic);
   if (needsReadback) {
-    TextureFlags flags = TextureFlags::IMMUTABLE;
+    TextureFlags flags = aLayer->Flags() |
+                         TextureFlags::IMMUTABLE;
 
-    CompositableForwarder* shadowForwarder = nullptr;
-    if (layer) {
-      flags |= layer->Flags();
-      shadowForwarder = layer->ClientManager()->AsShadowForwarder();
-    } else {
-      MOZ_ASSERT(asyncRenderer);
-      flags |= mTextureFlags;
-      shadowForwarder = GetForwarder();
-    }
-
+    auto manager = aLayer->ClientManager();
+    auto shadowForwarder = manager->AsShadowForwarder();
     auto layersBackend = shadowForwarder->GetCompositorBackendType();
     mReadbackClient = TexClientFromReadback(surf, forwarder, flags, layersBackend);
 
-    if (asyncRenderer) {
-      // Above codes will readback the GLContext to mReadbackClient
-      // in order to send frame to compositor. We copy from this
-      // TextureClient directly by calling CopyFromTextureClient().
-      // Therefore, if main-thread want the content of GLContext,
-      // it don't have to readback it again.
-      asyncRenderer->CopyFromTextureClient(mReadbackClient);
-    }
-
     newFront = mReadbackClient;
   } else {
     mReadbackClient = nullptr;
   }
 
   MOZ_ASSERT(newFront);
   if (!newFront) {
     // May happen in a release build in case of memory pressure.
     gfxCriticalError() << "Failed to allocate a TextureClient for SharedSurface Canvas. Size: " << aSize;
     return;
   }
 
-  mNewFront = newFront;
-}
-
-void
-CanvasClientSharedSurface::Updated()
-{
-  auto forwarder = GetForwarder();
-
 #ifndef MOZ_WIDGET_GONK
   if (mFront) {
     if (mFront->GetFlags() & TextureFlags::RECYCLE) {
       mFront->WaitForCompositorRecycle();
     }
   }
 #else
   // AutoRemoveTexture does the followings.
   // - Ensure to deliver FenceHandle from TextureHost to TextureClient, before
   //   next TextureClient usage.
   // - Control TextureClient's recycling timing.
   // - Call RemoveTexture() after newFront's UseTextures() call.
   //   It could improve performance of Host side's EGL handling on gonk
   AutoRemoveTexture autoRemove(this);
-  if (mFront && mFront != mNewFront) {
+  if (mFront && mFront != newFront) {
     autoRemove.mTexture = mFront;
   }
 #endif
 
-  mFront = mNewFront;
-  mNewFront = nullptr;
+  mFront = newFront;
 
   // Add the new TexClient.
   MOZ_ALWAYS_TRUE( AddTextureClient(mFront) );
 
   nsAutoTArray<CompositableForwarder::TimedTextureClient,1> textures;
   CompositableForwarder::TimedTextureClient* t = textures.AppendElement();
   t->mTextureClient = mFront;
   t->mPictureRect = nsIntRect(nsIntPoint(0, 0), mFront->GetSize());
-  t->mFrameID = mFrameID;
   forwarder->UseTextures(this, textures);
 }
 
 void
 CanvasClientSharedSurface::ClearSurfaces()
 {
   mFront = nullptr;
-  mNewFront = nullptr;
   mShSurfClient = nullptr;
   mReadbackClient = nullptr;
 }
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/client/CanvasClient.h
+++ b/gfx/layers/client/CanvasClient.h
@@ -8,83 +8,61 @@
 
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
 #include "mozilla/Attributes.h"         // for override
 #include "mozilla/RefPtr.h"             // for RefPtr, already_AddRefed
 #include "mozilla/layers/CompositableClient.h"  // for CompositableClient
 #include "mozilla/layers/CompositorTypes.h"  // for TextureInfo, etc
 #include "mozilla/layers/LayersSurfaces.h"  // for SurfaceDescriptor
 #include "mozilla/layers/TextureClient.h"  // for TextureClient, etc
-
-// Fix X11 header brain damage that conflicts with MaybeOneOf::None
-#undef None
-#include "mozilla/MaybeOneOf.h"
-
 #include "mozilla/mozalloc.h"           // for operator delete
 
 #include "mozilla/gfx/Point.h"          // for IntSize
 #include "mozilla/gfx/Types.h"          // for SurfaceFormat
 
 namespace mozilla {
 namespace layers {
 
-class AsyncCanvasRenderer;
 class ClientCanvasLayer;
 class CompositableForwarder;
-class ShadowableLayer;
 class SharedSurfaceTextureClient;
 
 /**
  * Compositable client for 2d and webgl canvas.
  */
 class CanvasClient : public CompositableClient
 {
 public:
-  typedef MaybeOneOf<ClientCanvasLayer*, AsyncCanvasRenderer*> Renderer;
-
   /**
    * Creates, configures, and returns a new canvas client. If necessary, a
    * message will be sent to the compositor to create a corresponding image
    * host.
    */
   enum CanvasClientType {
     CanvasClientSurface,
     CanvasClientGLContext,
     CanvasClientTypeShSurf,
-    CanvasClientAsync, // webgl on workers
   };
   static already_AddRefed<CanvasClient> CreateCanvasClient(CanvasClientType aType,
                                                        CompositableForwarder* aFwd,
                                                        TextureFlags aFlags);
 
   CanvasClient(CompositableForwarder* aFwd, TextureFlags aFlags)
     : CompositableClient(aFwd, aFlags)
-    , mFrameID(0)
   {
     mTextureFlags = aFlags;
   }
 
   virtual ~CanvasClient() {}
 
   virtual void Clear() {};
 
   virtual void Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer) = 0;
 
-  virtual bool AddTextureClient(TextureClient* aTexture) override
-  {
-    ++mFrameID;
-    return CompositableClient::AddTextureClient(aTexture);
-  }
-
-  virtual void UpdateAsync(AsyncCanvasRenderer* aRenderer) {}
-
   virtual void Updated() { }
-
-protected:
-  int32_t mFrameID;
 };
 
 // Used for 2D canvases and WebGL canvas on non-GL systems where readback is requried.
 class CanvasClient2D : public CanvasClient
 {
 public:
   CanvasClient2D(CompositableForwarder* aLayerForwarder,
                  TextureFlags aFlags)
@@ -102,17 +80,17 @@ public:
     mBuffer = nullptr;
   }
 
   virtual void Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer) override;
 
   virtual bool AddTextureClient(TextureClient* aTexture) override
   {
     MOZ_ASSERT((mTextureFlags & aTexture->GetFlags()) == mTextureFlags);
-    return CanvasClient::AddTextureClient(aTexture);
+    return CompositableClient::AddTextureClient(aTexture);
   }
 
   virtual void OnDetach() override
   {
     mBuffer = nullptr;
   }
 
 private:
@@ -128,17 +106,16 @@ private:
 // Used for GL canvases where we don't need to do any readback, i.e., with a
 // GL backend.
 class CanvasClientSharedSurface : public CanvasClient
 {
 private:
   RefPtr<SharedSurfaceTextureClient> mShSurfClient;
   RefPtr<TextureClient> mReadbackClient;
   RefPtr<TextureClient> mFront;
-  RefPtr<TextureClient> mNewFront;
 
   void ClearSurfaces();
 
 public:
   CanvasClientSharedSurface(CompositableForwarder* aLayerForwarder,
                             TextureFlags aFlags);
 
   ~CanvasClientSharedSurface();
@@ -148,60 +125,18 @@ public:
   }
 
   virtual void Clear() override {
     ClearSurfaces();
   }
 
   virtual void Update(gfx::IntSize aSize,
                       ClientCanvasLayer* aLayer) override;
-  void UpdateRenderer(gfx::IntSize aSize, Renderer& aRenderer);
-
-  virtual void UpdateAsync(AsyncCanvasRenderer* aRenderer) override;
-
-  virtual void Updated() override;
 
   virtual void OnDetach() override {
     ClearSurfaces();
   }
 };
 
-/**
- * Used for OMT<canvas> uploads using the image bridge protocol.
- * Actual CanvasClient is on the ImageBridgeChild thread, so we
- * only forward its AsyncID here
- */
-class CanvasClientBridge final : public CanvasClient
-{
-public:
-  CanvasClientBridge(CompositableForwarder* aLayerForwarder,
-                     TextureFlags aFlags)
-    : CanvasClient(aLayerForwarder, aFlags)
-    , mAsyncID(0)
-    , mLayer(nullptr)
-  {
-  }
-
-  TextureInfo GetTextureInfo() const override
-  {
-    return TextureInfo(CompositableType::IMAGE);
-  }
-
-  virtual void Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer) override
-  {
-  }
-
-  virtual void UpdateAsync(AsyncCanvasRenderer* aRenderer) override;
-
-  void SetLayer(ShadowableLayer* aLayer)
-  {
-    mLayer = aLayer;
-  }
-
-protected:
-  uint64_t mAsyncID;
-  ShadowableLayer* mLayer;
-};
-
 } // namespace layers
 } // namespace mozilla
 
 #endif
--- a/gfx/layers/client/ClientCanvasLayer.cpp
+++ b/gfx/layers/client/ClientCanvasLayer.cpp
@@ -6,25 +6,42 @@
 #include "ClientCanvasLayer.h"
 #include "GLContext.h"                  // for GLContext
 #include "GLScreenBuffer.h"             // for GLScreenBuffer
 #include "GeckoProfiler.h"              // for PROFILER_LABEL
 #include "SharedSurfaceEGL.h"           // for SurfaceFactory_EGLImage
 #include "SharedSurfaceGL.h"            // for SurfaceFactory_GLTexture, etc
 #include "ClientLayerManager.h"         // for ClientLayerManager, etc
 #include "mozilla/gfx/Point.h"          // for IntSize
-#include "mozilla/layers/AsyncCanvasRenderer.h"
 #include "mozilla/layers/CompositorTypes.h"
 #include "mozilla/layers/LayersTypes.h"
 #include "nsCOMPtr.h"                   // for already_AddRefed
 #include "nsISupportsImpl.h"            // for Layer::AddRef, etc
 #include "nsRect.h"                     // for mozilla::gfx::IntRect
 #include "nsXULAppAPI.h"                // for XRE_GetProcessType, etc
 #include "gfxPrefs.h"                   // for WebGLForceLayersReadback
 
+#ifdef XP_WIN
+#include "SharedSurfaceANGLE.h"         // for SurfaceFactory_ANGLEShareHandle
+#include "gfxWindowsPlatform.h"
+#endif
+
+#ifdef MOZ_WIDGET_GONK
+#include "SharedSurfaceGralloc.h"
+#endif
+
+#ifdef XP_MACOSX
+#include "SharedSurfaceIO.h"
+#endif
+
+#ifdef GL_PROVIDER_GLX
+#include "GLXLibrary.h"
+#include "SharedSurfaceGLX.h"
+#endif
+
 using namespace mozilla::gfx;
 using namespace mozilla::gl;
 
 namespace mozilla {
 namespace layers {
 
 ClientCanvasLayer::~ClientCanvasLayer()
 {
@@ -60,17 +77,56 @@ ClientCanvasLayer::Initialize(const Data
 
   auto forwarder = ClientManager()->AsShadowForwarder();
 
   mFlags = TextureFlags::ORIGIN_BOTTOM_LEFT;
   if (!aData.mIsGLAlphaPremult) {
     mFlags |= TextureFlags::NON_PREMULTIPLIED;
   }
 
-  UniquePtr<SurfaceFactory> factory = GLScreenBuffer::CreateFactory(mGLContext, caps, forwarder, mFlags);
+  UniquePtr<SurfaceFactory> factory;
+
+  if (!gfxPrefs::WebGLForceLayersReadback()) {
+    switch (forwarder->GetCompositorBackendType()) {
+      case mozilla::layers::LayersBackend::LAYERS_OPENGL: {
+#if defined(XP_MACOSX)
+        factory = SurfaceFactory_IOSurface::Create(mGLContext, caps, forwarder, mFlags);
+#elif defined(MOZ_WIDGET_GONK)
+        factory = MakeUnique<SurfaceFactory_Gralloc>(mGLContext, caps, forwarder, mFlags);
+#elif defined(GL_PROVIDER_GLX)
+        if (sGLXLibrary.UseSurfaceSharing())
+          factory = SurfaceFactory_GLXDrawable::Create(mGLContext, caps, forwarder, mFlags);
+#else
+        if (mGLContext->GetContextType() == GLContextType::EGL) {
+          if (XRE_IsParentProcess()) {
+            factory = SurfaceFactory_EGLImage::Create(mGLContext, caps, forwarder,
+                                                      mFlags);
+          }
+        }
+#endif
+        break;
+      }
+      case mozilla::layers::LayersBackend::LAYERS_D3D11: {
+#ifdef XP_WIN
+        // Enable surface sharing only if ANGLE and compositing devices
+        // are both WARP or both not WARP
+        if (mGLContext->IsANGLE() &&
+            (mGLContext->IsWARP() == gfxWindowsPlatform::GetPlatform()->IsWARP()) &&
+            gfxWindowsPlatform::GetPlatform()->CompositorD3D11TextureSharingWorks())
+        {
+          factory = SurfaceFactory_ANGLEShareHandle::Create(mGLContext, caps, forwarder,
+                                                            mFlags);
+        }
+#endif
+        break;
+      }
+      default:
+        break;
+    }
+  }
 
   if (mGLFrontbuffer) {
     // We're using a source other than the one in the default screen.
     // (SkiaGL)
     mFactory = Move(factory);
     if (!mFactory) {
       // Absolutely must have a factory here, so create a basic one
       mFactory = MakeUnique<SurfaceFactory_Basic>(mGLContext, caps, mFlags);
@@ -84,16 +140,21 @@ ClientCanvasLayer::Initialize(const Data
 void
 ClientCanvasLayer::RenderLayer()
 {
   PROFILER_LABEL("ClientCanvasLayer", "RenderLayer",
     js::ProfileEntry::Category::GRAPHICS);
 
   RenderMaskLayers(this);
 
+  if (!IsDirty()) {
+    return;
+  }
+  Painted();
+
   if (!mCanvasClient) {
     TextureFlags flags = TextureFlags::IMMEDIATE_UPLOAD;
     if (mOriginPos == gl::OriginPos::BottomLeft) {
       flags |= TextureFlags::ORIGIN_BOTTOM_LEFT;
     }
 
     if (!mGLContext) {
       // We don't support locking for buffer surfaces currently
@@ -106,50 +167,33 @@ ClientCanvasLayer::RenderLayer()
 
     mCanvasClient = CanvasClient::CreateCanvasClient(GetCanvasClientType(),
                                                      ClientManager()->AsShadowForwarder(),
                                                      flags);
     if (!mCanvasClient) {
       return;
     }
     if (HasShadow()) {
-      if (mAsyncRenderer) {
-        static_cast<CanvasClientBridge*>(mCanvasClient.get())->SetLayer(this);
-      } else {
-        mCanvasClient->Connect();
-        ClientManager()->AsShadowForwarder()->Attach(mCanvasClient, this);
-      }
+      mCanvasClient->Connect();
+      ClientManager()->AsShadowForwarder()->Attach(mCanvasClient, this);
     }
   }
 
-  if (mCanvasClient && mAsyncRenderer) {
-    mCanvasClient->UpdateAsync(mAsyncRenderer);
-  }
-
-  if (!IsDirty()) {
-    return;
-  }
-  Painted();
-
   FirePreTransactionCallback();
   mCanvasClient->Update(gfx::IntSize(mBounds.width, mBounds.height), this);
 
   FireDidTransactionCallback();
 
   ClientManager()->Hold(this);
   mCanvasClient->Updated();
 }
 
 CanvasClient::CanvasClientType
 ClientCanvasLayer::GetCanvasClientType()
 {
-  if (mAsyncRenderer) {
-    return CanvasClient::CanvasClientAsync;
-  }
-
   if (mGLContext) {
     return CanvasClient::CanvasClientTypeShSurf;
   }
   return CanvasClient::CanvasClientSurface;
 }
 
 already_AddRefed<CanvasLayer>
 ClientLayerManager::CreateCanvasLayer()
--- a/gfx/layers/client/ClientCanvasLayer.h
+++ b/gfx/layers/client/ClientCanvasLayer.h
@@ -92,16 +92,17 @@ protected:
   CanvasClientType GetCanvasClientType();
 
   RefPtr<CanvasClient> mCanvasClient;
 
   UniquePtr<gl::SurfaceFactory> mFactory;
 
   TextureFlags mFlags;
 
+  friend class DeprecatedCanvasClient2D;
   friend class CanvasClient2D;
   friend class CanvasClientSharedSurface;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -164,17 +164,16 @@ TextureChild::Recv__delete__()
   return true;
 }
 
 void
 TextureChild::ActorDestroy(ActorDestroyReason why)
 {
   if (mTextureClient) {
     mTextureClient->mActor = nullptr;
-    mTextureClient->mAllocator = nullptr;
   }
   mWaitForRecycle = nullptr;
   mKeep = nullptr;
 }
 
 // static
 PTextureChild*
 TextureClient::CreateIPDLActor()
--- a/gfx/layers/ipc/ImageBridgeChild.cpp
+++ b/gfx/layers/ipc/ImageBridgeChild.cpp
@@ -16,17 +16,16 @@
 #include "base/thread.h"                // for Thread
 #include "base/tracked.h"               // for FROM_HERE
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
 #include "mozilla/Monitor.h"            // for Monitor, MonitorAutoLock
 #include "mozilla/ReentrantMonitor.h"   // for ReentrantMonitor, etc
 #include "mozilla/ipc/MessageChannel.h" // for MessageChannel, etc
 #include "mozilla/ipc/Transport.h"      // for Transport
 #include "mozilla/gfx/Point.h"          // for IntSize
-#include "mozilla/layers/AsyncCanvasRenderer.h"
 #include "mozilla/media/MediaSystemResourceManager.h" // for MediaSystemResourceManager
 #include "mozilla/media/MediaSystemResourceManagerChild.h" // for MediaSystemResourceManagerChild
 #include "mozilla/layers/CompositableClient.h"  // for CompositableChild, etc
 #include "mozilla/layers/CompositorParent.h" // for CompositorParent
 #include "mozilla/layers/ISurfaceAllocator.h"  // for ISurfaceAllocator
 #include "mozilla/layers/ImageClient.h"  // for ImageClient
 #include "mozilla/layers/LayersMessages.h"  // for CompositableOperation
 #include "mozilla/layers/PCompositableChild.h"  // for PCompositableChild
@@ -227,29 +226,16 @@ static void CreateImageClientSync(RefPtr
 {
   ReentrantMonitorAutoEnter autoMon(*barrier);
   *result = sImageBridgeChildSingleton->CreateImageClientNow(
       aType, aImageContainer);
   *aDone = true;
   barrier->NotifyAll();
 }
 
-// dispatched function
-static void CreateCanvasClientSync(ReentrantMonitor* aBarrier,
-                                   CanvasClient::CanvasClientType aType,
-                                   TextureFlags aFlags,
-                                   RefPtr<CanvasClient>* const outResult,
-                                   bool* aDone)
-{
-  ReentrantMonitorAutoEnter autoMon(*aBarrier);
-  *outResult = sImageBridgeChildSingleton->CreateCanvasClientNow(aType, aFlags);
-  *aDone = true;
-  aBarrier->NotifyAll();
-}
-
 static void ConnectImageBridge(ImageBridgeChild * child, ImageBridgeParent * parent)
 {
   MessageLoop *parentMsgLoop = parent->GetMessageLoop();
   ipc::MessageChannel *parentChannel = parent->GetIPCChannel();
   child->Open(parentChannel, parentMsgLoop, mozilla::ipc::ChildSide);
 }
 
 ImageBridgeChild::ImageBridgeChild()
@@ -278,24 +264,19 @@ ImageBridgeChild::MarkShutDown()
 
 void
 ImageBridgeChild::Connect(CompositableClient* aCompositable,
                           ImageContainer* aImageContainer)
 {
   MOZ_ASSERT(aCompositable);
   MOZ_ASSERT(!mShuttingDown);
   uint64_t id = 0;
-
-  PImageContainerChild* imageContainerChild = nullptr;
-  if (aImageContainer)
-    imageContainerChild = aImageContainer->GetPImageContainerChild();
-
   PCompositableChild* child =
     SendPCompositableConstructor(aCompositable->GetTextureInfo(),
-                                 imageContainerChild, &id);
+                                 aImageContainer->GetPImageContainerChild(), &id);
   MOZ_ASSERT(child);
   aCompositable->InitIPDLActor(child, id);
 }
 
 PCompositableChild*
 ImageBridgeChild::AllocPCompositableChild(const TextureInfo& aInfo,
                                           PImageContainerChild* aChild, uint64_t* aID)
 {
@@ -388,45 +369,16 @@ void ImageBridgeChild::DispatchReleaseIm
     return;
   }
 
   sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
     FROM_HERE,
     NewRunnableFunction(&ReleaseImageClientNow, aClient, aChild));
 }
 
-static void ReleaseCanvasClientNow(CanvasClient* aClient)
-{
-  MOZ_ASSERT(InImageBridgeChildThread());
-  aClient->Release();
-}
-
-// static
-void ImageBridgeChild::DispatchReleaseCanvasClient(CanvasClient* aClient)
-{
-  if (!aClient) {
-    return;
-  }
-
-  if (!IsCreated()) {
-    // CompositableClient::Release should normally happen in the ImageBridgeChild
-    // thread because it usually generate some IPDL messages.
-    // However, if we take this branch it means that the ImageBridgeChild
-    // has already shut down, along with the CompositableChild, which means no
-    // message will be sent and it is safe to run this code from any thread.
-    MOZ_ASSERT(aClient->GetIPDLActor() == nullptr);
-    aClient->Release();
-    return;
-  }
-
-  sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
-    FROM_HERE,
-    NewRunnableFunction(&ReleaseCanvasClientNow, aClient));
-}
-
 static void ReleaseTextureClientNow(TextureClient* aClient)
 {
   MOZ_ASSERT(InImageBridgeChildThread());
   RELEASE_MANUALLY(aClient);
 }
 
 // static
 void ImageBridgeChild::DispatchReleaseTextureClient(TextureClient* aClient)
@@ -455,17 +407,17 @@ static void UpdateImageClientNow(ImageCl
 {
   MOZ_ASSERT(aClient);
   MOZ_ASSERT(aContainer);
   sImageBridgeChildSingleton->BeginTransaction();
   aClient->UpdateImage(aContainer, Layer::CONTENT_OPAQUE);
   sImageBridgeChildSingleton->EndTransaction();
 }
 
-// static
+//static
 void ImageBridgeChild::DispatchImageClientUpdate(ImageClient* aClient,
                                                  ImageContainer* aContainer)
 {
   if (!aClient || !aContainer || !IsCreated()) {
     return;
   }
 
   if (InImageBridgeChildThread()) {
@@ -475,61 +427,16 @@ void ImageBridgeChild::DispatchImageClie
   sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
     FROM_HERE,
     NewRunnableFunction<
       void (*)(ImageClient*, ImageContainer*),
       ImageClient*,
       nsRefPtr<ImageContainer> >(&UpdateImageClientNow, aClient, aContainer));
 }
 
-static void UpdateAsyncCanvasRendererSync(AsyncCanvasRenderer* aWrapper,
-                                          ReentrantMonitor* aBarrier,
-                                          bool* const outDone)
-{
-  ImageBridgeChild::UpdateAsyncCanvasRendererNow(aWrapper);
-
-  ReentrantMonitorAutoEnter autoMon(*aBarrier);
-  *outDone = true;
-  aBarrier->NotifyAll();
-}
-
-// static
-void ImageBridgeChild::UpdateAsyncCanvasRenderer(AsyncCanvasRenderer* aWrapper)
-{
-  aWrapper->GetCanvasClient()->UpdateAsync(aWrapper);
-
-  if (InImageBridgeChildThread()) {
-    UpdateAsyncCanvasRendererNow(aWrapper);
-    return;
-  }
-
-  ReentrantMonitor barrier("UpdateAsyncCanvasRenderer Lock");
-  ReentrantMonitorAutoEnter autoMon(barrier);
-  bool done = false;
-
-  sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
-    FROM_HERE,
-    NewRunnableFunction(&UpdateAsyncCanvasRendererSync, aWrapper, &barrier, &done));
-
-  // should stop the thread until the CanvasClient has been created on
-  // the other thread
-  while (!done) {
-    barrier.Wait();
-  }
-}
-
-// static
-void ImageBridgeChild::UpdateAsyncCanvasRendererNow(AsyncCanvasRenderer* aWrapper)
-{
-  MOZ_ASSERT(aWrapper);
-  sImageBridgeChildSingleton->BeginTransaction();
-  aWrapper->GetCanvasClient()->Updated();
-  sImageBridgeChildSingleton->EndTransaction();
-}
-
 static void FlushAllImagesSync(ImageClient* aClient, ImageContainer* aContainer,
                                AsyncTransactionWaiter* aWaiter)
 {
   MOZ_ASSERT(aClient);
   sImageBridgeChildSingleton->BeginTransaction();
   if (aContainer) {
     aContainer->ClearImagesFromImageBridge();
   }
@@ -537,17 +444,17 @@ static void FlushAllImagesSync(ImageClie
   sImageBridgeChildSingleton->EndTransaction();
   // This decrement is balanced by the increment in FlushAllImages.
   // If any AsyncTransactionTrackers were created by FlushAllImages and attached
   // to aWaiter, aWaiter will not complete until those trackers all complete.
   // Otherwise, aWaiter will be ready to complete now.
   aWaiter->DecrementWaitCount();
 }
 
-// static
+//static
 void ImageBridgeChild::FlushAllImages(ImageClient* aClient,
                                       ImageContainer* aContainer)
 {
   if (!IsCreated()) {
     return;
   }
   MOZ_ASSERT(aClient);
   MOZ_ASSERT(!sImageBridgeChildSingleton->mShuttingDown);
@@ -793,52 +700,16 @@ ImageBridgeChild::CreateImageClientNow(C
     = ImageClient::CreateImageClient(aType, this, TextureFlags::NO_FLAGS);
   MOZ_ASSERT(client, "failed to create ImageClient");
   if (client) {
     client->Connect(aImageContainer);
   }
   return client.forget();
 }
 
-already_AddRefed<CanvasClient>
-ImageBridgeChild::CreateCanvasClient(CanvasClient::CanvasClientType aType,
-                                     TextureFlags aFlag)
-{
-  if (InImageBridgeChildThread()) {
-    return CreateCanvasClientNow(aType, aFlag);
-  }
-  ReentrantMonitor barrier("CreateCanvasClient Lock");
-  ReentrantMonitorAutoEnter autoMon(barrier);
-  bool done = false;
-
-  RefPtr<CanvasClient> result = nullptr;
-  GetMessageLoop()->PostTask(FROM_HERE,
-                             NewRunnableFunction(&CreateCanvasClientSync,
-                                 &barrier, aType, aFlag, &result, &done));
-  // should stop the thread until the CanvasClient has been created on the
-  // other thread
-  while (!done) {
-    barrier.Wait();
-  }
-  return result.forget();
-}
-
-already_AddRefed<CanvasClient>
-ImageBridgeChild::CreateCanvasClientNow(CanvasClient::CanvasClientType aType,
-                                        TextureFlags aFlag)
-{
-  RefPtr<CanvasClient> client
-    = CanvasClient::CreateCanvasClient(aType, this, aFlag);
-  MOZ_ASSERT(client, "failed to create CanvasClient");
-  if (client) {
-    client->Connect();
-  }
-  return client.forget();
-}
-
 bool
 ImageBridgeChild::AllocUnsafeShmem(size_t aSize,
                                    ipc::SharedMemory::SharedMemoryType aType,
                                    ipc::Shmem* aShmem)
 {
   MOZ_ASSERT(!mShuttingDown);
   if (InImageBridgeChildThread()) {
     return PImageBridgeChild::AllocUnsafeShmem(aSize, aType, aShmem);
--- a/gfx/layers/ipc/ImageBridgeChild.h
+++ b/gfx/layers/ipc/ImageBridgeChild.h
@@ -7,17 +7,16 @@
 #define MOZILLA_GFX_IMAGEBRIDGECHILD_H
 
 #include <stddef.h>                     // for size_t
 #include <stdint.h>                     // for uint32_t, uint64_t
 #include "mozilla/Attributes.h"         // for override
 #include "mozilla/RefPtr.h"             // for already_AddRefed
 #include "mozilla/ipc/SharedMemory.h"   // for SharedMemory, etc
 #include "mozilla/layers/AsyncTransactionTracker.h" // for AsyncTransactionTrackerHolder
-#include "mozilla/layers/CanvasClient.h"
 #include "mozilla/layers/CompositableForwarder.h"
 #include "mozilla/layers/CompositorTypes.h"
 #include "mozilla/layers/PImageBridgeChild.h"
 #include "nsDebug.h"                    // for NS_RUNTIMEABORT
 #include "nsRegion.h"                   // for nsIntRegion
 #include "mozilla/gfx/Rect.h"
 
 class MessageLoop;
@@ -28,17 +27,16 @@ class Thread;
 
 namespace mozilla {
 namespace ipc {
 class Shmem;
 } // namespace ipc
 
 namespace layers {
 
-class AsyncCanvasRenderer;
 class AsyncTransactionTracker;
 class ImageClient;
 class ImageContainer;
 class ImageBridgeParent;
 class CompositableClient;
 struct CompositableTransaction;
 class Image;
 class TextureClient;
@@ -207,30 +205,22 @@ public:
 
   virtual bool
   RecvDidComposite(InfallibleTArray<ImageCompositeNotification>&& aNotifications) override;
 
   already_AddRefed<ImageClient> CreateImageClient(CompositableType aType,
                                                   ImageContainer* aImageContainer);
   already_AddRefed<ImageClient> CreateImageClientNow(CompositableType aType,
                                                      ImageContainer* aImageContainer);
-  already_AddRefed<CanvasClient> CreateCanvasClient(CanvasClient::CanvasClientType aType,
-                                                    TextureFlags aFlag);
-  already_AddRefed<CanvasClient> CreateCanvasClientNow(CanvasClient::CanvasClientType aType,
-                                                       TextureFlags aFlag);
 
   static void DispatchReleaseImageClient(ImageClient* aClient,
                                          PImageContainerChild* aChild = nullptr);
-  static void DispatchReleaseCanvasClient(CanvasClient* aClient);
   static void DispatchReleaseTextureClient(TextureClient* aClient);
   static void DispatchImageClientUpdate(ImageClient* aClient, ImageContainer* aContainer);
 
-  static void UpdateAsyncCanvasRenderer(AsyncCanvasRenderer* aClient);
-  static void UpdateAsyncCanvasRendererNow(AsyncCanvasRenderer* aClient);
-
   /**
    * Flush all Images sent to CompositableHost.
    */
   static void FlushAllImages(ImageClient* aClient, ImageContainer* aContainer);
 
   // CompositableForwarder
 
   virtual void Connect(CompositableClient* aCompositable,
--- a/gfx/layers/ipc/PImageBridge.ipdl
+++ b/gfx/layers/ipc/PImageBridge.ipdl
@@ -53,17 +53,17 @@ parent:
   // that all of the messages from the parent side have been received and processed
   // before sending Stop, and that after Stop returns, there is no message in
   // flight on any side and we can safely destroy the channel and threads.
   sync WillStop();
   // Second step
   sync Stop();
 
   sync PCompositable(TextureInfo aInfo,
-                     nullable PImageContainer aImageContainer) returns (uint64_t id);
+                     PImageContainer aImageContainer) returns (uint64_t id);
   async PTexture(SurfaceDescriptor aSharedData, TextureFlags aTextureFlags);
   async PMediaSystemResourceManager();
   async PImageContainer();
 
   async ChildAsyncMessages(AsyncChildMessageData[] aMessages);
 };
 
 
--- a/gfx/layers/moz.build
+++ b/gfx/layers/moz.build
@@ -102,17 +102,16 @@ EXPORTS.mozilla.layers += [
     'apz/testutil/APZTestData.h',
     'apz/util/ActiveElementManager.h',
     'apz/util/APZCCallbackHelper.h',
     'apz/util/APZEventState.h',
     'apz/util/APZThreadUtils.h',
     'apz/util/ChromeProcessController.h',
     'apz/util/DoubleTapToZoom.h',
     'apz/util/InputAPZContext.h',
-    'AsyncCanvasRenderer.h',
     'AtomicRefCountedWithFinalize.h',
     'AxisPhysicsModel.h',
     'AxisPhysicsMSDModel.h',
     'basic/BasicCompositor.h',
     'basic/MacIOSurfaceTextureHostBasic.h',
     'basic/TextureHostBasic.h',
     'client/CanvasClient.h',
     'client/CompositableClient.h',
@@ -248,17 +247,16 @@ UNIFIED_SOURCES += [
     'apz/testutil/APZTestData.cpp',
     'apz/util/ActiveElementManager.cpp',
     'apz/util/APZCCallbackHelper.cpp',
     'apz/util/APZEventState.cpp',
     'apz/util/APZThreadUtils.cpp',
     'apz/util/ChromeProcessController.cpp',
     'apz/util/DoubleTapToZoom.cpp',
     'apz/util/InputAPZContext.cpp',
-    'AsyncCanvasRenderer.cpp',
     'AxisPhysicsModel.cpp',
     'AxisPhysicsMSDModel.cpp',
     'basic/BasicCanvasLayer.cpp',
     'basic/BasicColorLayer.cpp',
     'basic/BasicCompositor.cpp',
     'basic/BasicContainerLayer.cpp',
     'basic/BasicImages.cpp',
     'basic/BasicLayerManager.cpp',
--- a/gfx/src/gfxCrashReporterUtils.cpp
+++ b/gfx/src/gfxCrashReporterUtils.cpp
@@ -79,32 +79,16 @@ public:
     if (!observerService)
       return NS_OK;
     nsRefPtr<ObserverToDestroyFeaturesAlreadyReported> observer = new ObserverToDestroyFeaturesAlreadyReported;
     observerService->AddObserver(observer, "xpcom-shutdown", false);
     return NS_OK;
   }
 };
 
-class AppendAppNotesRunnable : public nsCancelableRunnable {
-public:
-  explicit AppendAppNotesRunnable(nsAutoCString aFeatureStr)
-    : mFeatureString(aFeatureStr)
-  {
-  }
-
-  NS_IMETHOD Run() override {
-    CrashReporter::AppendAppNotesToCrashReport(mFeatureString);
-    return NS_OK;
-  }
-
-private:
-  nsCString mFeatureString;
-};
-
 void
 ScopedGfxFeatureReporter::WriteAppNote(char statusChar)
 {
   StaticMutexAutoLock al(gFeaturesAlreadyReportedMutex);
 
   if (!gFeaturesAlreadyReported) {
     gFeaturesAlreadyReported = new nsTArray<nsCString>;
     nsCOMPtr<nsIRunnable> r = new RegisterObserverRunnable();
@@ -113,18 +97,17 @@ ScopedGfxFeatureReporter::WriteAppNote(c
 
   nsAutoCString featureString;
   featureString.AppendPrintf("%s%c ",
                              mFeature,
                              statusChar);
 
   if (!gFeaturesAlreadyReported->Contains(featureString)) {
     gFeaturesAlreadyReported->AppendElement(featureString);
-    nsCOMPtr<nsIRunnable> r = new AppendAppNotesRunnable(featureString);
-    NS_DispatchToMainThread(r);
+    CrashReporter::AppendAppNotesToCrashReport(featureString);
   }
 }
 
 } // end namespace mozilla
 
 #else
 
 namespace mozilla {
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -382,42 +382,22 @@ private:
   DECL_GFX_PREF(Live, "mousewheel.transaction.timeout",        MouseWheelTransactionTimeoutMs, int32_t, (int32_t)1500);
 
   DECL_GFX_PREF(Live, "nglayout.debug.widget_update_flashing", WidgetUpdateFlashing, bool, false);
 
   DECL_GFX_PREF(Live, "test.events.async.enabled",             TestEventsAsyncEnabled, bool, false);
   DECL_GFX_PREF(Live, "test.mousescroll",                      MouseScrollTestingEnabled, bool, false);
 
   DECL_GFX_PREF(Live, "ui.click_hold_context_menus.delay",     UiClickHoldContextMenusDelay, int32_t, 500);
-
-  // WebGL (for pref access from Worker threads)
-  DECL_GFX_PREF(Live, "webgl.all-angle-options",               WebGLAllANGLEOptions, bool, false);
-  DECL_GFX_PREF(Live, "webgl.angle.force-d3d11",               WebGLANGLEForceD3D11, bool, false);
-  DECL_GFX_PREF(Live, "webgl.angle.try-d3d11",                 WebGLANGLETryD3D11, bool, false);
+  DECL_GFX_PREF(Once, "webgl.angle.force-d3d11",               WebGLANGLEForceD3D11, bool, false);
+  DECL_GFX_PREF(Once, "webgl.angle.try-d3d11",                 WebGLANGLETryD3D11, bool, false);
   DECL_GFX_PREF(Once, "webgl.angle.force-warp",                WebGLANGLEForceWARP, bool, false);
-  DECL_GFX_PREF(Live, "webgl.bypass-shader-validation",        WebGLBypassShaderValidator, bool, true);
-  DECL_GFX_PREF(Live, "webgl.can-lose-context-in-foreground",  WebGLCanLoseContextInForeground, bool, true);
-  DECL_GFX_PREF(Live, "webgl.default-no-alpha",                WebGLDefaultNoAlpha, bool, false);
-  DECL_GFX_PREF(Live, "webgl.disable-angle",                   WebGLDisableANGLE, bool, false);
-  DECL_GFX_PREF(Live, "webgl.disable-extensions",              WebGLDisableExtensions, bool, false);
-
   DECL_GFX_PREF(Live, "webgl.disable-fail-if-major-performance-caveat",
                 WebGLDisableFailIfMajorPerformanceCaveat, bool, false);
-  DECL_GFX_PREF(Live, "webgl.disabled",                        WebGLDisabled, bool, false);
-
-  DECL_GFX_PREF(Live, "webgl.enable-draft-extensions",         WebGLDraftExtensionsEnabled, bool, false);
-  DECL_GFX_PREF(Live, "webgl.enable-privileged-extensions",    WebGLPrivilegedExtensionsEnabled, bool, false);
-  DECL_GFX_PREF(Live, "webgl.force-enabled",                   WebGLForceEnabled, bool, false);
-  DECL_GFX_PREF(Live, "webgl.force-layers-readback",           WebGLForceLayersReadback, bool, false);
-  DECL_GFX_PREF(Live, "webgl.lose-context-on-memory-pressure", WebGLLoseContextOnMemoryPressure, bool, false);
-  DECL_GFX_PREF(Live, "webgl.max-warnings-per-context",        WebGLMaxWarningsPerContext, uint32_t, 32);
-  DECL_GFX_PREF(Live, "webgl.min_capability_mode",             WebGLMinCapabilityMode, bool, false);
-  DECL_GFX_PREF(Live, "webgl.msaa-force",                      WebGLForceMSAA, bool, false);
-  DECL_GFX_PREF(Live, "webgl.prefer-16bpp",                    WebGLPrefer16bpp, bool, false);
-  DECL_GFX_PREF(Live, "webgl.restore-context-when-visible",    WebGLRestoreWhenVisible, bool, true);
+  DECL_GFX_PREF(Once, "webgl.force-layers-readback",           WebGLForceLayersReadback, bool, false);
 
   // WARNING:
   // Please make sure that you've added your new preference to the list above in alphabetical order.
   // Please do not just append it to the end of the list.
 
 public:
   // Manage the singleton:
   static gfxPrefs& GetSingleton()
--- a/gfx/thebes/gfxUtils.cpp
+++ b/gfx/thebes/gfxUtils.cpp
@@ -7,29 +7,25 @@
 
 #include "cairo.h"
 #include "gfxContext.h"
 #include "gfxImageSurface.h"
 #include "gfxPlatform.h"
 #include "gfxDrawable.h"
 #include "imgIEncoder.h"
 #include "mozilla/Base64.h"
-#include "mozilla/dom/ImageEncoder.h"
-#include "mozilla/dom/WorkerPrivate.h"
-#include "mozilla/dom/WorkerRunnable.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/gfx/DataSurfaceHelpers.h"
 #include "mozilla/gfx/Logging.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/Vector.h"
 #include "nsComponentManagerUtils.h"
 #include "nsIClipboardHelper.h"
 #include "nsIFile.h"
-#include "nsIGfxInfo.h"
 #include "nsIPresShell.h"
 #include "nsPresContext.h"
 #include "nsRegion.h"
 #include "nsServiceManagerUtils.h"
 #include "yuv_convert.h"
 #include "ycbcr_to_rgb565.h"
 #include "GeckoProfiler.h"
 #include "ImageContainer.h"
@@ -1542,135 +1538,16 @@ gfxUtils::CopyAsDataURI(DrawTarget* aDT)
   RefPtr<SourceSurface> surface = aDT->Snapshot();
   if (surface) {
     CopyAsDataURI(surface);
   } else {
     NS_WARNING("Failed to get surface!");
   }
 }
 
-/* static */ void
-gfxUtils::GetImageBuffer(gfx::DataSourceSurface* aSurface,
-                         bool aIsAlphaPremultiplied,
-                         uint8_t** outImageBuffer,
-                         int32_t* outFormat)
-{
-    *outImageBuffer = nullptr;
-    *outFormat = 0;
-
-    DataSourceSurface::MappedSurface map;
-    if (!aSurface->Map(DataSourceSurface::MapType::READ, &map))
-        return;
-
-    uint32_t bufferSize = aSurface->GetSize().width * aSurface->GetSize().height * 4;
-    uint8_t* imageBuffer = new (fallible) uint8_t[bufferSize];
-    if (!imageBuffer) {
-        aSurface->Unmap();
-        return;
-    }
-    memcpy(imageBuffer, map.mData, bufferSize);
-
-    aSurface->Unmap();
-
-    int32_t format = imgIEncoder::INPUT_FORMAT_HOSTARGB;
-    if (!aIsAlphaPremultiplied) {
-        // We need to convert to INPUT_FORMAT_RGBA, otherwise
-        // we are automatically considered premult, and unpremult'd.
-        // Yes, it is THAT silly.
-        // Except for different lossy conversions by color,
-        // we could probably just change the label, and not change the data.
-        gfxUtils::ConvertBGRAtoRGBA(imageBuffer, bufferSize);
-        format = imgIEncoder::INPUT_FORMAT_RGBA;
-    }
-
-    *outImageBuffer = imageBuffer;
-    *outFormat = format;
-}
-
-/* static */ nsresult
-gfxUtils::GetInputStream(gfx::DataSourceSurface* aSurface,
-                         bool aIsAlphaPremultiplied,
-                         const char* aMimeType,
-                         const char16_t* aEncoderOptions,
-                         nsIInputStream** outStream)
-{
-    nsCString enccid("@mozilla.org/image/encoder;2?type=");
-    enccid += aMimeType;
-    nsCOMPtr<imgIEncoder> encoder = do_CreateInstance(enccid.get());
-    if (!encoder)
-        return NS_ERROR_FAILURE;
-
-    nsAutoArrayPtr<uint8_t> imageBuffer;
-    int32_t format = 0;
-    GetImageBuffer(aSurface, aIsAlphaPremultiplied, getter_Transfers(imageBuffer), &format);
-    if (!imageBuffer)
-        return NS_ERROR_FAILURE;
-
-    return dom::ImageEncoder::GetInputStream(aSurface->GetSize().width,
-                                             aSurface->GetSize().height,
-                                             imageBuffer, format,
-                                             encoder, aEncoderOptions, outStream);
-}
-
-class GetFeatureStatusRunnable final : public dom::workers::WorkerMainThreadRunnable
-{
-public:
-    GetFeatureStatusRunnable(dom::workers::WorkerPrivate* workerPrivate,
-                             const nsCOMPtr<nsIGfxInfo>& gfxInfo,
-                             int32_t feature,
-                             int32_t* status)
-      : WorkerMainThreadRunnable(workerPrivate)
-      , mGfxInfo(gfxInfo)
-      , mFeature(feature)
-      , mStatus(status)
-      , mNSResult(NS_OK)
-    {
-    }
-
-    bool MainThreadRun() override
-    {
-      if (mGfxInfo) {
-        mNSResult = mGfxInfo->GetFeatureStatus(mFeature, mStatus);
-      }
-      return true;
-    }
-
-    nsresult GetNSResult() const
-    {
-      return mNSResult;
-    }
-
-protected:
-    ~GetFeatureStatusRunnable() {}
-
-private:
-    nsCOMPtr<nsIGfxInfo> mGfxInfo;
-    int32_t mFeature;
-    int32_t* mStatus;
-    nsresult mNSResult;
-};
-
-/* static */ nsresult
-gfxUtils::ThreadSafeGetFeatureStatus(const nsCOMPtr<nsIGfxInfo>& gfxInfo,
-                                     int32_t feature, int32_t* status)
-{
-  if (!NS_IsMainThread()) {
-    dom::workers::WorkerPrivate* workerPrivate =
-      dom::workers::GetCurrentThreadWorkerPrivate();
-    nsRefPtr<GetFeatureStatusRunnable> runnable =
-      new GetFeatureStatusRunnable(workerPrivate, gfxInfo, feature, status);
-
-    runnable->Dispatch(workerPrivate->GetJSContext());
-
-    return runnable->GetNSResult();
-  }
-
-  return gfxInfo->GetFeatureStatus(feature, status);
-}
-
 /* static */ bool
 gfxUtils::DumpDisplayList() {
   return gfxPrefs::LayoutDumpDisplayList();
 }
 
 FILE *gfxUtils::sDumpPaintFile = stderr;
 
 #ifdef MOZ_DUMP_PAINTING
--- a/gfx/thebes/gfxUtils.h
+++ b/gfx/thebes/gfxUtils.h
@@ -12,18 +12,16 @@
 #include "mozilla/gfx/2D.h"
 #include "mozilla/RefPtr.h"
 #include "nsColor.h"
 #include "nsPrintfCString.h"
 #include "mozilla/gfx/Rect.h"
 
 class gfxASurface;
 class gfxDrawable;
-class nsIInputStream;
-class nsIGfxInfo;
 class nsIntRegion;
 class nsIPresShell;
 
 namespace mozilla {
 namespace layers {
 struct PlanarYCbCrData;
 } // namespace layers
 namespace image {
@@ -278,31 +276,16 @@ public:
     static void DumpAsDataURI(DrawTarget* aDT, FILE* aFile);
     static inline void DumpAsDataURI(DrawTarget* aDT) {
         DumpAsDataURI(aDT, stdout);
     }
     static nsCString GetAsDataURI(SourceSurface* aSourceSurface);
     static nsCString GetAsDataURI(DrawTarget* aDT);
     static nsCString GetAsLZ4Base64Str(DataSourceSurface* aSourceSurface);
 
-    static void GetImageBuffer(DataSourceSurface* aSurface,
-                               bool aIsAlphaPremultiplied,
-                               uint8_t** outImageBuffer,
-                               int32_t* outFormat);
-
-    static nsresult GetInputStream(DataSourceSurface* aSurface,
-                                   bool aIsAlphaPremultiplied,
-                                   const char* aMimeType,
-                                   const char16_t* aEncoderOptions,
-                                   nsIInputStream** outStream);
-
-    static nsresult ThreadSafeGetFeatureStatus(const nsCOMPtr<nsIGfxInfo>& gfxInfo,
-                                               int32_t feature,
-                                               int32_t* status);
-
     /**
      * Copy to the clipboard as a PNG encoded Data URL.
      */
     static void CopyAsDataURI(SourceSurface* aSourceSurface);
     static void CopyAsDataURI(DrawTarget* aDT);
 
     static bool DumpDisplayList();
 
--- a/gfx/thebes/moz.build
+++ b/gfx/thebes/moz.build
@@ -267,17 +267,16 @@ include('/ipc/chromium/chromium-config.m
 
 FINAL_LIBRARY = 'xul'
 
 GENERATED_FILES = [
     'DeprecatedPremultiplyTables.h',
 ]
 
 LOCAL_INCLUDES += [
-    '/dom/workers',
     '/dom/xml',
 ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
   LOCAL_INCLUDES += ['/widget/gonk']
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gtk2', 'gtk3', 'gonk', 'qt'):
     DEFINES['MOZ_ENABLE_FREETYPE'] = True
--- a/js/public/StructuredClone.h
+++ b/js/public/StructuredClone.h
@@ -190,30 +190,27 @@ class JS_PUBLIC_API(JSAutoStructuredClon
     ~JSAutoStructuredCloneBuffer() { clear(); }
 
     uint64_t* data() const { return data_; }
     size_t nbytes() const { return nbytes_; }
 
     void clear(const JSStructuredCloneCallbacks* optionalCallbacks=nullptr, void* closure=nullptr);
 
     // Copy some memory. It will be automatically freed by the destructor.
-    bool copy(const uint64_t* data, size_t nbytes, uint32_t version=JS_STRUCTURED_CLONE_VERSION,
-              const JSStructuredCloneCallbacks* callbacks=nullptr, void* closure=nullptr);
+    bool copy(const uint64_t* data, size_t nbytes, uint32_t version=JS_STRUCTURED_CLONE_VERSION);
 
     // Adopt some memory. It will be automatically freed by the destructor.
     // data must have been allocated by the JS engine (e.g., extracted via
     // JSAutoStructuredCloneBuffer::steal).
-    void adopt(uint64_t* data, size_t nbytes, uint32_t version=JS_STRUCTURED_CLONE_VERSION,
-               const JSStructuredCloneCallbacks* callbacks=nullptr, void* closure=nullptr);
+    void adopt(uint64_t* data, size_t nbytes, uint32_t version=JS_STRUCTURED_CLONE_VERSION);
 
     // Release the buffer and transfer ownership to the caller. The caller is
     // responsible for calling JS_ClearStructuredClone or feeding the memory
     // back to JSAutoStructuredCloneBuffer::adopt.
-    void steal(uint64_t** datap, size_t* nbytesp, uint32_t* versionp=nullptr,
-               const JSStructuredCloneCallbacks** callbacks=nullptr, void** closure=nullptr);
+    void steal(uint64_t** datap, size_t* nbytesp, uint32_t* versionp=nullptr);
 
     // Abandon ownership of any transferable objects stored in the buffer,
     // without freeing the buffer itself. Useful when copying the data out into
     // an external container, though note that you will need to use adopt() or
     // JS_ClearStructuredClone to properly release that data eventually.
     void abandon() { ownTransferables_ = IgnoreTransferablesIfAny; }
 
     bool read(JSContext* cx, JS::MutableHandleValue vp,
--- a/js/src/vm/StructuredClone.cpp
+++ b/js/src/vm/StructuredClone.cpp
@@ -2049,26 +2049,26 @@ JS_StructuredClone(JSContext* cx, Handle
     }
 
     return buf.read(cx, vp, callbacks, closure);
 }
 
 JSAutoStructuredCloneBuffer::JSAutoStructuredCloneBuffer(JSAutoStructuredCloneBuffer&& other)
 {
     ownTransferables_ = other.ownTransferables_;
-    other.steal(&data_, &nbytes_, &version_, &callbacks_, &closure_);
+    other.steal(&data_, &nbytes_, &version_);
 }
 
 JSAutoStructuredCloneBuffer&
 JSAutoStructuredCloneBuffer::operator=(JSAutoStructuredCloneBuffer&& other)
 {
     MOZ_ASSERT(&other != this);
     clear();
     ownTransferables_ = other.ownTransferables_;
-    other.steal(&data_, &nbytes_, &version_, &callbacks_, &closure_);
+    other.steal(&data_, &nbytes_, &version_);
     return *this;
 }
 
 void
 JSAutoStructuredCloneBuffer::clear(const JSStructuredCloneCallbacks* optionalCallbacks,
                                    void* optionalClosure)
 {
     if (!data_)
@@ -2083,73 +2083,57 @@ JSAutoStructuredCloneBuffer::clear(const
     ownTransferables_ = NoTransferables;
     js_free(data_);
     data_ = nullptr;
     nbytes_ = 0;
     version_ = 0;
 }
 
 bool
-JSAutoStructuredCloneBuffer::copy(const uint64_t* srcData, size_t nbytes, uint32_t version,
-                                  const JSStructuredCloneCallbacks* callbacks,
-                                  void* closure)
+JSAutoStructuredCloneBuffer::copy(const uint64_t* srcData, size_t nbytes, uint32_t version)
 {
     // transferable objects cannot be copied
     if (StructuredCloneHasTransferObjects(data_, nbytes_))
         return false;
 
     uint64_t* newData = static_cast<uint64_t*>(js_malloc(nbytes));
     if (!newData)
         return false;
 
     js_memcpy(newData, srcData, nbytes);
 
     clear();
     data_ = newData;
     nbytes_ = nbytes;
     version_ = version;
-    callbacks_ = callbacks;
-    closure_ = closure;
     ownTransferables_ = NoTransferables;
     return true;
 }
 
 void
-JSAutoStructuredCloneBuffer::adopt(uint64_t* data, size_t nbytes, uint32_t version,
-                                   const JSStructuredCloneCallbacks* callbacks,
-                                   void* closure)
+JSAutoStructuredCloneBuffer::adopt(uint64_t* data, size_t nbytes, uint32_t version)
 {
     clear();
     data_ = data;
     nbytes_ = nbytes;
     version_ = version;
-    callbacks_ = callbacks;
-    closure_ = closure;
     ownTransferables_ = OwnsTransferablesIfAny;
 }
 
 void
-JSAutoStructuredCloneBuffer::steal(uint64_t** datap, size_t* nbytesp, uint32_t* versionp,
-                                   const JSStructuredCloneCallbacks** callbacks,
-                                   void** closure)
+JSAutoStructuredCloneBuffer::steal(uint64_t** datap, size_t* nbytesp, uint32_t* versionp)
 {
     *datap = data_;
     *nbytesp = nbytes_;
     if (versionp)
         *versionp = version_;
-    if (callbacks)
-        *callbacks = callbacks_;
-    if (closure)
-        *closure = closure_;
 
     data_ = nullptr;
     nbytes_ = 0;
     version_ = 0;
-    callbacks_ = 0;
-    closure_ = 0;
     ownTransferables_ = NoTransferables;
 }
 
 bool
 JSAutoStructuredCloneBuffer::read(JSContext* cx, MutableHandleValue vp,
                                   const JSStructuredCloneCallbacks* optionalCallbacks,
                                   void* closure)
 {
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -4161,18 +4161,16 @@ pref("webgl.renderer-string-override", "
 pref("webgl.vendor-string-override", "");
 
 #ifdef XP_WIN
 pref("webgl.angle.try-d3d11", true);
 pref("webgl.angle.force-d3d11", false);
 pref("webgl.angle.force-warp", false);
 #endif
 
-pref("gfx.offscreencanvas.enabled", false);
-
 #ifdef MOZ_WIDGET_GONK
 pref("gfx.gralloc.fence-with-readpixels", false);
 #endif
 
 // Stagefright prefs
 pref("stagefright.force-enabled", false);
 pref("stagefright.disabled", false);