Bug 1234472 - Add gonk sideband stream handling to gfx ipc r=nical

This commit is contained in:
Sotaro Ikeda 2016-01-05 20:50:39 -08:00
parent fa60969e08
commit 66491f2195
12 changed files with 316 additions and 21 deletions

View File

@ -15,6 +15,7 @@
#include "mozilla/ReentrantMonitor.h" // for ReentrantMonitorAutoEnter, etc #include "mozilla/ReentrantMonitor.h" // for ReentrantMonitorAutoEnter, etc
#include "mozilla/TimeStamp.h" // for TimeStamp #include "mozilla/TimeStamp.h" // for TimeStamp
#include "mozilla/gfx/Point.h" // For IntSize #include "mozilla/gfx/Point.h" // For IntSize
#include "mozilla/layers/GonkNativeHandle.h"
#include "mozilla/layers/LayersTypes.h" // for LayersBackend, etc #include "mozilla/layers/LayersTypes.h" // for LayersBackend, etc
#include "mozilla/mozalloc.h" // for operator delete, etc #include "mozilla/mozalloc.h" // for operator delete, etc
#include "nsAutoPtr.h" // for nsRefPtr, nsAutoArrayPtr, etc #include "nsAutoPtr.h" // for nsRefPtr, nsAutoArrayPtr, etc
@ -846,6 +847,11 @@ public:
gfx::IntSize mSize; gfx::IntSize mSize;
}; };
struct SidebandStreamData {
GonkNativeHandle mStream;
gfx::IntSize mSize;
};
OverlayImage() : Image(nullptr, ImageFormat::OVERLAY_IMAGE) { mOverlayId = INVALID_OVERLAY; } OverlayImage() : Image(nullptr, ImageFormat::OVERLAY_IMAGE) { mOverlayId = INVALID_OVERLAY; }
void SetData(const Data& aData) void SetData(const Data& aData)
@ -854,13 +860,21 @@ public:
mSize = aData.mSize; mSize = aData.mSize;
} }
void SetData(const SidebandStreamData& aData)
{
mSidebandStream = aData.mStream;
mSize = aData.mSize;
}
already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() { return nullptr; } ; already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() { return nullptr; } ;
int32_t GetOverlayId() { return mOverlayId; } int32_t GetOverlayId() { return mOverlayId; }
const GonkNativeHandle& GetSidebandStream() { return mSidebandStream; }
gfx::IntSize GetSize() { return mSize; } gfx::IntSize GetSize() { return mSize; }
private: private:
int32_t mOverlayId; int32_t mOverlayId;
GonkNativeHandle mSidebandStream;
gfx::IntSize mSize; gfx::IntSize mSize;
}; };
#endif #endif

View File

@ -10,9 +10,7 @@
#ifdef MOZ_WIDGET_GONK #ifdef MOZ_WIDGET_GONK
#include <utils/RefBase.h> #include <utils/RefBase.h>
#if ANDROID_VERSION >= 21 #include "mozilla/layers/GonkNativeHandle.h"
#include <utils/NativeHandle.h>
#endif
#endif #endif
#include "mozilla/gfx/Point.h" // for IntPoint #include "mozilla/gfx/Point.h" // for IntPoint
@ -116,13 +114,16 @@ struct LayerRenderState {
void SetOverlayId(const int32_t& aId) void SetOverlayId(const int32_t& aId)
{ mOverlayId = aId; } { mOverlayId = aId; }
void SetSidebandStream(const GonkNativeHandle& aStream)
{
mSidebandStream = aStream;
}
android::GraphicBuffer* GetGrallocBuffer() const android::GraphicBuffer* GetGrallocBuffer() const
{ return mSurface.get(); } { return mSurface.get(); }
#if ANDROID_VERSION >= 21 const GonkNativeHandle& GetSidebandStream()
android::NativeHandle* GetSidebandStream() const { return mSidebandStream; }
{ return mSidebandStream.get(); }
#endif
#endif #endif
void SetOffset(const nsIntPoint& aOffset) void SetOffset(const nsIntPoint& aOffset)
@ -146,9 +147,7 @@ struct LayerRenderState {
// size of mSurface // size of mSurface
gfx::IntSize mSize; gfx::IntSize mSize;
TextureHost* mTexture; TextureHost* mTexture;
#if ANDROID_VERSION >= 21 GonkNativeHandle mSidebandStream;
android::sp<android::NativeHandle> mSidebandStream;
#endif
#endif #endif
}; };

