forked from mirrors/gecko-dev
Bug 1877429 - Prevent offscreen canvas2d updates from racing with compositing. r=gfx-reviewers,lsalzman
When OffscreenCanvas::CommitFrameToCompositor uses the non-remote texture canvas path with Skia, it uses ImageBridgeChild for compositing. When ImageContainer::SetCurrentImages is called, there was an intermediate state where the relevant textures were not yet marked as read only for the compositor's consumption, because the event to do so was dispatched asynchronously to the ImageBridgeChild thread. If the owning thread of the canvas (main or DOM worker) ran immediately after CommitFrameToCompositor, then we could run into texture reuse since nothing marked the texture yet as being used for compositing. This had the end result of sometimes displaying back buffer textures currently being used for drawing on the display pipeline. This patch makes it so that we mark OffscreenCanvas textures as read only for the compositor before dispatching, and releasing the lock either when we swap the images in the ImageContainer (winning the race with ImageBridgeChild), or after the compositor has finished with it (losing the race, if any, with ImageBridgeChild). Additionally, to handle better the case where we run out of buffers, we need to implement ImageBridgeChild::SyncWithCompositor, to be analogous to how WebRenderBridgeChild::SyncWithCompositor works. We achieve this by calling from ImageBridgeChild back into the appropriate WebRenderBridgeChild based on the window ID associated with the canvas, It also adds a new pref, gfx.offscreencanvas.shared-provider, which allows one to switch between PersistentBufferProviderShared and Basic. The latter of which is used if we fallback from using shared buffers if it takes too long to get the shared buffers back from the compositor. Differential Revision: https://phabricator.services.mozilla.com/D200991
This commit is contained in:
parent
5f2afd585c
commit
4d74abb189
18 changed files with 174 additions and 27 deletions
|
|
@ -1492,8 +1492,7 @@ bool CanvasRenderingContext2D::BorrowTarget(const IntRect& aPersistedRect,
|
||||||
bool CanvasRenderingContext2D::EnsureTarget(const gfx::Rect* aCoveredRect,
|
bool CanvasRenderingContext2D::EnsureTarget(const gfx::Rect* aCoveredRect,
|
||||||
bool aWillClear) {
|
bool aWillClear) {
|
||||||
if (AlreadyShutDown()) {
|
if (AlreadyShutDown()) {
|
||||||
gfxCriticalErrorOnce()
|
gfxCriticalNoteOnce << "Attempt to render into a Canvas2d after shutdown.";
|
||||||
<< "Attempt to render into a Canvas2d after shutdown.";
|
|
||||||
SetErrorState();
|
SetErrorState();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -1726,6 +1725,10 @@ bool CanvasRenderingContext2D::TrySharedTarget(
|
||||||
GetSize(), GetSurfaceFormat(),
|
GetSize(), GetSurfaceFormat(),
|
||||||
!mAllowAcceleration || GetEffectiveWillReadFrequently());
|
!mAllowAcceleration || GetEffectiveWillReadFrequently());
|
||||||
} else if (mOffscreenCanvas) {
|
} else if (mOffscreenCanvas) {
|
||||||
|
if (!StaticPrefs::gfx_offscreencanvas_shared_provider()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
RefPtr<layers::ImageBridgeChild> imageBridge =
|
RefPtr<layers::ImageBridgeChild> imageBridge =
|
||||||
layers::ImageBridgeChild::GetSingleton();
|
layers::ImageBridgeChild::GetSingleton();
|
||||||
if (NS_WARN_IF(!imageBridge)) {
|
if (NS_WARN_IF(!imageBridge)) {
|
||||||
|
|
@ -1734,7 +1737,8 @@ bool CanvasRenderingContext2D::TrySharedTarget(
|
||||||
|
|
||||||
aOutProvider = layers::PersistentBufferProviderShared::Create(
|
aOutProvider = layers::PersistentBufferProviderShared::Create(
|
||||||
GetSize(), GetSurfaceFormat(), imageBridge,
|
GetSize(), GetSurfaceFormat(), imageBridge,
|
||||||
!mAllowAcceleration || GetEffectiveWillReadFrequently());
|
!mAllowAcceleration || GetEffectiveWillReadFrequently(),
|
||||||
|
mOffscreenCanvas->GetWindowID());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!aOutProvider) {
|
if (!aOutProvider) {
|
||||||
|
|
|
||||||
|
|
@ -281,6 +281,19 @@ OffscreenCanvas::CreateContext(CanvasContextType aContextType) {
|
||||||
return ret.forget();
|
return ret.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Maybe<uint64_t> OffscreenCanvas::GetWindowID() {
|
||||||
|
if (NS_IsMainThread()) {
|
||||||
|
if (nsIGlobalObject* global = GetOwnerGlobal()) {
|
||||||
|
if (auto* window = global->GetAsInnerWindow()) {
|
||||||
|
return Some(window->WindowID());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (auto* workerPrivate = GetCurrentThreadWorkerPrivate()) {
|
||||||
|
return Some(workerPrivate->WindowID());
|
||||||
|
}
|
||||||
|
return Nothing();
|
||||||
|
}
|
||||||
|
|
||||||
void OffscreenCanvas::UpdateDisplayData(
|
void OffscreenCanvas::UpdateDisplayData(
|
||||||
const OffscreenCanvasDisplayData& aData) {
|
const OffscreenCanvasDisplayData& aData) {
|
||||||
if (!mDisplay) {
|
if (!mDisplay) {
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,8 @@ class OffscreenCanvas final : public DOMEventTargetHelper,
|
||||||
JS::Handle<JS::Value> aParams,
|
JS::Handle<JS::Value> aParams,
|
||||||
ErrorResult& aRv);
|
ErrorResult& aRv);
|
||||||
|
|
||||||
|
Maybe<uint64_t> GetWindowID();
|
||||||
|
|
||||||
nsICanvasRenderingContextInternal* GetContext() const {
|
nsICanvasRenderingContextInternal* GetContext() const {
|
||||||
return mCurrentContext;
|
return mCurrentContext;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -319,6 +319,9 @@ void ImageContainer::SetCurrentImageInternal(
|
||||||
if (aImages[0].mProducerID != mCurrentProducerID) {
|
if (aImages[0].mProducerID != mCurrentProducerID) {
|
||||||
mCurrentProducerID = aImages[0].mProducerID;
|
mCurrentProducerID = aImages[0].mProducerID;
|
||||||
}
|
}
|
||||||
|
for (auto& img : mCurrentImages) {
|
||||||
|
img.mImage->OnAbandonForwardToHost();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nsTArray<OwningImage> newImages;
|
nsTArray<OwningImage> newImages;
|
||||||
|
|
@ -347,6 +350,7 @@ void ImageContainer::SetCurrentImageInternal(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
img->mImage->OnPrepareForwardToHost();
|
||||||
}
|
}
|
||||||
|
|
||||||
mCurrentImages = std::move(newImages);
|
mCurrentImages = std::move(newImages);
|
||||||
|
|
|
||||||
|
|
@ -129,6 +129,9 @@ class Image {
|
||||||
bool IsDRM() const { return mIsDRM; }
|
bool IsDRM() const { return mIsDRM; }
|
||||||
virtual void SetIsDRM(bool aIsDRM) { mIsDRM = aIsDRM; }
|
virtual void SetIsDRM(bool aIsDRM) { mIsDRM = aIsDRM; }
|
||||||
|
|
||||||
|
virtual void OnPrepareForwardToHost() {}
|
||||||
|
virtual void OnAbandonForwardToHost() {}
|
||||||
|
|
||||||
virtual already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() = 0;
|
virtual already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() = 0;
|
||||||
|
|
||||||
enum class BuildSdbFlags : uint8_t {
|
enum class BuildSdbFlags : uint8_t {
|
||||||
|
|
|
||||||
|
|
@ -266,7 +266,8 @@ already_AddRefed<PersistentBufferProviderShared>
|
||||||
PersistentBufferProviderShared::Create(gfx::IntSize aSize,
|
PersistentBufferProviderShared::Create(gfx::IntSize aSize,
|
||||||
gfx::SurfaceFormat aFormat,
|
gfx::SurfaceFormat aFormat,
|
||||||
KnowsCompositor* aKnowsCompositor,
|
KnowsCompositor* aKnowsCompositor,
|
||||||
bool aWillReadFrequently) {
|
bool aWillReadFrequently,
|
||||||
|
const Maybe<uint64_t>& aWindowID) {
|
||||||
if (!aKnowsCompositor || !aKnowsCompositor->GetTextureForwarder() ||
|
if (!aKnowsCompositor || !aKnowsCompositor->GetTextureForwarder() ||
|
||||||
!aKnowsCompositor->GetTextureForwarder()->IPCOpen()) {
|
!aKnowsCompositor->GetTextureForwarder()->IPCOpen()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
@ -290,19 +291,21 @@ PersistentBufferProviderShared::Create(gfx::IntSize aSize,
|
||||||
|
|
||||||
RefPtr<PersistentBufferProviderShared> provider =
|
RefPtr<PersistentBufferProviderShared> provider =
|
||||||
new PersistentBufferProviderShared(aSize, aFormat, aKnowsCompositor,
|
new PersistentBufferProviderShared(aSize, aFormat, aKnowsCompositor,
|
||||||
texture, aWillReadFrequently);
|
texture, aWillReadFrequently,
|
||||||
|
aWindowID);
|
||||||
return provider.forget();
|
return provider.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
PersistentBufferProviderShared::PersistentBufferProviderShared(
|
PersistentBufferProviderShared::PersistentBufferProviderShared(
|
||||||
gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
||||||
KnowsCompositor* aKnowsCompositor, RefPtr<TextureClient>& aTexture,
|
KnowsCompositor* aKnowsCompositor, RefPtr<TextureClient>& aTexture,
|
||||||
bool aWillReadFrequently)
|
bool aWillReadFrequently, const Maybe<uint64_t>& aWindowID)
|
||||||
: mSize(aSize),
|
: mSize(aSize),
|
||||||
mFormat(aFormat),
|
mFormat(aFormat),
|
||||||
mKnowsCompositor(aKnowsCompositor),
|
mKnowsCompositor(aKnowsCompositor),
|
||||||
mFront(Nothing()),
|
mFront(Nothing()),
|
||||||
mWillReadFrequently(aWillReadFrequently) {
|
mWillReadFrequently(aWillReadFrequently),
|
||||||
|
mWindowID(aWindowID) {
|
||||||
MOZ_ASSERT(aKnowsCompositor);
|
MOZ_ASSERT(aKnowsCompositor);
|
||||||
if (mTextures.append(aTexture)) {
|
if (mTextures.append(aTexture)) {
|
||||||
mBack = Some<uint32_t>(0);
|
mBack = Some<uint32_t>(0);
|
||||||
|
|
@ -481,7 +484,7 @@ PersistentBufferProviderShared::BorrowDrawTarget(
|
||||||
// especially when switching between layer managers (during tab-switch).
|
// especially when switching between layer managers (during tab-switch).
|
||||||
// To make sure we don't get too far ahead of the compositor, we send a
|
// To make sure we don't get too far ahead of the compositor, we send a
|
||||||
// sync ping to the compositor thread...
|
// sync ping to the compositor thread...
|
||||||
mKnowsCompositor->SyncWithCompositor();
|
mKnowsCompositor->SyncWithCompositor(mWindowID);
|
||||||
// ...and try again.
|
// ...and try again.
|
||||||
for (uint32_t i = 0; i < mTextures.length(); ++i) {
|
for (uint32_t i = 0; i < mTextures.length(); ++i) {
|
||||||
if (!mTextures[i]->IsReadLocked()) {
|
if (!mTextures[i]->IsReadLocked()) {
|
||||||
|
|
|
||||||
|
|
@ -206,7 +206,8 @@ class PersistentBufferProviderShared : public PersistentBufferProvider,
|
||||||
|
|
||||||
static already_AddRefed<PersistentBufferProviderShared> Create(
|
static already_AddRefed<PersistentBufferProviderShared> Create(
|
||||||
gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
||||||
KnowsCompositor* aKnowsCompositor, bool aWillReadFrequently = false);
|
KnowsCompositor* aKnowsCompositor, bool aWillReadFrequently = false,
|
||||||
|
const Maybe<uint64_t>& aWindowID = Nothing());
|
||||||
|
|
||||||
bool IsShared() const override { return true; }
|
bool IsShared() const override { return true; }
|
||||||
|
|
||||||
|
|
@ -237,7 +238,8 @@ class PersistentBufferProviderShared : public PersistentBufferProvider,
|
||||||
PersistentBufferProviderShared(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
PersistentBufferProviderShared(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
||||||
KnowsCompositor* aKnowsCompositor,
|
KnowsCompositor* aKnowsCompositor,
|
||||||
RefPtr<TextureClient>& aTexture,
|
RefPtr<TextureClient>& aTexture,
|
||||||
bool aWillReadFrequently);
|
bool aWillReadFrequently,
|
||||||
|
const Maybe<uint64_t>& aWindowID);
|
||||||
|
|
||||||
~PersistentBufferProviderShared();
|
~PersistentBufferProviderShared();
|
||||||
|
|
||||||
|
|
@ -262,6 +264,8 @@ class PersistentBufferProviderShared : public PersistentBufferProvider,
|
||||||
Maybe<uint32_t> mFront;
|
Maybe<uint32_t> mFront;
|
||||||
// Whether to avoid acceleration.
|
// Whether to avoid acceleration.
|
||||||
bool mWillReadFrequently = false;
|
bool mWillReadFrequently = false;
|
||||||
|
// Owning window ID of the buffer provider.
|
||||||
|
Maybe<uint64_t> mWindowID;
|
||||||
|
|
||||||
RefPtr<gfx::DrawTarget> mDrawTarget;
|
RefPtr<gfx::DrawTarget> mDrawTarget;
|
||||||
RefPtr<gfx::SourceSurface> mSnapshot;
|
RefPtr<gfx::SourceSurface> mSnapshot;
|
||||||
|
|
|
||||||
|
|
@ -45,5 +45,13 @@ TextureClient* TextureWrapperImage::GetTextureClient(
|
||||||
return mTextureClient;
|
return mTextureClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextureWrapperImage::OnPrepareForwardToHost() {
|
||||||
|
mTextureClient->OnPrepareForwardToHost();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextureWrapperImage::OnAbandonForwardToHost() {
|
||||||
|
mTextureClient->OnAbandonForwardToHost();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace layers
|
} // namespace layers
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,8 @@ class TextureWrapperImage final : public Image {
|
||||||
gfx::IntRect GetPictureRect() const override;
|
gfx::IntRect GetPictureRect() const override;
|
||||||
already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() override;
|
already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() override;
|
||||||
TextureClient* GetTextureClient(KnowsCompositor* aKnowsCompositor) override;
|
TextureClient* GetTextureClient(KnowsCompositor* aKnowsCompositor) override;
|
||||||
|
void OnPrepareForwardToHost() override;
|
||||||
|
void OnAbandonForwardToHost() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
gfx::IntRect mPictureRect;
|
gfx::IntRect mPictureRect;
|
||||||
|
|
|
||||||
|
|
@ -839,30 +839,77 @@ void TextureClient::EnableReadLock() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextureClient::OnPrepareForwardToHost() {
|
||||||
|
if (!ShouldReadLock()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MutexAutoLock lock(mMutex);
|
||||||
|
if (NS_WARN_IF(!mReadLock)) {
|
||||||
|
MOZ_ASSERT(!mAllocator->IPCOpen(), "Should have created readlock already!");
|
||||||
|
MOZ_ASSERT(!mIsPendingForwardReadLocked);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mIsPendingForwardReadLocked) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mReadLock->ReadLock();
|
||||||
|
mIsPendingForwardReadLocked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextureClient::OnAbandonForwardToHost() {
|
||||||
|
if (!ShouldReadLock()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MutexAutoLock lock(mMutex);
|
||||||
|
if (!mReadLock || !mIsPendingForwardReadLocked) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mReadLock->ReadUnlock();
|
||||||
|
mIsPendingForwardReadLocked = false;
|
||||||
|
}
|
||||||
|
|
||||||
bool TextureClient::OnForwardedToHost() {
|
bool TextureClient::OnForwardedToHost() {
|
||||||
if (mData) {
|
if (mData) {
|
||||||
mData->OnForwardedToHost();
|
mData->OnForwardedToHost();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ShouldReadLock() || !mUpdated) {
|
if (!ShouldReadLock()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
MutexAutoLock lock(mMutex);
|
||||||
MutexAutoLock lock(mMutex);
|
EnsureHasReadLock();
|
||||||
EnsureHasReadLock();
|
|
||||||
|
|
||||||
if (NS_WARN_IF(!mReadLock)) {
|
if (NS_WARN_IF(!mReadLock)) {
|
||||||
MOZ_ASSERT(!mAllocator->IPCOpen());
|
MOZ_ASSERT(!mAllocator->IPCOpen());
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mUpdated) {
|
||||||
|
if (mIsPendingForwardReadLocked) {
|
||||||
|
mIsPendingForwardReadLocked = false;
|
||||||
|
mReadLock->ReadUnlock();
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
// Take a read lock on behalf of the TextureHost. The latter will unlock
|
|
||||||
// after the shared data is available again for drawing.
|
|
||||||
mReadLock->ReadLock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mUpdated = false;
|
mUpdated = false;
|
||||||
|
|
||||||
|
if (mIsPendingForwardReadLocked) {
|
||||||
|
// We have successfully forwarded, just clear the flag and let the
|
||||||
|
// TextureHost be responsible for unlocking.
|
||||||
|
mIsPendingForwardReadLocked = false;
|
||||||
|
} else {
|
||||||
|
// Otherwise we did not need to readlock in advance, so do so now. We do
|
||||||
|
// this on behalf of the TextureHost.
|
||||||
|
mReadLock->ReadLock();
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -677,6 +677,8 @@ class TextureClient : public AtomicRefCountedWithFinalize<TextureClient> {
|
||||||
|
|
||||||
void SetUpdated() { mUpdated = true; }
|
void SetUpdated() { mUpdated = true; }
|
||||||
|
|
||||||
|
void OnPrepareForwardToHost();
|
||||||
|
void OnAbandonForwardToHost();
|
||||||
bool OnForwardedToHost();
|
bool OnForwardedToHost();
|
||||||
|
|
||||||
// Mark that the TextureClient will be used by the paint thread, and should
|
// Mark that the TextureClient will be used by the paint thread, and should
|
||||||
|
|
@ -762,6 +764,7 @@ class TextureClient : public AtomicRefCountedWithFinalize<TextureClient> {
|
||||||
#endif
|
#endif
|
||||||
bool mIsLocked;
|
bool mIsLocked;
|
||||||
bool mIsReadLocked MOZ_GUARDED_BY(mMutex);
|
bool mIsReadLocked MOZ_GUARDED_BY(mMutex);
|
||||||
|
bool mIsPendingForwardReadLocked MOZ_GUARDED_BY(mMutex) = false;
|
||||||
// This member tracks that the texture was written into until the update
|
// This member tracks that the texture was written into until the update
|
||||||
// is sent to the compositor. We need this remember to lock mReadLock on
|
// is sent to the compositor. We need this remember to lock mReadLock on
|
||||||
// behalf of the compositor just before sending the notification.
|
// behalf of the compositor just before sending the notification.
|
||||||
|
|
|
||||||
|
|
@ -33,10 +33,12 @@
|
||||||
#include "mozilla/mozalloc.h" // for operator new, etc
|
#include "mozilla/mozalloc.h" // for operator new, etc
|
||||||
#include "transport/runnable_utils.h"
|
#include "transport/runnable_utils.h"
|
||||||
#include "nsContentUtils.h"
|
#include "nsContentUtils.h"
|
||||||
|
#include "nsGlobalWindowInner.h"
|
||||||
#include "nsISupportsImpl.h" // for ImageContainer::AddRef, etc
|
#include "nsISupportsImpl.h" // for ImageContainer::AddRef, etc
|
||||||
#include "nsTArray.h" // for AutoTArray, nsTArray, etc
|
#include "nsTArray.h" // for AutoTArray, nsTArray, etc
|
||||||
#include "nsTArrayForwardDeclare.h" // for AutoTArray
|
#include "nsTArrayForwardDeclare.h" // for AutoTArray
|
||||||
#include "nsThreadUtils.h" // for NS_IsMainThread
|
#include "nsThreadUtils.h" // for NS_IsMainThread
|
||||||
|
#include "WindowRenderer.h"
|
||||||
|
|
||||||
#if defined(XP_WIN)
|
#if defined(XP_WIN)
|
||||||
# include "mozilla/gfx/DeviceManagerDx.h"
|
# include "mozilla/gfx/DeviceManagerDx.h"
|
||||||
|
|
@ -395,6 +397,43 @@ void ImageBridgeChild::FlushAllImages(ImageClient* aClient,
|
||||||
task.Wait();
|
task.Wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ImageBridgeChild::SyncWithCompositor(const Maybe<uint64_t>& aWindowID) {
|
||||||
|
if (NS_WARN_IF(InImageBridgeChildThread())) {
|
||||||
|
MOZ_ASSERT_UNREACHABLE("Cannot call on ImageBridge thread!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!aWindowID) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto fnSyncWithWindow = [&]() {
|
||||||
|
if (auto* window = nsGlobalWindowInner::GetInnerWindowWithId(*aWindowID)) {
|
||||||
|
if (auto* widget = window->GetNearestWidget()) {
|
||||||
|
if (auto* renderer = widget->GetWindowRenderer()) {
|
||||||
|
if (auto* kc = renderer->AsKnowsCompositor()) {
|
||||||
|
kc->SyncWithCompositor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (NS_IsMainThread()) {
|
||||||
|
fnSyncWithWindow();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SynchronousTask task("SyncWithCompositor Lock");
|
||||||
|
RefPtr<Runnable> runnable =
|
||||||
|
NS_NewRunnableFunction("ImageBridgeChild::SyncWithCompositor", [&]() {
|
||||||
|
AutoCompleteTask complete(&task);
|
||||||
|
fnSyncWithWindow();
|
||||||
|
});
|
||||||
|
NS_DispatchToMainThread(runnable.forget());
|
||||||
|
task.Wait();
|
||||||
|
}
|
||||||
|
|
||||||
void ImageBridgeChild::BeginTransaction() {
|
void ImageBridgeChild::BeginTransaction() {
|
||||||
MOZ_ASSERT(CanSend());
|
MOZ_ASSERT(CanSend());
|
||||||
MOZ_ASSERT(mTxn->Finished(), "uncommitted txn?");
|
MOZ_ASSERT(mTxn->Finished(), "uncommitted txn?");
|
||||||
|
|
|
||||||
|
|
@ -166,6 +166,9 @@ class ImageBridgeChild final : public PImageBridgeChild,
|
||||||
|
|
||||||
base::ProcessId GetParentPid() const override { return OtherPid(); }
|
base::ProcessId GetParentPid() const override { return OtherPid(); }
|
||||||
|
|
||||||
|
void SyncWithCompositor(
|
||||||
|
const Maybe<uint64_t>& aWindowID = Nothing()) override;
|
||||||
|
|
||||||
PTextureChild* AllocPTextureChild(
|
PTextureChild* AllocPTextureChild(
|
||||||
const SurfaceDescriptor& aSharedData, ReadLockDescriptor& aReadLock,
|
const SurfaceDescriptor& aSharedData, ReadLockDescriptor& aReadLock,
|
||||||
const LayersBackend& aLayersBackend, const TextureFlags& aFlags,
|
const LayersBackend& aLayersBackend, const TextureFlags& aFlags,
|
||||||
|
|
|
||||||
|
|
@ -46,8 +46,9 @@ LayersIPCActor* KnowsCompositorMediaProxy::GetLayersIPCActor() {
|
||||||
return mThreadSafeAllocator->GetLayersIPCActor();
|
return mThreadSafeAllocator->GetLayersIPCActor();
|
||||||
}
|
}
|
||||||
|
|
||||||
void KnowsCompositorMediaProxy::SyncWithCompositor() {
|
void KnowsCompositorMediaProxy::SyncWithCompositor(
|
||||||
mThreadSafeAllocator->SyncWithCompositor();
|
const Maybe<uint64_t>& aWindowID) {
|
||||||
|
mThreadSafeAllocator->SyncWithCompositor(aWindowID);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsSurfaceDescriptorValid(const SurfaceDescriptor& aSurface) {
|
bool IsSurfaceDescriptorValid(const SurfaceDescriptor& aSurface) {
|
||||||
|
|
|
||||||
|
|
@ -175,7 +175,10 @@ class KnowsCompositor {
|
||||||
* content process accumulates resource allocations that the compositor is not
|
* content process accumulates resource allocations that the compositor is not
|
||||||
* consuming and releasing.
|
* consuming and releasing.
|
||||||
*/
|
*/
|
||||||
virtual void SyncWithCompositor() { MOZ_ASSERT_UNREACHABLE("Unimplemented"); }
|
virtual void SyncWithCompositor(
|
||||||
|
const Maybe<uint64_t>& aWindowID = Nothing()) {
|
||||||
|
MOZ_ASSERT_UNREACHABLE("Unimplemented");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helpers for finding other related interface. These are infallible.
|
* Helpers for finding other related interface. These are infallible.
|
||||||
|
|
@ -216,7 +219,8 @@ class KnowsCompositorMediaProxy : public KnowsCompositor {
|
||||||
|
|
||||||
LayersIPCActor* GetLayersIPCActor() override;
|
LayersIPCActor* GetLayersIPCActor() override;
|
||||||
|
|
||||||
void SyncWithCompositor() override;
|
void SyncWithCompositor(
|
||||||
|
const Maybe<uint64_t>& aWindowID = Nothing()) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~KnowsCompositorMediaProxy();
|
virtual ~KnowsCompositorMediaProxy();
|
||||||
|
|
|
||||||
|
|
@ -347,7 +347,8 @@ LayersIPCActor* WebRenderBridgeChild::GetLayersIPCActor() {
|
||||||
return static_cast<LayersIPCActor*>(GetCompositorBridgeChild());
|
return static_cast<LayersIPCActor*>(GetCompositorBridgeChild());
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebRenderBridgeChild::SyncWithCompositor() {
|
void WebRenderBridgeChild::SyncWithCompositor(
|
||||||
|
const Maybe<uint64_t>& aWindowID) {
|
||||||
if (!IPCOpen()) {
|
if (!IPCOpen()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -93,7 +93,8 @@ class WebRenderBridgeChild final : public PWebRenderBridgeChild,
|
||||||
// KnowsCompositor
|
// KnowsCompositor
|
||||||
TextureForwarder* GetTextureForwarder() override;
|
TextureForwarder* GetTextureForwarder() override;
|
||||||
LayersIPCActor* GetLayersIPCActor() override;
|
LayersIPCActor* GetLayersIPCActor() override;
|
||||||
void SyncWithCompositor() override;
|
void SyncWithCompositor(
|
||||||
|
const Maybe<uint64_t>& aWindowID = Nothing()) override;
|
||||||
|
|
||||||
void AddPipelineIdForCompositable(const wr::PipelineId& aPipelineId,
|
void AddPipelineIdForCompositable(const wr::PipelineId& aPipelineId,
|
||||||
const CompositableHandle& aHandle,
|
const CompositableHandle& aHandle,
|
||||||
|
|
|
||||||
|
|
@ -6195,6 +6195,11 @@
|
||||||
value: true
|
value: true
|
||||||
mirror: always
|
mirror: always
|
||||||
|
|
||||||
|
- name: gfx.offscreencanvas.shared-provider
|
||||||
|
type: RelaxedAtomicBool
|
||||||
|
value: true
|
||||||
|
mirror: always
|
||||||
|
|
||||||
- name: gfx.omta.background-color
|
- name: gfx.omta.background-color
|
||||||
type: bool
|
type: bool
|
||||||
value: true
|
value: true
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue