Bug 1002823 - [Stingray] Add a new kind of image layer without graphic buffer for overlaying video input. r=nical

This commit is contained in:
chiajung hung 2014-08-18 22:14:00 -04:00
parent 0c24fa6846
commit 8e5b9fd3aa
22 changed files with 334 additions and 4 deletions

View File

@ -169,6 +169,7 @@ MOZ_BEGIN_ENUM_CLASS(CompositableType, uint8_t)
BUFFER_SIMPLE_TILED,
// the new compositable types
IMAGE, // image with single buffering
IMAGE_OVERLAY, // image without buffer
CONTENT_SINGLE, // thebes layer interface, single buffering
CONTENT_DOUBLE, // thebes layer interface, double buffering
BUFFER_COUNT

View File

@ -56,6 +56,10 @@ ImageFactory::CreateImage(ImageFormat aFormat,
img = new GrallocImage();
return img.forget();
}
if (aFormat == ImageFormat::OVERLAY_IMAGE) {
img = new OverlayImage();
return img.forget();
}
#endif
if (aFormat == ImageFormat::PLANAR_YCBCR) {
img = new PlanarYCbCrImage(aRecycleBin);
@ -146,6 +150,17 @@ ImageContainer::CreateImage(ImageFormat aFormat)
{
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
#ifdef MOZ_WIDGET_GONK
if (aFormat == ImageFormat::OVERLAY_IMAGE) {
if (mImageClient && mImageClient->GetTextureInfo().mCompositableType != CompositableType::IMAGE_OVERLAY) {
// If this ImageContainer is async but the image type mismatch, fix it here
if (ImageBridgeChild::IsCreated()) {
ImageBridgeChild::DispatchReleaseImageClient(mImageClient);
mImageClient = ImageBridgeChild::GetSingleton()->CreateImageClient(CompositableType::IMAGE_OVERLAY).drop();
}
}
}
#endif
if (mImageClient) {
nsRefPtr<Image> img = mImageClient->CreateImage(aFormat);
if (img) {

View File

@ -918,6 +918,39 @@ public:
RemoteImageData::Format mFormat;
};
#ifdef MOZ_WIDGET_GONK
class OverlayImage : public Image {
/**
* OverlayImage is a special Image type that does not hold any buffer.
* It only hold an Id as identifier to the real content of the Image.
* Therefore, OverlayImage must be handled by some specialized hardware(e.g. HWC)
* to show its content.
*/
public:
struct Data {
int32_t mOverlayId;
gfx::IntSize mSize;
};
OverlayImage() : Image(nullptr, ImageFormat::OVERLAY_IMAGE) { mOverlayId = INVALID_OVERLAY; }
void SetData(const Data& aData)
{
mOverlayId = aData.mOverlayId;
mSize = aData.mSize;
}
TemporaryRef<gfx::SourceSurface> GetAsSourceSurface() { return nullptr; } ;
int32_t GetOverlayId() { return mOverlayId; }
gfx::IntSize GetSize() { return mSize; }
private:
int32_t mOverlayId;
gfx::IntSize mSize;
};
#endif
} //namespace
} //namespace

View File

@ -71,7 +71,13 @@ MOZ_BEGIN_ENUM_CLASS(ImageFormat)
* The D3D9_RGB32_TEXTURE format creates a D3D9SurfaceImage, and wraps a
* IDirect3DTexture9 in RGB32 layout.
*/
D3D9_RGB32_TEXTURE
D3D9_RGB32_TEXTURE,
/**
* An Image type carries an opaque handle once for each stream.
* The opaque handle would be a platform specific identifier.
*/
OVERLAY_IMAGE
MOZ_END_ENUM_CLASS(ImageFormat)
MOZ_BEGIN_ENUM_CLASS(StereoMode)

View File

@ -32,6 +32,8 @@ struct PRLogModuleInfo;
# define MOZ_LAYERS_LOG_IF_SHADOWABLE(layer, _args)
#endif // if defined(DEBUG) || defined(PR_LOGGING)
#define INVALID_OVERLAY -1
namespace android {
class GraphicBuffer;
}
@ -93,6 +95,7 @@ struct LayerRenderState {
: mFlags(LayerRenderStateFlags::LAYER_RENDER_STATE_DEFAULT)
, mHasOwnOffset(false)
, mSurface(nullptr)
, mOverlayId(INVALID_OVERLAY)
, mTexture(nullptr)
#endif
{}
@ -105,6 +108,7 @@ struct LayerRenderState {
: mFlags(aFlags)
, mHasOwnOffset(false)
, mSurface(aSurface)
, mOverlayId(INVALID_OVERLAY)
, mSize(aSize)
, mTexture(aTexture)
{}
@ -117,6 +121,9 @@ struct LayerRenderState {
bool FormatRBSwapped() const
{ return bool(mFlags & LayerRenderStateFlags::FORMAT_RB_SWAP); }
void SetOverlayId(const int32_t& aId)
{ mOverlayId = aId; }
#endif
void SetOffset(const nsIntPoint& aOffset)
@ -134,7 +141,8 @@ struct LayerRenderState {
#ifdef MOZ_WIDGET_GONK
// surface to render
android::sp<android::GraphicBuffer> mSurface;
// size of mSurface
int32_t mOverlayId;
// size of mSurface
nsIntSize mSize;
TextureHost* mTexture;
#endif

View File

@ -110,6 +110,11 @@ protected:
#ifdef MOZ_WIDGET_GONK
// gralloc buffer needs CompositableType::BUFFER_IMAGE_BUFFERED to prevent
// the buffer's usage conflict.
if (autoLock.GetImage()->GetFormat() == ImageFormat::OVERLAY_IMAGE) {
mImageClientTypeContainer = CompositableType::IMAGE_OVERLAY;
return mImageClientTypeContainer;
}
mImageClientTypeContainer = autoLock.GetImage() ?
CompositableType::BUFFER_IMAGE_BUFFERED : CompositableType::BUFFER_UNKNOWN;
#else

View File

@ -61,6 +61,11 @@ ImageClient::CreateImageClient(CompositableType aCompositableHostType,
case CompositableType::BUFFER_UNKNOWN:
result = nullptr;
break;
#ifdef MOZ_WIDGET_GONK
case CompositableType::IMAGE_OVERLAY:
result = new ImageClientOverlay(aForwarder, aFlags);
break;
#endif
default:
MOZ_CRASH("unhandled program type");
}
@ -423,5 +428,55 @@ ImageClientSingle::CreateImage(ImageFormat aFormat)
}
}
#ifdef MOZ_WIDGET_GONK
ImageClientOverlay::ImageClientOverlay(CompositableForwarder* aFwd,
TextureFlags aFlags)
: ImageClient(aFwd, aFlags, CompositableType::IMAGE_OVERLAY)
{
}
bool
ImageClientOverlay::UpdateImage(ImageContainer* aContainer, uint32_t aContentFlags)
{
AutoLockImage autoLock(aContainer);
Image *image = autoLock.GetImage();
if (!image) {
return false;
}
if (mLastPaintedImageSerial == image->GetSerial()) {
return true;
}
AutoRemoveTexture autoRemoveTexture(this);
if (image->GetFormat() == ImageFormat::OVERLAY_IMAGE) {
OverlayImage* overlayImage = static_cast<OverlayImage*>(image);
uint32_t overlayId = overlayImage->GetOverlayId();
gfx::IntSize size = overlayImage->GetSize();
OverlaySource source;
source.handle() = OverlayHandle(overlayId);
source.size() = size;
GetForwarder()->UseOverlaySource(this, source);
}
UpdatePictureRect(image->GetPictureRect());
return true;
}
already_AddRefed<Image>
ImageClientOverlay::CreateImage(ImageFormat aFormat)
{
nsRefPtr<Image> img;
switch (aFormat) {
case ImageFormat::OVERLAY_IMAGE:
img = new OverlayImage();
return img.forget();
default:
return nullptr;
}
}
#endif
}
}

View File

@ -182,6 +182,29 @@ protected:
ShadowableLayer* mLayer;
};
#ifdef MOZ_WIDGET_GONK
/**
* And ImageClient to handle opaque video stream.
* Such video stream does not upload new Image for each frame.
* Gecko have no way to get the buffer content from the Image, since the Image
* does not contain the real buffer.
* It need special hardware to display the Image
*/
class ImageClientOverlay : public ImageClient
{
public:
ImageClientOverlay(CompositableForwarder* aFwd,
TextureFlags aFlags);
virtual bool UpdateImage(ImageContainer* aContainer, uint32_t aContentFlags);
virtual already_AddRefed<Image> CreateImage(ImageFormat aFormat);
TextureInfo GetTextureInfo() const MOZ_OVERRIDE
{
return TextureInfo(CompositableType::IMAGE_OVERLAY);
}
};
#endif
}
}

