b=843599; use gralloc buffers for WebGL streaming on B2G; r=nical,jgilbert,jrmuizel
authorVladimir Vukicevic <vladimir@pobox.com>
Mon, 27 May 2013 10:12:13 -0400
changeset 134461 a33154335e3786c0f4914ea0d99f3471b826d6c8
parent 134460 25ea966531cafbae9fa719d5d0618dee43557f6f
child 134462 f00dba4fef632ebf7e65cbac7775afd5024cead8
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
reviewersnical, jgilbert, jrmuizel
bugs843599
milestone24.0a1
b=843599; use gralloc buffers for WebGL streaming on B2G; r=nical,jgilbert,jrmuizel
content/canvas/src/WebGLContext.cpp
content/media/omx/OmxDecoder.cpp
content/media/omx/OmxDecoder.h
gfx/gl/GLScreenBuffer.cpp
gfx/gl/Makefile.in
gfx/gl/SharedSurfaceGralloc.cpp
gfx/gl/SharedSurfaceGralloc.h
gfx/gl/SurfaceTypes.h
gfx/gl/moz.build
gfx/layers/CompositorTypes.h
gfx/layers/client/CanvasClient.cpp
gfx/layers/client/ClientCanvasLayer.cpp
gfx/layers/client/ClientCanvasLayer.h
gfx/layers/composite/TextureHost.cpp
gfx/layers/ipc/ISurfaceAllocator.h
gfx/layers/ipc/ImageBridgeChild.cpp
gfx/layers/ipc/ImageBridgeChild.h
gfx/layers/ipc/LayerTransactionChild.cpp
gfx/layers/ipc/LayerTransactionChild.h
gfx/layers/ipc/LayerTransactionParent.cpp
gfx/layers/ipc/LayerTransactionParent.h
gfx/layers/ipc/LayersSurfaces.ipdlh
gfx/layers/ipc/PLayerTransaction.ipdl
gfx/layers/ipc/ShadowLayerUtilsGralloc.cpp
gfx/layers/ipc/ShadowLayerUtilsGralloc.h
gfx/layers/ipc/ShadowLayers.cpp
gfx/layers/ipc/ShadowLayers.h
gfx/layers/opengl/TextureHostOGL.cpp
modules/libpref/src/init/all.js
--- a/content/canvas/src/WebGLContext.cpp
+++ b/content/canvas/src/WebGLContext.cpp
@@ -11,16 +11,17 @@
 #include "AccessCheck.h"
 #include "nsIConsoleService.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIClassInfoImpl.h"
 #include "nsContentUtils.h"
 #include "nsIXPConnect.h"
 #include "nsError.h"
 #include "nsIGfxInfo.h"
+#include "nsIWidget.h"
 
 #include "nsIPropertyBag.h"
 #include "nsIVariant.h"
 
 #include "imgIEncoder.h"
 
 #include "gfxContext.h"
 #include "gfxPattern.h"
@@ -44,16 +45,20 @@
 #include "nsIObserverService.h"
 #include "mozilla/Services.h"
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/ProcessPriorityManager.h"
 
 #include "Layers.h"
 
