Backout bug 1066280 for regressions. a=regressions
authorJeff Gilbert <jgilbert@mozilla.com>
Wed, 15 Oct 2014 12:58:22 -0700
changeset 233324 d56d0157891e97004f6a55b7000a5883917dae77
parent 233323 189ac924dfa6121245d15226ec9e1cc78d962715
child 233325 8cd0eedecef2bdfa08026922f05ee9c083e5a3cf
push id4187
push userbhearsum@mozilla.com
push dateFri, 28 Nov 2014 15:29:12 +0000
treeherdermozilla-beta@f23cc6a30c11 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersregressions
bugs1066280
milestone35.0a2
Backout bug 1066280 for regressions. a=regressions
dom/canvas/CanvasRenderingContext2D.cpp
dom/canvas/CanvasRenderingContext2D.h
dom/canvas/WebGLContext.cpp
gfx/2d/DrawTargetSkia.cpp
gfx/2d/HelpersCairo.h
gfx/gl/GLContext.cpp
gfx/gl/GLContext.h
gfx/gl/GLReadTexImageHelper.cpp
gfx/gl/GLReadTexImageHelper.h
gfx/gl/GLScreenBuffer.cpp
gfx/gl/GLScreenBuffer.h
gfx/gl/GLUploadHelpers.cpp
gfx/gl/ScopedGLHelpers.cpp
gfx/gl/ScopedGLHelpers.h
gfx/gl/SharedSurface.cpp
gfx/gl/SharedSurface.h
gfx/gl/SharedSurfaceGralloc.cpp
gfx/gl/SharedSurfaceGralloc.h
gfx/gl/SharedSurfaceIO.h
gfx/gl/SurfaceStream.cpp
gfx/gl/SurfaceStream.h
gfx/gl/SurfaceTypes.cpp
gfx/gl/SurfaceTypes.h
gfx/gl/moz.build
gfx/layers/CopyableCanvasLayer.cpp
gfx/layers/CopyableCanvasLayer.h
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/client/TextureClient.h
gfx/layers/composite/TextureHost.cpp
gfx/layers/composite/TextureHost.h
gfx/layers/d3d10/CanvasLayerD3D10.cpp
gfx/layers/d3d11/TextureD3D11.cpp
gfx/layers/d3d9/CanvasLayerD3D9.cpp
gfx/layers/ipc/LayersSurfaces.ipdlh
gfx/layers/moz.build
gfx/layers/opengl/GrallocTextureClient.cpp
gfx/layers/opengl/GrallocTextureClient.h
gfx/layers/opengl/TextureClientOGL.cpp
gfx/layers/opengl/TextureClientOGL.h
gfx/layers/opengl/TextureHostOGL.h
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -111,16 +111,17 @@
 #include "nsSVGLength2.h"
 #include "nsDeviceContext.h"
 #include "nsFontMetrics.h"
 
 #undef free // apparently defined by some windows header, clashing with a free()
             // method in SkTypes.h
 #ifdef USE_SKIA
 #include "SkiaGLGlue.h"
+#include "SurfaceStream.h"
 #include "SurfaceTypes.h"
 #endif
 
 using mozilla::gl::GLContext;
 using mozilla::gl::SkiaGLGlue;
 using mozilla::gl::GLContextProvider;
 
 #ifdef XP_WIN
@@ -705,17 +706,17 @@ public:
     }
   }
 
   static void PreTransactionCallback(void* aData)
   {
     CanvasRenderingContext2DUserData* self =
       static_cast<CanvasRenderingContext2DUserData*>(aData);
     CanvasRenderingContext2D* context = self->mContext;
-    if (!context || !context->mTarget)
+    if (!context || !context->mStream || !context->mTarget)
       return;
 
     // Since SkiaGL default to store drawing command until flush
     // We will have to flush it before present.
     context->mTarget->Flush();
   }
 
   static void DidTransactionCallback(void* aData)
@@ -820,16 +821,17 @@ DrawTarget* CanvasRenderingContext2D::sE
 
 CanvasRenderingContext2D::CanvasRenderingContext2D()
   : mRenderingMode(RenderingMode::OpenGLBackendMode)
   // these are the default values from the Canvas spec
   , mWidth(0), mHeight(0)
   , mZero(false), mOpaque(false)
   , mResetLayer(true)
   , mIPC(false)