View File

@ -205,6 +205,11 @@ CompositableHost::Create(const TextureInfo& aTextureInfo)
case CompositableType::IMAGE:
result = new ImageHost(aTextureInfo);
break;
#ifdef MOZ_WIDGET_GONK
case CompositableType::IMAGE_OVERLAY:
result = new ImageHostOverlay(aTextureInfo);
break;
#endif
case CompositableType::CONTENT_SINGLE:
result = new ContentHostSingleBuffered(aTextureInfo);
break;

View File

@ -19,6 +19,7 @@
#include "mozilla/layers/CompositorTypes.h" // for TextureInfo, etc
#include "mozilla/layers/Effects.h" // for Texture Effect
#include "mozilla/layers/LayersTypes.h" // for LayerRenderState, etc
#include "mozilla/layers/LayersMessages.h"
#include "mozilla/layers/TextureHost.h" // for TextureHost
#include "mozilla/mozalloc.h" // for operator delete
#include "nsCOMPtr.h" // for already_AddRefed
@ -255,6 +256,7 @@ public:
virtual void UseTextureHost(TextureHost* aTexture);
virtual void UseComponentAlphaTextures(TextureHost* aTextureOnBlack,
TextureHost* aTextureOnWhite);
virtual void UseOverlaySource(OverlaySource aOverlay) { }
virtual void RemoveTextureHost(TextureHost* aTexture);

