2017-10-28 02:10:06 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
2017-01-06 21:10:15 +03:00
|
|
|
/* 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/. */
|
|
|
|
|
2017-06-09 06:56:13 +03:00
|
|
|
#include "base/task.h"
|
|
|
|
#include "GeckoProfiler.h"
|
2020-12-10 17:26:32 +03:00
|
|
|
#include "gfxPlatform.h"
|
2020-04-05 06:49:51 +03:00
|
|
|
#include "GLContext.h"
|
2017-01-06 21:10:15 +03:00
|
|
|
#include "RenderThread.h"
|
2021-07-19 20:35:55 +03:00
|
|
|
#include "nsThread.h"
|
2017-01-06 21:10:15 +03:00
|
|
|
#include "nsThreadUtils.h"
|
2020-09-23 00:43:49 +03:00
|
|
|
#include "transport/runnable_utils.h"
|
2021-07-19 20:35:55 +03:00
|
|
|
#include "mozilla/BackgroundHangMonitor.h"
|
2018-05-28 18:29:41 +03:00
|
|
|
#include "mozilla/layers/AsyncImagePipelineManager.h"
|
2020-04-05 06:49:51 +03:00
|
|
|
#include "mozilla/gfx/gfxVars.h"
|
2018-06-13 18:01:06 +03:00
|
|
|
#include "mozilla/gfx/GPUParent.h"
|
2020-12-07 23:36:11 +03:00
|
|
|
#include "mozilla/gfx/GPUProcessManager.h"
|
2017-01-27 23:30:18 +03:00
|
|
|
#include "mozilla/layers/CompositorThread.h"
|
|
|
|
#include "mozilla/layers/CompositorBridgeParent.h"
|
2019-06-19 19:14:56 +03:00
|
|
|
#include "mozilla/layers/CompositorManagerParent.h"
|
2018-09-08 21:41:34 +03:00
|
|
|
#include "mozilla/layers/WebRenderBridgeParent.h"
|
2018-04-23 14:57:17 +03:00
|
|
|
#include "mozilla/layers/SharedSurfacesParent.h"
|
2021-11-19 10:41:29 +03:00
|
|
|
#include "mozilla/layers/SurfacePool.h"
|
2017-01-06 21:10:15 +03:00
|
|
|
#include "mozilla/StaticPtr.h"
|
2018-06-25 17:55:26 +03:00
|
|
|
#include "mozilla/Telemetry.h"
|
2017-03-07 13:37:28 +03:00
|
|
|
#include "mozilla/webrender/RendererOGL.h"
|
2017-03-31 17:29:14 +03:00
|
|
|
#include "mozilla/webrender/RenderTextureHost.h"
|
2017-03-07 13:37:28 +03:00
|
|
|
#include "mozilla/widget/CompositorWidget.h"
|
2021-03-29 02:55:05 +03:00
|
|
|
#include "OGLShaderProgram.h"
|
2017-01-06 21:10:15 +03:00
|
|
|
|
2018-03-29 05:21:47 +03:00
|
|
|
#ifdef XP_WIN
|
2020-08-13 00:25:17 +03:00
|
|
|
# include "GLContextEGL.h"
|
2018-10-04 05:54:50 +03:00
|
|
|
# include "GLLibraryEGL.h"
|
2018-03-29 05:21:47 +03:00
|
|
|
# include "mozilla/widget/WinCompositorWindowThread.h"
|
2020-08-07 10:14:46 +03:00
|
|
|
# include "mozilla/gfx/DeviceManagerDx.h"
|
|
|
|
//# include "nsWindowsHelpers.h"
|
|
|
|
//# include <d3d11.h>
|
2018-03-29 05:21:47 +03:00
|
|
|
#endif
|
|
|
|
|
2019-03-20 14:51:33 +03:00
|
|
|
#ifdef MOZ_WIDGET_ANDROID
|
|
|
|
# include "GLLibraryEGL.h"
|
2020-10-14 10:56:47 +03:00
|
|
|
# include "mozilla/webrender/RenderAndroidSurfaceTextureHost.h"
|
2019-03-20 14:51:33 +03:00
|
|
|
#endif
|
|
|
|
|
2020-04-05 06:49:51 +03:00
|
|
|
#ifdef MOZ_WIDGET_GTK
|
2021-03-11 17:32:53 +03:00
|
|
|
# include "mozilla/WidgetUtilsGtk.h"
|
2020-04-05 06:49:51 +03:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef MOZ_WAYLAND
|
|
|
|
# include "GLLibraryEGL.h"
|
|
|
|
#endif
|
|
|
|
|
2018-10-04 05:54:50 +03:00
|
|
|
using namespace mozilla;
|
|
|
|
|
2020-09-13 20:31:14 +03:00
|
|
|
static already_AddRefed<gl::GLContext> CreateGLContext(nsACString& aError);
|
2018-10-04 05:54:50 +03:00
|
|
|
|
2018-12-01 06:05:56 +03:00
|
|
|
MOZ_DEFINE_MALLOC_SIZE_OF(WebRenderRendererMallocSizeOf)
|
|
|
|
|
2021-04-28 15:33:55 +03:00
|
|
|
namespace mozilla::wr {
|
2017-01-06 21:10:15 +03:00
|
|
|
|
2021-09-02 01:27:15 +03:00
|
|
|
LazyLogModule gRenderThreadLog("RenderThread");
|
|
|
|
// Should be called only on RenderThread, since LazyLogModule is not thread safe
|
|
|
|
#define LOG(...) MOZ_LOG(gRenderThreadLog, LogLevel::Debug, (__VA_ARGS__))
|
|
|
|
|
2017-01-06 21:10:15 +03:00
|
|
|
static StaticRefPtr<RenderThread> sRenderThread;
|
2021-07-19 20:35:55 +03:00
|
|
|
static mozilla::BackgroundHangMonitor* sBackgroundHangMonitor;
|
2017-01-06 21:10:15 +03:00
|
|
|
|
2021-07-19 20:35:55 +03:00
|
|
|
RenderThread::RenderThread(RefPtr<nsIThread> aThread)
|
|
|
|
: mThread(std::move(aThread)),
|
2019-12-09 23:21:41 +03:00
|
|
|
mThreadPool(false),
|
|
|
|
mThreadPoolLP(true),
|
2021-03-29 16:34:16 +03:00
|
|
|
mSingletonGLIsForHardwareWebRender(true),
|
2019-01-17 02:25:35 +03:00
|
|
|
mWindowInfos("RenderThread.mWindowInfos"),
|
2017-03-07 13:37:28 +03:00
|
|
|
mRenderTextureMapLock("RenderThread.mRenderTextureMapLock"),
|
2017-07-03 15:08:22 +03:00
|
|
|
mHasShutdown(false),
|
2019-06-19 19:14:56 +03:00
|
|
|
mHandlingDeviceReset(false),
|
2021-08-27 18:24:28 +03:00
|
|
|
mHandlingWebRenderError(false) {}
|
2017-01-06 21:10:15 +03:00
|
|
|
|
2021-08-27 18:24:28 +03:00
|
|
|
RenderThread::~RenderThread() { MOZ_ASSERT(mRenderTexturesDeferred.empty()); }
|
2017-01-06 21:10:15 +03:00
|
|
|
|
2017-01-17 03:22:09 +03:00
|
|
|
// static
|
2017-01-06 21:10:15 +03:00
|
|
|
RenderThread* RenderThread::Get() { return sRenderThread; }
|
|
|
|
|
|
|
|
// static
|
|
|
|
void RenderThread::Start() {
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
MOZ_ASSERT(!sRenderThread);
|
|
|
|
|
2021-07-19 20:35:55 +03:00
|
|
|
RefPtr<nsIThread> thread;
|
|
|
|
nsresult rv = NS_NewNamedThread(
|
|
|
|
"Renderer", getter_AddRefs(thread),
|
|
|
|
NS_NewRunnableFunction("Renderer::BackgroundHanSetup", []() {
|
|
|
|
sBackgroundHangMonitor = new mozilla::BackgroundHangMonitor(
|
|
|
|
"Render",
|
|
|
|
/* Timeout values are powers-of-two to enable us get better
|
|
|
|
data. 128ms is chosen for transient hangs because 8Hz should
|
|
|
|
be the minimally acceptable goal for Render
|
|
|
|
responsiveness (normal goal is 60Hz). */
|
|
|
|
128,
|
|
|
|
/* 2048ms is chosen for permanent hangs because it's longer than
|
|
|
|
* most Render hangs seen in the wild, but is short enough
|
|
|
|
* to not miss getting native hang stacks. */
|
|
|
|
2048);
|
|
|
|
nsCOMPtr<nsIThread> thread = NS_GetCurrentThread();
|
|
|
|
static_cast<nsThread*>(thread.get())->SetUseHangMonitor(true);
|
|
|
|
}));
|
|
|
|
|
|
|
|
if (NS_FAILED(rv)) {
|
2017-01-06 21:10:15 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
sRenderThread = new RenderThread(thread);
|
2018-03-29 05:21:47 +03:00
|
|
|
#ifdef XP_WIN
|
|
|
|
widget::WinCompositorWindowThread::Start();
|
|
|
|
#endif
|
2018-04-23 14:57:17 +03:00
|
|
|
layers::SharedSurfacesParent::Initialize();
|
2018-05-31 09:07:34 +03:00
|
|
|
|
2018-10-04 05:54:50 +03:00
|
|
|
RefPtr<Runnable> runnable = WrapRunnable(
|
|
|
|
RefPtr<RenderThread>(sRenderThread.get()), &RenderThread::InitDeviceTask);
|
2021-07-19 20:35:55 +03:00
|
|
|
sRenderThread->PostRunnable(runnable.forget());
|
2017-01-06 21:10:15 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
void RenderThread::ShutDown() {
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
MOZ_ASSERT(sRenderThread);
|
|
|
|
|
2017-07-03 15:08:22 +03:00
|
|
|
{
|
|
|
|
MutexAutoLock lock(sRenderThread->mRenderTextureMapLock);
|
|
|
|
sRenderThread->mHasShutdown = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
layers::SynchronousTask task("RenderThread");
|
|
|
|
RefPtr<Runnable> runnable =
|
|
|
|
WrapRunnable(RefPtr<RenderThread>(sRenderThread.get()),
|
|
|
|
&RenderThread::ShutDownTask, &task);
|
2021-07-19 20:35:55 +03:00
|
|
|
sRenderThread->PostRunnable(runnable.forget());
|
2017-07-03 15:08:22 +03:00
|
|
|
task.Wait();
|
2017-01-06 21:10:15 +03:00
|
|
|
|
2021-03-30 01:43:27 +03:00
|
|
|
layers::SharedSurfacesParent::Shutdown();
|
|
|
|
|
2017-01-06 21:10:15 +03:00
|
|
|
sRenderThread = nullptr;
|
2018-03-29 05:21:47 +03:00
|
|
|
#ifdef XP_WIN
|
2019-05-26 05:17:10 +03:00
|
|
|
if (widget::WinCompositorWindowThread::Get()) {
|
|
|
|
widget::WinCompositorWindowThread::ShutDown();
|
|
|
|
}
|
2018-03-29 05:21:47 +03:00
|
|
|
#endif
|
2017-01-06 21:10:15 +03:00
|
|
|
}
|
|
|
|
|
2018-04-25 05:24:55 +03:00
|
|
|
extern void ClearAllBlobImageResources();
|
|
|
|
|
2017-07-03 15:08:22 +03:00
|
|
|
void RenderThread::ShutDownTask(layers::SynchronousTask* aTask) {
|
|
|
|
layers::AutoCompleteTask complete(aTask);
|
|
|
|
MOZ_ASSERT(IsInRenderThread());
|
2021-09-02 01:27:15 +03:00
|
|
|
LOG("RenderThread::ShutDownTask()");
|
2018-04-23 14:57:17 +03:00
|
|
|
|
2019-07-01 18:24:32 +03:00
|
|
|
// Let go of our handle to the (internally ref-counted) thread pool.
|
|
|
|
mThreadPool.Release();
|
2019-12-09 23:21:41 +03:00
|
|
|
mThreadPoolLP.Release();
|
2019-07-01 18:24:32 +03:00
|
|
|
|
2018-04-23 14:57:17 +03:00
|
|
|
// Releasing on the render thread will allow us to avoid dispatching to remove
|
|
|
|
// remaining textures from the texture map.
|
2021-03-30 01:43:27 +03:00
|
|
|
layers::SharedSurfacesParent::ShutdownRenderThread();
|
2018-04-25 05:24:55 +03:00
|
|
|
|
|
|
|
ClearAllBlobImageResources();
|
2021-03-17 13:51:45 +03:00
|
|
|
ClearSingletonGL();
|
Bug 1592044 - Reduce the frequency of IOSurface and framebuffer creation and destruction with the help of a surface pool. r=jgilbert
There are multiple SurfacePools: Main thread painting and the non-WebRender compositors create a new pool per window, and WebRender creates one shared pool across all windows. The non-WebRender users set the pool size limit to zero, i.e. no recycling across paints. This preserves the pre-existing behavior.
WebRender's pool size is configurable with the gfx.webrender.compositor.surface-pool-size pref.
Every window holds on to a SurfacePoolHandle. A SurfacePoolHandle has an owning reference to the pool, via a surface pool wrapper. Once all handles are gone, the surface pool goes away, too.
The SurfacePool holds on to IOSurfaces and MozFramebuffers. Both are created on demand, independently, but are associated with each other.
A given NativeLayer uses only one surface pool handle during its lifetime. The native layer no longer influences which GLContext its framebuffers are created for; the GL context is now managed by the surface pool handle.
As a result, a NativeLayer can no longer change which GLContext its framebuffers are created by.
So in the future, if we ever need to migrate a window frome one GLContext to another, we will need to recreate the NativeLayers inside it. I think that's ok.
Differential Revision: https://phabricator.services.mozilla.com/D54859
--HG--
extra : moz-landing-system : lando
2019-12-19 00:01:51 +03:00
|
|
|
ClearSharedSurfacePool();
|
2017-07-03 15:08:22 +03:00
|
|
|
}
|
|
|
|
|
2017-01-06 21:10:15 +03:00
|
|
|
// static
|
|
|
|
bool RenderThread::IsInRenderThread() {
|
2021-07-19 20:35:55 +03:00
|
|
|
return sRenderThread && sRenderThread->mThread == NS_GetCurrentThread();
|
2017-01-06 21:10:15 +03:00
|
|
|
}
|
|
|
|
|
2021-11-04 19:29:44 +03:00
|
|
|
// static
|
|
|
|
already_AddRefed<nsIThread> RenderThread::GetRenderThread() {
|
|
|
|
nsCOMPtr<nsIThread> thread;
|
|
|
|
if (sRenderThread) {
|
|
|
|
thread = sRenderThread->mThread;
|
|
|
|
}
|
|
|
|
return thread.forget();
|
|
|
|
}
|
|
|
|
|
2018-09-08 02:03:13 +03:00
|
|
|
void RenderThread::DoAccumulateMemoryReport(
|
|
|
|
MemoryReport aReport,
|
|
|
|
const RefPtr<MemoryReportPromise::Private>& aPromise) {
|
|
|
|
MOZ_ASSERT(IsInRenderThread());
|
2018-11-13 06:15:51 +03:00
|
|
|
|
2018-09-08 02:03:13 +03:00
|
|
|
for (auto& r : mRenderers) {
|
2018-11-13 06:15:51 +03:00
|
|
|
r.second->AccumulateMemoryReport(&aReport);
|
2018-09-08 02:03:13 +03:00
|
|
|
}
|
|
|
|
|
2018-12-01 06:05:56 +03:00
|
|
|
// Note memory used by the shader cache, which is shared across all WR
|
|
|
|
// instances.
|
|
|
|
MOZ_ASSERT(aReport.shader_cache == 0);
|
|
|
|
if (mProgramCache) {
|
|
|
|
aReport.shader_cache = wr_program_cache_report_memory(
|
|
|
|
mProgramCache->Raw(), &WebRenderRendererMallocSizeOf);
|
|
|
|
}
|
2018-10-31 01:13:32 +03:00
|
|
|
|
2020-12-15 18:37:11 +03:00
|
|
|
size_t renderTextureMemory = 0;
|
|
|
|
{
|
|
|
|
MutexAutoLock lock(mRenderTextureMapLock);
|
|
|
|
for (const auto& entry : mRenderTextures) {
|
|
|
|
renderTextureMemory += entry.second->Bytes();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
aReport.render_texture_hosts = renderTextureMemory;
|
|
|
|
|
2018-09-08 02:03:13 +03:00
|
|
|
aPromise->Resolve(aReport, __func__);
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
RefPtr<MemoryReportPromise> RenderThread::AccumulateMemoryReport(
|
|
|
|
MemoryReport aInitial) {
|
|
|
|
RefPtr<MemoryReportPromise::Private> p =
|
|
|
|
new MemoryReportPromise::Private(__func__);
|
|
|
|
MOZ_ASSERT(!IsInRenderThread());
|
2021-07-19 20:35:55 +03:00
|
|
|
if (!Get()) {
|
2018-09-28 08:36:30 +03:00
|
|
|
// This happens when the GPU process fails to start and we fall back to the
|
|
|
|
// basic compositor in the parent process. We could assert against this if
|
|
|
|
// we made the webrender detection code in gfxPlatform.cpp smarter. See bug
|
|
|
|
// 1494430 comment 12.
|
2018-09-26 23:44:59 +03:00
|
|
|
NS_WARNING("No render thread, returning empty memory report");
|
|
|
|
p->Resolve(aInitial, __func__);
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
2021-07-19 20:35:55 +03:00
|
|
|
Get()->PostRunnable(
|
2018-09-08 02:03:13 +03:00
|
|
|
NewRunnableMethod<MemoryReport, RefPtr<MemoryReportPromise::Private>>(
|
|
|
|
"wr::RenderThread::DoAccumulateMemoryReport", Get(),
|
|
|
|
&RenderThread::DoAccumulateMemoryReport, aInitial, p));
|
|
|
|
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
2017-01-17 03:22:09 +03:00
|
|
|
void RenderThread::AddRenderer(wr::WindowId aWindowId,
|
|
|
|
UniquePtr<RendererOGL> aRenderer) {
|
2017-01-16 17:22:47 +03:00
|
|
|
MOZ_ASSERT(IsInRenderThread());
|
2021-09-02 01:27:15 +03:00
|
|
|
LOG("RenderThread::AddRenderer() aWindowId %" PRIx64 "", AsUint64(aWindowId));
|
2017-07-03 15:08:22 +03:00
|
|
|
|
|
|
|
if (mHasShutdown) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-05-30 22:15:35 +03:00
|
|
|
mRenderers[aWindowId] = std::move(aRenderer);
|
2017-05-19 03:21:38 +03:00
|
|
|
|
2019-01-18 19:48:22 +03:00
|
|
|
auto windows = mWindowInfos.Lock();
|
|
|
|
windows->emplace(AsUint64(aWindowId), new WindowInfo());
|
2017-01-06 21:10:15 +03:00
|
|
|
}
|
|
|
|
|
2017-01-17 03:22:09 +03:00
|
|
|
void RenderThread::RemoveRenderer(wr::WindowId aWindowId) {
|
2017-01-16 17:22:47 +03:00
|
|
|
MOZ_ASSERT(IsInRenderThread());
|
2021-09-02 01:27:15 +03:00
|
|
|
LOG("RenderThread::RemoveRenderer() aWindowId %" PRIx64 "",
|
|
|
|
AsUint64(aWindowId));
|
2017-07-03 15:08:22 +03:00
|
|
|
|
|
|
|
if (mHasShutdown) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-01-06 21:10:15 +03:00
|
|
|
mRenderers.erase(aWindowId);
|
2017-05-19 03:21:38 +03:00
|
|
|
|
2021-02-02 02:36:36 +03:00
|
|
|
if (mRenderers.empty()) {
|
2018-06-13 18:01:06 +03:00
|
|
|
mHandlingDeviceReset = false;
|
2021-02-02 02:36:36 +03:00
|
|
|
mHandlingWebRenderError = false;
|
2018-06-13 18:01:06 +03:00
|
|
|
}
|
|
|
|
|
2019-01-17 02:25:35 +03:00
|
|
|
auto windows = mWindowInfos.Lock();
|
|
|
|
auto it = windows->find(AsUint64(aWindowId));
|
|
|
|
MOZ_ASSERT(it != windows->end());
|
2018-06-25 17:55:19 +03:00
|
|
|
WindowInfo* toDelete = it->second;
|
2019-01-17 02:25:35 +03:00
|
|
|
windows->erase(it);
|
2018-06-25 17:55:19 +03:00
|
|
|
delete toDelete;
|
2017-01-06 21:10:15 +03:00
|
|
|
}
|
|
|
|
|
2017-01-17 03:22:09 +03:00
|
|
|
RendererOGL* RenderThread::GetRenderer(wr::WindowId aWindowId) {
|
2017-01-16 17:22:47 +03:00
|
|
|
MOZ_ASSERT(IsInRenderThread());
|
|
|
|
|
|
|
|
auto it = mRenderers.find(aWindowId);
|
|
|
|
MOZ_ASSERT(it != mRenderers.end());
|
|
|
|
|
|
|
|
if (it == mRenderers.end()) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2017-01-25 00:20:54 +03:00
|
|
|
return it->second.get();
|
2017-01-16 17:22:47 +03:00
|
|
|
}
|
2017-01-06 21:10:15 +03:00
|
|
|
|
2018-06-13 18:01:06 +03:00
|
|
|
size_t RenderThread::RendererCount() {
|
|
|
|
MOZ_ASSERT(IsInRenderThread());
|
|
|
|
return mRenderers.size();
|
|
|
|
}
|
|
|
|
|
2020-09-18 04:24:57 +03:00
|
|
|
void RenderThread::BeginRecordingForWindow(wr::WindowId aWindowId,
|
|
|
|
const TimeStamp& aRecordingStart,
|
|
|
|
wr::PipelineId aRootPipelineId) {
|
2019-05-31 03:31:39 +03:00
|
|
|
MOZ_ASSERT(IsInRenderThread());
|
2020-09-18 22:32:14 +03:00
|
|
|
RendererOGL* renderer = GetRenderer(aWindowId);
|
|
|
|
MOZ_ASSERT(renderer);
|
2019-05-31 03:31:52 +03:00
|
|
|
|
2020-09-18 22:32:14 +03:00
|
|
|
renderer->BeginRecording(aRecordingStart, aRootPipelineId);
|
2019-05-31 03:31:39 +03:00
|
|
|
}
|
|
|
|
|
2019-07-31 21:28:34 +03:00
|
|
|
void RenderThread::WriteCollectedFramesForWindow(wr::WindowId aWindowId) {
|
|
|
|
MOZ_ASSERT(IsInRenderThread());
|
2019-07-31 21:28:47 +03:00
|
|
|
|
|
|
|
RendererOGL* renderer = GetRenderer(aWindowId);
|
|
|
|
MOZ_ASSERT(renderer);
|
2020-09-18 22:32:14 +03:00
|
|
|
renderer->WriteCollectedFrames();
|
2019-07-31 21:28:34 +03:00
|
|
|
}
|
|
|
|
|
2019-11-08 01:34:49 +03:00
|
|
|
Maybe<layers::CollectedFrames> RenderThread::GetCollectedFramesForWindow(
|
|
|
|
wr::WindowId aWindowId) {
|
|
|
|
MOZ_ASSERT(IsInRenderThread());
|
|
|
|
|
|
|
|
RendererOGL* renderer = GetRenderer(aWindowId);
|
|
|
|
MOZ_ASSERT(renderer);
|
2020-09-18 22:32:14 +03:00
|
|
|
return renderer->GetCollectedFrames();
|
2019-11-08 01:34:49 +03:00
|
|
|
}
|
|
|
|
|
2019-08-06 10:01:15 +03:00
|
|
|
void RenderThread::HandleFrameOneDoc(wr::WindowId aWindowId, bool aRender) {
|
2017-07-03 15:08:22 +03:00
|
|
|
if (mHasShutdown) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-01-06 21:10:15 +03:00
|
|
|
if (!IsInRenderThread()) {
|
2021-07-19 20:35:55 +03:00
|
|
|
PostRunnable(NewRunnableMethod<wr::WindowId, bool>(
|
2019-08-06 10:01:15 +03:00
|
|
|
"wr::RenderThread::HandleFrameOneDoc", this,
|
|
|
|
&RenderThread::HandleFrameOneDoc, aWindowId, aRender));
|
2017-01-06 21:10:15 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-09-26 12:52:04 +03:00
|
|
|
if (IsDestroyed(aWindowId)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mHandlingDeviceReset) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-08-06 10:01:15 +03:00
|
|
|
bool render = false;
|
2019-08-05 15:07:29 +03:00
|
|
|
PendingFrameInfo frame;
|
2019-08-06 10:01:15 +03:00
|
|
|
{ // scope lock
|
|
|
|
auto windows = mWindowInfos.Lock();
|
|
|
|
auto it = windows->find(AsUint64(aWindowId));
|
|
|
|
if (it == windows->end()) {
|
|
|
|
MOZ_ASSERT(false);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-08-05 15:07:29 +03:00
|
|
|
WindowInfo* info = it->second;
|
|
|
|
PendingFrameInfo& frameInfo = info->mPendingFrames.front();
|
|
|
|
frameInfo.mFrameNeedsRender |= aRender;
|
|
|
|
render = frameInfo.mFrameNeedsRender;
|
|
|
|
|
|
|
|
frame = frameInfo;
|
2019-08-06 10:01:15 +03:00
|
|
|
}
|
|
|
|
|
2019-11-08 15:52:16 +03:00
|
|
|
// It is for ensuring that PrepareForUse() is called before
|
|
|
|
// RenderTextureHost::Lock().
|
2020-08-21 10:32:47 +03:00
|
|
|
HandleRenderTextureOps();
|
2019-11-08 15:52:16 +03:00
|
|
|
|
2019-08-06 10:01:15 +03:00
|
|
|
UpdateAndRender(aWindowId, frame.mStartId, frame.mStartTime, render,
|
2018-12-08 02:28:41 +03:00
|
|
|
/* aReadbackSize */ Nothing(),
|
2019-04-30 20:49:30 +03:00
|
|
|
/* aReadbackFormat */ Nothing(),
|
2020-04-02 20:23:15 +03:00
|
|
|
/* aReadbackBuffer */ Nothing());
|
2019-08-05 15:09:46 +03:00
|
|
|
|
|
|
|
{ // scope lock
|
|
|
|
auto windows = mWindowInfos.Lock();
|
|
|
|
auto it = windows->find(AsUint64(aWindowId));
|
|
|
|
if (it == windows->end()) {
|
|
|
|
MOZ_ASSERT(false);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
WindowInfo* info = it->second;
|
|
|
|
info->mPendingFrames.pop();
|
|
|
|
}
|
|
|
|
|
|
|
|
// The start time is from WebRenderBridgeParent::CompositeToTarget. From that
|
|
|
|
// point until now (when the frame is finally pushed to the screen) is
|
|
|
|
// equivalent to the COMPOSITE_TIME metric in the non-WR codepath.
|
|
|
|
mozilla::Telemetry::AccumulateTimeDelta(mozilla::Telemetry::COMPOSITE_TIME,
|
|
|
|
frame.mStartTime);
|
2017-01-06 21:10:15 +03:00
|
|
|
}
|
|
|
|
|
2020-09-15 16:22:24 +03:00
|
|
|
void RenderThread::SetClearColor(wr::WindowId aWindowId, wr::ColorF aColor) {
|
|
|
|
if (mHasShutdown) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!IsInRenderThread()) {
|
2021-07-19 20:35:55 +03:00
|
|
|
PostRunnable(NewRunnableMethod<wr::WindowId, wr::ColorF>(
|
2020-09-15 16:22:24 +03:00
|
|
|
"wr::RenderThread::SetClearColor", this, &RenderThread::SetClearColor,
|
|
|
|
aWindowId, aColor));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IsDestroyed(aWindowId)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto it = mRenderers.find(aWindowId);
|
|
|
|
MOZ_ASSERT(it != mRenderers.end());
|
|
|
|
if (it != mRenderers.end()) {
|
|
|
|
wr_renderer_set_clear_color(it->second->GetRenderer(), aColor);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-28 15:33:55 +03:00
|
|
|
void RenderThread::SetProfilerUI(wr::WindowId aWindowId, const nsCString& aUI) {
|
Bug 1671289 - Improve WebRender's integrated profiler. r=gw
In a (large-ish) nutshell:
- Consolidate all counters under a single type.
- Counters are all arranged in an array and referred to via index.
- All counters can be displayed as average+max (float/int), graph, and change indicator.
- Specify what to show and in what form via a pref.
- All counters and visualizations support not having values every frame.
- GPU time queries visualization is easier to read relative to the frame budget:
- If the maximum value is under 16ms, the right side of the graph is fixed at 16ms.
- If the maximum value is above 16ms, draw a vertical bar at 16ms.
- Added a few new profile counters:
- Total frame CPU time (from API send to the end of GPU command submission).
- Visibility, Prepare, Batching and Glyph resolve times.
The main change is how profile counters are represented. Instead of having different types for different visualizations, every counter is represented the same way, tracking average/max values over half a ms and optionally recording a graph over a number of frames. Counters are stored in a vector and referred to via index (See constants at the top of profiler.rs).
The main motivation for this storage is to facilitate adding counters without having to think too much about where to store them and how to pass them to the renderer.
The profiler's UI is defined by a string with with a single syntax:
- Comma separated list of tokens (leading and trailing spaces ignored), which can be:
- A counter name:
- If prefixed with a '#' character, the counter is shown as a graph.
- If prefixed with a '*' character, the counter is shown as a change indicator
- By default (counter name without prefix), the counter is shown as average and max over half a second.
- A preset name:
- A preset is a builtin UI string in the same syntax that can be nested in the main UI string.
- Presets are defined towards the top of profiler.rs and can also refer to other presets.
- An empty token adds a bit of vertical space.
- A '|' token begins a new column.
- A '_' token begins a new row.
Differential Revision: https://phabricator.services.mozilla.com/D93603
2020-10-20 11:54:04 +03:00
|
|
|
if (mHasShutdown) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!IsInRenderThread()) {
|
2021-07-19 20:35:55 +03:00
|
|
|
PostRunnable(NewRunnableMethod<wr::WindowId, nsCString>(
|
Bug 1671289 - Improve WebRender's integrated profiler. r=gw
In a (large-ish) nutshell:
- Consolidate all counters under a single type.
- Counters are all arranged in an array and referred to via index.
- All counters can be displayed as average+max (float/int), graph, and change indicator.
- Specify what to show and in what form via a pref.
- All counters and visualizations support not having values every frame.
- GPU time queries visualization is easier to read relative to the frame budget:
- If the maximum value is under 16ms, the right side of the graph is fixed at 16ms.
- If the maximum value is above 16ms, draw a vertical bar at 16ms.
- Added a few new profile counters:
- Total frame CPU time (from API send to the end of GPU command submission).
- Visibility, Prepare, Batching and Glyph resolve times.
The main change is how profile counters are represented. Instead of having different types for different visualizations, every counter is represented the same way, tracking average/max values over half a ms and optionally recording a graph over a number of frames. Counters are stored in a vector and referred to via index (See constants at the top of profiler.rs).
The main motivation for this storage is to facilitate adding counters without having to think too much about where to store them and how to pass them to the renderer.
The profiler's UI is defined by a string with with a single syntax:
- Comma separated list of tokens (leading and trailing spaces ignored), which can be:
- A counter name:
- If prefixed with a '#' character, the counter is shown as a graph.
- If prefixed with a '*' character, the counter is shown as a change indicator
- By default (counter name without prefix), the counter is shown as average and max over half a second.
- A preset name:
- A preset is a builtin UI string in the same syntax that can be nested in the main UI string.
- Presets are defined towards the top of profiler.rs and can also refer to other presets.
- An empty token adds a bit of vertical space.
- A '|' token begins a new column.
- A '_' token begins a new row.
Differential Revision: https://phabricator.services.mozilla.com/D93603
2020-10-20 11:54:04 +03:00
|
|
|
"wr::RenderThread::SetProfilerUI", this, &RenderThread::SetProfilerUI,
|
|
|
|
aWindowId, aUI));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto it = mRenderers.find(aWindowId);
|
|
|
|
if (it != mRenderers.end()) {
|
|
|
|
it->second->SetProfilerUI(aUI);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-17 03:22:09 +03:00
|
|
|
void RenderThread::RunEvent(wr::WindowId aWindowId,
|
|
|
|
UniquePtr<RendererEvent> aEvent) {
|
2017-01-06 21:10:15 +03:00
|
|
|
if (!IsInRenderThread()) {
|
2021-07-19 20:35:55 +03:00
|
|
|
PostRunnable(NewRunnableMethod<wr::WindowId, UniquePtr<RendererEvent>&&>(
|
|
|
|
"wr::RenderThread::RunEvent", this, &RenderThread::RunEvent, aWindowId,
|
|
|
|
std::move(aEvent)));
|
2017-01-11 15:51:27 +03:00
|
|
|
return;
|
2017-01-06 21:10:15 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
aEvent->Run(*this, aWindowId);
|
|
|
|
aEvent = nullptr;
|
|
|
|
}
|
|
|
|
|
2018-05-28 18:29:41 +03:00
|
|
|
static void NotifyDidRender(layers::CompositorBridgeParent* aBridge,
|
2021-04-28 15:33:55 +03:00
|
|
|
const RefPtr<const WebRenderPipelineInfo>& aInfo,
|
2018-12-08 02:28:41 +03:00
|
|
|
VsyncId aCompositeStartId,
|
2018-11-16 05:13:56 +03:00
|
|
|
TimeStamp aCompositeStart, TimeStamp aRenderStart,
|
|
|
|
TimeStamp aEnd, bool aRender,
|
2018-11-16 02:09:05 +03:00
|
|
|
RendererStats aStats) {
|
2018-10-23 07:21:02 +03:00
|
|
|
if (aRender && aBridge->GetWrBridge()) {
|
|
|
|
// We call this here to mimic the behavior in LayerManagerComposite, as to
|
|
|
|
// not change what Talos measures. That is, we do not record an empty frame
|
|
|
|
// as a frame.
|
2018-09-08 21:41:34 +03:00
|
|
|
aBridge->GetWrBridge()->RecordFrame();
|
|
|
|
}
|
|
|
|
|
2020-12-09 01:21:37 +03:00
|
|
|
aBridge->NotifyDidRender(aCompositeStartId, aCompositeStart, aRenderStart,
|
|
|
|
aEnd, &aStats);
|
|
|
|
|
2020-05-05 15:55:27 +03:00
|
|
|
for (const auto& epoch : aInfo->Raw().epochs) {
|
2020-02-19 21:34:51 +03:00
|
|
|
aBridge->NotifyPipelineRendered(epoch.pipeline_id, epoch.epoch,
|
|
|
|
aCompositeStartId, aCompositeStart,
|
|
|
|
aRenderStart, aEnd, &aStats);
|
2018-11-29 21:30:06 +03:00
|
|
|
}
|
2018-12-28 18:48:06 +03:00
|
|
|
|
2018-12-10 22:31:12 +03:00
|
|
|
if (aBridge->GetWrBridge()) {
|
|
|
|
aBridge->GetWrBridge()->CompositeIfNeeded();
|
|
|
|
}
|
2017-01-27 23:30:18 +03:00
|
|
|
}
|
2017-01-06 21:10:15 +03:00
|
|
|
|
2018-12-07 01:19:03 +03:00
|
|
|
static void NotifyDidStartRender(layers::CompositorBridgeParent* aBridge) {
|
2019-08-05 15:02:38 +03:00
|
|
|
// Starting a render will change mIsRendering, and potentially
|
2018-12-07 01:19:03 +03:00
|
|
|
// change whether we can allow the bridge to intiate another frame.
|
|
|
|
if (aBridge->GetWrBridge()) {
|
|
|
|
aBridge->GetWrBridge()->CompositeIfNeeded();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-14 10:18:03 +03:00
|
|
|
void RenderThread::UpdateAndRender(
|
|
|
|
wr::WindowId aWindowId, const VsyncId& aStartId,
|
|
|
|
const TimeStamp& aStartTime, bool aRender,
|
|
|
|
const Maybe<gfx::IntSize>& aReadbackSize,
|
|
|
|
const Maybe<wr::ImageFormat>& aReadbackFormat,
|
2020-08-14 21:40:09 +03:00
|
|
|
const Maybe<Range<uint8_t>>& aReadbackBuffer, bool* aNeedsYFlip) {
|
2020-01-18 00:29:15 +03:00
|
|
|
AUTO_PROFILER_TRACING_MARKER("Paint", "Composite", GRAPHICS);
|
2021-02-24 03:50:07 +03:00
|
|
|
AUTO_PROFILER_LABEL("RenderThread::UpdateAndRender", GRAPHICS);
|
2017-01-16 17:22:47 +03:00
|
|
|
MOZ_ASSERT(IsInRenderThread());
|
2018-10-17 01:54:01 +03:00
|
|
|
MOZ_ASSERT(aRender || aReadbackBuffer.isNothing());
|
2017-01-16 17:22:47 +03:00
|
|
|
|
2017-01-06 21:10:15 +03:00
|
|
|
auto it = mRenderers.find(aWindowId);
|
|
|
|
MOZ_ASSERT(it != mRenderers.end());
|
|
|
|
if (it == mRenderers.end()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-11-16 05:13:56 +03:00
|
|
|
TimeStamp start = TimeStamp::Now();
|
|
|
|
|
2017-01-06 21:10:15 +03:00
|
|
|
auto& renderer = it->second;
|
2018-12-07 01:19:03 +03:00
|
|
|
|
2021-01-07 13:23:30 +03:00
|
|
|
if (renderer->IsPaused()) {
|
|
|
|
aRender = false;
|
|
|
|
}
|
2021-09-02 01:27:15 +03:00
|
|
|
LOG("RenderThread::UpdateAndRender() aWindowId %" PRIx64 " aRender %d",
|
|
|
|
AsUint64(aWindowId), aRender);
|
2021-01-07 13:23:30 +03:00
|
|
|
|
2020-05-08 23:20:44 +03:00
|
|
|
layers::CompositorThread()->Dispatch(
|
2018-12-07 01:19:03 +03:00
|
|
|
NewRunnableFunction("NotifyDidStartRenderRunnable", &NotifyDidStartRender,
|
|
|
|
renderer->GetCompositorBridge()));
|
|
|
|
|
2019-11-04 19:15:20 +03:00
|
|
|
wr::RenderedFrameId latestFrameId;
|
2018-11-16 02:09:05 +03:00
|
|
|
RendererStats stats = {0};
|
2018-10-02 06:13:22 +03:00
|
|
|
if (aRender) {
|
2020-08-14 21:40:09 +03:00
|
|
|
latestFrameId = renderer->UpdateAndRender(
|
|
|
|
aReadbackSize, aReadbackFormat, aReadbackBuffer, aNeedsYFlip, &stats);
|
2018-10-02 06:13:22 +03:00
|
|
|
} else {
|
|
|
|
renderer->Update();
|
2017-07-04 13:25:24 +03:00
|
|
|
}
|
2018-10-23 06:14:45 +03:00
|
|
|
// Check graphics reset status even when rendering is skipped.
|
2020-12-07 23:36:11 +03:00
|
|
|
renderer->CheckGraphicsResetStatus("PostUpdate", /* aForce */ false);
|
2017-01-27 23:30:18 +03:00
|
|
|
|
|
|
|
TimeStamp end = TimeStamp::Now();
|
2020-02-19 21:34:51 +03:00
|
|
|
RefPtr<const WebRenderPipelineInfo> info = renderer->FlushPipelineInfo();
|
2018-05-28 18:29:41 +03:00
|
|
|
|
2020-05-08 23:20:44 +03:00
|
|
|
layers::CompositorThread()->Dispatch(
|
2017-10-27 23:39:28 +03:00
|
|
|
NewRunnableFunction("NotifyDidRenderRunnable", &NotifyDidRender,
|
2018-12-08 02:28:41 +03:00
|
|
|
renderer->GetCompositorBridge(), info, aStartId,
|
|
|
|
aStartTime, start, end, aRender, stats));
|
2018-11-12 04:36:13 +03:00
|
|
|
|
2019-11-04 19:15:20 +03:00
|
|
|
if (latestFrameId.IsValid()) {
|
2020-09-18 22:32:14 +03:00
|
|
|
renderer->MaybeRecordFrame(info);
|
2019-05-31 03:31:39 +03:00
|
|
|
}
|
|
|
|
|
2020-09-02 17:21:36 +03:00
|
|
|
ipc::FileDescriptor fenceFd;
|
|
|
|
|
2019-11-04 19:15:20 +03:00
|
|
|
if (latestFrameId.IsValid()) {
|
2020-09-02 17:21:36 +03:00
|
|
|
fenceFd = renderer->GetAndResetReleaseFence();
|
|
|
|
|
2018-11-12 04:36:13 +03:00
|
|
|
// Wait for GPU after posting NotifyDidRender, since the wait is not
|
|
|
|
// necessary for the NotifyDidRender.
|
|
|
|
// The wait is necessary for Textures recycling of AsyncImagePipelineManager
|
|
|
|
// and for avoiding GPU queue is filled with too much tasks.
|
|
|
|
// WaitForGPU's implementation is different for each platform.
|
|
|
|
renderer->WaitForGPU();
|
2020-12-16 06:47:08 +03:00
|
|
|
} else {
|
2019-12-06 16:06:21 +03:00
|
|
|
// Update frame id for NotifyPipelinesUpdated() when rendering does not
|
2020-12-16 06:47:08 +03:00
|
|
|
// happen, either because rendering was not requested or the frame was
|
|
|
|
// canceled. Rendering can sometimes be canceled if UpdateAndRender is
|
|
|
|
// called when the window is not yet ready (not mapped or 0 size).
|
2019-12-06 16:06:21 +03:00
|
|
|
latestFrameId = renderer->UpdateFrameId();
|
|
|
|
}
|
|
|
|
|
2019-11-04 19:15:20 +03:00
|
|
|
RenderedFrameId lastCompletedFrameId = renderer->GetLastCompletedFrameId();
|
|
|
|
|
2018-11-12 04:36:13 +03:00
|
|
|
RefPtr<layers::AsyncImagePipelineManager> pipelineMgr =
|
|
|
|
renderer->GetCompositorBridge()->GetAsyncImagePipelineManager();
|
|
|
|
// pipelineMgr should always be non-null here because it is only nulled out
|
|
|
|
// after the WebRenderAPI instance for the CompositorBridgeParent is
|
|
|
|
// destroyed, and that destruction blocks until the renderer thread has
|
|
|
|
// removed the relevant renderer. And after that happens we should never reach
|
|
|
|
// this code at all; it would bail out at the mRenderers.find check above.
|
|
|
|
MOZ_ASSERT(pipelineMgr);
|
2020-09-02 17:21:36 +03:00
|
|
|
pipelineMgr->NotifyPipelinesUpdated(info, latestFrameId, lastCompletedFrameId,
|
|
|
|
std::move(fenceFd));
|
2017-01-06 21:10:15 +03:00
|
|
|
}
|
|
|
|
|
2017-04-05 17:12:11 +03:00
|
|
|
void RenderThread::Pause(wr::WindowId aWindowId) {
|
|
|
|
MOZ_ASSERT(IsInRenderThread());
|
2021-09-02 01:27:15 +03:00
|
|
|
LOG("RenderThread::Pause() aWindowId %" PRIx64 "", AsUint64(aWindowId));
|
2017-04-05 17:12:11 +03:00
|
|
|
|
|
|
|
auto it = mRenderers.find(aWindowId);
|
|
|
|
MOZ_ASSERT(it != mRenderers.end());
|
|
|
|
if (it == mRenderers.end()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
auto& renderer = it->second;
|
|
|
|
renderer->Pause();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool RenderThread::Resume(wr::WindowId aWindowId) {
|
|
|
|
MOZ_ASSERT(IsInRenderThread());
|
2021-09-02 01:27:15 +03:00
|
|
|
LOG("enderThread::Resume() aWindowId %" PRIx64 "", AsUint64(aWindowId));
|
2017-04-05 17:12:11 +03:00
|
|
|
|
|
|
|
auto it = mRenderers.find(aWindowId);
|
|
|
|
MOZ_ASSERT(it != mRenderers.end());
|
|
|
|
if (it == mRenderers.end()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
auto& renderer = it->second;
|
|
|
|
return renderer->Resume();
|
|
|
|
}
|
|
|
|
|
2017-11-03 05:22:28 +03:00
|
|
|
bool RenderThread::TooManyPendingFrames(wr::WindowId aWindowId) {
|
|
|
|
const int64_t maxFrameCount = 1;
|
|
|
|
|
|
|
|
// Too many pending frames if pending frames exit more than maxFrameCount
|
|
|
|
// or if RenderBackend is still processing a frame.
|
|
|
|
|
2019-01-17 02:25:35 +03:00
|
|
|
auto windows = mWindowInfos.Lock();
|
|
|
|
auto it = windows->find(AsUint64(aWindowId));
|
|
|
|
if (it == windows->end()) {
|
2017-11-03 05:22:28 +03:00
|
|
|
MOZ_ASSERT(false);
|
|
|
|
return true;
|
|
|
|
}
|
2018-06-25 17:55:19 +03:00
|
|
|
WindowInfo* info = it->second;
|
2017-11-03 05:22:28 +03:00
|
|
|
|
2019-08-05 14:59:35 +03:00
|
|
|
if (info->PendingCount() > maxFrameCount) {
|
2017-11-24 12:34:50 +03:00
|
|
|
return true;
|
|
|
|
}
|
2019-09-26 12:29:24 +03:00
|
|
|
// If there is no ongoing frame build, we accept a new frame.
|
|
|
|
return info->mPendingFrameBuild > 0;
|
2017-11-24 12:34:50 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bool RenderThread::IsDestroyed(wr::WindowId aWindowId) {
|
2019-01-17 02:25:35 +03:00
|
|
|
auto windows = mWindowInfos.Lock();
|
|
|
|
auto it = windows->find(AsUint64(aWindowId));
|
|
|
|
if (it == windows->end()) {
|
2017-11-03 05:22:28 +03:00
|
|
|
return true;
|
|
|
|
}
|
2017-11-24 12:34:50 +03:00
|
|
|
|
2018-06-25 17:55:19 +03:00
|
|
|
return it->second->mIsDestroyed;
|
2017-11-24 12:34:50 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void RenderThread::SetDestroyed(wr::WindowId aWindowId) {
|
2019-01-17 02:25:35 +03:00
|
|
|
auto windows = mWindowInfos.Lock();
|
|
|
|
auto it = windows->find(AsUint64(aWindowId));
|
|
|
|
if (it == windows->end()) {
|
2017-11-24 12:34:50 +03:00
|
|
|
MOZ_ASSERT(false);
|
|
|
|
return;
|
|
|
|
}
|
2018-06-25 17:55:19 +03:00
|
|
|
it->second->mIsDestroyed = true;
|
2017-05-19 03:21:38 +03:00
|
|
|
}
|
|
|
|
|
2018-06-25 17:55:26 +03:00
|
|
|
void RenderThread::IncPendingFrameCount(wr::WindowId aWindowId,
|
2018-12-08 02:28:41 +03:00
|
|
|
const VsyncId& aStartId,
|
2020-05-05 21:15:36 +03:00
|
|
|
const TimeStamp& aStartTime) {
|
2019-01-17 02:25:35 +03:00
|
|
|
auto windows = mWindowInfos.Lock();
|
|
|
|
auto it = windows->find(AsUint64(aWindowId));
|
|
|
|
if (it == windows->end()) {
|
2017-05-19 03:21:38 +03:00
|
|
|
MOZ_ASSERT(false);
|
|
|
|
return;
|
|
|
|
}
|
2020-05-05 21:15:36 +03:00
|
|
|
it->second->mPendingFrameBuild++;
|
2019-08-05 15:07:29 +03:00
|
|
|
it->second->mPendingFrames.push(
|
2020-05-05 21:15:36 +03:00
|
|
|
PendingFrameInfo{aStartTime, aStartId, false});
|
2017-11-03 05:22:28 +03:00
|
|
|
}
|
|
|
|
|
2019-09-26 12:29:24 +03:00
|
|
|
void RenderThread::DecPendingFrameBuildCount(wr::WindowId aWindowId) {
|
|
|
|
auto windows = mWindowInfos.Lock();
|
|
|
|
auto it = windows->find(AsUint64(aWindowId));
|
|
|
|
if (it == windows->end()) {
|
|
|
|
MOZ_ASSERT(false);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
WindowInfo* info = it->second;
|
|
|
|
MOZ_RELEASE_ASSERT(info->mPendingFrameBuild >= 1);
|
|
|
|
info->mPendingFrameBuild--;
|
|
|
|
}
|
|
|
|
|
2017-06-07 18:44:05 +03:00
|
|
|
void RenderThread::RegisterExternalImage(
|
2021-11-07 10:26:45 +03:00
|
|
|
const wr::ExternalImageId& aExternalImageId,
|
|
|
|
already_AddRefed<RenderTextureHost> aTexture) {
|
2017-03-07 13:37:28 +03:00
|
|
|
MutexAutoLock lock(mRenderTextureMapLock);
|
2017-06-07 18:44:05 +03:00
|
|
|
|
2017-07-03 15:08:22 +03:00
|
|
|
if (mHasShutdown) {
|
|
|
|
return;
|
|
|
|
}
|
2018-07-10 12:15:47 +03:00
|
|
|
MOZ_ASSERT(mRenderTextures.find(aExternalImageId) == mRenderTextures.end());
|
2020-06-11 10:28:30 +03:00
|
|
|
RefPtr<RenderTextureHost> texture = aTexture;
|
|
|
|
if (texture->SyncObjectNeeded()) {
|
|
|
|
mSyncObjectNeededRenderTextures.emplace(aExternalImageId, texture);
|
|
|
|
}
|
|
|
|
mRenderTextures.emplace(aExternalImageId, texture);
|
2017-03-07 13:37:28 +03:00
|
|
|
}
|
|
|
|
|
2021-11-07 10:26:45 +03:00
|
|
|
void RenderThread::UnregisterExternalImage(
|
|
|
|
const wr::ExternalImageId& aExternalImageId) {
|
2017-03-07 13:37:28 +03:00
|
|
|
MutexAutoLock lock(mRenderTextureMapLock);
|
2017-07-03 15:08:22 +03:00
|
|
|
if (mHasShutdown) {
|
|
|
|
return;
|
|
|
|
}
|
2018-07-10 12:15:47 +03:00
|
|
|
auto it = mRenderTextures.find(aExternalImageId);
|
2018-07-30 04:16:03 +03:00
|
|
|
if (it == mRenderTextures.end()) {
|
|
|
|
return;
|
|
|
|
}
|
2020-06-11 10:28:30 +03:00
|
|
|
|
|
|
|
auto& texture = it->second;
|
|
|
|
if (texture->SyncObjectNeeded()) {
|
|
|
|
MOZ_RELEASE_ASSERT(
|
|
|
|
mSyncObjectNeededRenderTextures.erase(aExternalImageId) == 1);
|
|
|
|
}
|
|
|
|
|
2017-06-07 18:44:05 +03:00
|
|
|
if (!IsInRenderThread()) {
|
|
|
|
// The RenderTextureHost should be released in render thread. So, post the
|
|
|
|
// deletion task here.
|
|
|
|
// The shmem and raw buffer are owned by compositor ipc channel. It's
|
|
|
|
// possible that RenderTextureHost is still exist after the shmem/raw buffer
|
|
|
|
// deletion. Then the buffer in RenderTextureHost becomes invalid. It's fine
|
|
|
|
// for this situation. Gecko will only release the buffer if WR doesn't need
|
|
|
|
// it. So, no one will access the invalid buffer in RenderTextureHost.
|
2018-07-10 12:15:47 +03:00
|
|
|
RefPtr<RenderTextureHost> texture = it->second;
|
|
|
|
mRenderTextures.erase(it);
|
2018-06-15 01:18:48 +03:00
|
|
|
mRenderTexturesDeferred.emplace_back(std::move(texture));
|
2021-07-19 20:35:55 +03:00
|
|
|
PostRunnable(NewRunnableMethod(
|
2018-06-15 01:18:48 +03:00
|
|
|
"RenderThread::DeferredRenderTextureHostDestroy", this,
|
2017-06-07 18:44:05 +03:00
|
|
|
&RenderThread::DeferredRenderTextureHostDestroy));
|
|
|
|
} else {
|
2018-07-10 12:15:47 +03:00
|
|
|
mRenderTextures.erase(it);
|
2017-06-07 18:44:05 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-07 10:26:45 +03:00
|
|
|
void RenderThread::PrepareForUse(const wr::ExternalImageId& aExternalImageId) {
|
2020-08-21 10:32:47 +03:00
|
|
|
AddRenderTextureOp(RenderTextureOp::PrepareForUse, aExternalImageId);
|
|
|
|
}
|
2019-04-04 01:05:27 +03:00
|
|
|
|
2021-11-07 10:26:45 +03:00
|
|
|
void RenderThread::NotifyNotUsed(const wr::ExternalImageId& aExternalImageId) {
|
2020-08-21 10:32:47 +03:00
|
|
|
AddRenderTextureOp(RenderTextureOp::NotifyNotUsed, aExternalImageId);
|
|
|
|
}
|
2019-04-04 01:05:27 +03:00
|
|
|
|
2021-11-07 10:26:45 +03:00
|
|
|
void RenderThread::NotifyForUse(const wr::ExternalImageId& aExternalImageId) {
|
2020-08-21 10:32:47 +03:00
|
|
|
AddRenderTextureOp(RenderTextureOp::NotifyForUse, aExternalImageId);
|
2019-04-04 01:05:27 +03:00
|
|
|
}
|
|
|
|
|
2021-11-07 10:26:45 +03:00
|
|
|
void RenderThread::AddRenderTextureOp(
|
|
|
|
RenderTextureOp aOp, const wr::ExternalImageId& aExternalImageId) {
|
2019-11-08 15:52:16 +03:00
|
|
|
MOZ_ASSERT(!IsInRenderThread());
|
2019-04-04 01:05:27 +03:00
|
|
|
|
|
|
|
MutexAutoLock lock(mRenderTextureMapLock);
|
|
|
|
|
|
|
|
auto it = mRenderTextures.find(aExternalImageId);
|
|
|
|
MOZ_ASSERT(it != mRenderTextures.end());
|
|
|
|
if (it == mRenderTextures.end()) {
|
|
|
|
return;
|
|
|
|
}
|
2020-08-21 10:32:47 +03:00
|
|
|
|
2019-04-04 01:05:27 +03:00
|
|
|
RefPtr<RenderTextureHost> texture = it->second;
|
2020-08-21 10:32:47 +03:00
|
|
|
mRenderTextureOps.emplace_back(aOp, std::move(texture));
|
2021-07-19 20:35:55 +03:00
|
|
|
PostRunnable(NewRunnableMethod("RenderThread::HandleRenderTextureOps", this,
|
|
|
|
&RenderThread::HandleRenderTextureOps));
|
2019-04-26 10:48:54 +03:00
|
|
|
}
|
|
|
|
|
2020-08-21 10:32:47 +03:00
|
|
|
void RenderThread::HandleRenderTextureOps() {
|
|
|
|
MOZ_ASSERT(IsInRenderThread());
|
2020-05-16 03:46:28 +03:00
|
|
|
|
2020-08-21 10:32:47 +03:00
|
|
|
std::list<std::pair<RenderTextureOp, RefPtr<RenderTextureHost>>>
|
|
|
|
renderTextureOps;
|
2020-05-16 03:46:28 +03:00
|
|
|
{
|
|
|
|
MutexAutoLock lock(mRenderTextureMapLock);
|
2020-08-21 10:32:47 +03:00
|
|
|
mRenderTextureOps.swap(renderTextureOps);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto& it : renderTextureOps) {
|
|
|
|
switch (it.first) {
|
|
|
|
case RenderTextureOp::PrepareForUse:
|
|
|
|
it.second->PrepareForUse();
|
|
|
|
break;
|
|
|
|
case RenderTextureOp::NotifyForUse:
|
|
|
|
it.second->NotifyForUse();
|
|
|
|
break;
|
|
|
|
case RenderTextureOp::NotifyNotUsed:
|
|
|
|
it.second->NotifyNotUsed();
|
|
|
|
break;
|
2020-05-16 03:46:28 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-23 14:57:17 +03:00
|
|
|
void RenderThread::UnregisterExternalImageDuringShutdown(
|
2021-11-07 10:26:45 +03:00
|
|
|
const wr::ExternalImageId& aExternalImageId) {
|
2018-04-23 14:57:17 +03:00
|
|
|
MOZ_ASSERT(IsInRenderThread());
|
|
|
|
MutexAutoLock lock(mRenderTextureMapLock);
|
|
|
|
MOZ_ASSERT(mHasShutdown);
|
2018-07-10 12:15:47 +03:00
|
|
|
MOZ_ASSERT(mRenderTextures.find(aExternalImageId) != mRenderTextures.end());
|
|
|
|
mRenderTextures.erase(aExternalImageId);
|
2018-04-23 14:57:17 +03:00
|
|
|
}
|
|
|
|
|
2020-06-11 10:28:30 +03:00
|
|
|
bool RenderThread::SyncObjectNeeded() {
|
|
|
|
MOZ_ASSERT(IsInRenderThread());
|
|
|
|
MutexAutoLock lock(mRenderTextureMapLock);
|
|
|
|
return !mSyncObjectNeededRenderTextures.empty();
|
|
|
|
}
|
|
|
|
|
2018-06-15 01:18:48 +03:00
|
|
|
void RenderThread::DeferredRenderTextureHostDestroy() {
|
|
|
|
MutexAutoLock lock(mRenderTextureMapLock);
|
|
|
|
mRenderTexturesDeferred.clear();
|
2017-03-07 13:37:28 +03:00
|
|
|
}
|
|
|
|
|
2017-06-28 02:20:36 +03:00
|
|
|
RenderTextureHost* RenderThread::GetRenderTexture(
|
2021-11-07 10:26:45 +03:00
|
|
|
const wr::ExternalImageId& aExternalImageId) {
|
2017-06-07 18:44:05 +03:00
|
|
|
MOZ_ASSERT(IsInRenderThread());
|
|
|
|
|
2017-03-07 13:37:28 +03:00
|
|
|
MutexAutoLock lock(mRenderTextureMapLock);
|
2021-11-07 10:26:45 +03:00
|
|
|
auto it = mRenderTextures.find(aExternalImageId);
|
2018-07-10 12:15:47 +03:00
|
|
|
MOZ_ASSERT(it != mRenderTextures.end());
|
|
|
|
if (it == mRenderTextures.end()) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
return it->second;
|
2017-03-07 13:37:28 +03:00
|
|
|
}
|
|
|
|
|
2018-10-10 06:20:20 +03:00
|
|
|
void RenderThread::InitDeviceTask() {
|
|
|
|
MOZ_ASSERT(IsInRenderThread());
|
2021-03-17 13:51:45 +03:00
|
|
|
MOZ_ASSERT(!mSingletonGL);
|
2021-09-02 01:27:15 +03:00
|
|
|
LOG("RenderThread::InitDeviceTask()");
|
2018-10-10 06:20:20 +03:00
|
|
|
|
2020-06-24 04:23:43 +03:00
|
|
|
if (gfx::gfxVars::UseSoftwareWebRender()) {
|
|
|
|
// Ensure we don't instantiate any shared GL context when SW-WR is used.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-09-13 20:31:14 +03:00
|
|
|
nsAutoCString err;
|
2021-03-29 16:34:16 +03:00
|
|
|
CreateSingletonGL(err);
|
2020-06-24 04:23:43 +03:00
|
|
|
if (gfx::gfxVars::UseWebRenderProgramBinaryDisk()) {
|
2019-03-16 03:31:38 +03:00
|
|
|
mProgramCache = MakeUnique<WebRenderProgramCache>(ThreadPool().Raw());
|
2018-10-10 06:20:20 +03:00
|
|
|
}
|
|
|
|
// Query the shared GL context to force the
|
|
|
|
// lazy initialization to happen now.
|
2021-03-17 13:51:45 +03:00
|
|
|
SingletonGL();
|
2018-05-31 09:07:34 +03:00
|
|
|
}
|
|
|
|
|
2021-07-19 20:35:55 +03:00
|
|
|
void RenderThread::PostRunnable(already_AddRefed<nsIRunnable> aRunnable) {
|
|
|
|
nsCOMPtr<nsIRunnable> runnable = aRunnable;
|
2021-07-19 20:35:55 +03:00
|
|
|
mThread->Dispatch(runnable.forget());
|
2021-07-19 20:35:55 +03:00
|
|
|
}
|
|
|
|
|
2020-12-10 17:26:32 +03:00
|
|
|
#ifndef XP_WIN
|
|
|
|
static DeviceResetReason GLenumToResetReason(GLenum aReason) {
|
|
|
|
switch (aReason) {
|
|
|
|
case LOCAL_GL_NO_ERROR:
|
|
|
|
return DeviceResetReason::FORCED_RESET;
|
|
|
|
case LOCAL_GL_INNOCENT_CONTEXT_RESET_ARB:
|
|
|
|
return DeviceResetReason::DRIVER_ERROR;
|
|
|
|
case LOCAL_GL_PURGED_CONTEXT_RESET_NV:
|
|
|
|
return DeviceResetReason::NVIDIA_VIDEO;
|
|
|
|
case LOCAL_GL_GUILTY_CONTEXT_RESET_ARB:
|
|
|
|
return DeviceResetReason::RESET;
|
|
|
|
case LOCAL_GL_UNKNOWN_CONTEXT_RESET_ARB:
|
|
|
|
return DeviceResetReason::UNKNOWN;
|
|
|
|
case LOCAL_GL_OUT_OF_MEMORY:
|
|
|
|
return DeviceResetReason::OUT_OF_MEMORY;
|
|
|
|
default:
|
|
|
|
return DeviceResetReason::OTHER;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2021-03-03 13:29:40 +03:00
|
|
|
void RenderThread::HandleDeviceReset(const char* aWhere, GLenum aReason) {
|
2018-06-13 18:01:06 +03:00
|
|
|
MOZ_ASSERT(IsInRenderThread());
|
|
|
|
|
|
|
|
if (mHandlingDeviceReset) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-12-10 17:26:32 +03:00
|
|
|
#ifndef XP_WIN
|
|
|
|
// On Windows, see DeviceManagerDx::MaybeResetAndReacquireDevices.
|
|
|
|
gfx::GPUProcessManager::RecordDeviceReset(GLenumToResetReason(aReason));
|
|
|
|
#endif
|
|
|
|
|
2020-12-14 03:26:18 +03:00
|
|
|
{
|
|
|
|
MutexAutoLock lock(mRenderTextureMapLock);
|
|
|
|
mRenderTexturesDeferred.clear();
|
|
|
|
for (const auto& entry : mRenderTextures) {
|
|
|
|
entry.second->ClearCachedResources();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-07 23:36:11 +03:00
|
|
|
mHandlingDeviceReset = aReason != LOCAL_GL_NO_ERROR;
|
|
|
|
if (mHandlingDeviceReset) {
|
|
|
|
// All RenderCompositors will be destroyed by the GPUProcessManager in
|
|
|
|
// either OnRemoteProcessDeviceReset via the GPUChild, or
|
|
|
|
// OnInProcessDeviceReset here directly.
|
2018-06-19 13:27:37 +03:00
|
|
|
gfxCriticalNote << "GFX: RenderThread detected a device reset in "
|
|
|
|
<< aWhere;
|
|
|
|
if (XRE_IsGPUProcess()) {
|
|
|
|
gfx::GPUParent::GetSingleton()->NotifyDeviceReset();
|
2020-12-07 23:36:11 +03:00
|
|
|
} else {
|
|
|
|
#ifndef XP_WIN
|
|
|
|
// FIXME(aosmond): Do we need to do this on Windows? nsWindow::OnPaint
|
|
|
|
// seems to do its own detection for the parent process.
|
|
|
|
bool guilty = aReason == LOCAL_GL_GUILTY_CONTEXT_RESET_ARB;
|
|
|
|
NS_DispatchToMainThread(NS_NewRunnableFunction(
|
|
|
|
"gfx::GPUProcessManager::OnInProcessDeviceReset", [guilty]() -> void {
|
|
|
|
gfx::GPUProcessManager::Get()->OnInProcessDeviceReset(guilty);
|
|
|
|
}));
|
|
|
|
#endif
|
2018-06-19 13:27:37 +03:00
|
|
|
}
|
2018-06-13 18:01:06 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool RenderThread::IsHandlingDeviceReset() {
|
|
|
|
MOZ_ASSERT(IsInRenderThread());
|
|
|
|
return mHandlingDeviceReset;
|
|
|
|
}
|
|
|
|
|
2018-06-19 13:27:37 +03:00
|
|
|
void RenderThread::SimulateDeviceReset() {
|
|
|
|
if (!IsInRenderThread()) {
|
2021-07-19 20:35:55 +03:00
|
|
|
PostRunnable(NewRunnableMethod("RenderThread::SimulateDeviceReset", this,
|
|
|
|
&RenderThread::SimulateDeviceReset));
|
2018-06-19 13:27:37 +03:00
|
|
|
} else {
|
|
|
|
// When this function is called GPUProcessManager::SimulateDeviceReset()
|
|
|
|
// already triggers destroying all CompositorSessions before re-creating
|
|
|
|
// them.
|
2021-03-03 13:29:40 +03:00
|
|
|
HandleDeviceReset("SimulateDeviceReset", LOCAL_GL_NO_ERROR);
|
2018-06-19 13:27:37 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-19 19:14:56 +03:00
|
|
|
static void DoNotifyWebRenderError(WebRenderError aError) {
|
|
|
|
layers::CompositorManagerParent::NotifyWebRenderError(aError);
|
|
|
|
}
|
|
|
|
|
2020-09-09 04:04:53 +03:00
|
|
|
void RenderThread::NotifyWebRenderError(WebRenderError aError) {
|
|
|
|
MOZ_ASSERT(IsInRenderThread());
|
|
|
|
|
|
|
|
layers::CompositorThread()->Dispatch(NewRunnableFunction(
|
|
|
|
"DoNotifyWebRenderErrorRunnable", &DoNotifyWebRenderError, aError));
|
|
|
|
}
|
|
|
|
|
2019-06-19 19:14:56 +03:00
|
|
|
void RenderThread::HandleWebRenderError(WebRenderError aError) {
|
|
|
|
if (mHandlingWebRenderError) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-09-09 04:04:53 +03:00
|
|
|
NotifyWebRenderError(aError);
|
|
|
|
|
2019-06-19 19:14:56 +03:00
|
|
|
{
|
|
|
|
MutexAutoLock lock(mRenderTextureMapLock);
|
|
|
|
mRenderTexturesDeferred.clear();
|
|
|
|
for (const auto& entry : mRenderTextures) {
|
|
|
|
entry.second->ClearCachedResources();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mHandlingWebRenderError = true;
|
|
|
|
// WebRender is going to be disabled by
|
|
|
|
// GPUProcessManager::NotifyWebRenderError()
|
|
|
|
}
|
|
|
|
|
|
|
|
bool RenderThread::IsHandlingWebRenderError() {
|
|
|
|
MOZ_ASSERT(IsInRenderThread());
|
|
|
|
return mHandlingWebRenderError;
|
|
|
|
}
|
|
|
|
|
2021-03-17 13:51:45 +03:00
|
|
|
gl::GLContext* RenderThread::SingletonGL() {
|
2020-09-13 20:31:14 +03:00
|
|
|
nsAutoCString err;
|
2021-04-28 15:33:55 +03:00
|
|
|
auto* gl = SingletonGL(err);
|
2020-09-13 20:31:14 +03:00
|
|
|
if (!err.IsEmpty()) {
|
|
|
|
gfxCriticalNote << err.get();
|
|
|
|
}
|
|
|
|
return gl;
|
|
|
|
}
|
|
|
|
|
2021-03-29 16:34:16 +03:00
|
|
|
void RenderThread::CreateSingletonGL(nsACString& aError) {
|
2021-09-02 01:27:15 +03:00
|
|
|
MOZ_ASSERT(IsInRenderThread());
|
|
|
|
LOG("RenderThread::CreateSingletonGL()");
|
|
|
|
|
2021-03-29 16:34:16 +03:00
|
|
|
mSingletonGL = CreateGLContext(aError);
|
|
|
|
mSingletonGLIsForHardwareWebRender = !gfx::gfxVars::UseSoftwareWebRender();
|
|
|
|
}
|
|
|
|
|
2021-03-17 13:51:45 +03:00
|
|
|
gl::GLContext* RenderThread::SingletonGL(nsACString& aError) {
|
2018-10-04 05:54:50 +03:00
|
|
|
MOZ_ASSERT(IsInRenderThread());
|
2021-03-17 13:51:45 +03:00
|
|
|
if (!mSingletonGL) {
|
2021-03-29 16:34:16 +03:00
|
|
|
CreateSingletonGL(aError);
|
2018-10-10 06:20:20 +03:00
|
|
|
mShaders = nullptr;
|
|
|
|
}
|
2021-07-20 22:10:58 +03:00
|
|
|
if (mSingletonGL && mSingletonGLIsForHardwareWebRender && !mShaders) {
|
2021-03-17 13:51:45 +03:00
|
|
|
mShaders = MakeUnique<WebRenderShaders>(mSingletonGL, mProgramCache.get());
|
2018-10-04 05:54:50 +03:00
|
|
|
}
|
|
|
|
|
2021-03-17 13:51:45 +03:00
|
|
|
return mSingletonGL.get();
|
2018-10-04 05:54:50 +03:00
|
|
|
}
|
|
|
|
|
2021-03-29 16:34:16 +03:00
|
|
|
gl::GLContext* RenderThread::SingletonGLForCompositorOGL() {
|
|
|
|
MOZ_RELEASE_ASSERT(gfx::gfxVars::UseSoftwareWebRender());
|
|
|
|
|
|
|
|
if (mSingletonGLIsForHardwareWebRender) {
|
|
|
|
// Clear singleton GL, since GLContext is for hardware WebRender.
|
|
|
|
ClearSingletonGL();
|
|
|
|
}
|
|
|
|
return SingletonGL();
|
|
|
|
}
|
|
|
|
|
2021-03-17 13:51:45 +03:00
|
|
|
void RenderThread::ClearSingletonGL() {
|
2018-10-04 05:54:50 +03:00
|
|
|
MOZ_ASSERT(IsInRenderThread());
|
2021-09-02 01:27:15 +03:00
|
|
|
LOG("RenderThread::ClearSingletonGL()");
|
|
|
|
|
Bug 1592044 - Reduce the frequency of IOSurface and framebuffer creation and destruction with the help of a surface pool. r=jgilbert
There are multiple SurfacePools: Main thread painting and the non-WebRender compositors create a new pool per window, and WebRender creates one shared pool across all windows. The non-WebRender users set the pool size limit to zero, i.e. no recycling across paints. This preserves the pre-existing behavior.
WebRender's pool size is configurable with the gfx.webrender.compositor.surface-pool-size pref.
Every window holds on to a SurfacePoolHandle. A SurfacePoolHandle has an owning reference to the pool, via a surface pool wrapper. Once all handles are gone, the surface pool goes away, too.
The SurfacePool holds on to IOSurfaces and MozFramebuffers. Both are created on demand, independently, but are associated with each other.
A given NativeLayer uses only one surface pool handle during its lifetime. The native layer no longer influences which GLContext its framebuffers are created for; the GL context is now managed by the surface pool handle.
As a result, a NativeLayer can no longer change which GLContext its framebuffers are created by.
So in the future, if we ever need to migrate a window frome one GLContext to another, we will need to recreate the NativeLayers inside it. I think that's ok.
Differential Revision: https://phabricator.services.mozilla.com/D54859
--HG--
extra : moz-landing-system : lando
2019-12-19 00:01:51 +03:00
|
|
|
if (mSurfacePool) {
|
2021-03-17 13:51:45 +03:00
|
|
|
mSurfacePool->DestroyGLResourcesForContext(mSingletonGL);
|
Bug 1592044 - Reduce the frequency of IOSurface and framebuffer creation and destruction with the help of a surface pool. r=jgilbert
There are multiple SurfacePools: Main thread painting and the non-WebRender compositors create a new pool per window, and WebRender creates one shared pool across all windows. The non-WebRender users set the pool size limit to zero, i.e. no recycling across paints. This preserves the pre-existing behavior.
WebRender's pool size is configurable with the gfx.webrender.compositor.surface-pool-size pref.
Every window holds on to a SurfacePoolHandle. A SurfacePoolHandle has an owning reference to the pool, via a surface pool wrapper. Once all handles are gone, the surface pool goes away, too.
The SurfacePool holds on to IOSurfaces and MozFramebuffers. Both are created on demand, independently, but are associated with each other.
A given NativeLayer uses only one surface pool handle during its lifetime. The native layer no longer influences which GLContext its framebuffers are created for; the GL context is now managed by the surface pool handle.
As a result, a NativeLayer can no longer change which GLContext its framebuffers are created by.
So in the future, if we ever need to migrate a window frome one GLContext to another, we will need to recreate the NativeLayers inside it. I think that's ok.
Differential Revision: https://phabricator.services.mozilla.com/D54859
--HG--
extra : moz-landing-system : lando
2019-12-19 00:01:51 +03:00
|
|
|
}
|
2021-03-29 02:55:05 +03:00
|
|
|
if (mProgramsForCompositorOGL) {
|
|
|
|
mProgramsForCompositorOGL->Clear();
|
|
|
|
mProgramsForCompositorOGL = nullptr;
|
|
|
|
}
|
2018-10-10 06:20:20 +03:00
|
|
|
mShaders = nullptr;
|
2021-03-17 13:51:45 +03:00
|
|
|
mSingletonGL = nullptr;
|
2018-10-04 05:54:50 +03:00
|
|
|
}
|
|
|
|
|
2021-03-29 02:55:05 +03:00
|
|
|
RefPtr<layers::ShaderProgramOGLsHolder>
|
|
|
|
RenderThread::GetProgramsForCompositorOGL() {
|
|
|
|
if (!mSingletonGL) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!mProgramsForCompositorOGL) {
|
|
|
|
mProgramsForCompositorOGL =
|
|
|
|
MakeAndAddRef<layers::ShaderProgramOGLsHolder>(mSingletonGL);
|
|
|
|
}
|
|
|
|
return mProgramsForCompositorOGL;
|
|
|
|
}
|
|
|
|
|
Bug 1592044 - Reduce the frequency of IOSurface and framebuffer creation and destruction with the help of a surface pool. r=jgilbert
There are multiple SurfacePools: Main thread painting and the non-WebRender compositors create a new pool per window, and WebRender creates one shared pool across all windows. The non-WebRender users set the pool size limit to zero, i.e. no recycling across paints. This preserves the pre-existing behavior.
WebRender's pool size is configurable with the gfx.webrender.compositor.surface-pool-size pref.
Every window holds on to a SurfacePoolHandle. A SurfacePoolHandle has an owning reference to the pool, via a surface pool wrapper. Once all handles are gone, the surface pool goes away, too.
The SurfacePool holds on to IOSurfaces and MozFramebuffers. Both are created on demand, independently, but are associated with each other.
A given NativeLayer uses only one surface pool handle during its lifetime. The native layer no longer influences which GLContext its framebuffers are created for; the GL context is now managed by the surface pool handle.
As a result, a NativeLayer can no longer change which GLContext its framebuffers are created by.
So in the future, if we ever need to migrate a window frome one GLContext to another, we will need to recreate the NativeLayers inside it. I think that's ok.
Differential Revision: https://phabricator.services.mozilla.com/D54859
--HG--
extra : moz-landing-system : lando
2019-12-19 00:01:51 +03:00
|
|
|
RefPtr<layers::SurfacePool> RenderThread::SharedSurfacePool() {
|
2021-05-11 16:38:59 +03:00
|
|
|
#if defined(XP_MACOSX) || defined(MOZ_WAYLAND)
|
Bug 1592044 - Reduce the frequency of IOSurface and framebuffer creation and destruction with the help of a surface pool. r=jgilbert
There are multiple SurfacePools: Main thread painting and the non-WebRender compositors create a new pool per window, and WebRender creates one shared pool across all windows. The non-WebRender users set the pool size limit to zero, i.e. no recycling across paints. This preserves the pre-existing behavior.
WebRender's pool size is configurable with the gfx.webrender.compositor.surface-pool-size pref.
Every window holds on to a SurfacePoolHandle. A SurfacePoolHandle has an owning reference to the pool, via a surface pool wrapper. Once all handles are gone, the surface pool goes away, too.
The SurfacePool holds on to IOSurfaces and MozFramebuffers. Both are created on demand, independently, but are associated with each other.
A given NativeLayer uses only one surface pool handle during its lifetime. The native layer no longer influences which GLContext its framebuffers are created for; the GL context is now managed by the surface pool handle.
As a result, a NativeLayer can no longer change which GLContext its framebuffers are created by.
So in the future, if we ever need to migrate a window frome one GLContext to another, we will need to recreate the NativeLayers inside it. I think that's ok.
Differential Revision: https://phabricator.services.mozilla.com/D54859
--HG--
extra : moz-landing-system : lando
2019-12-19 00:01:51 +03:00
|
|
|
if (!mSurfacePool) {
|
|
|
|
size_t poolSizeLimit =
|
|
|
|
StaticPrefs::gfx_webrender_compositor_surface_pool_size_AtStartup();
|
|
|
|
mSurfacePool = layers::SurfacePool::Create(poolSizeLimit);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return mSurfacePool;
|
|
|
|
}
|
|
|
|
|
|
|
|
void RenderThread::ClearSharedSurfacePool() { mSurfacePool = nullptr; }
|
|
|
|
|
2020-04-27 05:51:48 +03:00
|
|
|
static void GLAPIENTRY DebugMessageCallback(GLenum aSource, GLenum aType,
|
|
|
|
GLuint aId, GLenum aSeverity,
|
|
|
|
GLsizei aLength,
|
|
|
|
const GLchar* aMessage,
|
|
|
|
const GLvoid* aUserParam) {
|
|
|
|
constexpr const char* kContextLost = "Context has been lost.";
|
|
|
|
|
|
|
|
if (StaticPrefs::gfx_webrender_gl_debug_message_critical_note_AtStartup() &&
|
|
|
|
aSeverity == LOCAL_GL_DEBUG_SEVERITY_HIGH) {
|
|
|
|
auto message = std::string(aMessage, aLength);
|
|
|
|
// When content lost happned, error messages are flooded by its message.
|
|
|
|
if (message != kContextLost) {
|
|
|
|
gfxCriticalNote << message;
|
|
|
|
} else {
|
|
|
|
gfxCriticalNoteOnce << message;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (StaticPrefs::gfx_webrender_gl_debug_message_print_AtStartup()) {
|
|
|
|
gl::GLContext* gl = (gl::GLContext*)aUserParam;
|
|
|
|
gl->DebugCallback(aSource, aType, aId, aSeverity, aLength, aMessage);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
void RenderThread::MaybeEnableGLDebugMessage(gl::GLContext* aGLContext) {
|
|
|
|
if (!aGLContext) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool enableDebugMessage =
|
|
|
|
StaticPrefs::gfx_webrender_gl_debug_message_critical_note_AtStartup() ||
|
|
|
|
StaticPrefs::gfx_webrender_gl_debug_message_print_AtStartup();
|
|
|
|
|
|
|
|
if (enableDebugMessage &&
|
|
|
|
aGLContext->IsExtensionSupported(gl::GLContext::KHR_debug)) {
|
|
|
|
aGLContext->fEnable(LOCAL_GL_DEBUG_OUTPUT);
|
|
|
|
aGLContext->fDisable(LOCAL_GL_DEBUG_OUTPUT_SYNCHRONOUS);
|
|
|
|
aGLContext->fDebugMessageCallback(&DebugMessageCallback, (void*)aGLContext);
|
|
|
|
aGLContext->fDebugMessageControl(LOCAL_GL_DONT_CARE, LOCAL_GL_DONT_CARE,
|
|
|
|
LOCAL_GL_DONT_CARE, 0, nullptr, true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-10 06:20:20 +03:00
|
|
|
WebRenderShaders::WebRenderShaders(gl::GLContext* gl,
|
|
|
|
WebRenderProgramCache* programCache) {
|
|
|
|
mGL = gl;
|
2020-06-08 11:18:34 +03:00
|
|
|
mShaders =
|
|
|
|
wr_shaders_new(gl, programCache ? programCache->Raw() : nullptr,
|
|
|
|
StaticPrefs::gfx_webrender_precache_shaders_AtStartup());
|
2018-10-10 06:20:20 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
WebRenderShaders::~WebRenderShaders() {
|
|
|
|
wr_shaders_delete(mShaders, mGL.get());
|
|
|
|
}
|
2018-10-04 05:54:50 +03:00
|
|
|
|
2019-12-09 23:21:41 +03:00
|
|
|
WebRenderThreadPool::WebRenderThreadPool(bool low_priority) {
|
|
|
|
mThreadPool = wr_thread_pool_new(low_priority);
|
2017-06-13 18:57:16 +03:00
|
|
|
}
|
|
|
|
|
2019-07-12 01:36:44 +03:00
|
|
|
WebRenderThreadPool::~WebRenderThreadPool() { Release(); }
|
2017-06-13 18:57:16 +03:00
|
|
|
|
2019-07-01 18:24:32 +03:00
|
|
|
void WebRenderThreadPool::Release() {
|
|
|
|
if (mThreadPool) {
|
|
|
|
wr_thread_pool_delete(mThreadPool);
|
|
|
|
mThreadPool = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-31 09:07:34 +03:00
|
|
|
WebRenderProgramCache::WebRenderProgramCache(wr::WrThreadPool* aThreadPool) {
|
|
|
|
MOZ_ASSERT(aThreadPool);
|
|
|
|
|
|
|
|
nsAutoString path;
|
2020-04-05 06:49:51 +03:00
|
|
|
if (gfx::gfxVars::UseWebRenderProgramBinaryDisk()) {
|
2018-05-31 09:07:34 +03:00
|
|
|
path.Append(gfx::gfxVars::ProfDirectory());
|
|
|
|
}
|
|
|
|
mProgramCache = wr_program_cache_new(&path, aThreadPool);
|
2020-04-05 06:49:51 +03:00
|
|
|
if (gfx::gfxVars::UseWebRenderProgramBinaryDisk()) {
|
2019-07-09 13:20:04 +03:00
|
|
|
wr_try_load_startup_shaders_from_disk(mProgramCache);
|
2018-12-04 03:10:01 +03:00
|
|
|
}
|
2017-11-24 14:58:24 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
WebRenderProgramCache::~WebRenderProgramCache() {
|
|
|
|
wr_program_cache_delete(mProgramCache);
|
|
|
|
}
|
|
|
|
|
2021-04-28 15:33:55 +03:00
|
|
|
} // namespace mozilla::wr
|
2017-01-06 21:10:15 +03:00
|
|
|
|
2018-10-04 05:54:50 +03:00
|
|
|
#ifdef XP_WIN
|
2020-09-13 20:31:14 +03:00
|
|
|
static already_AddRefed<gl::GLContext> CreateGLContextANGLE(
|
|
|
|
nsACString& aError) {
|
2020-08-07 10:14:46 +03:00
|
|
|
const RefPtr<ID3D11Device> d3d11Device =
|
|
|
|
gfx::DeviceManagerDx::Get()->GetCompositorDevice();
|
|
|
|
if (!d3d11Device) {
|
2020-09-13 20:31:14 +03:00
|
|
|
aError.Assign("RcANGLE(no compositor device for EGLDisplay)"_ns);
|
2020-08-07 10:14:46 +03:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCString failureId;
|
|
|
|
const auto lib = gl::DefaultEglLibrary(&failureId);
|
|
|
|
if (!lib) {
|
2020-09-13 20:31:14 +03:00
|
|
|
aError.Assign(
|
|
|
|
nsPrintfCString("RcANGLE(load EGL lib failed: %s)", failureId.get()));
|
2020-08-07 10:14:46 +03:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
const auto egl = lib->CreateDisplay(d3d11Device.get());
|
|
|
|
if (!egl) {
|
2020-09-13 20:31:14 +03:00
|
|
|
aError.Assign(nsPrintfCString("RcANGLE(create EGLDisplay failed: %s)",
|
|
|
|
failureId.get()));
|
2018-10-04 05:54:50 +03:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2021-01-26 05:25:08 +03:00
|
|
|
gl::CreateContextFlags flags = gl::CreateContextFlags::PREFER_ES3;
|
|
|
|
|
|
|
|
if (StaticPrefs::gfx_webrender_prefer_robustness_AtStartup()) {
|
|
|
|
flags |= gl::CreateContextFlags::PREFER_ROBUSTNESS;
|
|
|
|
}
|
2018-10-04 05:54:50 +03:00
|
|
|
|
2018-09-27 08:31:30 +03:00
|
|
|
if (egl->IsExtensionSupported(
|
2020-08-07 10:14:46 +03:00
|
|
|
gl::EGLExtension::MOZ_create_context_provoking_vertex_dont_care)) {
|
2018-09-27 08:31:30 +03:00
|
|
|
flags |= gl::CreateContextFlags::PROVOKING_VERTEX_DONT_CARE;
|
|
|
|
}
|
|
|
|
|
2018-10-04 05:54:50 +03:00
|
|
|
// Create GLContext with dummy EGLSurface, the EGLSurface is not used.
|
|
|
|
// Instread we override it with EGLSurface of SwapChain's back buffer.
|
2020-08-07 10:14:46 +03:00
|
|
|
|
|
|
|
const auto dummySize = mozilla::gfx::IntSize(16, 16);
|
|
|
|
auto gl = gl::GLContextEGL::CreateEGLPBufferOffscreenContext(
|
|
|
|
egl, {flags}, dummySize, &failureId);
|
2018-10-04 05:54:50 +03:00
|
|
|
if (!gl || !gl->IsANGLE()) {
|
2020-09-13 20:31:14 +03:00
|
|
|
aError.Assign(nsPrintfCString("RcANGLE(create GL context failed: %x, %s)",
|
|
|
|
gl.get(), failureId.get()));
|
2018-10-04 05:54:50 +03:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!gl->MakeCurrent()) {
|
2020-09-13 20:31:14 +03:00
|
|
|
aError.Assign(
|
|
|
|
nsPrintfCString("RcANGLE(make current GL context failed: %x, %x)",
|
|
|
|
gl.get(), gl->mEgl->mLib->fGetError()));
|
2018-10-04 05:54:50 +03:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return gl.forget();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2021-06-02 02:55:28 +03:00
|
|
|
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WAYLAND) || defined(MOZ_X11)
|
2019-03-20 14:51:33 +03:00
|
|
|
static already_AddRefed<gl::GLContext> CreateGLContextEGL() {
|
|
|
|
// Create GLContext with dummy EGLSurface.
|
2021-03-23 15:10:58 +03:00
|
|
|
bool forHardwareWebRender = true;
|
|
|
|
// SW-WR uses CompositorOGL in native compositor.
|
|
|
|
if (gfx::gfxVars::UseSoftwareWebRender()) {
|
|
|
|
forHardwareWebRender = false;
|
|
|
|
}
|
2019-03-20 14:51:33 +03:00
|
|
|
RefPtr<gl::GLContext> gl =
|
|
|
|
gl::GLContextProviderEGL::CreateForCompositorWidget(
|
2021-03-23 15:10:58 +03:00
|
|
|
nullptr, forHardwareWebRender, /* aForceAccelerated */ true);
|
2019-03-20 14:51:33 +03:00
|
|
|
if (!gl || !gl->MakeCurrent()) {
|
2021-03-23 15:10:58 +03:00
|
|
|
gfxCriticalNote << "Failed GL context creation for hardware WebRender: "
|
|
|
|
<< forHardwareWebRender;
|
2019-03-20 14:51:33 +03:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
return gl.forget();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2019-11-19 20:46:39 +03:00
|
|
|
#ifdef XP_MACOSX
|
|
|
|
static already_AddRefed<gl::GLContext> CreateGLContextCGL() {
|
|
|
|
nsCString failureUnused;
|
|
|
|
return gl::GLContextProvider::CreateHeadless(
|
2020-06-15 21:25:55 +03:00
|
|
|
{gl::CreateContextFlags::ALLOW_OFFLINE_RENDERER |
|
|
|
|
gl::CreateContextFlags::FORCE_ENABLE_HARDWARE},
|
2019-11-19 20:46:39 +03:00
|
|
|
&failureUnused);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-09-13 20:31:14 +03:00
|
|
|
static already_AddRefed<gl::GLContext> CreateGLContext(nsACString& aError) {
|
2020-04-24 14:32:05 +03:00
|
|
|
RefPtr<gl::GLContext> gl;
|
|
|
|
|
2018-10-04 05:54:50 +03:00
|
|
|
#ifdef XP_WIN
|
|
|
|
if (gfx::gfxVars::UseWebRenderANGLE()) {
|
2020-09-13 20:31:14 +03:00
|
|
|
gl = CreateGLContextANGLE(aError);
|
2018-10-04 05:54:50 +03:00
|
|
|
}
|
2020-04-24 14:32:05 +03:00
|
|
|
#elif defined(MOZ_WIDGET_ANDROID)
|
|
|
|
gl = CreateGLContextEGL();
|
2021-06-02 02:55:28 +03:00
|
|
|
#elif defined(MOZ_WAYLAND) || defined(MOZ_X11)
|
2021-03-18 16:46:03 +03:00
|
|
|
if (gfx::gfxVars::UseEGL()) {
|
2020-04-24 14:32:05 +03:00
|
|
|
gl = CreateGLContextEGL();
|
2019-04-12 11:08:03 +03:00
|
|
|
}
|
2020-04-24 14:32:05 +03:00
|
|
|
#elif XP_MACOSX
|
|
|
|
gl = CreateGLContextCGL();
|
2019-03-20 14:51:33 +03:00
|
|
|
#endif
|
2019-11-19 20:46:39 +03:00
|
|
|
|
2020-04-27 05:51:48 +03:00
|
|
|
wr::RenderThread::MaybeEnableGLDebugMessage(gl);
|
2020-04-24 14:32:05 +03:00
|
|
|
|
|
|
|
return gl.forget();
|
2018-10-04 05:54:50 +03:00
|
|
|
}
|
|
|
|
|
2017-01-06 21:10:15 +03:00
|
|
|
extern "C" {
|
|
|
|
|
2020-12-16 06:47:08 +03:00
|
|
|
void wr_notifier_wake_up(mozilla::wr::WrWindowId aWindowId,
|
|
|
|
bool aCompositeNeeded) {
|
|
|
|
mozilla::wr::RenderThread::Get()->IncPendingFrameCount(aWindowId, VsyncId(),
|
|
|
|
TimeStamp::Now());
|
|
|
|
mozilla::wr::RenderThread::Get()->DecPendingFrameBuildCount(aWindowId);
|
|
|
|
mozilla::wr::RenderThread::Get()->HandleFrameOneDoc(aWindowId,
|
|
|
|
aCompositeNeeded);
|
2018-02-08 18:49:25 +03:00
|
|
|
}
|
|
|
|
|
2018-01-17 19:19:39 +03:00
|
|
|
void wr_notifier_new_frame_ready(mozilla::wr::WrWindowId aWindowId) {
|
2019-09-26 12:29:24 +03:00
|
|
|
mozilla::wr::RenderThread::Get()->DecPendingFrameBuildCount(aWindowId);
|
2019-08-06 10:01:15 +03:00
|
|
|
mozilla::wr::RenderThread::Get()->HandleFrameOneDoc(aWindowId,
|
|
|
|
/* aRender */ true);
|
2018-01-17 19:19:39 +03:00
|
|
|
}
|
|
|
|
|
2018-04-27 14:41:03 +03:00
|
|
|
void wr_notifier_nop_frame_done(mozilla::wr::WrWindowId aWindowId) {
|
2019-09-26 12:29:24 +03:00
|
|
|
mozilla::wr::RenderThread::Get()->DecPendingFrameBuildCount(aWindowId);
|
2019-08-06 10:01:15 +03:00
|
|
|
mozilla::wr::RenderThread::Get()->HandleFrameOneDoc(aWindowId,
|
|
|
|
/* aRender */ false);
|
2017-01-06 21:10:15 +03:00
|
|
|
}
|
|
|
|
|
2017-06-28 02:20:36 +03:00
|
|
|
void wr_notifier_external_event(mozilla::wr::WrWindowId aWindowId,
|
|
|
|
size_t aRawEvent) {
|
2017-01-17 03:22:09 +03:00
|
|
|
mozilla::UniquePtr<mozilla::wr::RendererEvent> evt(
|
|
|
|
reinterpret_cast<mozilla::wr::RendererEvent*>(aRawEvent));
|
|
|
|
mozilla::wr::RenderThread::Get()->RunEvent(mozilla::wr::WindowId(aWindowId),
|
2018-05-30 22:15:35 +03:00
|
|
|
std::move(evt));
|
2017-01-06 21:10:15 +03:00
|
|
|
}
|
|
|
|
|
2021-10-05 15:54:39 +03:00
|
|
|
static void NotifyScheduleRender(mozilla::wr::WrWindowId aWindowId,
|
|
|
|
wr::RenderReasons aReasons) {
|
2018-12-21 01:52:07 +03:00
|
|
|
RefPtr<mozilla::layers::CompositorBridgeParent> cbp = mozilla::layers::
|
|
|
|
CompositorBridgeParent::GetCompositorBridgeParentFromWindowId(aWindowId);
|
|
|
|
if (cbp) {
|
2021-10-05 15:54:39 +03:00
|
|
|
cbp->ScheduleComposition(aReasons);
|
2018-12-21 01:52:07 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-05 15:54:39 +03:00
|
|
|
void wr_schedule_render(mozilla::wr::WrWindowId aWindowId,
|
|
|
|
wr::RenderReasons aReasons) {
|
2021-04-27 00:04:29 +03:00
|
|
|
layers::CompositorThread()->Dispatch(NewRunnableFunction(
|
2021-10-05 15:54:39 +03:00
|
|
|
"NotifyScheduleRender", &NotifyScheduleRender, aWindowId, aReasons));
|
2021-04-27 00:04:29 +03:00
|
|
|
}
|
|
|
|
|
2021-04-28 15:33:55 +03:00
|
|
|
static void NotifyDidSceneBuild(
|
|
|
|
mozilla::wr::WrWindowId aWindowId,
|
|
|
|
const RefPtr<const wr::WebRenderPipelineInfo>& aInfo) {
|
2021-04-27 00:04:29 +03:00
|
|
|
RefPtr<mozilla::layers::CompositorBridgeParent> cbp = mozilla::layers::
|
|
|
|
CompositorBridgeParent::GetCompositorBridgeParentFromWindowId(aWindowId);
|
|
|
|
if (cbp) {
|
|
|
|
cbp->NotifyDidSceneBuild(aInfo);
|
|
|
|
}
|
2018-12-21 01:43:01 +03:00
|
|
|
}
|
|
|
|
|
2018-12-21 01:52:07 +03:00
|
|
|
void wr_finished_scene_build(mozilla::wr::WrWindowId aWindowId,
|
2021-04-28 15:33:55 +03:00
|
|
|
mozilla::wr::WrPipelineInfo* aPipelineInfo) {
|
2020-02-19 21:34:51 +03:00
|
|
|
RefPtr<wr::WebRenderPipelineInfo> info = new wr::WebRenderPipelineInfo();
|
2021-04-28 15:33:55 +03:00
|
|
|
info->Raw() = std::move(*aPipelineInfo);
|
2021-04-27 00:04:29 +03:00
|
|
|
layers::CompositorThread()->Dispatch(NewRunnableFunction(
|
|
|
|
"NotifyDidSceneBuild", &NotifyDidSceneBuild, aWindowId, info));
|
2018-05-11 16:09:16 +03:00
|
|
|
}
|
|
|
|
|
2017-01-06 21:10:15 +03:00
|
|
|
} // extern C
|