Bug 1855742 - Part 3. Allow recording based canvases with OffscreenCanvas. r=gfx-reviewers,lsalzman

It is disabled in this patch via the gfx.canvas.remote.allow-offscreen
pref. A follow up patch will enable this by default.

Differential Revision: https://phabricator.services.mozilla.com/D189532
This commit is contained in:
Andrew Osmond 2024-02-21 03:08:03 +00:00
Родитель c743180764
Коммит 89415472e9
4 изменённых файлов: 61 добавлений и 13 удалений

Просмотреть файл

@ -118,6 +118,7 @@
#include "mozilla/dom/SVGImageElement.h"
#include "mozilla/dom/TextMetrics.h"
#include "mozilla/FloatingPoint.h"
#include "mozilla/Logging.h"
#include "nsGlobalWindowInner.h"
#include "nsDeviceContext.h"
#include "nsFontMetrics.h"
@ -1684,15 +1685,27 @@ bool CanvasRenderingContext2D::TryAcceleratedTarget(
return false;
}
if (!mCanvasElement) {
return false;
if (mCanvasElement) {
MOZ_ASSERT(NS_IsMainThread());
WindowRenderer* renderer = WindowRendererFromCanvasElement(mCanvasElement);
if (NS_WARN_IF(!renderer)) {
return false;
}
aOutProvider = PersistentBufferProviderAccelerated::Create(
GetSize(), GetSurfaceFormat(), renderer->AsKnowsCompositor());
} else if (mOffscreenCanvas &&
StaticPrefs::gfx_canvas_remote_allow_offscreen()) {
RefPtr<ImageBridgeChild> imageBridge = ImageBridgeChild::GetSingleton();
if (NS_WARN_IF(!imageBridge)) {
return false;
}
aOutProvider = PersistentBufferProviderAccelerated::Create(
GetSize(), GetSurfaceFormat(), imageBridge);
}
WindowRenderer* renderer = WindowRendererFromCanvasElement(mCanvasElement);
if (!renderer) {
return false;
}
aOutProvider = PersistentBufferProviderAccelerated::Create(
GetSize(), GetSurfaceFormat(), renderer->AsKnowsCompositor());
if (!aOutProvider) {
return false;
}
@ -1716,8 +1729,10 @@ bool CanvasRenderingContext2D::TrySharedTarget(
}
if (mCanvasElement) {
MOZ_ASSERT(NS_IsMainThread());
WindowRenderer* renderer = WindowRendererFromCanvasElement(mCanvasElement);
if (!renderer) {
if (NS_WARN_IF(!renderer)) {
return false;
}
@ -1735,7 +1750,7 @@ bool CanvasRenderingContext2D::TrySharedTarget(
return false;
}
aOutProvider = layers::PersistentBufferProviderShared::Create(
aOutProvider = PersistentBufferProviderShared::Create(
GetSize(), GetSurfaceFormat(), imageBridge,
!mAllowAcceleration || GetEffectiveWillReadFrequently(),
mOffscreenCanvas->GetWindowID());

Просмотреть файл

@ -38,11 +38,25 @@ void OffscreenCanvasDisplayHelper::DestroyElement() {
MOZ_ASSERT(NS_IsMainThread());
MutexAutoLock lock(mMutex);
if (mImageContainer) {
mImageContainer->ClearAllImages();
mImageContainer = nullptr;
}
mFrontBufferSurface = nullptr;
mCanvasElement = nullptr;
}
void OffscreenCanvasDisplayHelper::DestroyCanvas() {
if (auto* cm = gfx::CanvasManagerChild::Get()) {
cm->EndCanvasTransaction();
}
MutexAutoLock lock(mMutex);
if (mImageContainer) {
mImageContainer->ClearAllImages();
mImageContainer = nullptr;
}
mFrontBufferSurface = nullptr;
mOffscreenCanvas = nullptr;
mWorkerRef = nullptr;
}
@ -141,6 +155,12 @@ bool OffscreenCanvasDisplayHelper::CommitFrameToCompositor(
nsICanvasRenderingContextInternal* aContext,
layers::TextureType aTextureType,
const Maybe<OffscreenCanvasDisplayData>& aData) {
auto endTransaction = MakeScopeExit([&]() {
if (auto* cm = gfx::CanvasManagerChild::Get()) {
cm->EndCanvasTransaction();
}
});
MutexAutoLock lock(mMutex);
gfx::SurfaceFormat format = gfx::SurfaceFormat::B8G8R8A8;

Просмотреть файл

@ -13,6 +13,7 @@
#include "mozilla/gfx/DrawTargetWebgl.h"
#include "mozilla/gfx/gfxVars.h"
#include "mozilla/gfx/GPUParent.h"
#include "mozilla/gfx/GPUProcessManager.h"
#include "mozilla/gfx/Logging.h"
#include "mozilla/ipc/Endpoint.h"
#include "mozilla/layers/BufferTexture.h"
@ -728,9 +729,15 @@ bool CanvasTranslator::CheckForFreshCanvasDevice(int aLineNumber) {
NotifyDeviceChanged();
}
RefPtr<Runnable> runnable = NS_NewRunnableFunction(
"CanvasTranslator NotifyDeviceReset",
[]() { gfx::GPUParent::GetSingleton()->NotifyDeviceReset(); });
RefPtr<Runnable> runnable =
NS_NewRunnableFunction("CanvasTranslator NotifyDeviceReset", []() {
if (XRE_IsGPUProcess()) {
gfx::GPUParent::GetSingleton()->NotifyDeviceReset();
} else {
gfx::GPUProcessManager::Get()->OnInProcessDeviceReset(
/* aTrackThreshold */ false);
}
});
// It is safe to wait here because only the Compositor thread waits on us and
// the main thread doesn't wait on the compositor thread in the GPU process.

Просмотреть файл

@ -5693,6 +5693,12 @@
value: false
mirror: once
# Whether OffscreenCanvas can use remote canvas
- name: gfx.canvas.remote.allow-offscreen
type: RelaxedAtomicBool
value: false
mirror: always
# How many worker threads spawned for remote canvas
# -1 - Calculate based on processor cores
# 0 - No worker threads spawned, will do work on CanvasRenderThread