View File

@ -279,5 +279,82 @@ ImageHost::GenEffect(const gfx::Filter& aFilter)
isAlphaPremultiplied);
}
#ifdef MOZ_WIDGET_GONK
ImageHostOverlay::ImageHostOverlay(const TextureInfo& aTextureInfo)
: CompositableHost(aTextureInfo)
, mHasPictureRect(false)
{
}
ImageHostOverlay::~ImageHostOverlay()
{
}
void
ImageHostOverlay::Composite(EffectChain& aEffectChain,
float aOpacity,
const gfx::Matrix4x4& aTransform,
const gfx::Filter& aFilter,
const gfx::Rect& aClipRect,
const nsIntRegion* aVisibleRegion)
{
if (!GetCompositor()) {
return;
}
if (mOverlay.handle().type() == OverlayHandle::Tnull_t)
return;
Color hollow(0.0f, 0.0f, 0.0f, 0.0f);
aEffectChain.mPrimaryEffect = new EffectSolidColor(hollow);
aEffectChain.mSecondaryEffects[EffectTypes::BLEND_MODE] = new EffectBlendMode(CompositionOp::OP_SOURCE);
gfx::Rect rect;
gfx::Rect clipRect(aClipRect.x, aClipRect.y,
aClipRect.width, aClipRect.height);
if (mHasPictureRect) {
rect.SetRect(mPictureRect.x, mPictureRect.y,
mPictureRect.width, mPictureRect.height);
} else {
rect.SetRect(0, 0,
mOverlay.size().width, mOverlay.size().height);
}
mCompositor->DrawQuad(rect, aClipRect, aEffectChain, aOpacity, aTransform);
mCompositor->DrawDiagnostics(DiagnosticFlags::IMAGE | DiagnosticFlags::BIGIMAGE,
rect, aClipRect, aTransform, mFlashCounter);
}
LayerRenderState
ImageHostOverlay::GetRenderState()
{
LayerRenderState state;
if (mOverlay.handle().type() == OverlayHandle::Tint32_t) {
state.SetOverlayId(mOverlay.handle().get_int32_t());
}
return state;
}
void
ImageHostOverlay::UseOverlaySource(OverlaySource aOverlay)
{
mOverlay = aOverlay;
}
void
ImageHostOverlay::PrintInfo(std::stringstream& aStream, const char* aPrefix)
{
aStream << aPrefix;
aStream << nsPrintfCString("ImageHost (0x%p)", this).get();
AppendToString(aStream, mPictureRect, " [picture-rect=", "]");
if (mOverlay.handle().type() == OverlayHandle::Tint32_t) {
nsAutoCString pfx(aPrefix);
pfx += " ";
aStream << nsPrintfCString("Overlay: %d", mOverlay.handle().get_int32_t()).get();
}
}
#endif
}
}

