зеркало из https://github.com/mozilla/gecko-dev.git
409 строки
10 KiB
C++
409 строки
10 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
|
/* 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 "mozilla/TaskQueue.h"
|
|
|
|
#include "gfxPrefs.h"
|
|
#include "MediaSystemResourceManagerChild.h"
|
|
#include "mozilla/layers/ImageBridgeChild.h"
|
|
|
|
#include "MediaSystemResourceManager.h"
|
|
|
|
namespace mozilla {
|
|
|
|
using namespace mozilla::ipc;
|
|
using namespace mozilla::layers;
|
|
|
|
/* static */ StaticRefPtr<MediaSystemResourceManager> MediaSystemResourceManager::sSingleton;
|
|
|
|
/* static */ MediaSystemResourceManager*
|
|
MediaSystemResourceManager::Get()
|
|
{
|
|
if (sSingleton) {
|
|
return sSingleton;
|
|
}
|
|
MediaSystemResourceManager::Init();
|
|
return sSingleton;
|
|
}
|
|
|
|
/* static */ void
|
|
MediaSystemResourceManager::Shutdown()
|
|
{
|
|
MOZ_ASSERT(InImageBridgeChildThread());
|
|
if (sSingleton) {
|
|
sSingleton->CloseIPC();
|
|
sSingleton = nullptr;
|
|
}
|
|
}
|
|
|
|
class RunnableCallTask : public Task
|
|
{
|
|
public:
|
|
explicit RunnableCallTask(nsIRunnable* aRunnable)
|
|
: mRunnable(aRunnable) {}
|
|
|
|
void Run() override
|
|
{
|
|
mRunnable->Run();
|
|
}
|
|
protected:
|
|
nsCOMPtr<nsIRunnable> mRunnable;
|
|
};
|
|
|
|
/* static */ void
|
|
MediaSystemResourceManager::Init()
|
|
{
|
|
if (!ImageBridgeChild::IsCreated()) {
|
|
NS_WARNING("ImageBridge does not exist");
|
|
return;
|
|
}
|
|
|
|
if (InImageBridgeChildThread()) {
|
|
if (!sSingleton) {
|
|
#ifdef DEBUG
|
|
static int timesCreated = 0;
|
|
timesCreated++;
|
|
MOZ_ASSERT(timesCreated == 1);
|
|
#endif
|
|
sSingleton = new MediaSystemResourceManager();
|
|
}
|
|
return;
|
|
}
|
|
|
|
ReentrantMonitor barrier("MediaSystemResourceManager::Init");
|
|
ReentrantMonitorAutoEnter autoMon(barrier);
|
|
bool done = false;
|
|
|
|
nsCOMPtr<nsIRunnable> runnable =
|
|
NS_NewRunnableFunction([&]() {
|
|
if (!sSingleton) {
|
|
sSingleton = new MediaSystemResourceManager();
|
|
}
|
|
ReentrantMonitorAutoEnter autoMon(barrier);
|
|
done = true;
|
|
barrier.NotifyAll();
|
|
});
|
|
|
|
ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(
|
|
FROM_HERE, new RunnableCallTask(runnable));
|
|
|
|
// should stop the thread until done.
|
|
while (!done) {
|
|
barrier.Wait();
|
|
}
|
|
|
|
}
|
|
|
|
MediaSystemResourceManager::MediaSystemResourceManager()
|
|
: mReentrantMonitor("MediaSystemResourceManager.mReentrantMonitor")
|
|
, mShutDown(false)
|
|
, mChild(nullptr)
|
|
{
|
|
MOZ_ASSERT(InImageBridgeChildThread());
|
|
OpenIPC();
|
|
}
|
|
|
|
MediaSystemResourceManager::~MediaSystemResourceManager()
|
|
{
|
|
MOZ_ASSERT(IsIpcClosed());
|
|
}
|
|
|
|
void
|
|
MediaSystemResourceManager::OpenIPC()
|
|
{
|
|
MOZ_ASSERT(InImageBridgeChildThread());
|
|
MOZ_ASSERT(!mChild);
|
|
|
|
media::PMediaSystemResourceManagerChild* child =
|
|
ImageBridgeChild::GetSingleton()->SendPMediaSystemResourceManagerConstructor();
|
|
mChild = static_cast<media::MediaSystemResourceManagerChild*>(child);
|
|
mChild->SetManager(this);
|
|
}
|
|
|
|
void
|
|
MediaSystemResourceManager::CloseIPC()
|
|
{
|
|
MOZ_ASSERT(InImageBridgeChildThread());
|
|
|
|
if (!mChild) {
|
|
return;
|
|
}
|
|
mChild->Destroy();
|
|
mChild = nullptr;
|
|
mShutDown = true;
|
|
}
|
|
|
|
void
|
|
MediaSystemResourceManager::OnIpcClosed()
|
|
{
|
|
mChild = nullptr;
|
|
}
|
|
|
|
bool
|
|
MediaSystemResourceManager::IsIpcClosed()
|
|
{
|
|
return mChild ? true : false;
|
|
}
|
|
|
|
void
|
|
MediaSystemResourceManager::Register(MediaSystemResourceClient* aClient)
|
|
{
|
|
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
|
MOZ_ASSERT(aClient);
|
|
MOZ_ASSERT(!mResourceClients.Get(aClient->mId));
|
|
|
|
mResourceClients.Put(aClient->mId, aClient);
|
|
}
|
|
|
|
void
|
|
MediaSystemResourceManager::Unregister(MediaSystemResourceClient* aClient)
|
|
{
|
|
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
|
MOZ_ASSERT(aClient);
|
|
MOZ_ASSERT(mResourceClients.Get(aClient->mId));
|
|
MOZ_ASSERT(mResourceClients.Get(aClient->mId) == aClient);
|
|
|
|
mResourceClients.Remove(aClient->mId);
|
|
}
|
|
|
|
bool
|
|
MediaSystemResourceManager::SetListener(MediaSystemResourceClient* aClient,
|
|
MediaSystemResourceReservationListener* aListener)
|
|
{
|
|
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
|
MOZ_ASSERT(aClient);
|
|
|
|
MediaSystemResourceClient* client = mResourceClients.Get(aClient->mId);
|
|
MOZ_ASSERT(client);
|
|
|
|
if (!client) {
|
|
return false;
|
|
}
|
|
// State Check
|
|
if (aClient->mResourceState != MediaSystemResourceClient::RESOURCE_STATE_START) {
|
|
return false;
|
|
}
|
|
aClient->mListener = aListener;
|
|
return true;
|
|
}
|
|
|
|
void
|
|
MediaSystemResourceManager::Acquire(MediaSystemResourceClient* aClient)
|
|
{
|
|
MOZ_ASSERT(aClient);
|
|
MOZ_ASSERT(!InImageBridgeChildThread());
|
|
|
|
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
|
MediaSystemResourceClient* client = mResourceClients.Get(aClient->mId);
|
|
MOZ_ASSERT(client);
|
|
MOZ_ASSERT(client == aClient);
|
|
|
|
aClient->mIsSync = false; // async request
|
|
|
|
if (!client) {
|
|
HandleAcquireResult(aClient->mId, false);
|
|
return;
|
|
}
|
|
// State Check
|
|
if (aClient->mResourceState != MediaSystemResourceClient::RESOURCE_STATE_START) {
|
|
HandleAcquireResult(aClient->mId, false);
|
|
return;
|
|
}
|
|
aClient->mResourceState = MediaSystemResourceClient::RESOURCE_STATE_WAITING;
|
|
ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(
|
|
FROM_HERE,
|
|
NewRunnableMethod(
|
|
this,
|
|
&MediaSystemResourceManager::DoAcquire,
|
|
aClient->mId));
|
|
}
|
|
|
|
bool
|
|
MediaSystemResourceManager::AcquireSyncNoWait(MediaSystemResourceClient* aClient)
|
|
{
|
|
MOZ_ASSERT(aClient);
|
|
MOZ_ASSERT(!InImageBridgeChildThread());
|
|
|
|
ReentrantMonitor barrier("MediaSystemResourceManager::AcquireSyncNoWait");
|
|
ReentrantMonitorAutoEnter autoMon(barrier);
|
|
bool done = false;
|
|
{
|
|
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
|
MediaSystemResourceClient* client = mResourceClients.Get(aClient->mId);
|
|
MOZ_ASSERT(client);
|
|
MOZ_ASSERT(client == aClient);
|
|
|
|
aClient->mIsSync = true; // sync request
|
|
|
|
if (InImageBridgeChildThread()) {
|
|
HandleAcquireResult(aClient->mId, false);
|
|
return false;
|
|
}
|
|
if (!aClient ||
|
|
!client ||
|
|
client != aClient) {
|
|
HandleAcquireResult(aClient->mId, false);
|
|
return false;
|
|
}
|
|
// State Check
|
|
if (aClient->mResourceState != MediaSystemResourceClient::RESOURCE_STATE_START) {
|
|
HandleAcquireResult(aClient->mId, false);
|
|
return false;
|
|
}
|
|
// Hold barrier Monitor until acquire task end.
|
|
aClient->mAcquireSyncWaitMonitor = &barrier;
|
|
aClient->mAcquireSyncWaitDone = &done;
|
|
aClient->mResourceState = MediaSystemResourceClient::RESOURCE_STATE_WAITING;
|
|
}
|
|
|
|
ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(
|
|
FROM_HERE,
|
|
NewRunnableMethod(
|
|
this,
|
|
&MediaSystemResourceManager::DoAcquire,
|
|
aClient->mId));
|
|
|
|
// should stop the thread until done.
|
|
while (!done) {
|
|
barrier.Wait();
|
|
}
|
|
|
|
{
|
|
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
|
if (aClient->mResourceState != MediaSystemResourceClient::RESOURCE_STATE_ACQUIRED) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
|
|
void
|
|
MediaSystemResourceManager::DoAcquire(uint32_t aId)
|
|
{
|
|
MOZ_ASSERT(InImageBridgeChildThread());
|
|
if (mShutDown || !mChild) {
|
|
HandleAcquireResult(aId, false);
|
|
return;
|
|
}
|
|
{
|
|
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
|
MediaSystemResourceClient* client = mResourceClients.Get(aId);
|
|
MOZ_ASSERT(client);
|
|
|
|
if (!client ||
|
|
client->mResourceState != MediaSystemResourceClient::RESOURCE_STATE_WAITING) {
|
|
HandleAcquireResult(aId, false);
|
|
return;
|
|
}
|
|
MOZ_ASSERT(aId == client->mId);
|
|
bool willWait = !client->mAcquireSyncWaitMonitor ? true : false;
|
|
mChild->SendAcquire(client->mId,
|
|
client->mResourceType,
|
|
willWait);
|
|
}
|
|
}
|
|
|
|
void
|
|
MediaSystemResourceManager::ReleaseResource(MediaSystemResourceClient* aClient)
|
|
{
|
|
MOZ_ASSERT(aClient);
|
|
{
|
|
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
|
MediaSystemResourceClient* client = mResourceClients.Get(aClient->mId);
|
|
MOZ_ASSERT(client);
|
|
MOZ_ASSERT(client == aClient);
|
|
|
|
if (!client ||
|
|
client != aClient ||
|
|
aClient->mResourceState == MediaSystemResourceClient::RESOURCE_STATE_START ||
|
|
aClient->mResourceState == MediaSystemResourceClient::RESOURCE_STATE_END) {
|
|
|
|
aClient->mResourceState = MediaSystemResourceClient::RESOURCE_STATE_END;
|
|
return;
|
|
}
|
|
|
|
aClient->mResourceState = MediaSystemResourceClient::RESOURCE_STATE_END;
|
|
|
|
ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(
|
|
FROM_HERE,
|
|
NewRunnableMethod(
|
|
this,
|
|
&MediaSystemResourceManager::DoRelease,
|
|
aClient->mId));
|
|
}
|
|
}
|
|
|
|
void
|
|
MediaSystemResourceManager::DoRelease(uint32_t aId)
|
|
{
|
|
MOZ_ASSERT(InImageBridgeChildThread());
|
|
if (mShutDown || !mChild) {
|
|
return;
|
|
}
|
|
mChild->SendRelease(aId);
|
|
}
|
|
|
|
void
|
|
MediaSystemResourceManager::RecvResponse(uint32_t aId, bool aSuccess)
|
|
{
|
|
HandleAcquireResult(aId, aSuccess);
|
|
}
|
|
|
|
void
|
|
MediaSystemResourceManager::HandleAcquireResult(uint32_t aId, bool aSuccess)
|
|
{
|
|
if (!InImageBridgeChildThread()) {
|
|
ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(
|
|
FROM_HERE,
|
|
NewRunnableMethod(
|
|
this,
|
|
&MediaSystemResourceManager::HandleAcquireResult,
|
|
aId,
|
|
aSuccess));
|
|
return;
|
|
}
|
|
|
|
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
|
MediaSystemResourceClient* client = mResourceClients.Get(aId);
|
|
if (!client) {
|
|
// Client was already unregistered.
|
|
return;
|
|
}
|
|
if (client->mResourceState != MediaSystemResourceClient::RESOURCE_STATE_WAITING) {
|
|
return;
|
|
}
|
|
|
|
// Update state
|
|
if (aSuccess) {
|
|
client->mResourceState = MediaSystemResourceClient::RESOURCE_STATE_ACQUIRED;
|
|
} else {
|
|
client->mResourceState = MediaSystemResourceClient::RESOURCE_STATE_NOT_ACQUIRED;
|
|
}
|
|
|
|
if (client->mIsSync) {
|
|
if (client->mAcquireSyncWaitMonitor) {
|
|
// Notify AcquireSync() complete
|
|
MOZ_ASSERT(client->mAcquireSyncWaitDone);
|
|
ReentrantMonitorAutoEnter autoMon(*client->mAcquireSyncWaitMonitor);
|
|
*client->mAcquireSyncWaitDone = true;
|
|
client->mAcquireSyncWaitMonitor->NotifyAll();
|
|
client->mAcquireSyncWaitMonitor = nullptr;
|
|
client->mAcquireSyncWaitDone = nullptr;
|
|
}
|
|
} else {
|
|
// Notify Acquire() result
|
|
if (client->mListener) {
|
|
if (aSuccess) {
|
|
client->mListener->ResourceReserved();
|
|
} else {
|
|
client->mListener->ResourceReserveFailed();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
} // namespace mozilla
|