Bug 1920580 - Add plumbing to allow compositor process to context reset individual canvases. r=lsalzman
This patch adds the necessary plumbing for accelerated canvas to trigger a context lost / context restored events on the Canvas2D DOM object. Currently we support this when the GPU process is crashed and restored, but accelerated canvas can lose its WebGL context in a similar manner. Note that not all accelerated canvases are impacted. Only the ones without a recent snapshot and/or already fallen back to Skia will require a context lost / restored event. Differential Revision: https://phabricator.services.mozilla.com/D223209
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
#include "mozilla/dom/WorkerRef.h"
|
||||
#include "mozilla/dom/WorkerRunnable.h"
|
||||
#include "mozilla/gfx/CanvasManagerChild.h"
|
||||
#include "mozilla/layers/PersistentBufferProvider.h"
|
||||
|
||||
using namespace mozilla::dom;
|
||||
|
||||
@@ -135,6 +136,31 @@ void CanvasShutdownManager::OnRemoteCanvasRestored() {
|
||||
}
|
||||
}
|
||||
|
||||
void CanvasShutdownManager::OnRemoteCanvasReset(
|
||||
const nsTArray<layers::RemoteTextureOwnerId>& aOwnerIds) {
|
||||
if (aOwnerIds.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto& canvas : mActiveCanvas) {
|
||||
auto* bufferProvider = canvas->GetBufferProvider();
|
||||
if (!bufferProvider) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Maybe<layers::RemoteTextureOwnerId> ownerId =
|
||||
bufferProvider->GetRemoteTextureOwnerId();
|
||||
if (!ownerId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (aOwnerIds.Contains(*ownerId)) {
|
||||
canvas->OnRemoteCanvasLost();
|
||||
canvas->OnRemoteCanvasRestored();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ void CanvasShutdownManager::MaybeRestoreRemoteCanvas() {
|
||||
// Calling Get will recreate the CanvasManagerChild, which in turn will
|
||||
// cause us to call OnRemoteCanvasRestore upon success.
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/StaticMutex.h"
|
||||
#include "mozilla/ThreadLocal.h"
|
||||
#include "mozilla/layers/LayersTypes.h"
|
||||
#include <set>
|
||||
|
||||
namespace mozilla {
|
||||
@@ -34,6 +35,8 @@ class CanvasShutdownManager final {
|
||||
|
||||
void OnRemoteCanvasLost();
|
||||
void OnRemoteCanvasRestored();
|
||||
void OnRemoteCanvasReset(
|
||||
const nsTArray<layers::RemoteTextureOwnerId>& aOwnerIds);
|
||||
|
||||
private:
|
||||
explicit CanvasShutdownManager(dom::StrongWorkerRef* aWorkerRef);
|
||||
|
||||
@@ -153,13 +153,14 @@ PersistentBufferProviderAccelerated::Create(gfx::IntSize aSize,
|
||||
}
|
||||
|
||||
RefPtr<PersistentBufferProviderAccelerated> provider =
|
||||
new PersistentBufferProviderAccelerated(texture);
|
||||
new PersistentBufferProviderAccelerated(remoteTextureOwnerId, texture);
|
||||
return provider.forget();
|
||||
}
|
||||
|
||||
PersistentBufferProviderAccelerated::PersistentBufferProviderAccelerated(
|
||||
RemoteTextureOwnerId aRemoteTextureOwnerId,
|
||||
const RefPtr<TextureClient>& aTexture)
|
||||
: mTexture(aTexture) {
|
||||
: mRemoteTextureOwnerId(aRemoteTextureOwnerId), mTexture(aTexture) {
|
||||
MOZ_COUNT_CTOR(PersistentBufferProviderAccelerated);
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,6 @@ namespace layers {
|
||||
class CompositableForwarder;
|
||||
class FwdTransactionTracker;
|
||||
class KnowsCompositor;
|
||||
struct RemoteTextureOwnerId;
|
||||
class TextureClient;
|
||||
|
||||
/**
|
||||
@@ -80,6 +79,10 @@ class PersistentBufferProvider : public RefCounted<PersistentBufferProvider>,
|
||||
|
||||
virtual TextureClient* GetTextureClient() { return nullptr; }
|
||||
|
||||
virtual Maybe<RemoteTextureOwnerId> GetRemoteTextureOwnerId() const {
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
virtual void OnMemoryPressure() {}
|
||||
|
||||
virtual void OnShutdown() {}
|
||||
@@ -170,6 +173,10 @@ class PersistentBufferProviderAccelerated : public PersistentBufferProvider {
|
||||
|
||||
void ReturnSnapshot(already_AddRefed<gfx::SourceSurface> aSnapshot) override;
|
||||
|
||||
Maybe<RemoteTextureOwnerId> GetRemoteTextureOwnerId() const override {
|
||||
return Some(mRemoteTextureOwnerId);
|
||||
}
|
||||
|
||||
bool PreservesDrawingState() const override { return true; }
|
||||
|
||||
void OnShutdown() override { Destroy(); }
|
||||
@@ -183,11 +190,13 @@ class PersistentBufferProviderAccelerated : public PersistentBufferProvider {
|
||||
|
||||
protected:
|
||||
explicit PersistentBufferProviderAccelerated(
|
||||
RemoteTextureOwnerId aRemoteTextureOwnerId,
|
||||
const RefPtr<TextureClient>& aTexture);
|
||||
~PersistentBufferProviderAccelerated() override;
|
||||
|
||||
void Destroy();
|
||||
|
||||
RemoteTextureOwnerId mRemoteTextureOwnerId;
|
||||
RefPtr<TextureClient> mTexture;
|
||||
|
||||
RefPtr<gfx::DrawTarget> mDrawTarget;
|
||||
|
||||
@@ -47,7 +47,8 @@ const EventType RECYCLE_BUFFER = EventType(EventType::LAST + 15);
|
||||
const EventType DROP_BUFFER = EventType(EventType::LAST + 16);
|
||||
const EventType PREPARE_SHMEM = EventType(EventType::LAST + 17);
|
||||
const EventType PRESENT_TEXTURE = EventType(EventType::LAST + 18);
|
||||
const EventType LAST_CANVAS_EVENT_TYPE = PRESENT_TEXTURE;
|
||||
const EventType DEVICE_RESET_ACKNOWLEDGED = EventType(EventType::LAST + 19);
|
||||
const EventType LAST_CANVAS_EVENT_TYPE = DEVICE_RESET_ACKNOWLEDGED;
|
||||
|
||||
class RecordedCanvasBeginTransaction final
|
||||
: public RecordedEventDerived<RecordedCanvasBeginTransaction> {
|
||||
@@ -485,6 +486,38 @@ template <class S>
|
||||
RecordedDeviceChangeAcknowledged::RecordedDeviceChangeAcknowledged(S& aStream)
|
||||
: RecordedEventDerived(DEVICE_CHANGE_ACKNOWLEDGED) {}
|
||||
|
||||
class RecordedDeviceResetAcknowledged final
|
||||
: public RecordedEventDerived<RecordedDeviceResetAcknowledged> {
|
||||
public:
|
||||
RecordedDeviceResetAcknowledged()
|
||||
: RecordedEventDerived(DEVICE_RESET_ACKNOWLEDGED) {}
|
||||
|
||||
template <class S>
|
||||
MOZ_IMPLICIT RecordedDeviceResetAcknowledged(S& aStream);
|
||||
|
||||
bool PlayCanvasEvent(CanvasTranslator* aTranslator) const;
|
||||
|
||||
template <class S>
|
||||
void Record(S& aStream) const;
|
||||
|
||||
std::string GetName() const final {
|
||||
return "RecordedDeviceResetAcknowledged";
|
||||
}
|
||||
};
|
||||
|
||||
inline bool RecordedDeviceResetAcknowledged::PlayCanvasEvent(
|
||||
CanvasTranslator* aTranslator) const {
|
||||
aTranslator->DeviceResetAcknowledged();
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class S>
|
||||
void RecordedDeviceResetAcknowledged::Record(S& aStream) const {}
|
||||
|
||||
template <class S>
|
||||
RecordedDeviceResetAcknowledged::RecordedDeviceResetAcknowledged(S& aStream)
|
||||
: RecordedEventDerived(DEVICE_RESET_ACKNOWLEDGED) {}
|
||||
|
||||
class RecordedCanvasDrawTargetCreation final
|
||||
: public RecordedEventDerived<RecordedCanvasDrawTargetCreation> {
|
||||
public:
|
||||
@@ -779,7 +812,8 @@ RecordedPresentTexture::RecordedPresentTexture(S& aStream)
|
||||
f(RECYCLE_BUFFER, RecordedRecycleBuffer); \
|
||||
f(DROP_BUFFER, RecordedDropBuffer); \
|
||||
f(PREPARE_SHMEM, RecordedPrepareShmem); \
|
||||
f(PRESENT_TEXTURE, RecordedPresentTexture);
|
||||
f(PRESENT_TEXTURE, RecordedPresentTexture); \
|
||||
f(DEVICE_RESET_ACKNOWLEDGED, RecordedDeviceResetAcknowledged);
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "mozilla/dom/WorkerRef.h"
|
||||
#include "mozilla/dom/WorkerRunnable.h"
|
||||
#include "mozilla/gfx/CanvasManagerChild.h"
|
||||
#include "mozilla/gfx/CanvasShutdownManager.h"
|
||||
#include "mozilla/gfx/DrawTargetRecording.h"
|
||||
#include "mozilla/gfx/Tools.h"
|
||||
#include "mozilla/gfx/Rect.h"
|
||||
@@ -276,7 +277,7 @@ CanvasChild::CanvasChild(dom::ThreadSafeWorkerRef* aWorkerRef)
|
||||
|
||||
CanvasChild::~CanvasChild() { MOZ_ASSERT(!mWorkerRef); }
|
||||
|
||||
static void NotifyCanvasDeviceReset() {
|
||||
static void NotifyCanvasDeviceChanged() {
|
||||
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
||||
if (obs) {
|
||||
obs->NotifyObservers(nullptr, "canvas-device-reset", nullptr);
|
||||
@@ -286,11 +287,23 @@ static void NotifyCanvasDeviceReset() {
|
||||
ipc::IPCResult CanvasChild::RecvNotifyDeviceChanged() {
|
||||
NS_ASSERT_OWNINGTHREAD(CanvasChild);
|
||||
|
||||
NotifyCanvasDeviceReset();
|
||||
NotifyCanvasDeviceChanged();
|
||||
mRecorder->RecordEvent(RecordedDeviceChangeAcknowledged());
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
ipc::IPCResult CanvasChild::RecvNotifyDeviceReset(
|
||||
const nsTArray<RemoteTextureOwnerId>& aOwnerIds) {
|
||||
NS_ASSERT_OWNINGTHREAD(CanvasChild);
|
||||
|
||||
if (auto* manager = gfx::CanvasShutdownManager::MaybeGet()) {
|
||||
manager->OnRemoteCanvasReset(aOwnerIds);
|
||||
}
|
||||
|
||||
mRecorder->RecordEvent(RecordedDeviceResetAcknowledged());
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
/* static */ bool CanvasChild::mDeactivated = false;
|
||||
|
||||
ipc::IPCResult CanvasChild::RecvDeactivate() {
|
||||
@@ -301,7 +314,7 @@ ipc::IPCResult CanvasChild::RecvDeactivate() {
|
||||
if (auto* cm = gfx::CanvasManagerChild::Get()) {
|
||||
cm->DeactivateCanvas();
|
||||
}
|
||||
NotifyCanvasDeviceReset();
|
||||
NotifyCanvasDeviceChanged();
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
|
||||
@@ -46,6 +46,9 @@ class CanvasChild final : public PCanvasChild, public SupportsWeakPtr {
|
||||
|
||||
ipc::IPCResult RecvNotifyDeviceChanged();
|
||||
|
||||
ipc::IPCResult RecvNotifyDeviceReset(
|
||||
const nsTArray<RemoteTextureOwnerId>& aOwnerIds);
|
||||
|
||||
ipc::IPCResult RecvDeactivate();
|
||||
|
||||
ipc::IPCResult RecvBlockCanvas();
|
||||
|
||||
@@ -862,6 +862,8 @@ void CanvasTranslator::DeviceChangeAcknowledged() {
|
||||
}
|
||||
}
|
||||
|
||||
void CanvasTranslator::DeviceResetAcknowledged() { DeviceChangeAcknowledged(); }
|
||||
|
||||
bool CanvasTranslator::CreateReferenceTexture() {
|
||||
if (mReferenceTextureData) {
|
||||
mReferenceTextureData->Unlock();
|
||||
|
||||
@@ -147,6 +147,11 @@ class CanvasTranslator final : public gfx::InlineTranslator,
|
||||
*/
|
||||
void DeviceChangeAcknowledged();
|
||||
|
||||
/**
|
||||
* Marks that device reset processing in the writing process has finished.
|
||||
*/
|
||||
void DeviceResetAcknowledged();
|
||||
|
||||
/**
|
||||
* Used during playback of events to create DrawTargets. For the
|
||||
* CanvasTranslator this means creating TextureDatas and getting the
|
||||
|
||||
@@ -9,6 +9,7 @@ include "mozilla/layers/LayersMessageUtils.h";
|
||||
include "mozilla/layers/CanvasTranslator.h";
|
||||
|
||||
[MoveOnly] using mozilla::CrossProcessSemaphoreHandle from "mozilla/ipc/CrossProcessSemaphore.h";
|
||||
using mozilla::layers::RemoteTextureOwnerId from "mozilla/layers/LayersTypes.h";
|
||||
using mozilla::layers::TextureType from "mozilla/layers/LayersTypes.h";
|
||||
[MoveOnly] using mozilla::ipc::SharedMemory::Handle from "mozilla/ipc/SharedMemory.h";
|
||||
using mozilla::gfx::BackendType from "mozilla/gfx/Types.h";
|
||||
@@ -72,6 +73,11 @@ child:
|
||||
*/
|
||||
async NotifyDeviceChanged();
|
||||
|
||||
/**
|
||||
* Notify that the canvas device used by the translator has been reset.
|
||||
*/
|
||||
async NotifyDeviceReset(RemoteTextureOwnerId[] aOwners);
|
||||
|
||||
/**
|
||||
* Deactivate remote canvas, which will cause fall back to software.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user