bool
ISurfaceAllocator::PlatformAllocSurfaceDescriptor(const gfxIntSize& aSize,
                                                  gfxASurface::gfxContentType aContent,
                                                  uint32_t aCaps,
                                                  SurfaceDescriptor* aBuffer)
{
  // Some GL implementations fail to render gralloc textures with
  // width < 64.  There's not much point in gralloc'ing buffers that
  // small anyway, so fall back on shared memory plus a texture
  // 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;
  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,
                                      defaultRBSwap);
  return true;
}
/*static*/ PGrallocBufferParent*
GrallocBufferActor::Create(const gfxIntSize& aSize,
                           const gfxContentType& aContent,
                           MaybeMagicGrallocBufferHandle* aOutHandle)
{
  SAMPLE_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));
  if (buffer->initCheck() != OK)
    return actor;

  size_t bpp = gfxASurface::BytePerPixelFromFormat(
      gfxPlatform::GetPlatform()->OptimalFormatForContent(aContent));
  actor->mAllocBytes = aSize.width * aSize.height * bpp;
  sCurrentAlloc += actor->mAllocBytes;

  actor->mGraphicBuffer = buffer;
  *aOutHandle = MagicGrallocBufferHandle(buffer);
  return actor;
}
/*static*/ PGrallocBufferParent*
GrallocBufferActor::Create(const gfxIntSize& aSize,
                           const gfxContentType& aContent,
                           MaybeMagicGrallocBufferHandle* aOutHandle)
{
  SAMPLE_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));
  if (buffer->initCheck() != OK)
    return actor;

  actor->mGraphicBuffer = buffer;
  *aOutHandle = MagicGrallocBufferHandle(buffer);
  return actor;
}