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 134114 a33154335e3786c0f4914ea0d99f3471b826d6c8
parent 134113 25ea966531cafbae9fa719d5d0618dee43557f6f
child 134115 f00dba4fef632ebf7e65cbac7775afd5024cead8
push id24783
push userryanvm@gmail.com
push dateWed, 05 Jun 2013 20:30:03 +0000
treeherdermozilla-central@204de5b7e0a6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnical, jgilbert, jrmuizel
bugs843599
milestone24.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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);