View File

@ -94,6 +94,40 @@ protected:
bool mLocked;
};
#ifdef MOZ_WIDGET_GONK
/**
* ImageHostOverlay works with ImageClientOverlay
*/
class ImageHostOverlay : public CompositableHost {
public:
ImageHostOverlay(const TextureInfo& aTextureInfo);
~ImageHostOverlay();
virtual CompositableType GetType() { return mTextureInfo.mCompositableType; }
virtual void Composite(EffectChain& aEffectChain,
float aOpacity,
const gfx::Matrix4x4& aTransform,
const gfx::Filter& aFilter,
const gfx::Rect& aClipRect,
const nsIntRegion* aVisibleRegion = nullptr) MOZ_OVERRIDE;
virtual LayerRenderState GetRenderState() MOZ_OVERRIDE;
virtual void UseOverlaySource(OverlaySource aOverlay) MOZ_OVERRIDE;
virtual void SetPictureRect(const nsIntRect& aPictureRect) MOZ_OVERRIDE
{
mPictureRect = aPictureRect;
mHasPictureRect = true;
}
virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix);
protected:
nsIntRect mPictureRect;
bool mHasPictureRect;
OverlaySource mOverlay;
};
#endif
}
}

View File

@ -54,6 +54,7 @@ ImageLayerComposite::SetCompositableHost(CompositableHost* aHost)
case CompositableType::BUFFER_IMAGE_SINGLE:
case CompositableType::BUFFER_IMAGE_BUFFERED:
case CompositableType::IMAGE:
case CompositableType::IMAGE_OVERLAY:
mImageHost = aHost;
return true;
default:

View File

