Bug 1210182 - Implement GrallocTextureHostBasic r=nical
authorSotaro Ikeda <sotaro.ikeda.g@gmail.com>
Mon, 26 Oct 2015 22:43:07 -0700
changeset 303069 cab34e0b0a7b02fa3b4e86e89c24d48cd96c1cbe
parent 303068 ef10857254a01368861d9c1cc0105de89be6d169
child 303070 57acb7a0a53f66359887e8315b68b638eb96d273
push id5392
push userraliiev@mozilla.com
push dateMon, 14 Dec 2015 20:08:23 +0000
treeherdermozilla-beta@16ce8562a975 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnical
bugs1210182
milestone44.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
Bug 1210182 - Implement GrallocTextureHostBasic r=nical
gfx/layers/Compositor.cpp
gfx/layers/Compositor.h
gfx/layers/GrallocImages.cpp
gfx/layers/GrallocImages.h
gfx/layers/basic/GrallocTextureHostBasic.cpp
gfx/layers/basic/GrallocTextureHostBasic.h
gfx/layers/basic/TextureHostBasic.cpp
gfx/layers/client/TextureClientSharedSurface.cpp
gfx/layers/composite/TextureHost.cpp
gfx/layers/moz.build
gfx/layers/opengl/CompositorOGL.cpp
gfx/layers/opengl/CompositorOGL.h
gfx/layers/opengl/GrallocTextureHost.cpp
widget/gonk/libdisplay/GonkDisplayJB.cpp
widget/gonk/libdisplay/GonkDisplayJB.h
--- a/gfx/layers/Compositor.cpp
+++ b/gfx/layers/Compositor.cpp
@@ -6,16 +6,23 @@
 #include "mozilla/layers/Compositor.h"
 #include "base/message_loop.h"          // for MessageLoop
 #include "mozilla/layers/CompositorParent.h"  // for CompositorParent
 #include "mozilla/layers/Effects.h"     // for Effect, EffectChain, etc
 #include "mozilla/mozalloc.h"           // for operator delete, etc
 #include "gfx2DGlue.h"
 #include "nsAppRunner.h"
 
+#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
+#include "libdisplay/GonkDisplay.h"     // for GonkDisplay
+#include <ui/Fence.h>
+#include "nsWindow.h"
+#include "nsScreenManagerGonk.h"
+#endif
+
 namespace mozilla {
 namespace gfx {
 class Matrix4x4;
 } // namespace gfx
 
 namespace layers {
 
 /* static */ void
@@ -348,10 +355,54 @@ DecomposeIntoNoRepeatRects(const gfx::Re
            flipped);
   SetRects(3, aLayerRects, aTextureRects,
            xmid, ymid, aRect.XMost(), aRect.YMost(),
            0.0f, 0.0f, br.x, br.y,
            flipped);
   return 4;
 }
 
+#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
+void
+Compositor::SetDispAcquireFence(Layer* aLayer, nsIWidget* aWidget)
+{
+  // OpenGL does not provide ReleaseFence for rendering.
+  // Instead use DispAcquireFence as layer buffer's ReleaseFence
+  // to prevent flickering and tearing.
+  // DispAcquireFence is DisplaySurface's AcquireFence.
+  // AcquireFence will be signaled when a buffer's content is available.
+  // See Bug 974152.
+
+  if (!aLayer || !aWidget) {
+    return;
+  }
+  nsWindow* window = static_cast<nsWindow*>(aWidget);
+  RefPtr<FenceHandle::FdObj> fence = new FenceHandle::FdObj(
+      window->GetScreen()->GetPrevDispAcquireFd());
+  mReleaseFenceHandle.Merge(FenceHandle(fence));
+}
+
+FenceHandle
+Compositor::GetReleaseFence()
+{
+  if (!mReleaseFenceHandle.IsValid()) {
+    return FenceHandle();
+  }
+
+  RefPtr<FenceHandle::FdObj> fdObj = mReleaseFenceHandle.GetDupFdObj();
+  return FenceHandle(fdObj);
+}
+
+#else
+void
+Compositor::SetDispAcquireFence(Layer* aLayer, nsIWidget* aWidget)
+{
+}
+
+FenceHandle
+Compositor::GetReleaseFence()
+{
+  return FenceHandle();
+}
+#endif
+
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/Compositor.h
+++ b/gfx/layers/Compositor.h
@@ -365,22 +365,19 @@ public:
                           gfx::Rect* aClipRectOut = nullptr,
                           gfx::Rect* aRenderBoundsOut = nullptr) = 0;
 
   /**
    * Flush the current frame to the screen and tidy up.
    */
   virtual void EndFrame() = 0;
 
-  virtual void SetDispAcquireFence(Layer* aLayer, nsIWidget* aWidget) {}
+  virtual void SetDispAcquireFence(Layer* aLayer, nsIWidget* aWidget);
 