+  , mStream(nullptr)
   , mIsEntireFrameInvalid(false)
   , mPredictManyRedrawCalls(false), mPathTransformWillUpdate(false)
   , mInvalidateCount(0)
 {
   sNumLivingContexts++;
 
   // The default is to use OpenGL mode
   if (!gfxPlatform::GetPlatform()->UseAcceleratedSkiaCanvas()) {
@@ -905,16 +907,17 @@ CanvasRenderingContext2D::Reset()
 
   // only do this for non-docshell created contexts,
   // since those are the ones that we created a surface for
   if (mTarget && IsTargetValid() && !mDocShell) {
     gCanvasAzureMemoryUsed -= mWidth * mHeight * 4;
   }
 
   mTarget = nullptr;
+  mStream = nullptr;
 
   // reset hit regions
   mHitRegionsOptions.ClearAndRetainStorage();
 
   // Since the target changes the backing texture will change, and this will
   // no longer be valid.
   mIsEntireFrameInvalid = false;
   mPredictManyRedrawCalls = false;
@@ -1017,20 +1020,18 @@ CanvasRenderingContext2D::Redraw(const m
   nsSVGEffects::InvalidateDirectRenderingObservers(mCanvasElement);
 
   mCanvasElement->InvalidateCanvasContent(&r);
 }
 
 void
 CanvasRenderingContext2D::DidRefresh()
 {
-  SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue();
-  if (glue) {
-    auto gl = glue->GetGLContext();
-    gl->FlushIfHeavyGLCallsSinceLastFlush();
+  if (mStream && mStream->GLContext()) {
+    mStream->GLContext()->FlushIfHeavyGLCallsSinceLastFlush();
   }
 }
 
 void
 CanvasRenderingContext2D::RedrawUser(const gfxRect& r)
 {
   if (mIsEntireFrameInvalid) {
     ++mInvalidateCount;
@@ -1046,16 +1047,17 @@ bool CanvasRenderingContext2D::SwitchRen
 {
   if (!IsTargetValid() || mRenderingMode == aRenderingMode) {
     return false;
   }
 
   RefPtr<SourceSurface> snapshot = mTarget->Snapshot();
   RefPtr<DrawTarget> oldTarget = mTarget;
   mTarget = nullptr;
+  mStream = nullptr;
   mResetLayer = true;
 
   // Recreate target using the new rendering mode
   RenderingMode attemptedMode = EnsureTarget(aRenderingMode);
   if (!IsTargetValid())
     return false;
 
   // We succeeded, so update mRenderingMode to reflect reality
@@ -1216,16 +1218,18 @@ CanvasRenderingContext2D::EnsureTarget(R
         DemoteOldestContextIfNecessary();
 
         SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue();
 
 #if USE_SKIA
         if (glue && glue->GetGrContext() && glue->GetGLContext()) {
           mTarget = Factory::CreateDrawTargetSkiaWithGrContext(glue->GetGrContext(), size, format);
           if (mTarget) {
+            mStream = gl::SurfaceStream::CreateForType(gl::SurfaceStreamType::TripleBuffer,
+                                                       glue->GetGLContext());
             AddDemotableContext(this);
           } else {
             printf_stderr("Failed to create a SkiaGL DrawTarget, falling back to software\n");
             mode = RenderingMode::SoftwareBackendMode;
           }
         }
 #endif
         if (!mTarget) {
@@ -4848,22 +4852,25 @@ CanvasRenderingContext2D::GetCanvasLayer
   mTarget->Flush();
 
   if (!mResetLayer && aOldLayer) {
     CanvasRenderingContext2DUserData* userData =
       static_cast<CanvasRenderingContext2DUserData*>(
         aOldLayer->GetUserData(&g2DContextLayerUserData));
 
     CanvasLayer::Data data;
-
-    SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue();
-    GLuint skiaGLTex = (GLuint)(uintptr_t)mTarget->GetNativeSurface(NativeSurfaceType::OPENGL_TEXTURE);
-    if (glue && skiaGLTex) {
-      data.mGLContext = glue->GetGLContext();
-      data.mFrontbufferGLTex = skiaGLTex;
+    if (mStream) {
+#ifdef USE_SKIA
+      SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue();
+
+      if (glue) {
+        data.mGLContext = glue->GetGLContext();
+        data.mStream = mStream.get();
+      }
+#endif
     } else {
       data.mDrawTarget = mTarget;
     }
 
     if (userData && userData->IsForContext(this) && aOldLayer->IsDataValid(data)) {
       nsRefPtr<CanvasLayer> ret = aOldLayer;
       return ret.forget();
     }
@@ -4890,30 +4897,35 @@ CanvasRenderingContext2D::GetCanvasLayer
   // The userData will receive DidTransactionCallbacks, which flush the
   // the invalidation state to indicate that the canvas is up to date.
   userData = new CanvasRenderingContext2DUserData(this);
   canvasLayer->SetDidTransactionCallback(
           CanvasRenderingContext2DUserData::DidTransactionCallback, userData);
   canvasLayer->SetUserData(&g2DContextLayerUserData, userData);
 
   CanvasLayer::Data data;
+  if (mStream) {
+    SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue();
+
+    if (glue) {
+      canvasLayer->SetPreTransactionCallback(
+              CanvasRenderingContext2DUserData::PreTransactionCallback, userData);
+#if USE_SKIA
+      data.mGLContext = glue->GetGLContext();
+#endif
+      data.mStream = mStream.get();
+      data.mTexID = (uint32_t)((uintptr_t)mTarget->GetNativeSurface(NativeSurfaceType::OPENGL_TEXTURE));
+    }
+  } else {
+    data.mDrawTarget = mTarget;
+  }
+
   data.mSize = nsIntSize(mWidth, mHeight);
   data.mHasAlpha = !mOpaque;
 
-  SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue();
-  GLuint skiaGLTex = (GLuint)(uintptr_t)mTarget->GetNativeSurface(NativeSurfaceType::OPENGL_TEXTURE);
-  if (glue && skiaGLTex) {
-    canvasLayer->SetPreTransactionCallback(
-            CanvasRenderingContext2DUserData::PreTransactionCallback, userData);
-    data.mGLContext = glue->GetGLContext();
-    data.mFrontbufferGLTex = skiaGLTex;
-  } else {
-    data.mDrawTarget = mTarget;
-  }
-
   canvasLayer->Initialize(data);
   uint32_t flags = mOpaque ? Layer::CONTENT_OPAQUE : 0;
   canvasLayer->SetContentFlags(flags);
   canvasLayer->Updated();
 
   mResetLayer = false;
 
   return canvasLayer.forget();
--- a/dom/canvas/CanvasRenderingContext2D.h
+++ b/dom/canvas/CanvasRenderingContext2D.h
@@ -29,16 +29,17 @@
 #include "nsSVGEffects.h"
 
 class nsGlobalWindow;
 class nsXULElement;
 
 namespace mozilla {
 namespace gl {
 class SourceSurface;
+class SurfaceStream;
 }
 
 namespace dom {
 class HTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement;
 class ImageData;
 class StringOrCanvasGradientOrCanvasPattern;
 class OwningStringOrCanvasGradientOrCanvasPattern;
 class TextMetrics;
@@ -759,16 +760,18 @@ protected:
   // If mCanvasElement is not provided, then a docshell is
   nsCOMPtr<nsIDocShell> mDocShell;
 
   // This is created lazily so it is necessary to call EnsureTarget before
   // accessing it. In the event of an error it will be equal to
   // sErrorTarget.
   mozilla::RefPtr<mozilla::gfx::DrawTarget> mTarget;
 
+  RefPtr<gl::SurfaceStream> mStream;
+
   /**
     * Flag to avoid duplicate calls to InvalidateFrame. Set to true whenever
     * Redraw is called, reset to false when Render is called.
     */
   bool mIsEntireFrameInvalid;
   /**
     * When this is set, the first call to Redraw(gfxRect) should set
     * mIsEntireFrameInvalid since we expect it will be followed by
--- a/dom/canvas/WebGLContext.cpp
+++ b/dom/canvas/WebGLContext.cpp
@@ -656,23 +656,19 @@ CreateOffscreen(GLContext* gl,
                 layers::ISurfaceAllocator* surfAllocator)
 {
     SurfaceCaps baseCaps;
 
     baseCaps.color = true;
     baseCaps.alpha = options.alpha;
     baseCaps.antialias = options.antialias;
     baseCaps.depth = options.depth;
-    baseCaps.premultAlpha = options.premultipliedAlpha;
     baseCaps.preserve = options.preserveDrawingBuffer;
     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 = Preferences::GetBool("webgl.prefer-16bpp", false);
 
 #ifdef MOZ_WIDGET_GONK
     baseCaps.surfaceAllocator = surfAllocator;
 #endif
@@ -1420,24 +1416,20 @@ WebGLContext::PresentScreenBuffer()
 {
     if (IsContextLost()) {
         return false;
     }
 
     if (!mShouldPresent) {
         return false;
     }
-    MOZ_ASSERT(!mBackbufferNeedsClear);
 
     gl->MakeCurrent();
-
-    GLScreenBuffer* screen = gl->Screen();
-    MOZ_ASSERT(screen);
-
-    if (!screen->PublishFrame(screen->Size())) {
+    MOZ_ASSERT(!mBackbufferNeedsClear);
+    if (!gl->PublishFrame()) {
         ForceLoseContext();
         return false;
     }
 
     if (!mOptions.preserveDrawingBuffer) {
         mBackbufferNeedsClear = true;
     }
 
--- a/gfx/2d/DrawTargetSkia.cpp
+++ b/gfx/2d/DrawTargetSkia.cpp
@@ -159,20 +159,20 @@ SetPaintPattern(SkPaint& aPaint, const P
       GradientStopsSkia *stops = static_cast<GradientStopsSkia*>(pat.mStops.get());
       SkShader::TileMode mode = ExtendModeToTileMode(stops->mExtendMode);
 
       if (stops->mCount >= 2) {
         SkPoint points[2];
         points[0] = SkPoint::Make(SkFloatToScalar(pat.mBegin.x), SkFloatToScalar(pat.mBegin.y));
         points[1] = SkPoint::Make(SkFloatToScalar(pat.mEnd.x), SkFloatToScalar(pat.mEnd.y));
 
-        SkShader* shader = SkGradientShader::CreateLinear(points,
-                                                          &stops->mColors.front(),
-                                                          &stops->mPositions.front(),
-                                                          stops->mCount,
+        SkShader* shader = SkGradientShader::CreateLinear(points, 
+                                                          &stops->mColors.front(), 
+                                                          &stops->mPositions.front(), 
+                                                          stops->mCount, 
                                                           mode);
 
         if (shader) {
             SkMatrix mat;
             GfxMatrixToSkiaMatrix(pat.mMatrix, mat);
             SkShader* matrixShader = SkShader::CreateLocalMatrixShader(shader, mat);
             SkSafeUnref(shader);
             SkSafeUnref(aPaint.setShader(matrixShader));
@@ -188,23 +188,23 @@ SetPaintPattern(SkPaint& aPaint, const P
       GradientStopsSkia *stops = static_cast<GradientStopsSkia*>(pat.mStops.get());
       SkShader::TileMode mode = ExtendModeToTileMode(stops->mExtendMode);
 
       if (stops->mCount >= 2) {
         SkPoint points[2];
         points[0] = SkPoint::Make(SkFloatToScalar(pat.mCenter1.x), SkFloatToScalar(pat.mCenter1.y));
         points[1] = SkPoint::Make(SkFloatToScalar(pat.mCenter2.x), SkFloatToScalar(pat.mCenter2.y));
 
-        SkShader* shader = SkGradientShader::CreateTwoPointConical(points[0],
+        SkShader* shader = SkGradientShader::CreateTwoPointConical(points[0], 
                                                                    SkFloatToScalar(pat.mRadius1),
-                                                                   points[1],
+                                                                   points[1], 
                                                                    SkFloatToScalar(pat.mRadius2),
-                                                                   &stops->mColors.front(),
-                                                                   &stops->mPositions.front(),
-                                                                   stops->mCount,
+                                                                   &stops->mColors.front(), 
+                                                                   &stops->mPositions.front(), 
+                                                                   stops->mCount, 
                                                                    mode);
         if (shader) {
             SkMatrix mat;
             GfxMatrixToSkiaMatrix(pat.mMatrix, mat);
             SkShader* matrixShader = SkShader::CreateLocalMatrixShader(shader, mat);
             SkSafeUnref(shader);
             SkSafeUnref(aPaint.setShader(matrixShader));
         }
@@ -341,17 +341,17 @@ DrawTargetSkia::DrawSurface(SourceSurfac
   }
 
   MarkChanged();
 
   SkRect destRect = RectToSkRect(aDest);
   SkRect sourceRect = RectToSkRect(aSource);
 
   TempBitmap bitmap = GetBitmapForSurface(aSurface);
-
+ 
   AutoPaintSetup paint(mCanvas.get(), aOptions, &aDest);
   if (aSurfOptions.mFilter == Filter::POINT) {
     paint.mPaint.setFilterLevel(SkPaint::kNone_FilterLevel);
   }
 
   mCanvas->drawBitmapRectToRect(bitmap.mBitmap, &sourceRect, destRect, &paint.mPaint);
 }
 
@@ -453,31 +453,31 @@ DrawTargetSkia::StrokeRect(const Rect &a
   AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern);
   if (!StrokeOptionsToPaint(paint.mPaint, aStrokeOptions)) {
     return;
   }
 
   mCanvas->drawRect(RectToSkRect(aRect), paint.mPaint);
 }
 
-void
+void 
 DrawTargetSkia::StrokeLine(const Point &aStart,
                            const Point &aEnd,
                            const Pattern &aPattern,
                            const StrokeOptions &aStrokeOptions,
                            const DrawOptions &aOptions)
 {
   MarkChanged();
   AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern);
   if (!StrokeOptionsToPaint(paint.mPaint, aStrokeOptions)) {
     return;
   }
 
-  mCanvas->drawLine(SkFloatToScalar(aStart.x), SkFloatToScalar(aStart.y),
-                    SkFloatToScalar(aEnd.x), SkFloatToScalar(aEnd.y),
+  mCanvas->drawLine(SkFloatToScalar(aStart.x), SkFloatToScalar(aStart.y), 
+                    SkFloatToScalar(aEnd.x), SkFloatToScalar(aEnd.y), 
                     paint.mPaint);
 }
 
 void
 DrawTargetSkia::Fill(const Path *aPath,
                     const Pattern &aPattern,
                     const DrawOptions &aOptions)
 {
@@ -558,17 +558,17 @@ DrawTargetSkia::Mask(const Pattern &aSou
                      const DrawOptions &aOptions)
 {
   MarkChanged();
   AutoPaintSetup paint(mCanvas.get(), aOptions, aSource);
 
   SkPaint maskPaint;
   TempBitmap tmpBitmap;
   SetPaintPattern(maskPaint, aMask, tmpBitmap);
-
+  
   SkLayerRasterizer::Builder builder;
   builder.addLayer(maskPaint);
   SkAutoTUnref<SkRasterizer> raster(builder.detachRasterizer());
   paint.mPaint.setRasterizer(raster.get());
 
   mCanvas->drawRect(SkRectCoveringWholeSurface(), paint.mPaint);
 }
 
@@ -612,17 +612,17 @@ DrawTargetSkia::CreateSourceSurfaceFromD
                                             SurfaceFormat aFormat) const
 {
   RefPtr<SourceSurfaceSkia> newSurf = new SourceSurfaceSkia();
 
   if (!newSurf->InitFromData(aData, aSize, aStride, aFormat)) {
     gfxDebug() << *this << ": Failure to create source surface from data. Size: " << aSize;
     return nullptr;
   }
-
+    
   return newSurf.forget();
 }
 
 TemporaryRef<DrawTarget>
 DrawTargetSkia::CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const
 {
   RefPtr<DrawTargetSkia> target = new DrawTargetSkia();
   if (!target->Init(aSize, aFormat)) {
@@ -700,33 +700,33 @@ DrawTargetSkia::CopySurface(SourceSurfac
   }
 
   MarkChanged();
 
   TempBitmap bitmap = GetBitmapForSurface(aSurface);
 
   // This is a fast path that is disabled for now to mimimize risk
   if (false && !bitmap.mBitmap.getTexture() && mCanvas->imageInfo() == bitmap.mBitmap.info()) {
-    SkBitmap bm(bitmap.mBitmap);
-    bm.lockPixels();
-    if (bm.getPixels()) {
-      SkImageInfo info = bm.info();
-      info.fWidth = aSourceRect.width;
-      info.fHeight = aSourceRect.height;
-      uint8_t* pixels = static_cast<uint8_t*>(bm.getPixels());
-      // adjust pixels for the source offset
-      pixels += aSourceRect.x + aSourceRect.y*bm.rowBytes();
-      mCanvas->writePixels(info, pixels, bm.rowBytes(), aDestination.x, aDestination.y);
-      return;
-    }
+	SkBitmap bm(bitmap.mBitmap);
+	bm.lockPixels();
+	if (bm.getPixels()) {
+	  SkImageInfo info = bm.info();
+	  info.fWidth = aSourceRect.width;
+	  info.fHeight = aSourceRect.height;
+	  uint8_t* pixels = static_cast<uint8_t*>(bm.getPixels());
+	  // adjust pixels for the source offset
+	  pixels += aSourceRect.x + aSourceRect.y*bm.rowBytes();
+	  mCanvas->writePixels(info, pixels, bm.rowBytes(), aDestination.x, aDestination.y);
+	  return;
+	}
   }
 
   mCanvas->save();
   mCanvas->resetMatrix();
-  SkRect dest = IntRectToSkRect(IntRect(aDestination.x, aDestination.y, aSourceRect.width, aSourceRect.height));
+  SkRect dest = IntRectToSkRect(IntRect(aDestination.x, aDestination.y, aSourceRect.width, aSourceRect.height)); 
   SkIRect source = IntRectToSkIRect(aSourceRect);
   mCanvas->clipRect(dest, SkRegion::kReplace_Op);
   SkPaint paint;
 
   if (mCanvas->imageInfo().colorType() == kRGB_565_SkColorType) {
     // Set the xfermode to SOURCE_OVER to workaround
     // http://code.google.com/p/skia/issues/detail?id=628
     // RGB565 is opaque so they're equivalent anyway
@@ -847,21 +847,21 @@ DrawTargetSkia::SetTransform(const Matri
 
 void*
 DrawTargetSkia::GetNativeSurface(NativeSurfaceType aType)
 {
   if (aType == NativeSurfaceType::OPENGL_TEXTURE) {
     return (void*)((uintptr_t)mTexture);
   }
 
-  return nullptr;
+  return nullptr;  
 }
 
 
-TemporaryRef<PathBuilder>
+TemporaryRef<PathBuilder> 
 DrawTargetSkia::CreatePathBuilder(FillRule aFillRule) const
 {
   return new PathBuilderSkia(aFillRule);
 }
 
 void
 DrawTargetSkia::ClearRect(const Rect &aRect)
 {
@@ -906,17 +906,17 @@ TemporaryRef<GradientStops>
 DrawTargetSkia::CreateGradientStops(GradientStop *aStops, uint32_t aNumStops, ExtendMode aExtendMode) const
 {
   std::vector<GradientStop> stops;
   stops.resize(aNumStops);
   for (uint32_t i = 0; i < aNumStops; i++) {
     stops[i] = aStops[i];
   }
   std::stable_sort(stops.begin(), stops.end());
-
+  
   return new GradientStopsSkia(stops, aNumStops, aExtendMode);
 }
 
 TemporaryRef<FilterNode>
 DrawTargetSkia::CreateFilter(FilterType aType)
 {
   return FilterNodeSoftware::Create(aType);
 }
--- a/gfx/2d/HelpersCairo.h
+++ b/gfx/2d/HelpersCairo.h
@@ -136,17 +136,16 @@ GfxFormatToCairoFormat(SurfaceFormat for
     case SurfaceFormat::B8G8R8X8:
       return CAIRO_FORMAT_RGB24;
     case SurfaceFormat::A8:
       return CAIRO_FORMAT_A8;
     case SurfaceFormat::R5G6B5:
       return CAIRO_FORMAT_RGB16_565;
     default:
       gfxWarning() << "Unknown image format";
-      MOZ_ASSERT(false, "Unknown image format");
       return CAIRO_FORMAT_ARGB32;
   }
 }
 
 static inline cairo_content_t
 GfxFormatToCairoContent(SurfaceFormat format)
 {
   switch (format)
@@ -155,17 +154,16 @@ GfxFormatToCairoContent(SurfaceFormat fo
       return CAIRO_CONTENT_COLOR_ALPHA;
     case SurfaceFormat::B8G8R8X8:
     case SurfaceFormat::R5G6B5:  //fall through
       return CAIRO_CONTENT_COLOR;
     case SurfaceFormat::A8:
       return CAIRO_CONTENT_ALPHA;
     default:
       gfxWarning() << "Unknown image format";
-      MOZ_ASSERT(false, "Unknown image format");
       return CAIRO_CONTENT_COLOR_ALPHA;
   }
 }
 
 static inline cairo_line_join_t
 GfxLineJoinToCairoLineJoin(JoinStyle style)
 {
   switch (style)
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -19,16 +19,17 @@
 #include "GLContextProvider.h"
 #include "GLTextureImage.h"
 #include "nsPrintfCString.h"
 #include "nsThreadUtils.h"
 #include "prenv.h"
 #include "prlink.h"
 #include "ScopedGLHelpers.h"
 #include "SharedSurfaceGL.h"
+#include "SurfaceStream.h"
 #include "GfxTexturesReporter.h"
 #include "TextureGarbageBin.h"
 #include "gfx2DGlue.h"
 #include "gfxPrefs.h"
 #include "mozilla/IntegerPrintfMacros.h"
 
 #include "OGLShaderProgram.h" // for ShaderProgramType
 
@@ -1986,16 +1987,35 @@ GLContext::AssembleOffscreenFBs(const GL
     } else if (readFB) {
         NS_RUNTIMEABORT("readFB created when not requested!");
     }
 
     return isComplete;
 }
 
 
+
+bool
+GLContext::PublishFrame()
+{
+    MOZ_ASSERT(mScreen);
+
+    return mScreen->PublishFrame(OffscreenSize());
+}
+
+SharedSurface*
+GLContext::RequestFrame()
+{
+    MOZ_ASSERT(mScreen);
+
+    return mScreen->Stream()->SwapConsumer();
+}
+
+
+
 void
 GLContext::ClearSafely()
 {
     // bug 659349 --- we must be very careful here: clearing a GL framebuffer is nontrivial, relies on a lot of state,
     // and in the case of the backbuffer of a WebGL context, state is exposed to scripts.
     //
     // The code here is taken from WebGLContext::ForceClearFramebufferWithDefaultValues, but I didn't find a good way of
     // sharing code with it. WebGL's code is somewhat performance-critical as it is typically called on every frame, so
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -1571,24 +1571,26 @@ public:
     }
 
     void fReadBuffer(GLenum mode) {
         BEFORE_GL_CALL;
         mSymbols.fReadBuffer(mode);
         AFTER_GL_CALL;
     }
 
+private:
     void raw_fReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels) {
         ASSERT_NOT_PASSING_STACK_BUFFER_TO_GL(pixels);
         BEFORE_GL_CALL;
         mSymbols.fReadPixels(x, y, width, height, format, type, pixels);
         AFTER_GL_CALL;
         mHeavyGLCallsSinceLastFlush = true;
     }
 
+public:
     void fReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels) {
         BeforeGLReadCall();
 
         bool didReadPixels = false;
         if (mScreen) {
             didReadPixels = mScreen->ReadPixels(x, y, width, height, format, type, pixels);
         }
 
@@ -3524,16 +3526,19 @@ public:
     bool IsOffscreen() const {
         return mScreen;
     }
 
     GLScreenBuffer* Screen() const {
         return mScreen.get();
     }
 
+    bool PublishFrame();
+    SharedSurface* RequestFrame();
+
     /* Clear to transparent black, with 0 depth and stencil,
      * while preserving current ClearColor etc. values.
      * Useful for resizing offscreen buffers.
      */
     void ClearSafely();
 
     bool WorkAroundDriverBugs() const { return mWorkAroundDriverBugs; }
 
--- a/gfx/gl/GLReadTexImageHelper.cpp
+++ b/gfx/gl/GLReadTexImageHelper.cpp
@@ -150,29 +150,26 @@ GLReadTexImageHelper::DidGLErrorOccur(co
         printf_stderr("GL ERROR: %s (0x%04x) %s\n",
                       mGL->GLErrorToString(error), error, str);
         return true;
     }
 
     return false;
 }
 
-bool
+static bool
 GetActualReadFormats(GLContext* gl,
                      GLenum destFormat, GLenum destType,
-                     GLenum* out_readFormat, GLenum* out_readType)
+                     GLenum& readFormat, GLenum& readType)
 {
-    MOZ_ASSERT(out_readFormat);
-    MOZ_ASSERT(out_readType);
-
     if (destFormat == LOCAL_GL_RGBA &&
         destType == LOCAL_GL_UNSIGNED_BYTE)
     {
-        *out_readFormat = destFormat;
-        *out_readType = destType;
+        readFormat = destFormat;
+        readType = destType;
         return true;
     }
 
     bool fallback = true;
     if (gl->IsGLES()) {
         GLenum auxFormat = 0;
         GLenum auxType = 0;
 
@@ -187,33 +184,30 @@ GetActualReadFormats(GLContext* gl,
     } else {
         switch (destFormat) {
             case LOCAL_GL_RGB: {
                 if (destType == LOCAL_GL_UNSIGNED_SHORT_5_6_5_REV)
                     fallback = false;
                 break;
             }
             case LOCAL_GL_BGRA: {
-                if (destType == LOCAL_GL_UNSIGNED_BYTE ||
-                    destType == LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV)
-                {
+                if (destType == LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV)
                     fallback = false;
-                }
                 break;
             }
         }
     }
 
     if (fallback) {
-        *out_readFormat = LOCAL_GL_RGBA;
-        *out_readType = LOCAL_GL_UNSIGNED_BYTE;
+        readFormat = LOCAL_GL_RGBA;
+        readType = LOCAL_GL_UNSIGNED_BYTE;
         return false;
     } else {
-        *out_readFormat = destFormat;
-        *out_readType = destType;
+        readFormat = destFormat;
+        readType = destType;
         return true;
     }
 }
 
 static void
 SwapRAndBComponents(DataSourceSurface* surf)
 {
     DataSourceSurface::MappedSurface map;
@@ -396,17 +390,17 @@ ReadPixelsIntoDataSurface(GLContext* gl,
     }
     destPixelSize = BytesPerPixel(dest->GetFormat());
     MOZ_ASSERT(dest->GetSize().width * destPixelSize <= dest->Stride());
 
     GLenum readFormat = destFormat;
     GLenum readType = destType;
     bool needsTempSurf = !GetActualReadFormats(gl,
                                                destFormat, destType,
-                                               &readFormat, &readType);
+                                               readFormat, readType);
 
     RefPtr<DataSourceSurface> tempSurf;
     DataSourceSurface* readSurf = dest;
     int readAlignment = GuessAlignment(dest->GetSize().width,
                                        destPixelSize,
                                        dest->Stride());
     if (!readAlignment) {
         needsTempSurf = true;
--- a/gfx/gl/GLReadTexImageHelper.h
+++ b/gfx/gl/GLReadTexImageHelper.h
@@ -17,22 +17,16 @@
 namespace mozilla {
 
 namespace gfx {
 class DataSourceSurface;
 }
 
 namespace gl {
 
-// Returns true if the `dest{Format,Type}` are the same as the
-// `read{Format,Type}`.
-bool GetActualReadFormats(GLContext* gl,
-                          GLenum destFormat, GLenum destType,
-                          GLenum* out_readFormat, GLenum* out_readType);
-
 void ReadPixelsIntoDataSurface(GLContext* aGL,
                                gfx::DataSourceSurface* aSurface);
 
 TemporaryRef<gfx::DataSourceSurface>
 ReadBackSurface(GLContext* gl, GLuint aTexture, bool aYInvert, gfx::SurfaceFormat aFormat);
 
 class GLReadTexImageHelper MOZ_FINAL
 {
--- a/gfx/gl/GLScreenBuffer.cpp
+++ b/gfx/gl/GLScreenBuffer.cpp
@@ -1,21 +1,21 @@
 /* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */
 /* 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 "GLScreenBuffer.h"
 
 #include <cstring>
-#include "CompositorTypes.h"
 #include "GLContext.h"
 #include "GLBlitHelper.h"
 #include "GLReadTexImageHelper.h"
 #include "SharedSurfaceGL.h"
+#include "SurfaceStream.h"
 #ifdef MOZ_WIDGET_GONK
 #include "SharedSurfaceGralloc.h"
 #include "nsXULAppAPI.h"
 #endif
 #ifdef XP_MACOSX
 #include "SharedSurfaceIO.h"
 #endif
 #include "ScopedGLHelpers.h"
@@ -38,43 +38,40 @@ GLScreenBuffer::Create(GLContext* gl,
     {
         return Move(ret);
     }
 
     UniquePtr<SurfaceFactory> factory;
 
 #ifdef MOZ_WIDGET_GONK
     /* On B2G, we want a Gralloc factory, and we want one right at the start */
-    layers::ISurfaceAllocator* allocator = caps.surfaceAllocator;
     if (!factory &&
-        allocator &&
+        caps.surfaceAllocator &&
         XRE_GetProcessType() != GeckoProcessType_Default)
     {
-        layers::TextureFlags flags = layers::TextureFlags::DEALLOCATE_CLIENT |
-                                     layers::TextureFlags::NEEDS_Y_FLIP;
-        if (!caps.premultAlpha) {
-            flags |= layers::TextureFlags::NON_PREMULTIPLIED;
-        }
-
-        factory = MakeUnique<SurfaceFactory_Gralloc>(gl, caps, flags,
-                                                     allocator);
+        factory = MakeUnique<SurfaceFactory_Gralloc>(gl, caps);
     }
 #endif
 #ifdef XP_MACOSX
     /* On OSX, we want an IOSurface factory, and we want one right at the start */
     if (!factory) {
         factory = SurfaceFactory_IOSurface::Create(gl, caps);
     }
 #endif
 
     if (!factory) {
         factory = MakeUnique<SurfaceFactory_Basic>(gl, caps);
     }
 
-    ret.reset( new GLScreenBuffer(gl, caps, Move(factory)) );
+    auto streamType = SurfaceStream::ChooseGLStreamType(SurfaceStream::MainThread,
+                                                        caps.preserve);
+    RefPtr<SurfaceStream> stream;
+    stream = SurfaceStream::CreateForType(streamType, gl, nullptr);
+
+    ret.reset( new GLScreenBuffer(gl, caps, Move(factory), stream) );
     return Move(ret);
 }
 
 GLScreenBuffer::~GLScreenBuffer()
 {
     mDraw = nullptr;
     mRead = nullptr;
 
@@ -373,20 +370,30 @@ GLScreenBuffer::AssureBlitted()
                                   LOCAL_GL_NEAREST);
         // Done!
     }
 
     mNeedsBlit = false;
 }
 
 void
-GLScreenBuffer::Morph(UniquePtr<SurfaceFactory> newFactory)
+GLScreenBuffer::Morph(UniquePtr<SurfaceFactory> newFactory,
+                      SurfaceStreamType streamType)
 {
-    MOZ_ASSERT(newFactory);
-    mFactory = Move(newFactory);
+    MOZ_ASSERT(mStream);
+
+    if (newFactory) {
+        mFactory = Move(newFactory);
+    }
+
+    if (mStream->mType == streamType)
+        return;
+
+    mStream = SurfaceStream::CreateForType(streamType, mGL, mStream);
+    MOZ_ASSERT(mStream);
 }
 
 bool
 GLScreenBuffer::Attach(SharedSurface* surf, const gfx::IntSize& size)
 {
     ScopedBindFramebuffer autoFB(mGL);
 
     if (mRead && SharedSurf())
@@ -416,71 +423,57 @@ GLScreenBuffer::Attach(SharedSurface* su
 
         mDraw = Move(draw);
         mRead = Move(read);
     }
 
     // Check that we're all set up.
     MOZ_ASSERT(SharedSurf() == surf);
 
+    if (!PreserveBuffer()) {
+        // DiscardFramebuffer here could help perf on some mobile platforms.
+    }
+
     return true;
 }
 
 bool
 GLScreenBuffer::Swap(const gfx::IntSize& size)
 {
-    RefPtr<ShSurfHandle> newBack = mFactory->NewShSurfHandle(size);
-    if (!newBack)
-        return false;
-
-    if (!Attach(newBack->Surf(), size))
-        return false;
-    // Attach was successful.
-
-    mFront = mBack;
-    mBack = newBack;
+    SharedSurface* nextSurf = mStream->SwapProducer(mFactory.get(), size);
+    if (!nextSurf) {
+        SurfaceFactory_Basic basicFactory(mGL, mFactory->mCaps);
+        nextSurf = mStream->SwapProducer(&basicFactory, size);
+        if (!nextSurf)
+          return false;
 
-    // Fence before copying.
-    if (mFront) {
-        mFront->Surf()->Fence();
+        NS_WARNING("SwapProd failed for sophisticated Factory type, fell back to Basic.");
     }
+    MOZ_ASSERT(nextSurf);
 
-    if (ShouldPreserveBuffer() &&
-        mFront &&
-        mBack)
-    {
-        auto src  = mFront->Surf();
-        auto dest = mBack->Surf();
-        SharedSurface::ProdCopy(src, dest, mFactory.get());
-    }
-
-    return true;
+    return Attach(nextSurf, size);
 }
 
 bool
 GLScreenBuffer::PublishFrame(const gfx::IntSize& size)
 {
     AssureBlitted();
 
     bool good = Swap(size);
     return good;
 }
 
 bool
 GLScreenBuffer::Resize(const gfx::IntSize& size)
 {
-    RefPtr<ShSurfHandle> newBack = mFactory->NewShSurfHandle(size);
-    if (!newBack)
+    SharedSurface* surf = mStream->Resize(mFactory.get(), size);
+    if (!surf)
         return false;
 
-    if (!Attach(newBack->Surf(), size))
-        return false;
-
-    mBack = newBack;
-    return true;
+    return Attach(surf, size);
 }
 
 bool
 GLScreenBuffer::CreateDraw(const gfx::IntSize& size,
                            UniquePtr<DrawBuffer>* out_buffer)
 {
     GLContext* gl = mFactory->mGL;
     const GLFormats& formats = mFactory->mFormats;
@@ -510,16 +503,17 @@ GLScreenBuffer::Readback(SharedSurface* 
   mGL->MakeCurrent();
 
   bool needsSwap = src != SharedSurf();
   if (needsSwap) {
       SharedSurf()->UnlockProd();
       src->LockProd();
   }
 
+
   {
       UniquePtr<ReadBuffer> buffer = CreateRead(src);
       MOZ_ASSERT(buffer);
 
       ScopedBindFramebuffer autoFB(mGL, buffer->mFB);
       ReadPixelsIntoDataSurface(mGL, dest);
   }
 
--- a/gfx/gl/GLScreenBuffer.h
+++ b/gfx/gl/GLScreenBuffer.h
@@ -10,31 +10,30 @@
  * so that even if you want to draw to the 'screen', even if that's not
  * actually the screen, just draw to 0. This GLScreenBuffer class takes the
  * logic handling out of GLContext.
 */
 
 #ifndef SCREEN_BUFFER_H_
 #define SCREEN_BUFFER_H_
 
+#include "SurfaceTypes.h"
+#include "SurfaceStream.h"
 #include "GLContextTypes.h"
 #include "GLDefs.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/gfx/Point.h"
 #include "mozilla/UniquePtr.h"
-#include "SharedSurface.h"
-#include "SurfaceTypes.h"
 
 namespace mozilla {
 namespace gl {
 
 class GLContext;
 class SharedSurface;
-class ShSurfHandle;
-class SurfaceFactory;
+class SurfaceStream;
 
 class DrawBuffer
 {
 public:
     // Fallible!
     // But it may return true with *out_buffer==nullptr if unneeded.
     static bool Create(GLContext* const gl,
                        const SurfaceCaps& caps,
@@ -83,17 +82,17 @@ protected:
     GLContext* const mGL;
 public:
     const GLuint mFB;
 protected:
     // mFB has the following attachments:
     const GLuint mDepthRB;
     const GLuint mStencilRB;
     // note no mColorRB here: this is provided by mSurf.
-    SharedSurface* mSurf;
+    SharedSurface* mSurf; // Owned by GLScreenBuffer's SurfaceStream.
 
     ReadBuffer(GLContext* gl,
                GLuint fb,
                GLuint depthRB,
                GLuint stencilRB,
                SharedSurface* surf)
         : mGL(gl)
         , mFB(fb)
@@ -125,19 +124,17 @@ public:
                                             const SurfaceCaps& caps);
 
 protected:
     GLContext* const mGL; // Owns us.
 public:
     const SurfaceCaps mCaps;
 protected:
     UniquePtr<SurfaceFactory> mFactory;
-
-    RefPtr<ShSurfHandle> mBack;
-    RefPtr<ShSurfHandle> mFront;
+    RefPtr<SurfaceStream> mStream;
 
     UniquePtr<DrawBuffer> mDraw;
     UniquePtr<ReadBuffer> mRead;
 
     bool mNeedsBlit;
 
     // Below are the parts that help us pretend to be framebuffer 0:
     GLuint mUserDrawFB;
@@ -147,48 +144,52 @@ protected:
 
 #ifdef DEBUG
     bool mInInternalMode_DrawFB;
     bool mInInternalMode_ReadFB;
 #endif
 
     GLScreenBuffer(GLContext* gl,
                    const SurfaceCaps& caps,
-                   UniquePtr<SurfaceFactory> factory)
+                   UniquePtr<SurfaceFactory> factory,
+                   const RefPtr<SurfaceStream>& stream)
         : mGL(gl)
         , mCaps(caps)
         , mFactory(Move(factory))
+        , mStream(stream)
+        , mDraw(nullptr)
+        , mRead(nullptr)
         , mNeedsBlit(true)
         , mUserDrawFB(0)
         , mUserReadFB(0)
         , mInternalDrawFB(0)
         , mInternalReadFB(0)
 #ifdef DEBUG
         , mInInternalMode_DrawFB(true)
         , mInInternalMode_ReadFB(true)
 #endif
     {}
 
 public:
     virtual ~GLScreenBuffer();
 
+    SurfaceStream* Stream() const {
+        return mStream;
+    }
+
     SurfaceFactory* Factory() const {
         return mFactory.get();
     }
 
-    ShSurfHandle* Front() const {
-        return mFront;
-    }
-
     SharedSurface* SharedSurf() const {
         MOZ_ASSERT(mRead);
         return mRead->SharedSurf();
     }
 
-    bool ShouldPreserveBuffer() const {
+    bool PreserveBuffer() const {
         return mCaps.preserve;
     }
 
     GLuint DrawFB() const {
         if (!mDraw)
             return ReadFB();
 
         return mDraw->mFB;
@@ -218,18 +219,30 @@ public:
      * it is backed by a SharedSurface.
      *
      * Returns true if the pixel data has been read back, false
      * otherwise.
      */
     bool ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
                     GLenum format, GLenum type, GLvoid *pixels);
 
-    // Morph changes the factory used to create surfaces.
-    void Morph(UniquePtr<SurfaceFactory> newFactory);
+    /* Morph swaps out our SurfaceStream mechanism and replaces it with
+     * one best suited to our platform and compositor configuration.
+     *
+     * Must be called on the producing thread.
+     * We haven't made any guarantee that rendering is actually
+     * done when Morph is run, just that it can't run concurrently
+     * with rendering. This means that we can't just drop the contents
+     * of the buffer, since we may only be partially done rendering.
+     *
+     * Once you pass newFactory into Morph, newFactory will be owned by
+     * GLScreenBuffer, so `forget` any references to it that still exist.
+     */
+    void Morph(UniquePtr<SurfaceFactory> newFactory,
+               SurfaceStreamType streamType);
 
 protected:
     // Returns false on error or inability to resize.
     bool Swap(const gfx::IntSize& size);
 
 public:
     bool PublishFrame(const gfx::IntSize& size);
 
--- a/gfx/gl/GLUploadHelpers.cpp
+++ b/gfx/gl/GLUploadHelpers.cpp
@@ -425,17 +425,16 @@ UploadImageDataToTexture(GLContext* gl,
     GLenum format = 0;
     GLenum internalFormat = 0;
     GLenum type = 0;
     int32_t pixelSize = BytesPerPixel(aFormat);
     SurfaceFormat surfaceFormat = gfx::SurfaceFormat::UNKNOWN;
 
     MOZ_ASSERT(gl->GetPreferredARGB32Format() == LOCAL_GL_BGRA ||
                gl->GetPreferredARGB32Format() == LOCAL_GL_RGBA);
-
     switch (aFormat) {
         case SurfaceFormat::B8G8R8A8:
             if (gl->GetPreferredARGB32Format() == LOCAL_GL_BGRA) {
               format = LOCAL_GL_BGRA;
               surfaceFormat = SurfaceFormat::R8G8B8A8;
               type = LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV;
             } else {
               format = LOCAL_GL_RGBA;
@@ -453,44 +452,16 @@ UploadImageDataToTexture(GLContext* gl,
               type = LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV;
             } else {
               format = LOCAL_GL_RGBA;
               surfaceFormat = SurfaceFormat::B8G8R8X8;
               type = LOCAL_GL_UNSIGNED_BYTE;
             }
             internalFormat = LOCAL_GL_RGBA;
             break;
-        case SurfaceFormat::R8G8B8A8:
-            if (gl->GetPreferredARGB32Format() == LOCAL_GL_BGRA) {
-              // Upload our RGBA as BGRA, but store that the uploaded format is
-              // BGRA. (sample from R to get B)
-              format = LOCAL_GL_BGRA;
-              type = LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV;
-              surfaceFormat = SurfaceFormat::B8G8R8A8;
-            } else {
-              format = LOCAL_GL_RGBA;
-              type = LOCAL_GL_UNSIGNED_BYTE;
-              surfaceFormat = SurfaceFormat::R8G8B8A8;
-            }
-            internalFormat = LOCAL_GL_RGBA;
-            break;
-        case SurfaceFormat::R8G8B8X8:
-            // Treat RGBX surfaces as RGBA except for the surface
-            // format used.
-            if (gl->GetPreferredARGB32Format() == LOCAL_GL_BGRA) {
-              format = LOCAL_GL_BGRA;
-              type = LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV;
-              surfaceFormat = SurfaceFormat::B8G8R8X8;
-            } else {
-              format = LOCAL_GL_RGBA;
-              type = LOCAL_GL_UNSIGNED_BYTE;
-              surfaceFormat = SurfaceFormat::R8G8B8X8;
-            }
-            internalFormat = LOCAL_GL_RGBA;
-            break;
         case SurfaceFormat::R5G6B5:
             internalFormat = format = LOCAL_GL_RGB;
             type = LOCAL_GL_UNSIGNED_SHORT_5_6_5;
             surfaceFormat = SurfaceFormat::R5G6B5;
             break;
         case SurfaceFormat::A8:
             internalFormat = format = LOCAL_GL_LUMINANCE;
             type = LOCAL_GL_UNSIGNED_BYTE;
--- a/gfx/gl/ScopedGLHelpers.cpp
+++ b/gfx/gl/ScopedGLHelpers.cpp
@@ -6,24 +6,16 @@
 #include "mozilla/UniquePtr.h"
 
 #include "GLContext.h"
 #include "ScopedGLHelpers.h"
 
 namespace mozilla {
 namespace gl {
 
-#ifdef DEBUG
-bool
-IsContextCurrent(GLContext* gl)
-{
-    return gl->IsCurrent();
-}
-#endif
-
 /* ScopedGLState - Wraps glEnable/glDisable. **********************************/
 
 // Use |newState = true| to enable, |false| to disable.
 ScopedGLState::ScopedGLState(GLContext* aGL, GLenum aCapability, bool aNewState)
     : ScopedGLWrapper<ScopedGLState>(aGL)
     , mCapability(aCapability)
 {
     mOldState = mGL->fIsEnabled(mCapability);
@@ -486,42 +478,10 @@ ScopedGLDrawState::~ScopedGLDrawState()
                               attrib0_normalized,
                               attrib0_stride,
                               attrib0_pointer);
 
     mGL->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, boundBuffer);
 
     mGL->fUseProgram(boundProgram);
 }
-
-////////////////////////////////////////////////////////////////////////
-// ScopedPackAlignment
-
-ScopedPackAlignment::ScopedPackAlignment(GLContext* gl, GLint scopedVal)
-    : ScopedGLWrapper<ScopedPackAlignment>(gl)
-{
-    MOZ_ASSERT(scopedVal == 1 ||
-               scopedVal == 2 ||
-               scopedVal == 4 ||
-               scopedVal == 8);
-
-    gl->fGetIntegerv(LOCAL_GL_PACK_ALIGNMENT, &mOldVal);
-
-    if (scopedVal != mOldVal) {
-        gl->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, scopedVal);
-    } else {
-      // Don't try to re-set it during unwrap.
-        mOldVal = 0;
-    }
-}
-
-void
-ScopedPackAlignment::UnwrapImpl() {
-    // Check that we're not falling out of scope after the current context changed.
-    MOZ_ASSERT(mGL->IsCurrent());
-
-    if (mOldVal) {
-        mGL->fPixelStorei(LOCAL_GL_PACK_ALIGNMENT, mOldVal);
-    }
-}
-
 } /* namespace gl */
 } /* namespace mozilla */
--- a/gfx/gl/ScopedGLHelpers.h
+++ b/gfx/gl/ScopedGLHelpers.h
@@ -1,45 +1,40 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef SCOPEDGLHELPERS_H_
 #define SCOPEDGLHELPERS_H_
 
-#include "GLDefs.h"
 #include "mozilla/UniquePtr.h"
 
+#include "GLContext.h"
+
 namespace mozilla {
 namespace gl {
 
-class GLContext;
-
-#ifdef DEBUG
-bool IsContextCurrent(GLContext* gl);
-#endif
-
 //RAII via CRTP!
 template <class Derived>
 struct ScopedGLWrapper
 {
 private:
     bool mIsUnwrapped;
 
 protected:
     GLContext* const mGL;
 
     explicit ScopedGLWrapper(GLContext* gl)
         : mIsUnwrapped(false)
         , mGL(gl)
     {
         MOZ_ASSERT(&ScopedGLWrapper<Derived>::Unwrap == &Derived::Unwrap);
         MOZ_ASSERT(&Derived::UnwrapImpl);
-        MOZ_ASSERT(IsContextCurrent(mGL));
+        MOZ_ASSERT(mGL->IsCurrent());
     }
 
     virtual ~ScopedGLWrapper() {
         if (!mIsUnwrapped)
             Unwrap();
     }
 
 public:
@@ -338,27 +333,12 @@ struct ScopedGLDrawState {
     void* attrib0_pointer;
 
     realGLboolean colorMask[4];
     GLint viewport[4];
     GLint scissorBox[4];
     GLContext* const mGL;
     GLuint packAlign;
 };
-
-struct ScopedPackAlignment
-    : public ScopedGLWrapper<ScopedPackAlignment>
-{
-    friend struct ScopedGLWrapper<ScopedPackAlignment>;
-
-protected:
-    GLint mOldVal;
-
-public:
-    ScopedPackAlignment(GLContext* aGL, GLint scopedVal);
-
-protected:
-    void UnwrapImpl();
-};
 } /* namespace gl */
 } /* namespace mozilla */
 
 #endif /* SCOPEDGLHELPERS_H_ */
--- a/gfx/gl/SharedSurface.cpp
+++ b/gfx/gl/SharedSurface.cpp
@@ -327,125 +327,21 @@ SurfaceFactory::NewSharedSurface(const g
 
         // Let `cur` be destroyed as it falls out of scope, if it wasn't
         // moved.
     }
 
     return CreateShared(size);
 }
 
-TemporaryRef<ShSurfHandle>
-SurfaceFactory::NewShSurfHandle(const gfx::IntSize& size)
-{
-    auto surf = NewSharedSurface(size);
-    if (!surf)
-        return nullptr;
-
-    return new ShSurfHandle(this, Move(surf));
-}
-
 // Auto-deletes surfs of the wrong type.
 void
 SurfaceFactory::Recycle(UniquePtr<SharedSurface> surf)
 {
     MOZ_ASSERT(surf);
 
     if (surf->mType == mType) {
         mScraps.Push(Move(surf));
     }
 }
 
-////////////////////////////////////////////////////////////////////////////////
-// ScopedReadbackFB
-
-ScopedReadbackFB::ScopedReadbackFB(SharedSurface* src)
-    : mGL(src->mGL)
-    , mAutoFB(mGL)
-    , mTempFB(0)
-    , mTempTex(0)
-    , mSurfToUnlock(nullptr)
-    , mSurfToLock(nullptr)
-{
-    switch (src->mAttachType) {
-    case AttachmentType::GLRenderbuffer:
-        {
-            mGL->fGenFramebuffers(1, &mTempFB);
-            mGL->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mTempFB);
-
-            GLuint rb = src->ProdRenderbuffer();
-            mGL->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
-                                          LOCAL_GL_COLOR_ATTACHMENT0,
-                                          LOCAL_GL_RENDERBUFFER, rb);
-            break;
-        }
-    case AttachmentType::GLTexture:
-        {
-            mGL->fGenFramebuffers(1, &mTempFB);
-            mGL->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mTempFB);
-
-            GLuint tex = src->ProdTexture();
-            GLenum texImageTarget = src->ProdTextureTarget();
-            mGL->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
-                                       LOCAL_GL_COLOR_ATTACHMENT0,
-                                       texImageTarget, tex, 0);
-            break;
-        }
-    case AttachmentType::Screen:
-        {
-            SharedSurface* origLocked = mGL->GetLockedSurface();
-            if (origLocked != src) {
-                if (origLocked) {
-                    mSurfToLock = origLocked;
-                    mSurfToLock->UnlockProd();
-                }
-
-                mSurfToUnlock = src;
-                mSurfToUnlock->LockProd();
-            }
-
-            // TODO: This should just be BindFB, but we don't have
-            // the patch for this yet. (bug 1045955)
-            MOZ_ASSERT(mGL->Screen());
-            mGL->Screen()->BindReadFB_Internal(0);
-            break;
-        }
-    default:
-        MOZ_CRASH("Unhandled `mAttachType`.");
-    }
-
-    if (src->NeedsIndirectReads()) {
-        mGL->fGenTextures(1, &mTempTex);
-
-        {
-            ScopedBindTexture autoTex(mGL, mTempTex);
-
-            GLenum format = src->mHasAlpha ? LOCAL_GL_RGBA
-                                           : LOCAL_GL_RGB;
-            auto width = src->mSize.width;
-            auto height = src->mSize.height;
-            mGL->fCopyTexImage2D(LOCAL_GL_TEXTURE_2D, 0, format, 0, 0, width,
-                                 height, 0);
-        }
-
-        mGL->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
-                                   LOCAL_GL_COLOR_ATTACHMENT0,
-                                   LOCAL_GL_TEXTURE_2D, mTempTex, 0);
-    }
-}
-
-ScopedReadbackFB::~ScopedReadbackFB()
-{
-    if (mTempFB) {
-        mGL->fDeleteFramebuffers(1, &mTempFB);
-    }
-    if (mTempTex) {
-        mGL->fDeleteTextures(1, &mTempTex);
-    }
-    if (mSurfToUnlock) {
-        mSurfToUnlock->UnlockProd();
-    }
-    if (mSurfToLock) {
-        mSurfToLock->LockProd();
-    }
-}
-
 } /* namespace gfx */
 } /* namespace mozilla */
--- a/gfx/gl/SharedSurface.h
+++ b/gfx/gl/SharedSurface.h
@@ -20,27 +20,25 @@
 
 #include "GLContextTypes.h"
 #include "GLDefs.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/gfx/Point.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/WeakPtr.h"
-#include "ScopedGLHelpers.h"
 #include "SurfaceTypes.h"
 
 class nsIThread;
 
 namespace mozilla {
 namespace gl {
 
 class GLContext;
 class SurfaceFactory;
-class ShSurfHandle;
 
 class SharedSurface
 {
 public:
     static void ProdCopy(SharedSurface* src, SharedSurface* dest,
                          SurfaceFactory* factory);
 
     const SharedSurfaceType mType;
@@ -123,20 +121,16 @@ public:
 
     virtual bool ReadPixels(GLint x, GLint y,
                             GLsizei width, GLsizei height,
                             GLenum format, GLenum type,
                             GLvoid* pixels)
     {
         return false;
     }
-
-    virtual bool NeedsIndirectReads() const {
-        return false;
-    }
 };
 
 template<typename T>
 class UniquePtrQueue
 {
     std::queue<T*> mQueue;
 
 public:
@@ -160,23 +154,19 @@ public:
             ret.reset(mQueue.front());
             mQueue.pop();
         }
 
         return Move(ret);
     }
 };
 
-class SurfaceFactory : public SupportsWeakPtr<SurfaceFactory>
+class SurfaceFactory
 {
 public:
-    // Should use the VIRTUAL version, but it's currently incompatible
-    // with SupportsWeakPtr. (bug 1049278)
-    MOZ_DECLARE_REFCOUNTED_TYPENAME(SurfaceFactory)
-
     GLContext* const mGL;
     const SurfaceCaps mCaps;
     const SharedSurfaceType mType;
     const GLFormats mFormats;
 
 protected:
     SurfaceCaps mDrawCaps;
     SurfaceCaps mReadCaps;
@@ -198,62 +188,17 @@ public:
 
 protected:
     virtual UniquePtr<SharedSurface> CreateShared(const gfx::IntSize& size) = 0;
 
     UniquePtrQueue<SharedSurface> mScraps;
 
 public:
     UniquePtr<SharedSurface> NewSharedSurface(const gfx::IntSize& size);
-    TemporaryRef<ShSurfHandle> NewShSurfHandle(const gfx::IntSize& size);
 
     // Auto-deletes surfs of the wrong type.
     void Recycle(UniquePtr<SharedSurface> surf);
 };
 
-class ShSurfHandle : public RefCounted<ShSurfHandle>
-{
-public:
-    MOZ_DECLARE_REFCOUNTED_TYPENAME(ShSurfHandle)
-
-private:
-    const WeakPtr<SurfaceFactory> mFactory;
-    UniquePtr<SharedSurface> mSurf;
-
-public:
-    ShSurfHandle(SurfaceFactory* factory, UniquePtr<SharedSurface> surf)
-        : mFactory(factory)
-        , mSurf(Move(surf))
-    {
-        MOZ_ASSERT(mFactory);
-        MOZ_ASSERT(mSurf);
-    }
-
-    ~ShSurfHandle() {
-        if (mFactory) {
-            mFactory->Recycle(Move(mSurf));
-        }
-    }
-
-    SharedSurface* Surf() const {
-        MOZ_ASSERT(mSurf.get());
-        return mSurf.get();
-    }
-};
-
-class ScopedReadbackFB
-{
-    GLContext* const mGL;
-    ScopedBindFramebuffer mAutoFB;
-    GLuint mTempFB;
-    GLuint mTempTex;
-    SharedSurface* mSurfToUnlock;
-    SharedSurface* mSurfToLock;
-
-public:
-    ScopedReadbackFB(SharedSurface* src);
-    ~ScopedReadbackFB();
-};
-
 } // namespace gl
 } // namespace mozilla
 
 #endif // SHARED_SURFACE_H_
--- a/gfx/gl/SharedSurfaceGralloc.cpp
+++ b/gfx/gl/SharedSurfaceGralloc.cpp
@@ -32,57 +32,60 @@
 namespace mozilla {
 namespace gl {
 
 using namespace mozilla::layers;
 using namespace android;
 
 SurfaceFactory_Gralloc::SurfaceFactory_Gralloc(GLContext* prodGL,
                                                const SurfaceCaps& caps,
-                                               layers::TextureFlags flags,
                                                layers::ISurfaceAllocator* allocator)
     : SurfaceFactory(prodGL, SharedSurfaceType::Gralloc, caps)
-    , mFlags(flags)
-    , mAllocator(allocator)
 {
-    MOZ_ASSERT(mAllocator);
+    if (caps.surfaceAllocator) {
+        allocator = caps.surfaceAllocator;
+    }
+
+    MOZ_ASSERT(allocator);
+
+    mAllocator = allocator;
 }
 
 /*static*/ UniquePtr<SharedSurface_Gralloc>
 SharedSurface_Gralloc::Create(GLContext* prodGL,
                               const GLFormats& formats,
                               const gfx::IntSize& size,
                               bool hasAlpha,
-                              layers::TextureFlags flags,
                               ISurfaceAllocator* allocator)
 {
     GLLibraryEGL* egl = &sEGLLibrary;
     MOZ_ASSERT(egl);
 
     UniquePtr<SharedSurface_Gralloc> ret;
 
     DEBUG_PRINT("SharedSurface_Gralloc::Create -------\n");
 
     if (!HasExtensions(egl, prodGL))
         return Move(ret);
 
     gfxContentType type = hasAlpha ? gfxContentType::COLOR_ALPHA
                                    : gfxContentType::COLOR;
 
-    auto platform = gfxPlatform::GetPlatform();
-    gfxImageFormat format = platform->OptimalFormatForContent(type);
+    gfxImageFormat format
+      = gfxPlatform::GetPlatform()->OptimalFormatForContent(type);
 
-    typedef GrallocTextureClientOGL ptrT;
-    RefPtr<ptrT> grallocTC = new ptrT(allocator,
-                                      gfx::ImageFormatToSurfaceFormat(format),
-                                      gfx::BackendType::NONE, // we don't need to use it with a DrawTarget
-                                      flags);
+    RefPtr<GrallocTextureClientOGL> grallocTC =
+      new GrallocTextureClientOGL(
+          allocator,
+          gfx::ImageFormatToSurfaceFormat(format),
+          gfx::BackendType::NONE, // we don't need to use it with a DrawTarget
+          layers::TextureFlags::DEFAULT);
 
     if (!grallocTC->AllocateForGLRendering(size)) {
-        return Move(ret);
+      return Move(ret);
     }
 
     sp<GraphicBuffer> buffer = grallocTC->GetGraphicBuffer();
 
     EGLDisplay display = egl->Display();
     EGLClientBuffer clientBuffer = buffer->getNativeBuffer();
     EGLint attrs[] = {
         LOCAL_EGL_NONE, LOCAL_EGL_NONE
--- a/gfx/gl/SharedSurfaceGralloc.h
+++ b/gfx/gl/SharedSurfaceGralloc.h
@@ -1,17 +1,16 @@
 /* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */
 /* 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 SHARED_SURFACE_GRALLOC_H_
 #define SHARED_SURFACE_GRALLOC_H_
 
-#include "mozilla/layers/CompositorTypes.h"
 #include "mozilla/layers/LayersSurfaces.h"
 #include "SharedSurface.h"
 
 namespace mozilla {
 namespace layers {
 class ISurfaceAllocator;
 class GrallocTextureClientOGL;
 }
@@ -23,17 +22,16 @@ class GLLibraryEGL;
 class SharedSurface_Gralloc
     : public SharedSurface
 {
 public:
     static UniquePtr<SharedSurface_Gralloc> Create(GLContext* prodGL,
                                                    const GLFormats& formats,
                                                    const gfx::IntSize& size,
                                                    bool hasAlpha,
-                                                   layers::TextureFlags flags,
                                                    layers::ISurfaceAllocator* allocator);
 
     static SharedSurface_Gralloc* Cast(SharedSurface* surf) {
         MOZ_ASSERT(surf->mType == SharedSurfaceType::Gralloc);
 
         return (SharedSurface_Gralloc*)surf;
     }
 
@@ -74,32 +72,30 @@ public:
         return mTextureClient;
     }
 };
 
 class SurfaceFactory_Gralloc
     : public SurfaceFactory
 {
 protected:
-    const layers::TextureFlags mFlags;
     RefPtr<layers::ISurfaceAllocator> mAllocator;
 
 public:
     SurfaceFactory_Gralloc(GLContext* prodGL,
                            const SurfaceCaps& caps,
-                           layers::TextureFlags flags,
-                           layers::ISurfaceAllocator* allocator);
+                           layers::ISurfaceAllocator* allocator = nullptr);
 
     virtual UniquePtr<SharedSurface> CreateShared(const gfx::IntSize& size) MOZ_OVERRIDE {
         bool hasAlpha = mReadCaps.alpha;
 
         UniquePtr<SharedSurface> ret;
         if (mAllocator) {
-            ret = SharedSurface_Gralloc::Create(mGL, mFormats, size, hasAlpha,
-                                                mFlags, mAllocator);
+            ret = SharedSurface_Gralloc::Create(mGL, mFormats, size,
+                                                hasAlpha, mAllocator);
         }
         return Move(ret);
     }
 };
 
 } /* namespace gl */
 } /* namespace mozilla */
 
--- a/gfx/gl/SharedSurfaceIO.h
+++ b/gfx/gl/SharedSurfaceIO.h
@@ -51,20 +51,16 @@ public:
     GLenum ConsTextureTarget() const {
         return LOCAL_GL_TEXTURE_RECTANGLE_ARB;
     }
 
     MacIOSurface* GetIOSurface() const {
         return mIOSurf;
     }
 
-    virtual bool NeedsIndirectReads() const MOZ_OVERRIDE {
-        return true;
-    }
-
 private:
     SharedSurface_IOSurface(const RefPtr<MacIOSurface>& ioSurf,
                             GLContext* gl, const gfx::IntSize& size,
                             bool hasAlpha);
 
     RefPtr<MacIOSurface> mIOSurf;
     GLuint mProdTex;
     const GLContext* mCurConsGL;
new file mode 100644
--- /dev/null
+++ b/gfx/gl/SurfaceStream.cpp
@@ -0,0 +1,559 @@
+/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */
+/* 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 "SurfaceStream.h"
+
+#include "gfxPoint.h"
+#include "SharedSurface.h"
+#include "SharedSurfaceGL.h"
+#include "GeckoProfiler.h"
+#include "mozilla/Move.h"
+
+namespace mozilla {
+namespace gl {
+
+SurfaceStreamType
+SurfaceStream::ChooseGLStreamType(SurfaceStream::OMTC omtc,
+                                  bool preserveBuffer)
+{
+    if (omtc == SurfaceStream::OffMainThread) {
+        if (preserveBuffer)
+            return SurfaceStreamType::TripleBuffer_Copy;
+        else
+            return SurfaceStreamType::TripleBuffer_Async;
+    } else {
+        if (preserveBuffer)
+            return SurfaceStreamType::SingleBuffer;
+        else
+            return SurfaceStreamType::TripleBuffer;
+    }
+}
+
+TemporaryRef<SurfaceStream>
+SurfaceStream::CreateForType(SurfaceStreamType type, mozilla::gl::GLContext* glContext, SurfaceStream* prevStream)
+{
+    RefPtr<SurfaceStream> result;
+
+    switch (type) {
+        case SurfaceStreamType::SingleBuffer:
+            result = new SurfaceStream_SingleBuffer(prevStream);
+            break;
+        case SurfaceStreamType::TripleBuffer_Copy:
+            result = new SurfaceStream_TripleBuffer_Copy(prevStream);
+            break;
+        case SurfaceStreamType::TripleBuffer_Async:
+            result = new SurfaceStream_TripleBuffer_Async(prevStream);
+            break;
+        case SurfaceStreamType::TripleBuffer:
+            result = new SurfaceStream_TripleBuffer(prevStream);
+            break;
+        default:
+            MOZ_CRASH("Invalid Type.");
+    }
+
+    result->mGLContext = glContext;
+
+    return result.forget();
+}
+
+bool
+SurfaceStream_TripleBuffer::CopySurfaceToProducer(SharedSurface* src, SurfaceFactory* factory)
+{
+    if (!mProducer) {
+        New(factory, src->mSize, &mProducer);
+        if (!mProducer) {
+            return false;
+        }
+    }
+
+    MOZ_ASSERT(src->mSize == mProducer->mSize, "Size mismatch");
+
+    SharedSurface::ProdCopy(src, mProducer.get(), factory);
+    return true;
+}
+
+void
+SurfaceStream::New(SurfaceFactory* factory, const gfx::IntSize& size,
+                   UniquePtr<SharedSurface>* surfSlot)
+{
+    MOZ_ASSERT(surfSlot);
+    UniquePtr<SharedSurface>& surf = *surfSlot;
+
+    MOZ_ASSERT(!surf);
+    surf = factory->NewSharedSurface(size);
+
+    if (surf) {
+        // Before next use, wait until SharedSurface's buffer
+        // is no longer being used.
+        surf->WaitForBufferOwnership();
+#ifdef DEBUG
+        mSurfaces.insert(surf.get());
+#endif
+    }
+}
+
+void
+SurfaceStream::MoveTo(UniquePtr<SharedSurface>* slotFrom,
+                      UniquePtr<SharedSurface>* slotTo)
+{
+    MOZ_ASSERT(slotFrom);
+    UniquePtr<SharedSurface>& from = *slotFrom;
+
+    MOZ_ASSERT(slotTo);
+    UniquePtr<SharedSurface>& to = *slotTo;
+
+    MOZ_ASSERT(!to);
+    to = Move(from);
+    MOZ_ASSERT(!from);
+}
+
+void
+SurfaceStream::Recycle(SurfaceFactory* factory, UniquePtr<SharedSurface>* surfSlot)
+{
+    MOZ_ASSERT(surfSlot);
+    UniquePtr<SharedSurface>& surf = *surfSlot;
+
+    if (surf) {
+#ifdef DEBUG
+        mSurfaces.erase(surf.get());
+#endif
+        factory->Recycle(Move(surf));
+    }
+    MOZ_ASSERT(!surf);
+}
+
+void
+SurfaceStream::Delete(UniquePtr<SharedSurface>* surfSlot)
+{
+    MOZ_ASSERT(surfSlot);
+    UniquePtr<SharedSurface>& surf = *surfSlot;
+
+    if (surf) {
+#ifdef DEBUG
+        mSurfaces.erase(surf.get());
+#endif
+        surf = nullptr;
+    }
+    MOZ_ASSERT(!surf);
+}
+
+UniquePtr<SharedSurface>
+SurfaceStream::Surrender(UniquePtr<SharedSurface>* surfSlot)
+{
+    MOZ_ASSERT(surfSlot);
+    UniquePtr<SharedSurface>& surf = *surfSlot;
+
+#ifdef DEBUG
+    if (surf) {
+        mSurfaces.erase(surf.get());
+    }
+#endif
+
+    UniquePtr<SharedSurface> ret = Move(surf);
+    MOZ_ASSERT(!surf);
+
+    return Move(ret);
+}
+
+// Move `surfSlot` to `return`, but record that the surf is now part of
+// this stream.
+UniquePtr<SharedSurface>
+SurfaceStream::Absorb(UniquePtr<SharedSurface>* surfSlot)
+{
+    MOZ_ASSERT(surfSlot);
+    UniquePtr<SharedSurface>& surf = *surfSlot;
+
+#ifdef DEBUG
+    if (surf) {
+        mSurfaces.insert(surf.get());
+    }
+#endif
+
+    UniquePtr<SharedSurface> ret = Move(surf);
+    MOZ_ASSERT(!surf);
+
+    return Move(ret);
+}
+
+void
+SurfaceStream::Scrap(UniquePtr<SharedSurface>* surfSlot)
+{
+    MOZ_ASSERT(surfSlot);
+    UniquePtr<SharedSurface>& surf = *surfSlot;
+
+    if (surf) {
+        mScraps.Push(Move(surf));
+    }
+    MOZ_ASSERT(!surf);
+
+}
+
+void
+SurfaceStream::RecycleScraps(SurfaceFactory* factory)
+{
+    while (!mScraps.Empty()) {
+        UniquePtr<SharedSurface> cur = mScraps.Pop();
+
+        Recycle(factory, &cur);
+    }
+}
+
+////////////////////////////////////////////////////////////////////////
+// SurfaceStream
+
+SurfaceStream::SurfaceStream(SurfaceStreamType type,
+                             SurfaceStream* prevStream)
+    : mType(type)
+    , mProducer(nullptr)
+    , mMonitor("SurfaceStream monitor")
+    , mIsAlive(true)
+{
+    MOZ_ASSERT(!prevStream || mType != prevStream->mType,
+               "We should not need to create a SurfaceStream from another "
+               "of the same type.");
+}
+
+SurfaceStream::~SurfaceStream()
+{
+    Delete(&mProducer);
+
+    while (!mScraps.Empty()) {
+        UniquePtr<SharedSurface> cur = mScraps.Pop();
+
+        Delete(&cur);
+    }
+
+    MOZ_ASSERT(mSurfaces.empty());
+}
+
+SharedSurface*
+SurfaceStream::SwapConsumer()
+{
+    MOZ_ASSERT(mIsAlive);
+
+    SharedSurface* ret = SwapConsumer_NoWait();
+    if (!ret)
+        return nullptr;
+
+    if (!ret->WaitSync()) {
+        return nullptr;
+    }
+
+    return ret;
+}
+
+SharedSurface*
+SurfaceStream::Resize(SurfaceFactory* factory, const gfx::IntSize& size)
+{
+    MonitorAutoLock lock(mMonitor);
+
+    if (mProducer) {
+        Scrap(&mProducer);
+    }
+
+    New(factory, size, &mProducer);
+    return mProducer.get();
+}
+
+////////////////////////////////////////////////////////////////////////
+// SurfaceStream_SingleBuffer
+
+SurfaceStream_SingleBuffer::SurfaceStream_SingleBuffer(SurfaceStream* prevStream)
+    : SurfaceStream(SurfaceStreamType::SingleBuffer, prevStream)
+    , mConsumer(nullptr)
+{
+    if (!prevStream)
+        return;
+
+    UniquePtr<SharedSurface> prevProducer;
+    UniquePtr<SharedSurface> prevConsumer;
+    prevStream->SurrenderSurfaces(&prevProducer, &prevConsumer);
+
+    mProducer = Absorb(&prevProducer);
+    mConsumer = Absorb(&prevConsumer);
+}
+
+SurfaceStream_SingleBuffer::~SurfaceStream_SingleBuffer()
+{
+    Delete(&mConsumer);
+}
+
+void
+SurfaceStream_SingleBuffer::SurrenderSurfaces(UniquePtr<SharedSurface>* out_producer,
+                                              UniquePtr<SharedSurface>* out_consumer)
+{
+    MOZ_ASSERT(out_producer);
+    MOZ_ASSERT(out_consumer);
+
+    mIsAlive = false;
+
+    *out_producer = Surrender(&mProducer);
+    *out_consumer = Surrender(&mConsumer);
+}
+
+SharedSurface*
+SurfaceStream_SingleBuffer::SwapProducer(SurfaceFactory* factory,
+                                         const gfx::IntSize& size)
+{
+    MonitorAutoLock lock(mMonitor);
+    if (mConsumer) {
+        Recycle(factory, &mConsumer);
+    }
+
+    if (mProducer) {
+        // Fence now, before we start (maybe) juggling Prod around.
+        mProducer->Fence();
+
+        // Size mismatch means we need to squirrel the current Prod
+        // into Cons, and leave Prod empty, so it gets a new surface below.
+        bool needsNewBuffer = mProducer->mSize != size;
+
+        // Even if we're the right size, if the type has changed, and we don't
+        // need to preserve, we should switch out for (presumedly) better perf.
+        if (mProducer->mType != factory->mType &&
+            !factory->mCaps.preserve)
+        {
+            needsNewBuffer = true;
+        }
+
+        if (needsNewBuffer) {
+            MoveTo(&mProducer, &mConsumer);
+        }
+    }
+
+    // The old Prod (if there every was one) was invalid,
+    // so we need a new one.
+    if (!mProducer) {
+        New(factory, size, &mProducer);
+    }
+
+    return mProducer.get();
+}
+
+SharedSurface*
+SurfaceStream_SingleBuffer::SwapConsumer_NoWait()
+{
+    MonitorAutoLock lock(mMonitor);
+
+    // Use Cons, if present.
+    // Otherwise, just use Prod directly.
+    SharedSurface* toConsume = mConsumer.get();
+    if (!toConsume)
+        toConsume = mProducer.get();
+
+    return toConsume;
+}
+
+////////////////////////////////////////////////////////////////////////
+// SurfaceStream_TripleBuffer_Copy
+
+SurfaceStream_TripleBuffer_Copy::SurfaceStream_TripleBuffer_Copy(SurfaceStream* prevStream)
+    : SurfaceStream(SurfaceStreamType::TripleBuffer_Copy, prevStream)
+    , mStaging(nullptr)
+    , mConsumer(nullptr)
+{
+    if (!prevStream)
+        return;
+
+    UniquePtr<SharedSurface> prevProducer;
+    UniquePtr<SharedSurface> prevConsumer;
+    prevStream->SurrenderSurfaces(&prevProducer, &prevConsumer);
+
+    mProducer = Absorb(&prevProducer);
+    mConsumer = Absorb(&prevConsumer);
+}
+
+SurfaceStream_TripleBuffer_Copy::~SurfaceStream_TripleBuffer_Copy()
+{
+    Delete(&mStaging);
+    Delete(&mConsumer);
+}
+
+void
+SurfaceStream_TripleBuffer_Copy::SurrenderSurfaces(UniquePtr<SharedSurface>* out_producer,
+                                                   UniquePtr<SharedSurface>* out_consumer)
+{
+    MOZ_ASSERT(out_producer);
+    MOZ_ASSERT(out_consumer);
+
+    mIsAlive = false;
+
+    *out_producer = Surrender(&mProducer);
+    *out_consumer = Surrender(&mConsumer);
+
+    if (!*out_consumer)
+        *out_consumer = Surrender(&mStaging);
+}
+
+SharedSurface*
+SurfaceStream_TripleBuffer_Copy::SwapProducer(SurfaceFactory* factory,
+                                              const gfx::IntSize& size)
+{
+    MonitorAutoLock lock(mMonitor);
+
+    RecycleScraps(factory);
+    if (mProducer) {
+        if (mStaging) {
+            // We'll re-use this for a new mProducer later on if
+            // the size remains the same
+            Recycle(factory, &mStaging);
+        }
+
+        MoveTo(&mProducer, &mStaging);
+        mStaging->Fence();
+
+        New(factory, size, &mProducer);
+
+        if (mProducer &&
+            mStaging->mSize == mProducer->mSize)
+        {
+            SharedSurface::ProdCopy(mStaging.get(), mProducer.get(), factory);
+        }
+    } else {
+        New(factory, size, &mProducer);
+    }
+
+    return mProducer.get();
+}
+
+SharedSurface*
+SurfaceStream_TripleBuffer_Copy::SwapConsumer_NoWait()
+{
+    MonitorAutoLock lock(mMonitor);
+
+    if (mStaging) {
+        Scrap(&mConsumer);
+        MoveTo(&mStaging, &mConsumer);
+    }
+
+    return mConsumer.get();
+}
+
+////////////////////////////////////////////////////////////////////////
+// SurfaceStream_TripleBuffer
+
+void SurfaceStream_TripleBuffer::Init(SurfaceStream* prevStream)
+{
+    if (!prevStream)
+        return;
+
+    UniquePtr<SharedSurface> prevProducer;
+    UniquePtr<SharedSurface> prevConsumer;
+    prevStream->SurrenderSurfaces(&prevProducer, &prevConsumer);
+
+    mProducer = Absorb(&prevProducer);
+    mConsumer = Absorb(&prevConsumer);
+}
+
+SurfaceStream_TripleBuffer::SurfaceStream_TripleBuffer(SurfaceStreamType type,
+                                                       SurfaceStream* prevStream)
+    : SurfaceStream(type, prevStream)
+    , mStaging(nullptr)
+    , mConsumer(nullptr)
+{
+    SurfaceStream_TripleBuffer::Init(prevStream);
+}
+
+SurfaceStream_TripleBuffer::SurfaceStream_TripleBuffer(SurfaceStream* prevStream)
+    : SurfaceStream(SurfaceStreamType::TripleBuffer, prevStream)
+    , mStaging(nullptr)
+    , mConsumer(nullptr)
+{
+    SurfaceStream_TripleBuffer::Init(prevStream);
+}
+
+SurfaceStream_TripleBuffer::~SurfaceStream_TripleBuffer()
+{
+    Delete(&mStaging);
+    Delete(&mConsumer);
+}
+
+void
+SurfaceStream_TripleBuffer::SurrenderSurfaces(UniquePtr<SharedSurface>* out_producer,
+                                              UniquePtr<SharedSurface>* out_consumer)
+{
+    MOZ_ASSERT(out_producer);
+    MOZ_ASSERT(out_consumer);
+
+    mIsAlive = false;
+
+    *out_producer = Surrender(&mProducer);
+    *out_consumer = Surrender(&mConsumer);
+
+    if (!*out_consumer)
+        *out_consumer = Surrender(&mStaging);
+}
+
+SharedSurface*
+SurfaceStream_TripleBuffer::SwapProducer(SurfaceFactory* factory,
+                                         const gfx::IntSize& size)
+{
+    PROFILER_LABEL("SurfaceStream_TripleBuffer", "SwapProducer",
+                   js::ProfileEntry::Category::GRAPHICS);
+
+    MonitorAutoLock lock(mMonitor);
+    if (mProducer) {
+        RecycleScraps(factory);
+
+        // If WaitForCompositor succeeds, mStaging has moved to mConsumer.
+        // If it failed, we might have to scrap it.
+        if (mStaging) {
+            WaitForCompositor();
+        }
+        if (mStaging) {
+            Scrap(&mStaging);
+        }
+
+        MoveTo(&mProducer, &mStaging);
+        mStaging->Fence();
+    }
+
+    MOZ_ASSERT(!mProducer);
+    New(factory, size, &mProducer);
+
+    return mProducer.get();
+}
+
+SharedSurface*
+SurfaceStream_TripleBuffer::SwapConsumer_NoWait()
+{
+    MonitorAutoLock lock(mMonitor);
+    if (mStaging) {
+        Scrap(&mConsumer);
+        MoveTo(&mStaging, &mConsumer);
+        mMonitor.NotifyAll();
+    }
+
+    return mConsumer.get();
+}
+
+////////////////////////////////////////////////////////////////////////
+// SurfaceStream_TripleBuffer_Async
+
+SurfaceStream_TripleBuffer_Async::SurfaceStream_TripleBuffer_Async(SurfaceStream* prevStream)
+    : SurfaceStream_TripleBuffer(SurfaceStreamType::TripleBuffer_Async,
+                                 prevStream)
+{
+}
+
+SurfaceStream_TripleBuffer_Async::~SurfaceStream_TripleBuffer_Async()
+{
+}
+
+void
+SurfaceStream_TripleBuffer_Async::WaitForCompositor()
+{
+    PROFILER_LABEL("SurfaceStream_TripleBuffer_Async",
+                   "WaitForCompositor",
+                   js::ProfileEntry::Category::GRAPHICS);
+
+    // If we haven't be notified within 100ms, then
+    // something must have happened and it will never arrive.
+    // Bail out to avoid deadlocking.
+    mMonitor.Wait(PR_MillisecondsToInterval(100));
+}
+
+} /* namespace gfx */
+} /* namespace mozilla */
new file mode 100644
--- /dev/null
+++ b/gfx/gl/SurfaceStream.h
@@ -0,0 +1,227 @@
+/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40; -*- */
+/* 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 SURFACESTREAM_H_
+#define SURFACESTREAM_H_
+
+#include <stack>
+#include <set>
+#include "mozilla/Monitor.h"
+#include "mozilla/Attributes.h"
+#include "mozilla/gfx/Point.h"
+#include "mozilla/GenericRefCounted.h"
+#include "mozilla/UniquePtr.h"
+#include "SurfaceTypes.h"
+#include "SharedSurface.h"
+
+namespace mozilla {
+
+namespace gl {
+class GLContext;
+class SharedSurface;
+class SurfaceFactory;
+
+// Owned by: ScreenBuffer
+class SurfaceStream : public GenericAtomicRefCounted
+{
+public:
+    MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SurfaceStream)
+    typedef enum {
+        MainThread,
+        OffMainThread
+    } OMTC;
+
+    static SurfaceStreamType ChooseGLStreamType(OMTC omtc,
+                                                bool preserveBuffer);
+
+    static TemporaryRef<SurfaceStream> CreateForType(SurfaceStreamType type,
+                                                     mozilla::gl::GLContext* glContext,
+                                                     SurfaceStream* prevStream = nullptr);
+
+    const SurfaceStreamType mType;
+
+    mozilla::gl::GLContext* GLContext() const { return mGLContext; }
+
+
+protected:
+    // |mProd| is owned by us, but can be ripped away when
+    // creating a new GLStream from this one.
+    UniquePtr<SharedSurface> mProducer;
+#ifdef DEBUG
+    std::set<SharedSurface*> mSurfaces;
+#endif
+    UniquePtrQueue<SharedSurface> mScraps;
+    mutable Monitor mMonitor;
+    bool mIsAlive;
+
+    // Do not use this. It exists solely so we can ref it in CanvasClientWebGL::Update()
+    // before sent up to the compositor. You have been warned (Bug 894405)
+    mozilla::gl::GLContext* mGLContext;
+
+    // |previous| can be null, indicating this is the first one.
+    // Otherwise, we pull in |mProd| from |previous| an our initial surface.
+    SurfaceStream(SurfaceStreamType type, SurfaceStream* prevStream);
+
+public:
+    virtual ~SurfaceStream();
+
+protected:
+    // These functions below are helpers to make trading buffers around easier.
+    // For instance, using Move(a,b) instead of normal assignment assures that
+    // we are never leaving anything hanging around, keeping things very safe.
+    void MoveTo(UniquePtr<SharedSurface>* slotFrom,
+                UniquePtr<SharedSurface>* slotTo);
+    void New(SurfaceFactory* factory, const gfx::IntSize& size,
+             UniquePtr<SharedSurface>* surfSlot);
+    void Delete(UniquePtr<SharedSurface>* surfSlot);
+    void Recycle(SurfaceFactory* factory,
+                 UniquePtr<SharedSurface>* surfSlot);
+
+    // Surrender control of a surface, and return it for use elsewhere.
+    UniquePtr<SharedSurface> Surrender(UniquePtr<SharedSurface>* surfSlot);
+    // Absorb control of a surface from elsewhere, clears its old location.
+    UniquePtr<SharedSurface> Absorb(UniquePtr<SharedSurface>* surfSlot);
+
+    // For holding on to surfaces we don't need until we can return them to the
+    // Producer's factory via SurfaceFactory::Recycle.
+    // Not thread-safe.
+    void Scrap(UniquePtr<SharedSurface>* surfSlot);
+
+    // Not thread-safe.
+    void RecycleScraps(SurfaceFactory* factory);
+
+public:
+    /* Note that ownership of the returned surfaces below
+     * transfers to the caller.
+     * SwapProd returns null on failure. Returning null doesn't mean nothing
+     * happened, but rather that a surface allocation failed. After returning
+     * null, we must be able to call SwapProducer again with better args
+     * and have everything work again.
+     * One common failure is asking for a too-large |size|.
+     */
+    virtual SharedSurface* SwapProducer(SurfaceFactory* factory,
+                                        const gfx::IntSize& size) = 0;
+
+    virtual SharedSurface* Resize(SurfaceFactory* factory, const gfx::IntSize& size);
+
+    virtual bool CopySurfaceToProducer(SharedSurface* src, SurfaceFactory* factory) { MOZ_ASSERT(0); return false; }
+
+protected:
+    // SwapCons will return the same surface more than once,
+    // if nothing new has been published.
+    virtual SharedSurface* SwapConsumer_NoWait() = 0;
+
+public:
+    virtual SharedSurface* SwapConsumer();
+
+    virtual void SurrenderSurfaces(UniquePtr<SharedSurface>* out_producer,
+                                   UniquePtr<SharedSurface>* out_consumer) = 0;
+};
+
+// Not thread-safe. Don't use cross-threads.
+class SurfaceStream_SingleBuffer
+    : public SurfaceStream
+{
+protected:
+    UniquePtr<SharedSurface> mConsumer; // Only present after resize-swap.
+
+public:
+    MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SurfaceStream_SingleBuffer)
+
+    explicit SurfaceStream_SingleBuffer(SurfaceStream* prevStream);
+    virtual ~SurfaceStream_SingleBuffer();
+
+    /* Since we're non-OMTC, we know the order of execution here:
+     * SwapProd gets called in UpdateSurface, followed by
+     * SwapCons being called in Render.
+     */
+    virtual SharedSurface* SwapProducer(SurfaceFactory* factory,
+                                        const gfx::IntSize& size) MOZ_OVERRIDE;
+
+    virtual SharedSurface* SwapConsumer_NoWait() MOZ_OVERRIDE;
+
+    virtual void SurrenderSurfaces(UniquePtr<SharedSurface>* out_producer,
+                                   UniquePtr<SharedSurface>* out_consumer) MOZ_OVERRIDE;
+};
+
+// Our hero for preserveDrawingBuffer=true.
+class SurfaceStream_TripleBuffer_Copy
+    : public SurfaceStream
+{
+protected:
+    UniquePtr<SharedSurface> mStaging;
+    UniquePtr<SharedSurface> mConsumer;
+
+public:
+    MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SurfaceStream_TripleBuffer_Copy)
+
+    explicit SurfaceStream_TripleBuffer_Copy(SurfaceStream* prevStream);
+    virtual ~SurfaceStream_TripleBuffer_Copy();
+
+    virtual SharedSurface* SwapProducer(SurfaceFactory* factory,
+                                        const gfx::IntSize& size) MOZ_OVERRIDE;
+
+    virtual SharedSurface* SwapConsumer_NoWait() MOZ_OVERRIDE;
+
+    virtual void SurrenderSurfaces(UniquePtr<SharedSurface>* out_producer,
+                                   UniquePtr<SharedSurface>* out_consumer) MOZ_OVERRIDE;
+};
+
+
+class SurfaceStream_TripleBuffer
+    : public SurfaceStream
+{
+protected:
+    UniquePtr<SharedSurface> mStaging;
+    UniquePtr<SharedSurface> mConsumer;
+
+    // Returns true if we were able to wait, false if not
+    virtual void WaitForCompositor() {}
+
+    // To support subclasses initializing the mType.
+    SurfaceStream_TripleBuffer(SurfaceStreamType type, SurfaceStream* prevStream);
+
+public:
+    MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SurfaceStream_TripleBuffer)
+
+    explicit SurfaceStream_TripleBuffer(SurfaceStream* prevStream);
+    virtual ~SurfaceStream_TripleBuffer();
+
+    virtual bool CopySurfaceToProducer(SharedSurface* src,
+                                       SurfaceFactory* factory) MOZ_OVERRIDE;
+
+private:
+    // Common constructor code.
+    void Init(SurfaceStream* prevStream);
+
+public:
+    // Done writing to prod, swap prod and staging
+    virtual SharedSurface* SwapProducer(SurfaceFactory* factory,
+                                        const gfx::IntSize& size) MOZ_OVERRIDE;
+
+    virtual SharedSurface* SwapConsumer_NoWait() MOZ_OVERRIDE;
+
+    virtual void SurrenderSurfaces(UniquePtr<SharedSurface>* out_producer,
+                                   UniquePtr<SharedSurface>* out_consumer) MOZ_OVERRIDE;
+};
+
+class SurfaceStream_TripleBuffer_Async
+    : public SurfaceStream_TripleBuffer
+{
+protected:
+    virtual void WaitForCompositor() MOZ_OVERRIDE;
+
+public:
+    MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SurfaceStream_TripleBuffer_Async)
+
+    explicit SurfaceStream_TripleBuffer_Async(SurfaceStream* prevStream);
+    virtual ~SurfaceStream_TripleBuffer_Async();
+};
+
+
+} // namespace gl
+} // namespace mozilla
+
+#endif // SURFACESTREAM_H_
--- a/gfx/gl/SurfaceTypes.cpp
+++ b/gfx/gl/SurfaceTypes.cpp
@@ -25,34 +25,32 @@ SurfaceCaps::operator=(const SurfaceCaps
 {
     any = other.any;
     color = other.color;
     alpha = other.alpha;
     bpp16 = other.bpp16;
     depth = other.depth;
     stencil = other.stencil;
     antialias = other.antialias;
-    premultAlpha = other.premultAlpha;
     preserve = other.preserve;
     surfaceAllocator = other.surfaceAllocator;
 
     return *this;
 }
 
 void
 SurfaceCaps::Clear()
 {
     any = false;
     color = false;
     alpha = false;
     bpp16 = false;
     depth = false;
     stencil = false;
     antialias = false;
-    premultAlpha = true;
     preserve = false;
     surfaceAllocator = nullptr;
 }
 
 SurfaceCaps::~SurfaceCaps()
 {
 }
 
--- a/gfx/gl/SurfaceTypes.h
+++ b/gfx/gl/SurfaceTypes.h
@@ -20,17 +20,16 @@ namespace gl {
 
 struct SurfaceCaps MOZ_FINAL
 {
     bool any;
     bool color, alpha;
     bool bpp16;
     bool depth, stencil;
     bool antialias;
-    bool premultAlpha;
     bool preserve;
 
     // The surface allocator that we want to create this
     // for.  May be null.
     RefPtr<layers::ISurfaceAllocator> surfaceAllocator;
 
     SurfaceCaps();
     SurfaceCaps(const SurfaceCaps& other);
@@ -77,16 +76,26 @@ MOZ_BEGIN_ENUM_CLASS(SharedSurfaceType, 
     DXGLInterop,
     DXGLInterop2,
     Gralloc,
     IOSurface,
 
     Max
 MOZ_END_ENUM_CLASS(SharedSurfaceType)
 
+
+MOZ_BEGIN_ENUM_CLASS(SurfaceStreamType, uint8_t)
+    SingleBuffer,
+    TripleBuffer_Copy,
+    TripleBuffer_Async,
+    TripleBuffer,
+    Max
+MOZ_END_ENUM_CLASS(SurfaceStreamType)
+
+
 MOZ_BEGIN_ENUM_CLASS(AttachmentType, uint8_t)
     Screen = 0,
 
     GLTexture,
     GLRenderbuffer,
 
     Max
 MOZ_END_ENUM_CLASS(AttachmentType)
--- a/gfx/gl/moz.build
+++ b/gfx/gl/moz.build
@@ -47,16 +47,17 @@ EXPORTS += [
     'GLTextureImage.h',
     'GLTypes.h',
     'GLUploadHelpers.h',
     'HeapCopyOfStackArray.h',
     'ScopedGLHelpers.h',
     'SharedSurface.h',
     'SharedSurfaceEGL.h',
     'SharedSurfaceGL.h',
+    'SurfaceStream.h',
     'SurfaceTypes.h',
     'TextureGarbageBin.h',
 ]
 
 if CONFIG['MOZ_X11']:
     EXPORTS += [
         'GLContextGLX.h',
         'GLXLibrary.h',
@@ -128,16 +129,17 @@ UNIFIED_SOURCES += [
     'GLReadTexImageHelper.cpp',
     'GLScreenBuffer.cpp',
     'GLTextureImage.cpp',
     'GLUploadHelpers.cpp',
     'ScopedGLHelpers.cpp',
     'SharedSurface.cpp',
     'SharedSurfaceEGL.cpp',
     'SharedSurfaceGL.cpp',
+    'SurfaceStream.cpp',
     'SurfaceTypes.cpp',
     'TextureGarbageBin.cpp',
     'TextureImageEGL.cpp',
 ]
 
 FAIL_ON_WARNINGS = True
 
 MSVC_ENABLE_PGO = True
--- a/gfx/layers/CopyableCanvasLayer.cpp
+++ b/gfx/layers/CopyableCanvasLayer.cpp
@@ -4,16 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "BasicLayersImpl.h"            // for FillWithMask, etc
 #include "CopyableCanvasLayer.h"
 #include "GLContext.h"                  // for GLContext
 #include "GLScreenBuffer.h"             // for GLScreenBuffer
 #include "SharedSurface.h"              // for SharedSurface
 #include "SharedSurfaceGL.h"              // for SharedSurface
+#include "SurfaceStream.h"              // for SurfaceStream
 #include "gfxPattern.h"                 // for gfxPattern, etc
 #include "gfxPlatform.h"                // for gfxPlatform, gfxImageFormat
 #include "gfxRect.h"                    // for gfxRect
 #include "gfxUtils.h"                   // for gfxUtils
 #include "gfx2DGlue.h"                  // for thebes --> moz2d transition
 #include "mozilla/gfx/BaseSize.h"       // for BaseSize
 #include "mozilla/gfx/Tools.h"
 #include "nsDebug.h"                    // for NS_ASSERTION, NS_WARNING, etc
@@ -25,17 +26,17 @@
 namespace mozilla {
 namespace layers {
 
 using namespace mozilla::gfx;
 using namespace mozilla::gl;
 
 CopyableCanvasLayer::CopyableCanvasLayer(LayerManager* aLayerManager, void *aImplData) :
   CanvasLayer(aLayerManager, aImplData)
-  , mGLFrontbuffer(nullptr)
+  , mStream(nullptr)
   , mIsAlphaPremultiplied(true)
 {
   MOZ_COUNT_CTOR(CopyableCanvasLayer);
 }
 
 CopyableCanvasLayer::~CopyableCanvasLayer()
 {
   MOZ_COUNT_DTOR(CopyableCanvasLayer);
@@ -43,135 +44,133 @@ CopyableCanvasLayer::~CopyableCanvasLaye
 
 void
 CopyableCanvasLayer::Initialize(const Data& aData)
 {
   NS_ASSERTION(mSurface == nullptr, "BasicCanvasLayer::Initialize called twice!");
 
   if (aData.mGLContext) {
     mGLContext = aData.mGLContext;
+    mStream = aData.mStream;
     mIsAlphaPremultiplied = aData.mIsGLAlphaPremult;
     mNeedsYFlip = true;
     MOZ_ASSERT(mGLContext->IsOffscreen(), "canvas gl context isn't offscreen");
 
-    if (aData.mFrontbufferGLTex) {
-      gfx::IntSize size(aData.mSize.width, aData.mSize.height);
-      mGLFrontbuffer = SharedSurface_GLTexture::Create(aData.mGLContext,
-                                                       nullptr,
-                                                       aData.mGLContext->GetGLFormats(),
-                                                       size, aData.mHasAlpha,
-                                                       aData.mFrontbufferGLTex);
-    }
+    // [Basic Layers, non-OMTC] WebGL layer init.
+    // `GLScreenBuffer::Morph`ing is only needed in BasicShadowableCanvasLayer.
   } else if (aData.mDrawTarget) {
     mDrawTarget = aData.mDrawTarget;
     mSurface = mDrawTarget->Snapshot();
     mNeedsYFlip = false;
   } else {
     NS_ERROR("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;
+  return mGLContext == aData.mGLContext && mStream == aData.mStream;
 }
 
 void
 CopyableCanvasLayer::UpdateTarget(DrawTarget* aDestTarget)
 {
+  if (!IsDirty())
+    return;
+  Painted();
+
   if (mDrawTarget) {
     mDrawTarget->Flush();
     mSurface = mDrawTarget->Snapshot();
   }
 
   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 (mDrawTarget) {
-    return;
-  }
-
-  MOZ_ASSERT(mGLContext);
+  if (mGLContext) {
+    SharedSurface* sharedSurf = nullptr;
+    if (mStream) {
+      sharedSurf = mStream->SwapConsumer();
+    } else {
+      sharedSurf = mGLContext->RequestFrame();
+    }
 
-  SharedSurface* frontbuffer = nullptr;
-  if (mGLFrontbuffer) {
-    frontbuffer = mGLFrontbuffer.get();
-  } else {
-    GLScreenBuffer* screen = mGLContext->Screen();
-    ShSurfHandle* front = screen->Front();
-    if (front) {
-      frontbuffer = front->Surf();
+    if (!sharedSurf) {
+      NS_WARNING("Null frame received.");
+      return;
     }
-  }
 
-  if (!frontbuffer) {
-    NS_WARNING("Null frame received.");
-    return;
-  }
-
-  IntSize readSize(frontbuffer->mSize);
-  SurfaceFormat format = (GetContentFlags() & CONTENT_OPAQUE)
-                          ? SurfaceFormat::B8G8R8X8
-                          : SurfaceFormat::B8G8R8A8;
-  bool needsPremult = frontbuffer->mHasAlpha && !mIsAlphaPremultiplied;
+    IntSize readSize(sharedSurf->mSize);
+    SurfaceFormat format = (GetContentFlags() & CONTENT_OPAQUE)
+                            ? SurfaceFormat::B8G8R8X8
+                            : SurfaceFormat::B8G8R8A8;
+    bool needsPremult = sharedSurf->mHasAlpha && !mIsAlphaPremultiplied;
 
-  // Try to read back directly into aDestTarget's output buffer
-  if (aDestTarget) {
-    uint8_t* destData;
-    IntSize destSize;
-    int32_t destStride;
-    SurfaceFormat destFormat;
-    if (aDestTarget->LockBits(&destData, &destSize, &destStride, &destFormat)) {
-      if (destSize == readSize && destFormat == format) {
-        RefPtr<DataSourceSurface> data =
-          Factory::CreateWrappingDataSourceSurface(destData, destStride, destSize, destFormat);
-        mGLContext->Screen()->Readback(frontbuffer, data);
-        if (needsPremult) {
-            gfxUtils::PremultiplyDataSurface(data, data);
+    // Try to read back directly into aDestTarget's output buffer
+    if (aDestTarget) {
+      uint8_t* destData;
+      IntSize destSize;
+      int32_t destStride;
+      SurfaceFormat destFormat;
+      if (aDestTarget->LockBits(&destData, &destSize, &destStride, &destFormat)) {
+        if (destSize == readSize && destFormat == format) {
+          RefPtr<DataSourceSurface> data =
+            Factory::CreateWrappingDataSourceSurface(destData, destStride, destSize, destFormat);
+          mGLContext->Screen()->Readback(sharedSurf, data);
+          if (needsPremult) {
+              gfxUtils::PremultiplyDataSurface(data, data);
+          }
+          aDestTarget->ReleaseBits(destData);
+          return;
         }
         aDestTarget->ReleaseBits(destData);
+      }
+    }
+
+    RefPtr<SourceSurface> resultSurf;
+    if (sharedSurf->mType == SharedSurfaceType::Basic && !needsPremult) {
+      SharedSurface_Basic* sharedSurf_Basic = SharedSurface_Basic::Cast(sharedSurf);
+      resultSurf = sharedSurf_Basic->GetData();
+    } else {
+      RefPtr<DataSourceSurface> data = GetTempSurface(readSize, format);
+      // There will already be a warning from inside of GetTempSurface, but
+      // it doesn't hurt to complain:
+      if (NS_WARN_IF(!data)) {
         return;
       }
-      aDestTarget->ReleaseBits(destData);
+
+      // Readback handles Flush/MarkDirty.
+      mGLContext->Screen()->Readback(sharedSurf, data);
+      if (needsPremult) {
+        gfxUtils::PremultiplyDataSurface(data, data);
+      }
+      resultSurf = data;
     }
-  }
-
-  RefPtr<DataSourceSurface> resultSurf = GetTempSurface(readSize, format);
-  // There will already be a warning from inside of GetTempSurface, but
-  // it doesn't hurt to complain:
-  if (NS_WARN_IF(!resultSurf)) {
-    return;
-  }
+    MOZ_ASSERT(resultSurf);
 
-  // Readback handles Flush/MarkDirty.
-  mGLContext->Screen()->Readback(frontbuffer, resultSurf);
-  if (needsPremult) {
-    gfxUtils::PremultiplyDataSurface(resultSurf, resultSurf);
-  }
-  MOZ_ASSERT(resultSurf);
-
-  if (aDestTarget) {
-    aDestTarget->CopySurface(resultSurf,
-                             IntRect(0, 0, readSize.width, readSize.height),
-                             IntPoint(0, 0));
-  } else {
-    // If !aDestSurface then we will end up painting using mSurface, so
-    // stick our surface into mSurface, so that the Paint() path is the same.
-    mSurface = resultSurf;
+    if (aDestTarget) {
+      aDestTarget->CopySurface(resultSurf,
+                               IntRect(0, 0, readSize.width, readSize.height),
+                               IntPoint(0, 0));
+    } else {
+      // If !aDestSurface then we will end up painting using mSurface, so
+      // stick our surface into mSurface, so that the Paint() path is the same.
+      mSurface = resultSurf;
+    }
   }
 }
 
 DataSourceSurface*
 CopyableCanvasLayer::GetTempSurface(const IntSize& aSize,
                                     const SurfaceFormat aFormat)
 {
   if (!mCachedTempSurface ||
--- a/gfx/layers/CopyableCanvasLayer.h
+++ b/gfx/layers/CopyableCanvasLayer.h
@@ -16,16 +16,20 @@
 #include "mozilla/Preferences.h"        // for Preferences
 #include "mozilla/RefPtr.h"             // for RefPtr
 #include "mozilla/gfx/2D.h"             // for DrawTarget
 #include "mozilla/mozalloc.h"           // for operator delete, etc
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 
 namespace mozilla {
+namespace gl{
+class SurfaceStream;
+}
+
 namespace layers {
 
 class CanvasClientWebGL;
 
 /**
  * A shared CanvasLayer implementation that supports copying
  * its contents into a gfxASurface using UpdateSurface.
  */
@@ -33,31 +37,32 @@ class CopyableCanvasLayer : public Canva
 {
 public:
   CopyableCanvasLayer(LayerManager* aLayerManager, void *aImplData);
 
 protected:
   virtual ~CopyableCanvasLayer();
 
 public:
-  virtual void Initialize(const Data& aData) MOZ_OVERRIDE;
+  virtual void Initialize(const Data& aData);
 
-  virtual bool IsDataValid(const Data& aData) MOZ_OVERRIDE;
+  virtual bool IsDataValid(const Data& aData);
 
   bool IsGLLayer() { return !!mGLContext; }
 
 protected:
   void UpdateTarget(gfx::DrawTarget* aDestTarget = nullptr);
 
   RefPtr<gfx::SourceSurface> mSurface;
   nsRefPtr<gl::GLContext> mGLContext;
-  GLuint mCanvasFrontbufferTexID;
   mozilla::RefPtr<mozilla::gfx::DrawTarget> mDrawTarget;
 
-  UniquePtr<gl::SharedSurface> mGLFrontbuffer;
+  RefPtr<gl::SurfaceStream> mStream;
+
+  uint32_t mCanvasFramebuffer;
 
   bool mIsAlphaPremultiplied;
   bool mNeedsYFlip;
 
   RefPtr<gfx::DataSourceSurface> mCachedTempSurface;
 
   gfx::DataSourceSurface* GetTempSurface(const gfx::IntSize& aSize,
                                          const gfx::SurfaceFormat aFormat);
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -54,17 +54,17 @@ namespace mozilla {
 
 class ComputedTimingFunction;
 class FrameLayerBuilder;
 class StyleAnimationValue;
 class WebGLContext;
 
 namespace gl {
 class GLContext;
-class SharedSurface;
+class SurfaceStream;
 }
 
 namespace gfx {
 class DrawTarget;
 }
 
 namespace dom {
 class OverfillCallback;
@@ -2005,28 +2005,32 @@ protected:
  * must not be modified during a layer transaction.
  */
 class CanvasLayer : public Layer {
 public:
   struct Data {
     Data()
       : mDrawTarget(nullptr)
       , mGLContext(nullptr)
-      , mFrontbufferGLTex(0)
+      , mStream(nullptr)
+      , mTexID(0)
       , mSize(0,0)
       , mHasAlpha(false)
       , mIsGLAlphaPremult(true)
     { }
 
     // One of these two must be specified for Canvas2D, but never both
     mozilla::gfx::DrawTarget* mDrawTarget; // a DrawTarget for the canvas contents
     mozilla::gl::GLContext* mGLContext; // or this, for GL.
 
-    // Frontbuffer override
-    uint32_t mFrontbufferGLTex;
+    // Canvas/SkiaGL uses this
+    mozilla::gl::SurfaceStream* mStream;
+
+    // ID of the texture backing the canvas layer (defaults to 0)
+    uint32_t mTexID;
 
     // The size of the canvas content
     nsIntSize mSize;
 
     // Whether the canvas drawingbuffer has an alpha channel.
     bool mHasAlpha;
 
     // Whether mGLContext contains data that is alpha-premultiplied.
--- a/gfx/layers/basic/BasicCanvasLayer.cpp
+++ b/gfx/layers/basic/BasicCanvasLayer.cpp
@@ -23,23 +23,19 @@ namespace layers {
 void
 BasicCanvasLayer::Paint(DrawTarget* aDT,
                         const Point& aDeviceOffset,
                         Layer* aMaskLayer)
 {
   if (IsHidden())
     return;
 
-  if (IsDirty()) {
-    Painted();
-
-    FirePreTransactionCallback();
-    UpdateTarget();
-    FireDidTransactionCallback();
-  }
+  FirePreTransactionCallback();
+  UpdateTarget();
+  FireDidTransactionCallback();
 
   if (!mSurface) {
     return;
   }
 
   Matrix oldTM;
   if (mNeedsYFlip) {
     oldTM = aDT->GetTransform();
--- a/gfx/layers/client/CanvasClient.cpp
+++ b/gfx/layers/client/CanvasClient.cpp
@@ -4,20 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "CanvasClient.h"
 
 #include "ClientCanvasLayer.h"          // for ClientCanvasLayer
 #include "CompositorChild.h"            // for CompositorChild
 #include "GLContext.h"                  // for GLContext
 #include "GLScreenBuffer.h"             // for GLScreenBuffer
-#include "ScopedGLHelpers.h"
+#include "SurfaceStream.h"              // for SurfaceStream
+#include "SurfaceTypes.h"               // for SurfaceStreamHandle
 #include "gfx2DGlue.h"                  // for ImageFormatToSurfaceFormat
 #include "gfxPlatform.h"                // for gfxPlatform
-#include "GLReadTexImageHelper.h"
 #include "mozilla/gfx/BaseSize.h"       // for BaseSize
 #include "mozilla/layers/CompositableForwarder.h"
 #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
@@ -38,24 +38,21 @@ CanvasClient::CreateCanvasClient(CanvasC
                                  TextureFlags aFlags)
 {
 #ifndef MOZ_WIDGET_GONK
   if (XRE_GetProcessType() != GeckoProcessType_Default) {
     NS_WARNING("Most platforms still need an optimized way to share GL cross process.");
     return new CanvasClient2D(aForwarder, aFlags);
   }
 #endif
-
-  switch (aType) {
-  case CanvasClientTypeShSurf:
-    return new CanvasClientSharedSurface(aForwarder, aFlags);
-
-  default:
-    return new CanvasClient2D(aForwarder, aFlags);
+  if (aType == CanvasClientGLContext) {
+    aFlags |= TextureFlags::DEALLOCATE_CLIENT;
+    return new CanvasClientSurfaceStream(aForwarder, aFlags);
   }
+  return new CanvasClient2D(aForwarder, aFlags);
 }
 
 void
 CanvasClient2D::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
 {
   AutoRemoveTexture autoRemove(this);
   if (mBuffer &&
       (mBuffer->IsImmutable() || mBuffer->GetSize() != aSize)) {
@@ -137,265 +134,103 @@ CanvasClient2D::CreateTextureClientForCa
   // XXX - We should use CreateTextureClientForDrawing, but we first need
   // to use double buffering.
   return TextureClient::CreateForRawBufferAccess(GetForwarder(),
                                                  aFormat, aSize, backend,
                                                  mTextureInfo.mTextureFlags | aFlags);
 #endif
 }
 
-////////////////////////////////////////////////////////////////////////
-
-CanvasClientSharedSurface::CanvasClientSharedSurface(CompositableForwarder* aLayerForwarder,
+CanvasClientSurfaceStream::CanvasClientSurfaceStream(CompositableForwarder* aLayerForwarder,
                                                      TextureFlags aFlags)
   : CanvasClient(aLayerForwarder, aFlags)
 {
 }
 
-////////////////////////////////////////
-// Accelerated backends
-
-static TemporaryRef<TextureClient>
-TexClientFromShSurf(SharedSurface* surf, TextureFlags flags)
-{
-  switch (surf->mType) {
-    case SharedSurfaceType::Basic:
-      return nullptr;
-
-#ifdef MOZ_WIDGET_GONK
-    case SharedSurfaceType::Gralloc:
-      return GrallocTextureClientOGL::FromSharedSurface(surf, flags);
-#endif
-
-    default:
-      return new SharedSurfaceTextureClient(flags, surf);
-  }
-}
-
-////////////////////////////////////////
-// Readback
-
-// For formats compatible with R8G8B8A8.
-static inline void SwapRB_R8G8B8A8(uint8_t* pixel) {
-  // [RR, GG, BB, AA]
-  Swap(pixel[0], pixel[2]);
-}
-
-class TexClientFactory
+void
+CanvasClientSurfaceStream::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
 {
-  ISurfaceAllocator* const mAllocator;
-  const bool mHasAlpha;
-  const gfx::IntSize mSize;
-  const gfx::BackendType mBackendType;
-  const TextureFlags mBaseTexFlags;
-  const LayersBackend mLayersBackend;
+  aLayer->mGLContext->MakeCurrent();
+  GLScreenBuffer* screen = aLayer->mGLContext->Screen();
+  SurfaceStream* stream = nullptr;
+
+  if (aLayer->mStream) {
+    stream = aLayer->mStream;
 
-public:
-  TexClientFactory(ISurfaceAllocator* allocator, bool hasAlpha,
-                   const gfx::IntSize& size, gfx::BackendType backendType,
-                   TextureFlags baseTexFlags, LayersBackend layersBackend)
-    : mAllocator(allocator)
-    , mHasAlpha(hasAlpha)
-    , mSize(size)
-    , mBackendType(backendType)
-    , mBaseTexFlags(baseTexFlags)
-    , mLayersBackend(layersBackend)
-  {
-  }
-
-protected:
-  TemporaryRef<BufferTextureClient> Create(gfx::SurfaceFormat format) {
-    return TextureClient::CreateForRawBufferAccess(mAllocator, format,
-                                                   mSize, mBackendType,
-                                                   mBaseTexFlags);
-  }
-
-public:
-  TemporaryRef<BufferTextureClient> CreateB8G8R8AX8() {
-    gfx::SurfaceFormat format = mHasAlpha ? gfx::SurfaceFormat::B8G8R8A8
-                                          : gfx::SurfaceFormat::B8G8R8X8;
-    return Create(format);
+    // Copy our current surface to the current producer surface in our stream, then
+    // call SwapProducer to make a new buffer ready.
+    stream->CopySurfaceToProducer(aLayer->mTextureSurface.get(),
+                                  aLayer->mFactory.get());
+    stream->SwapProducer(aLayer->mFactory.get(),
+                         gfx::IntSize(aSize.width, aSize.height));
+  } else {
+    stream = screen->Stream();
   }
 
-  TemporaryRef<BufferTextureClient> CreateR8G8B8AX8() {
-    RefPtr<BufferTextureClient> ret;
-
-    bool areRGBAFormatsBroken = mLayersBackend == LayersBackend::LAYERS_BASIC;
-    if (!areRGBAFormatsBroken) {
-      gfx::SurfaceFormat format = mHasAlpha ? gfx::SurfaceFormat::R8G8B8A8
-                                            : gfx::SurfaceFormat::R8G8B8X8;
-      ret = Create(format);
-    }
-
-    if (!ret) {
-      ret = CreateB8G8R8AX8();
-      if (ret) {
-        ret->AddFlags(TextureFlags::RB_SWAPPED);
-      }
-    }
-
-    return ret.forget();
+#ifdef MOZ_WIDGET_GONK
+  SharedSurface* surf = stream->SwapConsumer();
+  if (!surf) {
+    printf_stderr("surf is null post-SwapConsumer!\n");
+    return;
   }
-};
-
-static TemporaryRef<TextureClient>
-TexClientFromReadback(SharedSurface* src, ISurfaceAllocator* allocator,
-                      TextureFlags baseFlags, LayersBackend layersBackend)
-{
-  auto backendType = gfx::BackendType::CAIRO;
-  TexClientFactory factory(allocator, src->mHasAlpha, src->mSize, backendType,
-                           baseFlags, layersBackend);
-
-  RefPtr<BufferTextureClient> texClient;
-
-  {
-    gl::ScopedReadbackFB autoReadback(src);
-
-    // We have a source FB, now we need a format.
-    GLenum destFormat = LOCAL_GL_BGRA;
-    GLenum destType = LOCAL_GL_UNSIGNED_BYTE;
-    GLenum readFormat;
-    GLenum readType;
-
-    // We actually don't care if they match, since we can handle
-    // any read{Format,Type} we get.
-    auto gl = src->mGL;
-    GetActualReadFormats(gl, destFormat, destType, &readFormat, &readType);
-
-    MOZ_ASSERT(readFormat == LOCAL_GL_RGBA ||
-               readFormat == LOCAL_GL_BGRA);
-    MOZ_ASSERT(readType == LOCAL_GL_UNSIGNED_BYTE);
 
-    // With a format and type, we can create texClient.
-    if (readFormat == LOCAL_GL_BGRA &&
-        readType == LOCAL_GL_UNSIGNED_BYTE)
-    {
-      // 0xAARRGGBB
-      // In Lendian: [BB, GG, RR, AA]
-      texClient = factory.CreateB8G8R8AX8();
-
-    } else if (readFormat == LOCAL_GL_RGBA &&
-               readType == LOCAL_GL_UNSIGNED_BYTE)
-    {
-      // [RR, GG, BB, AA]
-      texClient = factory.CreateR8G8B8AX8();
-    } else {
-      MOZ_CRASH("Bad `read{Format,Type}`.");
-    }
-
-    MOZ_ASSERT(texClient);
-    if (!texClient)
-        return nullptr;
-
-    // With a texClient, we can lock for writing.
-    MOZ_ALWAYS_TRUE( texClient->Lock(OpenMode::OPEN_WRITE) );
-
-    uint8_t* lockedBytes = texClient->GetLockedData();
-
-    // ReadPixels from the current FB into lockedBits.
-    auto width = src->mSize.width;
-    auto height = src->mSize.height;
-
-    {
-      ScopedPackAlignment autoAlign(gl, 4);
-
-      gl->raw_fReadPixels(0, 0, width, height, readFormat, readType, lockedBytes);
-    }
-
-    // RB_SWAPPED doesn't work with D3D11. (bug 1051010)
-    // RB_SWAPPED doesn't work with Basic. (bug ???????)
-    // RB_SWAPPED doesn't work with D3D9. (bug ???????)
-    bool layersNeedsManualSwap = layersBackend == LayersBackend::LAYERS_BASIC ||
-                                 layersBackend == LayersBackend::LAYERS_D3D9 ||
-                                 layersBackend == LayersBackend::LAYERS_D3D11;
-    if (texClient->HasFlags(TextureFlags::RB_SWAPPED) &&
-        layersNeedsManualSwap)
-    {
-      size_t pixels = width * height;
-      uint8_t* itr = lockedBytes;
-      for (size_t i = 0; i < pixels; i++) {
-        SwapRB_R8G8B8A8(itr);
-        itr += 4;
-      }
-
-      texClient->RemoveFlags(TextureFlags::RB_SWAPPED);
-    }
-
-    texClient->Unlock();
+  if (surf->mType != SharedSurfaceType::Gralloc) {
+    printf_stderr("Unexpected non-Gralloc SharedSurface in IPC path!");
+    MOZ_ASSERT(false);
+    return;
   }
 
-  return texClient.forget();
-}
+  SharedSurface_Gralloc* grallocSurf = SharedSurface_Gralloc::Cast(surf);
 
-////////////////////////////////////////
+  RefPtr<GrallocTextureClientOGL> grallocTextureClient =
+    static_cast<GrallocTextureClientOGL*>(grallocSurf->GetTextureClient());
 
-static TemporaryRef<gl::ShSurfHandle>
-CloneSurface(gl::SharedSurface* src, gl::SurfaceFactory* factory)
-{
-    RefPtr<gl::ShSurfHandle> dest = factory->NewShSurfHandle(src->mSize);
-    SharedSurface::ProdCopy(src, dest->Surf(), factory);
-    return dest.forget();
-}
-
-void
-CanvasClientSharedSurface::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
-{
-  if (mFront) {
-    mPrevFront = mFront;
-    mFront = nullptr;
+  // If IPDLActor is null means this TextureClient didn't AddTextureClient yet
+  if (!grallocTextureClient->GetIPDLActor()) {
+    grallocTextureClient->SetTextureFlags(mTextureInfo.mTextureFlags);
+    AddTextureClient(grallocTextureClient);
   }
 
-  auto gl = aLayer->mGLContext;
-  gl->MakeCurrent();
-
-  if (aLayer->mGLFrontbuffer) {
-    mFront = CloneSurface(aLayer->mGLFrontbuffer.get(), aLayer->mFactory.get());
-    if (mFront)
-      mFront->Surf()->Fence();
-  } else {
-    mFront = gl->Screen()->Front();
-    if (!mFront)
-      return;
+  if (grallocTextureClient->GetIPDLActor()) {
+    UseTexture(grallocTextureClient);
   }
-  MOZ_ASSERT(mFront);
 
-  // Alright, now sort out the IPC goop.
-  SharedSurface* surf = mFront->Surf();
-  auto forwarder = GetForwarder();
-  auto flags = GetTextureFlags() | TextureFlags::IMMUTABLE;
-
-  // Get a TexClient from our surf.
-  RefPtr<TextureClient> newTex = TexClientFromShSurf(surf, flags);
-  if (!newTex) {
-    auto manager = aLayer->ClientManager();
-    auto shadowForwarder = manager->AsShadowForwarder();
-    auto layersBackend = shadowForwarder->GetCompositorBackendType();
-
-    newTex = TexClientFromReadback(surf, forwarder, flags, layersBackend);
-  }
-  MOZ_ASSERT(newTex);
-
-  // Add the new TexClient.
-  MOZ_ALWAYS_TRUE( newTex->InitIPDLActor(forwarder) );
-  MOZ_ASSERT(newTex->GetIPDLActor());
-
-  // Remove the old TexClient.
-  if (mFrontTex) {
+  if (mBuffer) {
     // remove old buffer from CompositableHost
     RefPtr<AsyncTransactionTracker> tracker = new RemoveTextureFromCompositableTracker();
     // Hold TextureClient until transaction complete.
-    tracker->SetTextureClient(mFrontTex);
-    mFrontTex->SetRemoveFromCompositableTracker(tracker);
+    tracker->SetTextureClient(mBuffer);
+    mBuffer->SetRemoveFromCompositableTracker(tracker);
     // RemoveTextureFromCompositableAsync() expects CompositorChild's presence.
-    GetForwarder()->RemoveTextureFromCompositableAsync(tracker, this, mFrontTex);
-
-    mFrontTex = nullptr;
+    GetForwarder()->RemoveTextureFromCompositableAsync(tracker, this, mBuffer);
   }
+  mBuffer = grallocTextureClient;
+#else
+  bool isCrossProcess = !(XRE_GetProcessType() == GeckoProcessType_Default);
+  if (isCrossProcess) {
+    printf_stderr("isCrossProcess, but not MOZ_WIDGET_GONK! Someone needs to write some code!");
+    MOZ_ASSERT(false);
+  } else {
+    bool bufferCreated = false;
+    if (!mBuffer) {
+      StreamTextureClient* textureClient =
+        new StreamTextureClient(mTextureInfo.mTextureFlags);
+      textureClient->InitWith(stream);
+      mBuffer = textureClient;
+      bufferCreated = true;
+    }
 
-  // Use the new TexClient.
-  mFrontTex = newTex;
+    if (bufferCreated && !AddTextureClient(mBuffer)) {
+      mBuffer = nullptr;
+    }
 
-  forwarder->UpdatedTexture(this, mFrontTex, nullptr);
-  forwarder->UseTexture(this, mFrontTex);
+    if (mBuffer) {
+      GetForwarder()->UpdatedTexture(this, mBuffer, nullptr);
+      GetForwarder()->UseTexture(this, mBuffer);
+    }
+  }
+#endif
+
+  aLayer->Painted();
 }
 
 }
 }
--- a/gfx/layers/client/CanvasClient.h
+++ b/gfx/layers/client/CanvasClient.h
@@ -16,17 +16,16 @@
 #include "mozilla/mozalloc.h"           // for operator delete
 
 #include "mozilla/gfx/Point.h"          // for IntSize
 #include "mozilla/gfx/Types.h"          // for SurfaceFormat
 
 namespace mozilla {
 namespace gl {
 class SharedSurface;
-class ShSurfHandle;
 }
 }
 
 namespace mozilla {
 namespace layers {
 
 class ClientCanvasLayer;
 class CompositableForwarder;
@@ -40,17 +39,16 @@ public:
   /**
    * 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,
   };
   static TemporaryRef<CanvasClient> CreateCanvasClient(CanvasClientType aType,
                                                        CompositableForwarder* aFwd,
                                                        TextureFlags aFlags);
 
   CanvasClient(CompositableForwarder* aFwd, TextureFlags aFlags)
     : CompositableClient(aFwd, aFlags)
   {
@@ -109,42 +107,38 @@ private:
                                  TextureFlags aFlags,
                                  ClientCanvasLayer* aLayer);
 
   RefPtr<TextureClient> mBuffer;
 };
 
 // Used for GL canvases where we don't need to do any readback, i.e., with a
 // GL backend.
-class CanvasClientSharedSurface : public CanvasClient
+class CanvasClientSurfaceStream : public CanvasClient
 {
-private:
-  RefPtr<gl::ShSurfHandle> mFront;
-  RefPtr<gl::ShSurfHandle> mPrevFront;
+public:
+  CanvasClientSurfaceStream(CompositableForwarder* aLayerForwarder, TextureFlags aFlags);
 
-  RefPtr<TextureClient> mFrontTex;
-
-public:
-  CanvasClientSharedSurface(CompositableForwarder* aLayerForwarder,
-                            TextureFlags aFlags);
-
-  virtual TextureInfo GetTextureInfo() const MOZ_OVERRIDE {
+  TextureInfo GetTextureInfo() const
+  {
     return TextureInfo(CompositableType::IMAGE);
   }
 
-  virtual void Clear() MOZ_OVERRIDE {
-    mFront = nullptr;
-    mPrevFront = nullptr;
-    mFrontTex = nullptr;
+  virtual void Clear() MOZ_OVERRIDE
+  {
+    mBuffer = nullptr;
   }
 
-  virtual void Update(gfx::IntSize aSize,
-                      ClientCanvasLayer* aLayer) MOZ_OVERRIDE;
+  virtual void Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer) MOZ_OVERRIDE;
 
-  virtual void OnDetach() MOZ_OVERRIDE {
-    CanvasClientSharedSurface::Clear();
+  virtual void OnDetach() MOZ_OVERRIDE
+  {
+    mBuffer = nullptr;
   }
+
+private:
+  RefPtr<TextureClient> mBuffer;
 };
 
 }
 }
 
 #endif
--- a/gfx/layers/client/ClientCanvasLayer.cpp
+++ b/gfx/layers/client/ClientCanvasLayer.cpp
@@ -4,16 +4,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #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 "SurfaceStream.h"              // for SurfaceStream, etc
+#include "SurfaceTypes.h"               // for SurfaceStreamType
 #include "ClientLayerManager.h"         // for ClientLayerManager, etc
 #include "mozilla/gfx/Point.h"          // for IntSize
 #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 nsIntRect
 #include "nsXULAppAPI.h"                // for XRE_GetProcessType, etc
@@ -39,131 +41,141 @@ namespace layers {
 
 ClientCanvasLayer::~ClientCanvasLayer()
 {
   MOZ_COUNT_DTOR(ClientCanvasLayer);
   if (mCanvasClient) {
     mCanvasClient->OnDetach();
     mCanvasClient = nullptr;
   }
+  if (mTextureSurface) {
+    mTextureSurface = nullptr;
+  }
 }
 
 void
 ClientCanvasLayer::Initialize(const Data& aData)
 {
   CopyableCanvasLayer::Initialize(aData);
 
   mCanvasClient = nullptr;
 
-  if (!mGLContext)
-    return;
-
-  GLScreenBuffer* screen = mGLContext->Screen();
+  if (mGLContext) {
+    GLScreenBuffer* screen = mGLContext->Screen();
 
-  SurfaceCaps caps;
-  if (mGLFrontbuffer) {
-    // The screen caps are irrelevant if we're using a separate frontbuffer.
-    caps = mGLFrontbuffer->mHasAlpha ? SurfaceCaps::ForRGBA()
-                                     : SurfaceCaps::ForRGB();
-  } else {
-    MOZ_ASSERT(screen);
-    caps = screen->mCaps;
-  }
-  MOZ_ASSERT(caps.alpha == aData.mHasAlpha);
+    SurfaceCaps caps;
+    if (mStream) {
+      // The screen caps are irrelevant if we're using a separate stream
+      caps = aData.mHasAlpha ? SurfaceCaps::ForRGBA() : SurfaceCaps::ForRGB();
+    } else {
+      caps = screen->mCaps;
+    }
+    MOZ_ASSERT(caps.alpha == aData.mHasAlpha);
 
-  UniquePtr<SurfaceFactory> factory;
+    SurfaceStreamType streamType =
+        SurfaceStream::ChooseGLStreamType(SurfaceStream::OffMainThread,
+                                          screen->PreserveBuffer());
+    UniquePtr<SurfaceFactory> factory;
 
-  if (!gfxPrefs::WebGLForceLayersReadback()) {
-    switch (ClientManager()->AsShadowForwarder()->GetCompositorBackendType()) {
-      case mozilla::layers::LayersBackend::LAYERS_OPENGL: {
-        if (mGLContext->GetContextType() == GLContextType::EGL) {
+    if (!gfxPrefs::WebGLForceLayersReadback()) {
+      switch (ClientManager()->AsShadowForwarder()->GetCompositorBackendType()) {
+        case mozilla::layers::LayersBackend::LAYERS_OPENGL: {
+          if (mGLContext->GetContextType() == GLContextType::EGL) {
 #ifdef MOZ_WIDGET_GONK
-          TextureFlags flags = TextureFlags::DEALLOCATE_CLIENT |
-                               TextureFlags::NEEDS_Y_FLIP;
-          if (!aData.mIsGLAlphaPremult) {
-            flags |= TextureFlags::NON_PREMULTIPLIED;
+            factory = MakeUnique<SurfaceFactory_Gralloc>(mGLContext,
+                                                         caps,
+                                                         ClientManager()->AsShadowForwarder());
+#else
+            bool isCrossProcess = !(XRE_GetProcessType() == GeckoProcessType_Default);
+            if (!isCrossProcess) {
+              // [Basic/OGL Layers, OMTC] WebGL layer init.
+              factory = SurfaceFactory_EGLImage::Create(mGLContext, caps);
+            } else {
+              // we could do readback here maybe
+              NS_NOTREACHED("isCrossProcess but not on native B2G!");
+            }
+#endif
+          } else {
+            // [Basic Layers, OMTC] WebGL layer init.
+            // Well, this *should* work...
+#ifdef XP_MACOSX
+            factory = SurfaceFactory_IOSurface::Create(mGLContext, caps);
+#else
+            GLContext* nullConsGL = nullptr; // Bug 1050044.
+            factory = MakeUnique<SurfaceFactory_GLTexture>(mGLContext, nullConsGL, caps);
+#endif
           }
-          factory = MakeUnique<SurfaceFactory_Gralloc>(mGLContext,
-                                                       caps,
-                                                       flags,
-                                                       ClientManager()->AsShadowForwarder());
-#else
-          bool isCrossProcess = !(XRE_GetProcessType() == GeckoProcessType_Default);
-          if (!isCrossProcess) {
-            // [Basic/OGL Layers, OMTC] WebGL layer init.
-            factory = SurfaceFactory_EGLImage::Create(mGLContext, caps);
-          } else {
-            // we could do readback here maybe
-            NS_NOTREACHED("isCrossProcess but not on native B2G!");
+          break;
+        }
+        case mozilla::layers::LayersBackend::LAYERS_D3D10:
+        case mozilla::layers::LayersBackend::LAYERS_D3D11: {
+#ifdef XP_WIN
+          if (mGLContext->IsANGLE()) {
+            factory = SurfaceFactory_ANGLEShareHandle::Create(mGLContext, caps);
           }
 #endif
-        } else {
-          // [Basic Layers, OMTC] WebGL layer init.
-          // Well, this *should* work...
-#ifdef XP_MACOSX
-          factory = SurfaceFactory_IOSurface::Create(mGLContext, caps);
-#else
-          GLContext* nullConsGL = nullptr; // Bug 1050044.
-          factory = MakeUnique<SurfaceFactory_GLTexture>(mGLContext, nullConsGL, caps);
-#endif
-        }
-        break;
-      }
-      case mozilla::layers::LayersBackend::LAYERS_D3D10:
-      case mozilla::layers::LayersBackend::LAYERS_D3D11: {
-#ifdef XP_WIN
-        if (mGLContext->IsANGLE()) {
-          factory = SurfaceFactory_ANGLEShareHandle::Create(mGLContext, caps);
+          break;
         }
-#endif
-        break;
+        default:
+          break;
       }
-      default:
-        break;
     }
-  }
+
+    if (mStream) {
+      // We're using a stream other than the one in the default screen
+      mFactory = Move(factory);
+      if (!mFactory) {
+        // Absolutely must have a factory here, so create a basic one
+        mFactory = MakeUnique<SurfaceFactory_Basic>(mGLContext, caps);
+      }
 
-  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);
+      gfx::IntSize size = gfx::IntSize(aData.mSize.width, aData.mSize.height);
+      mTextureSurface = SharedSurface_GLTexture::Create(mGLContext, mGLContext,
+                                                        mGLContext->GetGLFormats(),
+                                                        size, caps.alpha, aData.mTexID);
+      SharedSurface* producer = mStream->SwapProducer(mFactory.get(), size);
+      if (!producer) {
+        // Fallback to basic factory
+        mFactory = MakeUnique<SurfaceFactory_Basic>(mGLContext, caps);
+        producer = mStream->SwapProducer(mFactory.get(), size);
+        MOZ_ASSERT(producer, "Failed to create initial canvas surface with basic factory");
+      }
+    } else if (factory) {
+      screen->Morph(Move(factory), streamType);
     }
-  } else {
-    if (factory)
-      screen->Morph(Move(factory));
   }
 }
 
 void
 ClientCanvasLayer::RenderLayer()
 {
   PROFILER_LABEL("ClientCanvasLayer", "RenderLayer",
     js::ProfileEntry::Category::GRAPHICS);
 
   if (GetMaskLayer()) {
     ToClientLayer(GetMaskLayer())->RenderLayer();
   }
 
   if (!IsDirty()) {
     return;
   }
-  Painted();
 
   if (!mCanvasClient) {
     TextureFlags flags = TextureFlags::IMMEDIATE_UPLOAD;
     if (mNeedsYFlip) {
       flags |= TextureFlags::NEEDS_Y_FLIP;
     }
 
     if (!mGLContext) {
       // We don't support locking for buffer surfaces currently
       flags |= TextureFlags::IMMEDIATE_UPLOAD;
+    } else {
+      // GLContext's SurfaceStream handles ownership itself,
+      // and doesn't require layers to do any deallocation.
+      flags |= TextureFlags::DEALLOCATE_CLIENT;
     }
 
     if (!mIsAlphaPremultiplied) {
       flags |= TextureFlags::NON_PREMULTIPLIED;
     }
 
     mCanvasClient = CanvasClient::CreateCanvasClient(GetCanvasClientType(),
                                                      ClientManager()->AsShadowForwarder(),
@@ -182,25 +194,16 @@ ClientCanvasLayer::RenderLayer()
 
   FireDidTransactionCallback();
 
   ClientManager()->Hold(this);
   mCanvasClient->Updated();
   mCanvasClient->OnTransaction();
 }
 
-CanvasClient::CanvasClientType
-ClientCanvasLayer::GetCanvasClientType()
-{
-  if (mGLContext) {
-    return CanvasClient::CanvasClientTypeShSurf;
-  }
-  return CanvasClient::CanvasClientSurface;
-}
-
 already_AddRefed<CanvasLayer>
 ClientLayerManager::CreateCanvasLayer()
 {
   NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
   nsRefPtr<ClientCanvasLayer> layer =
     new ClientCanvasLayer(this);
   CREATE_SHADOW(Canvas);
   return layer.forget();
--- a/gfx/layers/client/ClientCanvasLayer.h
+++ b/gfx/layers/client/ClientCanvasLayer.h
@@ -16,16 +16,17 @@
 #include "mozilla/mozalloc.h"           // for operator delete
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsDebug.h"                    // for NS_ASSERTION
 #include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "nsRegion.h"                   // for nsIntRegion
 
 namespace mozilla {
 namespace gl {
+class SurfaceStream;
 class SharedSurface;
 class SurfaceFactory;
 }
 
 namespace layers {
 
 class CompositableClient;
 class ShadowableLayer;
@@ -33,72 +34,82 @@ class ShadowableLayer;
 class ClientCanvasLayer : public CopyableCanvasLayer,
                           public ClientLayer
 {
   typedef CanvasClient::CanvasClientType CanvasClientType;
 public:
   explicit ClientCanvasLayer(ClientLayerManager* aLayerManager) :
     CopyableCanvasLayer(aLayerManager,
                         static_cast<ClientLayer*>(MOZ_THIS_IN_INITIALIZER_LIST()))
+    , mTextureSurface(nullptr)
+    , mFactory(nullptr)
   {
     MOZ_COUNT_CTOR(ClientCanvasLayer);
   }
 
 protected:
   virtual ~ClientCanvasLayer();
 
 public:
-  virtual void SetVisibleRegion(const nsIntRegion& aRegion) MOZ_OVERRIDE
+  virtual void SetVisibleRegion(const nsIntRegion& aRegion)
   {
     NS_ASSERTION(ClientManager()->InConstruction(),
                  "Can only set properties in construction phase");
     CanvasLayer::SetVisibleRegion(aRegion);
   }
 
-  virtual void Initialize(const Data& aData) MOZ_OVERRIDE;
+  virtual void Initialize(const Data& aData);
 
-  virtual void RenderLayer() MOZ_OVERRIDE;
+  virtual void RenderLayer();
 
-  virtual void ClearCachedResources() MOZ_OVERRIDE
+  virtual void ClearCachedResources()
   {
     if (mCanvasClient) {
       mCanvasClient->Clear();
     }
   }
 
-  virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs) MOZ_OVERRIDE
+  virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
   {
     aAttrs = CanvasLayerAttributes(mFilter, mBounds);
   }
 
-  virtual Layer* AsLayer()  MOZ_OVERRIDE { return this; }
-  virtual ShadowableLayer* AsShadowableLayer()  MOZ_OVERRIDE { return this; }
+  virtual Layer* AsLayer() { return this; }
+  virtual ShadowableLayer* AsShadowableLayer() { return this; }
 
-  virtual void Disconnect() MOZ_OVERRIDE
+  virtual void Disconnect()
   {
     mCanvasClient = nullptr;
     ClientLayer::Disconnect();
   }
 
   virtual CompositableClient* GetCompositableClient() MOZ_OVERRIDE
   {
     return mCanvasClient;
   }
 protected:
   ClientLayerManager* ClientManager()
   {
     return static_cast<ClientLayerManager*>(mManager);
   }
 
-  CanvasClientType GetCanvasClientType();
+  CanvasClientType GetCanvasClientType()
+  {
+    if (mGLContext) {
+      return CanvasClient::CanvasClientGLContext;
+    }
+    return CanvasClient::CanvasClientSurface;
+  }
 
   RefPtr<CanvasClient> mCanvasClient;
 
+  UniquePtr<gl::SharedSurface> mTextureSurface;
   UniquePtr<gl::SurfaceFactory> mFactory;
 
   friend class DeprecatedCanvasClient2D;
   friend class CanvasClient2D;
-  friend class CanvasClientSharedSurface;
+  friend class DeprecatedCanvasClientSurfaceStream;
+  friend class CanvasClientSurfaceStream;
 };
 }
 }
 
 #endif
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -14,17 +14,17 @@
 #include "mozilla/layers/ImageDataSerializer.h"
 #include "mozilla/layers/YCbCrImageDataSerializer.h"
 #include "nsDebug.h"                    // for NS_ASSERTION, NS_WARNING, etc
 #include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "ImageContainer.h"             // for PlanarYCbCrData, etc
 #include "mozilla/gfx/2D.h"
 #include "mozilla/layers/TextureClientOGL.h"
 #include "mozilla/layers/PTextureChild.h"
-#include "SharedSurface.h"
+#include "SurfaceStream.h"
 #include "GLContext.h"
 
 #ifdef XP_WIN
 #include "mozilla/layers/TextureD3D9.h"
 #include "mozilla/layers/TextureD3D11.h"
 #include "mozilla/layers/TextureDIB.h"
 #include "gfxWindowsPlatform.h"
 #include "gfx2DGlue.h"
@@ -787,46 +787,67 @@ BufferTextureClient::AllocateForYCbCr(gf
   YCbCrImageDataSerializer serializer(GetBuffer(), GetBufferSize());
   serializer.InitializeBufferInfo(aYSize,
                                   aCbCrSize,
                                   aStereoMode);
   mSize = aYSize;
   return true;
 }
 
-uint8_t*
-BufferTextureClient::GetLockedData() const
+////////////////////////////////////////////////////////////////////////
+// StreamTextureClient
+StreamTextureClient::StreamTextureClient(TextureFlags aFlags)
+  : TextureClient(aFlags)
+  , mIsLocked(false)
 {
-  MOZ_ASSERT(IsLocked());
-
-  ImageDataSerializer serializer(GetBuffer(), GetBufferSize());
-  MOZ_ASSERT(serializer.IsValid());
-
-  return serializer.GetData();
 }
 
-////////////////////////////////////////////////////////////////////////
-// SharedSurfaceTextureClient
-
-SharedSurfaceTextureClient::SharedSurfaceTextureClient(TextureFlags aFlags,
-                                                       gl::SharedSurface* surf)
-  : TextureClient(aFlags)
-  , mIsLocked(false)
-  , mSurf(surf)
-  , mGL(mSurf->mGL)
-{
-  mSurf->Fence();
-}
-
-SharedSurfaceTextureClient::~SharedSurfaceTextureClient()
+StreamTextureClient::~StreamTextureClient()
 {
   // the data is owned externally.
 }
 
 bool
-SharedSurfaceTextureClient::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
+StreamTextureClient::Lock(OpenMode mode)
 {
-  aOutDescriptor = SharedSurfaceDescriptor((uintptr_t)mSurf);
+  MOZ_ASSERT(!mIsLocked);
+  if (!IsValid() || !IsAllocated()) {
+    return false;
+  }
+  mIsLocked = true;
   return true;
 }
 
+void
+StreamTextureClient::Unlock()
+{
+  MOZ_ASSERT(mIsLocked);
+  mIsLocked = false;
+}
+
+bool
+StreamTextureClient::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
+{
+  if (!IsAllocated()) {
+    return false;
+  }
+
+  aOutDescriptor = SurfaceStreamDescriptor((uintptr_t)mStream.get(), false);
+  return true;
+}
+
+void
+StreamTextureClient::InitWith(gl::SurfaceStream* aStream)
+{
+  MOZ_ASSERT(!IsAllocated());
+  mStream = aStream;
+  mGL = mStream->GLContext();
+}
+
+bool
+StreamTextureClient::IsAllocated() const
+{
+  return mStream != 0;
+}
+
+
 }
 }
--- a/gfx/layers/client/TextureClient.h
+++ b/gfx/layers/client/TextureClient.h
@@ -29,17 +29,17 @@
 #include "GfxTexturesReporter.h"
 
 class gfxReusableSurfaceWrapper;
 class gfxImageSurface;
 
 namespace mozilla {
 namespace gl {
 class GLContext;
-class SharedSurface;
+class SurfaceStream;
 }
 
 namespace layers {
 
 class AsyncTransactionTracker;
 class ContentClient;
 class CompositableForwarder;
 class ISurfaceAllocator;
@@ -291,33 +291,16 @@ public:
   /**
    * TextureFlags contain important information about various aspects
    * of the texture, like how its liferime is managed, and how it
    * should be displayed.
    * See TextureFlags in CompositorTypes.h.
    */
   TextureFlags GetFlags() const { return mFlags; }
 
-  bool HasFlags(TextureFlags aFlags) const
-  {
-    return (mFlags & aFlags) == aFlags;
-  }
-
-  void AddFlags(TextureFlags aFlags)
-  {
-    MOZ_ASSERT(!IsSharedWithCompositor());
-    mFlags |= aFlags;
-  }
-
-  void RemoveFlags(TextureFlags aFlags)
-  {
-    MOZ_ASSERT(!IsSharedWithCompositor());
-    mFlags &= ~aFlags;
-  }
-
   /**
    * valid only for TextureFlags::RECYCLE TextureClient.
    * When called this texture client will grab a strong reference and release
    * it once the compositor notifies that it is done with the texture.
    * NOTE: In this stage the texture client can no longer be used by the
    * client in a transaction.
    */
   void WaitForCompositorRecycle();
@@ -443,16 +426,22 @@ protected:
    * Some texture implementations rely on the fact that the descriptor will be
    * deserialized.
    * Calling ToSurfaceDescriptor again after it has already returned true,
    * or never constructing a TextureHost with aDescriptor may result in a memory
    * leak (see CairoTextureClientD3D9 for example).
    */
   virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aDescriptor) = 0;
 
+  void AddFlags(TextureFlags  aFlags)
+  {
+    MOZ_ASSERT(!IsSharedWithCompositor());
+    mFlags |= aFlags;
+  }
+
   ISurfaceAllocator* GetAllocator()
   {
     return mAllocator;
   }
 
   RefPtr<TextureChild> mActor;
   RefPtr<ISurfaceAllocator> mAllocator;
   TextureFlags mFlags;
@@ -510,18 +499,16 @@ public:
   virtual gfx::IntSize GetSize() const { return mSize; }
 
   virtual bool Lock(OpenMode aMode) MOZ_OVERRIDE;
 
   virtual void Unlock() MOZ_OVERRIDE;
 
   virtual bool IsLocked() const MOZ_OVERRIDE { return mLocked; }
 
-  uint8_t* GetLockedData() const;
-
   virtual bool CanExposeDrawTarget() const MOZ_OVERRIDE { return true; }
 
   virtual gfx::DrawTarget* BorrowDrawTarget() MOZ_OVERRIDE;
 
   virtual bool AllocateForSurface(gfx::IntSize aSize,
                                   TextureAllocationFlags aFlags = ALLOC_DEFAULT) MOZ_OVERRIDE;
 
   // TextureClientYCbCr
@@ -623,71 +610,63 @@ public:
   virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return true; }
 
 protected:
   uint8_t* mBuffer;
   size_t mBufSize;
 };
 
 /**
- * A TextureClient implementation to share SharedSurfaces.
+ * A TextureClient implementation to share SurfaceStream.
  */
-class SharedSurfaceTextureClient : public TextureClient
+class StreamTextureClient : public TextureClient
 {
 public:
-  SharedSurfaceTextureClient(TextureFlags aFlags, gl::SharedSurface* surf);
+  explicit StreamTextureClient(TextureFlags aFlags);
 
 protected:
-  ~SharedSurfaceTextureClient();
+  ~StreamTextureClient();
 
 public:
-  // Boilerplate start
-  virtual bool IsAllocated() const MOZ_OVERRIDE { return true; }
+  virtual bool IsAllocated() const MOZ_OVERRIDE;
 
-  virtual bool Lock(OpenMode) MOZ_OVERRIDE {
-    MOZ_ASSERT(!mIsLocked);
-    mIsLocked = true;
-    return true;
-  }
+  virtual bool Lock(OpenMode mode) MOZ_OVERRIDE;
 
-  virtual void Unlock() MOZ_OVERRIDE {
-    MOZ_ASSERT(mIsLocked);
-    mIsLocked = false;
-  }
+  virtual void Unlock() MOZ_OVERRIDE;
 
   virtual bool IsLocked() const MOZ_OVERRIDE { return mIsLocked; }
 
+  virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) MOZ_OVERRIDE;
+
   virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return false; }
 
-  virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE {
+  void InitWith(gl::SurfaceStream* aStream);
+
+  virtual gfx::IntSize GetSize() const { return gfx::IntSize(); }
+
+  virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE
+  {
     return gfx::SurfaceFormat::UNKNOWN;
   }
 
-  virtual gfx::IntSize GetSize() const MOZ_OVERRIDE { return gfx::IntSize(); }
-
   // This TextureClient should not be used in a context where we use CreateSimilar
   // (ex. component alpha) because the underlying texture data is always created by
   // an external producer.
   virtual TemporaryRef<TextureClient>
-  CreateSimilar(TextureFlags, TextureAllocationFlags) const MOZ_OVERRIDE {
-    return nullptr;
-  }
+  CreateSimilar(TextureFlags, TextureAllocationFlags) const MOZ_OVERRIDE { return nullptr; }
 
-  virtual bool AllocateForSurface(gfx::IntSize,
-                                  TextureAllocationFlags) MOZ_OVERRIDE {
+  virtual bool AllocateForSurface(gfx::IntSize aSize, TextureAllocationFlags aFlags) MOZ_OVERRIDE
+  {
     MOZ_CRASH("Should never hit this.");
     return false;
   }
-  // Boilerplate end
-
-  virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) MOZ_OVERRIDE;
 
 protected:
   bool mIsLocked;
-  gl::SharedSurface* const mSurf;
+  RefPtr<gl::SurfaceStream> mStream;
   RefPtr<gl::GLContext> mGL; // Just for reference holding.
 };
 
 struct TextureClientAutoUnlock
 {
   TextureClient* mTexture;
 
   explicit TextureClientAutoUnlock(TextureClient* aTexture)
--- a/gfx/layers/composite/TextureHost.cpp
+++ b/gfx/layers/composite/TextureHost.cpp
@@ -21,16 +21,17 @@
 #include "nsAutoPtr.h"                  // for nsRefPtr
 #include "nsPrintfCString.h"            // for nsPrintfCString
 #include "mozilla/layers/PTextureParent.h"
 #include "mozilla/unused.h"
 #include <limits>
 #include "SharedSurface.h"
 #include "SharedSurfaceEGL.h"
 #include "SharedSurfaceGL.h"
+#include "SurfaceStream.h"
 #include "../opengl/CompositorOGL.h"
 
 #ifdef MOZ_ENABLE_D3D10_LAYER
 #include "../d3d11/CompositorD3D11.h"
 #endif
 
 #ifdef MOZ_WIDGET_GONK
 #include "../opengl/GrallocTextureClient.h"
@@ -194,18 +195,18 @@ TextureHost::Create(const SurfaceDescrip
     case SurfaceDescriptor::TSurfaceDescriptorDIB:
       return CreateBackendIndependentTextureHost(aDesc, aDeallocator, aFlags);
 
     case SurfaceDescriptor::TEGLImageDescriptor:
     case SurfaceDescriptor::TNewSurfaceDescriptorGralloc:
     case SurfaceDescriptor::TSurfaceTextureDescriptor:
       return CreateTextureHostOGL(aDesc, aDeallocator, aFlags);
 
-    case SurfaceDescriptor::TSharedSurfaceDescriptor:
-      return new SharedSurfaceTextureHost(aFlags, aDesc.get_SharedSurfaceDescriptor());
+    case SurfaceDescriptor::TSurfaceStreamDescriptor:
+      return new StreamTextureHost(aFlags, aDesc.get_SurfaceStreamDescriptor());
 
     case SurfaceDescriptor::TSurfaceDescriptorMacIOSurface:
       if (Compositor::GetBackend() == LayersBackend::LAYERS_OPENGL) {
         return CreateTextureHostOGL(aDesc, aDeallocator, aFlags);
       } else {
         return CreateTextureHostBasic(aDesc, aDeallocator, aFlags);
       }
 
@@ -790,140 +791,214 @@ TextureParent::ClearTextureHost()
   // Clear recycle callback.
   mTextureHost->ClearRecycleCallback();
   mWaitForClientRecycle = nullptr;
 
   mTextureHost->mActor = nullptr;
   mTextureHost = nullptr;
 }
 
-////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
+// StreamTextureHost
 
-static RefPtr<TextureSource>
-SharedSurfaceToTexSource(gl::SharedSurface* abstractSurf, Compositor* compositor)
+StreamTextureHost::StreamTextureHost(TextureFlags aFlags,
+                                     const SurfaceStreamDescriptor& aDesc)
+  : TextureHost(aFlags)
+{
+  mStream = (gl::SurfaceStream*)aDesc.surfStream();
+  MOZ_ASSERT(mStream);
+}
+
+StreamTextureHost::~StreamTextureHost()
 {
-  MOZ_ASSERT(abstractSurf);
-  MOZ_ASSERT(abstractSurf->mType != gl::SharedSurfaceType::Basic);
-  MOZ_ASSERT(abstractSurf->mType != gl::SharedSurfaceType::Gralloc);
+  // If need to deallocate textures, call DeallocateSharedData() before
+  // the destructor
+}
 
-  if (!compositor) {
-    return nullptr;
+bool
+StreamTextureHost::Lock()
+{
+  if (!mCompositor) {
+    return false;
+  }
+
+  gl::SharedSurface* abstractSurf = mStream->SwapConsumer();
+  if (!abstractSurf) {
+    return false;
   }
 
-  gfx::SurfaceFormat format = abstractSurf->mHasAlpha ? gfx::SurfaceFormat::R8G8B8A8
-                                                      : gfx::SurfaceFormat::R8G8B8X8;
-
-  RefPtr<TextureSource> texSource;
-  switch (abstractSurf->mType) {
-#ifdef XP_WIN
-    case gl::SharedSurfaceType::EGLSurfaceANGLE: {
-      auto surf = gl::SharedSurface_ANGLEShareHandle::Cast(abstractSurf);
-      HANDLE shareHandle = surf->GetShareHandle();
-
-      MOZ_ASSERT(compositor->GetBackendType() == LayersBackend::LAYERS_D3D11);
-      CompositorD3D11* compositorD3D11 = static_cast<CompositorD3D11*>(compositor);
-      ID3D11Device* d3d = compositorD3D11->GetDevice();
-
-      nsRefPtr<ID3D11Texture2D> tex;
-      HRESULT hr = d3d->OpenSharedResource(shareHandle,
-                                           __uuidof(ID3D11Texture2D),
-                                           getter_AddRefs(tex));
-      if (FAILED(hr)) {
-        NS_WARNING("Failed to open shared resource.");
-        break;
+  bool compositorSupportsShSurfType = false;
+  switch (mCompositor->GetBackendType()) {
+    case LayersBackend::LAYERS_BASIC:
+    case LayersBackend::LAYERS_D3D9:
+    case LayersBackend::LAYERS_D3D10:
+      switch (abstractSurf->mType) {
+        case gl::SharedSurfaceType::Basic:
+          compositorSupportsShSurfType = true;
+          break;
+        default:
+          break;
       }
-      texSource = new DataTextureSourceD3D11(format, compositorD3D11, tex);
       break;
-    }
-#endif
-    case gl::SharedSurfaceType::GLTextureShare: {
-      auto surf = gl::SharedSurface_GLTexture::Cast(abstractSurf);
-
-      MOZ_ASSERT(compositor->GetBackendType() == LayersBackend::LAYERS_OPENGL);
-      CompositorOGL* compositorOGL = static_cast<CompositorOGL*>(compositor);
-      gl::GLContext* gl = compositorOGL->gl();
-
-      GLenum target = surf->ConsTextureTarget();
-      GLuint tex = surf->ConsTexture(gl);
-      texSource = new GLTextureSource(compositorOGL, tex, format, target,
-                                      surf->mSize);
+    case LayersBackend::LAYERS_OPENGL:
+      switch (abstractSurf->mType) {
+        case gl::SharedSurfaceType::Basic:
+        case gl::SharedSurfaceType::GLTextureShare:
+        case gl::SharedSurfaceType::EGLImageShare:
+        case gl::SharedSurfaceType::Gralloc:
+        case gl::SharedSurfaceType::IOSurface:
+          compositorSupportsShSurfType = true;
+          break;
+        default:
+          break;
+      }
       break;
-    }
-    case gl::SharedSurfaceType::EGLImageShare: {
-      auto surf = gl::SharedSurface_EGLImage::Cast(abstractSurf);
-
-      MOZ_ASSERT(compositor->GetBackendType() == LayersBackend::LAYERS_OPENGL);
-      CompositorOGL* compositorOGL = static_cast<CompositorOGL*>(compositor);
-      gl::GLContext* gl = compositorOGL->gl();
-      MOZ_ASSERT(gl->IsCurrent());
-
-      GLenum target = 0;
-      GLuint tex = 0;
-      surf->AcquireConsumerTexture(gl, &tex, &target);
-
-      texSource = new GLTextureSource(compositorOGL, tex, format, target,
-                                      surf->mSize);
+    case LayersBackend::LAYERS_D3D11:
+      switch (abstractSurf->mType) {
+        case gl::SharedSurfaceType::Basic:
+        case gl::SharedSurfaceType::EGLSurfaceANGLE:
+          compositorSupportsShSurfType = true;
+          break;
+        default:
+          break;
+      }
       break;
-    }
-#ifdef XP_MACOSX
-    case gl::SharedSurfaceType::IOSurface: {
-      auto surf = gl::SharedSurface_IOSurface::Cast(abstractSurf);
-      MacIOSurface* ioSurf = surf->GetIOSurface();
-
-      MOZ_ASSERT(compositor->GetBackendType() == LayersBackend::LAYERS_OPENGL);
-      CompositorOGL* compositorOGL = static_cast<CompositorOGL*>(compositor);
-
-      texSource = new MacIOSurfaceTextureSourceOGL(compositorOGL, ioSurf);
-      break;
-    }
-#endif
     default:
       break;
   }
 
-  MOZ_ASSERT(texSource.get(), "TextureSource creation failed.");
-  return texSource;
+  RefPtr<TextureSource> newTexSource;
+  if (compositorSupportsShSurfType) {
+    gfx::SurfaceFormat format = abstractSurf->mHasAlpha ? gfx::SurfaceFormat::R8G8B8A8
+                                                        : gfx::SurfaceFormat::R8G8B8X8;
+
+    switch (abstractSurf->mType) {
+      case gl::SharedSurfaceType::Basic: {
+        gl::SharedSurface_Basic* surf = gl::SharedSurface_Basic::Cast(abstractSurf);
+
+        if (!this->mDataTextureSource) {
+          TextureFlags flags = TextureFlags::DEALLOCATE_CLIENT;
+          this->mDataTextureSource = mCompositor->CreateDataTextureSource(flags);
+        }
+        this->mDataTextureSource->Update(surf->GetData());
+
+        newTexSource = mDataTextureSource;
+        break;
+      }
+      case gl::SharedSurfaceType::GLTextureShare: {
+        gl::SharedSurface_GLTexture* surf = gl::SharedSurface_GLTexture::Cast(abstractSurf);
+
+        MOZ_ASSERT(mCompositor->GetBackendType() == LayersBackend::LAYERS_OPENGL);
+        CompositorOGL* compositorOGL = static_cast<CompositorOGL*>(mCompositor);
+        gl::GLContext* gl = compositorOGL->gl();
+
+        GLenum target = surf->ConsTextureTarget();
+        GLuint tex = surf->ConsTexture(gl);
+        newTexSource = new GLTextureSource(compositorOGL,
+                                           tex,
+                                           format,
+                                           target,
+                                           surf->mSize);
+        break;
+      }
+#ifdef MOZ_ENABLE_D3D10_LAYER
+      case gl::SharedSurfaceType::EGLSurfaceANGLE: {
+        gl::SharedSurface_ANGLEShareHandle* surf = gl::SharedSurface_ANGLEShareHandle::Cast(abstractSurf);
+        HANDLE shareHandle = surf->GetShareHandle();
+
+        MOZ_ASSERT(mCompositor->GetBackendType() == LayersBackend::LAYERS_D3D11);
+        CompositorD3D11* compositorD3D11 = static_cast<CompositorD3D11*>(mCompositor);
+        ID3D11Device* d3d = compositorD3D11->GetDevice();
+
+        nsRefPtr<ID3D11Texture2D> tex;
+        HRESULT hr = d3d->OpenSharedResource(shareHandle,
+                                             __uuidof(ID3D11Texture2D),
+                                             getter_AddRefs(tex));
+        if (FAILED(hr)) {
+          NS_WARNING("Failed to open shared resource.");
+          break;
+        }
+        newTexSource = new DataTextureSourceD3D11(format, compositorD3D11, tex);
+        break;
+      }
+#endif
+      case gl::SharedSurfaceType::EGLImageShare: {
+        gl::SharedSurface_EGLImage* surf = gl::SharedSurface_EGLImage::Cast(abstractSurf);
+
+        MOZ_ASSERT(mCompositor->GetBackendType() == LayersBackend::LAYERS_OPENGL);
+        CompositorOGL* compositorOGL = static_cast<CompositorOGL*>(mCompositor);
+        gl::GLContext* gl = compositorOGL->gl();
+        MOZ_ASSERT(gl->IsCurrent());
+
+        GLenum target = 0;
+        GLuint tex = 0;
+        surf->AcquireConsumerTexture(gl, &tex, &target);
+
+        newTexSource = new GLTextureSource(compositorOGL,
+                                           tex,
+                                           format,
+                                           target,
+                                           surf->mSize);
+        break;
+      }
+      case gl::SharedSurfaceType::Gralloc: {
+        MOZ_ASSERT(false, "WebGL in the Host process? Gralloc without E10S? Not yet supported.");
+        break;
+      }
+#ifdef XP_MACOSX
+      case gl::SharedSurfaceType::IOSurface: {
+        gl::SharedSurface_IOSurface* surf = gl::SharedSurface_IOSurface::Cast(abstractSurf);
+        MacIOSurface* ioSurf = surf->GetIOSurface();
+
+        MOZ_ASSERT(mCompositor->GetBackendType() == LayersBackend::LAYERS_OPENGL);
+        CompositorOGL* compositorOGL = static_cast<CompositorOGL*>(mCompositor);
+
+        newTexSource = new MacIOSurfaceTextureSourceOGL(compositorOGL,
+                                                        ioSurf);
+        break;
+      }
+#endif
+      default:
+        break;
+    }
+  } else {
+    // Do readback, and make a buffer view for it?
+    NS_WARNING("`!compositorSupportsShSurfType`.");
+    return false;
+  }
+
+  MOZ_ASSERT(newTexSource.get(), "TextureSource creation failed.");
+  if (!newTexSource)
+    return false;
+
+  mTextureSource = newTexSource;
+  return true;
 }
 
-////////////////////////////////////////////////////////////////////////////////
-// SharedSurfaceTextureHost
+void
+StreamTextureHost::Unlock()
+{
+}
 
-SharedSurfaceTextureHost::SharedSurfaceTextureHost(TextureFlags aFlags,
-                                                   const SharedSurfaceDescriptor& aDesc)
-  : TextureHost(aFlags)
-  , mIsLocked(false)
-  , mSurf((gl::SharedSurface*)aDesc.surf())
-  , mCompositor(nullptr)
+void
+StreamTextureHost::SetCompositor(Compositor* aCompositor)
 {
-  MOZ_ASSERT(mSurf);
+  mCompositor = aCompositor;
 }
 
 gfx::SurfaceFormat
-SharedSurfaceTextureHost::GetFormat() const
+StreamTextureHost::GetFormat() const
 {
-  MOZ_ASSERT(mTexSource);
-  return mTexSource->GetFormat();
+  MOZ_ASSERT(mTextureSource);
+  return mTextureSource->GetFormat();
 }
 
 gfx::IntSize
-SharedSurfaceTextureHost::GetSize() const
+StreamTextureHost::GetSize() const
 {
-  MOZ_ASSERT(mTexSource);
-  return mTexSource->GetSize();
+  MOZ_ASSERT(mTextureSource);
+  return mTextureSource->GetSize();
 }
 
-void
-SharedSurfaceTextureHost::EnsureTexSource()
-{
-  MOZ_ASSERT(mIsLocked);
-
-  if (mTexSource)
-    return;
-
-  mSurf->WaitSync();
-  mTexSource = SharedSurfaceToTexSource(mSurf, mCompositor);
-  MOZ_ASSERT(mTexSource);
-}
-
-////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////
 
 } // namespace
 } // namespace
--- a/gfx/layers/composite/TextureHost.h
+++ b/gfx/layers/composite/TextureHost.h
@@ -30,30 +30,30 @@
 
 class gfxReusableSurfaceWrapper;
 struct nsIntPoint;
 struct nsIntSize;
 struct nsIntRect;
 
 namespace mozilla {
 namespace gl {
-class SharedSurface;
+class SurfaceStream;
 }
 namespace ipc {
 class Shmem;
 }
 
 namespace layers {
 
 class Compositor;
 class CompositableHost;
 class CompositableBackendSpecificData;
 class CompositableParentManager;
 class SurfaceDescriptor;
-class SharedSurfaceDescriptor;
+class SurfaceStreamDescriptor;
 class ISurfaceAllocator;
 class TextureHostOGL;
 class TextureSourceOGL;
 class TextureSourceD3D9;
 class TextureSourceD3D11;
 class TextureSourceBasic;
 class DataTextureSource;
 class PTextureParent;
@@ -567,76 +567,57 @@ public:
 
   virtual const char *Name() MOZ_OVERRIDE { return "MemoryTextureHost"; }
 
 protected:
   uint8_t* mBuffer;
 };
 
 /**
- * A TextureHost for SharedSurfaces
+ * A TextureHost for shared SurfaceStream
  */
-class SharedSurfaceTextureHost : public TextureHost
+class StreamTextureHost : public TextureHost
 {
 public:
-  SharedSurfaceTextureHost(TextureFlags aFlags,
-                           const SharedSurfaceDescriptor& aDesc);
+  StreamTextureHost(TextureFlags aFlags,
+                    const SurfaceStreamDescriptor& aDesc);
 
-  virtual ~SharedSurfaceTextureHost() {};
+  virtual ~StreamTextureHost();
 
   virtual void DeallocateDeviceData() MOZ_OVERRIDE {};
 
-  virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() MOZ_OVERRIDE {
-    return nullptr; // XXX - implement this (for MOZ_DUMP_PAINTING)
-  }
+  virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
+
+  virtual bool Lock() MOZ_OVERRIDE;
+
+  virtual void Unlock() MOZ_OVERRIDE;
 
-  virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE {
-    MOZ_ASSERT(!mIsLocked);
+  virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE;
 
-    if (aCompositor == mCompositor)
-      return;
-
-    mTexSource = nullptr;
-    mCompositor = aCompositor;
+  virtual TextureSource* GetTextureSources() MOZ_OVERRIDE
+  {
+    return mTextureSource;
   }
 
-public:
-  virtual bool Lock() MOZ_OVERRIDE {
-    MOZ_ASSERT(!mIsLocked);
-    mIsLocked = true;
-    EnsureTexSource();
-    return true;
+  virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() MOZ_OVERRIDE
+  {
+    return nullptr; // XXX - implement this (for MOZ_DUMP_PAINTING)
   }
 
-  virtual void Unlock() MOZ_OVERRIDE {
-    MOZ_ASSERT(mIsLocked);
-    mIsLocked = false;
-  }
-
-  virtual TextureSource* GetTextureSources() MOZ_OVERRIDE {
-    MOZ_ASSERT(mIsLocked);
-    MOZ_ASSERT(mTexSource);
-    return mTexSource;
-  }
-
-  virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE;
-
   virtual gfx::IntSize GetSize() const MOZ_OVERRIDE;
 
 #ifdef MOZ_LAYERS_HAVE_LOG
-  virtual const char* Name() { return "SharedSurfaceTextureHost"; }
+  virtual const char* Name() { return "StreamTextureHost"; }
 #endif
 
 protected:
-  void EnsureTexSource();
-
-  bool mIsLocked;
-  gl::SharedSurface* const mSurf;
   Compositor* mCompositor;
-  RefPtr<TextureSource> mTexSource;
+  gl::SurfaceStream* mStream;
+  RefPtr<TextureSource> mTextureSource;
+  RefPtr<DataTextureSource> mDataTextureSource;
 };
 
 class MOZ_STACK_CLASS AutoLockTextureHost
 {
 public:
   explicit AutoLockTextureHost(TextureHost* aTexture)
     : mTexture(aTexture)
   {
--- a/gfx/layers/d3d10/CanvasLayerD3D10.cpp
+++ b/gfx/layers/d3d10/CanvasLayerD3D10.cpp
@@ -3,16 +3,17 @@
  * 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 "CanvasLayerD3D10.h"
 
 #include "../d3d9/Nv3DVUtils.h"
 #include "gfxWindowsSurface.h"
 #include "gfxWindowsPlatform.h"
+#include "SurfaceStream.h"
 #include "SharedSurfaceANGLE.h"
 #include "SharedSurfaceGL.h"
 #include "gfxContext.h"
 #include "GLContext.h"
 #include "gfxPrefs.h"
 
 namespace mozilla {
 namespace layers {
@@ -41,27 +42,30 @@ CanvasLayerD3D10::Initialize(const Data&
 
   if (aData.mGLContext) {
     mGLContext = aData.mGLContext;
     NS_ASSERTION(mGLContext->IsOffscreen(), "Canvas GLContext must be offscreen.");
     mDataIsPremultiplied = aData.mIsGLAlphaPremult;
     mNeedsYFlip = true;
 
     GLScreenBuffer* screen = mGLContext->Screen();
+    SurfaceStreamType streamType =
+        SurfaceStream::ChooseGLStreamType(SurfaceStream::MainThread,
+                                          screen->PreserveBuffer());
 
     UniquePtr<SurfaceFactory> factory = nullptr;
     if (!gfxPrefs::WebGLForceLayersReadback()) {
       if (mGLContext->IsANGLE()) {
         factory = SurfaceFactory_ANGLEShareHandle::Create(mGLContext,
                                                           screen->mCaps);
       }
     }
 
     if (factory) {
-      screen->Morph(Move(factory));
+      screen->Morph(Move(factory), streamType);
     }
   } else if (aData.mDrawTarget) {
     mDrawTarget = aData.mDrawTarget;
     mNeedsYFlip = false;
     mDataIsPremultiplied = true;
     void *texture = mDrawTarget->GetNativeSurface(NativeSurfaceType::D3D10_TEXTURE);
 
     if (texture) {
@@ -112,23 +116,20 @@ CanvasLayerD3D10::UpdateSurface()
     return;
   }
 
   if (!mTexture) {
     return;
   }
 
   if (mGLContext) {
-    auto screen = mGLContext->Screen();
-    MOZ_ASSERT(screen);
-
-    SharedSurface* surf = screen->Front()->Surf();
-    if (!surf)
+    SharedSurface* surf = mGLContext->RequestFrame();
+    if (!surf) {
       return;
-    surf->WaitSync();
+    }
 
     switch (surf->mType) {
       case SharedSurfaceType::EGLSurfaceANGLE: {
         SharedSurface_ANGLEShareHandle* shareSurf = SharedSurface_ANGLEShareHandle::Cast(surf);
         HANDLE shareHandle = shareSurf->GetShareHandle();
 
         HRESULT hr = device()->OpenSharedResource(shareHandle,
                                                   __uuidof(ID3D10Texture2D),
--- a/gfx/layers/d3d11/TextureD3D11.cpp
+++ b/gfx/layers/d3d11/TextureD3D11.cpp
@@ -149,16 +149,19 @@ CreateTextureHostD3D11(const SurfaceDesc
       result = CreateBackendIndependentTextureHost(aDesc, aDeallocator, aFlags);
       break;
     }
     case SurfaceDescriptor::TSurfaceDescriptorD3D10: {
       result = new DXGITextureHostD3D11(aFlags,
                                         aDesc.get_SurfaceDescriptorD3D10());
       break;
     }
+    case SurfaceDescriptor::TSurfaceStreamDescriptor: {
+      MOZ_CRASH("Should never hit this.");
+    }
     default: {
       NS_WARNING("Unsupported SurfaceDescriptor type");
     }
   }
   return result;
 }
 
 TextureClientD3D11::TextureClientD3D11(gfx::SurfaceFormat aFormat, TextureFlags aFlags)
--- a/gfx/layers/d3d9/CanvasLayerD3D9.cpp
+++ b/gfx/layers/d3d9/CanvasLayerD3D9.cpp
@@ -3,16 +3,17 @@
  * 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 "mozilla/layers/PLayerTransaction.h"
 
 #include "gfxWindowsSurface.h"
 #include "gfxWindowsPlatform.h"
+#include "SurfaceStream.h"
 #include "SharedSurface.h"
 #include "SharedSurfaceGL.h"
 #include "GLContext.h"
 #include "CanvasLayerD3D9.h"
 
 using namespace mozilla::gfx;
 using namespace mozilla::gl;
 
@@ -74,23 +75,19 @@ CanvasLayerD3D9::UpdateSurface()
       NS_WARNING("CanvasLayerD3D9::Updated called but no texture present and creation failed!");
       return;
     }
   }
 
   RefPtr<SourceSurface> surface;
 
   if (mGLContext) {
-    auto screen = mGLContext->Screen();
-    MOZ_ASSERT(screen);
-
-    SharedSurface* surf = screen->Front()->Surf();
+    SharedSurface* surf = mGLContext->RequestFrame();
     if (!surf)
-      return;
-    surf->WaitSync();
+        return;
 
     SharedSurface_Basic* shareSurf = SharedSurface_Basic::Cast(surf);
     surface = shareSurf->GetData();
   } else {
     surface = mDrawTarget->Snapshot();
   }
 
   // WebGL reads entire surface.
--- a/gfx/layers/ipc/LayersSurfaces.ipdlh
+++ b/gfx/layers/ipc/LayersSurfaces.ipdlh
@@ -71,18 +71,19 @@ struct NewSurfaceDescriptorGralloc {
   /**
    * android::GraphicBuffer has a size information. But there are cases
    * that GraphicBuffer's size and actual video's size are different.
    * Extra size member is necessary. See Bug 850566.
    */
   IntSize size;
 };
 
-struct SharedSurfaceDescriptor {
-  uintptr_t surf;
+struct SurfaceStreamDescriptor {
+  uintptr_t surfStream;
+  bool yflip;
 };
 
 /**
  * Used for shmem-backed YCbCr and (flavors of) RGBA textures
  */
 struct SurfaceDescriptorShmem {
   Shmem data;
   SurfaceFormat format;
@@ -100,16 +101,16 @@ union SurfaceDescriptor {
   SurfaceDescriptorShmem;
   SurfaceDescriptorMemory;
   SurfaceDescriptorD3D9;
   SurfaceDescriptorDIB;
   SurfaceDescriptorD3D10;
   SurfaceDescriptorX11;
   SurfaceTextureDescriptor;
   EGLImageDescriptor;
+  SurfaceStreamDescriptor;
   SurfaceDescriptorMacIOSurface;
   NewSurfaceDescriptorGralloc;
-  SharedSurfaceDescriptor;
   null_t;
 };
 
 } // namespace
 } // namespace
--- a/gfx/layers/moz.build
+++ b/gfx/layers/moz.build
@@ -12,34 +12,32 @@ EXPORTS += [
     'basic/BasicPaintedLayer.h',
     'client/ClientCanvasLayer.h',
     'client/ClientContainerLayer.h',
     'client/ClientLayerManager.h',
     'client/ClientPaintedLayer.h',
     'client/ClientTiledPaintedLayer.h',
     'composite/CompositableHost.h',
     'composite/ImageHost.h',
-    'CompositorTypes.h',
     'CopyableCanvasLayer.h',
     'D3D9SurfaceImage.h',
     'FrameMetrics.h',
     'GLImages.h',
     'GrallocImages.h',
     'ImageContainer.h',
     'ImageLayers.h',
     'ImageTypes.h',
     'ipc/CompositorChild.h',
     'ipc/CompositorParent.h',
     'ipc/ShadowLayersManager.h',
     'ipc/ThreadSafeRefcountingWithMainThreadDestruction.h',
     'Layers.h',
     'LayerScope.h',
     'LayersLogging.h',
     'LayerSorter.h',
-    'LayersTypes.h',
     'LayerTreeInvalidation.h',
     'opengl/Composer2D.h',
     'opengl/OGLShaderProgram.h',
     'opengl/TexturePoolOGL.h',
     'protobuf/LayerScopePacket.pb.h',
     'ReadbackLayer.h',
     'TiledLayerBuffer.h',
 ]
@@ -95,17 +93,17 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'wind
             'd3d10/PaintedLayerD3D10.cpp',
             'd3d10/ReadbackManagerD3D10.cpp',
             'd3d11/TextureD3D11.cpp',
             'ipc/ShadowLayerUtilsD3D10.cpp',
         ]
         SOURCES += [
             'd3d11/CompositorD3D11.cpp',
             'd3d11/ReadbackManagerD3D11.cpp',
-        ]
+        ]         
         if CONFIG['MOZ_ENABLE_DIRECT2D1_1']:
             DEFINES['USE_D2D1_1'] = True
 
 EXPORTS.gfxipc += [
     'ipc/ShadowLayerUtils.h',
 ]
 
 EXPORTS.mozilla.layers += [
--- a/gfx/layers/opengl/GrallocTextureClient.cpp
+++ b/gfx/layers/opengl/GrallocTextureClient.cpp
@@ -7,17 +7,16 @@
 
 #include "mozilla/gfx/2D.h"
 #include "mozilla/layers/AsyncTransactionTracker.h" // for AsyncTransactionTracker
 #include "mozilla/layers/GrallocTextureClient.h"
 #include "mozilla/layers/CompositableForwarder.h"
 #include "mozilla/layers/ISurfaceAllocator.h"
 #include "mozilla/layers/ShadowLayerUtilsGralloc.h"
 #include "gfx2DGlue.h"
-#include "SharedSurfaceGralloc.h"
 
 namespace mozilla {
 namespace layers {
 
 using namespace mozilla::gfx;
 using namespace android;
 
 GrallocTextureClientOGL::GrallocTextureClientOGL(MaybeMagicGrallocBufferHandle buffer,
@@ -107,18 +106,18 @@ GrallocTextureClientOGL::WaitForBufferOw
     mRemoveFromCompositableTracker = nullptr;
   }
 
 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
    if (mReleaseFenceHandle.IsValid()) {
      android::sp<Fence> fence = mReleaseFenceHandle.mFence;
 #if ANDROID_VERSION == 17
      fence->waitForever(1000, "GrallocTextureClientOGL::Lock");
-     // 1000 is what Android uses. It is a warning timeout in ms.
-     // This timeout was removed in ANDROID_VERSION 18.
+     // 1000 is what Android uses. It is warning timeout ms.
+     // This timeous is removed since ANDROID_VERSION 18. 
 #else
      fence->waitForever("GrallocTextureClientOGL::Lock");
 #endif
      mReleaseFenceHandle = FenceHandle();
    }
 #endif
 }
 
@@ -342,35 +341,12 @@ GrallocTextureClientOGL::Allocate(uint32
 size_t
 GrallocTextureClientOGL::GetBufferSize() const
 {
   // see Bug 908196
   MOZ_CRASH("This method should never be called.");
   return 0;
 }
 
-/*static*/ TemporaryRef<TextureClient>
-GrallocTextureClientOGL::FromSharedSurface(gl::SharedSurface* abstractSurf,
-                                           TextureFlags flags)
-{
-  auto surf = gl::SharedSurface_Gralloc::Cast(abstractSurf);
-
-  RefPtr<TextureClient> ret = surf->GetTextureClient();
-
-  TextureFlags mask = TextureFlags::NEEDS_Y_FLIP |
-                      TextureFlags::RB_SWAPPED |
-                      TextureFlags::NON_PREMULTIPLIED;
-  TextureFlags required = flags & mask;
-  TextureFlags present = ret->GetFlags() & mask;
-
-  if (present != required) {
-    printf_stderr("Present flags: 0x%x. Required: 0x%x.\n",
-                  (uint32_t)present,
-                  (uint32_t)required);
-    MOZ_CRASH("Flag requirement mismatch.");
-  }
-  return ret.forget();
-}
-
 } // namesapace layers
 } // namesapace mozilla
 
 #endif // MOZ_WIDGET_GONK
--- a/gfx/layers/opengl/GrallocTextureClient.h
+++ b/gfx/layers/opengl/GrallocTextureClient.h
@@ -113,19 +113,16 @@ public:
   {
     return mMediaBuffer;
   }
 
   virtual TemporaryRef<TextureClient>
   CreateSimilar(TextureFlags aFlags = TextureFlags::DEFAULT,
                 TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const MOZ_OVERRIDE;
 
-  static TemporaryRef<TextureClient> FromSharedSurface(gl::SharedSurface* surf,
-                                                       TextureFlags flags);
-
 protected:
   /**
    * Unfortunately, until bug 879681 is fixed we need to use a GrallocBufferActor.
    */
   MaybeMagicGrallocBufferHandle mGrallocHandle;
 
   RefPtr<AsyncTransactionTracker> mRemoveFromCompositableTracker;
 
--- a/gfx/layers/opengl/TextureClientOGL.cpp
+++ b/gfx/layers/opengl/TextureClientOGL.cpp
@@ -1,14 +1,15 @@
 /* -*- Mode: C++; tab-width: 20; 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 "GLContext.h"                  // for GLContext, etc
+#include "SurfaceStream.h"
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
 #include "mozilla/layers/ISurfaceAllocator.h"
 #include "mozilla/layers/TextureClientOGL.h"
 #include "nsSize.h"                     // for nsIntSize
 
 using namespace mozilla::gl;
 
 namespace mozilla {
@@ -25,25 +26,25 @@ EGLImageTextureClient::EGLImageTextureCl
                                              bool aInverted)
   : TextureClient(aFlags)
   , mImage(aImage)
   , mSize(aSize)
   , mIsLocked(false)
 {
   MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default,
              "Can't pass an `EGLImage` between processes.");
-
+  
   // Our data is always owned externally.
   AddFlags(TextureFlags::DEALLOCATE_CLIENT);
-
+  
   if (aInverted) {
     AddFlags(TextureFlags::NEEDS_Y_FLIP);
   }
 }
-
+  
 EGLImageTextureClient::~EGLImageTextureClient()
 {
   // Our data is always owned externally.
 }
 
 bool
 EGLImageTextureClient::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
 {
@@ -59,24 +60,24 @@ EGLImageTextureClient::Lock(OpenMode mod
   {
     MOZ_ASSERT(!mIsLocked);
     if (!IsValid() || !IsAllocated()) {
       return false;
     }
     mIsLocked = true;
     return true;
   }
-
+  
 void
 EGLImageTextureClient::Unlock()
 {
   MOZ_ASSERT(mIsLocked);
   mIsLocked = false;
 }
-
+  
 ////////////////////////////////////////////////////////////////////////
 // SurfaceTextureClient
 
 #ifdef MOZ_WIDGET_ANDROID
 
 SurfaceTextureClient::SurfaceTextureClient(TextureFlags aFlags,
                                            nsSurfaceTexture* aSurfTex,
                                            gfx::IntSize aSize,
@@ -91,17 +92,17 @@ SurfaceTextureClient::SurfaceTextureClie
 
   // Our data is always owned externally.
   AddFlags(TextureFlags::DEALLOCATE_CLIENT);
 
   if (aInverted) {
     AddFlags(TextureFlags::NEEDS_Y_FLIP);
   }
 }
-
+  
 SurfaceTextureClient::~SurfaceTextureClient()
 {
   // Our data is always owned externally.
 }
 
 bool
 SurfaceTextureClient::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
 {
--- a/gfx/layers/opengl/TextureClientOGL.h
+++ b/gfx/layers/opengl/TextureClientOGL.h
@@ -11,16 +11,22 @@
 #include "mozilla/Attributes.h"         // for MOZ_OVERRIDE
 #include "mozilla/gfx/Point.h"          // for IntSize
 #include "mozilla/layers/CompositorTypes.h"
 #include "mozilla/layers/LayersSurfaces.h"  // for SurfaceDescriptor
 #include "mozilla/layers/TextureClient.h"  // for TextureClient, etc
 #include "nsSurfaceTexture.h"
 
 namespace mozilla {
+namespace gl {
+class SurfaceStream;
+}
+}
+
+namespace mozilla {
 namespace layers {
 
 class CompositableForwarder;
 
 class EGLImageTextureClient : public TextureClient
 {
 public:
   EGLImageTextureClient(TextureFlags aFlags,
--- a/gfx/layers/opengl/TextureHostOGL.h
+++ b/gfx/layers/opengl/TextureHostOGL.h
@@ -43,16 +43,20 @@ struct nsIntPoint;
 struct nsIntRect;
 struct nsIntSize;
 
 namespace mozilla {
 namespace gfx {
 class DataSourceSurface;
 }
 
+namespace gl {
+class SurfaceStream;
+}
+
 namespace layers {
 
 class Compositor;
 class CompositorOGL;
 class TextureImageTextureSourceOGL;
 class TextureSharedDataGonkOGL;
 
 /**