View File

@ -153,12 +153,13 @@ ImageClientSingle::UpdateImage(ImageContainer* aContainer, uint32_t aContentFlag
#ifdef MOZ_WIDGET_GONK #ifdef MOZ_WIDGET_GONK
if (image->GetFormat() == ImageFormat::OVERLAY_IMAGE) { if (image->GetFormat() == ImageFormat::OVERLAY_IMAGE) {
OverlayImage* overlayImage = static_cast<OverlayImage*>(image); OverlayImage* overlayImage = static_cast<OverlayImage*>(image);
uint32_t overlayId = overlayImage->GetOverlayId();
gfx::IntSize size = overlayImage->GetSize();
OverlaySource source; OverlaySource source;
source.handle() = OverlayHandle(overlayId); if (overlayImage->GetSidebandStream().IsValid()) {
source.size() = size; source.handle() = OverlayHandle(overlayImage->GetSidebandStream());
} else {
source.handle() = OverlayHandle(overlayImage->GetOverlayId());
}
source.size() = overlayImage->GetSize();
GetForwarder()->UseOverlaySource(this, source, image->GetPictureRect()); GetForwarder()->UseOverlaySource(this, source, image->GetPictureRect());
continue; continue;
} }

View File

@ -136,8 +136,7 @@ void
ImageHost::UseOverlaySource(OverlaySource aOverlay, ImageHost::UseOverlaySource(OverlaySource aOverlay,
const gfx::IntRect& aPictureRect) const gfx::IntRect& aPictureRect)
{ {
if ((aOverlay.handle().type() == OverlayHandle::Tint32_t) && if (ImageHostOverlay::IsValid(aOverlay)) {
aOverlay.handle().get_int32_t() != INVALID_OVERLAY) {
if (!mImageHostOverlay) { if (!mImageHostOverlay) {
mImageHostOverlay = new ImageHostOverlay(); mImageHostOverlay = new ImageHostOverlay();
} }
@ -590,6 +589,18 @@ ImageHostOverlay::~ImageHostOverlay()
MOZ_COUNT_DTOR(ImageHostOverlay); MOZ_COUNT_DTOR(ImageHostOverlay);
} }
/* static */ bool
ImageHostOverlay::IsValid(OverlaySource aOverlay)
{
if ((aOverlay.handle().type() == OverlayHandle::Tint32_t) &&
aOverlay.handle().get_int32_t() != INVALID_OVERLAY) {
return true;
} else if (aOverlay.handle().type() == OverlayHandle::TGonkNativeHandle) {
return true;
}
return false;
}
void void
ImageHostOverlay::Composite(Compositor* aCompositor, ImageHostOverlay::Composite(Compositor* aCompositor,
uint32_t aFlashCounter, uint32_t aFlashCounter,
@ -627,7 +638,11 @@ ImageHostOverlay::GetRenderState()
#ifdef MOZ_WIDGET_GONK #ifdef MOZ_WIDGET_GONK
if (mOverlay.handle().type() == OverlayHandle::Tint32_t) { if (mOverlay.handle().type() == OverlayHandle::Tint32_t) {
state.SetOverlayId(mOverlay.handle().get_int32_t()); state.SetOverlayId(mOverlay.handle().get_int32_t());
} else if (mOverlay.handle().type() == OverlayHandle::TGonkNativeHandle) {
state.SetSidebandStream(mOverlay.handle().get_GonkNativeHandle());
} }
state.mSize.width = mPictureRect.Width();
state.mSize.height = mPictureRect.Height();
#endif #endif
return state; return state;
} }

View File

@ -156,6 +156,8 @@ public:
NS_INLINE_DECL_REFCOUNTING(ImageHostOverlay) NS_INLINE_DECL_REFCOUNTING(ImageHostOverlay)
ImageHostOverlay(); ImageHostOverlay();
static bool IsValid(OverlaySource aOverlay);
virtual void Composite(Compositor* aCompositor, virtual void Composite(Compositor* aCompositor,
uint32_t aFlashCounter, uint32_t aFlashCounter,
LayerComposite* aLayer, LayerComposite* aLayer,

View File

@ -0,0 +1,67 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: sw=2 ts=8 et :
*/
/* 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 <unistd.h>
#include "GonkNativeHandle.h"
using namespace mozilla::layers;
namespace mozilla {
namespace layers {
GonkNativeHandle::GonkNativeHandle()
: mNhObj(new NhObj())
{
}
GonkNativeHandle::GonkNativeHandle(NhObj* aNhObj)
: mNhObj(aNhObj)
{
MOZ_ASSERT(aNhObj);
}
void
GonkNativeHandle::TransferToAnother(GonkNativeHandle& aHandle)
{
aHandle.mNhObj = this->GetAndResetNhObj();
}
already_AddRefed<GonkNativeHandle::NhObj>
GonkNativeHandle::GetAndResetNhObj()
{
RefPtr<NhObj> nhObj = mNhObj;
mNhObj = new NhObj();
return nhObj.forget();
}
already_AddRefed<GonkNativeHandle::NhObj>
GonkNativeHandle::GetDupNhObj()
{
RefPtr<NhObj> nhObj;
if (IsValid()) {
native_handle* nativeHandle =
native_handle_create(mNhObj->mHandle->numFds, mNhObj->mHandle->numInts);
for (int i = 0; i < mNhObj->mHandle->numFds; ++i) {
nativeHandle->data[i] = dup(mNhObj->mHandle->data[i]);
}
memcpy(nativeHandle->data + nativeHandle->numFds,
mNhObj->mHandle->data + mNhObj->mHandle->numFds,
sizeof(int) * mNhObj->mHandle->numInts);
nhObj = new GonkNativeHandle::NhObj(nativeHandle);
} else {
nhObj = new GonkNativeHandle::NhObj();
}
return nhObj.forget();
}
} // namespace layers
} // namespace mozilla

View File

@ -0,0 +1,95 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: sw=2 ts=8 et :
*/
/* 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 IPC_GonkNativeHandle_h
#define IPC_GonkNativeHandle_h
#ifdef MOZ_WIDGET_GONK
#include <cutils/native_handle.h>
#endif
#include "mozilla/RefPtr.h" // for RefPtr
#include "nsISupportsImpl.h"
namespace mozilla {
namespace layers {
#ifdef MOZ_WIDGET_GONK
// GonkNativeHandle wraps android's native_handle_t and is used to support
// android's sideband stream.
// The sideband stream is a device-specific mechanism for passing buffers
// to hwcomposer. It is used to render TV streams and DRM protected streams.
// The native_handle_t represents device-specific kernel objects on android.
class GonkNativeHandle {
public:
class NhObj {
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(NhObj)
friend class GonkNativeHandle;
public:
NhObj()
: mHandle(nullptr) {}
explicit NhObj(native_handle_t* aHandle)
: mHandle(aHandle) {}
native_handle_t* GetAndResetNativeHandle()
{
native_handle_t* handle = mHandle;
mHandle = nullptr;
return handle;
}
private:
virtual ~NhObj() {
if (mHandle) {
native_handle_close(mHandle);
native_handle_delete(mHandle);
}
}
native_handle_t* mHandle;
};
GonkNativeHandle();
explicit GonkNativeHandle(NhObj* aNhObj);
bool operator==(const GonkNativeHandle& aOther) const {
return mNhObj.get() == aOther.mNhObj.get();
}
bool IsValid() const
{
return mNhObj && mNhObj->mHandle;
}
void TransferToAnother(GonkNativeHandle& aHandle);
already_AddRefed<NhObj> GetAndResetNhObj();
already_AddRefed<NhObj> GetDupNhObj();
// Return non owning handle.
native_handle_t* GetRawNativeHandle() const
{
if (mNhObj) {
return mNhObj->mHandle;
}
return nullptr;
}
private:
RefPtr<NhObj> mNhObj;
};
#else
struct GonkNativeHandle {
bool operator==(const GonkNativeHandle&) const { return false; }
};
#endif
} // namespace layers
} // namespace mozilla
#endif // IPC_GonkNativeHandle_h

View File

@ -0,0 +1,60 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: sw=2 ts=8 et :
*/
/* 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 "GonkNativeHandleUtils.h"
using namespace mozilla::layers;
namespace IPC {
void
ParamTraits<GonkNativeHandle>::Write(Message* aMsg,
const paramType& aParam)
{
GonkNativeHandle handle = aParam;
MOZ_ASSERT(handle.IsValid());
RefPtr<GonkNativeHandle::NhObj> nhObj = handle.GetAndResetNhObj();
native_handle_t* nativeHandle = nhObj->GetAndResetNativeHandle();
aMsg->WriteSize(nativeHandle->numInts);
aMsg->WriteBytes((nativeHandle->data + nativeHandle->numFds), sizeof(int) * nativeHandle->numInts);
for (size_t i = 0; i < static_cast<size_t>(nativeHandle->numFds); ++i) {
aMsg->WriteFileDescriptor(base::FileDescriptor(nativeHandle->data[i], true));
}
}
bool
ParamTraits<GonkNativeHandle>::Read(const Message* aMsg,
void** aIter, paramType* aResult)
{
size_t numInts;
if (!aMsg->ReadSize(aIter, &numInts)) {
return false;
}
numInts /= sizeof(int);
size_t numFds = aMsg->num_fds();
native_handle* nativeHandle = native_handle_create(numFds, numInts);
const char* data = reinterpret_cast<const char*>(nativeHandle->data + nativeHandle->numFds);
if (!aMsg->ReadBytes(aIter, &data, numInts * sizeof(int))) {
return false;
}
for (size_t i = 0; i < static_cast<size_t>(nativeHandle->numFds); ++i) {
base::FileDescriptor fd;
if (!aMsg->ReadFileDescriptor(aIter, &fd)) {
return false;
}
nativeHandle->data[i] = fd.fd;
}
return true;
}
} // namespace IPC

View File

@ -0,0 +1,36 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: sw=2 ts=8 et :
*/
/* 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 IPC_GonkNativeHandleUtils_h
#define IPC_GonkNativeHandleUtils_h
#include "ipc/IPCMessageUtils.h"
#include "GonkNativeHandle.h"
namespace IPC {
#ifdef MOZ_WIDGET_GONK
template <>
struct ParamTraits<mozilla::layers::GonkNativeHandle> {
typedef mozilla::layers::GonkNativeHandle paramType;
static void Write(Message* aMsg, const paramType& aParam);
static bool Read(const Message* aMsg, void** aIter, paramType* aResult);
};
#else
template <>
struct ParamTraits<mozilla::layers::GonkNativeHandle> {
typedef mozilla::layers::GonkNativeHandle paramType;
static void Write(Message*, const paramType&) {}
static bool Read(const Message*, void**, paramType*) { return false; }
};
#endif
} // namespace IPC
#endif // IPC_GonkNativeHandleUtils_h

View File

@ -14,12 +14,14 @@ using mozilla::gfx::SurfaceFormat from "mozilla/gfx/Types.h";
using mozilla::gfx::IntRect from "mozilla/gfx/Rect.h"; using mozilla::gfx::IntRect from "mozilla/gfx/Rect.h";
using mozilla::gfx::IntSize from "mozilla/gfx/Point.h"; using mozilla::gfx::IntSize from "mozilla/gfx/Point.h";
using gfxImageFormat from "gfxTypes.h"; using gfxImageFormat from "gfxTypes.h";
using struct mozilla::layers::GonkNativeHandle from "mozilla/layers/GonkNativeHandleUtils.h";
namespace mozilla { namespace mozilla {
namespace layers { namespace layers {
union OverlayHandle { union OverlayHandle {
int32_t; int32_t;
GonkNativeHandle;
null_t; null_t;
}; };

View File

@ -153,6 +153,8 @@ EXPORTS.mozilla.layers += [
'ipc/CompositorLRU.h', 'ipc/CompositorLRU.h',
'ipc/CompositorParent.h', 'ipc/CompositorParent.h',
'ipc/FenceUtils.h', 'ipc/FenceUtils.h',
'ipc/GonkNativeHandle.h',
'ipc/GonkNativeHandleUtils.h',
'ipc/ImageBridgeChild.h', 'ipc/ImageBridgeChild.h',
'ipc/ImageBridgeParent.h', 'ipc/ImageBridgeParent.h',
'ipc/ImageContainerParent.h', 'ipc/ImageContainerParent.h',
@ -237,6 +239,8 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
] ]
] ]
SOURCES += [ SOURCES += [
'ipc/GonkNativeHandle.cpp',
'ipc/GonkNativeHandleUtils.cpp',
'ipc/ShadowLayerUtilsGralloc.cpp', 'ipc/ShadowLayerUtilsGralloc.cpp',
] ]

View File

@ -353,7 +353,7 @@ HwcComposer2D::PrepareLayerList(Layer* aLayer,
LayerRenderState state = aLayer->GetRenderState(); LayerRenderState state = aLayer->GetRenderState();
#if ANDROID_VERSION >= 21 #if ANDROID_VERSION >= 21
if (!state.GetGrallocBuffer() && !state.GetSidebandStream()) { if (!state.GetGrallocBuffer() && !state.GetSidebandStream().IsValid()) {
#else #else
if (!state.GetGrallocBuffer()) { if (!state.GetGrallocBuffer()) {
#endif #endif
@ -450,8 +450,8 @@ HwcComposer2D::PrepareLayerList(Layer* aLayer,
mHal->SetCrop(hwcLayer, sourceCrop); mHal->SetCrop(hwcLayer, sourceCrop);
buffer_handle_t handle = nullptr; buffer_handle_t handle = nullptr;
#if ANDROID_VERSION >= 21 #if ANDROID_VERSION >= 21
if (state.GetSidebandStream()) { if (state.GetSidebandStream().IsValid()) {
handle = state.GetSidebandStream()->handle(); handle = state.GetSidebandStream().GetRawNativeHandle();
} else if (state.GetGrallocBuffer()) { } else if (state.GetGrallocBuffer()) {
handle = state.GetGrallocBuffer()->getNativeBuffer()->handle; handle = state.GetGrallocBuffer()->getNativeBuffer()->handle;
} }
@ -468,7 +468,7 @@ HwcComposer2D::PrepareLayerList(Layer* aLayer,
#if ANDROID_VERSION >= 17 #if ANDROID_VERSION >= 17
hwcLayer.compositionType = HWC_FRAMEBUFFER; hwcLayer.compositionType = HWC_FRAMEBUFFER;
#if ANDROID_VERSION >= 21 #if ANDROID_VERSION >= 21
if (state.GetSidebandStream()) { if (state.GetSidebandStream().IsValid()) {
hwcLayer.compositionType = HWC_SIDEBAND; hwcLayer.compositionType = HWC_SIDEBAND;
} }
#endif #endif