-  virtual FenceHandle GetReleaseFence()
-  {
-    return FenceHandle();
-  }
+  virtual FenceHandle GetReleaseFence();
 
   /**
    * Post-rendering stuff if the rendering is done outside of this Compositor
    * e.g., by Composer2D.
    * aTransform is the transform from user space to window space.
    */
   virtual void EndFrameForExternalComposition(const gfx::Matrix& aTransform) = 0;
 
@@ -536,16 +533,20 @@ protected:
 
   ScreenRotation mScreenRotation;
 
   virtual gfx::IntSize GetWidgetSize() const = 0;
 
   RefPtr<gfx::DrawTarget> mTarget;
   gfx::IntRect mTargetBounds;
 
+#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
+  FenceHandle mReleaseFenceHandle;
+#endif
+
 private:
   static LayersBackend sBackend;
 
 };
 
 // Returns the number of rects. (Up to 4)
 typedef gfx::Rect decomposedRectArrayT[4];
 size_t DecomposeIntoNoRepeatRects(const gfx::Rect& aRect,
--- a/gfx/layers/GrallocImages.cpp
+++ b/gfx/layers/GrallocImages.cpp
@@ -392,51 +392,64 @@ ConvertOmxYUVFormatToRGB565(android::sp<
   if (rv) {
     NS_WARNING("OMX color conversion failed");
     return BAD_VALUE;
   }
 
   return OK;
 }
 
+already_AddRefed<gfx::DataSourceSurface>
+GetDataSourceSurfaceFrom(android::sp<android::GraphicBuffer>& aGraphicBuffer,
+                         gfx::IntSize aSize,
+                         const layers::PlanarYCbCrData& aYcbcrData)
+{
+  MOZ_ASSERT(aGraphicBuffer.get());
+
+  RefPtr<gfx::DataSourceSurface> surface =
+    gfx::Factory::CreateDataSourceSurface(aSize, gfx::SurfaceFormat::R5G6B5);
+  if (NS_WARN_IF(!surface)) {
+    return nullptr;
+  }
+
+  gfx::DataSourceSurface::MappedSurface mappedSurface;
+  if (!surface->Map(gfx::DataSourceSurface::WRITE, &mappedSurface)) {
+    NS_WARNING("Could not map DataSourceSurface");
+    return nullptr;
+  }
+
+  int32_t rv;
+  rv = ConvertOmxYUVFormatToRGB565(aGraphicBuffer, surface, &mappedSurface, aYcbcrData);
+  if (rv == OK) {
+    surface->Unmap();
+    return surface.forget();
+  }
+
+  rv = ConvertVendorYUVFormatToRGB565(aGraphicBuffer, surface, &mappedSurface);
+  surface->Unmap();
+  if (rv != OK) {
+    NS_WARNING("Unknown color format");
+    return nullptr;
+  }
+
+  return surface.forget();
+}
+
 already_AddRefed<gfx::SourceSurface>
 GrallocImage::GetAsSourceSurface()
 {
   if (!mTextureClient) {
     return nullptr;
   }
 
   android::sp<GraphicBuffer> graphicBuffer =
     mTextureClient->GetGraphicBuffer();
 
   RefPtr<gfx::DataSourceSurface> surface =
-    gfx::Factory::CreateDataSourceSurface(GetSize(), gfx::SurfaceFormat::R5G6B5);
-  if (NS_WARN_IF(!surface)) {
-    return nullptr;
-  }
-
-  gfx::DataSourceSurface::MappedSurface mappedSurface;
-  if (!surface->Map(gfx::DataSourceSurface::WRITE, &mappedSurface)) {
-    NS_WARNING("Could not map DataSourceSurface");
-    return nullptr;
-  }
-
-  int32_t rv;
-  rv = ConvertOmxYUVFormatToRGB565(graphicBuffer, surface, &mappedSurface, mData);
-  if (rv == OK) {
-    surface->Unmap();
-    return surface.forget();
-  }
-
-  rv = ConvertVendorYUVFormatToRGB565(graphicBuffer, surface, &mappedSurface);
-  surface->Unmap();
-  if (rv != OK) {
-    NS_WARNING("Unknown color format");
-    return nullptr;
-  }
+    GetDataSourceSurfaceFrom(graphicBuffer, mSize, mData);
 
   return surface.forget();
 }
 
 android::sp<android::GraphicBuffer>
 GrallocImage::GetGraphicBuffer() const
 {
   if (!mTextureClient) {
--- a/gfx/layers/GrallocImages.h
+++ b/gfx/layers/GrallocImages.h
@@ -17,16 +17,21 @@
 
 #include <ui/GraphicBuffer.h>
 
 namespace mozilla {
 namespace layers {
 
 class GrallocTextureClientOGL;
 
+already_AddRefed<gfx::DataSourceSurface>
+GetDataSourceSurfaceFrom(android::sp<android::GraphicBuffer>& aGraphicBuffer,
+                         gfx::IntSize aSize,
+                         const layers::PlanarYCbCrData& aYcbcrData);
+
 /**
  * The YUV format supported by Android HAL
  *
  * 4:2:0 - CbCr width and height is half that of Y.
  *
  * This format assumes
  * - an even width
  * - an even height
new file mode 100644
--- /dev/null
+++ b/gfx/layers/basic/GrallocTextureHostBasic.cpp
@@ -0,0 +1,291 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "GrallocTextureHostBasic.h"
+#include "GrallocImages.h"  // for GetDataSourceSurfaceFrom()
+#include "mozilla/layers/SharedBufferManagerParent.h"
+
+#if ANDROID_VERSION >= 17
+#include <ui/Fence.h>
+#endif
+
+namespace mozilla {
+namespace layers {
+
+static SurfaceFormat
+HalFormatToSurfaceFormat(int aHalFormat, TextureFlags aFlags)
+{
+  bool swapRB = bool(aFlags & TextureFlags::RB_SWAPPED);
+  switch (aHalFormat) {
+  case android::PIXEL_FORMAT_BGRA_8888:
+    return swapRB ? gfx::SurfaceFormat::R8G8B8A8 : gfx::SurfaceFormat::B8G8R8A8;
+  case android::PIXEL_FORMAT_RGBA_8888:
+    return swapRB ? gfx::SurfaceFormat::B8G8R8A8 : gfx::SurfaceFormat::R8G8B8A8;
+  case android::PIXEL_FORMAT_RGBX_8888:
+    return swapRB ? gfx::SurfaceFormat::B8G8R8X8 : gfx::SurfaceFormat::R8G8B8X8;
+  case android::PIXEL_FORMAT_RGB_565:
+    return gfx::SurfaceFormat::R5G6B5;
+  case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+  case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+  case HAL_PIXEL_FORMAT_YCbCr_422_I:
+  case GrallocImage::HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
+  case GrallocImage::HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+  case HAL_PIXEL_FORMAT_YV12:
+#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
+  case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
+#endif
+      // Needs convert to RGB565
+      return gfx::SurfaceFormat::R5G6B5;
+  default:
+    if (aHalFormat >= 0x100 && aHalFormat <= 0x1FF) {
+      // Reserved range for HAL specific formats.
+      // Needs convert to RGB565
+      return gfx::SurfaceFormat::R5G6B5;
+    } else {
+      MOZ_CRASH("Unhandled HAL pixel format");
+      return SurfaceFormat::UNKNOWN; // not reached
+    }
+  }
+}
+
+static bool
+NeedsConvertFromYUVtoRGB565(int aHalFormat)
+{
+  switch (aHalFormat) {
+  case android::PIXEL_FORMAT_BGRA_8888:
+  case android::PIXEL_FORMAT_RGBA_8888:
+  case android::PIXEL_FORMAT_RGBX_8888:
+  case android::PIXEL_FORMAT_RGB_565:
+    return false;
+  case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+  case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+  case HAL_PIXEL_FORMAT_YCbCr_422_I:
+  case GrallocImage::HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
+  case GrallocImage::HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+  case HAL_PIXEL_FORMAT_YV12:
+#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
+  case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
+#endif
+      return true;
+  default:
+    if (aHalFormat >= 0x100 && aHalFormat <= 0x1FF) {
+      // Reserved range for HAL specific formats.
+      return true;
+    } else {
+      MOZ_CRASH("Unhandled HAL pixel format");
+      return false; // not reached
+    }
+  }
+}
+
+GrallocTextureHostBasic::GrallocTextureHostBasic(
+  TextureFlags aFlags,
+  const NewSurfaceDescriptorGralloc& aDescriptor)
+  : TextureHost(aFlags)
+  , mGrallocHandle(aDescriptor)
+  , mSize(0, 0)
+  , mCropSize(0, 0)
+  , mFormat(gfx::SurfaceFormat::UNKNOWN)
+  , mIsOpaque(aDescriptor.isOpaque())
+{
+  android::GraphicBuffer* grallocBuffer = GetGraphicBufferFromDesc(mGrallocHandle).get();
+  MOZ_ASSERT(grallocBuffer);
+
+  if (grallocBuffer) {
+    mFormat =
+      HalFormatToSurfaceFormat(grallocBuffer->getPixelFormat(),
+                               aFlags & TextureFlags::RB_SWAPPED);
+    mSize = gfx::IntSize(grallocBuffer->getWidth(), grallocBuffer->getHeight());
+    mCropSize = mSize;
+  } else {
+    printf_stderr("gralloc buffer is nullptr\n");
+  }
+}
+
+bool
+GrallocTextureHostBasic::Lock()
+{
+  if (!mCompositor || !IsValid()) {
+    return false;
+  }
+
+  if (mTextureSource) {
+    return true;
+  }
+
+  android::sp<android::GraphicBuffer> graphicBuffer =
+    GetGraphicBufferFromDesc(mGrallocHandle);
+  MOZ_ASSERT(graphicBuffer.get());
+
+  RefPtr<gfx::DataSourceSurface> surf;
+  if (NeedsConvertFromYUVtoRGB565(graphicBuffer->getPixelFormat())) {
+    PlanarYCbCrData ycbcrData;
+    surf = GetDataSourceSurfaceFrom(graphicBuffer,
+                                    mCropSize,
+                                    ycbcrData);
+  } else {
+    uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN;
+    int32_t rv = graphicBuffer->lock(usage,
+                                     reinterpret_cast<void**>(&mMappedBuffer));
+    if (rv) {
+      mMappedBuffer = nullptr;
+      NS_WARNING("Couldn't lock graphic buffer");
+      return false;
+    }
+    surf = Factory::CreateWrappingDataSourceSurface(
+             mMappedBuffer,
+             graphicBuffer->getStride() * gfx::BytesPerPixel(mFormat),
+             mCropSize,
+             mFormat);
+  }
+  mTextureSource = mCompositor->CreateDataTextureSource(mFlags);
+  mTextureSource->Update(surf, nullptr);
+  return true;
+}
+
+bool
+GrallocTextureHostBasic::IsValid() const
+{
+  android::GraphicBuffer* graphicBuffer = GetGraphicBufferFromDesc(mGrallocHandle).get();
+  return graphicBuffer != nullptr;
+}
+
+bool
+GrallocTextureHostBasic::BindTextureSource(CompositableTextureSourceRef& aTexture)
+{
+  aTexture = mTextureSource;
+  return !!aTexture;
+}
+
+void
+GrallocTextureHostBasic::UnbindTextureSource()
+{
+  ClearTextureSource();
+}
+
+void
+GrallocTextureHostBasic::ClearTextureSource()
+{
+  mTextureSource = nullptr;
+  if (mMappedBuffer) {
+    android::GraphicBuffer* graphicBuffer = GetGraphicBufferFromDesc(mGrallocHandle).get();
+    MOZ_ASSERT(graphicBuffer);
+    mMappedBuffer = nullptr;
+    graphicBuffer->unlock();
+  }
+}
+
+void
+GrallocTextureHostBasic::SetCompositor(Compositor* aCompositor)
+{
+  BasicCompositor* compositor = static_cast<BasicCompositor*>(aCompositor);
+  mCompositor = compositor;
+  if (mTextureSource) {
+    mTextureSource->SetCompositor(compositor);
+  }
+}
+
+gfx::SurfaceFormat
+GrallocTextureHostBasic::GetFormat() const {
+  return mFormat;
+}
+
+void
+GrallocTextureHostBasic::WaitAcquireFenceHandleSyncComplete()
+{
+  if (!mAcquireFenceHandle.IsValid()) {
+    return;
+  }
+
+#if ANDROID_VERSION >= 17
+  RefPtr<FenceHandle::FdObj> fdObj = mAcquireFenceHandle.GetAndResetFdObj();
+  android::sp<android::Fence> fence(
+    new android::Fence(fdObj->GetAndResetFd()));
+
+  // Wait fece complete with timeout.
+  // If a source of the fence becomes invalid because of error,
+  // fene complete is not signaled. See Bug 1061435.
+  int rv = fence->wait(400 /*400 msec*/);
+  if (rv != android::OK) {
+    NS_ERROR("failed to wait fence complete");
+  }
+#endif
+}
+
+void
+GrallocTextureHostBasic::SetCropRect(nsIntRect aCropRect)
+{
+  MOZ_ASSERT(aCropRect.TopLeft() == IntPoint(0, 0));
+  MOZ_ASSERT(!aCropRect.IsEmpty());
+  MOZ_ASSERT(aCropRect.width <= mSize.width);
+  MOZ_ASSERT(aCropRect.height <= mSize.height);
+
+  gfx::IntSize cropSize(aCropRect.width, aCropRect.height);
+  if (mCropSize == cropSize) {
+    return;
+  }
+
+  mCropSize = cropSize;
+  ClearTextureSource();
+}
+
+void
+GrallocTextureHostBasic::DeallocateSharedData()
+{
+  ClearTextureSource();
+
+  if (mGrallocHandle.buffer().type() != MaybeMagicGrallocBufferHandle::Tnull_t) {
+    MaybeMagicGrallocBufferHandle handle = mGrallocHandle.buffer();
+    base::ProcessId owner;
+    if (handle.type() == MaybeMagicGrallocBufferHandle::TGrallocBufferRef) {
+      owner = handle.get_GrallocBufferRef().mOwner;
+    }
+    else {
+      owner = handle.get_MagicGrallocBufferHandle().mRef.mOwner;
+    }
+
+    SharedBufferManagerParent::DropGrallocBuffer(owner, mGrallocHandle);
+  }
+}
+
+void
+GrallocTextureHostBasic::ForgetSharedData()
+{
+  ClearTextureSource();
+}
+
+void
+GrallocTextureHostBasic::DeallocateDeviceData()
+{
+  ClearTextureSource();
+}
+
+LayerRenderState
+GrallocTextureHostBasic::GetRenderState()
+{
+  android::GraphicBuffer* graphicBuffer = GetGraphicBufferFromDesc(mGrallocHandle).get();
+
+  if (graphicBuffer) {
+    LayerRenderStateFlags flags = LayerRenderStateFlags::LAYER_RENDER_STATE_DEFAULT;
+    if (mIsOpaque) {
+      flags |= LayerRenderStateFlags::OPAQUE;
+    }
+    if (mFlags & TextureFlags::ORIGIN_BOTTOM_LEFT) {
+      flags |= LayerRenderStateFlags::ORIGIN_BOTTOM_LEFT;
+    }
+    if (mFlags & TextureFlags::RB_SWAPPED) {
+      flags |= LayerRenderStateFlags::FORMAT_RB_SWAP;
+    }
+    return LayerRenderState(graphicBuffer,
+                            mCropSize,
+                            flags,
+                            this);
+  }
+
+  return LayerRenderState();
+}
+
+} // namespace layers
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/gfx/layers/basic/GrallocTextureHostBasic.h
@@ -0,0 +1,86 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef MOZILLA_GFX_GRALLOCTEXTUREHOST_BASIC_H
+#define MOZILLA_GFX_GRALLOCTEXTUREHOST_BASIC_H
+
+#include "mozilla/layers/BasicCompositor.h"
+#include "mozilla/layers/ShadowLayerUtilsGralloc.h"
+#include "mozilla/layers/TextureHostBasic.h"
+
+namespace mozilla {
+namespace layers {
+
+class BasicCompositor;
+
+/**
+ * A TextureHost for shared gralloc
+ *
+ * Most of the logic actually happens in GrallocTextureSourceBasic.
+ */
+class GrallocTextureHostBasic : public TextureHost
+{
+public:
+  GrallocTextureHostBasic(TextureFlags aFlags,
+                          const NewSurfaceDescriptorGralloc& aDescriptor);
+
+  virtual void SetCompositor(Compositor* aCompositor) override;
+
+  virtual bool Lock() override;
+
+  virtual gfx::SurfaceFormat GetFormat() const override;
+
+  virtual bool BindTextureSource(CompositableTextureSourceRef& aTexture) override;
+
+  virtual void UnbindTextureSource() override;
+
+  virtual already_AddRefed<gfx::DataSourceSurface> GetAsSurface() override
+  {
+    return nullptr; // XXX - implement this (for MOZ_DUMP_PAINTING)
+  }
+
+  virtual void WaitAcquireFenceHandleSyncComplete() override;
+
+  virtual gfx::IntSize GetSize() const override { return mCropSize; }
+
+  virtual void SetCropRect(nsIntRect aCropRect) override;
+
+  virtual void DeallocateSharedData() override;
+
+  virtual void ForgetSharedData() override;
+
+  virtual void DeallocateDeviceData() override;
+
+  virtual LayerRenderState GetRenderState() override;
+
+  bool IsValid() const;
+
+  void ClearTextureSource();
+
+#ifdef MOZ_LAYERS_HAVE_LOG
+  virtual const char* Name() override { return "GrallocTextureHostBasic"; }
+#endif
+
+protected:
+  RefPtr<BasicCompositor> mCompositor;
+  RefPtr<DataTextureSource> mTextureSource;
+  NewSurfaceDescriptorGralloc mGrallocHandle;
+  // gralloc buffer size.
+  gfx::IntSize mSize;
+  // Size reported by TextureClient, can be different in some cases (video?),
+  // used by LayerRenderState.
+  gfx::IntSize mCropSize;
+  gfx::SurfaceFormat mFormat;
+  bool mIsOpaque;
+  /**
+   * Points to a mapped gralloc buffer when TextureSource is valid.
+   */
+  uint8_t* mMappedBuffer;
+};
+
+} // namespace layers
+} // namespace mozilla
+
+#endif // MOZILLA_GFX_GRALLOCTEXTUREHOST_BASIC_H
--- a/gfx/layers/basic/TextureHostBasic.cpp
+++ b/gfx/layers/basic/TextureHostBasic.cpp
@@ -2,16 +2,19 @@
 * 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 "TextureHostBasic.h"
 #ifdef XP_MACOSX
 #include "MacIOSurfaceTextureHostBasic.h"
 #endif
+#ifdef MOZ_WIDGET_GONK
+#include "GrallocTextureHostBasic.h"
+#endif
 
 using namespace mozilla::gl;
 using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace layers {
 
 already_AddRefed<TextureHost>
@@ -21,13 +24,20 @@ CreateTextureHostBasic(const SurfaceDesc
 {
 #ifdef XP_MACOSX
   if (aDesc.type() == SurfaceDescriptor::TSurfaceDescriptorMacIOSurface) {
     const SurfaceDescriptorMacIOSurface& desc =
       aDesc.get_SurfaceDescriptorMacIOSurface();
     return MakeAndAddRef<MacIOSurfaceTextureHostBasic>(aFlags, desc);
   }
 #endif
+#ifdef MOZ_WIDGET_GONK
+  if (aDesc.type() == SurfaceDescriptor::TNewSurfaceDescriptorGralloc) {
+      const NewSurfaceDescriptorGralloc& desc =
+        aDesc.get_NewSurfaceDescriptorGralloc();
+    return MakeAndAddRef<GrallocTextureHostBasic>(aFlags, desc);
+    }
+#endif
   return CreateBackendIndependentTextureHost(aDesc, aDeallocator, aFlags);
 }
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/client/TextureClientSharedSurface.cpp
+++ b/gfx/layers/client/TextureClientSharedSurface.cpp
@@ -9,19 +9,22 @@
 #include "mozilla/gfx/2D.h"
 #include "mozilla/gfx/Logging.h"        // for gfxDebug
 #include "mozilla/layers/ISurfaceAllocator.h"
 #include "mozilla/unused.h"
 #include "nsThreadUtils.h"
 #include "SharedSurface.h"
 
 #ifdef MOZ_WIDGET_GONK
+#include "mozilla/layers/GrallocTextureClient.h"
 #include "SharedSurfaceGralloc.h"
 #endif
 
+using namespace mozilla::gl;
+
 namespace mozilla {
 namespace layers {
 
 SharedSurfaceTextureClient::SharedSurfaceTextureClient(ISurfaceAllocator* aAllocator,
                                                        TextureFlags aFlags,
                                                        UniquePtr<gl::SharedSurface> surf,
                                                        gl::SurfaceFactory* factory)
   : TextureClient(aAllocator, aFlags | TextureFlags::RECYCLE)
--- a/gfx/layers/composite/TextureHost.cpp
+++ b/gfx/layers/composite/TextureHost.cpp
@@ -209,20 +209,20 @@ TextureHost::Create(const SurfaceDescrip
   switch (aDesc.type()) {
     case SurfaceDescriptor::TSurfaceDescriptorShmem:
     case SurfaceDescriptor::TSurfaceDescriptorMemory:
     case SurfaceDescriptor::TSurfaceDescriptorDIB:
     case SurfaceDescriptor::TSurfaceDescriptorFileMapping:
       return CreateBackendIndependentTextureHost(aDesc, aDeallocator, aFlags);
 
     case SurfaceDescriptor::TEGLImageDescriptor:
-    case SurfaceDescriptor::TNewSurfaceDescriptorGralloc:
     case SurfaceDescriptor::TSurfaceTextureDescriptor:
       return CreateTextureHostOGL(aDesc, aDeallocator, aFlags);
 
+    case SurfaceDescriptor::TNewSurfaceDescriptorGralloc:
     case SurfaceDescriptor::TSurfaceDescriptorMacIOSurface:
       if (aBackend == LayersBackend::LAYERS_OPENGL) {
         return CreateTextureHostOGL(aDesc, aDeallocator, aFlags);
       } else {
         return CreateTextureHostBasic(aDesc, aDeallocator, aFlags);
       }
 
 #ifdef MOZ_X11
--- a/gfx/layers/moz.build
+++ b/gfx/layers/moz.build
@@ -212,19 +212,21 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'coco
         'MacIOSurfaceImage.cpp',
     ]
 
 # NB: Gralloc is available on other platforms that use the android GL
 # libraries, but only Gonk is able to use it reliably because Gecko
 # has full system permissions there.
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
     EXPORTS.mozilla.layers += [
+        'basic/GrallocTextureHostBasic.h',
         'ipc/ShadowLayerUtilsGralloc.h',
     ]
     UNIFIED_SOURCES += [
+        'basic/GrallocTextureHostBasic.cpp',
         'GrallocImages.cpp',
         'opengl/EGLImageHelpers.cpp',
         'opengl/GrallocTextureClient.cpp',
         'opengl/GrallocTextureHost.cpp',
     ]
     LOCAL_INCLUDES += ['/widget/gonk']
     CXXFLAGS += [
          '-I%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
--- a/gfx/layers/opengl/CompositorOGL.cpp
+++ b/gfx/layers/opengl/CompositorOGL.cpp
@@ -46,23 +46,16 @@
 #endif
 
 #ifdef XP_MACOSX
 #include "nsCocoaFeatures.h"
 #endif
 
 #include "GeckoProfiler.h"
 
-#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
-#include "libdisplay/GonkDisplay.h"     // for GonkDisplay
-#include <ui/Fence.h>
-#include "nsWindow.h"
-#include "nsScreenManagerGonk.h"
-#endif
-
 namespace mozilla {
 
 using namespace std;
 using namespace gfx;
 
 namespace layers {
 
 using namespace mozilla::gl;
@@ -1453,60 +1446,16 @@ CompositorOGL::EndFrame()
 
   mGLContext->fActiveTexture(LOCAL_GL_TEXTURE2);
   mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, 0);
   if (!mGLContext->IsGLES()) {
     mGLContext->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, 0);
   }
 }
 
-#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
-void
-CompositorOGL::SetDispAcquireFence(Layer* aLayer, nsIWidget* aWidget)
-{
-  // OpenGL does not provide ReleaseFence for rendering.
-  // Instead use DispAcquireFence as layer buffer's ReleaseFence
-  // to prevent flickering and tearing.
-  // DispAcquireFence is DisplaySurface's AcquireFence.
-  // AcquireFence will be signaled when a buffer's content is available.
-  // See Bug 974152.
-
-  if (!aLayer || !aWidget) {
-    return;
-  }
-  nsWindow* window = static_cast<nsWindow*>(aWidget);
-  RefPtr<FenceHandle::FdObj> fence = new FenceHandle::FdObj(
-      window->GetScreen()->GetPrevDispAcquireFd());
-  mReleaseFenceHandle.Merge(FenceHandle(fence));
-}
-
-FenceHandle
-CompositorOGL::GetReleaseFence()
-{
-  if (!mReleaseFenceHandle.IsValid()) {
-    return FenceHandle();
-  }
-
-  RefPtr<FenceHandle::FdObj> fdObj = mReleaseFenceHandle.GetDupFdObj();
-  return FenceHandle(fdObj);
-}
-
-#else
-void
-CompositorOGL::SetDispAcquireFence(Layer* aLayer, nsIWidget* aWidget)
-{
-}
-
-FenceHandle
-CompositorOGL::GetReleaseFence()
-{
-  return FenceHandle();
-}
-#endif
-
 void
 CompositorOGL::EndFrameForExternalComposition(const gfx::Matrix& aTransform)
 {
   MOZ_ASSERT(!mTarget);
   if (mTexturePool) {
     mTexturePool->EndFrame();
   }
 }
--- a/gfx/layers/opengl/CompositorOGL.h
+++ b/gfx/layers/opengl/CompositorOGL.h
@@ -227,18 +227,16 @@ public:
   virtual void DrawQuad(const gfx::Rect& aRect,
                         const gfx::Rect& aClipRect,
                         const EffectChain &aEffectChain,
                         gfx::Float aOpacity,
                         const gfx::Matrix4x4& aTransform,
                         const gfx::Rect& aVisibleRect) override;
 
   virtual void EndFrame() override;
-  virtual void SetDispAcquireFence(Layer* aLayer, nsIWidget* aWidget) override;
-  virtual FenceHandle GetReleaseFence() override;
   virtual void EndFrameForExternalComposition(const gfx::Matrix& aTransform) override;
 
   virtual bool SupportsPartialTextureUpdate() override;
 
   virtual bool CanUseCanvasLayerForSize(const gfx::IntSize &aSize) override
   {
     if (!mGLContext)
       return false;
@@ -447,17 +445,16 @@ private:
   bool mDestroyed;
 
   /**
    * Size of the OpenGL context's primary framebuffer in pixels. Used by
    * FlipY for the y-flipping calculation and by the DEAA shader.
    */
   gfx::IntSize mViewportSize;
 
-  FenceHandle mReleaseFenceHandle;
   ShaderProgramOGL *mCurrentProgram;
 
   gfx::Rect mRenderBound;
 
   CompositorOGLVRObjects mVR;
 };
 
 } // namespace layers
--- a/gfx/layers/opengl/GrallocTextureHost.cpp
+++ b/gfx/layers/opengl/GrallocTextureHost.cpp
@@ -113,17 +113,17 @@ GrallocTextureHostOGL::GrallocTextureHos
 
   if (graphicBuffer) {
     mFormat =
       SurfaceFormatForAndroidPixelFormat(graphicBuffer->getPixelFormat(),
                                          aFlags & TextureFlags::RB_SWAPPED);
     mSize = gfx::IntSize(graphicBuffer->getWidth(), graphicBuffer->getHeight());
     mCropSize = mSize;
   } else {
-    printf_stderr("gralloc buffer is nullptr");
+    printf_stderr("gralloc buffer is nullptr\n");
   }
 }
 
 GrallocTextureHostOGL::~GrallocTextureHostOGL()
 {
   DestroyEGLImage();
 }
 
@@ -414,17 +414,17 @@ GrallocTextureHostOGL::WaitAcquireFenceH
   }
 
   // Wait sync complete with timeout.
   // If a source of the fence becomes invalid because of error,
   // fene complete is not signaled. See Bug 1061435.
   EGLint status = sEGLLibrary.fClientWaitSync(EGL_DISPLAY(),
                                               sync,
                                               0,
-                                              400000000 /*400 usec*/);
+                                              400000000 /*400 msec*/);
   if (status != LOCAL_EGL_CONDITION_SATISFIED) {
     NS_ERROR("failed to wait native fence sync");
   }
   MOZ_ALWAYS_TRUE( sEGLLibrary.fDestroySync(EGL_DISPLAY(), sync) );
 }
 
 void
 GrallocTextureHostOGL::SetCropRect(nsIntRect aCropRect)
--- a/widget/gonk/libdisplay/GonkDisplayJB.cpp
+++ b/widget/gonk/libdisplay/GonkDisplayJB.cpp
@@ -318,34 +318,51 @@ GonkDisplayJB::DequeueBuffer()
     fence->waitForever("GonkDisplayJB_DequeueBuffer");
 #endif
     return buf;
 }
 
 bool
 GonkDisplayJB::QueueBuffer(ANativeWindowBuffer* buf)
 {
+    bool success = false;
+    int error = DoQueueBuffer(buf);
+    // Check for bootAnim or normal display flow.
+    if (!mBootAnimSTClient.get()) {
+        success = Post(mDispSurface->lastHandle, mDispSurface->GetPrevDispAcquireFd());
+    } else {
+        success = Post(mBootAnimDispSurface->lastHandle, mBootAnimDispSurface->GetPrevDispAcquireFd());
+    }
+    return error == 0 && success;
+}
+
+int
+GonkDisplayJB::DoQueueBuffer(ANativeWindowBuffer* buf)
+{
     int error = 0;
-    bool success = false;
     // Check for bootAnim or normal display flow.
     if (!mBootAnimSTClient.get()) {
         error = mSTClient->queueBuffer(mSTClient.get(), buf, -1);
-        success = Post(mDispSurface->lastHandle, mDispSurface->GetPrevDispAcquireFd());
     } else {
         error = mBootAnimSTClient->queueBuffer(mBootAnimSTClient.get(), buf, -1);
-        success = Post(mBootAnimDispSurface->lastHandle, mBootAnimDispSurface->GetPrevDispAcquireFd());
     }
-
-    return error == 0 && success;
+    return error;
 }
 
 void
 GonkDisplayJB::UpdateDispSurface(EGLDisplay dpy, EGLSurface sur)
 {
-    eglSwapBuffers(dpy, sur);
+    if (sur != EGL_NO_SURFACE) {
+      eglSwapBuffers(dpy, sur);
+    } else {
+      // When BasicCompositor is used as Compositor,
+      // EGLSurface does not exit.
+      ANativeWindowBuffer* buf = DequeueBuffer();
+      DoQueueBuffer(buf);
+    }
 }
 
 void
 GonkDisplayJB::NotifyBootAnimationStopped()
 {
     if (mBootAnimSTClient.get()) {
         mBootAnimSTClient = nullptr;
         mBootAnimDispSurface = nullptr;
--- a/widget/gonk/libdisplay/GonkDisplayJB.h
+++ b/widget/gonk/libdisplay/GonkDisplayJB.h
@@ -53,16 +53,18 @@ public:
     virtual void NotifyBootAnimationStopped();
 
 private:
     void CreateSurface(android::sp<ANativeWindow>& aNativeWindow,
                        android::sp<android::DisplaySurface>& aDisplaySurface,
                        uint32_t aWidth, uint32_t aHeight);
     void PowerOnDisplay(int aDpy);
 
+    int DoQueueBuffer(ANativeWindowBuffer* buf);
+
     hw_module_t const*        mModule;
     hw_module_t const*        mFBModule;
     hwc_composer_device_1_t*  mHwc;
     framebuffer_device_t*     mFBDevice;
     power_module_t*           mPowerModule;
     android::sp<android::DisplaySurface> mDispSurface;
     android::sp<ANativeWindow> mSTClient;
     android::sp<android::DisplaySurface> mBootAnimDispSurface;