+#ifdef MOZ_WIDGET_GONK
+#include "mozilla/layers/ShadowLayers.h"
+#endif
+
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::gfx;
 using namespace mozilla::gl;
 using namespace mozilla::layers;
 
 NS_IMETHODIMP
 WebGLMemoryPressureObserver::Observe(nsISupports* aSubject,
@@ -458,16 +463,30 @@ WebGLContext::SetDimensions(int32_t widt
 
     // we should really have this behind a
     // |gfxPlatform::GetPlatform()->GetScreenDepth() == 16| check, but
     // for now it's just behind a pref for testing/evaluation.
     caps.bpp16 = prefer16bit;
 
     caps.preserve = mOptions.preserveDrawingBuffer;
 
+#ifdef MOZ_WIDGET_GONK
+    nsIWidget *docWidget = nsContentUtils::WidgetForDocument(mCanvasElement->OwnerDoc());
+    if (docWidget) {
+        layers::LayerManager *layerManager = docWidget->GetLayerManager();
+        if (layerManager) {
+            // XXX we really want "AsSurfaceAllocator" here for generality
+            layers::ShadowLayerForwarder *forwarder = layerManager->AsShadowForwarder();
+            if (forwarder) {
+                caps.surfaceAllocator = static_cast<layers::ISurfaceAllocator*>(forwarder);
+            }
+        }
+    }
+#endif
+
     bool forceMSAA =
         Preferences::GetBool("webgl.msaa-force", false);
 
     int32_t status;
     nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
     if (mOptions.antialias &&
         gfxInfo &&
         NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_WEBGL_MSAA, &status))) {
--- a/content/media/omx/OmxDecoder.cpp
+++ b/content/media/omx/OmxDecoder.cpp
@@ -34,18 +34,18 @@ PRLogModuleInfo *gOmxDecoderLog;
 using namespace MPAPI;
 using namespace mozilla;
 
 namespace mozilla {
 namespace layers {
 
 VideoGraphicBuffer::VideoGraphicBuffer(const android::wp<android::OmxDecoder> aOmxDecoder,
                                        android::MediaBuffer *aBuffer,
-                                       SurfaceDescriptor *aDescriptor)
-  : GraphicBufferLocked(*aDescriptor),
+                                       SurfaceDescriptor& aDescriptor)
+  : GraphicBufferLocked(aDescriptor),
     mMediaBuffer(aBuffer),
     mOmxDecoder(aOmxDecoder)
 {
   mMediaBuffer->add_ref();
 }
 
 VideoGraphicBuffer::~VideoGraphicBuffer()
 {
@@ -587,21 +587,21 @@ bool OmxDecoder::ReadVideo(VideoFrame *a
     if ((mVideoBuffer->graphicBuffer().get())) {
       descriptor = mNativeWindow->getSurfaceDescriptorFromBuffer(mVideoBuffer->graphicBuffer().get());
     }
 
     if (descriptor) {
       // Change the descriptor's size to video's size. There are cases that
       // GraphicBuffer's size and actual video size is different.
       // See Bug 850566.
-      const mozilla::layers::SurfaceDescriptorGralloc& grallocDesc = descriptor->get_SurfaceDescriptorGralloc();
-      mozilla::layers::SurfaceDescriptor newDescriptor = mozilla::layers::SurfaceDescriptorGralloc(grallocDesc.bufferParent(),
-                                                               grallocDesc.bufferChild(), nsIntSize(mVideoWidth, mVideoHeight), grallocDesc.external());
+      mozilla::layers::SurfaceDescriptorGralloc newDescriptor = descriptor->get_SurfaceDescriptorGralloc();
+      newDescriptor.size() = nsIntSize(mVideoWidth, mVideoHeight);
 
-      aFrame->mGraphicBuffer = new mozilla::layers::VideoGraphicBuffer(this, mVideoBuffer, &newDescriptor);
+      mozilla::layers::SurfaceDescriptor descWrapper(newDescriptor);
+      aFrame->mGraphicBuffer = new mozilla::layers::VideoGraphicBuffer(this, mVideoBuffer, descWrapper);
       aFrame->mRotation = mVideoRotation;
       aFrame->mTimeUs = timeUs;
       aFrame->mKeyFrame = keyFrame;
       aFrame->Y.mWidth = mVideoWidth;
       aFrame->Y.mHeight = mVideoHeight;
     } else {
       char *data = static_cast<char *>(mVideoBuffer->data()) + mVideoBuffer->range_offset();
       size_t length = mVideoBuffer->range_length();
--- a/content/media/omx/OmxDecoder.h
+++ b/content/media/omx/OmxDecoder.h
@@ -22,17 +22,17 @@ namespace layers {
 
 class VideoGraphicBuffer : public GraphicBufferLocked {
   // XXX change this to an actual smart pointer at some point
   android::MediaBuffer *mMediaBuffer;
   android::wp<android::OmxDecoder> mOmxDecoder;
   public:
     VideoGraphicBuffer(const android::wp<android::OmxDecoder> aOmxDecoder,
                        android::MediaBuffer *aBuffer,
-                       SurfaceDescriptor *aDescriptor);
+                       SurfaceDescriptor& aDescriptor);
     ~VideoGraphicBuffer();
     void Unlock();
 };
 
 }
 }
 
 namespace android {
--- a/gfx/gl/GLScreenBuffer.cpp
+++ b/gfx/gl/GLScreenBuffer.cpp
@@ -5,16 +5,20 @@
 
 #include "GLScreenBuffer.h"
 
 #include <cstring>
 #include "gfxImageSurface.h"
 #include "GLContext.h"
 #include "SharedSurfaceGL.h"
 #include "SurfaceStream.h"
+#ifdef MOZ_WIDGET_GONK
+#include "SharedSurfaceGralloc.h"
+#include "nsXULAppAPI.h"
+#endif
 
 using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace gl {
 
 GLScreenBuffer*
 GLScreenBuffer::Create(GLContext* gl,
@@ -22,17 +26,30 @@ GLScreenBuffer::Create(GLContext* gl,
                      const SurfaceCaps& caps)
 {
     if (caps.antialias &&
         !gl->SupportsFramebufferMultisample())
     {
         return nullptr;
     }
 
-    SurfaceFactory_GL* factory = new SurfaceFactory_Basic(gl, caps);
+    SurfaceFactory_GL* factory = nullptr;
+
+#ifdef MOZ_WIDGET_GONK
+    /* On B2G, we want a Gralloc factory, and we want one right at the start */
+    if (!factory &&
+        XRE_GetProcessType() != GeckoProcessType_Default)
+    {
+        factory = new SurfaceFactory_Gralloc(gl, caps);
+    }
+#endif
+
+    if (!factory)
+        factory = new SurfaceFactory_Basic(gl, caps);
+
     SurfaceStream* stream = SurfaceStream::CreateForType(
         SurfaceStream::ChooseGLStreamType(SurfaceStream::MainThread,
                                           caps.preserve),
         nullptr);
 
     return new GLScreenBuffer(gl, caps, factory, stream);
 }
 
--- a/gfx/gl/Makefile.in
+++ b/gfx/gl/Makefile.in
@@ -74,12 +74,14 @@ CMMSRCS += GLContextProvider$(GL_PROVIDE
 endif
 
 ifdef MOZ_ANDROID_OMTC
 DEFINES += -DMOZ_ANDROID_OMTC
 endif
 
 include $(topsrcdir)/config/rules.mk
 
+include $(topsrcdir)/ipc/chromium/chromium-config.mk
+
 DEFINES := $(filter-out -DUNICODE,$(DEFINES))
 
 CXXFLAGS += $(MOZ_CAIRO_CFLAGS) $(MOZ_PIXMAN_CFLAGS) $(TK_CFLAGS)
 CFLAGS   += $(MOZ_CAIRO_CFLAGS) $(MOZ_PIXMAN_CFLAGS) $(TK_CFLAGS)
new file mode 100644
--- /dev/null
+++ b/gfx/gl/SharedSurfaceGralloc.cpp
@@ -0,0 +1,167 @@
+/* -*- 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 "mozilla/Preferences.h"
+
+#include "SharedSurfaceGralloc.h"
+
+#include "GLContext.h"
+#include "SharedSurfaceGL.h"
+#include "SurfaceFactory.h"
+#include "GLLibraryEGL.h"
+#include "mozilla/layers/ShadowLayers.h"
+
+#include "ui/GraphicBuffer.h"
+#include "../layers/ipc/ShadowLayers.h"
+
+#define DEBUG_GRALLOC
+#ifdef DEBUG_GRALLOC
+#define DEBUG_PRINT(...) do { printf_stderr(__VA_ARGS__); } while (0)
+#else
+#define DEBUG_PRINT(...) do { } while (0)
+#endif
+
+using namespace mozilla;
+using namespace mozilla::gfx;
+using namespace gl;
+using namespace layers;
+using namespace android;
+
+static bool sForceReadPixelsToFence = false;
+
+
+SurfaceFactory_Gralloc::SurfaceFactory_Gralloc(GLContext* prodGL,
+                                               const SurfaceCaps& caps,
+                                               layers::ISurfaceAllocator* allocator)
+    : SurfaceFactory_GL(prodGL, SharedSurfaceType::Gralloc, caps)
+{
+    if (caps.surfaceAllocator) {
+        allocator = caps.surfaceAllocator;
+    }
+
+    MOZ_ASSERT(allocator);
+
+    mAllocator = allocator;
+}
+
+SharedSurface_Gralloc*
+SharedSurface_Gralloc::Create(GLContext* prodGL,
+                              const GLFormats& formats,
+                              const gfxIntSize& size,
+                              bool hasAlpha,
+                              ISurfaceAllocator* allocator)
+{
+    static bool runOnce = true;
+    if (runOnce) {
+        sForceReadPixelsToFence = false;
+        mozilla::Preferences::AddBoolVarCache(&sForceReadPixelsToFence,
+                                              "gfx.gralloc.fence-with-readpixels");
+        runOnce = false;
+    }
+
+    GLLibraryEGL* egl = prodGL->GetLibraryEGL();
+    MOZ_ASSERT(egl);
+
+    DEBUG_PRINT("SharedSurface_Gralloc::Create -------\n");
+
+    if (!HasExtensions(egl, prodGL))
+        return nullptr;
+
+    SurfaceDescriptor baseDesc;
+    SurfaceDescriptorGralloc desc;
+
+    gfxASurface::gfxContentType type = hasAlpha ? gfxASurface::CONTENT_COLOR_ALPHA
+                                                : gfxASurface::CONTENT_COLOR;
+    if (!allocator->AllocSurfaceDescriptorWithCaps(size, type, USING_GL_RENDERING_ONLY, &baseDesc))
+        return false;
+
+    if (baseDesc.type() != SurfaceDescriptor::TSurfaceDescriptorGralloc) {
+        allocator->DestroySharedSurface(&baseDesc);
+        return false;
+    }
+
+    desc = baseDesc.get_SurfaceDescriptorGralloc();
+
+    sp<GraphicBuffer> buffer = GrallocBufferActor::GetFrom(desc);
+
+    EGLDisplay display = egl->Display();
+    EGLClientBuffer clientBuffer = buffer->getNativeBuffer();
+    EGLint attrs[] = {
+        LOCAL_EGL_NONE, LOCAL_EGL_NONE
+    };
+    EGLImage image = egl->fCreateImage(display,
+                                       EGL_NO_CONTEXT,
+                                       LOCAL_EGL_NATIVE_BUFFER_ANDROID,
+                                       clientBuffer, attrs);
+    if (!image) {
+        allocator->DestroySharedSurface(&baseDesc);
+        return nullptr;
+    }
+
+    prodGL->MakeCurrent();
+    GLuint prodTex = 0;
+    prodGL->fGenTextures(1, &prodTex);
+    ScopedBindTexture autoTex(prodGL, prodTex);
+    prodGL->fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_2D, image);
+
+    egl->fDestroyImage(display, image);
+
+    SharedSurface_Gralloc *surf = new SharedSurface_Gralloc(prodGL, size, hasAlpha, egl, allocator, desc, prodTex);
+
+    DEBUG_PRINT("SharedSurface_Gralloc::Create: success -- surface %p, GraphicBuffer %p.\n", surf, buffer.get());
+
+    return surf;
+}
+
+
+bool
+SharedSurface_Gralloc::HasExtensions(GLLibraryEGL* egl, GLContext* gl)
+{
+    return egl->HasKHRImageBase() &&
+           gl->IsExtensionSupported(GLContext::OES_EGL_image);
+}
+
+SharedSurface_Gralloc::~SharedSurface_Gralloc()
+{
+
+    DEBUG_PRINT("[SharedSurface_Gralloc %p] destroyed\n", this);
+
+    mGL->MakeCurrent();
+    mGL->fDeleteTextures(1, (GLuint*)&mProdTex);
+
+    SurfaceDescriptor desc(mDesc);
+    mAllocator->DestroySharedSurface(&desc);
+}
+
+void
+SharedSurface_Gralloc::Fence()
+{
+    // We should be able to rely on genlock write locks/read locks.
+    // But they're broken on some configs, and even a glFinish doesn't
+    // work.  glReadPixels seems to, though.
+    if (sForceReadPixelsToFence) {
+        mGL->MakeCurrent();
+        // read a 1x1 pixel
+        unsigned char pixels[4];
+        mGL->fReadPixels(0, 0, 1, 1, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, &pixels[0]);
+    }
+}
+
+bool
+SharedSurface_Gralloc::WaitSync()
+{
+    return true;
+}
+
+void
+SharedSurface_Gralloc::LockProdImpl()
+{
+}
+
+void
+SharedSurface_Gralloc::UnlockProdImpl()
+{
+}
+
new file mode 100644
--- /dev/null
+++ b/gfx/gl/SharedSurfaceGralloc.h
@@ -0,0 +1,111 @@
+/* -*- 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 "SharedSurfaceGL.h"
+#include "mozilla/layers/LayersSurfaces.h"
+
+namespace mozilla {
+namespace layers {
+class ISurfaceAllocator;
+class SurfaceDescriptorGralloc;
+}
+
+namespace gl {
+class GLContext;
+class GLLibraryEGL;
+
+class SharedSurface_Gralloc
+    : public SharedSurface_GL
+{
+public:
+    static SharedSurface_Gralloc* Create(GLContext* prodGL,
+                                         const GLFormats& formats,
+                                         const gfxIntSize& size,
+                                         bool hasAlpha,
+                                         layers::ISurfaceAllocator* allocator);
+
+    static SharedSurface_Gralloc* Cast(SharedSurface* surf) {
+        MOZ_ASSERT(surf->Type() == SharedSurfaceType::Gralloc);
+
+        return (SharedSurface_Gralloc*)surf;
+    }
+
+protected:
+    GLLibraryEGL* const mEGL;
+    layers::ISurfaceAllocator* const mAllocator;
+    // We keep the SurfaceDescriptor around, because we'll end up
+    // using it often and it's handy to do so.  The actual
+    // GraphicBuffer is kept alive by the sp<GraphicBuffer> in
+    // GrallocBufferActor; the actor will stay alive until we
+    // explicitly destroy this descriptor (and thus deallocate the
+    // actor) it in the destructor of this class.  This is okay to do
+    // on the client, but is very bad to do on the server (because on
+    // the client, the actor has no chance of going away unless the
+    // whole app died).
+    layers::SurfaceDescriptorGralloc mDesc;
+    const GLuint mProdTex;
+
+    SharedSurface_Gralloc(GLContext* prodGL,
+                          const gfxIntSize& size,
+                          bool hasAlpha,
+                          GLLibraryEGL* egl,
+                          layers::ISurfaceAllocator* allocator,
+                          layers::SurfaceDescriptorGralloc& desc,
+                          GLuint prodTex)
+        : SharedSurface_GL(SharedSurfaceType::Gralloc,
+                           AttachmentType::GLTexture,
+                           prodGL,
+                           size,
+                           hasAlpha)
+        , mEGL(egl)
+        , mAllocator(allocator)
+        , mDesc(desc)
+        , mProdTex(prodTex)
+    {}
+
+    static bool HasExtensions(GLLibraryEGL* egl, GLContext* gl);
+
+public:
+    virtual ~SharedSurface_Gralloc();
+
+    virtual void Fence();
+    virtual bool WaitSync();
+
+    virtual void LockProdImpl();
+    virtual void UnlockProdImpl();
+
+    virtual GLuint Texture() const {
+        return mProdTex;
+    }
+
+    layers::SurfaceDescriptorGralloc& GetDescriptor() {
+        return mDesc;
+    }
+};
+
+class SurfaceFactory_Gralloc
+    : public SurfaceFactory_GL
+{
+protected:
+    layers::ISurfaceAllocator* mAllocator;
+
+public:
+    SurfaceFactory_Gralloc(GLContext* prodGL,
+                           const SurfaceCaps& caps,
+                           layers::ISurfaceAllocator* allocator = nullptr);
+
+    virtual SharedSurface* CreateShared(const gfxIntSize& size) {
+        bool hasAlpha = mReadCaps.alpha;
+        return SharedSurface_Gralloc::Create(mGL, mFormats, size, hasAlpha, mAllocator);
+    }
+};
+
+} /* namespace gl */
+} /* namespace mozilla */
+
+#endif /* SHARED_SURFACE_GRALLOC_H_ */
--- a/gfx/gl/SurfaceTypes.h
+++ b/gfx/gl/SurfaceTypes.h
@@ -7,29 +7,37 @@
 #define SURFACE_TYPES_H_
 
 #include "mozilla/TypedEnum.h"
 #include "mozilla/StandardInteger.h"
 
 #include <cstring>
 
 namespace mozilla {
+namespace layers {
+class ISurfaceAllocator;
+}
+
 namespace gfx {
 
 typedef uintptr_t SurfaceStreamHandle;
 
 struct SurfaceCaps
 {
     bool any;
     bool color, alpha;
     bool bpp16;
     bool depth, stencil;
     bool antialias;
     bool preserve;
 
+    // The surface allocator that we want to create this
+    // for.  May be null.
+    layers::ISurfaceAllocator* surfaceAllocator;
+
     SurfaceCaps() {
         Clear();
     }
 
     void Clear() {
         std::memset(this, 0, sizeof(SurfaceCaps));
     }
 
--- a/gfx/gl/moz.build
+++ b/gfx/gl/moz.build
@@ -70,16 +70,20 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'wind
         'SharedSurfaceANGLE.cpp',
     ]
 if CONFIG['MOZ_ENABLE_SKIA_GPU']:
     EXPORTS += ['GLContextSkia.h']
     CPP_SOURCES += [
         'GLContextSkia.cpp',
     ]
 
+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
+    CPP_SOURCES += ['SharedSurfaceGralloc.cpp']
+    EXPORTS += ['SharedSurfaceGralloc.h']
+
 if gl_provider == 'CGL':
     # TODO: CMMSRCS
     pass
 else:
     CPP_SOURCES += [
         'GLContextProvider%s.cpp' % gl_provider,
     ]
 
--- a/gfx/layers/CompositorTypes.h
+++ b/gfx/layers/CompositorTypes.h
@@ -31,16 +31,19 @@ const TextureFlags ForceSingleTile    = 
 // Allow using 'repeat' mode for wrapping.
 const TextureFlags AllowRepeat        = 0x8;
 // The texture represents a tile which is newly created.
 const TextureFlags NewTile            = 0x10;
 // The host is responsible for tidying up any shared resources.
 const TextureFlags HostRelease        = 0x20;
 // The texture is part of a component-alpha pair
 const TextureFlags ComponentAlpha     = 0x40;
+// The shared resources are owned by client
+const TextureFlags OwnByClient        = 0x80;
+
 
 /**
  * The kind of memory held by the texture client/host pair. This will
  * determine how the texture client is drawn into and how the memory
  * is shared between client and host.
  */
 enum TextureClientType
 {
--- a/gfx/layers/client/CanvasClient.cpp
+++ b/gfx/layers/client/CanvasClient.cpp
@@ -6,16 +6,20 @@
 #include "mozilla/layers/CanvasClient.h"
 #include "mozilla/layers/TextureClient.h"
 #include "ClientCanvasLayer.h"
 #include "mozilla/layers/ShadowLayers.h"
 #include "SharedTextureImage.h"
 #include "nsXULAppAPI.h"
 #include "GLContext.h"
 #include "SurfaceStream.h"
+#include "SharedSurface.h"
+#ifdef MOZ_WIDGET_GONK
+#include "SharedSurfaceGralloc.h"
+#endif
 
 using namespace mozilla::gl;
 
 namespace mozilla {
 namespace layers {
 
 /* static */ TemporaryRef<CanvasClient>
 CanvasClient::CreateCanvasClient(CompositableType aCompositableHostType,
@@ -90,17 +94,41 @@ CanvasClientWebGL::Update(gfx::IntSize a
   }
 
   NS_ASSERTION(aLayer->mGLContext, "CanvasClientWebGL should only be used with GL canvases");
 
   // the content type won't be used
   mTextureClient->EnsureAllocated(aSize, gfxASurface::CONTENT_COLOR);
 
   GLScreenBuffer* screen = aLayer->mGLContext->Screen();
-  SurfaceStreamHandle handle = screen->Stream()->GetShareHandle();
+  SurfaceStream* stream = screen->Stream();
+
+  bool isCrossProcess = !(XRE_GetProcessType() == GeckoProcessType_Default);
+  if (isCrossProcess) {
+    // swap staging -> consumer so we can send it to the compositor
+    SharedSurface* surf = stream->SwapConsumer();
+    if (!surf) {
+      printf_stderr("surf is null post-SwapConsumer!\n");
+      return;
+    }
 
-  mTextureClient->SetDescriptor(SurfaceStreamDescriptor(handle, false));
+#ifdef MOZ_WIDGET_GONK
+    if (surf->Type() != SharedSurfaceType::Gralloc) {
+      printf_stderr("Unexpected non-Gralloc SharedSurface in IPC path!");
+      return;
+    }
+
+    SharedSurface_Gralloc* grallocSurf = SharedSurface_Gralloc::Cast(surf);
+    mTextureClient->SetDescriptor(grallocSurf->GetDescriptor());
+#else
+    printf_stderr("isCrossProcess, but not MOZ_WIDGET_GONK! Someone needs to write some code!");
+    MOZ_ASSERT(false);
+#endif
+  } else {
+    SurfaceStreamHandle handle = stream->GetShareHandle();
+    mTextureClient->SetDescriptor(SurfaceStreamDescriptor(handle, false));
+  }
 
   aLayer->Painted();
 }
 
 }
 }
--- a/gfx/layers/client/ClientCanvasLayer.cpp
+++ b/gfx/layers/client/ClientCanvasLayer.cpp
@@ -3,16 +3,19 @@
  * 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 "ClientCanvasLayer.h"
 #include "gfxPlatform.h"
 #include "SurfaceStream.h"
 #include "SharedSurfaceGL.h"
 #include "SharedSurfaceEGL.h"
+#ifdef MOZ_WIDGET_GONK
+#include "SharedSurfaceGralloc.h"
+#endif
 
 using namespace mozilla::gl;
 
 namespace mozilla {
 namespace layers {
 
 void
 ClientCanvasLayer::Initialize(const Data& aData)
@@ -32,17 +35,22 @@ ClientCanvasLayer::Initialize(const Data
         if (mGLContext->GetEGLContext()) {
           bool isCrossProcess = !(XRE_GetProcessType() == GeckoProcessType_Default);
 
           if (!isCrossProcess) {
             // [Basic/OGL Layers, OMTC] WebGL layer init.
             factory = SurfaceFactory_EGLImage::Create(mGLContext, screen->Caps());
           } else {
             // [Basic/OGL Layers, OOPC] WebGL layer init. (Out Of Process Compositing)
-            // Fall back to readback.
+#ifdef MOZ_WIDGET_GONK
+            factory = new SurfaceFactory_Gralloc(mGLContext, screen->Caps(), ClientManager());
+#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...
           factory = new SurfaceFactory_GLTexture(mGLContext, nullptr, screen->Caps());
         }
       }
     }
@@ -65,16 +73,25 @@ ClientCanvasLayer::RenderLayer()
     ToClientLayer(GetMaskLayer())->RenderLayer();
   }
   
   if (!mCanvasClient) {
     TextureFlags flags = 0;
     if (mNeedsYFlip) {
       flags |= NeedsYFlip;
     }
+
+    bool isCrossProcess = !(XRE_GetProcessType() == GeckoProcessType_Default);
+    //Append OwnByClient flag for streaming buffer under OOPC case
+    if (isCrossProcess && mGLContext) {
+      GLScreenBuffer* screen = mGLContext->Screen();
+      if (screen && screen->Stream()) {
+        flags |= OwnByClient;
+      }
+    }
     mCanvasClient = CanvasClient::CreateCanvasClient(GetCompositableClientType(),
                                                      ClientManager(), flags);
     if (!mCanvasClient) {
       return;
     }
     if (HasShadow()) {
       mCanvasClient->Connect();
       ClientManager()->Attach(mCanvasClient, this);
--- a/gfx/layers/client/ClientCanvasLayer.h
+++ b/gfx/layers/client/ClientCanvasLayer.h
@@ -68,17 +68,17 @@ public:
 protected:
   ClientLayerManager* ClientManager()
   {
     return static_cast<ClientLayerManager*>(mManager);
   }
   
   CompositableType GetCompositableClientType()
   {
-    if (mGLContext && XRE_GetProcessType() == GeckoProcessType_Default) {
+    if (mGLContext) {
       return BUFFER_IMAGE_BUFFERED;
     }
     return BUFFER_IMAGE_SINGLE;
   }
 
   RefPtr<CanvasClient> mCanvasClient;
 
   friend class CanvasClient2D;
--- a/gfx/layers/composite/TextureHost.cpp
+++ b/gfx/layers/composite/TextureHost.cpp
@@ -72,20 +72,22 @@ TextureHost::TextureHost()
   , mDeAllocator(nullptr)
 {
   MOZ_COUNT_CTOR(TextureHost);
 }
 
 TextureHost::~TextureHost()
 {
   if (mBuffer) {
-    if (mDeAllocator) {
-      mDeAllocator->DestroySharedSurface(mBuffer);
-    } else {
-      MOZ_ASSERT(mBuffer->type() == SurfaceDescriptor::Tnull_t);
+    if (!(mFlags & OwnByClient)) {
+      if (mDeAllocator) {
+        mDeAllocator->DestroySharedSurface(mBuffer);
+      } else {
+        MOZ_ASSERT(mBuffer->type() == SurfaceDescriptor::Tnull_t);
+      }
     }
     delete mBuffer;
   }
   MOZ_COUNT_DTOR(TextureHost);
 }
 
 void
 TextureHost::Update(const SurfaceDescriptor& aImage,
--- a/gfx/layers/ipc/ISurfaceAllocator.h
+++ b/gfx/layers/ipc/ISurfaceAllocator.h
@@ -39,17 +39,21 @@ class PGrallocBufferChild;
 class MaybeMagicGrallocBufferHandle;
 
 enum BufferCapabilities {
   DEFAULT_BUFFER_CAPS = 0,
   /**
    * The allocated buffer must be efficiently mappable as a
    * gfxImageSurface.
    */
-  MAP_AS_IMAGE_SURFACE = 1 << 0
+  MAP_AS_IMAGE_SURFACE = 1 << 0,
+  /**
+   * The allocated buffer will be used for GL rendering only
+   */
+  USING_GL_RENDERING_ONLY = 1 << 1
 };
 
 class SurfaceDescriptor;
 
 
 ipc::SharedMemory::SharedMemoryType OptimalShmemType();
 bool IsSurfaceDescriptorValid(const SurfaceDescriptor& aSurface);
 bool IsSurfaceDescriptorOwned(const SurfaceDescriptor& aDescriptor);
@@ -109,18 +113,21 @@ protected:
   // this method is needed for a temporary fix, will be removed after
   // TextureClient/Host rework.
   virtual bool IsOnCompositorSide() const = 0;
   static bool PlatformDestroySharedSurface(SurfaceDescriptor* aSurface);
   virtual bool PlatformAllocSurfaceDescriptor(const gfxIntSize& aSize,
                                               gfxASurface::gfxContentType aContent,
                                               uint32_t aCaps,
                                               SurfaceDescriptor* aBuffer);
+
+  // method that does the actual allocation work
   virtual PGrallocBufferChild* AllocGrallocBuffer(const gfxIntSize& aSize,
-                                                  gfxASurface::gfxContentType aContent,
+                                                  uint32_t aFormat,
+                                                  uint32_t aUsage,
                                                   MaybeMagicGrallocBufferHandle* aHandle)
   {
     return nullptr;
   }
 
   ~ISurfaceAllocator() {}
 };
 
--- a/gfx/layers/ipc/ImageBridgeChild.cpp
+++ b/gfx/layers/ipc/ImageBridgeChild.cpp
@@ -576,17 +576,17 @@ ImageBridgeChild::AllocSurfaceDescriptor
   if (handle.Tnull_t == handle.type()) {
     PGrallocBufferChild::Send__delete__(gc);
     return false;
   }
 
   GrallocBufferActor* gba = static_cast<GrallocBufferActor*>(gc);
   gba->InitFromHandle(handle.get_MagicGrallocBufferHandle());
 
-  *aBuffer = SurfaceDescriptorGralloc(nullptr, gc, aSize, /* external */ false);
+  *aBuffer = SurfaceDescriptorGralloc(nullptr, gc, aSize, /* external */ false, /* swapRB */ false);
   return true;
 #else
   NS_RUNTIMEABORT("No gralloc buffers for you");
   return false;
 #endif
 }
 
 bool
@@ -743,23 +743,24 @@ ImageBridgeChild::DeallocShmem(ipc::Shme
     while (!done) {
       barrier.Wait();
     }
   }
 }
 
 PGrallocBufferChild*
 ImageBridgeChild::AllocGrallocBuffer(const gfxIntSize& aSize,
-                                     gfxASurface::gfxContentType aContent,
+                                     uint32_t aFormat,
+                                     uint32_t aUsage,
                                      MaybeMagicGrallocBufferHandle* aHandle)
 {
 #ifdef MOZ_WIDGET_GONK
   return SendPGrallocBufferConstructor(aSize,
-                                       aContent,
-                                       GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
+                                       aFormat,
+                                       aUsage,
                                        aHandle);
 #else
   NS_RUNTIMEABORT("not implemented");
   return nullptr;
 #endif
 }
 
 } // layers
--- a/gfx/layers/ipc/ImageBridgeChild.h
+++ b/gfx/layers/ipc/ImageBridgeChild.h
@@ -194,17 +194,17 @@ public:
    * Part of the allocation of gralloc SurfaceDescriptor that is
    * executed on the ImageBridgeChild thread after invoking
    * AllocSurfaceDescriptorGralloc.
    *
    * Must be called from the ImageBridgeChild thread.
    */
   bool
   AllocSurfaceDescriptorGrallocNow(const gfxIntSize& aSize,
-                                   const uint32_t& aContent,
+                                   const uint32_t& aFormat,
                                    const uint32_t& aUsage,
                                    SurfaceDescriptor* aBuffer);
 
   /**
    * Deallocate a remotely allocated gralloc buffer.
    */
   bool
   DeallocSurfaceDescriptorGralloc(const SurfaceDescriptor& aBuffer);
@@ -332,17 +332,18 @@ protected:
   ImageBridgeChild();
   bool DispatchAllocShmemInternal(size_t aSize,
                                   SharedMemory::SharedMemoryType aType,
                                   Shmem* aShmem,
                                   bool aUnsafe);
 
   CompositableTransaction* mTxn;
 
+  // ISurfaceAllocator
   virtual PGrallocBufferChild* AllocGrallocBuffer(const gfxIntSize& aSize,
-                                                  gfxASurface::gfxContentType aContent,
+                                                  uint32_t aFormat, uint32_t aUsage,
                                                   MaybeMagicGrallocBufferHandle* aHandle) MOZ_OVERRIDE;
 };
 
 } // layers
 } // mozilla
 
 #endif
--- a/gfx/layers/ipc/LayerTransactionChild.cpp
+++ b/gfx/layers/ipc/LayerTransactionChild.cpp
@@ -19,18 +19,19 @@ LayerTransactionChild::Destroy()
   NS_ABORT_IF_FALSE(0 == ManagedPLayerChild().Length(),
                     "layers should have been cleaned up by now");
   PLayerTransactionChild::Send__delete__(this);
   // WARNING: |this| has gone to the great heap in the sky
 }
 
 PGrallocBufferChild*
 LayerTransactionChild::AllocPGrallocBuffer(const gfxIntSize&,
-                                       const gfxContentType&,
-                                       MaybeMagicGrallocBufferHandle*)
+                                           const uint32_t&,
+                                           const uint32_t&,
+                                           MaybeMagicGrallocBufferHandle*)
 {
 #ifdef MOZ_HAVE_SURFACEDESCRIPTORGRALLOC
   return GrallocBufferActor::Create();
 #else
   NS_RUNTIMEABORT("No gralloc buffers for you");
   return nullptr;
 #endif
 }
--- a/gfx/layers/ipc/LayerTransactionChild.h
+++ b/gfx/layers/ipc/LayerTransactionChild.h
@@ -25,17 +25,18 @@ public:
    * It is expected (checked with an assert) that all shadow layers
    * created by this have already been destroyed and
    * Send__delete__()d by the time this method is called.
    */
   void Destroy();
 
 protected:
   virtual PGrallocBufferChild*
-  AllocPGrallocBuffer(const gfxIntSize&, const gfxContentType&,
+  AllocPGrallocBuffer(const gfxIntSize&,
+                      const uint32_t&, const uint32_t&,
                       MaybeMagicGrallocBufferHandle*) MOZ_OVERRIDE;
   virtual bool
   DeallocPGrallocBuffer(PGrallocBufferChild* actor) MOZ_OVERRIDE;
 
   virtual PLayerChild* AllocPLayer() MOZ_OVERRIDE;
   virtual bool DeallocPLayer(PLayerChild* actor) MOZ_OVERRIDE;
 
   virtual PCompositableChild* AllocPCompositable(const TextureInfo& aInfo) MOZ_OVERRIDE;
--- a/gfx/layers/ipc/LayerTransactionParent.cpp
+++ b/gfx/layers/ipc/LayerTransactionParent.cpp
@@ -511,21 +511,22 @@ LayerTransactionParent::RecvClearCachedR
     // of resources to exactly that subtree, so we specify it here.
     mLayerManager->ClearCachedResources(mRoot);
   }
   return true;
 }
 
 PGrallocBufferParent*
 LayerTransactionParent::AllocPGrallocBuffer(const gfxIntSize& aSize,
-                                            const gfxContentType& aContent,
+                                            const uint32_t& aFormat,
+                                            const uint32_t& aUsage,
                                             MaybeMagicGrallocBufferHandle* aOutHandle)
 {
 #ifdef MOZ_HAVE_SURFACEDESCRIPTORGRALLOC
-  return GrallocBufferActor::Create(aSize, aContent, aOutHandle);
+  return GrallocBufferActor::Create(aSize, aFormat, aUsage, aOutHandle);
 #else
   NS_RUNTIMEABORT("No gralloc buffers for you");
   return nullptr;
 #endif
 }
 
 bool
 LayerTransactionParent::DeallocPGrallocBuffer(PGrallocBufferParent* actor)
--- a/gfx/layers/ipc/LayerTransactionParent.h
+++ b/gfx/layers/ipc/LayerTransactionParent.h
@@ -77,17 +77,18 @@ protected:
 
   virtual bool RecvClearCachedResources() MOZ_OVERRIDE;
   virtual bool RecvGetOpacity(PLayerParent* aParent,
                               float* aOpacity) MOZ_OVERRIDE;
   virtual bool RecvGetTransform(PLayerParent* aParent,
                                 gfx3DMatrix* aTransform) MOZ_OVERRIDE;
 
   virtual PGrallocBufferParent*
-  AllocPGrallocBuffer(const gfxIntSize& aSize, const gfxContentType& aContent,
+  AllocPGrallocBuffer(const gfxIntSize& aSize,
+                      const uint32_t& aFormat, const uint32_t& aUsage,
                       MaybeMagicGrallocBufferHandle* aOutHandle) MOZ_OVERRIDE;
   virtual bool
   DeallocPGrallocBuffer(PGrallocBufferParent* actor) MOZ_OVERRIDE;
 
   virtual PLayerParent* AllocPLayer() MOZ_OVERRIDE;
   virtual bool DeallocPLayer(PLayerParent* actor) MOZ_OVERRIDE;
 
   virtual PCompositableParent* AllocPCompositable(const TextureInfo& aInfo) MOZ_OVERRIDE;
--- a/gfx/layers/ipc/LayersSurfaces.ipdlh
+++ b/gfx/layers/ipc/LayersSurfaces.ipdlh
@@ -57,16 +57,27 @@ struct SurfaceDescriptorGralloc {
   /**
    * We can have one source producing gralloc buffers and sharing them
    * with another source that may also produce its own gralloc buffers.
    * This happens for camera preview buffers sent to video code.  When
    * that happens, the producer can mark the buffer as "external" to
    * prevent its consumer from mistakenly freeing the buffer.
    */
   bool external;
+
+  /**
+   * This gralloc buffer will be treated as if the RB bytes are swapped.
+   * This is useful for rendering using Cairo/Thebes, because there is no
+   * BGRX Android pixel format, and so we have to do byte swapping.
+   *
+   * For example, if the GraphicBuffer has an Android pixel format of
+   * PIXEL_FORMAT_RGBA_8888 and isRBSwapped is true, when it is sampled
+   * (for example, with GL), a BGRA shader should be used.
+   */
+  bool isRBSwapped;
 };
 
 struct SurfaceStreamDescriptor {
   SurfaceStreamHandle handle;
   bool yflip;
 };
 
 struct YCbCrImage {
--- a/gfx/layers/ipc/PLayerTransaction.ipdl
+++ b/gfx/layers/ipc/PLayerTransaction.ipdl
@@ -38,18 +38,40 @@ sync protocol PLayerTransaction {
   manages PCompositable;
   manages PGrallocBuffer;
 
 parent:
   /**
    * Only the parent side has privileges to allocate the buffer.
    * Allocation may fail (pmem is a scarce resource), and if so null_t
    * is returned.
+   *
+   * |format| is an Android PixelFormat (see PixelFormat.h)
+   *
+   * commonly used PixelFormats are:
+   *   PIXEL_FORMAT_RGBA_8888
+   *   PIXEL_FORMAT_RGBX_8888
+   *   PIXEL_FORMAT_BGRA_8888
+   *
+   * Note that SurfaceDescriptorGralloc has a "isRBSwapped" boolean
+   * that can treat the R/B bytes as swapped when they are rendered
+   * to the screen, to help with matching the native pixel format
+   * of other rendering engines.
+   *
+   * |usage| is a USAGE_* mask (see GraphicBuffer.h)
+   *
+   * commonly used USAGE flags are:
+   *   USAGE_SW_READ_OFTEN | USAGE_SW_WRITE_OFTEN | USAGE_HW_TEXTURE
+   *     - used for software rendering to a buffer which the compositor
+   *       treats as a texture
+   *   USAGE_HW_RENDER | USAGE_HW_TEXTURE
+   *     - used for GL rendering to a buffer which the compositor
+   *       treats as a texture
    */
-  sync PGrallocBuffer(gfxIntSize size, gfxContentType content)
+  sync PGrallocBuffer(gfxIntSize size, uint32_t format, uint32_t usage)
     returns (MaybeMagicGrallocBufferHandle handle);
   async PLayer();
   async PCompositable(TextureInfo aTextureInfo);
 
   // The isFirstPaint flag can be used to indicate that this is the first update
   // for a particular document.
   sync Update(Edit[] cset, TargetConfig targetConfig, bool isFirstPaint)
     returns (EditReply[] reply);
--- a/gfx/layers/ipc/ShadowLayerUtilsGralloc.cpp
+++ b/gfx/layers/ipc/ShadowLayerUtilsGralloc.cpp
@@ -141,16 +141,41 @@ PixelFormatForImageFormat(gfxASurface::g
   case gfxASurface::ImageFormatA8:
     return android::PIXEL_FORMAT_A_8;
   default:
     MOZ_NOT_REACHED("Unknown gralloc pixel format");
   }
   return gfxASurface::ImageFormatARGB32;
 }
 
+static size_t
+BytesPerPixelForPixelFormat(android::PixelFormat aFormat)
+{
+  switch (aFormat) {
+  case PIXEL_FORMAT_RGBA_8888:
+  case PIXEL_FORMAT_RGBX_8888:
+  case PIXEL_FORMAT_BGRA_8888:
+    return 4;
+  case PIXEL_FORMAT_RGB_888:
+    return 3;
+  case PIXEL_FORMAT_RGB_565:
+  case PIXEL_FORMAT_RGBA_5551:
+  case PIXEL_FORMAT_RGBA_4444:
+  case PIXEL_FORMAT_LA_88:
+    return 2;
+  case PIXEL_FORMAT_L_8:
+  case PIXEL_FORMAT_A_8:
+  case PIXEL_FORMAT_RGB_332:
+    return 1;
+  default:
+    MOZ_NOT_REACHED("Unknown gralloc pixel format");
+  }
+  return gfxASurface::ImageFormatARGB32;
+}
+
 static android::PixelFormat
 PixelFormatForContentType(gfxASurface::gfxContentType aContentType)
 {
   return PixelFormatForImageFormat(
     gfxPlatform::GetPlatform()->OptimalFormatForContent(aContentType));
 }
 
 static gfxASurface::gfxContentType
@@ -192,38 +217,42 @@ GrallocBufferActor::~GrallocBufferActor(
 {
   if (mAllocBytes > 0) {
     sCurrentAlloc -= mAllocBytes;
   }
 }
 
 /*static*/ PGrallocBufferParent*
 GrallocBufferActor::Create(const gfxIntSize& aSize,
-                           const gfxContentType& aContent,
+                           const uint32_t& aFormat,
+                           const uint32_t& aUsage,
                            MaybeMagicGrallocBufferHandle* aOutHandle)
 {
   PROFILER_LABEL("GrallocBufferActor", "Create");
   GrallocBufferActor* actor = new GrallocBufferActor();
   *aOutHandle = null_t();
-  android::PixelFormat format = PixelFormatForContentType(aContent);
-  sp<GraphicBuffer> buffer(
-    new GraphicBuffer(aSize.width, aSize.height, format,
-                      GraphicBuffer::USAGE_SW_READ_OFTEN |
-                      GraphicBuffer::USAGE_SW_WRITE_OFTEN |
-                      GraphicBuffer::USAGE_HW_TEXTURE));
+  uint32_t format = aFormat;
+  uint32_t usage = aUsage;
+
+  if (format == 0 || usage == 0) {
+    printf_stderr("GrallocBufferActor::Create -- format and usage must be non-zero");
+    return actor;
+  }
+
+  sp<GraphicBuffer> buffer(new GraphicBuffer(aSize.width, aSize.height, format, usage));
   if (buffer->initCheck() != OK)
     return actor;
 
-  size_t bpp = gfxASurface::BytePerPixelFromFormat(
-      gfxPlatform::GetPlatform()->OptimalFormatForContent(aContent));
+  size_t bpp = BytesPerPixelForPixelFormat(format);
   actor->mAllocBytes = aSize.width * aSize.height * bpp;
   sCurrentAlloc += actor->mAllocBytes;
 
   actor->mGraphicBuffer = buffer;
   *aOutHandle = MagicGrallocBufferHandle(buffer);
+
   return actor;
 }
 
 // used only for hacky fix in gecko 23 for bug 862324
 void GrallocBufferActor::ActorDestroy(ActorDestroyReason)
 {
   if (mTextureHost) {
     mTextureHost->ForgetBuffer();
@@ -256,34 +285,16 @@ LayerManagerComposite::SupportsDirectTex
 }
 
 /*static*/ void
 LayerManagerComposite::PlatformSyncBeforeReplyUpdate()
 {
   // Nothing to be done for gralloc.
 }
 
-/*static*/ PGrallocBufferParent*
-GrallocBufferActor::Create(const gfxIntSize& aSize,
-                           const uint32_t& aFormat,
-                           const uint32_t& aUsage,
-                           MaybeMagicGrallocBufferHandle* aOutHandle)
-{
-  GrallocBufferActor* actor = new GrallocBufferActor();
-  *aOutHandle = null_t();
-  sp<GraphicBuffer> buffer(
-    new GraphicBuffer(aSize.width, aSize.height, aFormat, aUsage));
-  if (buffer->initCheck() != OK)
-    return actor;
-
-  actor->mGraphicBuffer = buffer;
-  *aOutHandle = MagicGrallocBufferHandle(buffer);
-  return actor;
-}
-
 bool
 ISurfaceAllocator::PlatformDestroySharedSurface(SurfaceDescriptor* aSurface)
 {
   if (SurfaceDescriptor::TSurfaceDescriptorGralloc != aSurface->type()) {
     return false;
   }
 
   // we should have either a bufferParent or bufferChild
@@ -317,20 +328,21 @@ GrallocBufferActor::InitFromHandle(const
   MOZ_ASSERT(!mGraphicBuffer.get());
   MOZ_ASSERT(aHandle.mGraphicBuffer.get());
 
   mGraphicBuffer = aHandle.mGraphicBuffer;
 }
 
 PGrallocBufferChild*
 ShadowLayerForwarder::AllocGrallocBuffer(const gfxIntSize& aSize,
-                                         gfxASurface::gfxContentType aContent,
+                                         uint32_t aFormat,
+                                         uint32_t aUsage,
                                          MaybeMagicGrallocBufferHandle* aHandle)
 {
-  return mShadowManager->SendPGrallocBufferConstructor(aSize, aContent, aHandle);
+  return mShadowManager->SendPGrallocBufferConstructor(aSize, aFormat, aUsage, aHandle);
 }
 
 bool
 ISurfaceAllocator::PlatformAllocSurfaceDescriptor(const gfxIntSize& aSize,
                                                   gfxASurface::gfxContentType aContent,
                                                   uint32_t aCaps,
                                                   SurfaceDescriptor* aBuffer)
 {
@@ -340,30 +352,56 @@ ISurfaceAllocator::PlatformAllocSurfaceD
   // upload.
   if (aSize.width < 64) {
     return false;
   }
   PROFILER_LABEL("ShadowLayerForwarder", "PlatformAllocSurfaceDescriptor");
   // Gralloc buffers are efficiently mappable as gfxImageSurface, so
   // no need to check |aCaps & MAP_AS_IMAGE_SURFACE|.
   MaybeMagicGrallocBufferHandle handle;
-  PGrallocBufferChild* gc = AllocGrallocBuffer(aSize, aContent, &handle);
+  PGrallocBufferChild* gc;
+  bool defaultRBSwap;
+
+  if (aCaps & USING_GL_RENDERING_ONLY) {
+    gc = AllocGrallocBuffer(aSize,
+                            PixelFormatForContentType(aContent),
+                            GraphicBuffer::USAGE_HW_RENDER |
+                            GraphicBuffer::USAGE_HW_TEXTURE,
+                            &handle);
+    // If you're allocating for USING_GL_RENDERING_ONLY, then we don't flag
+    // this for RB swap.
+    defaultRBSwap = false;
+  } else {
+    gc = AllocGrallocBuffer(aSize,
+                            PixelFormatForContentType(aContent),
+                            GraphicBuffer::USAGE_SW_READ_OFTEN |
+                            GraphicBuffer::USAGE_SW_WRITE_OFTEN |
+                            GraphicBuffer::USAGE_HW_TEXTURE,
+                            &handle);
+    // But if you're allocating for non-GL-only rendering, we flag for
+    // RB swap to preserve old behaviour and proper interaction with
+    // cairo.
+    defaultRBSwap = true;
+  }
+
   if (!gc) {
     NS_ERROR("GrallocBufferConstructor failed by returned null");
     return false;
   } else if (handle.Tnull_t == handle.type()) {
     NS_ERROR("GrallocBufferConstructor failed by returning handle with type Tnull_t");
     PGrallocBufferChild::Send__delete__(gc);
     return false;
   }
 
   GrallocBufferActor* gba = static_cast<GrallocBufferActor*>(gc);
   gba->InitFromHandle(handle.get_MagicGrallocBufferHandle());
 
-  *aBuffer = SurfaceDescriptorGralloc(nullptr, gc, aSize, /* external */ false);
+  *aBuffer = SurfaceDescriptorGralloc(nullptr, gc, aSize,
+                                      /* external */ false,
+                                      defaultRBSwap);
   return true;
 }
 
 //-----------------------------------------------------------------------------
 // Both processes
 
 /*static*/ sp<GraphicBuffer>
 GrallocBufferActor::GetFrom(const SurfaceDescriptorGralloc& aDescriptor)
--- a/gfx/layers/ipc/ShadowLayerUtilsGralloc.h
+++ b/gfx/layers/ipc/ShadowLayerUtilsGralloc.h
@@ -67,20 +67,16 @@ class GrallocBufferActor : public PGrall
   friend class LayerManagerComposite;
   friend class ImageBridgeChild;
   typedef android::GraphicBuffer GraphicBuffer;
 
 public:
   virtual ~GrallocBufferActor();
 
   static PGrallocBufferParent*
-  Create(const gfxIntSize& aSize, const gfxContentType& aContent,
-         MaybeMagicGrallocBufferHandle* aOutHandle);
-
-  static PGrallocBufferParent*
   Create(const gfxIntSize& aSize, const uint32_t& aFormat, const uint32_t& aUsage,
          MaybeMagicGrallocBufferHandle* aOutHandle);
 
   static PGrallocBufferChild*
   Create();
 
   static android::sp<GraphicBuffer>
   GetFrom(const SurfaceDescriptorGralloc& aDescriptor);
--- a/gfx/layers/ipc/ShadowLayers.cpp
+++ b/gfx/layers/ipc/ShadowLayers.cpp
@@ -24,16 +24,18 @@
 #include "RenderTrace.h"
 #include "GeckoProfiler.h"
 #include "nsXULAppAPI.h"
 #include "mozilla/layers/ImageClient.h"
 #include "mozilla/layers/CanvasClient.h"
 #include "mozilla/layers/ContentClient.h"
 #include "ISurfaceAllocator.h"
 
+#include "nsTraceRefcntImpl.h"
+
 using namespace mozilla::ipc;
 using namespace mozilla::gl;
 using namespace mozilla::dom;
 
 namespace mozilla {
 namespace layers {
 
 typedef nsTArray<SurfaceDescriptor> BufferArray;
--- a/gfx/layers/ipc/ShadowLayers.h
+++ b/gfx/layers/ipc/ShadowLayers.h
@@ -383,18 +383,20 @@ public:
   OpenDescriptor(OpenMode aMode, const SurfaceDescriptor& aSurface);
 
 protected:
   ShadowLayerForwarder();
 
   PLayerTransactionChild* mShadowManager;
 
 #ifdef MOZ_HAVE_SURFACEDESCRIPTORGRALLOC
+  // from ISurfaceAllocator
   virtual PGrallocBufferChild* AllocGrallocBuffer(const gfxIntSize& aSize,
-                                                  gfxASurface::gfxContentType aContent,
+                                                  uint32_t aFormat,
+                                                  uint32_t aUsage,
                                                   MaybeMagicGrallocBufferHandle* aHandle) MOZ_OVERRIDE;
 #endif
 
 private:
   /**
    * Try to query the content type efficiently, but at worst map the
    * surface and return it in *aSurface.
    */
--- a/gfx/layers/opengl/TextureHostOGL.cpp
+++ b/gfx/layers/opengl/TextureHostOGL.cpp
@@ -635,23 +635,26 @@ TiledTextureHostOGL::Lock()
   mGL->MakeCurrent();
   mGL->fActiveTexture(LOCAL_GL_TEXTURE0);
 
   return true;
 }
 
 #ifdef MOZ_WIDGET_GONK
 static gfx::SurfaceFormat
-SurfaceFormatForAndroidPixelFormat(android::PixelFormat aFormat)
+SurfaceFormatForAndroidPixelFormat(android::PixelFormat aFormat,
+                                   bool swapRB = false)
 {
   switch (aFormat) {
+  case android::PIXEL_FORMAT_BGRA_8888:
+    return swapRB ? FORMAT_R8G8B8A8 : FORMAT_B8G8R8A8;
   case android::PIXEL_FORMAT_RGBA_8888:
-    return FORMAT_B8G8R8A8;
+    return swapRB ? FORMAT_B8G8R8A8 : FORMAT_R8G8B8A8;
   case android::PIXEL_FORMAT_RGBX_8888:
-    return FORMAT_B8G8R8X8;
+    return swapRB ? FORMAT_B8G8R8X8 : FORMAT_R8G8B8X8;
   case android::PIXEL_FORMAT_RGB_565:
     return FORMAT_R5G6B5;
   case android::PIXEL_FORMAT_A_8:
     return FORMAT_A8;
   case HAL_PIXEL_FORMAT_YCbCr_422_SP:
   case HAL_PIXEL_FORMAT_YCrCb_420_SP:
   case HAL_PIXEL_FORMAT_YCbCr_422_I:
   case HAL_PIXEL_FORMAT_YV12:
@@ -754,17 +757,18 @@ GrallocTextureHostOGL::SwapTexturesImpl(
 
   if (mBuffer) {
     // only done for hacky fix in gecko 23 for bug 862324.
     RegisterTextureHostAtGrallocBufferActor(nullptr, *mBuffer);
   }
 
   const SurfaceDescriptorGralloc& desc = aImage.get_SurfaceDescriptorGralloc();
   mGraphicBuffer = GrallocBufferActor::GetFrom(desc);
-  mFormat = SurfaceFormatForAndroidPixelFormat(mGraphicBuffer->getPixelFormat());
+  mFormat = SurfaceFormatForAndroidPixelFormat(mGraphicBuffer->getPixelFormat(),
+                                               desc.isRBSwapped());
   mTextureTarget = TextureTargetForAndroidPixelFormat(mGraphicBuffer->getPixelFormat());
 
   DeleteTextures();
 
   // only done for hacky fix in gecko 23 for bug 862324.
   // Doing this in SetBuffer is not enough, as ImageHostBuffered::SwapTextures can
   // change the value of *mBuffer without calling SetBuffer again.
   RegisterTextureHostAtGrallocBufferActor(this, aImage);
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -3961,16 +3961,20 @@ pref("webgl.min_capability_mode", false)
 pref("webgl.disable-extensions", false);
 pref("webgl.msaa-force", false);
 pref("webgl.prefer-16bpp", false);
 pref("webgl.default-no-alpha", false);
 pref("webgl.force-layers-readback", false);
 pref("webgl.lose-context-on-heap-minimize", false);
 pref("webgl.can-lose-context-in-foreground", true);
 pref("webgl.max-warnings-per-context", 32);
+#ifdef MOZ_WIDGET_GONK
+pref("gfx.gralloc.fence-with-readpixels", false);
+#endif
+
 
 // Stagefright prefs
 pref("stagefright.force-enabled", false);
 pref("stagefright.disabled", false);
 
 #ifdef XP_WIN
 // The default TCP send window on Windows is too small, and autotuning only occurs on receive
 pref("network.tcp.sendbuffer", 131072);