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: */
|
2012-05-21 15:12:37 +04: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/. */
|
2011-12-16 00:07:19 +04:00
|
|
|
|
2016-03-22 21:08:38 +03:00
|
|
|
#include "mozilla/layers/CompositorBridgeParent.h"
|
2018-03-06 18:25:39 +03:00
|
|
|
|
2013-08-12 03:17:23 +04:00
|
|
|
#include <stdio.h> // for fprintf, stdout
|
|
|
|
#include <stdint.h> // for uint64_t
|
|
|
|
#include <map> // for _Rb_tree_iterator, etc
|
|
|
|
#include <utility> // for pair
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2018-03-06 18:25:39 +03:00
|
|
|
#include "apz/src/APZCTreeManager.h" // for APZCTreeManager
|
2013-08-12 03:17:23 +04:00
|
|
|
#include "LayerTransactionParent.h" // for LayerTransactionParent
|
|
|
|
#include "RenderTrace.h" // for RenderTraceLayers
|
|
|
|
#include "base/message_loop.h" // for MessageLoop
|
2015-04-01 11:40:35 +03:00
|
|
|
#include "base/process.h" // for ProcessId
|
2013-08-12 03:17:23 +04:00
|
|
|
#include "base/task.h" // for CancelableTask, etc
|
|
|
|
#include "base/thread.h" // for Thread
|
|
|
|
#include "gfxContext.h" // for gfxContext
|
|
|
|
#include "gfxPlatform.h" // for gfxPlatform
|
2016-03-10 12:20:40 +03:00
|
|
|
#include "TreeTraversal.h" // for ForEachNode
|
2014-07-23 03:02:25 +04:00
|
|
|
#ifdef MOZ_WIDGET_GTK
|
|
|
|
# include "gfxPlatformGtk.h" // for gfxPlatform
|
|
|
|
#endif
|
2013-08-12 03:17:23 +04:00
|
|
|
#include "mozilla/AutoRestore.h" // for AutoRestore
|
2015-01-13 21:26:26 +03:00
|
|
|
#include "mozilla/ClearOnShutdown.h" // for ClearOnShutdown
|
2013-08-12 03:17:23 +04:00
|
|
|
#include "mozilla/DebugOnly.h" // for DebugOnly
|
2019-07-26 04:10:23 +03:00
|
|
|
#include "mozilla/StaticPrefs_gfx.h"
|
|
|
|
#include "mozilla/StaticPrefs_layers.h"
|
|
|
|
#include "mozilla/StaticPrefs_layout.h"
|
2019-04-10 00:38:15 +03:00
|
|
|
#include "mozilla/dom/BrowserParent.h"
|
2013-09-27 04:37:19 +04:00
|
|
|
#include "mozilla/gfx/2D.h" // for DrawTarget
|
2013-08-12 03:17:23 +04:00
|
|
|
#include "mozilla/gfx/Point.h" // for IntSize
|
2015-04-21 18:04:57 +03:00
|
|
|
#include "mozilla/gfx/Rect.h" // for IntSize
|
2017-02-07 12:37:57 +03:00
|
|
|
#include "mozilla/gfx/gfxVars.h" // for gfxVars
|
2017-10-30 15:51:52 +03:00
|
|
|
#include "VRManager.h" // for VRManager
|
2013-08-12 03:17:23 +04:00
|
|
|
#include "mozilla/ipc/Transport.h" // for Transport
|
2017-02-15 00:49:27 +03:00
|
|
|
#include "mozilla/gfx/gfxVars.h"
|
2017-08-30 03:10:22 +03:00
|
|
|
#include "mozilla/gfx/GPUParent.h"
|
2017-02-10 01:30:11 +03:00
|
|
|
#include "mozilla/layers/AnimationHelper.h" // for CompositorAnimationStorage
|
2016-08-16 23:59:13 +03:00
|
|
|
#include "mozilla/layers/APZCTreeManagerParent.h" // for APZCTreeManagerParent
|
2018-03-02 07:00:41 +03:00
|
|
|
#include "mozilla/layers/APZSampler.h" // for APZSampler
|
|
|
|
#include "mozilla/layers/APZThreadUtils.h" // for APZThreadUtils
|
2018-03-29 01:36:42 +03:00
|
|
|
#include "mozilla/layers/APZUpdater.h" // for APZUpdater
|
2013-08-12 03:17:23 +04:00
|
|
|
#include "mozilla/layers/AsyncCompositionManager.h"
|
|
|
|
#include "mozilla/layers/BasicCompositor.h" // for BasicCompositor
|
2019-03-12 18:06:48 +03:00
|
|
|
#include "mozilla/layers/CompositionRecorder.h" // for CompositionRecorder
|
2013-08-12 03:17:23 +04:00
|
|
|
#include "mozilla/layers/Compositor.h" // for Compositor
|
2017-06-14 18:40:00 +03:00
|
|
|
#include "mozilla/layers/CompositorManagerParent.h" // for CompositorManagerParent
|
2013-08-12 03:17:23 +04:00
|
|
|
#include "mozilla/layers/CompositorOGL.h" // for CompositorOGL
|
2016-05-16 09:38:34 +03:00
|
|
|
#include "mozilla/layers/CompositorThread.h"
|
2013-08-12 03:17:23 +04:00
|
|
|
#include "mozilla/layers/CompositorTypes.h"
|
2016-11-21 04:14:32 +03:00
|
|
|
#include "mozilla/layers/CompositorVsyncScheduler.h"
|
2019-03-04 00:02:25 +03:00
|
|
|
#include "mozilla/layers/ContentCompositorBridgeParent.h"
|
2015-06-08 19:53:41 +03:00
|
|
|
#include "mozilla/layers/FrameUniformityData.h"
|
2015-07-06 06:02:26 +03:00
|
|
|
#include "mozilla/layers/ImageBridgeParent.h"
|
2013-08-12 03:17:23 +04:00
|
|
|
#include "mozilla/layers/LayerManagerComposite.h"
|
2017-06-24 00:23:12 +03:00
|
|
|
#include "mozilla/layers/LayerManagerMLGPU.h"
|
2016-08-16 23:59:13 +03:00
|
|
|
#include "mozilla/layers/LayerTreeOwnerTracker.h"
|
2013-08-12 03:17:23 +04:00
|
|
|
#include "mozilla/layers/LayersTypes.h"
|
|
|
|
#include "mozilla/layers/PLayerTransactionParent.h"
|
2016-01-08 22:17:39 +03:00
|
|
|
#include "mozilla/layers/RemoteContentController.h"
|
2016-11-16 16:54:51 +03:00
|
|
|
#include "mozilla/layers/WebRenderBridgeParent.h"
|
2017-07-25 11:54:36 +03:00
|
|
|
#include "mozilla/layers/AsyncImagePipelineManager.h"
|
2017-01-17 03:21:52 +03:00
|
|
|
#include "mozilla/webrender/WebRenderAPI.h"
|
2015-07-05 21:56:04 +03:00
|
|
|
#include "mozilla/media/MediaSystemResourceService.h" // for MediaSystemResourceService
|
2013-08-12 03:17:23 +04:00
|
|
|
#include "mozilla/mozalloc.h" // for operator new, etc
|
2019-05-28 21:58:06 +03:00
|
|
|
#include "mozilla/PerfStats.h"
|
2014-12-11 05:15:48 +03:00
|
|
|
#include "mozilla/Telemetry.h"
|
2014-07-23 03:02:25 +04:00
|
|
|
#ifdef MOZ_WIDGET_GTK
|
|
|
|
# include "basic/X11BasicCompositor.h" // for X11BasicCompositor
|
|
|
|
#endif
|
2013-08-12 03:17:23 +04:00
|
|
|
#include "nsCOMPtr.h" // for already_AddRefed
|
2015-02-10 01:34:50 +03:00
|
|
|
#include "nsDebug.h" // for NS_ASSERTION, etc
|
2014-02-27 01:36:35 +04:00
|
|
|
#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc
|
2013-08-12 03:17:23 +04:00
|
|
|
#include "nsIWidget.h" // for nsIWidget
|
|
|
|
#include "nsTArray.h" // for nsTArray
|
|
|
|
#include "nsThreadUtils.h" // for NS_IsMainThread
|
|
|
|
#include "nsXULAppAPI.h" // for XRE_GetIOMessageLoop
|
2013-05-03 21:34:29 +04:00
|
|
|
#ifdef XP_WIN
|
|
|
|
# include "mozilla/layers/CompositorD3D11.h"
|
2018-03-29 05:21:47 +03:00
|
|
|
# include "mozilla/widget/WinCompositorWidget.h"
|
2019-05-10 01:10:35 +03:00
|
|
|
# include "mozilla/WindowsVersion.h"
|
2013-05-03 21:34:29 +04:00
|
|
|
#endif
|
2013-09-10 23:56:49 +04:00
|
|
|
#include "GeckoProfiler.h"
|
2013-06-03 14:14:37 +04:00
|
|
|
#include "mozilla/ipc/ProtocolTypes.h"
|
2016-08-23 07:09:32 +03:00
|
|
|
#include "mozilla/Unused.h"
|
2014-05-05 19:38:00 +04:00
|
|
|
#include "mozilla/Hal.h"
|
|
|
|
#include "mozilla/HalTypes.h"
|
2014-07-04 22:04:11 +04:00
|
|
|
#include "mozilla/StaticPtr.h"
|
2016-07-05 22:41:21 +03:00
|
|
|
#include "mozilla/Telemetry.h"
|
2017-10-04 01:11:18 +03:00
|
|
|
#ifdef MOZ_GECKO_PROFILER
|
|
|
|
# include "ProfilerMarkerPayload.h"
|
|
|
|
#endif
|
2014-10-22 02:40:54 +04:00
|
|
|
#include "mozilla/VsyncDispatcher.h"
|
2016-07-18 11:54:02 +03:00
|
|
|
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
|
2017-10-04 01:11:18 +03:00
|
|
|
# include "VsyncSource.h"
|
2016-07-18 11:54:02 +03:00
|
|
|
#endif
|
2016-07-01 11:15:16 +03:00
|
|
|
#include "mozilla/widget/CompositorWidget.h"
|
|
|
|
#ifdef MOZ_WIDGET_SUPPORTS_OOP_COMPOSITING
|
|
|
|
# include "mozilla/widget/CompositorWidgetParent.h"
|
|
|
|
#endif
|
2017-06-24 00:23:12 +03:00
|
|
|
#ifdef XP_WIN
|
|
|
|
# include "mozilla/gfx/DeviceManagerDx.h"
|
|
|
|
#endif
|
2012-07-13 23:38:09 +04:00
|
|
|
|
2015-08-03 09:11:00 +03:00
|
|
|
#include "LayerScope.h"
|
|
|
|
|
2014-05-22 14:11:45 +04:00
|
|
|
namespace mozilla {
|
2015-09-18 00:23:13 +03:00
|
|
|
|
2014-05-22 14:11:45 +04:00
|
|
|
namespace layers {
|
|
|
|
|
2012-07-18 03:59:45 +04:00
|
|
|
using namespace mozilla::ipc;
|
2013-09-27 04:37:19 +04:00
|
|
|
using namespace mozilla::gfx;
|
2012-03-13 00:32:02 +04:00
|
|
|
|
2015-04-01 11:40:35 +03:00
|
|
|
using base::ProcessId;
|
2015-02-11 23:01:26 +03:00
|
|
|
using base::Thread;
|
|
|
|
|
2019-01-07 06:14:28 +03:00
|
|
|
using mozilla::Telemetry::LABELS_CONTENT_FRAME_TIME_REASON;
|
|
|
|
|
2018-09-11 17:50:30 +03:00
|
|
|
/// Equivalent to asserting CompositorThreadHolder::IsInCompositorThread with
|
|
|
|
/// the addition that it doesn't assert if the compositor thread holder is
|
|
|
|
/// already gone during late shutdown.
|
|
|
|
static void AssertIsInCompositorThread() {
|
|
|
|
MOZ_RELEASE_ASSERT(!CompositorThread() ||
|
|
|
|
CompositorThreadHolder::IsInCompositorThread());
|
|
|
|
}
|
|
|
|
|
2017-06-14 18:40:00 +03:00
|
|
|
CompositorBridgeParentBase::CompositorBridgeParentBase(
|
|
|
|
CompositorManagerParent* aManager)
|
|
|
|
: mCanSend(true), mCompositorManager(aManager) {}
|
|
|
|
|
|
|
|
CompositorBridgeParentBase::~CompositorBridgeParentBase() {}
|
|
|
|
|
2016-08-26 00:08:52 +03:00
|
|
|
ProcessId CompositorBridgeParentBase::GetChildProcessId() { return OtherPid(); }
|
|
|
|
|
|
|
|
void CompositorBridgeParentBase::NotifyNotUsed(PTextureParent* aTexture,
|
|
|
|
uint64_t aTransactionId) {
|
|
|
|
RefPtr<TextureHost> texture = TextureHost::AsTextureHost(aTexture);
|
|
|
|
if (!texture) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-10-27 11:02:12 +03:00
|
|
|
if (!(texture->GetFlags() & TextureFlags::RECYCLE)) {
|
2016-08-26 00:08:52 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-10-27 11:02:12 +03:00
|
|
|
uint64_t textureId = TextureHost::GetTextureSerial(aTexture);
|
|
|
|
mPendingAsyncMessage.push_back(OpNotifyNotUsed(textureId, aTransactionId));
|
2016-08-26 00:08:52 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void CompositorBridgeParentBase::SendAsyncMessage(
|
2019-07-10 07:47:53 +03:00
|
|
|
const nsTArray<AsyncParentMessageData>& aMessage) {
|
2016-08-26 00:08:52 +03:00
|
|
|
Unused << SendParentAsyncMessages(aMessage);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CompositorBridgeParentBase::AllocShmem(
|
|
|
|
size_t aSize, ipc::SharedMemory::SharedMemoryType aType,
|
|
|
|
ipc::Shmem* aShmem) {
|
|
|
|
return PCompositorBridgeParent::AllocShmem(aSize, aType, aShmem);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CompositorBridgeParentBase::AllocUnsafeShmem(
|
|
|
|
size_t aSize, ipc::SharedMemory::SharedMemoryType aType,
|
|
|
|
ipc::Shmem* aShmem) {
|
|
|
|
return PCompositorBridgeParent::AllocUnsafeShmem(aSize, aType, aShmem);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CompositorBridgeParentBase::DeallocShmem(ipc::Shmem& aShmem) {
|
|
|
|
PCompositorBridgeParent::DeallocShmem(aShmem);
|
|
|
|
}
|
|
|
|
|
2018-04-23 21:24:36 +03:00
|
|
|
static inline MessageLoop* CompositorLoop() {
|
|
|
|
return CompositorThreadHolder::Loop();
|
|
|
|
}
|
|
|
|
|
2016-10-24 22:12:55 +03:00
|
|
|
base::ProcessId CompositorBridgeParentBase::RemotePid() { return OtherPid(); }
|
|
|
|
|
|
|
|
bool CompositorBridgeParentBase::StartSharingMetrics(
|
|
|
|
ipc::SharedMemoryBasic::Handle aHandle,
|
|
|
|
CrossProcessMutexHandle aMutexHandle, LayersId aLayersId,
|
|
|
|
uint32_t aApzcId) {
|
2018-04-23 21:24:36 +03:00
|
|
|
if (!CompositorThreadHolder::IsInCompositorThread()) {
|
|
|
|
MOZ_ASSERT(CompositorLoop());
|
|
|
|
CompositorLoop()->PostTask(
|
|
|
|
NewRunnableMethod<ipc::SharedMemoryBasic::Handle,
|
|
|
|
CrossProcessMutexHandle, LayersId, uint32_t>(
|
|
|
|
"layers::CompositorBridgeParent::StartSharingMetrics", this,
|
|
|
|
&CompositorBridgeParentBase::StartSharingMetrics, aHandle,
|
|
|
|
aMutexHandle, aLayersId, aApzcId));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
|
2017-06-14 18:40:00 +03:00
|
|
|
if (!mCanSend) {
|
|
|
|
return false;
|
|
|
|
}
|
2016-10-24 22:12:55 +03:00
|
|
|
return PCompositorBridgeParent::SendSharedCompositorFrameMetrics(
|
|
|
|
aHandle, aMutexHandle, aLayersId, aApzcId);
|
|
|
|
}
|
|
|
|
|
2018-11-01 23:15:46 +03:00
|
|
|
bool CompositorBridgeParentBase::StopSharingMetrics(
|
|
|
|
ScrollableLayerGuid::ViewID aScrollId, uint32_t aApzcId) {
|
2018-04-23 21:24:36 +03:00
|
|
|
if (!CompositorThreadHolder::IsInCompositorThread()) {
|
|
|
|
MOZ_ASSERT(CompositorLoop());
|
|
|
|
CompositorLoop()->PostTask(
|
2018-11-01 23:15:46 +03:00
|
|
|
NewRunnableMethod<ScrollableLayerGuid::ViewID, uint32_t>(
|
2018-04-23 21:24:36 +03:00
|
|
|
"layers::CompositorBridgeParent::StopSharingMetrics", this,
|
|
|
|
&CompositorBridgeParentBase::StopSharingMetrics, aScrollId,
|
|
|
|
aApzcId));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
|
2017-06-14 18:40:00 +03:00
|
|
|
if (!mCanSend) {
|
|
|
|
return false;
|
|
|
|
}
|
2016-10-24 22:12:55 +03:00
|
|
|
return PCompositorBridgeParent::SendReleaseSharedCompositorFrameMetrics(
|
|
|
|
aScrollId, aApzcId);
|
|
|
|
}
|
|
|
|
|
2016-03-22 21:08:38 +03:00
|
|
|
CompositorBridgeParent::LayerTreeState::LayerTreeState()
|
2016-07-31 22:39:00 +03:00
|
|
|
: mApzcTreeManagerParent(nullptr),
|
|
|
|
mParent(nullptr),
|
2013-12-09 05:40:58 +04:00
|
|
|
mLayerManager(nullptr),
|
2019-03-05 04:37:37 +03:00
|
|
|
mContentCompositorBridgeParent(nullptr),
|
2014-05-29 01:42:14 +04:00
|
|
|
mLayerTree(nullptr),
|
2015-01-29 22:41:55 +03:00
|
|
|
mUpdatedPluginDataAvailable(false) {}
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2016-03-22 21:08:38 +03:00
|
|
|
CompositorBridgeParent::LayerTreeState::~LayerTreeState() {
|
2015-01-29 20:57:55 +03:00
|
|
|
if (mController) {
|
|
|
|
mController->Destroy();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-02 20:38:31 +03:00
|
|
|
typedef std::map<LayersId, CompositorBridgeParent::LayerTreeState> LayerTreeMap;
|
2016-11-18 21:12:25 +03:00
|
|
|
LayerTreeMap sIndirectLayerTrees;
|
|
|
|
StaticAutoPtr<mozilla::Monitor> sIndirectLayerTreesLock;
|
2015-01-13 21:26:26 +03:00
|
|
|
|
|
|
|
static void EnsureLayerTreeMapReady() {
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
if (!sIndirectLayerTreesLock) {
|
|
|
|
sIndirectLayerTreesLock = new Monitor("IndirectLayerTree");
|
|
|
|
mozilla::ClearOnShutdown(&sIndirectLayerTreesLock);
|
|
|
|
}
|
|
|
|
}
|
2013-07-24 01:53:22 +04:00
|
|
|
|
2016-02-29 09:53:12 +03:00
|
|
|
template <typename Lambda>
|
2016-03-22 21:08:38 +03:00
|
|
|
inline void CompositorBridgeParent::ForEachIndirectLayerTree(
|
|
|
|
const Lambda& aCallback) {
|
2016-02-29 09:53:12 +03:00
|
|
|
sIndirectLayerTreesLock->AssertCurrentThreadOwns();
|
|
|
|
for (auto it = sIndirectLayerTrees.begin(); it != sIndirectLayerTrees.end();
|
|
|
|
it++) {
|
|
|
|
LayerTreeState* state = &it->second;
|
|
|
|
if (state->mParent == this) {
|
|
|
|
aCallback(state, it->first);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-04 22:04:11 +04:00
|
|
|
/**
|
|
|
|
* A global map referencing each compositor by ID.
|
|
|
|
*
|
|
|
|
* This map is used by the ImageBridge protocol to trigger
|
|
|
|
* compositions without having to keep references to the
|
|
|
|
* compositor
|
|
|
|
*/
|
2019-09-02 20:38:31 +03:00
|
|
|
typedef std::map<uint64_t, CompositorBridgeParent*> CompositorMap;
|
2016-05-16 09:38:34 +03:00
|
|
|
static StaticAutoPtr<CompositorMap> sCompositorMap;
|
2014-07-04 22:04:11 +04:00
|
|
|
|
2016-07-18 07:24:27 +03:00
|
|
|
void CompositorBridgeParent::Setup() {
|
2016-05-16 09:38:34 +03:00
|
|
|
EnsureLayerTreeMapReady();
|
|
|
|
|
2014-07-04 22:04:11 +04:00
|
|
|
MOZ_ASSERT(!sCompositorMap);
|
|
|
|
sCompositorMap = new CompositorMap;
|
2014-07-05 05:24:32 +04:00
|
|
|
}
|
2014-07-03 22:53:27 +04:00
|
|
|
|
2016-05-16 09:38:34 +03:00
|
|
|
void CompositorBridgeParent::FinishShutdown() {
|
2018-09-11 17:50:48 +03:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
|
|
|
|
if (sCompositorMap) {
|
|
|
|
MOZ_ASSERT(sCompositorMap->empty());
|
|
|
|
sCompositorMap = nullptr;
|
|
|
|
}
|
|
|
|
|
2016-05-16 09:38:34 +03:00
|
|
|
// TODO: this should be empty by now...
|
|
|
|
sIndirectLayerTrees.clear();
|
2014-07-04 22:04:11 +04:00
|
|
|
}
|
|
|
|
|
2015-08-21 03:57:42 +03:00
|
|
|
#ifdef COMPOSITOR_PERFORMANCE_WARNING
|
2015-04-30 21:35:13 +03:00
|
|
|
static int32_t CalculateCompositionFrameRate() {
|
2015-08-21 03:57:42 +03:00
|
|
|
// Used when layout.frame_rate is -1. Needs to be kept in sync with
|
|
|
|
// DEFAULT_FRAME_RATE in nsRefreshDriver.cpp.
|
|
|
|
// TODO: This should actually return the vsync rate.
|
|
|
|
const int32_t defaultFrameRate = 60;
|
2019-06-27 07:48:58 +03:00
|
|
|
int32_t compositionFrameRatePref =
|
|
|
|
StaticPrefs::layers_offmainthreadcomposition_frame_rate();
|
2015-04-30 21:35:13 +03:00
|
|
|
if (compositionFrameRatePref < 0) {
|
|
|
|
// Use the same frame rate for composition as for layout.
|
2019-06-27 09:28:25 +03:00
|
|
|
int32_t layoutFrameRatePref = StaticPrefs::layout_frame_rate();
|
2015-04-30 21:35:13 +03:00
|
|
|
if (layoutFrameRatePref < 0) {
|
|
|
|
// TODO: The main thread frame scheduling code consults the actual
|
|
|
|
// monitor refresh rate in this case. We should do the same.
|
2015-08-21 03:57:42 +03:00
|
|
|
return defaultFrameRate;
|
2015-04-30 21:35:13 +03:00
|
|
|
}
|
|
|
|
return layoutFrameRatePref;
|
|
|
|
}
|
|
|
|
return compositionFrameRatePref;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2018-04-13 16:01:28 +03:00
|
|
|
CompositorBridgeParent::CompositorBridgeParent(
|
|
|
|
CompositorManagerParent* aManager, CSSToLayoutDeviceScale aScale,
|
|
|
|
const TimeDuration& aVsyncRate, const CompositorOptions& aOptions,
|
|
|
|
bool aUseExternalSurfaceSize, const gfx::IntSize& aSurfaceSize)
|
2017-06-14 18:40:00 +03:00
|
|
|
: CompositorBridgeParentBase(aManager),
|
|
|
|
mWidget(nullptr),
|
2016-07-18 07:24:27 +03:00
|
|
|
mScale(aScale),
|
2016-07-26 11:57:11 +03:00
|
|
|
mVsyncRate(aVsyncRate),
|
2018-04-20 22:13:06 +03:00
|
|
|
mPendingTransaction{0},
|
2012-02-08 21:08:03 +04:00
|
|
|
mPaused(false),
|
2019-07-31 21:28:38 +03:00
|
|
|
mHaveCompositionRecorder(false),
|
2013-04-30 07:16:04 +04:00
|
|
|
mUseExternalSurfaceSize(aUseExternalSurfaceSize),
|
2016-06-28 03:05:34 +03:00
|
|
|
mEGLSurfaceSize(aSurfaceSize),
|
2017-01-13 01:29:41 +03:00
|
|
|
mOptions(aOptions),
|
2012-05-10 06:32:54 +04:00
|
|
|
mPauseCompositionMonitor("PauseCompositionMonitor"),
|
2012-05-29 21:49:03 +04:00
|
|
|
mResumeCompositionMonitor("ResumeCompositionMonitor"),
|
2018-06-16 17:42:33 +03:00
|
|
|
mCompositorBridgeID(0),
|
2018-04-13 16:01:28 +03:00
|
|
|
mRootLayerTreeID{0},
|
2012-11-22 06:40:57 +04:00
|
|
|
mOverrideComposeReadiness(false),
|
2012-12-23 08:54:23 +04:00
|
|
|
mForceCompositionTask(nullptr),
|
2015-04-30 21:35:13 +03:00
|
|
|
mCompositorScheduler(nullptr),
|
2017-02-10 01:30:11 +03:00
|
|
|
mAnimationStorage(nullptr),
|
2016-08-16 18:46:13 +03:00
|
|
|
mPaintTime(TimeDuration::Forever())
|
2015-10-06 22:23:24 +03:00
|
|
|
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
|
2018-04-13 16:01:28 +03:00
|
|
|
,
|
|
|
|
mLastPluginUpdateLayerTreeId{0},
|
2016-01-12 20:05:58 +03:00
|
|
|
mDeferPluginWindows(false),
|
2016-02-04 18:10:55 +03:00
|
|
|
mPluginWindowsHidden(false)
|
2015-10-06 22:23:24 +03:00
|
|
|
#endif
|
2016-07-18 07:24:27 +03:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-07-18 07:24:27 +03:00
|
|
|
void CompositorBridgeParent::InitSameProcess(widget::CompositorWidget* aWidget,
|
2018-03-25 02:06:01 +03:00
|
|
|
const LayersId& aLayerTreeId) {
|
2018-07-24 00:46:47 +03:00
|
|
|
MOZ_ASSERT(XRE_IsParentProcess() || recordreplay::IsRecordingOrReplaying());
|
2017-06-14 18:40:00 +03:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
|
2016-07-18 07:24:27 +03:00
|
|
|
mWidget = aWidget;
|
2016-07-18 07:24:27 +03:00
|
|
|
mRootLayerTreeID = aLayerTreeId;
|
2016-07-18 07:24:27 +03:00
|
|
|
|
|
|
|
Initialize();
|
|
|
|
}
|
|
|
|
|
2018-03-25 02:06:01 +03:00
|
|
|
mozilla::ipc::IPCResult CompositorBridgeParent::RecvInitialize(
|
|
|
|
const LayersId& aRootLayerTreeId) {
|
2018-03-16 23:28:18 +03:00
|
|
|
MOZ_ASSERT(XRE_IsGPUProcess());
|
|
|
|
|
2016-07-18 07:24:28 +03:00
|
|
|
mRootLayerTreeID = aRootLayerTreeId;
|
|
|
|
|
|
|
|
Initialize();
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2016-07-18 07:24:28 +03:00
|
|
|
}
|
|
|
|
|
2016-07-18 07:24:27 +03:00
|
|
|
void CompositorBridgeParent::Initialize() {
|
2014-07-04 22:04:11 +04:00
|
|
|
MOZ_ASSERT(CompositorThread(),
|
2016-03-22 21:08:38 +03:00
|
|
|
"The compositor thread must be Initialized before instanciating a "
|
|
|
|
"CompositorBridgeParent.");
|
2016-04-13 00:04:50 +03:00
|
|
|
|
2018-03-16 23:28:18 +03:00
|
|
|
if (mOptions.UseAPZ()) {
|
|
|
|
MOZ_ASSERT(!mApzcTreeManager);
|
|
|
|
MOZ_ASSERT(!mApzSampler);
|
2018-03-29 01:36:42 +03:00
|
|
|
MOZ_ASSERT(!mApzUpdater);
|
2018-03-16 23:28:18 +03:00
|
|
|
mApzcTreeManager = new APZCTreeManager(mRootLayerTreeID);
|
2018-04-19 17:10:00 +03:00
|
|
|
mApzSampler = new APZSampler(mApzcTreeManager, mOptions.UseWebRender());
|
2018-04-19 17:09:59 +03:00
|
|
|
mApzUpdater = new APZUpdater(mApzcTreeManager, mOptions.UseWebRender());
|
2018-03-16 23:28:18 +03:00
|
|
|
}
|
|
|
|
|
2018-04-26 00:35:31 +03:00
|
|
|
mPaused = mOptions.InitiallyPaused();
|
|
|
|
|
2017-06-20 11:17:20 +03:00
|
|
|
mCompositorBridgeID = 0;
|
Bug 825928: Land layers refactoring. r=jrmuizel,bas,nical,mattwoodrow,roc,nrc,benwa,bjacob,jgilbert,kchen CLOSED TREE
Please contact Bas Schouten <bschouten@mozilla.com>, Nicolas Silva <nsilva@mozilla.com> or Nicholas Cameron <ncameron@mozilla.com> with general questions. Below is a rough list of authors to contact with specific questions.
Authors:
gfx/layers/Compositor.* gfx/layers/Effects.h - Compositor Interface - bas,nrc,nical
gfx/layers/d3d* - D3D9/D3D10 - bas
gfx/layers/ThebesLayer* - ThebesLayers - nrc,bas
gfx/layers/composite/* - CompositeLayers - nrc,nical
gfx/layers/client/* - Client - nrc,nical,bas
gfx/layers/*Image* - nical
gfx/layers/ipc ipc - IPC - nical
gfx/layers/opengl - CompositorOGL - nrc,nical
gfx/2d - bas,nrc
gfx/gl - GLContext - bjacob
dom/* layout/* - DOM - mattwoodrow
2013-04-10 13:20:52 +04:00
|
|
|
// FIXME: This holds on the the fact that right now the only thing that
|
|
|
|
// can destroy this instance is initialized on the compositor thread after
|
2012-07-13 23:38:09 +04:00
|
|
|
// this task has been processed.
|
2015-01-27 23:52:44 +03:00
|
|
|
MOZ_ASSERT(CompositorLoop());
|
2017-10-27 23:39:28 +03:00
|
|
|
CompositorLoop()->PostTask(NewRunnableFunction(
|
2017-06-20 11:17:20 +03:00
|
|
|
"AddCompositorRunnable", &AddCompositor, this, &mCompositorBridgeID));
|
2012-07-18 03:59:45 +04:00
|
|
|
|
2015-01-13 21:26:26 +03:00
|
|
|
{ // scope lock
|
|
|
|
MonitorAutoLock lock(*sIndirectLayerTreesLock);
|
|
|
|
sIndirectLayerTrees[mRootLayerTreeID].mParent = this;
|
|
|
|
}
|
2013-07-30 22:03:43 +04:00
|
|
|
|
2016-07-18 07:24:27 +03:00
|
|
|
LayerScope::SetPixelScale(mScale.scale);
|
2016-07-19 21:56:07 +03:00
|
|
|
|
2017-01-24 16:03:08 +03:00
|
|
|
if (!mOptions.UseWebRender()) {
|
2016-12-04 11:40:52 +03:00
|
|
|
mCompositorScheduler = new CompositorVsyncScheduler(this, mWidget);
|
|
|
|
}
|
2011-12-16 00:07:19 +04:00
|
|
|
}
|
|
|
|
|
2016-03-22 21:08:38 +03:00
|
|
|
LayersId CompositorBridgeParent::RootLayerTreeId() {
|
2018-03-25 02:06:01 +03:00
|
|
|
MOZ_ASSERT(mRootLayerTreeID.IsValid());
|
2013-07-30 22:03:43 +04:00
|
|
|
return mRootLayerTreeID;
|
|
|
|
}
|
|
|
|
|
2016-03-22 21:08:38 +03:00
|
|
|
CompositorBridgeParent::~CompositorBridgeParent() {
|
2019-07-10 07:47:53 +03:00
|
|
|
nsTArray<PTextureParent*> textures;
|
2016-04-13 00:04:50 +03:00
|
|
|
ManagedPTextureParent(textures);
|
|
|
|
// We expect all textures to be destroyed by now.
|
|
|
|
MOZ_DIAGNOSTIC_ASSERT(textures.Length() == 0);
|
|
|
|
for (unsigned int i = 0; i < textures.Length(); ++i) {
|
|
|
|
RefPtr<TextureHost> tex = TextureHost::AsTextureHost(textures[i]);
|
|
|
|
tex->DeallocateDeviceData();
|
|
|
|
}
|
2011-12-16 00:07:19 +04:00
|
|
|
}
|
|
|
|
|
2018-07-31 19:21:49 +03:00
|
|
|
void CompositorBridgeParent::ForceIsFirstPaint() {
|
2018-10-19 16:48:04 +03:00
|
|
|
if (mWrBridge) {
|
|
|
|
mWrBridge->ForceIsFirstPaint();
|
|
|
|
} else {
|
|
|
|
mCompositionManager->ForceIsFirstPaint();
|
|
|
|
}
|
2011-12-16 00:07:19 +04:00
|
|
|
}
|
|
|
|
|
2016-06-21 18:31:21 +03:00
|
|
|
void CompositorBridgeParent::StopAndClearResources() {
|
|
|
|
if (mForceCompositionTask) {
|
|
|
|
mForceCompositionTask->Cancel();
|
|
|
|
mForceCompositionTask = nullptr;
|
|
|
|
}
|
|
|
|
|
2012-03-29 19:26:58 +04:00
|
|
|
mPaused = true;
|
2012-03-30 23:43:11 +04:00
|
|
|
|
2018-04-16 21:21:04 +03:00
|
|
|
// We need to clear the APZ tree before we destroy the WebRender API below,
|
|
|
|
// because in the case of async scene building that will shut down the updater
|
|
|
|
// thread and we need to run the task before that happens.
|
|
|
|
MOZ_ASSERT((mApzSampler != nullptr) == (mApzcTreeManager != nullptr));
|
|
|
|
MOZ_ASSERT((mApzUpdater != nullptr) == (mApzcTreeManager != nullptr));
|
|
|
|
if (mApzUpdater) {
|
2018-11-30 21:19:17 +03:00
|
|
|
mApzSampler->Destroy();
|
2018-04-16 21:21:04 +03:00
|
|
|
mApzSampler = nullptr;
|
|
|
|
mApzUpdater->ClearTree(mRootLayerTreeID);
|
|
|
|
mApzUpdater = nullptr;
|
|
|
|
mApzcTreeManager = nullptr;
|
|
|
|
}
|
|
|
|
|
2016-03-22 21:08:38 +03:00
|
|
|
// Ensure that the layer manager is destroyed before CompositorBridgeChild.
|
2013-04-11 14:14:29 +04:00
|
|
|
if (mLayerManager) {
|
2015-01-13 21:26:26 +03:00
|
|
|
MonitorAutoLock lock(*sIndirectLayerTreesLock);
|
2018-03-25 02:06:01 +03:00
|
|
|
ForEachIndirectLayerTree([this](LayerTreeState* lts, LayersId) -> void {
|
2016-02-29 09:53:12 +03:00
|
|
|
mLayerManager->ClearCachedResources(lts->mRoot);
|
|
|
|
lts->mLayerManager = nullptr;
|
|
|
|
lts->mParent = nullptr;
|
|
|
|
});
|
2013-04-11 14:14:29 +04:00
|
|
|
mLayerManager->Destroy();
|
2013-04-28 10:46:30 +04:00
|
|
|
mLayerManager = nullptr;
|
|
|
|
mCompositionManager = nullptr;
|
2013-04-11 14:14:29 +04:00
|
|
|
}
|
2012-03-30 23:43:11 +04:00
|
|
|
|
2017-01-17 18:17:38 +03:00
|
|
|
if (mWrBridge) {
|
2018-06-02 19:15:15 +03:00
|
|
|
// Ensure we are not holding the sIndirectLayerTreesLock when destroying
|
|
|
|
// the WebRenderBridgeParent instances because it may block on WR.
|
|
|
|
std::vector<RefPtr<WebRenderBridgeParent>> indirectBridgeParents;
|
2018-05-11 23:36:22 +03:00
|
|
|
{ // scope lock
|
|
|
|
MonitorAutoLock lock(*sIndirectLayerTreesLock);
|
2018-06-02 19:15:15 +03:00
|
|
|
ForEachIndirectLayerTree([&](LayerTreeState* lts, LayersId) -> void {
|
2018-05-11 23:36:22 +03:00
|
|
|
if (lts->mWrBridge) {
|
2018-06-02 19:15:15 +03:00
|
|
|
indirectBridgeParents.emplace_back(lts->mWrBridge.forget());
|
2018-05-11 23:36:22 +03:00
|
|
|
}
|
|
|
|
lts->mParent = nullptr;
|
|
|
|
});
|
|
|
|
}
|
2018-06-02 19:15:15 +03:00
|
|
|
for (const RefPtr<WebRenderBridgeParent>& bridge : indirectBridgeParents) {
|
|
|
|
bridge->Destroy();
|
|
|
|
}
|
|
|
|
indirectBridgeParents.clear();
|
2018-05-11 23:36:22 +03:00
|
|
|
|
2019-03-22 21:28:42 +03:00
|
|
|
RefPtr<wr::WebRenderAPI> api =
|
|
|
|
mWrBridge->GetWebRenderAPI(wr::RenderRoot::Default);
|
2018-05-11 23:36:22 +03:00
|
|
|
// Ensure we are not holding the sIndirectLayerTreesLock here because we
|
|
|
|
// are going to block on WR threads in order to shut it down properly.
|
2017-01-17 18:17:38 +03:00
|
|
|
mWrBridge->Destroy();
|
|
|
|
mWrBridge = nullptr;
|
2018-10-12 09:47:29 +03:00
|
|
|
|
|
|
|
if (api) {
|
|
|
|
// Make extra sure we are done cleaning WebRender up before continuing.
|
|
|
|
// After that we wont have a way to talk to a lot of the webrender parts.
|
|
|
|
api->FlushSceneBuilder();
|
|
|
|
api = nullptr;
|
|
|
|
}
|
|
|
|
|
2017-08-15 04:41:41 +03:00
|
|
|
if (mAsyncImageManager) {
|
|
|
|
mAsyncImageManager->Destroy();
|
|
|
|
// WebRenderAPI should be already destructed
|
|
|
|
mAsyncImageManager = nullptr;
|
|
|
|
}
|
2016-11-25 04:18:27 +03:00
|
|
|
}
|
|
|
|
|
2015-11-24 04:50:51 +03:00
|
|
|
if (mCompositor) {
|
2016-04-11 19:18:24 +03:00
|
|
|
mCompositor->Destroy();
|
|
|
|
mCompositor = nullptr;
|
2015-11-24 04:50:51 +03:00
|
|
|
}
|
2016-06-29 00:54:20 +03:00
|
|
|
|
2016-07-19 21:56:07 +03:00
|
|
|
// This must be destroyed now since it accesses the widget.
|
|
|
|
if (mCompositorScheduler) {
|
|
|
|
mCompositorScheduler->Destroy();
|
|
|
|
mCompositorScheduler = nullptr;
|
|
|
|
}
|
|
|
|
|
2016-06-29 00:54:20 +03:00
|
|
|
// After this point, it is no longer legal to access the widget.
|
2016-07-01 11:15:16 +03:00
|
|
|
mWidget = nullptr;
|
2017-05-08 21:48:23 +03:00
|
|
|
|
|
|
|
// Clear mAnimationStorage here to ensure that the compositor thread
|
|
|
|
// still exists when we destroy it.
|
|
|
|
mAnimationStorage = nullptr;
|
2016-06-21 18:31:21 +03:00
|
|
|
}
|
2015-11-24 04:50:51 +03:00
|
|
|
|
2016-06-21 18:31:21 +03:00
|
|
|
mozilla::ipc::IPCResult CompositorBridgeParent::RecvWillClose() {
|
|
|
|
StopAndClearResources();
|
2018-04-23 21:24:36 +03:00
|
|
|
// Once we get the WillClose message, the client side is going to go away
|
|
|
|
// soon and we can't be guaranteed that sending messages will work.
|
|
|
|
mCanSend = false;
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2012-03-30 23:43:11 +04:00
|
|
|
}
|
|
|
|
|
2016-03-22 21:08:38 +03:00
|
|
|
void CompositorBridgeParent::DeferredDestroy() {
|
2014-07-04 22:04:11 +04:00
|
|
|
MOZ_ASSERT(!NS_IsMainThread());
|
2015-11-24 04:50:51 +03:00
|
|
|
mSelfRef = nullptr;
|
2011-12-17 04:21:51 +04:00
|
|
|
}
|
|
|
|
|
2016-03-22 21:08:38 +03:00
|
|
|
mozilla::ipc::IPCResult CompositorBridgeParent::RecvPause() {
|
2012-03-29 02:00:10 +04:00
|
|
|
PauseComposition();
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2012-03-29 02:00:10 +04:00
|
|
|
}
|
|
|
|
|
2019-09-04 22:58:51 +03:00
|
|
|
mozilla::ipc::IPCResult CompositorBridgeParent::RecvRequestFxrOutput() {
|
|
|
|
#ifdef XP_WIN
|
|
|
|
// Continue forwarding the request to the Widget + SwapChain
|
|
|
|
mWidget->AsWindows()->RequestFxrOutput();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return IPC_OK();
|
|
|
|
}
|
|
|
|
|
2016-03-22 21:08:38 +03:00
|
|
|
mozilla::ipc::IPCResult CompositorBridgeParent::RecvResume() {
|
2012-03-29 02:00:10 +04:00
|
|
|
ResumeComposition();
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2012-03-29 02:00:10 +04:00
|
|
|
}
|
|
|
|
|
2019-07-16 04:28:32 +03:00
|
|
|
mozilla::ipc::IPCResult CompositorBridgeParent::RecvResumeAsync() {
|
|
|
|
ResumeComposition();
|
|
|
|
return IPC_OK();
|
|
|
|
}
|
|
|
|
|
2016-03-22 21:08:38 +03:00
|
|
|
mozilla::ipc::IPCResult CompositorBridgeParent::RecvMakeSnapshot(
|
|
|
|
const SurfaceDescriptor& aInSnapshot, const gfx::IntRect& aRect) {
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<DrawTarget> target =
|
|
|
|
GetDrawTargetForDescriptor(aInSnapshot, gfx::BackendType::CAIRO);
|
2016-01-06 15:56:00 +03:00
|
|
|
MOZ_ASSERT(target);
|
|
|
|
if (!target) {
|
|
|
|
// We kill the content process rather than have it continue with an invalid
|
|
|
|
// snapshot, that may be too harsh and we could decide to return some sort
|
|
|
|
// of error to the child process and let it deal with it...
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_FAIL_NO_REASON(this);
|
2016-01-06 15:56:00 +03:00
|
|
|
}
|
2014-05-28 05:21:32 +04:00
|
|
|
ForceComposeToTarget(target, &aRect);
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2012-10-04 11:05:24 +04:00
|
|
|
}
|
|
|
|
|
2017-05-15 20:03:32 +03:00
|
|
|
mozilla::ipc::IPCResult
|
|
|
|
CompositorBridgeParent::RecvWaitOnTransactionProcessed() {
|
|
|
|
return IPC_OK();
|
|
|
|
}
|
|
|
|
|
2016-03-22 21:08:38 +03:00
|
|
|
mozilla::ipc::IPCResult CompositorBridgeParent::RecvFlushRendering() {
|
2018-04-12 06:18:50 +03:00
|
|
|
if (mWrBridge) {
|
2018-02-02 18:48:25 +03:00
|
|
|
mWrBridge->FlushRendering();
|
2017-06-02 02:07:59 +03:00
|
|
|
return IPC_OK();
|
|
|
|
}
|
|
|
|
|
2017-04-10 09:58:29 +03:00
|
|
|
if (mCompositorScheduler->NeedsComposite()) {
|
2014-03-10 08:47:12 +04:00
|
|
|
CancelCurrentCompositeTask();
|
2014-02-11 08:58:01 +04:00
|
|
|
ForceComposeToTarget(nullptr);
|
2013-06-18 11:58:43 +04:00
|
|
|
}
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2013-06-18 11:58:43 +04:00
|
|
|
}
|
|
|
|
|
2017-05-05 11:10:48 +03:00
|
|
|
mozilla::ipc::IPCResult CompositorBridgeParent::RecvFlushRenderingAsync() {
|
2018-04-12 06:18:50 +03:00
|
|
|
if (mWrBridge) {
|
2018-07-28 11:47:08 +03:00
|
|
|
mWrBridge->FlushRendering(false);
|
2017-06-02 02:07:59 +03:00
|
|
|
return IPC_OK();
|
|
|
|
}
|
|
|
|
|
2017-05-05 11:10:48 +03:00
|
|
|
return RecvFlushRendering();
|
|
|
|
}
|
|
|
|
|
2016-03-22 21:08:38 +03:00
|
|
|
mozilla::ipc::IPCResult CompositorBridgeParent::RecvForcePresent() {
|
2018-04-11 05:34:25 +03:00
|
|
|
if (mWrBridge) {
|
2018-10-15 14:28:01 +03:00
|
|
|
mWrBridge->ScheduleForcedGenerateFrame();
|
2018-04-11 05:34:25 +03:00
|
|
|
}
|
2016-02-25 00:24:26 +03:00
|
|
|
// During the shutdown sequence mLayerManager may be null
|
2016-02-24 06:50:09 +03:00
|
|
|
if (mLayerManager) {
|
|
|
|
mLayerManager->ForcePresent();
|
|
|
|
}
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2016-02-24 06:50:09 +03:00
|
|
|
}
|
|
|
|
|
2016-03-22 21:08:38 +03:00
|
|
|
mozilla::ipc::IPCResult CompositorBridgeParent::RecvNotifyRegionInvalidated(
|
|
|
|
const nsIntRegion& aRegion) {
|
2013-11-21 23:25:16 +04:00
|
|
|
if (mLayerManager) {
|
|
|
|
mLayerManager->AddInvalidRegion(aRegion);
|
|
|
|
}
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2013-11-21 23:25:16 +04:00
|
|
|
}
|
|
|
|
|
2016-03-22 21:08:38 +03:00
|
|
|
void CompositorBridgeParent::Invalidate() {
|
2018-05-01 23:33:43 +03:00
|
|
|
if (mLayerManager) {
|
|
|
|
mLayerManager->InvalidateAll();
|
2015-06-11 18:20:04 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-22 21:08:38 +03:00
|
|
|
mozilla::ipc::IPCResult CompositorBridgeParent::RecvStartFrameTimeRecording(
|
|
|
|
const int32_t& aBufferSize, uint32_t* aOutStartIndex) {
|
2013-11-27 11:32:19 +04:00
|
|
|
if (mLayerManager) {
|
|
|
|
*aOutStartIndex = mLayerManager->StartFrameTimeRecording(aBufferSize);
|
2018-09-08 21:41:34 +03:00
|
|
|
} else if (mWrBridge) {
|
|
|
|
*aOutStartIndex = mWrBridge->StartFrameTimeRecording(aBufferSize);
|
2013-11-27 11:32:19 +04:00
|
|
|
} else {
|
|
|
|
*aOutStartIndex = 0;
|
|
|
|
}
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2013-11-27 11:32:19 +04:00
|
|
|
}
|
|
|
|
|
2016-03-22 21:08:38 +03:00
|
|
|
mozilla::ipc::IPCResult CompositorBridgeParent::RecvStopFrameTimeRecording(
|
2019-07-10 07:47:53 +03:00
|
|
|
const uint32_t& aStartIndex, nsTArray<float>* intervals) {
|
2013-11-27 11:32:19 +04:00
|
|
|
if (mLayerManager) {
|
|
|
|
mLayerManager->StopFrameTimeRecording(aStartIndex, *intervals);
|
2018-09-08 21:41:34 +03:00
|
|
|
} else if (mWrBridge) {
|
|
|
|
mWrBridge->StopFrameTimeRecording(aStartIndex, *intervals);
|
2013-11-27 11:32:19 +04:00
|
|
|
}
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2013-11-27 11:32:19 +04:00
|
|
|
}
|
|
|
|
|
2016-03-22 21:08:38 +03:00
|
|
|
void CompositorBridgeParent::ActorDestroy(ActorDestroyReason why) {
|
2017-06-14 18:40:00 +03:00
|
|
|
mCanSend = false;
|
|
|
|
|
2016-06-21 18:31:21 +03:00
|
|
|
StopAndClearResources();
|
2013-04-11 14:14:29 +04:00
|
|
|
|
2017-06-20 11:17:20 +03:00
|
|
|
RemoveCompositor(mCompositorBridgeID);
|
2015-11-24 04:50:51 +03:00
|
|
|
|
|
|
|
mCompositionManager = nullptr;
|
|
|
|
|
2016-06-21 18:31:21 +03:00
|
|
|
{ // scope lock
|
|
|
|
MonitorAutoLock lock(*sIndirectLayerTreesLock);
|
|
|
|
sIndirectLayerTrees.erase(mRootLayerTreeID);
|
|
|
|
}
|
|
|
|
|
2015-11-24 04:50:51 +03:00
|
|
|
// There are chances that the ref count reaches zero on the main thread
|
|
|
|
// shortly after this function returns while some ipdl code still needs to run
|
|
|
|
// on this thread. We must keep the compositor parent alive untill the code
|
|
|
|
// handling message reception is finished on this thread.
|
|
|
|
mSelfRef = this;
|
2017-06-12 22:34:10 +03:00
|
|
|
MessageLoop::current()->PostTask(
|
|
|
|
NewRunnableMethod("layers::CompositorBridgeParent::DeferredDestroy", this,
|
|
|
|
&CompositorBridgeParent::DeferredDestroy));
|
2013-04-11 14:14:29 +04:00
|
|
|
}
|
|
|
|
|
2019-03-22 21:28:42 +03:00
|
|
|
void CompositorBridgeParent::ScheduleRenderOnCompositorThread(
|
2019-04-17 18:12:10 +03:00
|
|
|
const wr::RenderRootSet& aRenderRoots) {
|
2015-01-27 23:52:44 +03:00
|
|
|
MOZ_ASSERT(CompositorLoop());
|
2019-04-17 18:12:10 +03:00
|
|
|
CompositorLoop()->PostTask(NewRunnableMethod<wr::RenderRootSet>(
|
2019-03-22 21:28:42 +03:00
|
|
|
"layers::CompositorBridgeParent::ScheduleComposition", this,
|
2019-04-16 01:34:13 +03:00
|
|
|
&CompositorBridgeParent::ScheduleComposition, aRenderRoots));
|
2012-02-04 06:35:58 +04:00
|
|
|
}
|
|
|
|
|
2016-03-22 21:08:38 +03:00
|
|
|
void CompositorBridgeParent::InvalidateOnCompositorThread() {
|
2015-06-11 18:20:04 +03:00
|
|
|
MOZ_ASSERT(CompositorLoop());
|
2017-06-12 22:34:10 +03:00
|
|
|
CompositorLoop()->PostTask(
|
|
|
|
NewRunnableMethod("layers::CompositorBridgeParent::Invalidate", this,
|
|
|
|
&CompositorBridgeParent::Invalidate));
|
2015-06-11 18:20:04 +03:00
|
|
|
}
|
|
|
|
|
2016-03-22 21:08:38 +03:00
|
|
|
void CompositorBridgeParent::PauseComposition() {
|
2016-05-16 09:40:13 +03:00
|
|
|
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread(),
|
2014-06-06 00:42:13 +04:00
|
|
|
"PauseComposition() can only be called on the compositor thread");
|
2012-05-10 06:32:54 +04:00
|
|
|
|
2012-07-18 03:59:45 +04:00
|
|
|
MonitorAutoLock lock(mPauseCompositionMonitor);
|
2012-05-10 06:32:54 +04:00
|
|
|
|
2012-02-06 22:57:06 +04:00
|
|
|
if (!mPaused) {
|
|
|
|
mPaused = true;
|
2012-02-05 22:33:38 +04:00
|
|
|
|
2018-11-02 12:00:45 +03:00
|
|
|
TimeStamp now = TimeStamp::Now();
|
2018-04-12 06:18:50 +03:00
|
|
|
if (mCompositor) {
|
2017-04-05 17:12:11 +03:00
|
|
|
mCompositor->Pause();
|
2018-12-08 02:28:41 +03:00
|
|
|
DidComposite(VsyncId(), now, now);
|
2018-04-12 06:18:50 +03:00
|
|
|
} else if (mWrBridge) {
|
2017-04-05 17:12:11 +03:00
|
|
|
mWrBridge->Pause();
|
2018-11-02 12:00:45 +03:00
|
|
|
NotifyPipelineRendered(mWrBridge->PipelineId(),
|
2018-12-08 02:28:41 +03:00
|
|
|
mWrBridge->GetCurrentEpoch(), VsyncId(), now, now,
|
|
|
|
now);
|
2017-04-05 17:12:11 +03:00
|
|
|
}
|
2012-02-06 22:57:06 +04:00
|
|
|
}
|
2012-05-10 06:32:54 +04:00
|
|
|
|
|
|
|
// if anyone's waiting to make sure that composition really got paused, tell
|
|
|
|
// them
|
|
|
|
lock.NotifyAll();
|
2012-02-05 22:33:38 +04:00
|
|
|
}
|
|
|
|
|
2016-03-22 21:08:38 +03:00
|
|
|
void CompositorBridgeParent::ResumeComposition() {
|
2016-05-16 09:40:13 +03:00
|
|
|
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread(),
|
2014-06-06 00:42:13 +04:00
|
|
|
"ResumeComposition() can only be called on the compositor thread");
|
2012-05-29 21:49:03 +04:00
|
|
|
|
2012-07-18 03:59:45 +04:00
|
|
|
MonitorAutoLock lock(mResumeCompositionMonitor);
|
2012-05-29 21:49:03 +04:00
|
|
|
|
Bug 1354411 - Rebuild CompositorSessions if WebRender is disabled r=kats
When WebRender creation is failed, WebRender is disabled in gecko. There is a case that WebRenderBridgeParents exist when WebRender is disabled. To handle this, gecko needs to rebuild all CompositorSessions.
There is also a problem related to gfxVars::UseWebRender on compositor thread. If e10s is enabled, but no-gpu process(default on linux and mac), gfxVars::UseWebRender change is soon notified by compositor thread tasks. If WebRender creation failure happens at 2nd WebRender creation, several WebRenderBridgeParents for 1st WebRender could exist. IPC messages from WebRenderLayerManager are normally async, then there is a chance that the WebRenderBridgeParents receive the messages after the gfxVars::UseWebRender change. Further the gfxVars::UseWebRender change in content process could be delayed than WebRenderBridgeParents, then content process does not have a way to stop sending PWebRenderBridge IPC until the change of gfxVars::UseWebRender is received. WebRenderBridgeParent related tasks handle the message, but some tasks are done based on gfxVars::UseWebRender. At this time, gfxVars::UseWebRender returned false on compositor thread, then it cause unexpected result for WebRenderBridgeParent and WebRender. To addres this inconsistent situation, WebRenderBridgeParent related tasks on compositor thread stop to use gfxVars::UseWebRender.
2017-08-04 08:36:41 +03:00
|
|
|
bool resumed =
|
|
|
|
mOptions.UseWebRender() ? mWrBridge->Resume() : mCompositor->Resume();
|
2017-04-05 17:12:11 +03:00
|
|
|
if (!resumed) {
|
2012-02-05 22:33:38 +04:00
|
|
|
#ifdef MOZ_WIDGET_ANDROID
|
2013-01-10 20:21:10 +04:00
|
|
|
// We can't get a surface. This could be because the activity changed
|
|
|
|
// between the time resume was scheduled and now.
|
2016-03-22 21:08:38 +03:00
|
|
|
__android_log_print(
|
|
|
|
ANDROID_LOG_INFO, "CompositorBridgeParent",
|
|
|
|
"Unable to renew compositor surface; remaining in paused state");
|
Bug 825928: Land layers refactoring. r=jrmuizel,bas,nical,mattwoodrow,roc,nrc,benwa,bjacob,jgilbert,kchen CLOSED TREE
Please contact Bas Schouten <bschouten@mozilla.com>, Nicolas Silva <nsilva@mozilla.com> or Nicholas Cameron <ncameron@mozilla.com> with general questions. Below is a rough list of authors to contact with specific questions.
Authors:
gfx/layers/Compositor.* gfx/layers/Effects.h - Compositor Interface - bas,nrc,nical
gfx/layers/d3d* - D3D9/D3D10 - bas
gfx/layers/ThebesLayer* - ThebesLayers - nrc,bas
gfx/layers/composite/* - CompositeLayers - nrc,nical
gfx/layers/client/* - Client - nrc,nical,bas
gfx/layers/*Image* - nical
gfx/layers/ipc ipc - IPC - nical
gfx/layers/opengl - CompositorOGL - nrc,nical
gfx/2d - bas,nrc
gfx/gl - GLContext - bjacob
dom/* layout/* - DOM - mattwoodrow
2013-04-10 13:20:52 +04:00
|
|
|
#endif
|
2013-01-10 20:21:10 +04:00
|
|
|
lock.NotifyAll();
|
|
|
|
return;
|
|
|
|
}
|
2012-05-29 21:49:03 +04:00
|
|
|
|
2013-01-10 20:21:10 +04:00
|
|
|
mPaused = false;
|
Bug 825928: Land layers refactoring. r=jrmuizel,bas,nical,mattwoodrow,roc,nrc,benwa,bjacob,jgilbert,kchen CLOSED TREE
Please contact Bas Schouten <bschouten@mozilla.com>, Nicolas Silva <nsilva@mozilla.com> or Nicholas Cameron <ncameron@mozilla.com> with general questions. Below is a rough list of authors to contact with specific questions.
Authors:
gfx/layers/Compositor.* gfx/layers/Effects.h - Compositor Interface - bas,nrc,nical
gfx/layers/d3d* - D3D9/D3D10 - bas
gfx/layers/ThebesLayer* - ThebesLayers - nrc,bas
gfx/layers/composite/* - CompositeLayers - nrc,nical
gfx/layers/client/* - Client - nrc,nical,bas
gfx/layers/*Image* - nical
gfx/layers/ipc ipc - IPC - nical
gfx/layers/opengl - CompositorOGL - nrc,nical
gfx/2d - bas,nrc
gfx/gl - GLContext - bjacob
dom/* layout/* - DOM - mattwoodrow
2013-04-10 13:20:52 +04:00
|
|
|
|
2016-09-01 00:06:01 +03:00
|
|
|
Invalidate();
|
2018-02-02 00:28:50 +03:00
|
|
|
mCompositorScheduler->ForceComposeToTarget(nullptr, nullptr);
|
2012-06-12 18:24:31 +04:00
|
|
|
|
2012-05-29 21:49:03 +04:00
|
|
|
// if anyone's waiting to make sure that composition really got resumed, tell
|
|
|
|
// them
|
|
|
|
lock.NotifyAll();
|
2012-02-05 22:33:38 +04:00
|
|
|
}
|
|
|
|
|
2016-03-22 21:08:38 +03:00
|
|
|
void CompositorBridgeParent::ForceComposition() {
|
2012-11-22 06:40:57 +04:00
|
|
|
// Cancel the orientation changed state to force composition
|
|
|
|
mForceCompositionTask = nullptr;
|
2019-04-17 18:14:25 +03:00
|
|
|
ScheduleRenderOnCompositorThread(wr::RenderRootSet());
|
2012-11-22 06:40:57 +04:00
|
|
|
}
|
|
|
|
|
2016-03-22 21:08:38 +03:00
|
|
|
void CompositorBridgeParent::CancelCurrentCompositeTask() {
|
2015-04-30 21:35:13 +03:00
|
|
|
mCompositorScheduler->CancelCurrentCompositeTask();
|
2014-03-10 08:47:12 +04:00
|
|
|
}
|
|
|
|
|
2018-11-15 04:54:18 +03:00
|
|
|
void CompositorBridgeParent::SetEGLSurfaceRect(int x, int y, int width,
|
|
|
|
int height) {
|
2013-04-30 07:16:04 +04:00
|
|
|
NS_ASSERTION(mUseExternalSurfaceSize,
|
|
|
|
"Compositor created without UseExternalSurfaceSize provided");
|
2012-05-08 23:40:41 +04:00
|
|
|
mEGLSurfaceSize.SizeTo(width, height);
|
2013-12-09 05:40:58 +04:00
|
|
|
if (mCompositor) {
|
|
|
|
mCompositor->SetDestinationSurfaceSize(
|
|
|
|
gfx::IntSize(mEGLSurfaceSize.width, mEGLSurfaceSize.height));
|
2018-11-15 04:54:18 +03:00
|
|
|
if (mCompositor->AsCompositorOGL()) {
|
|
|
|
mCompositor->AsCompositorOGL()->SetSurfaceOrigin(ScreenIntPoint(x, y));
|
|
|
|
}
|
2012-05-08 23:40:41 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-15 04:54:18 +03:00
|
|
|
void CompositorBridgeParent::ResumeCompositionAndResize(int x, int y, int width,
|
|
|
|
int height) {
|
|
|
|
SetEGLSurfaceRect(x, y, width, height);
|
2012-04-20 19:46:30 +04:00
|
|
|
ResumeComposition();
|
|
|
|
}
|
|
|
|
|
2012-05-10 06:32:54 +04:00
|
|
|
/*
|
|
|
|
* This will execute a pause synchronously, waiting to make sure that the
|
|
|
|
* compositor really is paused.
|
|
|
|
*/
|
2016-03-22 21:08:38 +03:00
|
|
|
void CompositorBridgeParent::SchedulePauseOnCompositorThread() {
|
2012-07-18 03:59:45 +04:00
|
|
|
MonitorAutoLock lock(mPauseCompositionMonitor);
|
2012-05-10 06:32:54 +04:00
|
|
|
|
2015-01-27 23:52:44 +03:00
|
|
|
MOZ_ASSERT(CompositorLoop());
|
2017-06-12 22:34:10 +03:00
|
|
|
CompositorLoop()->PostTask(
|
|
|
|
NewRunnableMethod("layers::CompositorBridgeParent::PauseComposition",
|
|
|
|
this, &CompositorBridgeParent::PauseComposition));
|
2012-05-10 06:32:54 +04:00
|
|
|
|
|
|
|
// Wait until the pause has actually been processed by the compositor thread
|
|
|
|
lock.Wait();
|
2012-02-05 22:33:38 +04:00
|
|
|
}
|
|
|
|
|
2016-03-22 21:08:38 +03:00
|
|
|
bool CompositorBridgeParent::ScheduleResumeOnCompositorThread() {
|
2015-04-11 05:14:00 +03:00
|
|
|
MonitorAutoLock lock(mResumeCompositionMonitor);
|
|
|
|
|
|
|
|
MOZ_ASSERT(CompositorLoop());
|
2017-06-12 22:34:10 +03:00
|
|
|
CompositorLoop()->PostTask(
|
|
|
|
NewRunnableMethod("layers::CompositorBridgeParent::ResumeComposition",
|
|
|
|
this, &CompositorBridgeParent::ResumeComposition));
|
2015-04-11 05:14:00 +03:00
|
|
|
|
|
|
|
// Wait until the resume has actually been processed by the compositor thread
|
|
|
|
lock.Wait();
|
|
|
|
|
|
|
|
return !mPaused;
|
|
|
|
}
|
|
|
|
|
2018-11-15 04:54:18 +03:00
|
|
|
bool CompositorBridgeParent::ScheduleResumeOnCompositorThread(int x, int y,
|
|
|
|
int width,
|
|
|
|
int height) {
|
2012-07-18 03:59:45 +04:00
|
|
|
MonitorAutoLock lock(mResumeCompositionMonitor);
|
2012-05-29 21:49:03 +04:00
|
|
|
|
2015-01-27 23:52:44 +03:00
|
|
|
MOZ_ASSERT(CompositorLoop());
|
2018-11-15 04:54:18 +03:00
|
|
|
CompositorLoop()->PostTask(NewRunnableMethod<int, int, int, int>(
|
2017-06-12 22:34:10 +03:00
|
|
|
"layers::CompositorBridgeParent::ResumeCompositionAndResize", this,
|
|
|
|
&CompositorBridgeParent::ResumeCompositionAndResize, x, y, width,
|
|
|
|
height));
|
2012-05-29 21:49:03 +04:00
|
|
|
|
|
|
|
// Wait until the resume has actually been processed by the compositor thread
|
|
|
|
lock.Wait();
|
2013-01-10 20:21:10 +04:00
|
|
|
|
|
|
|
return !mPaused;
|
2012-02-05 22:33:38 +04:00
|
|
|
}
|
|
|
|
|
2016-04-28 03:06:05 +03:00
|
|
|
void CompositorBridgeParent::ScheduleTask(
|
|
|
|
already_AddRefed<CancelableRunnable> task, int time) {
|
2012-05-24 21:34:20 +04:00
|
|
|
if (time == 0) {
|
2018-05-30 22:15:35 +03:00
|
|
|
MessageLoop::current()->PostTask(std::move(task));
|
2012-04-24 17:22:36 +04:00
|
|
|
} else {
|
2018-05-30 22:15:35 +03:00
|
|
|
MessageLoop::current()->PostDelayedTask(std::move(task), time);
|
2012-04-24 17:22:36 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-16 18:46:13 +03:00
|
|
|
void CompositorBridgeParent::UpdatePaintTime(LayerTransactionParent* aLayerTree,
|
|
|
|
const TimeDuration& aPaintTime) {
|
|
|
|
// We get a lot of paint timings for things with empty transactions.
|
|
|
|
if (!mLayerManager || aPaintTime.ToMilliseconds() < 1.0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mLayerManager->SetPaintTime(aPaintTime);
|
|
|
|
}
|
|
|
|
|
2019-05-28 16:42:57 +03:00
|
|
|
void CompositorBridgeParent::RegisterPayloads(
|
2018-12-13 17:56:51 +03:00
|
|
|
LayerTransactionParent* aLayerTree,
|
2019-05-28 16:42:57 +03:00
|
|
|
const nsTArray<CompositionPayload>& aPayload) {
|
2018-12-13 17:56:51 +03:00
|
|
|
// We get a lot of paint timings for things with empty transactions.
|
|
|
|
if (!mLayerManager) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-05-28 16:42:57 +03:00
|
|
|
mLayerManager->RegisterPayloads(aPayload);
|
2018-12-13 17:56:51 +03:00
|
|
|
}
|
|
|
|
|
2018-03-25 02:06:01 +03:00
|
|
|
void CompositorBridgeParent::NotifyShadowTreeTransaction(
|
2017-06-13 09:00:49 +03:00
|
|
|
LayersId aId, bool aIsFirstPaint, const FocusTarget& aFocusTarget,
|
2014-05-31 02:52:43 +04:00
|
|
|
bool aScheduleComposite, uint32_t aPaintSequenceNumber,
|
2016-05-16 21:53:44 +03:00
|
|
|
bool aIsRepeatTransaction, bool aHitTestUpdate) {
|
2016-07-18 11:54:02 +03:00
|
|
|
if (!aIsRepeatTransaction && mLayerManager && mLayerManager->GetRoot()) {
|
|
|
|
// Process plugin data here to give time for them to update before the next
|
|
|
|
// composition.
|
|
|
|
bool pluginsUpdatedFlag = true;
|
|
|
|
AutoResolveRefLayers resolve(mCompositionManager, this, nullptr,
|
|
|
|
&pluginsUpdatedFlag);
|
|
|
|
|
|
|
|
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
|
|
|
|
// If plugins haven't been updated, stop waiting.
|
|
|
|
if (!pluginsUpdatedFlag) {
|
|
|
|
mWaitForPluginsUntil = TimeStamp();
|
|
|
|
mHaveBlockedForPlugins = false;
|
|
|
|
}
|
|
|
|
#endif
|
2016-05-16 21:53:44 +03:00
|
|
|
|
2018-03-29 01:36:42 +03:00
|
|
|
if (mApzUpdater) {
|
2019-03-22 21:28:42 +03:00
|
|
|
mApzUpdater->UpdateFocusState(mRootLayerTreeID,
|
|
|
|
WRRootId::NonWebRender(aId), aFocusTarget);
|
2017-06-13 09:00:49 +03:00
|
|
|
if (aHitTestUpdate) {
|
2018-03-29 01:36:42 +03:00
|
|
|
mApzUpdater->UpdateHitTestingTree(
|
2019-07-06 11:18:28 +03:00
|
|
|
mLayerManager->GetRoot(), aIsFirstPaint, aId, aPaintSequenceNumber);
|
2017-06-13 09:00:49 +03:00
|
|
|
}
|
2016-05-16 21:53:44 +03:00
|
|
|
}
|
2013-07-30 22:03:40 +04:00
|
|
|
|
2014-02-11 02:14:11 +04:00
|
|
|
mLayerManager->NotifyShadowTreeTransaction();
|
2012-08-07 06:41:29 +04:00
|
|
|
}
|
2013-12-16 09:38:42 +04:00
|
|
|
if (aScheduleComposite) {
|
|
|
|
ScheduleComposition();
|
|
|
|
}
|
2012-08-07 06:41:29 +04:00
|
|
|
}
|
|
|
|
|
2019-03-22 21:28:42 +03:00
|
|
|
void CompositorBridgeParent::ScheduleComposition(
|
2019-04-17 18:12:10 +03:00
|
|
|
const wr::RenderRootSet& aRenderRoots) {
|
2016-05-16 09:40:13 +03:00
|
|
|
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
|
2015-01-22 03:13:15 +03:00
|
|
|
if (mPaused) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-11-30 15:38:47 +03:00
|
|
|
if (mWrBridge) {
|
2019-04-16 01:34:13 +03:00
|
|
|
mWrBridge->ScheduleGenerateFrame(aRenderRoots);
|
2017-11-30 15:38:47 +03:00
|
|
|
} else {
|
|
|
|
mCompositorScheduler->ScheduleComposition();
|
|
|
|
}
|
2014-02-11 08:58:01 +04:00
|
|
|
}
|
|
|
|
|
2014-10-20 08:04:39 +04:00
|
|
|
// Go down the composite layer tree, setting properties to match their
|
|
|
|
// content-side counterparts.
|
2019-02-26 01:07:19 +03:00
|
|
|
/* static */
|
|
|
|
void CompositorBridgeParent::SetShadowProperties(Layer* aLayer) {
|
2016-03-10 12:20:40 +03:00
|
|
|
ForEachNode<ForwardIterator>(aLayer, [](Layer* layer) {
|
|
|
|
if (Layer* maskLayer = layer->GetMaskLayer()) {
|
|
|
|
SetShadowProperties(maskLayer);
|
|
|
|
}
|
|
|
|
for (size_t i = 0; i < layer->GetAncestorMaskLayerCount(); i++) {
|
|
|
|
SetShadowProperties(layer->GetAncestorMaskLayerAt(i));
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: Bug 717688 -- Do these updates in
|
|
|
|
// LayerTransactionParent::RecvUpdate.
|
2016-11-24 08:11:27 +03:00
|
|
|
HostLayer* layerCompositor = layer->AsHostLayer();
|
2016-03-10 12:20:40 +03:00
|
|
|
// Set the layerComposite's base transform to the layer's base transform.
|
Bug 1425837 - Part 3: Don't store AnimationArray (a.k.a. AnimationInfo::mAnimations) on the compositor thread. r=birtles
The original implementation about "setting animations" is a little bit hard
to read. In `SetAnimations()`, we create a new intermediate data,
`AnimData`, and we mutate the original animations. And then iterate this
mutated animations & intermediate data for sampling. In this bug, we are
planning to group the AnimData as a useful data structure for supporting
multiple properties transform-like animations, so it seems the structure
of original animations may be hard to use after that. Therefore,
we decide to do some reworks on this:
First, we do renames,
1. InfalliableTArray to nsTArray. (They are the same.)
2. AnimData to PropertyAnimation.
3. SetAnimations() to ExtractAnimations(), which returns
nsTArray<PropertyAnimationGroup>. Each entry in the array is for one
property. In this patch, there is only one entry. We will extend this
to multiple entries in the next patch.
And then rework `ExtractAnimations()`, which stores all the necessary data
in `PropertyAnimationGroup`. For WR, we store this in
`CompositorAnimationStorage`. For non-WR, we store it in `AnimationInfo`.
So we can just use this organized data structure for supporting multiple
properties animations. (See the next patch.)
Depends on D22563
Differential Revision: https://phabricator.services.mozilla.com/D23062
--HG--
extra : moz-landing-system : lando
2019-03-18 21:04:48 +03:00
|
|
|
const auto& animations = layer->GetPropertyAnimationGroups();
|
2018-04-24 03:27:54 +03:00
|
|
|
// If there is any animation, the animation value will override
|
|
|
|
// non-animated value later, so we don't need to set the non-animated
|
|
|
|
// value here.
|
|
|
|
if (animations.IsEmpty()) {
|
|
|
|
layerCompositor->SetShadowBaseTransform(layer->GetBaseTransform());
|
|
|
|
layerCompositor->SetShadowTransformSetByAnimation(false);
|
|
|
|
layerCompositor->SetShadowOpacity(layer->GetOpacity());
|
|
|
|
layerCompositor->SetShadowOpacitySetByAnimation(false);
|
|
|
|
}
|
2016-11-24 08:11:27 +03:00
|
|
|
layerCompositor->SetShadowVisibleRegion(layer->GetVisibleRegion());
|
|
|
|
layerCompositor->SetShadowClipRect(layer->GetClipRect());
|
2016-03-10 12:20:40 +03:00
|
|
|
});
|
2014-10-20 08:04:39 +04:00
|
|
|
}
|
|
|
|
|
2018-12-08 02:28:03 +03:00
|
|
|
void CompositorBridgeParent::CompositeToTarget(VsyncId aId, DrawTarget* aTarget,
|
2016-03-22 21:08:38 +03:00
|
|
|
const gfx::IntRect* aRect) {
|
2019-01-18 18:40:15 +03:00
|
|
|
AUTO_PROFILER_TRACING("Paint", "Composite", GRAPHICS);
|
Bug 1375392 - Tweak the PROFILER_LABEL* macros. r=mstange.
This patch makes the following changes to the macros.
- Removes PROFILER_LABEL_FUNC. It's only suitable for use in functions outside
classes, due to PROFILER_FUNCTION_NAME not getting class names, and it was
mostly misused.
- Removes PROFILER_FUNCTION_NAME. It's no longer used, and __func__ is
universally available now anyway.
- Combines the first two string literal arguments of PROFILER_LABEL and
PROFILER_LABEL_DYNAMIC into a single argument. There was no good reason for
them to be separate, and it forced a '::' in the label, which isn't always
appropriate. Also, the meaning of the "name_space" argument was interpreted
in an interesting variety of ways.
- Adds an "AUTO_" prefix to PROFILER_LABEL and PROFILER_LABEL_DYNAMIC, to make
it clearer they construct RAII objects rather than just being function calls.
(I myself have screwed up the scoping because of this in the past.)
- Fills in the 'js::ProfileEntry::Category::' qualifier within the macro, so
the caller doesn't need to. This makes a *lot* more of the uses fit onto a
single line.
The patch also makes the following changes to the macro uses (beyond those
required by the changes described above).
- Fixes a bunch of labels that had gotten out of sync with the name of the
class and/or function that encloses them.
- Removes a useless PROFILER_LABEL use within a trivial scope in
EventStateManager::DispatchMouseOrPointerEvent(). It clearly wasn't serving
any useful purpose. It also serves as extra evidence that the AUTO_ prefix is
a good idea.
- Tweaks DecodePool::SyncRunIf{Preferred,Possible} so that the labelling is
done within them, instead of at their callsites, because that's a more
standard way of doing things.
--HG--
extra : rebase_source : 318d1bc6fc1425a94aacbf489dd46e4f83211de4
2017-06-22 10:08:53 +03:00
|
|
|
AUTO_PROFILER_LABEL("CompositorBridgeParent::CompositeToTarget", GRAPHICS);
|
2019-05-28 21:58:06 +03:00
|
|
|
PerfStats::AutoMetricRecording<PerfStats::Metric::Compositing> autoRecording;
|
2014-05-24 01:12:29 +04:00
|
|
|
|
2016-05-16 09:40:13 +03:00
|
|
|
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread(),
|
2014-06-06 00:42:13 +04:00
|
|
|
"Composite can only be called on the compositor thread");
|
2014-12-11 05:15:48 +03:00
|
|
|
TimeStamp start = TimeStamp::Now();
|
2014-03-04 23:41:24 +04:00
|
|
|
|
2012-10-04 11:05:24 +04:00
|
|
|
if (!CanComposite()) {
|
2015-09-09 02:14:51 +03:00
|
|
|
TimeStamp end = TimeStamp::Now();
|
2018-12-08 02:28:41 +03:00
|
|
|
DidComposite(aId, start, end);
|
2011-12-16 00:07:25 +04:00
|
|
|
return;
|
2011-12-19 22:17:29 +04:00
|
|
|
}
|
2011-12-16 00:07:25 +04:00
|
|
|
|
2016-07-18 11:54:02 +03:00
|
|
|
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
|
|
|
|
if (!mWaitForPluginsUntil.IsNull() && mWaitForPluginsUntil > start) {
|
|
|
|
mHaveBlockedForPlugins = true;
|
|
|
|
ScheduleComposition();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2015-10-06 22:23:24 +03:00
|
|
|
/*
|
|
|
|
* AutoResolveRefLayers handles two tasks related to Windows and Linux
|
|
|
|
* plugin window management:
|
|
|
|
* 1) calculating if we have remote content in the view. If we do not have
|
2016-03-22 21:08:38 +03:00
|
|
|
* remote content, all plugin windows for this CompositorBridgeParent (window)
|
2015-10-06 22:23:24 +03:00
|
|
|
* can be hidden since we do not support plugins in chrome when running
|
|
|
|
* under e10s.
|
|
|
|
* 2) Updating plugin position, size, and clip. We do this here while the
|
|
|
|
* remote layer tree is hooked up to to chrome layer tree. This is needed
|
|
|
|
* since plugin clipping can depend on chrome (for example, due to tab modal
|
|
|
|
* prompts). Updates in step 2 are applied via an async ipc message sent
|
|
|
|
* to the main thread.
|
|
|
|
*/
|
2016-03-24 17:40:26 +03:00
|
|
|
bool hasRemoteContent = false;
|
|
|
|
bool updatePluginsFlag = true;
|
|
|
|
AutoResolveRefLayers resolve(mCompositionManager, this, &hasRemoteContent,
|
|
|
|
&updatePluginsFlag);
|
2015-10-06 22:23:24 +03:00
|
|
|
|
2016-03-24 17:40:26 +03:00
|
|
|
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
|
2015-10-06 22:23:24 +03:00
|
|
|
// We do not support plugins in local content. When switching tabs
|
|
|
|
// to local pages, hide every plugin associated with the window.
|
2016-08-04 21:33:44 +03:00
|
|
|
if (!hasRemoteContent && gfxVars::BrowserTabsRemoteAutostart() &&
|
2015-10-06 22:23:24 +03:00
|
|
|
mCachedPluginData.Length()) {
|
2016-07-01 11:15:16 +03:00
|
|
|
Unused << SendHideAllPlugins(GetWidget()->GetWidgetKey());
|
2015-10-06 22:23:24 +03:00
|
|
|
mCachedPluginData.Clear();
|
2015-10-06 22:23:24 +03:00
|
|
|
}
|
|
|
|
#endif
|
2014-02-11 08:00:16 +04:00
|
|
|
|
2018-11-19 10:55:28 +03:00
|
|
|
nsCString none;
|
2014-02-11 08:00:16 +04:00
|
|
|
if (aTarget) {
|
2014-05-28 05:21:32 +04:00
|
|
|
mLayerManager->BeginTransactionWithDrawTarget(aTarget, *aRect);
|
2014-02-11 08:00:16 +04:00
|
|
|
} else {
|
2018-11-19 10:55:28 +03:00
|
|
|
mLayerManager->BeginTransaction(none);
|
2014-02-11 08:00:16 +04:00
|
|
|
}
|
|
|
|
|
2014-10-20 08:04:39 +04:00
|
|
|
SetShadowProperties(mLayerManager->GetRoot());
|
|
|
|
|
2012-11-22 06:40:57 +04:00
|
|
|
if (mForceCompositionTask && !mOverrideComposeReadiness) {
|
2013-04-28 10:46:30 +04:00
|
|
|
if (mCompositionManager->ReadyForCompose()) {
|
2012-11-22 06:40:57 +04:00
|
|
|
mForceCompositionTask->Cancel();
|
|
|
|
mForceCompositionTask = nullptr;
|
2013-04-28 10:46:30 +04:00
|
|
|
} else {
|
|
|
|
return;
|
2012-11-22 06:40:57 +04:00
|
|
|
}
|
|
|
|
}
|
2012-07-18 03:59:45 +04:00
|
|
|
|
2014-09-30 18:07:05 +04:00
|
|
|
mCompositionManager->ComputeRotation();
|
|
|
|
|
2018-02-02 16:57:35 +03:00
|
|
|
TimeStamp time =
|
|
|
|
mTestTime.valueOr(mCompositorScheduler->GetLastComposeTime());
|
2016-07-26 11:57:11 +03:00
|
|
|
bool requestNextFrame =
|
|
|
|
mCompositionManager->TransformShadowTree(time, mVsyncRate);
|
2018-07-24 00:47:28 +03:00
|
|
|
|
|
|
|
// Don't eagerly schedule new compositions here when recording or replaying.
|
|
|
|
// Recording/replaying processes schedule composites at the top of the main
|
|
|
|
// thread's event loop rather than via PVsync, which can cause the composites
|
|
|
|
// scheduled here to pile up without any drawing actually happening.
|
|
|
|
if (requestNextFrame && !recordreplay::IsRecordingOrReplaying()) {
|
2012-07-20 10:48:27 +04:00
|
|
|
ScheduleComposition();
|
2016-07-18 11:54:02 +03:00
|
|
|
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
|
|
|
|
// If we have visible windowed plugins then we need to wait for content (and
|
|
|
|
// then the plugins) to have been updated by the active animation.
|
|
|
|
if (!mPluginWindowsHidden && mCachedPluginData.Length()) {
|
2016-10-26 02:25:52 +03:00
|
|
|
mWaitForPluginsUntil =
|
|
|
|
mCompositorScheduler->GetLastComposeTime() + (mVsyncRate * 2);
|
2016-07-18 11:54:02 +03:00
|
|
|
}
|
|
|
|
#endif
|
2012-07-20 10:48:27 +04:00
|
|
|
}
|
2012-02-10 07:47:50 +04:00
|
|
|
|
2013-04-28 10:46:30 +04:00
|
|
|
RenderTraceLayers(mLayerManager->GetRoot(), "0000");
|
|
|
|
|
2019-06-27 07:48:58 +03:00
|
|
|
if (StaticPrefs::layers_dump_host_layers() || StaticPrefs::layers_dump()) {
|
2013-11-24 02:44:18 +04:00
|
|
|
printf_stderr("Painting --- compositing layer tree:\n");
|
2016-03-17 23:18:10 +03:00
|
|
|
mLayerManager->Dump(/* aSorted = */ true);
|
2012-07-24 23:01:09 +04:00
|
|
|
}
|
2013-12-04 00:04:47 +04:00
|
|
|
mLayerManager->SetDebugOverlayWantsNextFrame(false);
|
2015-07-07 06:38:38 +03:00
|
|
|
mLayerManager->EndTransaction(time);
|
2012-02-11 03:06:17 +04:00
|
|
|
|
2015-09-09 02:14:51 +03:00
|
|
|
if (!aTarget) {
|
|
|
|
TimeStamp end = TimeStamp::Now();
|
2018-12-08 02:28:41 +03:00
|
|
|
DidComposite(aId, start, end);
|
2015-09-09 02:14:51 +03:00
|
|
|
}
|
|
|
|
|
2017-02-16 06:03:20 +03:00
|
|
|
// We're not really taking advantage of the stored composite-again-time here.
|
|
|
|
// We might be able to skip the next few composites altogether. However,
|
|
|
|
// that's a bit complex to implement and we'll get most of the advantage
|
|
|
|
// by skipping compositing when we detect there's nothing invalid. This is why
|
|
|
|
// we do "composite until" rather than "composite again at".
|
|
|
|
//
|
|
|
|
// TODO(bug 1328602) Figure out what we should do here with the render thread.
|
|
|
|
if (!mLayerManager->GetCompositeUntilTime().IsNull() ||
|
|
|
|
mLayerManager->DebugOverlayWantsNextFrame()) {
|
2017-01-18 22:50:00 +03:00
|
|
|
ScheduleComposition();
|
2013-12-03 19:49:46 +04:00
|
|
|
}
|
|
|
|
|
2012-02-11 03:06:17 +04:00
|
|
|
#ifdef COMPOSITOR_PERFORMANCE_WARNING
|
2015-04-30 21:35:13 +03:00
|
|
|
TimeDuration executionTime =
|
|
|
|
TimeStamp::Now() - mCompositorScheduler->GetLastComposeTime();
|
2014-03-04 23:41:24 +04:00
|
|
|
TimeDuration frameBudget = TimeDuration::FromMilliseconds(15);
|
|
|
|
int32_t frameRate = CalculateCompositionFrameRate();
|
|
|
|
if (frameRate > 0) {
|
|
|
|
frameBudget = TimeDuration::FromSeconds(1.0 / frameRate);
|
|
|
|
}
|
|
|
|
if (executionTime > frameBudget) {
|
|
|
|
printf_stderr("Compositor: Composite execution took %4.1f ms\n",
|
|
|
|
executionTime.ToMilliseconds());
|
2012-02-11 03:06:17 +04:00
|
|
|
}
|
|
|
|
#endif
|
2014-01-30 03:26:38 +04:00
|
|
|
|
|
|
|
// 0 -> Full-tilt composite
|
2019-06-27 07:48:58 +03:00
|
|
|
if (StaticPrefs::layers_offmainthreadcomposition_frame_rate() == 0 ||
|
2017-02-16 06:03:20 +03:00
|
|
|
mLayerManager->AlwaysScheduleComposite()) {
|
2014-01-30 03:26:38 +04:00
|
|
|
// Special full-tilt composite mode for performance testing
|
|
|
|
ScheduleComposition();
|
|
|
|
}
|
2017-01-18 22:50:00 +03:00
|
|
|
|
2017-02-16 06:03:20 +03:00
|
|
|
// TODO(bug 1328602) Need an equivalent that works with the rende thread.
|
|
|
|
mLayerManager->SetCompositionTime(TimeStamp());
|
2014-01-30 03:26:38 +04:00
|
|
|
|
2014-12-11 05:15:48 +03:00
|
|
|
mozilla::Telemetry::AccumulateTimeDelta(mozilla::Telemetry::COMPOSITE_TIME,
|
|
|
|
start);
|
2011-12-16 00:07:19 +04:00
|
|
|
}
|
|
|
|
|
2016-03-22 21:08:38 +03:00
|
|
|
mozilla::ipc::IPCResult CompositorBridgeParent::RecvRemotePluginsReady() {
|
2016-01-12 20:05:58 +03:00
|
|
|
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
|
2016-07-18 11:54:02 +03:00
|
|
|
mWaitForPluginsUntil = TimeStamp();
|
|
|
|
if (mHaveBlockedForPlugins) {
|
|
|
|
mHaveBlockedForPlugins = false;
|
|
|
|
ForceComposeToTarget(nullptr);
|
|
|
|
} else {
|
|
|
|
ScheduleComposition();
|
|
|
|
}
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2015-10-06 22:23:24 +03:00
|
|
|
#else
|
2018-06-18 08:43:11 +03:00
|
|
|
MOZ_ASSERT_UNREACHABLE(
|
|
|
|
"CompositorBridgeParent::RecvRemotePluginsReady calls "
|
|
|
|
"unexpected on this platform.");
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_FAIL_NO_REASON(this);
|
2015-10-06 22:23:24 +03:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2016-03-22 21:08:38 +03:00
|
|
|
void CompositorBridgeParent::ForceComposeToTarget(DrawTarget* aTarget,
|
|
|
|
const gfx::IntRect* aRect) {
|
Bug 1375392 - Tweak the PROFILER_LABEL* macros. r=mstange.
This patch makes the following changes to the macros.
- Removes PROFILER_LABEL_FUNC. It's only suitable for use in functions outside
classes, due to PROFILER_FUNCTION_NAME not getting class names, and it was
mostly misused.
- Removes PROFILER_FUNCTION_NAME. It's no longer used, and __func__ is
universally available now anyway.
- Combines the first two string literal arguments of PROFILER_LABEL and
PROFILER_LABEL_DYNAMIC into a single argument. There was no good reason for
them to be separate, and it forced a '::' in the label, which isn't always
appropriate. Also, the meaning of the "name_space" argument was interpreted
in an interesting variety of ways.
- Adds an "AUTO_" prefix to PROFILER_LABEL and PROFILER_LABEL_DYNAMIC, to make
it clearer they construct RAII objects rather than just being function calls.
(I myself have screwed up the scoping because of this in the past.)
- Fills in the 'js::ProfileEntry::Category::' qualifier within the macro, so
the caller doesn't need to. This makes a *lot* more of the uses fit onto a
single line.
The patch also makes the following changes to the macro uses (beyond those
required by the changes described above).
- Fixes a bunch of labels that had gotten out of sync with the name of the
class and/or function that encloses them.
- Removes a useless PROFILER_LABEL use within a trivial scope in
EventStateManager::DispatchMouseOrPointerEvent(). It clearly wasn't serving
any useful purpose. It also serves as extra evidence that the AUTO_ prefix is
a good idea.
- Tweaks DecodePool::SyncRunIf{Preferred,Possible} so that the labelling is
done within them, instead of at their callsites, because that's a more
standard way of doing things.
--HG--
extra : rebase_source : 318d1bc6fc1425a94aacbf489dd46e4f83211de4
2017-06-22 10:08:53 +03:00
|
|
|
AUTO_PROFILER_LABEL("CompositorBridgeParent::ForceComposeToTarget", GRAPHICS);
|
2014-05-24 01:12:29 +04:00
|
|
|
|
2012-11-22 06:40:57 +04:00
|
|
|
AutoRestore<bool> override(mOverrideComposeReadiness);
|
|
|
|
mOverrideComposeReadiness = true;
|
2015-04-30 21:35:13 +03:00
|
|
|
mCompositorScheduler->ForceComposeToTarget(aTarget, aRect);
|
2012-10-04 11:05:24 +04:00
|
|
|
}
|
|
|
|
|
2018-03-25 02:06:01 +03:00
|
|
|
PAPZCTreeManagerParent* CompositorBridgeParent::AllocPAPZCTreeManagerParent(
|
|
|
|
const LayersId& aLayersId) {
|
2018-03-16 23:28:18 +03:00
|
|
|
// This should only ever get called in the GPU process.
|
|
|
|
MOZ_ASSERT(XRE_IsGPUProcess());
|
2017-01-13 01:29:41 +03:00
|
|
|
// We should only ever get this if APZ is enabled in this compositor.
|
|
|
|
MOZ_ASSERT(mOptions.UseAPZ());
|
2018-03-29 01:36:42 +03:00
|
|
|
// The mApzcTreeManager and mApzUpdater should have been created via
|
|
|
|
// RecvInitialize()
|
2018-03-16 23:28:18 +03:00
|
|
|
MOZ_ASSERT(mApzcTreeManager);
|
2018-03-29 01:36:42 +03:00
|
|
|
MOZ_ASSERT(mApzUpdater);
|
2016-08-29 16:18:00 +03:00
|
|
|
// The main process should pass in 0 because we assume mRootLayerTreeID
|
2018-03-25 02:06:01 +03:00
|
|
|
MOZ_ASSERT(!aLayersId.IsValid());
|
2016-08-29 16:18:00 +03:00
|
|
|
|
|
|
|
MonitorAutoLock lock(*sIndirectLayerTreesLock);
|
|
|
|
CompositorBridgeParent::LayerTreeState& state =
|
|
|
|
sIndirectLayerTrees[mRootLayerTreeID];
|
2018-03-02 07:00:41 +03:00
|
|
|
MOZ_ASSERT(state.mParent.get() == this);
|
2016-08-29 16:18:00 +03:00
|
|
|
MOZ_ASSERT(!state.mApzcTreeManagerParent);
|
2018-03-29 01:36:42 +03:00
|
|
|
state.mApzcTreeManagerParent = new APZCTreeManagerParent(
|
2019-03-22 21:28:42 +03:00
|
|
|
WRRootId(mRootLayerTreeID, wr::RenderRoot::Default), mApzcTreeManager,
|
|
|
|
mApzUpdater);
|
2016-08-29 16:18:00 +03:00
|
|
|
|
|
|
|
return state.mApzcTreeManagerParent;
|
2016-08-16 23:59:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bool CompositorBridgeParent::DeallocPAPZCTreeManagerParent(
|
|
|
|
PAPZCTreeManagerParent* aActor) {
|
2016-08-29 16:18:00 +03:00
|
|
|
delete aActor;
|
|
|
|
return true;
|
2016-08-16 23:59:13 +03:00
|
|
|
}
|
|
|
|
|
2018-03-06 18:25:36 +03:00
|
|
|
void CompositorBridgeParent::AllocateAPZCTreeManagerParent(
|
|
|
|
const MonitorAutoLock& aProofOfLayerTreeStateLock,
|
2019-03-22 21:28:42 +03:00
|
|
|
const WRRootId& aWrRootId, LayerTreeState& aState) {
|
2018-03-06 18:25:36 +03:00
|
|
|
MOZ_ASSERT(aState.mParent == this);
|
|
|
|
MOZ_ASSERT(mApzcTreeManager);
|
2018-03-29 01:36:42 +03:00
|
|
|
MOZ_ASSERT(mApzUpdater);
|
2018-03-06 18:25:36 +03:00
|
|
|
MOZ_ASSERT(!aState.mApzcTreeManagerParent);
|
2018-03-29 01:36:42 +03:00
|
|
|
aState.mApzcTreeManagerParent =
|
2019-03-22 21:28:42 +03:00
|
|
|
new APZCTreeManagerParent(aWrRootId, mApzcTreeManager, mApzUpdater);
|
2018-03-06 18:25:36 +03:00
|
|
|
}
|
|
|
|
|
2018-03-25 02:06:01 +03:00
|
|
|
PAPZParent* CompositorBridgeParent::AllocPAPZParent(const LayersId& aLayersId) {
|
2016-08-29 16:18:00 +03:00
|
|
|
// The main process should pass in 0 because we assume mRootLayerTreeID
|
2018-03-25 02:06:01 +03:00
|
|
|
MOZ_ASSERT(!aLayersId.IsValid());
|
2016-08-29 16:18:00 +03:00
|
|
|
|
|
|
|
RemoteContentController* controller = new RemoteContentController();
|
|
|
|
|
|
|
|
// Increment the controller's refcount before we return it. This will keep the
|
|
|
|
// controller alive until it is released by IPDL in DeallocPAPZParent.
|
|
|
|
controller->AddRef();
|
|
|
|
|
|
|
|
MonitorAutoLock lock(*sIndirectLayerTreesLock);
|
|
|
|
CompositorBridgeParent::LayerTreeState& state =
|
|
|
|
sIndirectLayerTrees[mRootLayerTreeID];
|
|
|
|
MOZ_ASSERT(!state.mController);
|
|
|
|
state.mController = controller;
|
|
|
|
|
|
|
|
return controller;
|
2016-08-02 09:59:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bool CompositorBridgeParent::DeallocPAPZParent(PAPZParent* aActor) {
|
2016-08-29 16:18:00 +03:00
|
|
|
RemoteContentController* controller =
|
|
|
|
static_cast<RemoteContentController*>(aActor);
|
|
|
|
controller->Release();
|
|
|
|
return true;
|
2016-08-02 09:59:00 +03:00
|
|
|
}
|
|
|
|
|
2018-03-06 18:25:38 +03:00
|
|
|
#if defined(MOZ_WIDGET_ANDROID)
|
2018-03-08 01:34:11 +03:00
|
|
|
AndroidDynamicToolbarAnimator*
|
|
|
|
CompositorBridgeParent::GetAndroidDynamicToolbarAnimator() {
|
|
|
|
return mApzcTreeManager ? mApzcTreeManager->GetAndroidDynamicToolbarAnimator()
|
|
|
|
: nullptr;
|
|
|
|
}
|
2018-03-06 18:25:38 +03:00
|
|
|
#endif
|
2016-08-16 23:59:13 +03:00
|
|
|
|
2018-03-02 07:00:41 +03:00
|
|
|
RefPtr<APZSampler> CompositorBridgeParent::GetAPZSampler() {
|
|
|
|
return mApzSampler;
|
|
|
|
}
|
|
|
|
|
2018-03-29 01:36:42 +03:00
|
|
|
RefPtr<APZUpdater> CompositorBridgeParent::GetAPZUpdater() {
|
|
|
|
return mApzUpdater;
|
|
|
|
}
|
|
|
|
|
2017-01-05 22:04:38 +03:00
|
|
|
CompositorBridgeParent*
|
2018-03-25 02:06:01 +03:00
|
|
|
CompositorBridgeParent::GetCompositorBridgeParentFromLayersId(
|
|
|
|
const LayersId& aLayersId) {
|
2017-01-05 22:04:38 +03:00
|
|
|
MonitorAutoLock lock(*sIndirectLayerTreesLock);
|
|
|
|
return sIndirectLayerTrees[aLayersId].mParent;
|
|
|
|
}
|
|
|
|
|
2019-02-26 01:07:19 +03:00
|
|
|
/*static*/
|
|
|
|
RefPtr<CompositorBridgeParent>
|
2018-05-11 16:09:16 +03:00
|
|
|
CompositorBridgeParent::GetCompositorBridgeParentFromWindowId(
|
|
|
|
const wr::WindowId& aWindowId) {
|
|
|
|
MonitorAutoLock lock(*sIndirectLayerTreesLock);
|
|
|
|
for (auto it = sIndirectLayerTrees.begin(); it != sIndirectLayerTrees.end();
|
|
|
|
it++) {
|
|
|
|
LayerTreeState* state = &it->second;
|
|
|
|
if (!state->mWrBridge) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
// state->mWrBridge might be a root WebRenderBridgeParent or one of a
|
|
|
|
// content process, but in either case the state->mParent will be the same.
|
|
|
|
// So we don't need to distinguish between the two.
|
2019-03-22 21:28:42 +03:00
|
|
|
if (RefPtr<wr::WebRenderAPI> api =
|
|
|
|
state->mWrBridge->GetWebRenderAPI(wr::RenderRoot::Default)) {
|
2018-05-11 16:09:16 +03:00
|
|
|
if (api->GetId() == aWindowId) {
|
|
|
|
return state->mParent;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2016-03-22 21:08:38 +03:00
|
|
|
bool CompositorBridgeParent::CanComposite() {
|
2014-06-06 17:51:27 +04:00
|
|
|
return mLayerManager && mLayerManager->GetRoot() && !mPaused;
|
2012-10-04 11:05:24 +04:00
|
|
|
}
|
|
|
|
|
2016-03-22 21:08:38 +03:00
|
|
|
void CompositorBridgeParent::ScheduleRotationOnCompositorThread(
|
|
|
|
const TargetConfig& aTargetConfig, bool aIsFirstPaint) {
|
2016-05-16 09:40:13 +03:00
|
|
|
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
|
2014-04-28 06:22:00 +04:00
|
|
|
|
2013-04-28 10:46:30 +04:00
|
|
|
if (!aIsFirstPaint && !mCompositionManager->IsFirstPaint() &&
|
|
|
|
mCompositionManager->RequiresReorientation(aTargetConfig.orientation())) {
|
2013-07-20 12:48:55 +04:00
|
|
|
if (mForceCompositionTask != nullptr) {
|
Bug 825928: Land layers refactoring. r=jrmuizel,bas,nical,mattwoodrow,roc,nrc,benwa,bjacob,jgilbert,kchen CLOSED TREE
Please contact Bas Schouten <bschouten@mozilla.com>, Nicolas Silva <nsilva@mozilla.com> or Nicholas Cameron <ncameron@mozilla.com> with general questions. Below is a rough list of authors to contact with specific questions.
Authors:
gfx/layers/Compositor.* gfx/layers/Effects.h - Compositor Interface - bas,nrc,nical
gfx/layers/d3d* - D3D9/D3D10 - bas
gfx/layers/ThebesLayer* - ThebesLayers - nrc,bas
gfx/layers/composite/* - CompositeLayers - nrc,nical
gfx/layers/client/* - Client - nrc,nical,bas
gfx/layers/*Image* - nical
gfx/layers/ipc ipc - IPC - nical
gfx/layers/opengl - CompositorOGL - nrc,nical
gfx/2d - bas,nrc
gfx/gl - GLContext - bjacob
dom/* layout/* - DOM - mattwoodrow
2013-04-10 13:20:52 +04:00
|
|
|
mForceCompositionTask->Cancel();
|
|
|
|
}
|
2017-06-12 22:34:10 +03:00
|
|
|
RefPtr<CancelableRunnable> task = NewCancelableRunnableMethod(
|
|
|
|
"layers::CompositorBridgeParent::ForceComposition", this,
|
|
|
|
&CompositorBridgeParent::ForceComposition);
|
2016-04-28 03:06:05 +03:00
|
|
|
mForceCompositionTask = task;
|
2019-06-27 07:48:58 +03:00
|
|
|
ScheduleTask(task.forget(), StaticPrefs::layers_orientation_sync_timeout());
|
Bug 825928: Land layers refactoring. r=jrmuizel,bas,nical,mattwoodrow,roc,nrc,benwa,bjacob,jgilbert,kchen CLOSED TREE
Please contact Bas Schouten <bschouten@mozilla.com>, Nicolas Silva <nsilva@mozilla.com> or Nicholas Cameron <ncameron@mozilla.com> with general questions. Below is a rough list of authors to contact with specific questions.
Authors:
gfx/layers/Compositor.* gfx/layers/Effects.h - Compositor Interface - bas,nrc,nical
gfx/layers/d3d* - D3D9/D3D10 - bas
gfx/layers/ThebesLayer* - ThebesLayers - nrc,bas
gfx/layers/composite/* - CompositeLayers - nrc,nical
gfx/layers/client/* - Client - nrc,nical,bas
gfx/layers/*Image* - nical
gfx/layers/ipc ipc - IPC - nical
gfx/layers/opengl - CompositorOGL - nrc,nical
gfx/2d - bas,nrc
gfx/gl - GLContext - bjacob
dom/* layout/* - DOM - mattwoodrow
2013-04-10 13:20:52 +04:00
|
|
|
}
|
2014-04-28 06:22:00 +04:00
|
|
|
}
|
|
|
|
|
2016-03-22 21:08:38 +03:00
|
|
|
void CompositorBridgeParent::ShadowLayersUpdated(
|
|
|
|
LayerTransactionParent* aLayerTree, const TransactionInfo& aInfo,
|
2016-05-16 21:53:44 +03:00
|
|
|
bool aHitTestUpdate) {
|
2017-01-04 20:58:58 +03:00
|
|
|
const TargetConfig& targetConfig = aInfo.targetConfig();
|
|
|
|
|
|
|
|
ScheduleRotationOnCompositorThread(targetConfig, aInfo.isFirstPaint());
|
Bug 825928: Land layers refactoring. r=jrmuizel,bas,nical,mattwoodrow,roc,nrc,benwa,bjacob,jgilbert,kchen CLOSED TREE
Please contact Bas Schouten <bschouten@mozilla.com>, Nicolas Silva <nsilva@mozilla.com> or Nicholas Cameron <ncameron@mozilla.com> with general questions. Below is a rough list of authors to contact with specific questions.
Authors:
gfx/layers/Compositor.* gfx/layers/Effects.h - Compositor Interface - bas,nrc,nical
gfx/layers/d3d* - D3D9/D3D10 - bas
gfx/layers/ThebesLayer* - ThebesLayers - nrc,bas
gfx/layers/composite/* - CompositeLayers - nrc,nical
gfx/layers/client/* - Client - nrc,nical,bas
gfx/layers/*Image* - nical
gfx/layers/ipc ipc - IPC - nical
gfx/layers/opengl - CompositorOGL - nrc,nical
gfx/2d - bas,nrc
gfx/gl - GLContext - bjacob
dom/* layout/* - DOM - mattwoodrow
2013-04-10 13:20:52 +04:00
|
|
|
|
|
|
|
// Instruct the LayerManager to update its render bounds now. Since all the
|
|
|
|
// orientation change, dimension change would be done at the stage, update the
|
|
|
|
// size here is free of race condition.
|
2017-01-04 20:58:58 +03:00
|
|
|
mLayerManager->UpdateRenderBounds(targetConfig.naturalBounds());
|
|
|
|
mLayerManager->SetRegionToClear(targetConfig.clearRegion());
|
2016-11-24 08:11:27 +03:00
|
|
|
if (mLayerManager->GetCompositor()) {
|
2017-01-04 20:58:58 +03:00
|
|
|
mLayerManager->GetCompositor()->SetScreenRotation(targetConfig.rotation());
|
2016-11-24 08:11:27 +03:00
|
|
|
}
|
Bug 825928: Land layers refactoring. r=jrmuizel,bas,nical,mattwoodrow,roc,nrc,benwa,bjacob,jgilbert,kchen CLOSED TREE
Please contact Bas Schouten <bschouten@mozilla.com>, Nicolas Silva <nsilva@mozilla.com> or Nicholas Cameron <ncameron@mozilla.com> with general questions. Below is a rough list of authors to contact with specific questions.
Authors:
gfx/layers/Compositor.* gfx/layers/Effects.h - Compositor Interface - bas,nrc,nical
gfx/layers/d3d* - D3D9/D3D10 - bas
gfx/layers/ThebesLayer* - ThebesLayers - nrc,bas
gfx/layers/composite/* - CompositeLayers - nrc,nical
gfx/layers/client/* - Client - nrc,nical,bas
gfx/layers/*Image* - nical
gfx/layers/ipc ipc - IPC - nical
gfx/layers/opengl - CompositorOGL - nrc,nical
gfx/2d - bas,nrc
gfx/gl - GLContext - bjacob
dom/* layout/* - DOM - mattwoodrow
2013-04-10 13:20:52 +04:00
|
|
|
|
2017-04-06 01:42:50 +03:00
|
|
|
mCompositionManager->Updated(aInfo.isFirstPaint(), targetConfig);
|
Bug 825928: Land layers refactoring. r=jrmuizel,bas,nical,mattwoodrow,roc,nrc,benwa,bjacob,jgilbert,kchen CLOSED TREE
Please contact Bas Schouten <bschouten@mozilla.com>, Nicolas Silva <nsilva@mozilla.com> or Nicholas Cameron <ncameron@mozilla.com> with general questions. Below is a rough list of authors to contact with specific questions.
Authors:
gfx/layers/Compositor.* gfx/layers/Effects.h - Compositor Interface - bas,nrc,nical
gfx/layers/d3d* - D3D9/D3D10 - bas
gfx/layers/ThebesLayer* - ThebesLayers - nrc,bas
gfx/layers/composite/* - CompositeLayers - nrc,nical
gfx/layers/client/* - Client - nrc,nical,bas
gfx/layers/*Image* - nical
gfx/layers/ipc ipc - IPC - nical
gfx/layers/opengl - CompositorOGL - nrc,nical
gfx/2d - bas,nrc
gfx/gl - GLContext - bjacob
dom/* layout/* - DOM - mattwoodrow
2013-04-10 13:20:52 +04:00
|
|
|
Layer* root = aLayerTree->GetRoot();
|
|
|
|
mLayerManager->SetRoot(root);
|
2013-07-30 22:03:40 +04:00
|
|
|
|
2018-03-29 01:36:42 +03:00
|
|
|
if (mApzUpdater && !aInfo.isRepeatTransaction()) {
|
2019-03-22 21:28:42 +03:00
|
|
|
mApzUpdater->UpdateFocusState(mRootLayerTreeID,
|
|
|
|
WRRootId::NonWebRender(mRootLayerTreeID),
|
2018-03-02 07:00:41 +03:00
|
|
|
aInfo.focusTarget());
|
2017-06-13 09:00:49 +03:00
|
|
|
|
|
|
|
if (aHitTestUpdate) {
|
|
|
|
AutoResolveRefLayers resolve(mCompositionManager);
|
2016-05-16 21:53:44 +03:00
|
|
|
|
2019-07-06 11:18:28 +03:00
|
|
|
mApzUpdater->UpdateHitTestingTree(root, aInfo.isFirstPaint(),
|
|
|
|
mRootLayerTreeID,
|
2017-06-13 09:00:49 +03:00
|
|
|
aInfo.paintSequenceNumber());
|
|
|
|
}
|
2013-07-30 22:03:40 +04:00
|
|
|
}
|
2014-05-29 01:43:39 +04:00
|
|
|
|
2015-07-16 21:18:55 +03:00
|
|
|
// The transaction ID might get reset to 1 if the page gets reloaded, see
|
|
|
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=1145295#c41
|
|
|
|
// Otherwise, it should be continually increasing.
|
2018-04-20 22:13:06 +03:00
|
|
|
MOZ_ASSERT(aInfo.id() == TransactionId{1} ||
|
|
|
|
aInfo.id() > mPendingTransaction);
|
2017-01-04 20:58:58 +03:00
|
|
|
mPendingTransaction = aInfo.id();
|
2018-06-26 21:40:10 +03:00
|
|
|
mRefreshStartTime = aInfo.refreshStart();
|
2017-08-11 04:57:21 +03:00
|
|
|
mTxnStartTime = aInfo.transactionStart();
|
|
|
|
mFwdTime = aInfo.fwdTime();
|
2019-05-28 16:42:57 +03:00
|
|
|
RegisterPayloads(aLayerTree, aInfo.payload());
|
2013-07-30 22:03:40 +04:00
|
|
|
|
2014-10-23 00:03:18 +04:00
|
|
|
if (root) {
|
|
|
|
SetShadowProperties(root);
|
|
|
|
}
|
2017-01-04 20:58:58 +03:00
|
|
|
if (aInfo.scheduleComposite()) {
|
2013-12-16 09:38:42 +04:00
|
|
|
ScheduleComposition();
|
2014-05-29 01:42:16 +04:00
|
|
|
if (mPaused) {
|
2015-08-25 08:51:58 +03:00
|
|
|
TimeStamp now = TimeStamp::Now();
|
2018-12-08 02:28:41 +03:00
|
|
|
DidComposite(VsyncId(), now, now);
|
2014-05-29 01:42:16 +04:00
|
|
|
}
|
2013-12-16 09:38:42 +04:00
|
|
|
}
|
2014-02-11 02:14:11 +04:00
|
|
|
mLayerManager->NotifyShadowTreeTransaction();
|
Bug 825928: Land layers refactoring. r=jrmuizel,bas,nical,mattwoodrow,roc,nrc,benwa,bjacob,jgilbert,kchen CLOSED TREE
Please contact Bas Schouten <bschouten@mozilla.com>, Nicolas Silva <nsilva@mozilla.com> or Nicholas Cameron <ncameron@mozilla.com> with general questions. Below is a rough list of authors to contact with specific questions.
Authors:
gfx/layers/Compositor.* gfx/layers/Effects.h - Compositor Interface - bas,nrc,nical
gfx/layers/d3d* - D3D9/D3D10 - bas
gfx/layers/ThebesLayer* - ThebesLayers - nrc,bas
gfx/layers/composite/* - CompositeLayers - nrc,nical
gfx/layers/client/* - Client - nrc,nical,bas
gfx/layers/*Image* - nical
gfx/layers/ipc ipc - IPC - nical
gfx/layers/opengl - CompositorOGL - nrc,nical
gfx/2d - bas,nrc
gfx/gl - GLContext - bjacob
dom/* layout/* - DOM - mattwoodrow
2013-04-10 13:20:52 +04:00
|
|
|
}
|
|
|
|
|
2018-02-02 16:57:35 +03:00
|
|
|
void CompositorBridgeParent::ScheduleComposite(
|
|
|
|
LayerTransactionParent* aLayerTree) {
|
2014-03-03 04:59:58 +04:00
|
|
|
ScheduleComposition();
|
|
|
|
}
|
|
|
|
|
2018-03-25 02:06:01 +03:00
|
|
|
bool CompositorBridgeParent::SetTestSampleTime(const LayersId& aId,
|
2016-03-22 21:08:38 +03:00
|
|
|
const TimeStamp& aTime) {
|
2018-01-24 01:20:23 +03:00
|
|
|
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
|
|
|
|
|
2014-03-22 01:59:57 +04:00
|
|
|
if (aTime.IsNull()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-02-02 16:57:35 +03:00
|
|
|
mTestTime = Some(aTime);
|
2019-05-06 20:48:54 +03:00
|
|
|
if (mApzcTreeManager) {
|
|
|
|
mApzcTreeManager->SetTestSampleTime(mTestTime);
|
|
|
|
}
|
2014-03-22 01:59:57 +04:00
|
|
|
|
2018-01-24 01:20:23 +03:00
|
|
|
if (mWrBridge) {
|
2018-02-02 18:48:25 +03:00
|
|
|
mWrBridge->FlushRendering();
|
2018-01-24 01:20:23 +03:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-04-30 21:35:13 +03:00
|
|
|
bool testComposite =
|
|
|
|
mCompositionManager && mCompositorScheduler->NeedsComposite();
|
2014-10-22 02:40:54 +04:00
|
|
|
|
2014-03-22 01:59:57 +04:00
|
|
|
// Update but only if we were already scheduled to animate
|
2014-10-22 02:40:54 +04:00
|
|
|
if (testComposite) {
|
2014-03-22 01:59:57 +04:00
|
|
|
AutoResolveRefLayers resolve(mCompositionManager);
|
2016-07-26 11:57:11 +03:00
|
|
|
bool requestNextFrame =
|
|
|
|
mCompositionManager->TransformShadowTree(aTime, mVsyncRate);
|
2014-03-22 01:59:57 +04:00
|
|
|
if (!requestNextFrame) {
|
|
|
|
CancelCurrentCompositeTask();
|
2014-05-29 01:42:16 +04:00
|
|
|
// Pretend we composited in case someone is wating for this event.
|
2015-08-25 08:51:58 +03:00
|
|
|
TimeStamp now = TimeStamp::Now();
|
2018-12-08 02:28:41 +03:00
|
|
|
DidComposite(VsyncId(), now, now);
|
2014-03-22 01:59:57 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-03-25 02:06:01 +03:00
|
|
|
void CompositorBridgeParent::LeaveTestMode(const LayersId& aId) {
|
2018-02-02 16:57:35 +03:00
|
|
|
mTestTime = Nothing();
|
2019-05-06 20:48:54 +03:00
|
|
|
if (mApzcTreeManager) {
|
|
|
|
mApzcTreeManager->SetTestSampleTime(mTestTime);
|
|
|
|
}
|
2014-03-22 01:59:57 +04:00
|
|
|
}
|
|
|
|
|
2018-06-05 03:18:21 +03:00
|
|
|
void CompositorBridgeParent::ApplyAsyncProperties(
|
|
|
|
LayerTransactionParent* aLayerTree, TransformsToSkip aSkip) {
|
2018-02-02 16:57:35 +03:00
|
|
|
// NOTE: This should only be used for testing. For example, when mTestTime is
|
|
|
|
// non-empty, or when called from test-only methods like
|
Bug 1113425 part 2 - Apply async properties when querying the animated transform; r=mattwoodrow
In order to test off-main thread animations, we have a method that will return
the animated transform value set on a shadow layer. This method will return null
if the transform was not set by animation.
However, in some situations we temporarily clear the animation transform. For
example, when we synchronize a composite layer with its content layer, we reset
the animation transform. Then, on the next composite, we will recalculate the
animated value.
If we try to query the animated transform value in between resetting it and the
next composite we will get back null. To avoid a race condition, in
ShadowLayersUpdated after potentially clearing the animated transform, we
synchronously update the async properties on the layer transform in order
to reinstate the animated transform (so it is there when we go to query it).
However we *only* do this when the mIsTesting flag is set which is true
whenever we have the refresh driver under test control. Furthermore, we only
do it when we already have a pending composite task to better match conditions
under regular operation.
In test_deferred_start.html, however, we specifically need to test without
putting the refresh driver under test control. As a result mIsTesting will be
false and we can encounter a race condition when querying the animated
transform.
To work around this, this patch makes us *also* update async properties
when fetching the animated transform value. The method for getting the
animated transform value is only used for testing so it should have no effect
on the regular compositing behavior.
It would seem that we could then remove the call from ShadowLayersUpdated but
doing this caused a small number of test cases to fail. In particular one test
for *opacity* in test_animations_omta.html was failing at the end of the
animation because we ended up with a stale opacity animation value on the
compositor which the synchronous update was previously removing. The test,
in this case, should be ignoring the value on the compositor but, unlike
transform, there is no flag for indicating whether or not the opacity on shadow
layers has been set by animations. As a result, this patch leaves the call that
triggers a synchronous update in test mode when updating shadow layers.
2015-03-17 12:38:12 +03:00
|
|
|
// LayerTransactionParent::RecvGetAnimationTransform.
|
|
|
|
|
2015-04-25 03:05:52 +03:00
|
|
|
// Synchronously update the layer tree
|
|
|
|
if (aLayerTree->GetRoot()) {
|
Bug 1113425 part 2 - Apply async properties when querying the animated transform; r=mattwoodrow
In order to test off-main thread animations, we have a method that will return
the animated transform value set on a shadow layer. This method will return null
if the transform was not set by animation.
However, in some situations we temporarily clear the animation transform. For
example, when we synchronize a composite layer with its content layer, we reset
the animation transform. Then, on the next composite, we will recalculate the
animated value.
If we try to query the animated transform value in between resetting it and the
next composite we will get back null. To avoid a race condition, in
ShadowLayersUpdated after potentially clearing the animated transform, we
synchronously update the async properties on the layer transform in order
to reinstate the animated transform (so it is there when we go to query it).
However we *only* do this when the mIsTesting flag is set which is true
whenever we have the refresh driver under test control. Furthermore, we only
do it when we already have a pending composite task to better match conditions
under regular operation.
In test_deferred_start.html, however, we specifically need to test without
putting the refresh driver under test control. As a result mIsTesting will be
false and we can encounter a race condition when querying the animated
transform.
To work around this, this patch makes us *also* update async properties
when fetching the animated transform value. The method for getting the
animated transform value is only used for testing so it should have no effect
on the regular compositing behavior.
It would seem that we could then remove the call from ShadowLayersUpdated but
doing this caused a small number of test cases to fail. In particular one test
for *opacity* in test_animations_omta.html was failing at the end of the
animation because we ended up with a stale opacity animation value on the
compositor which the synchronous update was previously removing. The test,
in this case, should be ignoring the value on the compositor but, unlike
transform, there is no flag for indicating whether or not the opacity on shadow
layers has been set by animations. As a result, this patch leaves the call that
triggers a synchronous update in test mode when updating shadow layers.
2015-03-17 12:38:12 +03:00
|
|
|
AutoResolveRefLayers resolve(mCompositionManager);
|
2015-04-25 03:05:52 +03:00
|
|
|
SetShadowProperties(mLayerManager->GetRoot());
|
|
|
|
|
2018-02-02 16:57:35 +03:00
|
|
|
TimeStamp time =
|
|
|
|
mTestTime.valueOr(mCompositorScheduler->GetLastComposeTime());
|
Bug 1113425 part 2 - Apply async properties when querying the animated transform; r=mattwoodrow
In order to test off-main thread animations, we have a method that will return
the animated transform value set on a shadow layer. This method will return null
if the transform was not set by animation.
However, in some situations we temporarily clear the animation transform. For
example, when we synchronize a composite layer with its content layer, we reset
the animation transform. Then, on the next composite, we will recalculate the
animated value.
If we try to query the animated transform value in between resetting it and the
next composite we will get back null. To avoid a race condition, in
ShadowLayersUpdated after potentially clearing the animated transform, we
synchronously update the async properties on the layer transform in order
to reinstate the animated transform (so it is there when we go to query it).
However we *only* do this when the mIsTesting flag is set which is true
whenever we have the refresh driver under test control. Furthermore, we only
do it when we already have a pending composite task to better match conditions
under regular operation.
In test_deferred_start.html, however, we specifically need to test without
putting the refresh driver under test control. As a result mIsTesting will be
false and we can encounter a race condition when querying the animated
transform.
To work around this, this patch makes us *also* update async properties
when fetching the animated transform value. The method for getting the
animated transform value is only used for testing so it should have no effect
on the regular compositing behavior.
It would seem that we could then remove the call from ShadowLayersUpdated but
doing this caused a small number of test cases to fail. In particular one test
for *opacity* in test_animations_omta.html was failing at the end of the
animation because we ended up with a stale opacity animation value on the
compositor which the synchronous update was previously removing. The test,
in this case, should be ignoring the value on the compositor but, unlike
transform, there is no flag for indicating whether or not the opacity on shadow
layers has been set by animations. As a result, this patch leaves the call that
triggers a synchronous update in test mode when updating shadow layers.
2015-03-17 12:38:12 +03:00
|
|
|
bool requestNextFrame =
|
2018-06-05 03:18:21 +03:00
|
|
|
mCompositionManager->TransformShadowTree(time, mVsyncRate, aSkip);
|
Bug 1113425 part 2 - Apply async properties when querying the animated transform; r=mattwoodrow
In order to test off-main thread animations, we have a method that will return
the animated transform value set on a shadow layer. This method will return null
if the transform was not set by animation.
However, in some situations we temporarily clear the animation transform. For
example, when we synchronize a composite layer with its content layer, we reset
the animation transform. Then, on the next composite, we will recalculate the
animated value.
If we try to query the animated transform value in between resetting it and the
next composite we will get back null. To avoid a race condition, in
ShadowLayersUpdated after potentially clearing the animated transform, we
synchronously update the async properties on the layer transform in order
to reinstate the animated transform (so it is there when we go to query it).
However we *only* do this when the mIsTesting flag is set which is true
whenever we have the refresh driver under test control. Furthermore, we only
do it when we already have a pending composite task to better match conditions
under regular operation.
In test_deferred_start.html, however, we specifically need to test without
putting the refresh driver under test control. As a result mIsTesting will be
false and we can encounter a race condition when querying the animated
transform.
To work around this, this patch makes us *also* update async properties
when fetching the animated transform value. The method for getting the
animated transform value is only used for testing so it should have no effect
on the regular compositing behavior.
It would seem that we could then remove the call from ShadowLayersUpdated but
doing this caused a small number of test cases to fail. In particular one test
for *opacity* in test_animations_omta.html was failing at the end of the
animation because we ended up with a stale opacity animation value on the
compositor which the synchronous update was previously removing. The test,
in this case, should be ignoring the value on the compositor but, unlike
transform, there is no flag for indicating whether or not the opacity on shadow
layers has been set by animations. As a result, this patch leaves the call that
triggers a synchronous update in test mode when updating shadow layers.
2015-03-17 12:38:12 +03:00
|
|
|
if (!requestNextFrame) {
|
|
|
|
CancelCurrentCompositeTask();
|
|
|
|
// Pretend we composited in case someone is waiting for this event.
|
2015-08-25 08:51:58 +03:00
|
|
|
TimeStamp now = TimeStamp::Now();
|
2018-12-08 02:28:41 +03:00
|
|
|
DidComposite(VsyncId(), now, now);
|
Bug 1113425 part 2 - Apply async properties when querying the animated transform; r=mattwoodrow
In order to test off-main thread animations, we have a method that will return
the animated transform value set on a shadow layer. This method will return null
if the transform was not set by animation.
However, in some situations we temporarily clear the animation transform. For
example, when we synchronize a composite layer with its content layer, we reset
the animation transform. Then, on the next composite, we will recalculate the
animated value.
If we try to query the animated transform value in between resetting it and the
next composite we will get back null. To avoid a race condition, in
ShadowLayersUpdated after potentially clearing the animated transform, we
synchronously update the async properties on the layer transform in order
to reinstate the animated transform (so it is there when we go to query it).
However we *only* do this when the mIsTesting flag is set which is true
whenever we have the refresh driver under test control. Furthermore, we only
do it when we already have a pending composite task to better match conditions
under regular operation.
In test_deferred_start.html, however, we specifically need to test without
putting the refresh driver under test control. As a result mIsTesting will be
false and we can encounter a race condition when querying the animated
transform.
To work around this, this patch makes us *also* update async properties
when fetching the animated transform value. The method for getting the
animated transform value is only used for testing so it should have no effect
on the regular compositing behavior.
It would seem that we could then remove the call from ShadowLayersUpdated but
doing this caused a small number of test cases to fail. In particular one test
for *opacity* in test_animations_omta.html was failing at the end of the
animation because we ended up with a stale opacity animation value on the
compositor which the synchronous update was previously removing. The test,
in this case, should be ignoring the value on the compositor but, unlike
transform, there is no flag for indicating whether or not the opacity on shadow
layers has been set by animations. As a result, this patch leaves the call that
triggers a synchronous update in test mode when updating shadow layers.
2015-03-17 12:38:12 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-10 04:03:12 +03:00
|
|
|
CompositorAnimationStorage* CompositorBridgeParent::GetAnimationStorage() {
|
2017-02-10 01:30:11 +03:00
|
|
|
if (!mAnimationStorage) {
|
|
|
|
mAnimationStorage = new CompositorAnimationStorage();
|
|
|
|
}
|
|
|
|
return mAnimationStorage;
|
|
|
|
}
|
|
|
|
|
2016-03-22 21:08:38 +03:00
|
|
|
mozilla::ipc::IPCResult CompositorBridgeParent::RecvGetFrameUniformity(
|
|
|
|
FrameUniformityData* aOutData) {
|
2015-06-08 19:53:41 +03:00
|
|
|
mCompositionManager->GetFrameUniformity(aOutData);
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2015-06-08 19:53:41 +03:00
|
|
|
}
|
|
|
|
|
2018-03-06 18:25:37 +03:00
|
|
|
void CompositorBridgeParent::SetTestAsyncScrollOffset(
|
2019-03-22 21:28:42 +03:00
|
|
|
const WRRootId& aWrRootId, const ScrollableLayerGuid::ViewID& aScrollId,
|
2018-03-06 18:25:37 +03:00
|
|
|
const CSSPoint& aPoint) {
|
2018-03-29 01:36:42 +03:00
|
|
|
if (mApzUpdater) {
|
2019-03-22 21:28:42 +03:00
|
|
|
MOZ_ASSERT(aWrRootId.IsValid());
|
|
|
|
mApzUpdater->SetTestAsyncScrollOffset(aWrRootId, aScrollId, aPoint);
|
2018-03-06 18:25:37 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CompositorBridgeParent::SetTestAsyncZoom(
|
2019-03-22 21:28:42 +03:00
|
|
|
const WRRootId& aWrRootId, const ScrollableLayerGuid::ViewID& aScrollId,
|
2018-03-06 18:25:37 +03:00
|
|
|
const LayerToParentLayerScale& aZoom) {
|
2018-03-29 01:36:42 +03:00
|
|
|
if (mApzUpdater) {
|
2019-03-22 21:28:42 +03:00
|
|
|
MOZ_ASSERT(aWrRootId.IsValid());
|
|
|
|
mApzUpdater->SetTestAsyncZoom(aWrRootId, aScrollId, aZoom);
|
2018-03-06 18:25:37 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-22 21:28:42 +03:00
|
|
|
void CompositorBridgeParent::FlushApzRepaints(const WRRootId& aWrRootId) {
|
2018-04-20 21:27:35 +03:00
|
|
|
MOZ_ASSERT(mApzUpdater);
|
2019-03-22 21:28:42 +03:00
|
|
|
MOZ_ASSERT(aWrRootId.IsValid());
|
2018-04-20 21:27:35 +03:00
|
|
|
mApzUpdater->RunOnControllerThread(
|
2019-03-22 21:28:42 +03:00
|
|
|
UpdaterQueueSelector(aWrRootId),
|
|
|
|
NS_NewRunnableFunction(
|
|
|
|
"layers::CompositorBridgeParent::FlushApzRepaints",
|
|
|
|
[=]() { APZCTreeManager::FlushApzRepaints(aWrRootId.mLayersId); }));
|
2015-06-19 15:25:41 +03:00
|
|
|
}
|
|
|
|
|
2019-03-22 21:28:42 +03:00
|
|
|
void CompositorBridgeParent::GetAPZTestData(const WRRootId& aWrRootId,
|
2016-03-22 21:08:38 +03:00
|
|
|
APZTestData* aOutData) {
|
2018-03-29 01:36:42 +03:00
|
|
|
if (mApzUpdater) {
|
2019-03-22 21:28:42 +03:00
|
|
|
MOZ_ASSERT(aWrRootId.IsValid());
|
|
|
|
mApzUpdater->GetAPZTestData(aWrRootId, aOutData);
|
2018-03-02 07:00:40 +03:00
|
|
|
}
|
2014-05-08 03:56:48 +04:00
|
|
|
}
|
|
|
|
|
2018-03-25 02:06:01 +03:00
|
|
|
void CompositorBridgeParent::SetConfirmedTargetAPZC(
|
2017-05-28 14:51:48 +03:00
|
|
|
const LayersId& aLayersId, const uint64_t& aInputBlockId,
|
2019-03-22 21:28:42 +03:00
|
|
|
const nsTArray<SLGuidAndRenderRoot>& aTargets) {
|
2018-04-20 21:27:35 +03:00
|
|
|
if (!mApzcTreeManager || !mApzUpdater) {
|
2015-04-14 19:24:32 +03:00
|
|
|
return;
|
|
|
|
}
|
2016-09-24 00:14:01 +03:00
|
|
|
// Need to specifically bind this since it's overloaded.
|
|
|
|
void (APZCTreeManager::*setTargetApzcFunc)(
|
2019-03-22 21:28:42 +03:00
|
|
|
uint64_t, const nsTArray<SLGuidAndRenderRoot>&) =
|
2016-09-24 00:14:01 +03:00
|
|
|
&APZCTreeManager::SetTargetAPZC;
|
2017-06-12 22:34:10 +03:00
|
|
|
RefPtr<Runnable> task = NewRunnableMethod<
|
2019-03-22 21:28:42 +03:00
|
|
|
uint64_t, StoreCopyPassByConstLRef<nsTArray<SLGuidAndRenderRoot>>>(
|
2017-06-12 22:34:10 +03:00
|
|
|
"layers::CompositorBridgeParent::SetConfirmedTargetAPZC",
|
|
|
|
mApzcTreeManager.get(), setTargetApzcFunc, aInputBlockId, aTargets);
|
2019-03-22 21:28:42 +03:00
|
|
|
UpdaterQueueSelector selector(aLayersId);
|
|
|
|
for (size_t i = 0; i < aTargets.Length(); i++) {
|
|
|
|
selector.mRenderRoots += aTargets[i].mRenderRoot;
|
|
|
|
}
|
|
|
|
mApzUpdater->RunOnControllerThread(selector, task.forget());
|
2015-04-14 19:24:32 +03:00
|
|
|
}
|
2014-05-08 03:56:48 +04:00
|
|
|
|
2016-03-22 21:08:38 +03:00
|
|
|
void CompositorBridgeParent::InitializeLayerManager(
|
|
|
|
const nsTArray<LayersBackend>& aBackendHints) {
|
2013-08-18 10:46:16 +04:00
|
|
|
NS_ASSERTION(!mLayerManager, "Already initialised mLayerManager");
|
2013-12-11 07:51:00 +04:00
|
|
|
NS_ASSERTION(!mCompositor, "Already initialised mCompositor");
|
2013-08-18 10:46:16 +04:00
|
|
|
|
2017-06-24 00:23:12 +03:00
|
|
|
if (!InitializeAdvancedLayers(aBackendHints, nullptr)) {
|
|
|
|
mCompositor = NewCompositor(aBackendHints);
|
|
|
|
if (!mCompositor) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
mLayerManager = new LayerManagerComposite(mCompositor);
|
2016-02-29 09:53:14 +03:00
|
|
|
}
|
2017-06-20 11:17:20 +03:00
|
|
|
mLayerManager->SetCompositorBridgeID(mCompositorBridgeID);
|
2016-02-29 09:53:14 +03:00
|
|
|
|
|
|
|
MonitorAutoLock lock(*sIndirectLayerTreesLock);
|
|
|
|
sIndirectLayerTrees[mRootLayerTreeID].mLayerManager = mLayerManager;
|
|
|
|
}
|
|
|
|
|
2017-06-24 00:23:12 +03:00
|
|
|
bool CompositorBridgeParent::InitializeAdvancedLayers(
|
|
|
|
const nsTArray<LayersBackend>& aBackendHints,
|
|
|
|
TextureFactoryIdentifier* aOutIdentifier) {
|
|
|
|
#ifdef XP_WIN
|
|
|
|
if (!mOptions.UseAdvancedLayers()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-07-07 04:29:38 +03:00
|
|
|
// Currently LayerManagerMLGPU hardcodes a D3D11 device, so we reject using
|
|
|
|
// AL if LAYERS_D3D11 isn't in the backend hints.
|
|
|
|
if (!aBackendHints.Contains(LayersBackend::LAYERS_D3D11)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-06-24 00:23:12 +03:00
|
|
|
RefPtr<LayerManagerMLGPU> manager = new LayerManagerMLGPU(mWidget);
|
|
|
|
if (!manager->Initialize()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aOutIdentifier) {
|
|
|
|
*aOutIdentifier = manager->GetTextureFactoryIdentifier();
|
|
|
|
}
|
|
|
|
mLayerManager = manager;
|
|
|
|
return true;
|
|
|
|
#else
|
|
|
|
return false;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2016-03-22 21:08:38 +03:00
|
|
|
RefPtr<Compositor> CompositorBridgeParent::NewCompositor(
|
|
|
|
const nsTArray<LayersBackend>& aBackendHints) {
|
2013-08-18 10:46:16 +04:00
|
|
|
for (size_t i = 0; i < aBackendHints.Length(); ++i) {
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<Compositor> compositor;
|
2014-01-23 22:26:41 +04:00
|
|
|
if (aBackendHints[i] == LayersBackend::LAYERS_OPENGL) {
|
2016-03-25 11:38:55 +03:00
|
|
|
compositor =
|
|
|
|
new CompositorOGL(this, mWidget, mEGLSurfaceSize.width,
|
2013-12-09 05:40:58 +04:00
|
|
|
mEGLSurfaceSize.height, mUseExternalSurfaceSize);
|
2014-01-23 22:26:41 +04:00
|
|
|
} else if (aBackendHints[i] == LayersBackend::LAYERS_BASIC) {
|
2014-07-23 03:02:25 +04:00
|
|
|
#ifdef MOZ_WIDGET_GTK
|
2016-08-04 21:33:44 +03:00
|
|
|
if (gfxVars::UseXRender()) {
|
2016-07-01 11:15:16 +03:00
|
|
|
compositor = new X11BasicCompositor(this, mWidget);
|
2014-07-23 03:02:25 +04:00
|
|
|
} else
|
|
|
|
#endif
|
|
|
|
{
|
2016-07-01 11:15:16 +03:00
|
|
|
compositor = new BasicCompositor(this, mWidget);
|
2014-07-23 03:02:25 +04:00
|
|
|
}
|
2013-08-18 10:46:16 +04:00
|
|
|
#ifdef XP_WIN
|
2014-01-23 22:26:41 +04:00
|
|
|
} else if (aBackendHints[i] == LayersBackend::LAYERS_D3D11) {
|
2016-07-01 11:15:16 +03:00
|
|
|
compositor = new CompositorD3D11(this, mWidget);
|
2013-08-18 10:46:16 +04:00
|
|
|
#endif
|
|
|
|
}
|
2016-07-05 22:41:21 +03:00
|
|
|
nsCString failureReason;
|
2018-01-22 13:41:56 +03:00
|
|
|
|
|
|
|
// Some software GPU emulation implementations will happily try to create
|
|
|
|
// unreasonably big surfaces and then fail in awful ways.
|
|
|
|
// Let's at least limit this to the default max texture size we use for
|
|
|
|
// content, anything larger than that will fail to render on the content
|
|
|
|
// side anyway. We can revisit this value and make it even tighter if need
|
|
|
|
// be.
|
|
|
|
const int max_fb_size = 32767;
|
|
|
|
const LayoutDeviceIntSize size = mWidget->GetClientSize();
|
|
|
|
if (size.width > max_fb_size || size.height > max_fb_size) {
|
|
|
|
failureReason = "FEATURE_FAILURE_MAX_FRAMEBUFFER_SIZE";
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2017-11-03 10:38:34 +03:00
|
|
|
MOZ_ASSERT(!gfxVars::UseWebRender() ||
|
|
|
|
aBackendHints[i] == LayersBackend::LAYERS_BASIC);
|
2016-07-05 22:41:21 +03:00
|
|
|
if (compositor && compositor->Initialize(&failureReason)) {
|
|
|
|
if (failureReason.IsEmpty()) {
|
|
|
|
failureReason = "SUCCESS";
|
|
|
|
}
|
2016-07-29 18:41:33 +03:00
|
|
|
|
|
|
|
// should only report success here
|
|
|
|
if (aBackendHints[i] == LayersBackend::LAYERS_OPENGL) {
|
2016-07-05 22:41:21 +03:00
|
|
|
Telemetry::Accumulate(Telemetry::OPENGL_COMPOSITING_FAILURE_ID,
|
|
|
|
failureReason);
|
|
|
|
}
|
|
|
|
#ifdef XP_WIN
|
2016-07-29 18:41:33 +03:00
|
|
|
else if (aBackendHints[i] == LayersBackend::LAYERS_D3D11) {
|
2016-07-05 22:41:21 +03:00
|
|
|
Telemetry::Accumulate(Telemetry::D3D11_COMPOSITING_FAILURE_ID,
|
|
|
|
failureReason);
|
|
|
|
}
|
|
|
|
#endif
|
2016-07-29 18:41:33 +03:00
|
|
|
|
2016-02-29 09:53:14 +03:00
|
|
|
return compositor;
|
2013-08-18 10:46:16 +04:00
|
|
|
}
|
2016-07-29 18:41:33 +03:00
|
|
|
|
|
|
|
// report any failure reasons here
|
|
|
|
if (aBackendHints[i] == LayersBackend::LAYERS_OPENGL) {
|
2016-10-23 03:28:00 +03:00
|
|
|
gfxCriticalNote << "[OPENGL] Failed to init compositor with reason: "
|
|
|
|
<< failureReason.get();
|
2016-07-29 18:41:33 +03:00
|
|
|
Telemetry::Accumulate(Telemetry::OPENGL_COMPOSITING_FAILURE_ID,
|
|
|
|
failureReason);
|
|
|
|
}
|
|
|
|
#ifdef XP_WIN
|
|
|
|
else if (aBackendHints[i] == LayersBackend::LAYERS_D3D11) {
|
2016-10-23 03:28:00 +03:00
|
|
|
gfxCriticalNote << "[D3D11] Failed to init compositor with reason: "
|
|
|
|
<< failureReason.get();
|
2016-07-29 18:41:33 +03:00
|
|
|
Telemetry::Accumulate(Telemetry::D3D11_COMPOSITING_FAILURE_ID,
|
|
|
|
failureReason);
|
|
|
|
}
|
|
|
|
#endif
|
2013-08-18 10:46:16 +04:00
|
|
|
}
|
2016-02-29 09:53:14 +03:00
|
|
|
|
|
|
|
return nullptr;
|
2013-08-18 10:46:16 +04:00
|
|
|
}
|
|
|
|
|
2016-03-22 21:08:38 +03:00
|
|
|
PLayerTransactionParent* CompositorBridgeParent::AllocPLayerTransactionParent(
|
|
|
|
const nsTArray<LayersBackend>& aBackendHints, const LayersId& aId) {
|
2018-03-25 02:06:01 +03:00
|
|
|
MOZ_ASSERT(!aId.IsValid());
|
2012-07-18 03:59:45 +04:00
|
|
|
|
2019-05-10 01:10:35 +03:00
|
|
|
#ifdef XP_WIN
|
|
|
|
// This is needed to avoid freezing the window on a device crash on double
|
|
|
|
// buffering, see bug 1549674.
|
2019-07-09 09:37:45 +03:00
|
|
|
if (gfxVars::UseDoubleBufferingWithCompositor() && XRE_IsGPUProcess()) {
|
2019-05-10 01:10:35 +03:00
|
|
|
mWidget->AsWindows()->EnsureCompositorWindow();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2013-08-18 10:46:16 +04:00
|
|
|
InitializeLayerManager(aBackendHints);
|
2013-05-01 04:42:05 +04:00
|
|
|
|
2013-08-18 10:46:16 +04:00
|
|
|
if (!mLayerManager) {
|
|
|
|
NS_WARNING("Failed to initialise Compositor");
|
2018-06-26 21:40:10 +03:00
|
|
|
LayerTransactionParent* p = new LayerTransactionParent(
|
|
|
|
/* aManager */ nullptr, this, /* aAnimStorage */ nullptr,
|
|
|
|
mRootLayerTreeID, mVsyncRate);
|
2013-11-27 19:18:38 +04:00
|
|
|
p->AddIPDLReference();
|
|
|
|
return p;
|
2013-05-01 04:42:05 +04:00
|
|
|
}
|
|
|
|
|
2017-02-10 01:30:11 +03:00
|
|
|
mCompositionManager = new AsyncCompositionManager(this, mLayerManager);
|
2013-05-01 04:42:05 +04:00
|
|
|
|
2018-06-26 21:40:10 +03:00
|
|
|
LayerTransactionParent* p = new LayerTransactionParent(
|
|
|
|
mLayerManager, this, GetAnimationStorage(), mRootLayerTreeID, mVsyncRate);
|
2013-11-27 19:18:38 +04:00
|
|
|
p->AddIPDLReference();
|
|
|
|
return p;
|
2011-12-16 00:07:19 +04:00
|
|
|
}
|
|
|
|
|
2016-03-22 21:08:38 +03:00
|
|
|
bool CompositorBridgeParent::DeallocPLayerTransactionParent(
|
|
|
|
PLayerTransactionParent* actor) {
|
2013-11-27 19:18:38 +04:00
|
|
|
static_cast<LayerTransactionParent*>(actor)->ReleaseIPDLReference();
|
2011-12-16 00:07:19 +04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-06-22 03:58:55 +03:00
|
|
|
CompositorBridgeParent* CompositorBridgeParent::GetCompositorBridgeParent(
|
|
|
|
uint64_t id) {
|
2018-09-11 17:50:30 +03:00
|
|
|
AssertIsInCompositorThread();
|
2012-07-13 23:38:09 +04:00
|
|
|
CompositorMap::iterator it = sCompositorMap->find(id);
|
2012-07-30 18:20:58 +04:00
|
|
|
return it != sCompositorMap->end() ? it->second : nullptr;
|
2012-07-13 23:38:09 +04:00
|
|
|
}
|
|
|
|
|
2016-03-22 21:08:38 +03:00
|
|
|
void CompositorBridgeParent::AddCompositor(CompositorBridgeParent* compositor,
|
|
|
|
uint64_t* outID) {
|
2018-09-11 17:50:30 +03:00
|
|
|
AssertIsInCompositorThread();
|
2018-03-08 11:56:11 +03:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
static uint64_t sNextID = 1;
|
Bug 825928: Land layers refactoring. r=jrmuizel,bas,nical,mattwoodrow,roc,nrc,benwa,bjacob,jgilbert,kchen CLOSED TREE
Please contact Bas Schouten <bschouten@mozilla.com>, Nicolas Silva <nsilva@mozilla.com> or Nicholas Cameron <ncameron@mozilla.com> with general questions. Below is a rough list of authors to contact with specific questions.
Authors:
gfx/layers/Compositor.* gfx/layers/Effects.h - Compositor Interface - bas,nrc,nical
gfx/layers/d3d* - D3D9/D3D10 - bas
gfx/layers/ThebesLayer* - ThebesLayers - nrc,bas
gfx/layers/composite/* - CompositeLayers - nrc,nical
gfx/layers/client/* - Client - nrc,nical,bas
gfx/layers/*Image* - nical
gfx/layers/ipc ipc - IPC - nical
gfx/layers/opengl - CompositorOGL - nrc,nical
gfx/2d - bas,nrc
gfx/gl - GLContext - bjacob
dom/* layout/* - DOM - mattwoodrow
2013-04-10 13:20:52 +04:00
|
|
|
|
2012-07-13 23:38:09 +04:00
|
|
|
++sNextID;
|
|
|
|
(*sCompositorMap)[sNextID] = compositor;
|
|
|
|
*outID = sNextID;
|
|
|
|
}
|
|
|
|
|
2016-03-22 21:08:38 +03:00
|
|
|
CompositorBridgeParent* CompositorBridgeParent::RemoveCompositor(uint64_t id) {
|
2018-09-11 17:50:30 +03:00
|
|
|
AssertIsInCompositorThread();
|
2018-03-08 11:56:11 +03:00
|
|
|
|
2012-07-13 23:38:09 +04:00
|
|
|
CompositorMap::iterator it = sCompositorMap->find(id);
|
|
|
|
if (it == sCompositorMap->end()) {
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2012-07-13 23:38:09 +04:00
|
|
|
}
|
2016-03-22 21:08:38 +03:00
|
|
|
CompositorBridgeParent* retval = it->second;
|
2012-07-13 23:38:09 +04:00
|
|
|
sCompositorMap->erase(it);
|
Bug 825928: Land layers refactoring. r=jrmuizel,bas,nical,mattwoodrow,roc,nrc,benwa,bjacob,jgilbert,kchen CLOSED TREE
Please contact Bas Schouten <bschouten@mozilla.com>, Nicolas Silva <nsilva@mozilla.com> or Nicholas Cameron <ncameron@mozilla.com> with general questions. Below is a rough list of authors to contact with specific questions.
Authors:
gfx/layers/Compositor.* gfx/layers/Effects.h - Compositor Interface - bas,nrc,nical
gfx/layers/d3d* - D3D9/D3D10 - bas
gfx/layers/ThebesLayer* - ThebesLayers - nrc,bas
gfx/layers/composite/* - CompositeLayers - nrc,nical
gfx/layers/client/* - Client - nrc,nical,bas
gfx/layers/*Image* - nical
gfx/layers/ipc ipc - IPC - nical
gfx/layers/opengl - CompositorOGL - nrc,nical
gfx/2d - bas,nrc
gfx/gl - GLContext - bjacob
dom/* layout/* - DOM - mattwoodrow
2013-04-10 13:20:52 +04:00
|
|
|
return retval;
|
2012-07-13 23:38:09 +04:00
|
|
|
}
|
|
|
|
|
2018-12-08 02:27:28 +03:00
|
|
|
void CompositorBridgeParent::NotifyVsync(const VsyncEvent& aVsync,
|
2018-03-25 02:06:01 +03:00
|
|
|
const LayersId& aLayersId) {
|
2016-07-19 21:56:07 +03:00
|
|
|
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_GPU);
|
|
|
|
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
|
|
|
|
|
|
|
|
MonitorAutoLock lock(*sIndirectLayerTreesLock);
|
|
|
|
auto it = sIndirectLayerTrees.find(aLayersId);
|
|
|
|
if (it == sIndirectLayerTrees.end()) return;
|
|
|
|
|
|
|
|
CompositorBridgeParent* cbp = it->second.mParent;
|
|
|
|
if (!cbp || !cbp->mWidget) return;
|
|
|
|
|
|
|
|
RefPtr<VsyncObserver> obs = cbp->mWidget->GetVsyncObserver();
|
|
|
|
if (!obs) return;
|
|
|
|
|
2018-12-08 02:27:28 +03:00
|
|
|
obs->NotifyVsync(aVsync);
|
2016-07-19 21:56:07 +03:00
|
|
|
}
|
|
|
|
|
2018-03-25 02:06:01 +03:00
|
|
|
mozilla::ipc::IPCResult CompositorBridgeParent::RecvNotifyChildCreated(
|
2017-04-10 00:30:27 +03:00
|
|
|
const LayersId& child, CompositorOptions* aOptions) {
|
2015-01-17 18:25:57 +03:00
|
|
|
MonitorAutoLock lock(*sIndirectLayerTreesLock);
|
2013-07-12 06:32:09 +04:00
|
|
|
NotifyChildCreated(child);
|
2017-04-10 00:30:27 +03:00
|
|
|
*aOptions = mOptions;
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2013-07-12 06:32:09 +04:00
|
|
|
}
|
|
|
|
|
2018-03-25 02:06:01 +03:00
|
|
|
mozilla::ipc::IPCResult CompositorBridgeParent::RecvNotifyChildRecreated(
|
2017-04-10 00:30:27 +03:00
|
|
|
const LayersId& aChild, CompositorOptions* aOptions) {
|
2016-09-20 11:19:32 +03:00
|
|
|
MonitorAutoLock lock(*sIndirectLayerTreesLock);
|
|
|
|
|
|
|
|
if (sIndirectLayerTrees.find(aChild) != sIndirectLayerTrees.end()) {
|
2017-11-01 05:58:10 +03:00
|
|
|
NS_WARNING("Invalid to register the same layer tree twice");
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_FAIL_NO_REASON(this);
|
2016-09-20 11:19:32 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
NotifyChildCreated(aChild);
|
2017-04-10 00:30:27 +03:00
|
|
|
*aOptions = mOptions;
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2016-09-20 11:19:32 +03:00
|
|
|
}
|
|
|
|
|
2018-03-25 02:06:01 +03:00
|
|
|
void CompositorBridgeParent::NotifyChildCreated(LayersId aChild) {
|
2015-01-17 18:25:57 +03:00
|
|
|
sIndirectLayerTreesLock->AssertCurrentThreadOwns();
|
2013-07-12 06:32:09 +04:00
|
|
|
sIndirectLayerTrees[aChild].mParent = this;
|
2013-12-09 05:40:58 +04:00
|
|
|
sIndirectLayerTrees[aChild].mLayerManager = mLayerManager;
|
2013-07-12 06:32:09 +04:00
|
|
|
}
|
|
|
|
|
2018-03-25 02:06:01 +03:00
|
|
|
mozilla::ipc::IPCResult CompositorBridgeParent::RecvMapAndNotifyChildCreated(
|
2017-04-10 00:30:27 +03:00
|
|
|
const LayersId& aChild, const base::ProcessId& aOwnerPid,
|
|
|
|
CompositorOptions* aOptions) {
|
2017-04-04 01:13:37 +03:00
|
|
|
// We only use this message when the remote compositor is in the GPU process.
|
|
|
|
// It is harmless to call it, though.
|
|
|
|
MOZ_ASSERT(XRE_IsGPUProcess());
|
|
|
|
|
|
|
|
LayerTreeOwnerTracker::Get()->Map(aChild, aOwnerPid);
|
|
|
|
|
|
|
|
MonitorAutoLock lock(*sIndirectLayerTreesLock);
|
|
|
|
NotifyChildCreated(aChild);
|
2017-04-10 00:30:27 +03:00
|
|
|
*aOptions = mOptions;
|
2017-04-04 01:13:37 +03:00
|
|
|
return IPC_OK();
|
|
|
|
}
|
|
|
|
|
2018-03-25 02:06:01 +03:00
|
|
|
mozilla::ipc::IPCResult CompositorBridgeParent::RecvAdoptChild(
|
|
|
|
const LayersId& child) {
|
2018-03-29 01:36:42 +03:00
|
|
|
RefPtr<APZUpdater> oldApzUpdater;
|
2016-07-31 22:39:00 +03:00
|
|
|
APZCTreeManagerParent* parent;
|
2018-05-09 22:23:30 +03:00
|
|
|
bool scheduleComposition = false;
|
2019-03-04 00:02:25 +03:00
|
|
|
RefPtr<ContentCompositorBridgeParent> cpcp;
|
2018-05-09 22:23:30 +03:00
|
|
|
RefPtr<WebRenderBridgeParent> childWrBridge;
|
|
|
|
|
2019-08-20 09:38:00 +03:00
|
|
|
// Before adopting the child, save the old compositor's root content
|
|
|
|
// controller. We may need this to clear old layer transforms associated
|
|
|
|
// with the child.
|
|
|
|
// This is outside the lock because GetGeckoContentControllerForRoot()
|
|
|
|
// does its own locking.
|
|
|
|
RefPtr<GeckoContentController> oldRootController =
|
|
|
|
GetGeckoContentControllerForRoot(child);
|
|
|
|
|
2018-05-09 22:23:30 +03:00
|
|
|
{ // scope lock
|
2016-01-08 22:17:39 +03:00
|
|
|
MonitorAutoLock lock(*sIndirectLayerTreesLock);
|
2018-09-20 12:01:43 +03:00
|
|
|
// If child is already belong to this CompositorBridgeParent,
|
|
|
|
// no need to handle adopting child.
|
|
|
|
if (sIndirectLayerTrees[child].mParent == this) {
|
|
|
|
return IPC_OK();
|
|
|
|
}
|
|
|
|
|
2018-03-20 17:01:27 +03:00
|
|
|
if (sIndirectLayerTrees[child].mParent) {
|
|
|
|
// We currently don't support adopting children from one compositor to
|
|
|
|
// another if the two compositors don't have the same options.
|
|
|
|
MOZ_ASSERT(sIndirectLayerTrees[child].mParent->mOptions == mOptions);
|
2018-03-29 01:36:42 +03:00
|
|
|
oldApzUpdater = sIndirectLayerTrees[child].mParent->mApzUpdater;
|
2018-03-20 17:01:27 +03:00
|
|
|
}
|
2016-01-08 22:17:39 +03:00
|
|
|
NotifyChildCreated(child);
|
|
|
|
if (sIndirectLayerTrees[child].mLayerTree) {
|
2017-07-10 04:03:12 +03:00
|
|
|
sIndirectLayerTrees[child].mLayerTree->SetLayerManager(
|
|
|
|
mLayerManager, GetAnimationStorage());
|
2017-06-28 00:56:16 +03:00
|
|
|
// Trigger composition to handle a case that mLayerTree was not composited
|
|
|
|
// yet by previous CompositorBridgeParent, since nsRefreshDriver might
|
|
|
|
// wait composition complete.
|
2018-05-09 22:23:30 +03:00
|
|
|
scheduleComposition = true;
|
2016-01-08 22:17:39 +03:00
|
|
|
}
|
2018-05-09 22:23:30 +03:00
|
|
|
if (mWrBridge) {
|
|
|
|
childWrBridge = sIndirectLayerTrees[child].mWrBridge;
|
2019-03-05 04:37:37 +03:00
|
|
|
cpcp = sIndirectLayerTrees[child].mContentCompositorBridgeParent;
|
2017-06-30 04:06:11 +03:00
|
|
|
}
|
2016-07-31 22:39:00 +03:00
|
|
|
parent = sIndirectLayerTrees[child].mApzcTreeManagerParent;
|
2014-10-15 02:11:38 +04:00
|
|
|
}
|
2016-01-08 22:17:39 +03:00
|
|
|
|
2018-05-09 22:23:30 +03:00
|
|
|
if (scheduleComposition) {
|
|
|
|
ScheduleComposition();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (childWrBridge) {
|
|
|
|
MOZ_ASSERT(mWrBridge);
|
2019-03-22 21:28:42 +03:00
|
|
|
nsTArray<RefPtr<wr::WebRenderAPI>> apis;
|
|
|
|
DebugOnly<bool> cloneSuccess = mWrBridge->CloneWebRenderAPIs(apis);
|
|
|
|
MOZ_ASSERT(cloneSuccess);
|
2018-07-27 16:42:30 +03:00
|
|
|
wr::Epoch newEpoch = childWrBridge->UpdateWebRender(
|
2019-03-22 21:28:42 +03:00
|
|
|
mWrBridge->CompositorScheduler(), std::move(apis),
|
|
|
|
mWrBridge->AsyncImageManager(), GetAnimationStorage(),
|
|
|
|
mWrBridge->GetTextureFactoryIdentifier());
|
2018-05-09 22:23:30 +03:00
|
|
|
// Pretend we composited, since parent CompositorBridgeParent was replaced.
|
2018-07-27 16:42:30 +03:00
|
|
|
TimeStamp now = TimeStamp::Now();
|
2018-12-08 02:28:41 +03:00
|
|
|
NotifyPipelineRendered(childWrBridge->PipelineId(), newEpoch, VsyncId(),
|
|
|
|
now, now, now);
|
2018-05-09 22:23:30 +03:00
|
|
|
}
|
|
|
|
|
2018-03-29 01:36:42 +03:00
|
|
|
if (oldApzUpdater) {
|
2019-08-20 09:38:00 +03:00
|
|
|
// We don't fully support moving a child from an APZ-enabled compositor to a
|
2018-03-08 00:41:44 +03:00
|
|
|
// APZ-disabled compositor. The mOptions assertion above should already
|
|
|
|
// ensure this, since APZ-ness is one of the things in mOptions. Note
|
2018-03-29 01:36:42 +03:00
|
|
|
// however it is possible for mApzUpdater to be non-null here with
|
|
|
|
// oldApzUpdater null, because the child may not have been previously
|
2018-03-08 00:41:44 +03:00
|
|
|
// composited.
|
2018-03-29 01:36:42 +03:00
|
|
|
MOZ_ASSERT(mApzUpdater);
|
2019-08-20 09:38:00 +03:00
|
|
|
|
|
|
|
// As this nonetheless can happen (if e.g. a WebExtension moves a tab
|
|
|
|
// into a popup window), try to handle it gracefully by clearing the
|
|
|
|
// old layer transforms associated with the child. (Since the new compositor
|
|
|
|
// is APZ-disabled, there will be nothing to update the transforms going
|
|
|
|
// forward.)
|
|
|
|
if (!mApzUpdater && oldRootController) {
|
|
|
|
nsTArray<MatrixMessage> clear;
|
|
|
|
clear.AppendElement(MatrixMessage(Nothing(), child));
|
|
|
|
oldRootController->NotifyLayerTransforms(clear);
|
|
|
|
}
|
2018-03-08 00:41:44 +03:00
|
|
|
}
|
2018-03-29 01:36:42 +03:00
|
|
|
if (mApzUpdater) {
|
2018-03-02 07:00:40 +03:00
|
|
|
if (parent) {
|
2018-03-02 07:00:41 +03:00
|
|
|
MOZ_ASSERT(mApzcTreeManager);
|
2018-03-29 01:36:42 +03:00
|
|
|
parent->ChildAdopted(mApzcTreeManager, mApzUpdater);
|
2018-03-02 07:00:40 +03:00
|
|
|
}
|
2019-03-22 21:28:42 +03:00
|
|
|
mApzUpdater->NotifyLayerTreeAdopted(
|
|
|
|
WRRootId(child, gfxUtils::GetContentRenderRoot()), oldApzUpdater);
|
2014-10-15 02:11:38 +04:00
|
|
|
}
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2014-10-15 02:11:38 +04:00
|
|
|
}
|
|
|
|
|
2017-01-17 23:13:41 +03:00
|
|
|
PWebRenderBridgeParent* CompositorBridgeParent::AllocPWebRenderBridgeParent(
|
2018-10-05 10:35:29 +03:00
|
|
|
const wr::PipelineId& aPipelineId, const LayoutDeviceIntSize& aSize) {
|
2018-03-25 02:06:01 +03:00
|
|
|
MOZ_ASSERT(wr::AsLayersId(aPipelineId) == mRootLayerTreeID);
|
2017-01-17 18:17:38 +03:00
|
|
|
MOZ_ASSERT(!mWrBridge);
|
2016-11-28 04:21:33 +03:00
|
|
|
MOZ_ASSERT(!mCompositor);
|
2016-12-21 05:13:57 +03:00
|
|
|
MOZ_ASSERT(!mCompositorScheduler);
|
2018-03-29 05:21:47 +03:00
|
|
|
MOZ_ASSERT(mWidget);
|
2016-11-16 16:54:51 +03:00
|
|
|
|
2019-02-07 10:01:41 +03:00
|
|
|
#ifdef XP_WIN
|
2019-07-19 12:26:03 +03:00
|
|
|
if (mWidget && (DeviceManagerDx::Get()->CanUseDComp() ||
|
|
|
|
gfxVars::UseWebRenderFlipSequentialWin())) {
|
2019-02-07 10:01:41 +03:00
|
|
|
mWidget->AsWindows()->EnsureCompositorWindow();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2017-02-10 18:16:47 +03:00
|
|
|
RefPtr<widget::CompositorWidget> widget = mWidget;
|
2018-04-10 19:29:55 +03:00
|
|
|
wr::WrWindowId windowId = wr::NewWindowId();
|
2018-04-10 19:29:55 +03:00
|
|
|
if (mApzUpdater) {
|
|
|
|
// If APZ is enabled, we need to register the APZ updater with the window id
|
|
|
|
// before the updater thread is created in WebRenderAPI::Create, so
|
|
|
|
// that the callback from the updater thread can find the right APZUpdater.
|
|
|
|
mApzUpdater->SetWebRenderWindowId(windowId);
|
|
|
|
}
|
2018-04-17 00:39:13 +03:00
|
|
|
if (mApzSampler) {
|
|
|
|
// Same as for mApzUpdater, but for the sampler thread.
|
|
|
|
mApzSampler->SetWebRenderWindowId(windowId);
|
|
|
|
}
|
2019-07-10 07:47:53 +03:00
|
|
|
nsTArray<RefPtr<wr::WebRenderAPI>> apis;
|
2019-03-22 21:28:42 +03:00
|
|
|
apis.AppendElement(
|
|
|
|
wr::WebRenderAPI::Create(this, std::move(widget), windowId, aSize));
|
|
|
|
if (!apis[0]) {
|
2017-08-29 16:41:53 +03:00
|
|
|
mWrBridge = WebRenderBridgeParent::CreateDestroyed(aPipelineId);
|
2017-08-02 16:21:17 +03:00
|
|
|
mWrBridge.get()->AddRef(); // IPDL reference
|
2017-07-28 12:22:21 +03:00
|
|
|
return mWrBridge;
|
|
|
|
}
|
2019-03-22 21:28:42 +03:00
|
|
|
|
2019-07-22 05:10:14 +03:00
|
|
|
if (StaticPrefs::gfx_webrender_split_render_roots_AtStartup()) {
|
2019-03-22 21:28:42 +03:00
|
|
|
apis.AppendElement(
|
|
|
|
apis[0]->CreateDocument(aSize, 1, wr::RenderRoot::Content));
|
2019-06-21 21:15:11 +03:00
|
|
|
apis.AppendElement(
|
|
|
|
apis[0]->CreateDocument(aSize, 2, wr::RenderRoot::Popover));
|
2019-03-22 21:28:42 +03:00
|
|
|
}
|
|
|
|
|
2019-07-10 07:47:53 +03:00
|
|
|
nsTArray<RefPtr<wr::WebRenderAPI>> clonedApis;
|
2019-03-22 21:28:42 +03:00
|
|
|
for (auto& api : apis) {
|
|
|
|
wr::TransactionBuilder txn;
|
|
|
|
txn.SetRootPipeline(aPipelineId);
|
|
|
|
api->SendTransaction(txn);
|
|
|
|
clonedApis.AppendElement(api->Clone());
|
|
|
|
}
|
|
|
|
|
|
|
|
mAsyncImageManager = new AsyncImagePipelineManager(std::move(clonedApis));
|
2017-08-09 15:46:25 +03:00
|
|
|
RefPtr<AsyncImagePipelineManager> asyncMgr = mAsyncImageManager;
|
2017-07-10 04:03:12 +03:00
|
|
|
RefPtr<CompositorAnimationStorage> animStorage = GetAnimationStorage();
|
2018-06-26 21:43:14 +03:00
|
|
|
mWrBridge = new WebRenderBridgeParent(this, aPipelineId, mWidget, nullptr,
|
2019-03-22 21:28:42 +03:00
|
|
|
std::move(apis), std::move(asyncMgr),
|
2018-06-26 21:43:14 +03:00
|
|
|
std::move(animStorage), mVsyncRate);
|
2017-08-02 16:21:17 +03:00
|
|
|
mWrBridge.get()->AddRef(); // IPDL reference
|
2017-01-19 02:46:21 +03:00
|
|
|
|
2017-01-17 18:17:38 +03:00
|
|
|
mCompositorScheduler = mWrBridge->CompositorScheduler();
|
2016-12-21 05:13:57 +03:00
|
|
|
MOZ_ASSERT(mCompositorScheduler);
|
2018-04-26 22:29:21 +03:00
|
|
|
{ // scope lock
|
|
|
|
MonitorAutoLock lock(*sIndirectLayerTreesLock);
|
|
|
|
MOZ_ASSERT(sIndirectLayerTrees[mRootLayerTreeID].mWrBridge == nullptr);
|
|
|
|
sIndirectLayerTrees[mRootLayerTreeID].mWrBridge = mWrBridge;
|
|
|
|
}
|
2017-01-17 18:17:38 +03:00
|
|
|
return mWrBridge;
|
2016-11-16 16:54:51 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bool CompositorBridgeParent::DeallocPWebRenderBridgeParent(
|
|
|
|
PWebRenderBridgeParent* aActor) {
|
|
|
|
WebRenderBridgeParent* parent = static_cast<WebRenderBridgeParent*>(aActor);
|
|
|
|
{
|
|
|
|
MonitorAutoLock lock(*sIndirectLayerTreesLock);
|
2018-03-25 02:06:01 +03:00
|
|
|
auto it = sIndirectLayerTrees.find(wr::AsLayersId(parent->PipelineId()));
|
2016-11-16 16:54:51 +03:00
|
|
|
if (it != sIndirectLayerTrees.end()) {
|
2017-01-17 18:17:38 +03:00
|
|
|
it->second.mWrBridge = nullptr;
|
2016-11-16 16:54:51 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
parent->Release(); // IPDL reference
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-08-20 16:23:54 +03:00
|
|
|
void CompositorBridgeParent::NotifyMemoryPressure() {
|
|
|
|
if (mWrBridge) {
|
2019-03-22 21:28:42 +03:00
|
|
|
RefPtr<wr::WebRenderAPI> api =
|
|
|
|
mWrBridge->GetWebRenderAPI(wr::RenderRoot::Default);
|
2018-08-20 16:23:54 +03:00
|
|
|
if (api) {
|
|
|
|
api->NotifyMemoryPressure();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-08 02:03:13 +03:00
|
|
|
void CompositorBridgeParent::AccumulateMemoryReport(wr::MemoryReport* aReport) {
|
|
|
|
if (mWrBridge) {
|
2019-03-22 21:28:42 +03:00
|
|
|
RefPtr<wr::WebRenderAPI> api =
|
|
|
|
mWrBridge->GetWebRenderAPI(wr::RenderRoot::Default);
|
2018-09-08 02:03:13 +03:00
|
|
|
if (api) {
|
|
|
|
api->AccumulateMemoryReport(aReport);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-12 20:58:17 +03:00
|
|
|
RefPtr<WebRenderBridgeParent> CompositorBridgeParent::GetWebRenderBridgeParent()
|
|
|
|
const {
|
|
|
|
return mWrBridge;
|
|
|
|
}
|
|
|
|
|
2017-06-28 03:29:05 +03:00
|
|
|
Maybe<TimeStamp> CompositorBridgeParent::GetTestingTimeStamp() const {
|
2018-02-02 16:57:35 +03:00
|
|
|
return mTestTime;
|
2017-06-28 03:29:05 +03:00
|
|
|
}
|
|
|
|
|
2018-12-02 17:02:27 +03:00
|
|
|
void EraseLayerState(LayersId aId) {
|
2018-04-10 19:29:54 +03:00
|
|
|
RefPtr<APZUpdater> apz;
|
2016-03-19 04:38:57 +03:00
|
|
|
|
2018-04-10 19:29:54 +03:00
|
|
|
{ // scope lock
|
|
|
|
MonitorAutoLock lock(*sIndirectLayerTreesLock);
|
|
|
|
auto iter = sIndirectLayerTrees.find(aId);
|
|
|
|
if (iter != sIndirectLayerTrees.end()) {
|
|
|
|
CompositorBridgeParent* parent = iter->second.mParent;
|
|
|
|
if (parent) {
|
|
|
|
apz = parent->GetAPZUpdater();
|
2018-03-02 07:00:40 +03:00
|
|
|
}
|
2018-04-10 19:29:54 +03:00
|
|
|
sIndirectLayerTrees.erase(iter);
|
2016-03-19 04:38:57 +03:00
|
|
|
}
|
2018-04-10 19:29:54 +03:00
|
|
|
}
|
2016-03-19 04:38:57 +03:00
|
|
|
|
2018-04-10 19:29:54 +03:00
|
|
|
if (apz) {
|
2019-03-22 21:28:42 +03:00
|
|
|
apz->NotifyLayerTreeRemoved(
|
|
|
|
WRRootId(aId, gfxUtils::GetContentRenderRoot()));
|
2016-03-19 04:38:57 +03:00
|
|
|
}
|
2012-07-20 10:48:27 +04:00
|
|
|
}
|
|
|
|
|
2019-02-26 01:07:19 +03:00
|
|
|
/*static*/
|
|
|
|
void CompositorBridgeParent::DeallocateLayerTreeId(LayersId aId) {
|
2014-04-24 12:40:35 +04:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
2014-05-12 01:03:00 +04:00
|
|
|
// Here main thread notifies compositor to remove an element from
|
|
|
|
// sIndirectLayerTrees. This removed element might be queried soon.
|
|
|
|
// Checking the elements of sIndirectLayerTrees exist or not before using.
|
2015-06-17 17:33:00 +03:00
|
|
|
if (!CompositorLoop()) {
|
|
|
|
gfxCriticalError() << "Attempting to post to a invalid Compositor Loop";
|
|
|
|
return;
|
|
|
|
}
|
2017-10-27 23:39:28 +03:00
|
|
|
CompositorLoop()->PostTask(
|
|
|
|
NewRunnableFunction("EraseLayerStateRunnable", &EraseLayerState, aId));
|
2014-04-24 12:40:35 +04:00
|
|
|
}
|
|
|
|
|
2018-03-25 02:06:01 +03:00
|
|
|
static void UpdateControllerForLayersId(LayersId aLayersId,
|
2013-07-30 22:03:40 +04:00
|
|
|
GeckoContentController* aController) {
|
|
|
|
// Adopt ref given to us by SetControllerForLayerTree()
|
2015-01-13 21:26:26 +03:00
|
|
|
MonitorAutoLock lock(*sIndirectLayerTreesLock);
|
2012-07-20 10:48:27 +04:00
|
|
|
sIndirectLayerTrees[aLayersId].mController =
|
2013-07-30 22:03:40 +04:00
|
|
|
already_AddRefed<GeckoContentController>(aController);
|
2012-07-20 10:48:27 +04:00
|
|
|
}
|
|
|
|
|
2015-09-25 20:54:11 +03:00
|
|
|
ScopedLayerTreeRegistration::ScopedLayerTreeRegistration(
|
|
|
|
APZCTreeManager* aApzctm, LayersId aLayersId, Layer* aRoot,
|
2013-07-30 22:03:41 +04:00
|
|
|
GeckoContentController* aController)
|
|
|
|
: mLayersId(aLayersId) {
|
2015-01-13 21:26:26 +03:00
|
|
|
EnsureLayerTreeMapReady();
|
|
|
|
MonitorAutoLock lock(*sIndirectLayerTreesLock);
|
2013-07-30 22:03:41 +04:00
|
|
|
sIndirectLayerTrees[aLayersId].mRoot = aRoot;
|
|
|
|
sIndirectLayerTrees[aLayersId].mController = aController;
|
|
|
|
}
|
|
|
|
|
|
|
|
ScopedLayerTreeRegistration::~ScopedLayerTreeRegistration() {
|
2015-01-13 21:26:26 +03:00
|
|
|
MonitorAutoLock lock(*sIndirectLayerTreesLock);
|
2013-07-30 22:03:41 +04:00
|
|
|
sIndirectLayerTrees.erase(mLayersId);
|
2012-07-20 10:48:27 +04:00
|
|
|
}
|
|
|
|
|
2019-02-26 01:07:19 +03:00
|
|
|
/*static*/
|
|
|
|
void CompositorBridgeParent::SetControllerForLayerTree(
|
2016-03-22 21:08:38 +03:00
|
|
|
LayersId aLayersId, GeckoContentController* aController) {
|
2012-07-20 10:48:27 +04:00
|
|
|
// This ref is adopted by UpdateControllerForLayersId().
|
|
|
|
aController->AddRef();
|
2017-10-27 23:39:28 +03:00
|
|
|
CompositorLoop()->PostTask(NewRunnableFunction(
|
|
|
|
"UpdateControllerForLayersIdRunnable", &UpdateControllerForLayersId,
|
|
|
|
aLayersId, aController));
|
2012-07-20 10:48:27 +04:00
|
|
|
}
|
|
|
|
|
2019-02-26 01:07:19 +03:00
|
|
|
/*static*/
|
|
|
|
already_AddRefed<IAPZCTreeManager> CompositorBridgeParent::GetAPZCTreeManager(
|
|
|
|
LayersId aLayersId) {
|
2015-11-03 19:12:46 +03:00
|
|
|
EnsureLayerTreeMapReady();
|
2015-11-27 03:20:04 +03:00
|
|
|
MonitorAutoLock lock(*sIndirectLayerTreesLock);
|
|
|
|
LayerTreeMap::iterator cit = sIndirectLayerTrees.find(aLayersId);
|
|
|
|
if (sIndirectLayerTrees.end() == cit) {
|
|
|
|
return nullptr;
|
2013-07-30 22:03:40 +04:00
|
|
|
}
|
2015-11-27 03:20:04 +03:00
|
|
|
LayerTreeState* lts = &cit->second;
|
2016-05-23 10:27:51 +03:00
|
|
|
|
2018-03-02 07:00:41 +03:00
|
|
|
RefPtr<IAPZCTreeManager> apzctm =
|
2016-05-23 10:27:51 +03:00
|
|
|
lts->mParent ? lts->mParent->mApzcTreeManager.get() : nullptr;
|
|
|
|
return apzctm.forget();
|
2013-07-30 22:03:40 +04:00
|
|
|
}
|
|
|
|
|
2017-10-04 01:11:18 +03:00
|
|
|
#if defined(MOZ_GECKO_PROFILER)
|
2014-10-02 00:01:59 +04:00
|
|
|
static void InsertVsyncProfilerMarker(TimeStamp aVsyncTimestamp) {
|
2016-05-16 09:40:13 +03:00
|
|
|
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
|
2018-11-19 09:29:15 +03:00
|
|
|
if (profiler_thread_is_being_profiled()) {
|
2019-09-04 10:56:51 +03:00
|
|
|
PROFILER_ADD_MARKER_WITH_PAYLOAD("VsyncTimestamp", GRAPHICS,
|
|
|
|
VsyncMarkerPayload, (aVsyncTimestamp));
|
2018-11-19 09:29:15 +03:00
|
|
|
}
|
2014-10-02 00:01:59 +04:00
|
|
|
}
|
2017-10-04 01:11:18 +03:00
|
|
|
#endif
|
2014-10-02 00:01:59 +04:00
|
|
|
|
2019-02-26 01:07:19 +03:00
|
|
|
/*static */
|
|
|
|
void CompositorBridgeParent::PostInsertVsyncProfilerMarker(
|
2016-03-22 21:08:38 +03:00
|
|
|
TimeStamp aVsyncTimestamp) {
|
2017-10-04 01:11:18 +03:00
|
|
|
#if defined(MOZ_GECKO_PROFILER)
|
2015-03-14 04:14:11 +03:00
|
|
|
// Called in the vsync thread
|
2016-05-16 09:38:34 +03:00
|
|
|
if (profiler_is_active() && CompositorThreadHolder::IsActive()) {
|
2016-04-28 03:06:05 +03:00
|
|
|
CompositorLoop()->PostTask(
|
2017-10-27 23:39:28 +03:00
|
|
|
NewRunnableFunction("InsertVsyncProfilerMarkerRunnable",
|
|
|
|
InsertVsyncProfilerMarker, aVsyncTimestamp));
|
2014-10-02 00:01:59 +04:00
|
|
|
}
|
2017-10-04 01:11:18 +03:00
|
|
|
#endif
|
2014-10-02 00:01:59 +04:00
|
|
|
}
|
2013-12-09 05:40:59 +04:00
|
|
|
|
2016-07-01 11:15:16 +03:00
|
|
|
widget::PCompositorWidgetParent*
|
|
|
|
CompositorBridgeParent::AllocPCompositorWidgetParent(
|
|
|
|
const CompositorWidgetInitData& aInitData) {
|
|
|
|
#if defined(MOZ_WIDGET_SUPPORTS_OOP_COMPOSITING)
|
|
|
|
if (mWidget) {
|
|
|
|
// Should not create two widgets on the same compositor.
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
widget::CompositorWidgetParent* widget =
|
2017-01-13 01:29:42 +03:00
|
|
|
new widget::CompositorWidgetParent(aInitData, mOptions);
|
2016-07-01 11:15:16 +03:00
|
|
|
widget->AddRef();
|
|
|
|
|
|
|
|
// Sending the constructor acts as initialization as well.
|
|
|
|
mWidget = widget;
|
|
|
|
return widget;
|
|
|
|
#else
|
|
|
|
return nullptr;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CompositorBridgeParent::DeallocPCompositorWidgetParent(
|
|
|
|
PCompositorWidgetParent* aActor) {
|
|
|
|
#if defined(MOZ_WIDGET_SUPPORTS_OOP_COMPOSITING)
|
|
|
|
static_cast<widget::CompositorWidgetParent*>(aActor)->Release();
|
|
|
|
return true;
|
|
|
|
#else
|
|
|
|
return false;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2016-08-24 01:18:55 +03:00
|
|
|
bool CompositorBridgeParent::IsPendingComposite() {
|
|
|
|
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
|
|
|
|
if (!mCompositor) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return mCompositor->IsPendingComposite();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CompositorBridgeParent::FinishPendingComposite() {
|
|
|
|
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
|
|
|
|
if (!mCompositor) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
return mCompositor->FinishPendingComposite();
|
|
|
|
}
|
|
|
|
|
2016-10-24 22:12:57 +03:00
|
|
|
CompositorController*
|
|
|
|
CompositorBridgeParent::LayerTreeState::GetCompositorController() const {
|
|
|
|
return mParent;
|
|
|
|
}
|
|
|
|
|
2016-10-24 22:12:55 +03:00
|
|
|
MetricsSharingController*
|
|
|
|
CompositorBridgeParent::LayerTreeState::CrossProcessSharingController() const {
|
2019-03-05 04:37:37 +03:00
|
|
|
return mContentCompositorBridgeParent;
|
2016-02-29 09:53:14 +03:00
|
|
|
}
|
|
|
|
|
2016-10-24 22:12:57 +03:00
|
|
|
MetricsSharingController*
|
|
|
|
CompositorBridgeParent::LayerTreeState::InProcessSharingController() const {
|
|
|
|
return mParent;
|
|
|
|
}
|
|
|
|
|
2018-12-08 02:28:41 +03:00
|
|
|
void CompositorBridgeParent::DidComposite(const VsyncId& aId,
|
2018-05-15 15:49:29 +03:00
|
|
|
TimeStamp& aCompositeStart,
|
|
|
|
TimeStamp& aCompositeEnd) {
|
2017-02-24 06:22:59 +03:00
|
|
|
if (mWrBridge) {
|
2018-07-27 16:42:30 +03:00
|
|
|
MOZ_ASSERT(false); // This should never get called for a WR compositor
|
2017-02-24 06:22:59 +03:00
|
|
|
} else {
|
2018-12-08 02:28:41 +03:00
|
|
|
NotifyDidComposite(mPendingTransaction, aId, aCompositeStart,
|
|
|
|
aCompositeEnd);
|
2017-08-11 04:57:21 +03:00
|
|
|
#if defined(ENABLE_FRAME_LATENCY_LOG)
|
2018-04-20 22:13:06 +03:00
|
|
|
if (mPendingTransaction.IsValid()) {
|
2018-06-26 21:40:10 +03:00
|
|
|
if (mRefreshStartTime) {
|
|
|
|
int32_t latencyMs =
|
|
|
|
lround((aCompositeEnd - mRefreshStartTime).ToMilliseconds());
|
2017-08-11 04:57:21 +03:00
|
|
|
printf_stderr(
|
|
|
|
"From transaction start to end of generate frame latencyMs %d this "
|
|
|
|
"%p\n",
|
|
|
|
latencyMs, this);
|
|
|
|
}
|
|
|
|
if (mFwdTime) {
|
2018-06-26 21:40:10 +03:00
|
|
|
int32_t latencyMs = lround((aCompositeEnd - mFwdTime).ToMilliseconds());
|
2017-08-11 04:57:21 +03:00
|
|
|
printf_stderr(
|
|
|
|
"From forwarding transaction to end of generate frame latencyMs %d "
|
|
|
|
"this %p\n",
|
|
|
|
latencyMs, this);
|
|
|
|
}
|
|
|
|
}
|
2018-06-26 21:40:10 +03:00
|
|
|
mRefreshStartTime = TimeStamp();
|
2017-08-11 04:57:21 +03:00
|
|
|
mTxnStartTime = TimeStamp();
|
|
|
|
mFwdTime = TimeStamp();
|
|
|
|
#endif
|
2018-04-20 22:13:06 +03:00
|
|
|
mPendingTransaction = TransactionId{0};
|
2017-02-24 06:22:59 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-21 01:52:07 +03:00
|
|
|
void CompositorBridgeParent::NotifyDidSceneBuild(
|
2019-04-16 01:34:13 +03:00
|
|
|
const nsTArray<wr::RenderRoot>& aRenderRoots,
|
|
|
|
RefPtr<wr::WebRenderPipelineInfo> aInfo) {
|
2018-12-21 01:43:01 +03:00
|
|
|
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
|
|
|
|
if (mPaused) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mWrBridge) {
|
2019-04-16 01:34:13 +03:00
|
|
|
mWrBridge->NotifyDidSceneBuild(aRenderRoots, aInfo);
|
2018-12-21 01:43:01 +03:00
|
|
|
} else {
|
|
|
|
mCompositorScheduler->ScheduleComposition();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-27 17:32:30 +03:00
|
|
|
void CompositorBridgeParent::NotifyPipelineRendered(
|
|
|
|
const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch,
|
2018-12-08 02:28:41 +03:00
|
|
|
const VsyncId& aCompositeStartId, TimeStamp& aCompositeStart,
|
|
|
|
TimeStamp& aRenderStart, TimeStamp& aCompositeEnd,
|
|
|
|
wr::RendererStats* aStats) {
|
2018-11-17 06:27:54 +03:00
|
|
|
if (!mWrBridge || !mAsyncImageManager) {
|
2017-05-17 03:28:20 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-11-16 05:13:56 +03:00
|
|
|
nsTArray<FrameStats> stats;
|
|
|
|
|
2018-10-19 16:48:04 +03:00
|
|
|
RefPtr<UiCompositorControllerParent> uiController =
|
|
|
|
UiCompositorControllerParent::GetFromRootLayerTreeId(mRootLayerTreeID);
|
|
|
|
|
2017-02-24 06:22:59 +03:00
|
|
|
if (mWrBridge->PipelineId() == aPipelineId) {
|
2018-04-27 17:32:31 +03:00
|
|
|
mWrBridge->RemoveEpochDataPriorTo(aEpoch);
|
2017-02-24 06:22:59 +03:00
|
|
|
|
2018-04-27 17:32:30 +03:00
|
|
|
if (!mPaused) {
|
2018-11-16 05:13:56 +03:00
|
|
|
TransactionId transactionId = mWrBridge->FlushTransactionIdsForEpoch(
|
2018-12-08 02:28:41 +03:00
|
|
|
aEpoch, aCompositeStartId, aCompositeStart, aRenderStart,
|
|
|
|
aCompositeEnd, uiController);
|
2018-04-27 17:32:30 +03:00
|
|
|
Unused << SendDidComposite(LayersId{0}, transactionId, aCompositeStart,
|
|
|
|
aCompositeEnd);
|
|
|
|
|
|
|
|
nsTArray<ImageCompositeNotificationInfo> notifications;
|
|
|
|
mWrBridge->ExtractImageCompositeNotifications(¬ifications);
|
|
|
|
if (!notifications.IsEmpty()) {
|
|
|
|
Unused << ImageBridgeParent::NotifyImageComposites(notifications);
|
|
|
|
}
|
2017-02-24 06:22:59 +03:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-11-17 06:27:54 +03:00
|
|
|
auto wrBridge = mAsyncImageManager->GetWrBridge(aPipelineId);
|
|
|
|
if (wrBridge && wrBridge->GetCompositorBridge()) {
|
|
|
|
MOZ_ASSERT(!wrBridge->IsRootWebRenderBridgeParent());
|
|
|
|
wrBridge->RemoveEpochDataPriorTo(aEpoch);
|
2018-04-27 17:32:30 +03:00
|
|
|
if (!mPaused) {
|
2018-11-16 05:13:56 +03:00
|
|
|
TransactionId transactionId = wrBridge->FlushTransactionIdsForEpoch(
|
2018-12-08 02:28:41 +03:00
|
|
|
aEpoch, aCompositeStartId, aCompositeStart, aRenderStart,
|
|
|
|
aCompositeEnd, uiController, aStats, &stats);
|
2018-11-17 06:27:54 +03:00
|
|
|
Unused << wrBridge->GetCompositorBridge()->SendDidComposite(
|
|
|
|
wrBridge->GetLayersId(), transactionId, aCompositeStart,
|
|
|
|
aCompositeEnd);
|
2018-04-27 17:32:30 +03:00
|
|
|
}
|
2018-11-17 06:27:54 +03:00
|
|
|
}
|
2018-11-16 05:13:56 +03:00
|
|
|
|
|
|
|
if (!stats.IsEmpty()) {
|
|
|
|
Unused << SendNotifyFrameStats(stats);
|
|
|
|
}
|
2016-12-01 07:36:41 +03:00
|
|
|
}
|
|
|
|
|
2018-05-28 18:29:41 +03:00
|
|
|
RefPtr<AsyncImagePipelineManager>
|
|
|
|
CompositorBridgeParent::GetAsyncImagePipelineManager() const {
|
|
|
|
return mAsyncImageManager;
|
|
|
|
}
|
|
|
|
|
2018-04-20 22:13:06 +03:00
|
|
|
void CompositorBridgeParent::NotifyDidComposite(TransactionId aTransactionId,
|
2018-12-08 02:28:41 +03:00
|
|
|
VsyncId aId,
|
2018-04-20 22:13:06 +03:00
|
|
|
TimeStamp& aCompositeStart,
|
|
|
|
TimeStamp& aCompositeEnd) {
|
2018-07-27 16:42:30 +03:00
|
|
|
MOZ_ASSERT(
|
|
|
|
!mWrBridge); // We should be going through NotifyPipelineRendered instead
|
|
|
|
|
2018-03-25 02:06:01 +03:00
|
|
|
Unused << SendDidComposite(LayersId{0}, aTransactionId, aCompositeStart,
|
|
|
|
aCompositeEnd);
|
2015-12-02 22:31:17 +03:00
|
|
|
|
2015-09-09 02:14:51 +03:00
|
|
|
if (mLayerManager) {
|
2017-01-04 18:19:30 +03:00
|
|
|
nsTArray<ImageCompositeNotificationInfo> notifications;
|
2015-09-09 02:14:51 +03:00
|
|
|
mLayerManager->ExtractImageCompositeNotifications(¬ifications);
|
|
|
|
if (!notifications.IsEmpty()) {
|
2015-11-02 08:53:26 +03:00
|
|
|
Unused << ImageBridgeParent::NotifyImageComposites(notifications);
|
2015-07-06 06:02:26 +03:00
|
|
|
}
|
|
|
|
}
|
2014-05-29 01:42:14 +04:00
|
|
|
|
2015-01-13 21:26:26 +03:00
|
|
|
MonitorAutoLock lock(*sIndirectLayerTreesLock);
|
2018-12-08 02:28:41 +03:00
|
|
|
ForEachIndirectLayerTree([&](LayerTreeState* lts,
|
|
|
|
const LayersId& aLayersId) -> void {
|
2019-03-05 04:37:37 +03:00
|
|
|
if (lts->mContentCompositorBridgeParent && lts->mParent == this) {
|
|
|
|
ContentCompositorBridgeParent* cpcp = lts->mContentCompositorBridgeParent;
|
2018-12-08 02:28:41 +03:00
|
|
|
cpcp->DidCompositeLocked(aLayersId, aId, aCompositeStart, aCompositeEnd);
|
|
|
|
}
|
|
|
|
});
|
2014-05-29 01:42:14 +04:00
|
|
|
}
|
|
|
|
|
2016-03-22 21:08:38 +03:00
|
|
|
void CompositorBridgeParent::InvalidateRemoteLayers() {
|
2016-02-29 09:53:12 +03:00
|
|
|
MOZ_ASSERT(CompositorLoop() == MessageLoop::current());
|
|
|
|
|
2018-03-25 02:06:01 +03:00
|
|
|
Unused << PCompositorBridgeParent::SendInvalidateLayers(LayersId{0});
|
2016-02-29 09:53:12 +03:00
|
|
|
|
|
|
|
MonitorAutoLock lock(*sIndirectLayerTreesLock);
|
2018-03-25 02:06:01 +03:00
|
|
|
ForEachIndirectLayerTree([](LayerTreeState* lts,
|
|
|
|
const LayersId& aLayersId) -> void {
|
2019-03-05 04:37:37 +03:00
|
|
|
if (lts->mContentCompositorBridgeParent) {
|
|
|
|
ContentCompositorBridgeParent* cpcp = lts->mContentCompositorBridgeParent;
|
2016-02-29 09:53:12 +03:00
|
|
|
Unused << cpcp->SendInvalidateLayers(aLayersId);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-12-02 17:02:27 +03:00
|
|
|
void UpdateIndirectTree(LayersId aId, Layer* aRoot,
|
|
|
|
const TargetConfig& aTargetConfig) {
|
2015-01-13 21:26:26 +03:00
|
|
|
MonitorAutoLock lock(*sIndirectLayerTreesLock);
|
2012-07-20 10:48:27 +04:00
|
|
|
sIndirectLayerTrees[aId].mRoot = aRoot;
|
2012-11-22 06:40:57 +04:00
|
|
|
sIndirectLayerTrees[aId].mTargetConfig = aTargetConfig;
|
2012-07-18 03:59:45 +04:00
|
|
|
}
|
|
|
|
|
2016-03-22 21:08:38 +03:00
|
|
|
/* static */ CompositorBridgeParent::LayerTreeState*
|
2018-03-25 02:06:01 +03:00
|
|
|
CompositorBridgeParent::GetIndirectShadowTree(LayersId aId) {
|
2018-03-02 07:00:41 +03:00
|
|
|
// Only the compositor thread should use this method variant
|
|
|
|
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
|
2018-01-18 15:28:56 +03:00
|
|
|
|
2015-01-13 21:26:26 +03:00
|
|
|
MonitorAutoLock lock(*sIndirectLayerTreesLock);
|
2014-04-22 01:46:50 +04:00
|
|
|
LayerTreeMap::iterator cit = sIndirectLayerTrees.find(aId);
|
2012-07-18 03:59:45 +04:00
|
|
|
if (sIndirectLayerTrees.end() == cit) {
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2012-07-18 03:59:45 +04:00
|
|
|
}
|
2012-07-20 10:48:27 +04:00
|
|
|
return &cit->second;
|
2012-07-18 03:59:45 +04:00
|
|
|
}
|
|
|
|
|
2019-02-26 01:07:19 +03:00
|
|
|
/* static */
|
|
|
|
bool CompositorBridgeParent::CallWithIndirectShadowTree(
|
2018-03-25 02:06:01 +03:00
|
|
|
LayersId aId,
|
2018-01-18 15:28:56 +03:00
|
|
|
const std::function<void(CompositorBridgeParent::LayerTreeState&)>& aFunc) {
|
|
|
|
// Note that this does not make things universally threadsafe just because the
|
|
|
|
// sIndirectLayerTreesLock mutex is held. This is because the compositor
|
|
|
|
// thread can mutate the LayerTreeState outside the lock. It does however
|
|
|
|
// ensure that the *storage* for the LayerTreeState remains stable, since we
|
|
|
|
// should always hold the lock when adding/removing entries to the map.
|
|
|
|
MonitorAutoLock lock(*sIndirectLayerTreesLock);
|
|
|
|
LayerTreeMap::iterator cit = sIndirectLayerTrees.find(aId);
|
|
|
|
if (sIndirectLayerTrees.end() == cit) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
aFunc(cit->second);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-09-24 16:46:02 +03:00
|
|
|
static CompositorBridgeParent::LayerTreeState* GetStateForRoot(
|
2018-03-25 02:06:01 +03:00
|
|
|
LayersId aContentLayersId, const MonitorAutoLock& aProofOfLock) {
|
2016-09-21 17:26:33 +03:00
|
|
|
CompositorBridgeParent::LayerTreeState* state = nullptr;
|
|
|
|
LayerTreeMap::iterator itr = sIndirectLayerTrees.find(aContentLayersId);
|
|
|
|
if (sIndirectLayerTrees.end() != itr) {
|
|
|
|
state = &itr->second;
|
|
|
|
}
|
|
|
|
|
|
|
|
// |state| is the state for the content process, but we want the APZCTMParent
|
|
|
|
// for the parent process owning that content process. So we have to jump to
|
|
|
|
// the LayerTreeState for the root layer tree id for that layer tree, and use
|
|
|
|
// the mApzcTreeManagerParent from that. This should also work with nested
|
|
|
|
// content processes, because RootLayerTreeId() will bypass any intermediate
|
|
|
|
// processes' ids and go straight to the root.
|
2019-08-22 10:15:52 +03:00
|
|
|
if (state && state->mParent) {
|
2018-03-25 02:06:01 +03:00
|
|
|
LayersId rootLayersId = state->mParent->RootLayerTreeId();
|
2016-09-21 17:26:33 +03:00
|
|
|
itr = sIndirectLayerTrees.find(rootLayersId);
|
|
|
|
state = (sIndirectLayerTrees.end() != itr) ? &itr->second : nullptr;
|
|
|
|
}
|
|
|
|
|
2016-09-24 16:46:02 +03:00
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
2019-02-26 01:07:19 +03:00
|
|
|
/* static */
|
|
|
|
APZCTreeManagerParent* CompositorBridgeParent::GetApzcTreeManagerParentForRoot(
|
2018-03-25 02:06:01 +03:00
|
|
|
LayersId aContentLayersId) {
|
2016-09-24 16:46:02 +03:00
|
|
|
MonitorAutoLock lock(*sIndirectLayerTreesLock);
|
|
|
|
CompositorBridgeParent::LayerTreeState* state =
|
|
|
|
GetStateForRoot(aContentLayersId, lock);
|
2016-09-21 17:26:33 +03:00
|
|
|
return state ? state->mApzcTreeManagerParent : nullptr;
|
|
|
|
}
|
|
|
|
|
2019-02-26 01:07:19 +03:00
|
|
|
/* static */
|
|
|
|
GeckoContentController*
|
2018-03-25 02:06:01 +03:00
|
|
|
CompositorBridgeParent::GetGeckoContentControllerForRoot(
|
|
|
|
LayersId aContentLayersId) {
|
2016-09-24 16:46:02 +03:00
|
|
|
MonitorAutoLock lock(*sIndirectLayerTreesLock);
|
|
|
|
CompositorBridgeParent::LayerTreeState* state =
|
|
|
|
GetStateForRoot(aContentLayersId, lock);
|
|
|
|
return state ? state->mController.get() : nullptr;
|
|
|
|
}
|
|
|
|
|
2016-04-13 00:04:50 +03:00
|
|
|
PTextureParent* CompositorBridgeParent::AllocPTextureParent(
|
2018-03-12 16:10:13 +03:00
|
|
|
const SurfaceDescriptor& aSharedData, const ReadLockDescriptor& aReadLock,
|
2016-04-13 00:04:50 +03:00
|
|
|
const LayersBackend& aLayersBackend, const TextureFlags& aFlags,
|
2017-04-20 04:24:13 +03:00
|
|
|
const LayersId& aId, const uint64_t& aSerial,
|
|
|
|
const wr::MaybeExternalImageId& aExternalImageId) {
|
2018-03-12 16:10:13 +03:00
|
|
|
return TextureHost::CreateIPDLActor(this, aSharedData, aReadLock,
|
|
|
|
aLayersBackend, aFlags, aSerial,
|
|
|
|
aExternalImageId);
|
2016-04-13 00:04:50 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bool CompositorBridgeParent::DeallocPTextureParent(PTextureParent* actor) {
|
|
|
|
return TextureHost::DestroyIPDLActor(actor);
|
|
|
|
}
|
|
|
|
|
2018-12-02 17:19:11 +03:00
|
|
|
mozilla::ipc::IPCResult CompositorBridgeParent::RecvInitPCanvasParent(
|
|
|
|
Endpoint<PCanvasParent>&& aEndpoint) {
|
|
|
|
MOZ_CRASH("PCanvasParent shouldn't be created via CompositorBridgeParent.");
|
|
|
|
}
|
|
|
|
|
2016-04-13 00:04:50 +03:00
|
|
|
bool CompositorBridgeParent::IsSameProcess() const {
|
|
|
|
return OtherPid() == base::GetCurrentProcId();
|
|
|
|
}
|
|
|
|
|
2018-08-10 18:14:57 +03:00
|
|
|
void CompositorBridgeParent::NotifyWebRenderContextPurge() {
|
|
|
|
MOZ_ASSERT(CompositorLoop() == MessageLoop::current());
|
2019-03-22 21:28:42 +03:00
|
|
|
RefPtr<wr::WebRenderAPI> api =
|
|
|
|
mWrBridge->GetWebRenderAPI(wr::RenderRoot::Default);
|
2018-08-10 18:14:57 +03:00
|
|
|
api->ClearAllCaches();
|
|
|
|
}
|
|
|
|
|
2015-03-04 16:46:15 +03:00
|
|
|
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
|
2015-10-06 22:23:24 +03:00
|
|
|
//#define PLUGINS_LOG(...) printf_stderr("CP [%s]: ", __FUNCTION__);
|
|
|
|
// printf_stderr(__VA_ARGS__);
|
|
|
|
// printf_stderr("\n");
|
|
|
|
# define PLUGINS_LOG(...)
|
|
|
|
|
2018-03-25 02:06:01 +03:00
|
|
|
bool CompositorBridgeParent::UpdatePluginWindowState(LayersId aId) {
|
2015-10-19 18:38:42 +03:00
|
|
|
MonitorAutoLock lock(*sIndirectLayerTreesLock);
|
2016-03-22 21:08:38 +03:00
|
|
|
CompositorBridgeParent::LayerTreeState& lts = sIndirectLayerTrees[aId];
|
2015-10-19 18:38:42 +03:00
|
|
|
if (!lts.mParent) {
|
|
|
|
PLUGINS_LOG("[%" PRIu64 "] layer tree compositor parent pointer is null",
|
|
|
|
aId);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-10-06 22:23:24 +03:00
|
|
|
// Check if this layer tree has received any shadow layer updates
|
2015-10-06 22:23:24 +03:00
|
|
|
if (!lts.mUpdatedPluginDataAvailable) {
|
2016-03-05 02:56:03 +03:00
|
|
|
PLUGINS_LOG("[%" PRIu64 "] no plugin data", aId);
|
|
|
|
return false;
|
2015-10-06 22:23:24 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// pluginMetricsChanged tracks whether we need to send plugin update
|
|
|
|
// data to the main thread. If we do we'll have to block composition,
|
|
|
|
// which we want to avoid if at all possible.
|
|
|
|
bool pluginMetricsChanged = false;
|
|
|
|
|
|
|
|
// Same layer tree checks
|
|
|
|
if (mLastPluginUpdateLayerTreeId == aId) {
|
|
|
|
// no plugin data and nothing has changed, bail.
|
|
|
|
if (!mCachedPluginData.Length() && !lts.mPluginData.Length()) {
|
|
|
|
PLUGINS_LOG("[%" PRIu64 "] no data, no changes", aId);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mCachedPluginData.Length() == lts.mPluginData.Length()) {
|
|
|
|
// check for plugin data changes
|
|
|
|
for (uint32_t idx = 0; idx < lts.mPluginData.Length(); idx++) {
|
|
|
|
if (!(mCachedPluginData[idx] == lts.mPluginData[idx])) {
|
|
|
|
pluginMetricsChanged = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// array lengths don't match, need to update
|
|
|
|
pluginMetricsChanged = true;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// exchanging layer trees, we need to update
|
|
|
|
pluginMetricsChanged = true;
|
2015-01-29 22:41:55 +03:00
|
|
|
}
|
|
|
|
|
2016-01-12 20:05:58 +03:00
|
|
|
// Check if plugin windows are currently hidden due to scrolling
|
|
|
|
if (mDeferPluginWindows) {
|
|
|
|
PLUGINS_LOG("[%" PRIu64 "] suppressing", aId);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-02-04 18:10:55 +03:00
|
|
|
// If the plugin windows were hidden but now are not, we need to force
|
|
|
|
// update the metrics to make sure they are visible again.
|
|
|
|
if (mPluginWindowsHidden) {
|
|
|
|
PLUGINS_LOG("[%" PRIu64 "] re-showing", aId);
|
|
|
|
mPluginWindowsHidden = false;
|
|
|
|
pluginMetricsChanged = true;
|
|
|
|
}
|
|
|
|
|
2015-10-06 22:23:24 +03:00
|
|
|
if (!lts.mPluginData.Length()) {
|
2016-03-23 01:30:14 +03:00
|
|
|
// Don't hide plugins if the previous remote layer tree didn't contain any.
|
|
|
|
if (!mCachedPluginData.Length()) {
|
|
|
|
PLUGINS_LOG("[%" PRIu64 "] nothing to hide", aId);
|
|
|
|
return false;
|
|
|
|
}
|
2016-04-30 02:20:42 +03:00
|
|
|
|
2016-07-01 11:15:16 +03:00
|
|
|
uintptr_t parentWidget = GetWidget()->GetWidgetKey();
|
2016-04-30 02:20:42 +03:00
|
|
|
|
2015-10-06 22:23:24 +03:00
|
|
|
// We will pass through here in cases where the previous shadow layer
|
|
|
|
// tree contained visible plugins and the new tree does not. All we need
|
|
|
|
// to do here is hide the plugins for the old tree, so don't waste time
|
|
|
|
// calculating clipping.
|
2015-10-06 22:23:24 +03:00
|
|
|
mPluginsLayerOffset = nsIntPoint(0, 0);
|
|
|
|
mPluginsLayerVisibleRegion.SetEmpty();
|
2015-11-02 08:53:26 +03:00
|
|
|
Unused << lts.mParent->SendHideAllPlugins(parentWidget);
|
2015-10-06 22:23:24 +03:00
|
|
|
lts.mUpdatedPluginDataAvailable = false;
|
2015-10-06 22:23:24 +03:00
|
|
|
PLUGINS_LOG("[%" PRIu64 "] hide all", aId);
|
|
|
|
} else {
|
|
|
|
// Retrieve the offset and visible region of the layer that hosts
|
2016-03-22 21:08:38 +03:00
|
|
|
// the plugins, CompositorBridgeChild needs these in calculating proper
|
2015-10-06 22:23:24 +03:00
|
|
|
// plugin clipping.
|
|
|
|
LayerTransactionParent* layerTree = lts.mLayerTree;
|
|
|
|
Layer* contentRoot = layerTree->GetRoot();
|
|
|
|
if (contentRoot) {
|
|
|
|
nsIntPoint offset;
|
|
|
|
nsIntRegion visibleRegion;
|
|
|
|
if (contentRoot->GetVisibleRegionRelativeToRootLayer(visibleRegion,
|
|
|
|
&offset)) {
|
|
|
|
// Check to see if these values have changed, if so we need to
|
|
|
|
// update plugin window position within the window.
|
|
|
|
if (!pluginMetricsChanged &&
|
|
|
|
mPluginsLayerVisibleRegion == visibleRegion &&
|
|
|
|
mPluginsLayerOffset == offset) {
|
|
|
|
PLUGINS_LOG("[%" PRIu64 "] no change", aId);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
mPluginsLayerOffset = offset;
|
|
|
|
mPluginsLayerVisibleRegion = visibleRegion;
|
2015-12-03 01:32:55 +03:00
|
|
|
Unused << lts.mParent->SendUpdatePluginConfigurations(
|
|
|
|
LayoutDeviceIntPoint::FromUnknownPoint(offset),
|
|
|
|
LayoutDeviceIntRegion::FromUnknownRegion(visibleRegion),
|
|
|
|
lts.mPluginData);
|
2015-10-06 22:23:24 +03:00
|
|
|
lts.mUpdatedPluginDataAvailable = false;
|
|
|
|
PLUGINS_LOG("[%" PRIu64 "] updated", aId);
|
2015-10-22 01:27:48 +03:00
|
|
|
} else {
|
|
|
|
PLUGINS_LOG("[%" PRIu64 "] no visibility data", aId);
|
|
|
|
return false;
|
2015-10-06 22:23:24 +03:00
|
|
|
}
|
2015-10-22 01:27:48 +03:00
|
|
|
} else {
|
|
|
|
PLUGINS_LOG("[%" PRIu64 "] no content root", aId);
|
|
|
|
return false;
|
2015-10-06 22:23:24 +03:00
|
|
|
}
|
2015-01-29 22:41:55 +03:00
|
|
|
}
|
2015-10-06 22:23:24 +03:00
|
|
|
|
|
|
|
mLastPluginUpdateLayerTreeId = aId;
|
|
|
|
mCachedPluginData = lts.mPluginData;
|
|
|
|
return true;
|
2015-01-29 22:41:55 +03:00
|
|
|
}
|
2016-01-12 20:05:58 +03:00
|
|
|
|
2016-03-22 21:08:38 +03:00
|
|
|
void CompositorBridgeParent::ScheduleShowAllPluginWindows() {
|
2016-01-12 20:05:58 +03:00
|
|
|
MOZ_ASSERT(CompositorLoop());
|
2017-06-12 22:34:10 +03:00
|
|
|
CompositorLoop()->PostTask(
|
|
|
|
NewRunnableMethod("layers::CompositorBridgeParent::ShowAllPluginWindows",
|
|
|
|
this, &CompositorBridgeParent::ShowAllPluginWindows));
|
2016-01-12 20:05:58 +03:00
|
|
|
}
|
|
|
|
|
2016-03-22 21:08:38 +03:00
|
|
|
void CompositorBridgeParent::ShowAllPluginWindows() {
|
2016-01-12 20:05:58 +03:00
|
|
|
MOZ_ASSERT(!NS_IsMainThread());
|
|
|
|
mDeferPluginWindows = false;
|
|
|
|
ScheduleComposition();
|
|
|
|
}
|
|
|
|
|
2016-03-22 21:08:38 +03:00
|
|
|
void CompositorBridgeParent::ScheduleHideAllPluginWindows() {
|
2016-01-12 20:05:58 +03:00
|
|
|
MOZ_ASSERT(CompositorLoop());
|
2017-06-12 22:34:10 +03:00
|
|
|
CompositorLoop()->PostTask(
|
|
|
|
NewRunnableMethod("layers::CompositorBridgeParent::HideAllPluginWindows",
|
|
|
|
this, &CompositorBridgeParent::HideAllPluginWindows));
|
2016-01-12 20:05:58 +03:00
|
|
|
}
|
|
|
|
|
2016-03-22 21:08:38 +03:00
|
|
|
void CompositorBridgeParent::HideAllPluginWindows() {
|
2016-01-12 20:05:58 +03:00
|
|
|
MOZ_ASSERT(!NS_IsMainThread());
|
|
|
|
// No plugins in the cache implies no plugins to manage
|
|
|
|
// in this content.
|
|
|
|
if (!mCachedPluginData.Length() || mDeferPluginWindows) {
|
|
|
|
return;
|
|
|
|
}
|
2016-04-30 02:20:42 +03:00
|
|
|
|
2016-07-01 11:15:16 +03:00
|
|
|
uintptr_t parentWidget = GetWidget()->GetWidgetKey();
|
2016-04-30 02:20:42 +03:00
|
|
|
|
2016-01-12 20:05:58 +03:00
|
|
|
mDeferPluginWindows = true;
|
2016-02-04 18:10:55 +03:00
|
|
|
mPluginWindowsHidden = true;
|
2016-07-18 11:54:02 +03:00
|
|
|
|
|
|
|
# if defined(XP_WIN)
|
|
|
|
// We will get an async reply that this has happened and then send hide.
|
2016-10-26 02:25:52 +03:00
|
|
|
mWaitForPluginsUntil = TimeStamp::Now() + mVsyncRate;
|
2016-07-18 11:54:02 +03:00
|
|
|
Unused << SendCaptureAllPlugins(parentWidget);
|
|
|
|
# else
|
2016-04-30 02:20:42 +03:00
|
|
|
Unused << SendHideAllPlugins(parentWidget);
|
2016-01-12 20:05:58 +03:00
|
|
|
ScheduleComposition();
|
2016-07-18 11:54:02 +03:00
|
|
|
# endif
|
2016-01-12 20:05:58 +03:00
|
|
|
}
|
2015-03-04 16:46:15 +03:00
|
|
|
#endif // #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
|
2015-01-29 22:41:55 +03:00
|
|
|
|
2016-07-18 11:54:02 +03:00
|
|
|
mozilla::ipc::IPCResult CompositorBridgeParent::RecvAllPluginsCaptured() {
|
|
|
|
#if defined(XP_WIN)
|
2016-07-18 11:54:02 +03:00
|
|
|
mWaitForPluginsUntil = TimeStamp();
|
|
|
|
mHaveBlockedForPlugins = false;
|
2016-07-18 11:54:02 +03:00
|
|
|
ForceComposeToTarget(nullptr);
|
|
|
|
Unused << SendHideAllPlugins(GetWidget()->GetWidgetKey());
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_OK();
|
2016-07-18 11:54:02 +03:00
|
|
|
#else
|
|
|
|
MOZ_ASSERT_UNREACHABLE(
|
|
|
|
"CompositorBridgeParent::RecvAllPluginsCaptured calls unexpected.");
|
2016-11-15 06:26:00 +03:00
|
|
|
return IPC_FAIL_NO_REASON(this);
|
2016-07-18 11:54:02 +03:00
|
|
|
#endif
|
|
|
|
}
|
2016-04-13 00:04:50 +03:00
|
|
|
|
2019-01-07 06:14:28 +03:00
|
|
|
int32_t RecordContentFrameTime(
|
|
|
|
const VsyncId& aTxnId, const TimeStamp& aVsyncStart,
|
|
|
|
const TimeStamp& aTxnStart, const VsyncId& aCompositeId,
|
|
|
|
const TimeStamp& aCompositeEnd, const TimeDuration& aFullPaintTime,
|
|
|
|
const TimeDuration& aVsyncRate, bool aContainsSVGGroup,
|
|
|
|
bool aRecordUploadStats, wr::RendererStats* aStats /* = nullptr */) {
|
|
|
|
double latencyMs = (aCompositeEnd - aTxnStart).ToMilliseconds();
|
|
|
|
double latencyNorm = latencyMs / aVsyncRate.ToMilliseconds();
|
|
|
|
int32_t fracLatencyNorm = lround(latencyNorm * 100.0);
|
|
|
|
|
|
|
|
#ifdef MOZ_GECKO_PROFILER
|
|
|
|
if (profiler_is_active()) {
|
|
|
|
class ContentFramePayload : public ProfilerMarkerPayload {
|
|
|
|
public:
|
|
|
|
ContentFramePayload(const mozilla::TimeStamp& aStartTime,
|
|
|
|
const mozilla::TimeStamp& aEndTime)
|
|
|
|
: ProfilerMarkerPayload(aStartTime, aEndTime) {}
|
|
|
|
virtual void StreamPayload(SpliceableJSONWriter& aWriter,
|
|
|
|
const TimeStamp& aProcessStartTime,
|
|
|
|
UniqueStacks& aUniqueStacks) override {
|
|
|
|
StreamCommonProps("CONTENT_FRAME_TIME", aWriter, aProcessStartTime,
|
|
|
|
aUniqueStacks);
|
|
|
|
}
|
|
|
|
};
|
2019-09-04 10:58:21 +03:00
|
|
|
AUTO_PROFILER_STATS(add_marker_with_ContentFramePayload);
|
2019-01-07 06:14:28 +03:00
|
|
|
profiler_add_marker_for_thread(
|
2019-02-16 20:37:43 +03:00
|
|
|
profiler_current_thread_id(), JS::ProfilingCategoryPair::GRAPHICS,
|
|
|
|
"CONTENT_FRAME_TIME",
|
2019-01-07 06:14:28 +03:00
|
|
|
MakeUnique<ContentFramePayload>(aTxnStart, aCompositeEnd));
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
Telemetry::Accumulate(Telemetry::CONTENT_FRAME_TIME, fracLatencyNorm);
|
|
|
|
|
|
|
|
if (!(aTxnId == VsyncId()) && aVsyncStart) {
|
|
|
|
latencyMs = (aCompositeEnd - aVsyncStart).ToMilliseconds();
|
|
|
|
latencyNorm = latencyMs / aVsyncRate.ToMilliseconds();
|
|
|
|
fracLatencyNorm = lround(latencyNorm * 100.0);
|
2019-01-07 06:17:42 +03:00
|
|
|
int32_t result = fracLatencyNorm;
|
2019-01-07 06:14:28 +03:00
|
|
|
Telemetry::Accumulate(Telemetry::CONTENT_FRAME_TIME_VSYNC, fracLatencyNorm);
|
|
|
|
|
2019-01-07 06:17:42 +03:00
|
|
|
if (aContainsSVGGroup) {
|
|
|
|
Telemetry::Accumulate(Telemetry::CONTENT_FRAME_TIME_WITH_SVG,
|
|
|
|
fracLatencyNorm);
|
|
|
|
}
|
|
|
|
|
2019-01-07 06:14:28 +03:00
|
|
|
// Record CONTENT_FRAME_TIME_REASON.
|
|
|
|
//
|
2019-01-07 06:15:57 +03:00
|
|
|
// Note that deseralizing a layers update (RecvUpdate) can delay the receipt
|
|
|
|
// of the composite vsync message
|
|
|
|
// (CompositorBridgeParent::CompositeToTarget), since they're using the same
|
|
|
|
// thread. This can mean that compositing might start significantly late,
|
|
|
|
// but this code will still detect it as having successfully started on the
|
|
|
|
// right vsync (which is somewhat correct). We'd now have reduced time left
|
|
|
|
// in the vsync interval to finish compositing, so the chances of a missed
|
|
|
|
// frame increases. This is effectively including the RecvUpdate work as
|
|
|
|
// part of the 'compositing' phase for this metric, but it isn't included in
|
|
|
|
// COMPOSITE_TIME, and *is* included in CONTENT_FULL_PAINT_TIME.
|
|
|
|
//
|
2019-01-07 06:14:28 +03:00
|
|
|
// Also of note is that when the root WebRenderBridgeParent decides to
|
|
|
|
// skip a composite (due to the Renderer being busy), that won't notify
|
|
|
|
// child WebRenderBridgeParents. That failure will show up as the
|
|
|
|
// composite starting late (since it did), but it's really a fault of a
|
|
|
|
// slow composite on the previous frame, not a slow
|
|
|
|
// CONTENT_FULL_PAINT_TIME. It would be nice to have a separate bucket for
|
|
|
|
// this category (scene was ready on the next vsync, but we chose not to
|
|
|
|
// composite), but I can't find a way to locate the right child
|
|
|
|
// WebRenderBridgeParents from the root. WebRender notifies us of the
|
|
|
|
// child pipelines contained within a render, after it finishes, but I
|
|
|
|
// can't see how to query what child pipeline would have been rendered,
|
|
|
|
// when we choose to not do it.
|
|
|
|
if (fracLatencyNorm < 200) {
|
|
|
|
// Success
|
|
|
|
Telemetry::AccumulateCategorical(
|
|
|
|
LABELS_CONTENT_FRAME_TIME_REASON::OnTime);
|
|
|
|
} else {
|
2019-01-16 01:33:25 +03:00
|
|
|
if (aCompositeId == VsyncId()) {
|
|
|
|
// aCompositeId is 0, possibly something got trigged from
|
2019-01-07 06:14:28 +03:00
|
|
|
// outside vsync?
|
2019-01-16 01:33:25 +03:00
|
|
|
Telemetry::AccumulateCategorical(
|
|
|
|
LABELS_CONTENT_FRAME_TIME_REASON::NoVsyncNoId);
|
|
|
|
} else if (aTxnId >= aCompositeId) {
|
|
|
|
// Vsync ids are nonsensical, maybe we're trying to catch up?
|
2019-01-07 06:14:28 +03:00
|
|
|
Telemetry::AccumulateCategorical(
|
|
|
|
LABELS_CONTENT_FRAME_TIME_REASON::NoVsync);
|
|
|
|
} else if (aCompositeId - aTxnId > 1) {
|
|
|
|
// Composite started late (and maybe took too long as well)
|
|
|
|
if (aFullPaintTime >= TimeDuration::FromMilliseconds(20)) {
|
|
|
|
Telemetry::AccumulateCategorical(
|
|
|
|
LABELS_CONTENT_FRAME_TIME_REASON::MissedCompositeLong);
|
|
|
|
} else if (aFullPaintTime >= TimeDuration::FromMilliseconds(10)) {
|
|
|
|
Telemetry::AccumulateCategorical(
|
|
|
|
LABELS_CONTENT_FRAME_TIME_REASON::MissedCompositeMid);
|
|
|
|
} else if (aFullPaintTime >= TimeDuration::FromMilliseconds(5)) {
|
|
|
|
Telemetry::AccumulateCategorical(
|
|
|
|
LABELS_CONTENT_FRAME_TIME_REASON::MissedCompositeLow);
|
|
|
|
} else {
|
|
|
|
Telemetry::AccumulateCategorical(
|
|
|
|
LABELS_CONTENT_FRAME_TIME_REASON::MissedComposite);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Composite started on time, but must have taken too long.
|
|
|
|
Telemetry::AccumulateCategorical(
|
|
|
|
LABELS_CONTENT_FRAME_TIME_REASON::SlowComposite);
|
|
|
|
}
|
|
|
|
}
|
2019-01-07 06:17:42 +03:00
|
|
|
|
|
|
|
if (aRecordUploadStats) {
|
|
|
|
if (aStats) {
|
|
|
|
latencyMs -= (double(aStats->resource_upload_time) / 1000000.0);
|
|
|
|
latencyNorm = latencyMs / aVsyncRate.ToMilliseconds();
|
|
|
|
fracLatencyNorm = lround(latencyNorm * 100.0);
|
|
|
|
}
|
|
|
|
Telemetry::Accumulate(
|
|
|
|
Telemetry::CONTENT_FRAME_TIME_WITHOUT_RESOURCE_UPLOAD,
|
|
|
|
fracLatencyNorm);
|
|
|
|
|
|
|
|
if (aStats) {
|
|
|
|
latencyMs -= (double(aStats->gpu_cache_upload_time) / 1000000.0);
|
|
|
|
latencyNorm = latencyMs / aVsyncRate.ToMilliseconds();
|
|
|
|
fracLatencyNorm = lround(latencyNorm * 100.0);
|
|
|
|
}
|
|
|
|
Telemetry::Accumulate(Telemetry::CONTENT_FRAME_TIME_WITHOUT_UPLOAD,
|
|
|
|
fracLatencyNorm);
|
|
|
|
}
|
|
|
|
return result;
|
2019-01-07 06:14:28 +03:00
|
|
|
}
|
|
|
|
|
2019-01-07 06:17:42 +03:00
|
|
|
return 0;
|
2019-01-07 06:14:28 +03:00
|
|
|
}
|
|
|
|
|
2019-03-12 18:06:48 +03:00
|
|
|
mozilla::ipc::IPCResult CompositorBridgeParent::RecvBeginRecording(
|
2019-07-31 23:21:03 +03:00
|
|
|
const TimeStamp& aRecordingStart, BeginRecordingResolver&& aResolve) {
|
2019-07-31 21:28:38 +03:00
|
|
|
if (mHaveCompositionRecorder) {
|
2019-07-31 23:21:03 +03:00
|
|
|
aResolve(false);
|
|
|
|
return IPC_OK();
|
|
|
|
}
|
|
|
|
|
2019-05-16 20:26:19 +03:00
|
|
|
if (mLayerManager) {
|
2019-07-31 21:28:38 +03:00
|
|
|
mLayerManager->SetCompositionRecorder(
|
2019-07-31 21:28:47 +03:00
|
|
|
MakeUnique<CompositionRecorder>(aRecordingStart));
|
2019-05-31 03:31:39 +03:00
|
|
|
} else if (mWrBridge) {
|
2019-07-31 21:28:47 +03:00
|
|
|
mWrBridge->SetCompositionRecorder(MakeUnique<WebRenderCompositionRecorder>(
|
|
|
|
aRecordingStart, mWrBridge->PipelineId()));
|
2019-05-16 20:26:19 +03:00
|
|
|
}
|
|
|
|
|
2019-07-31 21:28:38 +03:00
|
|
|
mHaveCompositionRecorder = true;
|
2019-07-31 23:21:03 +03:00
|
|
|
aResolve(true);
|
2019-07-31 21:28:38 +03:00
|
|
|
|
2019-03-12 18:06:48 +03:00
|
|
|
return IPC_OK();
|
|
|
|
}
|
|
|
|
|
2019-07-31 23:21:03 +03:00
|
|
|
mozilla::ipc::IPCResult CompositorBridgeParent::RecvEndRecording(
|
|
|
|
bool* aOutSuccess) {
|
2019-07-31 21:28:38 +03:00
|
|
|
if (!mHaveCompositionRecorder) {
|
2019-07-31 23:21:03 +03:00
|
|
|
*aOutSuccess = false;
|
|
|
|
return IPC_OK();
|
|
|
|
}
|
|
|
|
|
2019-05-16 20:26:19 +03:00
|
|
|
if (mLayerManager) {
|
2019-07-31 21:28:38 +03:00
|
|
|
mLayerManager->WriteCollectedFrames();
|
2019-07-31 21:28:34 +03:00
|
|
|
} else if (mWrBridge) {
|
|
|
|
mWrBridge->WriteCollectedFrames();
|
2019-05-16 20:26:19 +03:00
|
|
|
}
|
2019-05-31 03:31:39 +03:00
|
|
|
|
2019-07-31 21:28:38 +03:00
|
|
|
mHaveCompositionRecorder = false;
|
2019-07-31 23:21:03 +03:00
|
|
|
*aOutSuccess = true;
|
2019-07-31 21:28:38 +03:00
|
|
|
|
2019-03-12 18:06:48 +03:00
|
|
|
return IPC_OK();
|
|
|
|
}
|
|
|
|
|
2011-12-16 00:07:19 +04:00
|
|
|
} // namespace layers
|
|
|
|
} // namespace mozilla
|