@ -106,6 +106,11 @@ public:
virtual void UpdatePictureRect(CompositableClient* aCompositable,
const nsIntRect& aRect) = 0;
#ifdef MOZ_WIDGET_GONK
virtual void UseOverlaySource(CompositableClient* aCompositabl,
const OverlaySource& aOverlay) = 0;
#endif
/**
* Tell the CompositableHost on the compositor side to remove the texture
* from the CompositableHost.

View File

@ -227,6 +227,15 @@ CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation
}
break;
}
#ifdef MOZ_WIDGET_GONK
case CompositableOperation::TOpUseOverlaySource: {
const OpUseOverlaySource& op = aEdit.get_OpUseOverlaySource();
CompositableHost* compositable = AsCompositable(op);
MOZ_ASSERT(compositable->GetType() == CompositableType::IMAGE_OVERLAY, "Invalid operation!");
compositable->UseOverlaySource(op.overlay());
break;
}
#endif
case CompositableOperation::TOpUpdateTexture: {
const OpUpdateTexture& op = aEdit.get_OpUpdateTexture();
RefPtr<TextureHost> texture = TextureHost::AsTextureHost(op.textureParent());

View File

@ -135,6 +135,16 @@ ImageBridgeChild::UseComponentAlphaTextures(CompositableClient* aCompositable,
nullptr, aTextureOnWhite->GetIPDLActor()));
}
#ifdef MOZ_WIDGET_GONK
void
ImageBridgeChild::UseOverlaySource(CompositableClient* aCompositable,
const OverlaySource& aOverlay)
{
MOZ_ASSERT(aCompositable);
mTxn->AddEdit(OpUseOverlaySource(nullptr, aCompositable->GetIPDLActor(), aOverlay));
}
#endif
void
ImageBridgeChild::UpdatedTexture(CompositableClient* aCompositable,
TextureClient* aTexture,

View File

@ -224,6 +224,10 @@ public:
virtual void UseComponentAlphaTextures(CompositableClient* aCompositable,
TextureClient* aClientOnBlack,
TextureClient* aClientOnWhite) MOZ_OVERRIDE;
#ifdef MOZ_WIDGET_GONK
virtual void UseOverlaySource(CompositableClient* aCompositable,
const OverlaySource& aOverlay) MOZ_OVERRIDE;
#endif
virtual void SendFenceHandle(AsyncTransactionTracker* aTracker,
PTextureChild* aTexture,

View File

@ -310,6 +310,11 @@ struct OpUseTiledLayerBuffer {
SurfaceDescriptorTiles tileLayerDescriptor;
};
struct OpUseOverlaySource {
PCompositable compositable;
OverlaySource overlay;
};
struct OpCreatedIncrementalTexture {
PCompositable compositable;
TextureInfo textureInfo;
@ -422,6 +427,7 @@ union CompositableOperation {
OpUpdateTexture;
OpUseTexture;
OpUseComponentAlphaTextures;
OpUseOverlaySource;
};
// A unit of a changeset; a set of these comprise a changeset

View File

@ -20,6 +20,16 @@ using gfxImageFormat from "gfxTypes.h";
namespace mozilla {
namespace layers {
union OverlayHandle {
int32_t;
null_t;
};
struct OverlaySource {
OverlayHandle handle;
IntSize size;
};
union MaybeMagicGrallocBufferHandle {
MagicGrallocBufferHandle;
GrallocBufferRef;

View File

@ -432,6 +432,16 @@ ShadowLayerForwarder::UseComponentAlphaTextures(CompositableClient* aCompositabl
nullptr, aTextureOnWhite->GetIPDLActor()));
}
#ifdef MOZ_WIDGET_GONK
void
ShadowLayerForwarder::UseOverlaySource(CompositableClient* aCompositable,
const OverlaySource& aOverlay)
{
MOZ_ASSERT(aCompositable);
mTxn->AddEdit(OpUseOverlaySource(nullptr, aCompositable->GetIPDLActor(), aOverlay));
}
#endif
void
ShadowLayerForwarder::SendFenceHandle(AsyncTransactionTracker* aTracker,
PTextureChild* aTexture,

View File

@ -287,7 +287,10 @@ public:
virtual void UseComponentAlphaTextures(CompositableClient* aCompositable,
TextureClient* aClientOnBlack,
TextureClient* aClientOnWhite) MOZ_OVERRIDE;
#ifdef MOZ_WIDGET_GONK
virtual void UseOverlaySource(CompositableClient* aCompositable,
const OverlaySource& aOverlay) MOZ_OVERRIDE;
#endif
virtual void SendFenceHandle(AsyncTransactionTracker* aTracker,
PTextureChild* aTexture,
const FenceHandle& aFence) MOZ_OVERRIDE;

View File

@ -976,6 +976,8 @@ static bool SetBlendMode(GLContext* aGL, gfx::CompositionOp aBlendMode, bool aIs
GLenum srcBlend;
GLenum dstBlend;
GLenum srcColorBlend = LOCAL_GL_ONE;
GLenum dstColorBlend = LOCAL_GL_ONE;
switch (aBlendMode) {
case gfx::CompositionOp::OP_OVER:
@ -993,13 +995,19 @@ static bool SetBlendMode(GLContext* aGL, gfx::CompositionOp aBlendMode, bool aIs
srcBlend = LOCAL_GL_DST_COLOR;
dstBlend = LOCAL_GL_ONE_MINUS_SRC_ALPHA;
break;
case gfx::CompositionOp::OP_SOURCE:
srcBlend = LOCAL_GL_ONE;
dstBlend = LOCAL_GL_ZERO;
srcColorBlend = LOCAL_GL_ONE;
dstColorBlend = LOCAL_GL_ZERO;
break;
default:
MOZ_ASSERT_UNREACHABLE("Unsupported blend mode!");
return false;
}
aGL->fBlendFuncSeparate(srcBlend, dstBlend,
LOCAL_GL_ONE, LOCAL_GL_ONE);
srcColorBlend, dstColorBlend);
return true;
}