mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 21:01:08 +00:00
Bug 1741767: Use shared memory surfaces in Canvas 2D recording. r=lsalzman
This also changes SharedSurfacesParent to use a StaticMonitor, so that we can wait for the surface to be added. Differential Revision: https://phabricator.services.mozilla.com/D132703
This commit is contained in:
parent
8108a5c646
commit
0abafd6d24
@ -8,6 +8,7 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "mozilla/layers/SharedSurfacesChild.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
@ -501,6 +502,18 @@ void CanvasEventRingBuffer::ReturnRead(char* aOut, size_t aSize) {
|
||||
mWrite->returnCount = readCount;
|
||||
}
|
||||
|
||||
void CanvasDrawEventRecorder::StoreSourceSurfaceRecording(
|
||||
gfx::SourceSurface* aSurface, const char* aReason) {
|
||||
wr::ExternalImageId extId{};
|
||||
nsresult rv = layers::SharedSurfacesChild::Share(aSurface, extId);
|
||||
if (NS_FAILED(rv)) {
|
||||
DrawEventRecorderPrivate::StoreSourceSurfaceRecording(aSurface, aReason);
|
||||
return;
|
||||
}
|
||||
|
||||
StoreExternalSurfaceRecording(aSurface, wr::AsUint64(extId));
|
||||
}
|
||||
|
||||
void CanvasDrawEventRecorder::RecordSourceSurfaceDestruction(void* aSurface) {
|
||||
// We must only record things on the main thread and surfaces that have been
|
||||
// recorded can sometimes be destroyed off the main thread.
|
||||
|
@ -253,6 +253,9 @@ class CanvasDrawEventRecorder final : public gfx::DrawEventRecorderPrivate {
|
||||
aEvent.RecordToStream(mOutputStream);
|
||||
}
|
||||
|
||||
void StoreSourceSurfaceRecording(gfx::SourceSurface* aSurface,
|
||||
const char* aReason) final;
|
||||
|
||||
void RecordSourceSurfaceDestruction(void* aSurface) final;
|
||||
|
||||
void Flush() final {}
|
||||
|
@ -200,6 +200,13 @@ void CanvasChild::OnTextureForwarded() {
|
||||
|
||||
mHasOutstandingWriteLock = false;
|
||||
}
|
||||
|
||||
// We hold onto the last transaction's external surfaces until we have waited
|
||||
// for the write locks in this transaction. This means we know that the
|
||||
// surfaces have been picked up in the canvas threads and there is no race
|
||||
// with them being removed from SharedSurfacesParent. Note this releases the
|
||||
// current contents of mLastTransactionExternalSurfaces.
|
||||
mRecorder->TakeExternalSurfaces(mLastTransactionExternalSurfaces);
|
||||
}
|
||||
|
||||
void CanvasChild::EnsureBeginTransaction() {
|
||||
|
@ -141,6 +141,7 @@ class CanvasChild final : public PCanvasChild {
|
||||
uint32_t mLastWriteLockCheckpoint = 0;
|
||||
uint32_t mTransactionsSinceGetDataSurface = kCacheDataSurfaceThreshold;
|
||||
TimeStamp mLastNonEmptyTransaction = TimeStamp::NowLoRes();
|
||||
std::vector<RefPtr<gfx::SourceSurface>> mLastTransactionExternalSurfaces;
|
||||
bool mIsInTransaction = false;
|
||||
bool mHasOutstandingWriteLock = false;
|
||||
};
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "mozilla/gfx/GPUParent.h"
|
||||
#include "mozilla/gfx/Logging.h"
|
||||
#include "mozilla/ipc/Endpoint.h"
|
||||
#include "mozilla/layers/SharedSurfacesParent.h"
|
||||
#include "mozilla/layers/TextureClient.h"
|
||||
#include "mozilla/SyncRunnable.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
@ -502,6 +503,11 @@ UniquePtr<SurfaceDescriptor> CanvasTranslator::WaitForSurfaceDescriptor(
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
already_AddRefed<gfx::SourceSurface> CanvasTranslator::LookupExternalSurface(
|
||||
uint64_t aKey) {
|
||||
return SharedSurfacesParent::Get(wr::ToExternalImageId(aKey));
|
||||
}
|
||||
|
||||
already_AddRefed<gfx::GradientStops> CanvasTranslator::GetOrCreateGradientStops(
|
||||
gfx::GradientStop* aRawStops, uint32_t aNumStops,
|
||||
gfx::ExtendMode aExtendMode) {
|
||||
|
@ -175,6 +175,9 @@ class CanvasTranslator final : public gfx::InlineTranslator,
|
||||
InlineTranslator::RemoveSourceSurface(aRefPtr);
|
||||
}
|
||||
|
||||
already_AddRefed<gfx::SourceSurface> LookupExternalSurface(
|
||||
uint64_t aKey) final;
|
||||
|
||||
/**
|
||||
* Gets the cached DataSourceSurface, if it exists, associated with a
|
||||
* SourceSurface from another process.
|
||||
|
@ -22,26 +22,30 @@ namespace layers {
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
StaticMutex SharedSurfacesParent::sMutex;
|
||||
StaticMonitor SharedSurfacesParent::sMonitor;
|
||||
StaticAutoPtr<SharedSurfacesParent> SharedSurfacesParent::sInstance;
|
||||
|
||||
// Short wait to allow for a surface to be added, where the consumer has a
|
||||
// different thread route.
|
||||
static const TimeDuration kGetTimeout = TimeDuration::FromMilliseconds(50);
|
||||
|
||||
void SharedSurfacesParent::MappingTracker::NotifyExpiredLocked(
|
||||
SourceSurfaceSharedDataWrapper* aSurface,
|
||||
const StaticMutexAutoLock& aAutoLock) {
|
||||
const StaticMonitorAutoLock& aAutoLock) {
|
||||
RemoveObjectLocked(aSurface, aAutoLock);
|
||||
mExpired.AppendElement(aSurface);
|
||||
}
|
||||
|
||||
void SharedSurfacesParent::MappingTracker::TakeExpired(
|
||||
nsTArray<RefPtr<gfx::SourceSurfaceSharedDataWrapper>>& aExpired,
|
||||
const StaticMutexAutoLock& aAutoLock) {
|
||||
const StaticMonitorAutoLock& aAutoLock) {
|
||||
aExpired = std::move(mExpired);
|
||||
}
|
||||
|
||||
void SharedSurfacesParent::MappingTracker::NotifyHandlerEnd() {
|
||||
nsTArray<RefPtr<gfx::SourceSurfaceSharedDataWrapper>> expired;
|
||||
{
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
StaticMonitorAutoLock lock(sMonitor);
|
||||
TakeExpired(expired, lock);
|
||||
}
|
||||
|
||||
@ -56,7 +60,7 @@ SharedSurfacesParent::SharedSurfacesParent()
|
||||
/* static */
|
||||
void SharedSurfacesParent::Initialize() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
StaticMonitorAutoLock lock(sMonitor);
|
||||
if (!sInstance) {
|
||||
sInstance = new SharedSurfacesParent();
|
||||
}
|
||||
@ -67,7 +71,7 @@ void SharedSurfacesParent::ShutdownRenderThread() {
|
||||
// The main thread should blocked on waiting for the render thread to
|
||||
// complete so this should be safe to release off the main thread.
|
||||
MOZ_ASSERT(wr::RenderThread::IsInRenderThread());
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
StaticMonitorAutoLock lock(sMonitor);
|
||||
MOZ_ASSERT(sInstance);
|
||||
|
||||
for (const auto& key : sInstance->mSurfaces.Keys()) {
|
||||
@ -85,28 +89,34 @@ void SharedSurfacesParent::Shutdown() {
|
||||
// thread that could use it. The expiration tracker needs to be freed on the
|
||||
// main thread.
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
StaticMonitorAutoLock lock(sMonitor);
|
||||
sInstance = nullptr;
|
||||
}
|
||||
|
||||
/* static */
|
||||
already_AddRefed<DataSourceSurface> SharedSurfacesParent::Get(
|
||||
const wr::ExternalImageId& aId) {
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
StaticMonitorAutoLock lock(sMonitor);
|
||||
if (!sInstance) {
|
||||
gfxCriticalNote << "SSP:Get " << wr::AsUint64(aId) << " shtd";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<SourceSurfaceSharedDataWrapper> surface;
|
||||
sInstance->mSurfaces.Get(wr::AsUint64(aId), getter_AddRefs(surface));
|
||||
while (
|
||||
!sInstance->mSurfaces.Get(wr::AsUint64(aId), getter_AddRefs(surface))) {
|
||||
CVStatus status = lock.Wait(kGetTimeout);
|
||||
if (status == CVStatus::Timeout) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return surface.forget();
|
||||
}
|
||||
|
||||
/* static */
|
||||
already_AddRefed<DataSourceSurface> SharedSurfacesParent::Acquire(
|
||||
const wr::ExternalImageId& aId) {
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
StaticMonitorAutoLock lock(sMonitor);
|
||||
if (!sInstance) {
|
||||
gfxCriticalNote << "SSP:Acq " << wr::AsUint64(aId) << " shtd";
|
||||
return nullptr;
|
||||
@ -125,7 +135,7 @@ already_AddRefed<DataSourceSurface> SharedSurfacesParent::Acquire(
|
||||
/* static */
|
||||
bool SharedSurfacesParent::Release(const wr::ExternalImageId& aId,
|
||||
bool aForCreator) {
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
StaticMonitorAutoLock lock(sMonitor);
|
||||
if (!sInstance) {
|
||||
return false;
|
||||
}
|
||||
@ -151,7 +161,7 @@ void SharedSurfacesParent::AddSameProcess(const wr::ExternalImageId& aId,
|
||||
SourceSurfaceSharedData* aSurface) {
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
StaticMonitorAutoLock lock(sMonitor);
|
||||
if (!sInstance) {
|
||||
gfxCriticalNote << "SSP:Ads " << wr::AsUint64(aId) << " shtd";
|
||||
return;
|
||||
@ -174,11 +184,12 @@ void SharedSurfacesParent::AddSameProcess(const wr::ExternalImageId& aId,
|
||||
|
||||
surface->AddConsumer();
|
||||
sInstance->mSurfaces.InsertOrUpdate(id, std::move(surface));
|
||||
lock.NotifyAll();
|
||||
}
|
||||
|
||||
/* static */
|
||||
void SharedSurfacesParent::DestroyProcess(base::ProcessId aPid) {
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
StaticMonitorAutoLock lock(sMonitor);
|
||||
if (!sInstance) {
|
||||
return;
|
||||
}
|
||||
@ -217,7 +228,7 @@ void SharedSurfacesParent::Add(const wr::ExternalImageId& aId,
|
||||
surface->Init(aDesc.size(), aDesc.stride(), aDesc.format(),
|
||||
std::move(aDesc.handle()), aPid);
|
||||
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
StaticMonitorAutoLock lock(sMonitor);
|
||||
if (!sInstance) {
|
||||
gfxCriticalNote << "SSP:Add " << wr::AsUint64(aId) << " shtd";
|
||||
return;
|
||||
@ -231,6 +242,7 @@ void SharedSurfacesParent::Add(const wr::ExternalImageId& aId,
|
||||
|
||||
surface->AddConsumer();
|
||||
sInstance->mSurfaces.InsertOrUpdate(id, std::move(surface));
|
||||
lock.NotifyAll();
|
||||
}
|
||||
|
||||
/* static */
|
||||
@ -242,7 +254,7 @@ void SharedSurfacesParent::Remove(const wr::ExternalImageId& aId) {
|
||||
/* static */
|
||||
void SharedSurfacesParent::AddTrackingLocked(
|
||||
SourceSurfaceSharedDataWrapper* aSurface,
|
||||
const StaticMutexAutoLock& aAutoLock) {
|
||||
const StaticMonitorAutoLock& aAutoLock) {
|
||||
MOZ_ASSERT(!aSurface->GetExpirationState()->IsTracked());
|
||||
sInstance->mTracker.AddObjectLocked(aSurface, aAutoLock);
|
||||
}
|
||||
@ -250,7 +262,7 @@ void SharedSurfacesParent::AddTrackingLocked(
|
||||
/* static */
|
||||
void SharedSurfacesParent::AddTracking(
|
||||
SourceSurfaceSharedDataWrapper* aSurface) {
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
StaticMonitorAutoLock lock(sMonitor);
|
||||
if (!sInstance) {
|
||||
return;
|
||||
}
|
||||
@ -261,7 +273,7 @@ void SharedSurfacesParent::AddTracking(
|
||||
/* static */
|
||||
void SharedSurfacesParent::RemoveTrackingLocked(
|
||||
SourceSurfaceSharedDataWrapper* aSurface,
|
||||
const StaticMutexAutoLock& aAutoLock) {
|
||||
const StaticMonitorAutoLock& aAutoLock) {
|
||||
if (!aSurface->GetExpirationState()->IsTracked()) {
|
||||
return;
|
||||
}
|
||||
@ -272,7 +284,7 @@ void SharedSurfacesParent::RemoveTrackingLocked(
|
||||
/* static */
|
||||
void SharedSurfacesParent::RemoveTracking(
|
||||
SourceSurfaceSharedDataWrapper* aSurface) {
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
StaticMonitorAutoLock lock(sMonitor);
|
||||
if (!sInstance) {
|
||||
return;
|
||||
}
|
||||
@ -283,7 +295,7 @@ void SharedSurfacesParent::RemoveTracking(
|
||||
/* static */
|
||||
bool SharedSurfacesParent::AgeOneGenerationLocked(
|
||||
nsTArray<RefPtr<SourceSurfaceSharedDataWrapper>>& aExpired,
|
||||
const StaticMutexAutoLock& aAutoLock) {
|
||||
const StaticMonitorAutoLock& aAutoLock) {
|
||||
if (sInstance->mTracker.IsEmptyLocked(aAutoLock)) {
|
||||
return false;
|
||||
}
|
||||
@ -296,7 +308,7 @@ bool SharedSurfacesParent::AgeOneGenerationLocked(
|
||||
/* static */
|
||||
bool SharedSurfacesParent::AgeOneGeneration(
|
||||
nsTArray<RefPtr<SourceSurfaceSharedDataWrapper>>& aExpired) {
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
StaticMonitorAutoLock lock(sMonitor);
|
||||
if (!sInstance) {
|
||||
return false;
|
||||
}
|
||||
@ -323,7 +335,7 @@ void SharedSurfacesParent::ExpireMap(
|
||||
/* static */
|
||||
void SharedSurfacesParent::AccumulateMemoryReport(
|
||||
base::ProcessId aPid, SharedSurfacesMemoryReport& aReport) {
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
StaticMonitorAutoLock lock(sMonitor);
|
||||
if (!sInstance) {
|
||||
return;
|
||||
}
|
||||
@ -352,7 +364,7 @@ bool SharedSurfacesParent::AccumulateMemoryReport(
|
||||
return false;
|
||||
}
|
||||
|
||||
StaticMutexAutoLock lock(sMutex);
|
||||
StaticMonitorAutoLock lock(sMonitor);
|
||||
if (!sInstance) {
|
||||
return true;
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
#include <stdint.h> // for uint32_t
|
||||
#include "mozilla/Attributes.h" // for override
|
||||
#include "mozilla/StaticMutex.h" // for StaticMutex
|
||||
#include "mozilla/StaticMonitor.h" // for StaticMutex
|
||||
#include "mozilla/StaticPtr.h" // for StaticAutoPtr
|
||||
#include "mozilla/RefPtr.h" // for already_AddRefed
|
||||
#include "mozilla/ipc/SharedMemory.h" // for SharedMemory, etc
|
||||
@ -78,20 +78,20 @@ class SharedSurfacesParent final {
|
||||
gfx::SourceSurfaceSharedData* aSurface);
|
||||
|
||||
static void AddTrackingLocked(gfx::SourceSurfaceSharedDataWrapper* aSurface,
|
||||
const StaticMutexAutoLock& aAutoLock);
|
||||
const StaticMonitorAutoLock& aAutoLock);
|
||||
|
||||
static void RemoveTrackingLocked(
|
||||
gfx::SourceSurfaceSharedDataWrapper* aSurface,
|
||||
const StaticMutexAutoLock& aAutoLock);
|
||||
const StaticMonitorAutoLock& aAutoLock);
|
||||
|
||||
static bool AgeOneGenerationLocked(
|
||||
nsTArray<RefPtr<gfx::SourceSurfaceSharedDataWrapper>>& aExpired,
|
||||
const StaticMutexAutoLock& aAutoLock);
|
||||
const StaticMonitorAutoLock& aAutoLock);
|
||||
|
||||
static void ExpireMap(
|
||||
nsTArray<RefPtr<gfx::SourceSurfaceSharedDataWrapper>>& aExpired);
|
||||
|
||||
static StaticMutex sMutex;
|
||||
static StaticMonitor sMonitor;
|
||||
|
||||
static StaticAutoPtr<SharedSurfacesParent> sInstance;
|
||||
|
||||
@ -100,28 +100,28 @@ class SharedSurfacesParent final {
|
||||
|
||||
class MappingTracker final
|
||||
: public ExpirationTrackerImpl<gfx::SourceSurfaceSharedDataWrapper, 4,
|
||||
StaticMutex, StaticMutexAutoLock> {
|
||||
StaticMonitor, StaticMonitorAutoLock> {
|
||||
public:
|
||||
explicit MappingTracker(uint32_t aExpirationTimeoutMS,
|
||||
nsIEventTarget* aEventTarget)
|
||||
: ExpirationTrackerImpl<gfx::SourceSurfaceSharedDataWrapper, 4,
|
||||
StaticMutex, StaticMutexAutoLock>(
|
||||
StaticMonitor, StaticMonitorAutoLock>(
|
||||
aExpirationTimeoutMS, "SharedMappingTracker", aEventTarget) {}
|
||||
|
||||
void TakeExpired(
|
||||
nsTArray<RefPtr<gfx::SourceSurfaceSharedDataWrapper>>& aExpired,
|
||||
const StaticMutexAutoLock& aAutoLock);
|
||||
const StaticMonitorAutoLock& aAutoLock);
|
||||
|
||||
protected:
|
||||
void NotifyExpiredLocked(gfx::SourceSurfaceSharedDataWrapper* aSurface,
|
||||
const StaticMutexAutoLock& aAutoLock) override;
|
||||
const StaticMonitorAutoLock& aAutoLock) override;
|
||||
|
||||
void NotifyHandlerEndLocked(const StaticMutexAutoLock& aAutoLock) override {
|
||||
}
|
||||
void NotifyHandlerEndLocked(
|
||||
const StaticMonitorAutoLock& aAutoLock) override {}
|
||||
|
||||
void NotifyHandlerEnd() override;
|
||||
|
||||
StaticMutex& GetMutex() override { return sMutex; }
|
||||
StaticMonitor& GetMutex() override { return sMonitor; }
|
||||
|
||||
nsTArray<RefPtr<gfx::SourceSurfaceSharedDataWrapper>> mExpired;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user