mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 957323 - Handle android's fence on gonk r=nical,doublec,pchang
This commit is contained in:
parent
4ef6fc1b7b
commit
c0ff94d478
@ -15,6 +15,9 @@
|
||||
#include <stagefright/OMXClient.h>
|
||||
#include <stagefright/OMXCodec.h>
|
||||
#include <OMX.h>
|
||||
#if MOZ_WIDGET_GONK && ANDROID_VERSION >= 18
|
||||
#include <ui/Fence.h>
|
||||
#endif
|
||||
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Types.h"
|
||||
@ -213,7 +216,7 @@ VideoGraphicBuffer::Unlock()
|
||||
// The message is delivered to OmxDecoder on ALooper thread.
|
||||
// MediaBuffer::release() could take a very long time.
|
||||
// PostReleaseVideoBuffer() prevents long time locking.
|
||||
omxDecoder->PostReleaseVideoBuffer(mMediaBuffer);
|
||||
omxDecoder->PostReleaseVideoBuffer(mMediaBuffer, mReleaseFenceHandle);
|
||||
} else {
|
||||
NS_WARNING("OmxDecoder is not present");
|
||||
if (mMediaBuffer) {
|
||||
@ -794,7 +797,7 @@ bool OmxDecoder::ReadVideo(VideoFrame *aFrame, int64_t aTimeUs,
|
||||
{
|
||||
Mutex::Autolock autoLock(mSeekLock);
|
||||
mIsVideoSeeking = false;
|
||||
ReleaseAllPendingVideoBuffersLocked();
|
||||
PostReleaseVideoBuffer(nullptr, FenceHandle());
|
||||
}
|
||||
|
||||
aDoSeek = false;
|
||||
@ -841,6 +844,9 @@ bool OmxDecoder::ReadVideo(VideoFrame *aFrame, int64_t aTimeUs,
|
||||
aFrame->mKeyFrame = keyFrame;
|
||||
aFrame->Y.mWidth = mVideoWidth;
|
||||
aFrame->Y.mHeight = mVideoHeight;
|
||||
// Release to hold video buffer in OmxDecoder more.
|
||||
// MediaBuffer's ref count is changed from 2 to 1.
|
||||
ReleaseVideoBuffer();
|
||||
} else if (mVideoBuffer->range_length() > 0) {
|
||||
char *data = static_cast<char *>(mVideoBuffer->data()) + mVideoBuffer->range_offset();
|
||||
size_t length = mVideoBuffer->range_length();
|
||||
@ -1022,11 +1028,13 @@ void OmxDecoder::onMessageReceived(const sp<AMessage> &msg)
|
||||
}
|
||||
}
|
||||
|
||||
void OmxDecoder::PostReleaseVideoBuffer(MediaBuffer *aBuffer)
|
||||
void OmxDecoder::PostReleaseVideoBuffer(MediaBuffer *aBuffer, const FenceHandle& aReleaseFenceHandle)
|
||||
{
|
||||
{
|
||||
Mutex::Autolock autoLock(mPendingVideoBuffersLock);
|
||||
mPendingVideoBuffers.push(aBuffer);
|
||||
if (aBuffer) {
|
||||
mPendingVideoBuffers.push(BufferItem(aBuffer, aReleaseFenceHandle));
|
||||
}
|
||||
}
|
||||
|
||||
sp<AMessage> notify =
|
||||
@ -1037,14 +1045,13 @@ void OmxDecoder::PostReleaseVideoBuffer(MediaBuffer *aBuffer)
|
||||
|
||||
void OmxDecoder::ReleaseAllPendingVideoBuffersLocked()
|
||||
{
|
||||
Vector<MediaBuffer *> releasingVideoBuffers;
|
||||
Vector<BufferItem> releasingVideoBuffers;
|
||||
{
|
||||
Mutex::Autolock autoLock(mPendingVideoBuffersLock);
|
||||
|
||||
int size = mPendingVideoBuffers.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
MediaBuffer *buffer = mPendingVideoBuffers[i];
|
||||
releasingVideoBuffers.push(buffer);
|
||||
releasingVideoBuffers.push(mPendingVideoBuffers[i]);
|
||||
}
|
||||
mPendingVideoBuffers.clear();
|
||||
}
|
||||
@ -1052,7 +1059,28 @@ void OmxDecoder::ReleaseAllPendingVideoBuffersLocked()
|
||||
int size = releasingVideoBuffers.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
MediaBuffer *buffer;
|
||||
buffer = releasingVideoBuffers[i];
|
||||
buffer = releasingVideoBuffers[i].mMediaBuffer;
|
||||
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 18
|
||||
android::sp<Fence> fence;
|
||||
int fenceFd = -1;
|
||||
fence = releasingVideoBuffers[i].mReleaseFenceHandle.mFence;
|
||||
if (fence.get() && fence->isValid()) {
|
||||
fenceFd = fence->dup();
|
||||
}
|
||||
MOZ_ASSERT(buffer->refcount() == 1);
|
||||
// This code expect MediaBuffer's ref count is 1.
|
||||
// Return gralloc buffer to ANativeWindow
|
||||
ANativeWindow* window = static_cast<ANativeWindow*>(mNativeWindowClient.get());
|
||||
window->cancelBuffer(window,
|
||||
buffer->graphicBuffer().get(),
|
||||
fenceFd);
|
||||
// Mark MediaBuffer as rendered.
|
||||
// When gralloc buffer is directly returned to ANativeWindow,
|
||||
// this mark is necesary.
|
||||
sp<MetaData> metaData = buffer->meta_data();
|
||||
metaData->setInt32(kKeyRendered, 1);
|
||||
#endif
|
||||
// Return MediaBuffer to OMXCodec.
|
||||
buffer->release();
|
||||
}
|
||||
releasingVideoBuffers.clear();
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "GonkNativeWindow.h"
|
||||
#include "GonkNativeWindowClient.h"
|
||||
#include "GrallocImages.h"
|
||||
#include "mozilla/layers/FenceUtils.h"
|
||||
#include "MP3FrameParser.h"
|
||||
#include "MPAPI.h"
|
||||
#include "MediaResource.h"
|
||||
@ -83,6 +84,7 @@ class OmxDecoder : public OMXCodecProxy::EventListener {
|
||||
typedef mozilla::MP3FrameParser MP3FrameParser;
|
||||
typedef mozilla::MediaResource MediaResource;
|
||||
typedef mozilla::AbstractMediaDecoder AbstractMediaDecoder;
|
||||
typedef mozilla::layers::FenceHandle FenceHandle;
|
||||
|
||||
enum {
|
||||
kPreferSoftwareCodecs = 1,
|
||||
@ -122,11 +124,26 @@ class OmxDecoder : public OMXCodecProxy::EventListener {
|
||||
MediaBuffer *mVideoBuffer;
|
||||
MediaBuffer *mAudioBuffer;
|
||||
|
||||
struct BufferItem {
|
||||
BufferItem()
|
||||
: mMediaBuffer(nullptr)
|
||||
{
|
||||
}
|
||||
BufferItem(MediaBuffer* aMediaBuffer, const FenceHandle& aReleaseFenceHandle)
|
||||
: mMediaBuffer(aMediaBuffer)
|
||||
, mReleaseFenceHandle(aReleaseFenceHandle) {
|
||||
}
|
||||
|
||||
MediaBuffer* mMediaBuffer;
|
||||
// a fence will signal when the current buffer is no longer being read.
|
||||
FenceHandle mReleaseFenceHandle;
|
||||
};
|
||||
|
||||
// Hold video's MediaBuffers that are released during video seeking.
|
||||
// The holded MediaBuffers are released soon after seek completion.
|
||||
// OMXCodec does not accept MediaBuffer during seeking. If MediaBuffer is
|
||||
// returned to OMXCodec during seeking, OMXCodec calls assert.
|
||||
Vector<MediaBuffer *> mPendingVideoBuffers;
|
||||
Vector<BufferItem> mPendingVideoBuffers;
|
||||
// The lock protects mPendingVideoBuffers.
|
||||
Mutex mPendingVideoBuffersLock;
|
||||
|
||||
@ -235,7 +252,7 @@ public:
|
||||
void Pause();
|
||||
|
||||
// Post kNotifyPostReleaseVideoBuffer message to OmxDecoder via ALooper.
|
||||
void PostReleaseVideoBuffer(MediaBuffer *aBuffer);
|
||||
void PostReleaseVideoBuffer(MediaBuffer *aBuffer, const FenceHandle& aReleaseFenceHandle);
|
||||
// Receive a message from AHandlerReflector.
|
||||
// Called on ALooper thread.
|
||||
void onMessageReceived(const sp<AMessage> &msg);
|
||||
|
@ -8,11 +8,12 @@
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
|
||||
#include "mozilla/layers/AtomicRefCountedWithFinalize.h"
|
||||
#include "mozilla/layers/LayersSurfaces.h"
|
||||
#include "mozilla/gfx/Point.h"
|
||||
#include "ImageLayers.h"
|
||||
#include "ImageContainer.h"
|
||||
#include "mozilla/gfx/Point.h"
|
||||
#include "mozilla/layers/AtomicRefCountedWithFinalize.h"
|
||||
#include "mozilla/layers/FenceUtils.h"
|
||||
#include "mozilla/layers/LayersSurfaces.h"
|
||||
|
||||
#include <ui/GraphicBuffer.h>
|
||||
|
||||
@ -46,6 +47,16 @@ public:
|
||||
return mSurfaceDescriptor;
|
||||
}
|
||||
|
||||
void SetReleaseFenceHandle(const FenceHandle& aReleaseFenceHandle)
|
||||
{
|
||||
mReleaseFenceHandle = aReleaseFenceHandle;
|
||||
}
|
||||
|
||||
const FenceHandle& GetReleaseFenceHandle() const
|
||||
{
|
||||
return mReleaseFenceHandle;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void Unlock() {}
|
||||
|
||||
@ -65,6 +76,7 @@ private:
|
||||
|
||||
protected:
|
||||
SurfaceDescriptor mSurfaceDescriptor;
|
||||
FenceHandle mReleaseFenceHandle;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -38,6 +38,7 @@ class GraphicBuffer;
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class TextureHost;
|
||||
|
||||
typedef uint32_t TextureFlags;
|
||||
|
||||
@ -88,18 +89,20 @@ enum LayerRenderStateFlags {
|
||||
struct LayerRenderState {
|
||||
LayerRenderState()
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
: mSurface(nullptr), mFlags(0), mHasOwnOffset(false)
|
||||
: mSurface(nullptr), mFlags(0), mHasOwnOffset(false), mTexture(nullptr)
|
||||
#endif
|
||||
{}
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
LayerRenderState(android::GraphicBuffer* aSurface,
|
||||
const nsIntSize& aSize,
|
||||
uint32_t aFlags)
|
||||
uint32_t aFlags,
|
||||
TextureHost* aTexture)
|
||||
: mSurface(aSurface)
|
||||
, mSize(aSize)
|
||||
, mFlags(aFlags)
|
||||
, mHasOwnOffset(false)
|
||||
, mTexture(aTexture)
|
||||
{}
|
||||
|
||||
bool YFlipped() const
|
||||
@ -123,6 +126,7 @@ struct LayerRenderState {
|
||||
android::sp<android::GraphicBuffer> mSurface;
|
||||
// size of mSurface
|
||||
nsIntSize mSize;
|
||||
TextureHost* mTexture;
|
||||
#endif
|
||||
// see LayerRenderStateFlags
|
||||
uint32_t mFlags;
|
||||
|
@ -378,6 +378,20 @@ ClientLayerManager::ForwardTransaction(bool aScheduleComposite)
|
||||
->SetDescriptorFromReply(ots.textureId(), ots.image());
|
||||
break;
|
||||
}
|
||||
case EditReply::TReturnReleaseFence: {
|
||||
const ReturnReleaseFence& rep = reply.get_ReturnReleaseFence();
|
||||
FenceHandle fence = rep.fence();
|
||||
PTextureChild* child = rep.textureChild();
|
||||
|
||||
if (!fence.IsValid() || !child) {
|
||||
break;
|
||||
}
|
||||
RefPtr<TextureClient> texture = TextureClient::AsTextureClient(child);
|
||||
if (texture) {
|
||||
texture->SetReleaseFenceHandle(fence);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
NS_RUNTIMEABORT("not reached");
|
||||
|
@ -20,7 +20,6 @@
|
||||
#include "mozilla/layers/ShadowLayers.h" // for ShadowLayerForwarder
|
||||
#include "mozilla/layers/SharedPlanarYCbCrImage.h"
|
||||
#include "mozilla/layers/YCbCrImageDataSerializer.h"
|
||||
#include "mozilla/layers/PTextureChild.h"
|
||||
#include "nsDebug.h" // for NS_ASSERTION, NS_WARNING, etc
|
||||
#include "nsTraceRefcnt.h" // for MOZ_COUNT_CTOR, etc
|
||||
#include "ImageContainer.h" // for PlanarYCbCrImage, etc
|
||||
@ -159,6 +158,13 @@ TextureClient::DestroyIPDLActor(PTextureChild* actor)
|
||||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
TextureClient*
|
||||
TextureClient::AsTextureClient(PTextureChild* actor)
|
||||
{
|
||||
return actor? static_cast<TextureChild*>(actor)->mTextureClient : nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
TextureClient::InitIPDLActor(CompositableForwarder* aForwarder)
|
||||
{
|
||||
|
@ -17,10 +17,12 @@
|
||||
#include "mozilla/gfx/2D.h" // for DrawTarget
|
||||
#include "mozilla/gfx/Point.h" // for IntSize
|
||||
#include "mozilla/gfx/Types.h" // for SurfaceFormat
|
||||
#include "mozilla/layers/FenceUtils.h" // for FenceHandle
|
||||
#include "mozilla/ipc/Shmem.h" // for Shmem
|
||||
#include "mozilla/layers/AtomicRefCountedWithFinalize.h"
|
||||
#include "mozilla/layers/CompositorTypes.h" // for TextureFlags, etc
|
||||
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor
|
||||
#include "mozilla/layers/PTextureChild.h" // for PTextureChild
|
||||
#include "mozilla/mozalloc.h" // for operator delete
|
||||
#include "nsAutoPtr.h" // for nsRefPtr
|
||||
#include "nsCOMPtr.h" // for already_AddRefed
|
||||
@ -230,6 +232,11 @@ public:
|
||||
static PTextureChild* CreateIPDLActor();
|
||||
static bool DestroyIPDLActor(PTextureChild* actor);
|
||||
|
||||
/**
|
||||
* Get the TextureClient corresponding to the actor passed in parameter.
|
||||
*/
|
||||
static TextureClient* AsTextureClient(PTextureChild* actor);
|
||||
|
||||
virtual bool IsAllocated() const = 0;
|
||||
|
||||
virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aDescriptor) = 0;
|
||||
@ -287,6 +294,13 @@ public:
|
||||
*/
|
||||
void ForceRemove();
|
||||
|
||||
virtual void SetReleaseFenceHandle(FenceHandle aReleaseFenceHandle) {}
|
||||
|
||||
const FenceHandle& GetReleaseFenceHandle() const
|
||||
{
|
||||
return mReleaseFenceHandle;
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* Called once, just before the destructor.
|
||||
@ -325,6 +339,7 @@ protected:
|
||||
TextureFlags mFlags;
|
||||
bool mShared;
|
||||
bool mValid;
|
||||
FenceHandle mReleaseFenceHandle;
|
||||
|
||||
friend class TextureChild;
|
||||
};
|
||||
|
@ -36,6 +36,9 @@ CompositableHost::CompositableHost(const TextureInfo& aTextureInfo)
|
||||
CompositableHost::~CompositableHost()
|
||||
{
|
||||
MOZ_COUNT_DTOR(CompositableHost);
|
||||
if (mBackendData) {
|
||||
mBackendData->ClearData();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -62,6 +65,8 @@ CompositableHost::UseComponentAlphaTextures(TextureHost* aTextureOnBlack,
|
||||
void
|
||||
CompositableHost::RemoveTextureHost(TextureHost* aTexture)
|
||||
{
|
||||
// Clear strong refrence to CompositableBackendSpecificData
|
||||
aTexture->SetCompositableBackendSpecificData(nullptr);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "mozilla/layers/CompositorTypes.h" // for TextureInfo, etc
|
||||
#include "mozilla/layers/LayersTypes.h" // for LayerRenderState, etc
|
||||
#include "mozilla/layers/PCompositableParent.h"
|
||||
#include "mozilla/layers/TextureHost.h" // for TextureHost
|
||||
#include "mozilla/mozalloc.h" // for operator delete
|
||||
#include "nsCOMPtr.h" // for already_AddRefed
|
||||
#include "nsRegion.h" // for nsIntRegion
|
||||
@ -46,7 +47,6 @@ struct TiledLayerProperties
|
||||
|
||||
class Layer;
|
||||
class DeprecatedTextureHost;
|
||||
class TextureHost;
|
||||
class SurfaceDescriptor;
|
||||
class Compositor;
|
||||
class ISurfaceAllocator;
|
||||
@ -70,7 +70,45 @@ public:
|
||||
MOZ_COUNT_DTOR(CompositableBackendSpecificData);
|
||||
}
|
||||
virtual void SetCompositor(Compositor* aCompositor) {}
|
||||
virtual void ClearData() {}
|
||||
virtual void ClearData()
|
||||
{
|
||||
mCurrentReleaseFenceTexture = nullptr;
|
||||
ClearPendingReleaseFenceTextureList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a texture currently used for Composition.
|
||||
* This function is called when the texutre might receive ReleaseFence
|
||||
* as a result of Composition.
|
||||
*/
|
||||
void SetCurrentReleaseFenceTexture(TextureHost* aTexture)
|
||||
{
|
||||
if (mCurrentReleaseFenceTexture) {
|
||||
mPendingReleaseFenceTextures.push_back(mCurrentReleaseFenceTexture);
|
||||
}
|
||||
mCurrentReleaseFenceTexture = aTexture;
|
||||
}
|
||||
|
||||
virtual std::vector< RefPtr<TextureHost> >& GetPendingReleaseFenceTextureList()
|
||||
{
|
||||
return mPendingReleaseFenceTextures;
|
||||
}
|
||||
|
||||
virtual void ClearPendingReleaseFenceTextureList()
|
||||
{
|
||||
return mPendingReleaseFenceTextures.clear();
|
||||
}
|
||||
protected:
|
||||
/**
|
||||
* Store a TextureHost currently used for Composition
|
||||
* and it might receive ReleaseFence for the texutre.
|
||||
*/
|
||||
RefPtr<TextureHost> mCurrentReleaseFenceTexture;
|
||||
/**
|
||||
* Store TextureHosts that might have ReleaseFence to be delivered
|
||||
* to TextureClient by CompositableHost.
|
||||
*/
|
||||
std::vector< RefPtr<TextureHost> > mPendingReleaseFenceTextures;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -89,6 +89,12 @@ TextureHost::AsTextureHost(PTextureParent* actor)
|
||||
return actor? static_cast<TextureParent*>(actor)->mTextureHost : nullptr;
|
||||
}
|
||||
|
||||
PTextureParent*
|
||||
TextureHost::GetIPDLActor()
|
||||
{
|
||||
return mActor;
|
||||
}
|
||||
|
||||
// implemented in TextureOGL.cpp
|
||||
TemporaryRef<DeprecatedTextureHost> CreateDeprecatedTextureHostOGL(SurfaceDescriptorType aDescriptorType,
|
||||
uint32_t aDeprecatedTextureHostFlags,
|
||||
@ -242,7 +248,8 @@ TextureHost::SetCompositableBackendSpecificData(CompositableBackendSpecificData*
|
||||
|
||||
|
||||
TextureHost::TextureHost(TextureFlags aFlags)
|
||||
: mFlags(aFlags)
|
||||
: mActor(nullptr)
|
||||
, mFlags(aFlags)
|
||||
{}
|
||||
|
||||
TextureHost::~TextureHost()
|
||||
@ -723,6 +730,7 @@ TextureParent::Init(const SurfaceDescriptor& aSharedData,
|
||||
mTextureHost = TextureHost::Create(aSharedData,
|
||||
mAllocator,
|
||||
aFlags);
|
||||
mTextureHost->mActor = this;
|
||||
return !!mTextureHost;
|
||||
}
|
||||
|
||||
@ -760,6 +768,8 @@ TextureParent::ActorDestroy(ActorDestroyReason why)
|
||||
if (mTextureHost->GetFlags() & TEXTURE_DEALLOCATE_CLIENT) {
|
||||
mTextureHost->ForgetSharedData();
|
||||
}
|
||||
|
||||
mTextureHost->mActor = nullptr;
|
||||
mTextureHost = nullptr;
|
||||
}
|
||||
|
||||
|
@ -43,6 +43,7 @@ class CompositableHost;
|
||||
class CompositableBackendSpecificData;
|
||||
class SurfaceDescriptor;
|
||||
class ISurfaceAllocator;
|
||||
class TextureHostOGL;
|
||||
class TextureSourceOGL;
|
||||
class TextureSourceD3D9;
|
||||
class TextureSourceD3D11;
|
||||
@ -273,7 +274,6 @@ class TextureHost
|
||||
void Finalize();
|
||||
|
||||
friend class AtomicRefCountedWithFinalize<TextureHost>;
|
||||
|
||||
public:
|
||||
TextureHost(TextureFlags aFlags);
|
||||
|
||||
@ -395,6 +395,14 @@ public:
|
||||
*/
|
||||
static TextureHost* AsTextureHost(PTextureParent* actor);
|
||||
|
||||
/**
|
||||
* Return a pointer to the IPDLActor.
|
||||
*
|
||||
* This is to be used with IPDL messages only. Do not store the returned
|
||||
* pointer.
|
||||
*/
|
||||
PTextureParent* GetIPDLActor();
|
||||
|
||||
/**
|
||||
* Specific to B2G's Composer2D
|
||||
* XXX - more doc here
|
||||
@ -418,9 +426,17 @@ public:
|
||||
virtual const char *Name() { return "TextureHost"; }
|
||||
virtual void PrintInfo(nsACString& aTo, const char* aPrefix);
|
||||
|
||||
/**
|
||||
* Cast to a TextureHost for each backend.
|
||||
*/
|
||||
virtual TextureHostOGL* AsHostOGL() { return nullptr; }
|
||||
|
||||
protected:
|
||||
PTextureParent* mActor;
|
||||
TextureFlags mFlags;
|
||||
RefPtr<CompositableBackendSpecificData> mCompositableBackendData;
|
||||
|
||||
friend class TextureParent;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "CompositableTransactionParent.h"
|
||||
#include "CompositableHost.h" // for CompositableParent, etc
|
||||
#include "CompositorParent.h" // for CompositorParent
|
||||
#include "GLContext.h" // for GLContext
|
||||
#include "Layers.h" // for Layer
|
||||
#include "RenderTrace.h" // for RenderTraceInvalidateEnd, etc
|
||||
#include "TiledLayerBuffer.h" // for TiledLayerComposer
|
||||
@ -19,6 +20,7 @@
|
||||
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor
|
||||
#include "mozilla/layers/LayersTypes.h" // for MOZ_LAYERS_LOG
|
||||
#include "mozilla/layers/TextureHost.h" // for TextureHost
|
||||
#include "mozilla/layers/TextureHostOGL.h" // for TextureHostOGL
|
||||
#include "mozilla/layers/ThebesLayerComposite.h"
|
||||
#include "mozilla/mozalloc.h" // for operator delete
|
||||
#include "nsDebug.h" // for NS_WARNING, NS_ASSERTION
|
||||
@ -159,6 +161,8 @@ CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation
|
||||
RenderTraceInvalidateEnd(layer, "FF00FF");
|
||||
}
|
||||
|
||||
// return texure data to client if necessary
|
||||
ReturnTextureDataIfNecessary(compositable, replyv, op.compositableParent());
|
||||
break;
|
||||
}
|
||||
case CompositableOperation::TOpPaintTextureRegion: {
|
||||
@ -190,6 +194,8 @@ CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation
|
||||
OpContentBufferSwap(compositableParent, nullptr, frontUpdatedRegion));
|
||||
|
||||
RenderTraceInvalidateEnd(thebes, "FF00FF");
|
||||
// return texure data to client if necessary
|
||||
ReturnTextureDataIfNecessary(compositable, replyv, op.compositableParent());
|
||||
break;
|
||||
}
|
||||
case CompositableOperation::TOpPaintTextureIncremental: {
|
||||
@ -239,6 +245,8 @@ CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation
|
||||
|
||||
MOZ_ASSERT(tex.get());
|
||||
compositable->RemoveTextureHost(tex);
|
||||
// return texure data to client if necessary
|
||||
ReturnTextureDataIfNecessary(compositable, replyv, op.compositableParent());
|
||||
break;
|
||||
}
|
||||
case CompositableOperation::TOpUseTexture: {
|
||||
@ -257,6 +265,8 @@ CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation
|
||||
compositable->GetLayer()->SetInvalidRectToVisibleRegion();
|
||||
}
|
||||
}
|
||||
// return texure data to client if necessary
|
||||
ReturnTextureDataIfNecessary(compositable, replyv, op.compositableParent());
|
||||
break;
|
||||
}
|
||||
case CompositableOperation::TOpUseComponentAlphaTextures: {
|
||||
@ -271,6 +281,8 @@ CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation
|
||||
if (IsAsync()) {
|
||||
ScheduleComposition(op);
|
||||
}
|
||||
// return texure data to client if necessary
|
||||
ReturnTextureDataIfNecessary(compositable, replyv, op.compositableParent());
|
||||
break;
|
||||
}
|
||||
case CompositableOperation::TOpUpdateTexture: {
|
||||
@ -281,7 +293,6 @@ CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation
|
||||
texture->Updated(op.region().type() == MaybeRegion::TnsIntRegion
|
||||
? &op.region().get_nsIntRegion()
|
||||
: nullptr); // no region means invalidate the entire surface
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@ -293,6 +304,54 @@ CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation
|
||||
return true;
|
||||
}
|
||||
|
||||
#if MOZ_WIDGET_GONK && ANDROID_VERSION >= 18
|
||||
void
|
||||
CompositableParentManager::ReturnTextureDataIfNecessary(CompositableHost* aCompositable,
|
||||
EditReplyVector& replyv,
|
||||
PCompositableParent* aParent)
|
||||
{
|
||||
if (!aCompositable || !aCompositable->GetCompositableBackendSpecificData()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const std::vector< RefPtr<TextureHost> > textureList =
|
||||
aCompositable->GetCompositableBackendSpecificData()->GetPendingReleaseFenceTextureList();
|
||||
// Return pending Texture data
|
||||
for (size_t i = 0; i < textureList.size(); i++) {
|
||||
TextureHostOGL* hostOGL = textureList[i]->AsHostOGL();
|
||||
PTextureParent* actor = textureList[i]->GetIPDLActor();
|
||||
if (!hostOGL || !actor) {
|
||||
continue;
|
||||
}
|
||||
android::sp<android::Fence> fence = hostOGL->GetAndResetReleaseFence();
|
||||
if (fence.get() && fence->isValid()) {
|
||||
FenceHandle handle = FenceHandle(fence);
|
||||
replyv.push_back(ReturnReleaseFence(aParent, nullptr, actor, nullptr, handle));
|
||||
// Hold fence handle to prevent fence's file descriptor is closed before IPC happens.
|
||||
mPrevFenceHandles.push_back(handle);
|
||||
}
|
||||
}
|
||||
aCompositable->GetCompositableBackendSpecificData()->ClearPendingReleaseFenceTextureList();
|
||||
}
|
||||
#else
|
||||
void
|
||||
CompositableParentManager::ReturnTextureDataIfNecessary(CompositableHost* aCompositable,
|
||||
EditReplyVector& replyv,
|
||||
PCompositableParent* aParent)
|
||||
{
|
||||
if (!aCompositable || !aCompositable->GetCompositableBackendSpecificData()) {
|
||||
return;
|
||||
}
|
||||
aCompositable->GetCompositableBackendSpecificData()->ClearPendingReleaseFenceTextureList();
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
CompositableParentManager::ClearPrevFenceHandles()
|
||||
{
|
||||
mPrevFenceHandles.clear();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
|
@ -16,6 +16,8 @@
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class CompositableHost;
|
||||
|
||||
typedef std::vector<mozilla::layers::EditReply> EditReplyVector;
|
||||
|
||||
// Since PCompositble has two potential manager protocols, we can't just call
|
||||
@ -37,6 +39,14 @@ protected:
|
||||
* thread (ImageBridge for instance).
|
||||
*/
|
||||
virtual bool IsAsync() const { return false; }
|
||||
|
||||
void ReturnTextureDataIfNecessary(CompositableHost* aCompositable,
|
||||
EditReplyVector& replyv,
|
||||
PCompositableParent* aParent);
|
||||
void ClearPrevFenceHandles();
|
||||
|
||||
protected:
|
||||
std::vector<FenceHandle> mPrevFenceHandles;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
43
gfx/layers/ipc/FenceUtils.h
Normal file
43
gfx/layers/ipc/FenceUtils.h
Normal file
@ -0,0 +1,43 @@
|
||||
/* -*- 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_FencerUtils_h
|
||||
#define IPC_FencerUtils_h
|
||||
|
||||
#include "ipc/IPCMessageUtils.h"
|
||||
|
||||
/**
|
||||
* FenceHandle is used for delivering Fence object via ipc.
|
||||
*/
|
||||
#if MOZ_WIDGET_GONK && ANDROID_VERSION >= 18
|
||||
# include "mozilla/layers/FenceUtilsGonk.h"
|
||||
#else
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
struct FenceHandle {
|
||||
bool operator==(const FenceHandle&) const { return false; }
|
||||
bool IsValid() const { return false; }
|
||||
};
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
#endif // MOZ_WIDGET_GONK && ANDROID_VERSION >= 18
|
||||
|
||||
namespace IPC {
|
||||
|
||||
#if MOZ_WIDGET_GONK && ANDROID_VERSION >= 18
|
||||
#else
|
||||
template <>
|
||||
struct ParamTraits<mozilla::layers::FenceHandle> {
|
||||
typedef mozilla::layers::FenceHandle paramType;
|
||||
static void Write(Message*, const paramType&) {}
|
||||
static bool Read(const Message*, void**, paramType*) { return false; }
|
||||
};
|
||||
#endif // MOZ_WIDGET_GONK && ANDROID_VERSION >= 18
|
||||
|
||||
} // namespace IPC
|
||||
|
||||
#endif // IPC_FencerUtils_h
|
96
gfx/layers/ipc/FenceUtilsGonk.cpp
Normal file
96
gfx/layers/ipc/FenceUtilsGonk.cpp
Normal file
@ -0,0 +1,96 @@
|
||||
/* -*- 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 "GLContext.h"
|
||||
#include "mozilla/unused.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
|
||||
#include "FenceUtilsGonk.h"
|
||||
|
||||
using namespace android;
|
||||
using namespace base;
|
||||
using namespace mozilla::layers;
|
||||
|
||||
namespace IPC {
|
||||
|
||||
void
|
||||
ParamTraits<FenceHandle>::Write(Message* aMsg,
|
||||
const paramType& aParam)
|
||||
{
|
||||
Flattenable *flattenable = aParam.mFence.get();
|
||||
size_t nbytes = flattenable->getFlattenedSize();
|
||||
size_t nfds = flattenable->getFdCount();
|
||||
|
||||
char data[nbytes];
|
||||
int fds[nfds];
|
||||
flattenable->flatten(data, nbytes, fds, nfds);
|
||||
|
||||
aMsg->WriteSize(nbytes);
|
||||
aMsg->WriteSize(nfds);
|
||||
|
||||
aMsg->WriteBytes(data, nbytes);
|
||||
for (size_t n = 0; n < nfds; ++n) {
|
||||
// These buffers can't die in transit because they're created
|
||||
// synchonously and the parent-side buffer can only be dropped if
|
||||
// there's a crash.
|
||||
aMsg->WriteFileDescriptor(FileDescriptor(fds[n], false));
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ParamTraits<FenceHandle>::Read(const Message* aMsg,
|
||||
void** aIter, paramType* aResult)
|
||||
{
|
||||
size_t nbytes;
|
||||
size_t nfds;
|
||||
const char* data;
|
||||
|
||||
if (!aMsg->ReadSize(aIter, &nbytes) ||
|
||||
!aMsg->ReadSize(aIter, &nfds) ||
|
||||
!aMsg->ReadBytes(aIter, &data, nbytes)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int fds[nfds];
|
||||
|
||||
for (size_t n = 0; n < nfds; ++n) {
|
||||
FileDescriptor fd;
|
||||
if (!aMsg->ReadFileDescriptor(aIter, &fd)) {
|
||||
return false;
|
||||
}
|
||||
// If the GraphicBuffer was shared cross-process, SCM_RIGHTS does
|
||||
// the right thing and dup's the fd. If it's shared cross-thread,
|
||||
// SCM_RIGHTS doesn't dup the fd. That's surprising, but we just
|
||||
// deal with it here. NB: only the "default" (master) process can
|
||||
// alloc gralloc buffers.
|
||||
bool sameProcess = (XRE_GetProcessType() == GeckoProcessType_Default);
|
||||
int dupFd = sameProcess ? dup(fd.fd) : fd.fd;
|
||||
fds[n] = dupFd;
|
||||
}
|
||||
|
||||
sp<Fence> buffer(new Fence());
|
||||
Flattenable *flattenable = buffer.get();
|
||||
|
||||
if (NO_ERROR == flattenable->unflatten(data, nbytes, fds, nfds)) {
|
||||
aResult->mFence = buffer;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace IPC
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
FenceHandle::FenceHandle(const sp<Fence>& aFence)
|
||||
: mFence(aFence)
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
53
gfx/layers/ipc/FenceUtilsGonk.h
Normal file
53
gfx/layers/ipc/FenceUtilsGonk.h
Normal file
@ -0,0 +1,53 @@
|
||||
/* -*- 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 mozilla_layers_FenceUtilsGonk_h
|
||||
#define mozilla_layers_FenceUtilsGonk_h
|
||||
|
||||
#include <unistd.h>
|
||||
#include <ui/Fence.h>
|
||||
|
||||
#include "ipc/IPCMessageUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
struct FenceHandle {
|
||||
typedef android::Fence Fence;
|
||||
|
||||
FenceHandle()
|
||||
{ }
|
||||
FenceHandle(const android::sp<Fence>& aFence);
|
||||
|
||||
bool operator==(const FenceHandle& aOther) const {
|
||||
return mFence.get() == aOther.mFence.get();
|
||||
}
|
||||
|
||||
bool IsValid() const
|
||||
{
|
||||
return mFence.get() && mFence->isValid();
|
||||
}
|
||||
|
||||
android::sp<Fence> mFence;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
namespace IPC {
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::layers::FenceHandle> {
|
||||
typedef mozilla::layers::FenceHandle paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam);
|
||||
static bool Read(const Message* aMsg, void** aIter, paramType* aResult);
|
||||
};
|
||||
|
||||
} // namespace IPC
|
||||
|
||||
#endif // mozilla_layers_FenceUtilsGonk_h
|
@ -516,6 +516,20 @@ ImageBridgeChild::EndTransaction()
|
||||
->SetDescriptorFromReply(ots.textureId(), ots.image());
|
||||
break;
|
||||
}
|
||||
case EditReply::TReturnReleaseFence: {
|
||||
const ReturnReleaseFence& rep = reply.get_ReturnReleaseFence();
|
||||
FenceHandle fence = rep.fence();
|
||||
PTextureChild* child = rep.textureChild();
|
||||
|
||||
if (!fence.IsValid() || !child) {
|
||||
break;
|
||||
}
|
||||
RefPtr<TextureClient> texture = TextureClient::AsTextureClient(child);
|
||||
if (texture) {
|
||||
texture->SetReleaseFenceHandle(fence);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
NS_RUNTIMEABORT("not reached");
|
||||
}
|
||||
|
@ -75,6 +75,9 @@ ImageBridgeParent::RecvUpdate(const EditArray& aEdits, EditReplyArray* aReply)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Clear fence handles used in previsou transaction.
|
||||
ClearPrevFenceHandles();
|
||||
|
||||
EditReplyVector replyv;
|
||||
for (EditArray::index_type i = 0; i < aEdits.Length(); ++i) {
|
||||
ReceiveCompositableUpdate(aEdits[i], replyv);
|
||||
|
@ -204,6 +204,9 @@ LayerTransactionParent::RecvUpdate(const InfallibleTArray<Edit>& cset,
|
||||
return true;
|
||||
}
|
||||
|
||||
// Clear fence handles used in previsou transaction.
|
||||
ClearPrevFenceHandles();
|
||||
|
||||
EditReplyVector replyv;
|
||||
|
||||
{
|
||||
|
@ -39,6 +39,7 @@ using mozilla::layers::ScaleMode from "mozilla/layers/LayersTypes.h";
|
||||
using mozilla::layers::EventRegions from "mozilla/layers/LayersTypes.h";
|
||||
using mozilla::layers::DiagnosticTypes from "mozilla/layers/CompositorTypes.h";
|
||||
using struct mozilla::layers::FrameMetrics from "FrameMetrics.h";
|
||||
using struct mozilla::layers::FenceHandle from "mozilla/layers/FenceUtils.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
@ -396,11 +397,19 @@ struct OpTextureSwap {
|
||||
SurfaceDescriptor image;
|
||||
};
|
||||
|
||||
struct ReturnReleaseFence {
|
||||
PCompositable compositable;
|
||||
PTexture texture;
|
||||
FenceHandle fence;
|
||||
};
|
||||
|
||||
// Unit of a "changeset reply". This is a weird abstraction, probably
|
||||
// only to be used for buffer swapping.
|
||||
union EditReply {
|
||||
OpContentBufferSwap;
|
||||
OpTextureSwap;
|
||||
|
||||
ReturnReleaseFence;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
@ -129,6 +129,7 @@ EXPORTS.mozilla.layers += [
|
||||
'ipc/CompositableTransactionParent.h',
|
||||
'ipc/CompositorChild.h',
|
||||
'ipc/CompositorParent.h',
|
||||
'ipc/FenceUtils.h',
|
||||
'ipc/GeckoContentController.h',
|
||||
'ipc/GestureEventListener.h',
|
||||
'ipc/ImageBridgeChild.h',
|
||||
@ -202,6 +203,14 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
|
||||
'ipc/ShadowLayerUtilsGralloc.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['ANDROID_VERSION'] in ('18'):
|
||||
EXPORTS.mozilla.layers += [
|
||||
'ipc/FenceUtilsGonk.h',
|
||||
]
|
||||
SOURCES += [
|
||||
'ipc/FenceUtilsGonk.cpp',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'basic/BasicCanvasLayer.cpp',
|
||||
'basic/BasicColorLayer.cpp',
|
||||
|
@ -196,6 +196,16 @@ GrallocTextureClientOGL::UpdateSurface(gfxASurface* aSurface)
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
GrallocTextureClientOGL::SetReleaseFenceHandle(FenceHandle aReleaseFenceHandle)
|
||||
{
|
||||
if (mBufferLocked) {
|
||||
mBufferLocked->SetReleaseFenceHandle(aReleaseFenceHandle);
|
||||
} else {
|
||||
mReleaseFenceHandle = aReleaseFenceHandle;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
GrallocTextureClientOGL::Lock(OpenMode aMode)
|
||||
{
|
||||
@ -207,6 +217,15 @@ GrallocTextureClientOGL::Lock(OpenMode aMode)
|
||||
if (mMappedBuffer) {
|
||||
return true;
|
||||
}
|
||||
|
||||
#if MOZ_WIDGET_GONK && ANDROID_VERSION >= 18
|
||||
if (mReleaseFenceHandle.IsValid()) {
|
||||
android::sp<Fence> fence = mReleaseFenceHandle.mFence;
|
||||
fence->waitForever("GrallocTextureClientOGL::Lock");
|
||||
mReleaseFenceHandle = FenceHandle();
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32_t usage = 0;
|
||||
if (aMode & OPEN_READ) {
|
||||
usage |= GRALLOC_USAGE_SW_READ_OFTEN;
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include "mozilla/layers/TextureClient.h"
|
||||
#include "ISurfaceAllocator.h" // For IsSurfaceDescriptorValid
|
||||
#include "mozilla/layers/FenceUtils.h" // for FenceHandle
|
||||
#include "mozilla/layers/ShadowLayerUtilsGralloc.h"
|
||||
#include <ui/GraphicBuffer.h>
|
||||
|
||||
@ -59,6 +60,13 @@ public:
|
||||
|
||||
virtual TextureClientData* DropTextureData() MOZ_OVERRIDE;
|
||||
|
||||
virtual void SetReleaseFenceHandle(FenceHandle aReleaseFenceHandle) MOZ_OVERRIDE;
|
||||
|
||||
const FenceHandle& GetReleaseFenceHandle() const
|
||||
{
|
||||
return mReleaseFenceHandle;
|
||||
}
|
||||
|
||||
void InitWith(GrallocBufferActor* aActor, gfx::IntSize aSize);
|
||||
|
||||
void SetTextureFlags(TextureFlags aFlags) { AddFlags(aFlags); }
|
||||
|
@ -332,7 +332,8 @@ GrallocTextureHostOGL::GetRenderState()
|
||||
}
|
||||
return LayerRenderState(mTextureSource->mGraphicBuffer.get(),
|
||||
gfx::ThebesIntSize(mSize),
|
||||
flags);
|
||||
flags,
|
||||
this);
|
||||
}
|
||||
|
||||
return LayerRenderState();
|
||||
@ -379,6 +380,11 @@ GrallocTextureHostOGL::SetCompositableBackendSpecificData(CompositableBackendSpe
|
||||
if (mTextureSource) {
|
||||
mTextureSource->SetCompositableBackendSpecificData(aBackendData);
|
||||
}
|
||||
// Register this object to CompositableBackendSpecificData
|
||||
// as current TextureHost.
|
||||
if (aBackendData) {
|
||||
aBackendData->SetCurrentReleaseFenceTexture(this);
|
||||
}
|
||||
}
|
||||
|
||||
} // namepsace layers
|
||||
|
@ -71,6 +71,9 @@ protected:
|
||||
};
|
||||
|
||||
class GrallocTextureHostOGL : public TextureHost
|
||||
#if MOZ_WIDGET_GONK && ANDROID_VERSION >= 18
|
||||
, public TextureHostOGL
|
||||
#endif
|
||||
{
|
||||
friend class GrallocBufferActor;
|
||||
public:
|
||||
@ -104,6 +107,13 @@ public:
|
||||
return mTextureSource;
|
||||
}
|
||||
|
||||
#if MOZ_WIDGET_GONK && ANDROID_VERSION >= 18
|
||||
virtual TextureHostOGL* AsHostOGL() MOZ_OVERRIDE
|
||||
{
|
||||
return this;
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() MOZ_OVERRIDE;
|
||||
|
||||
virtual void SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData) MOZ_OVERRIDE;
|
||||
|
@ -176,6 +176,7 @@ void CompositableDataGonkOGL::SetCompositor(Compositor* aCompositor)
|
||||
|
||||
void CompositableDataGonkOGL::ClearData()
|
||||
{
|
||||
CompositableBackendSpecificData::ClearData();
|
||||
DeleteTextureIfPresent();
|
||||
}
|
||||
|
||||
@ -200,6 +201,41 @@ CompositableDataGonkOGL::DeleteTextureIfPresent()
|
||||
}
|
||||
}
|
||||
|
||||
#if MOZ_WIDGET_GONK && ANDROID_VERSION >= 18
|
||||
bool
|
||||
TextureHostOGL::SetReleaseFence(const android::sp<android::Fence>& aReleaseFence)
|
||||
{
|
||||
if (!aReleaseFence.get() || !aReleaseFence->isValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mReleaseFence.get()) {
|
||||
mReleaseFence = aReleaseFence;
|
||||
} else {
|
||||
android::sp<android::Fence> mergedFence = android::Fence::merge(
|
||||
android::String8::format("TextureHostOGL"),
|
||||
mReleaseFence, aReleaseFence);
|
||||
if (!mergedFence.get()) {
|
||||
// synchronization is broken, the best we can do is hope fences
|
||||
// signal in order so the new fence will act like a union.
|
||||
// This error handling is same as android::ConsumerBase does.
|
||||
mReleaseFence = aReleaseFence;
|
||||
return false;
|
||||
}
|
||||
mReleaseFence = mergedFence;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
android::sp<android::Fence>
|
||||
TextureHostOGL::GetAndResetReleaseFence()
|
||||
{
|
||||
android::sp<android::Fence> fence = mReleaseFence;
|
||||
mReleaseFence = android::Fence::NO_FENCE;
|
||||
return fence;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool
|
||||
TextureImageTextureSourceOGL::Update(gfx::DataSourceSurface* aSurface,
|
||||
nsIntRegion* aDestRegion,
|
||||
@ -1155,7 +1191,8 @@ GrallocDeprecatedTextureHostOGL::GetRenderState()
|
||||
|
||||
return LayerRenderState(mGraphicBuffer.get(),
|
||||
bufferSize,
|
||||
flags);
|
||||
flags,
|
||||
nullptr);
|
||||
}
|
||||
|
||||
return LayerRenderState();
|
||||
|
@ -32,6 +32,9 @@
|
||||
#include "OGLShaderProgram.h" // for ShaderProgramType, etc
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
#include <ui/GraphicBuffer.h>
|
||||
#if ANDROID_VERSION >= 18
|
||||
#include <ui/Fence.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
class gfxImageSurface;
|
||||
@ -117,6 +120,29 @@ public:
|
||||
virtual TextureImageDeprecatedTextureHostOGL* AsTextureImageDeprecatedTextureHost() { return nullptr; }
|
||||
};
|
||||
|
||||
/**
|
||||
* TextureHostOGL provides the necessary API for platform specific composition.
|
||||
*/
|
||||
class TextureHostOGL
|
||||
{
|
||||
public:
|
||||
#if MOZ_WIDGET_GONK && ANDROID_VERSION >= 18
|
||||
|
||||
/**
|
||||
* Store a fence that will signal when the current buffer is no longer being read.
|
||||
* Similar to android's GLConsumer::setReleaseFence()
|
||||
*/
|
||||
virtual bool SetReleaseFence(const android::sp<android::Fence>& aReleaseFence);
|
||||
|
||||
/**
|
||||
* Return a releaseFence's Fence and clear a reference to the Fence.
|
||||
*/
|
||||
virtual android::sp<android::Fence> GetAndResetReleaseFence();
|
||||
protected:
|
||||
android::sp<android::Fence> mReleaseFence;
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* A TextureSource backed by a TextureImage.
|
||||
*
|
||||
|
@ -19,11 +19,13 @@
|
||||
|
||||
#include "libdisplay/GonkDisplay.h"
|
||||
#include "Framebuffer.h"
|
||||
#include "GLContext.h" // for GLContext
|
||||
#include "HwcUtils.h"
|
||||
#include "HwcComposer2D.h"
|
||||
#include "mozilla/layers/LayerManagerComposite.h"
|
||||
#include "mozilla/layers/PLayerTransaction.h"
|
||||
#include "mozilla/layers/ShadowLayerUtilsGralloc.h"
|
||||
#include "mozilla/layers/TextureHostOGL.h" // for TextureHostOGL
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "cutils/properties.h"
|
||||
#include "gfx2DGlue.h"
|
||||
@ -67,7 +69,10 @@ HwcComposer2D::HwcComposer2D()
|
||||
, mHwc(nullptr)
|
||||
, mColorFill(false)
|
||||
, mRBSwapSupport(false)
|
||||
, mPrevRetireFence(-1)
|
||||
#if ANDROID_VERSION >= 18
|
||||
, mPrevRetireFence(Fence::NO_FENCE)
|
||||
, mPrevDisplayFence(Fence::NO_FENCE)
|
||||
#endif
|
||||
, mPrepared(false)
|
||||
{
|
||||
}
|
||||
@ -649,36 +654,29 @@ HwcComposer2D::Commit()
|
||||
|
||||
int err = mHwc->set(mHwc, HWC_NUM_DISPLAY_TYPES, displays);
|
||||
|
||||
// To avoid tearing, workaround for missing releaseFenceFd
|
||||
// waits in Gecko layers, see Bug 925444.
|
||||
if (!mPrevReleaseFds.IsEmpty()) {
|
||||
// Wait for previous retire Fence to signal.
|
||||
// Denotes contents on display have been replaced.
|
||||
// For buffer-sync, framework should not over-write
|
||||
// prev buffers until we close prev releaseFenceFds
|
||||
sp<Fence> fence = new Fence(mPrevRetireFence);
|
||||
if (fence->wait(1000) == -ETIME) {
|
||||
LOGE("Wait timed-out for retireFenceFd %d", mPrevRetireFence);
|
||||
}
|
||||
for (int i = 0; i < mPrevReleaseFds.Length(); i++) {
|
||||
close(mPrevReleaseFds[i]);
|
||||
}
|
||||
close(mPrevRetireFence);
|
||||
mPrevReleaseFds.Clear();
|
||||
}
|
||||
mPrevDisplayFence = mPrevRetireFence;
|
||||
mPrevRetireFence = Fence::NO_FENCE;
|
||||
|
||||
for (uint32_t j=0; j < (mList->numHwLayers - 1); j++) {
|
||||
if (mList->hwLayers[j].releaseFenceFd >= 0) {
|
||||
mPrevReleaseFds.AppendElement(mList->hwLayers[j].releaseFenceFd);
|
||||
}
|
||||
}
|
||||
int fd = mList->hwLayers[j].releaseFenceFd;
|
||||
mList->hwLayers[j].releaseFenceFd = -1;
|
||||
sp<Fence> fence = new Fence(fd);
|
||||
|
||||
LayerRenderState state = mHwcLayerMap[j]->GetLayer()->GetRenderState();
|
||||
if (!state.mTexture) {
|
||||
continue;
|
||||
}
|
||||
TextureHostOGL* texture = state.mTexture->AsHostOGL();
|
||||
if (!texture) {
|
||||
continue;
|
||||
}
|
||||
texture->SetReleaseFence(fence);
|
||||
}
|
||||
}
|
||||
|
||||
if (mList->retireFenceFd >= 0) {
|
||||
if (!mPrevReleaseFds.IsEmpty()) {
|
||||
mPrevRetireFence = mList->retireFenceFd;
|
||||
} else { // GPU Composition
|
||||
close(mList->retireFenceFd);
|
||||
}
|
||||
mPrevRetireFence = new Fence(mList->retireFenceFd);
|
||||
}
|
||||
|
||||
mPrepared = false;
|
||||
|
@ -23,6 +23,9 @@
|
||||
#include <list>
|
||||
|
||||
#include <hardware/hwcomposer.h>
|
||||
#if ANDROID_VERSION >= 18
|
||||
#include <ui/Fence.h>
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@ -83,8 +86,10 @@ private:
|
||||
//Holds all the dynamically allocated RectVectors needed
|
||||
//to render the current frame
|
||||
std::list<RectVector> mVisibleRegions;
|
||||
nsTArray<int> mPrevReleaseFds;
|
||||
int mPrevRetireFence;
|
||||
#if ANDROID_VERSION >= 18
|
||||
android::sp<android::Fence> mPrevRetireFence;
|
||||
android::sp<android::Fence> mPrevDisplayFence;
|
||||
#endif
|
||||
nsTArray<layers::LayerComposite*> mHwcLayerMap;
|
||||
bool mPrepared;
|
||||
};
|
||||
|
@ -105,8 +105,7 @@ status_t GonkNativeWindow::setDefaultBufferFormat(uint32_t defaultFormat) {
|
||||
}
|
||||
|
||||
already_AddRefed<GraphicBufferLocked>
|
||||
GonkNativeWindow::getCurrentBuffer()
|
||||
{
|
||||
GonkNativeWindow::getCurrentBuffer() {
|
||||
Mutex::Autolock _l(mMutex);
|
||||
GonkBufferQueue::BufferItem item;
|
||||
|
||||
@ -123,17 +122,20 @@ GonkNativeWindow::getCurrentBuffer()
|
||||
}
|
||||
|
||||
bool
|
||||
GonkNativeWindow::returnBuffer(uint32_t aIndex, uint32_t aGeneration) {
|
||||
BI_LOGD("GonkNativeWindow::returnBuffer: slot=%d (generation=%d)", aIndex, aGeneration);
|
||||
GonkNativeWindow::returnBuffer(uint32_t index, uint32_t generation, const sp<Fence>& fence) {
|
||||
BI_LOGD("GonkNativeWindow::returnBuffer: slot=%d (generation=%d)", index, generation);
|
||||
Mutex::Autolock lock(mMutex);
|
||||
|
||||
if (aGeneration != mBufferQueue->getGeneration()) {
|
||||
if (generation != mBufferQueue->getGeneration()) {
|
||||
BI_LOGD("returnBuffer: buffer is from generation %d (current is %d)",
|
||||
aGeneration, mBufferQueue->getGeneration());
|
||||
generation, mBufferQueue->getGeneration());
|
||||
return false;
|
||||
}
|
||||
|
||||
status_t err = releaseBufferLocked(aIndex);
|
||||
status_t err;
|
||||
err = addReleaseFenceLocked(index, fence);
|
||||
|
||||
err = releaseBufferLocked(index);
|
||||
if (err != NO_ERROR) {
|
||||
return false;
|
||||
}
|
||||
@ -141,8 +143,7 @@ GonkNativeWindow::returnBuffer(uint32_t aIndex, uint32_t aGeneration) {
|
||||
}
|
||||
|
||||
mozilla::layers::SurfaceDescriptor *
|
||||
GonkNativeWindow::getSurfaceDescriptorFromBuffer(ANativeWindowBuffer* buffer)
|
||||
{
|
||||
GonkNativeWindow::getSurfaceDescriptorFromBuffer(ANativeWindowBuffer* buffer) {
|
||||
Mutex::Autolock lock(mMutex);
|
||||
return mBufferQueue->getSurfaceDescriptorFromBuffer(buffer);
|
||||
}
|
||||
@ -161,4 +162,22 @@ void GonkNativeWindow::onFrameAvailable() {
|
||||
}
|
||||
}
|
||||
|
||||
void CameraGraphicBuffer::Unlock() {
|
||||
if (mLocked) {
|
||||
android::sp<android::Fence> fence;
|
||||
fence = mReleaseFenceHandle.IsValid() ? mReleaseFenceHandle.mFence : Fence::NO_FENCE;
|
||||
// The window might have been destroyed. The buffer is no longer
|
||||
// valid at that point.
|
||||
sp<GonkNativeWindow> window = mNativeWindow.promote();
|
||||
if (window.get() && window->returnBuffer(mIndex, mGeneration, fence)) {
|
||||
mLocked = false;
|
||||
} else {
|
||||
// If the window doesn't exist any more, release the buffer
|
||||
// directly.
|
||||
ImageBridgeChild *ibc = ImageBridgeChild::GetSingleton();
|
||||
ibc->DeallocSurfaceDescriptorGralloc(mSurfaceDescriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace android
|
||||
|
@ -116,7 +116,7 @@ class GonkNativeWindow: public GonkConsumerBase
|
||||
|
||||
// Return the buffer to the queue and mark it as FREE. After that
|
||||
// the buffer is useable again for the decoder.
|
||||
bool returnBuffer(uint32_t index, uint32_t generation);
|
||||
bool returnBuffer(uint32_t index, uint32_t generation, const sp<Fence>& fence);
|
||||
|
||||
SurfaceDescriptor* getSurfaceDescriptorFromBuffer(ANativeWindowBuffer* buffer);
|
||||
|
||||
@ -157,22 +157,7 @@ public:
|
||||
protected:
|
||||
// Unlock either returns the buffer to the native window or
|
||||
// destroys the buffer if the window is already released.
|
||||
virtual void Unlock() MOZ_OVERRIDE
|
||||
{
|
||||
if (mLocked) {
|
||||
// The window might have been destroyed. The buffer is no longer
|
||||
// valid at that point.
|
||||
sp<GonkNativeWindow> window = mNativeWindow.promote();
|
||||
if (window.get() && window->returnBuffer(mIndex, mGeneration)) {
|
||||
mLocked = false;
|
||||
} else {
|
||||
// If the window doesn't exist any more, release the buffer
|
||||
// directly.
|
||||
ImageBridgeChild *ibc = ImageBridgeChild::GetSingleton();
|
||||
ibc->DeallocSurfaceDescriptorGralloc(mSurfaceDescriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
virtual void Unlock() MOZ_OVERRIDE;
|
||||
|
||||
protected:
|
||||
wp<GonkNativeWindow> mNativeWindow;
|
||||
|
Loading…
Reference in New Issue
Block a user