summaryrefslogtreecommitdiffstats
path: root/gfx/layers/ipc/UiCompositorControllerParent.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/layers/ipc/UiCompositorControllerParent.cpp')
-rw-r--r--gfx/layers/ipc/UiCompositorControllerParent.cpp296
1 files changed, 296 insertions, 0 deletions
diff --git a/gfx/layers/ipc/UiCompositorControllerParent.cpp b/gfx/layers/ipc/UiCompositorControllerParent.cpp
new file mode 100644
index 0000000000..1e34969e84
--- /dev/null
+++ b/gfx/layers/ipc/UiCompositorControllerParent.cpp
@@ -0,0 +1,296 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+#include "UiCompositorControllerParent.h"
+
+#if defined(MOZ_WIDGET_ANDROID)
+# include "apz/src/APZCTreeManager.h"
+# include "mozilla/widget/AndroidCompositorWidget.h"
+#endif
+#include <utility>
+
+#include "FrameMetrics.h"
+#include "SynchronousTask.h"
+#include "mozilla/Unused.h"
+#include "mozilla/gfx/Types.h"
+#include "mozilla/ipc/Endpoint.h"
+#include "mozilla/layers/Compositor.h"
+#include "mozilla/layers/CompositorBridgeParent.h"
+#include "mozilla/layers/CompositorThread.h"
+#include "mozilla/layers/UiCompositorControllerMessageTypes.h"
+#include "mozilla/layers/WebRenderBridgeParent.h"
+
+namespace mozilla {
+namespace layers {
+
+typedef CompositorBridgeParent::LayerTreeState LayerTreeState;
+
+/* static */
+RefPtr<UiCompositorControllerParent>
+UiCompositorControllerParent::GetFromRootLayerTreeId(
+ const LayersId& aRootLayerTreeId) {
+ RefPtr<UiCompositorControllerParent> controller;
+ CompositorBridgeParent::CallWithIndirectShadowTree(
+ aRootLayerTreeId, [&](LayerTreeState& aState) -> void {
+ controller = aState.mUiControllerParent;
+ });
+ return controller;
+}
+
+/* static */
+RefPtr<UiCompositorControllerParent> UiCompositorControllerParent::Start(
+ const LayersId& aRootLayerTreeId,
+ Endpoint<PUiCompositorControllerParent>&& aEndpoint) {
+ RefPtr<UiCompositorControllerParent> parent =
+ new UiCompositorControllerParent(aRootLayerTreeId);
+
+ RefPtr<Runnable> task =
+ NewRunnableMethod<Endpoint<PUiCompositorControllerParent>&&>(
+ "layers::UiCompositorControllerParent::Open", parent,
+ &UiCompositorControllerParent::Open, std::move(aEndpoint));
+ CompositorThread()->Dispatch(task.forget());
+
+ return parent;
+}
+
+mozilla::ipc::IPCResult UiCompositorControllerParent::RecvPause() {
+ CompositorBridgeParent* parent =
+ CompositorBridgeParent::GetCompositorBridgeParentFromLayersId(
+ mRootLayerTreeId);
+ if (parent) {
+ parent->PauseComposition();
+ }
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult UiCompositorControllerParent::RecvResume(
+ bool* aOutResumed) {
+ *aOutResumed = false;
+ CompositorBridgeParent* parent =
+ CompositorBridgeParent::GetCompositorBridgeParentFromLayersId(
+ mRootLayerTreeId);
+ if (parent) {
+ *aOutResumed = parent->ResumeComposition();
+ }
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult UiCompositorControllerParent::RecvResumeAndResize(
+ const int32_t& aX, const int32_t& aY, const int32_t& aWidth,
+ const int32_t& aHeight, bool* aOutResumed) {
+ *aOutResumed = false;
+ CompositorBridgeParent* parent =
+ CompositorBridgeParent::GetCompositorBridgeParentFromLayersId(
+ mRootLayerTreeId);
+ if (parent) {
+ // Front-end expects a first paint callback upon resume/resize.
+ parent->ForceIsFirstPaint();
+#if defined(MOZ_WIDGET_ANDROID)
+ parent->GetWidget()->AsAndroid()->NotifyClientSizeChanged(
+ LayoutDeviceIntSize(aWidth, aHeight));
+#endif
+ *aOutResumed = parent->ResumeCompositionAndResize(aX, aY, aWidth, aHeight);
+ }
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
+UiCompositorControllerParent::RecvInvalidateAndRender() {
+ CompositorBridgeParent* parent =
+ CompositorBridgeParent::GetCompositorBridgeParentFromLayersId(
+ mRootLayerTreeId);
+ if (parent) {
+ parent->ScheduleComposition(wr::RenderReasons::OTHER);
+ }
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult UiCompositorControllerParent::RecvMaxToolbarHeight(
+ const int32_t& aHeight) {
+ mMaxToolbarHeight = aHeight;
+
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult UiCompositorControllerParent::RecvFixedBottomOffset(
+ const int32_t& aOffset) {
+#if defined(MOZ_WIDGET_ANDROID)
+ CompositorBridgeParent* parent =
+ CompositorBridgeParent::GetCompositorBridgeParentFromLayersId(
+ mRootLayerTreeId);
+ if (parent) {
+ parent->SetFixedLayerMargins(0, aOffset);
+ }
+#endif // defined(MOZ_WIDGET_ANDROID)
+
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult UiCompositorControllerParent::RecvDefaultClearColor(
+ const uint32_t& aColor) {
+ LayerTreeState* state =
+ CompositorBridgeParent::GetIndirectShadowTree(mRootLayerTreeId);
+
+ if (state && state->mWrBridge) {
+ state->mWrBridge->SetClearColor(gfx::DeviceColor::UnusualFromARGB(aColor));
+ }
+
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
+UiCompositorControllerParent::RecvRequestScreenPixels() {
+#if defined(MOZ_WIDGET_ANDROID)
+ LayerTreeState* state =
+ CompositorBridgeParent::GetIndirectShadowTree(mRootLayerTreeId);
+
+ if (state && state->mWrBridge) {
+ state->mWrBridge->RequestScreenPixels(this);
+ state->mWrBridge->ScheduleForcedGenerateFrame(wr::RenderReasons::OTHER);
+ }
+#endif // defined(MOZ_WIDGET_ANDROID)
+
+ return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
+UiCompositorControllerParent::RecvEnableLayerUpdateNotifications(
+ const bool& aEnable) {
+#if defined(MOZ_WIDGET_ANDROID)
+ // Layers updates are need by Robocop test which enables them
+ mCompositorLayersUpdateEnabled = aEnable;
+#endif // defined(MOZ_WIDGET_ANDROID)
+
+ return IPC_OK();
+}
+
+void UiCompositorControllerParent::ActorDestroy(ActorDestroyReason aWhy) {
+ MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
+ Shutdown();
+}
+
+void UiCompositorControllerParent::ToolbarAnimatorMessageFromCompositor(
+ int32_t aMessage) {
+ // This function can be call from ether compositor or controller thread.
+ if (!CompositorThreadHolder::IsInCompositorThread()) {
+ CompositorThread()->Dispatch(NewRunnableMethod<int32_t>(
+ "layers::UiCompositorControllerParent::"
+ "ToolbarAnimatorMessageFromCompositor",
+ this,
+ &UiCompositorControllerParent::ToolbarAnimatorMessageFromCompositor,
+ aMessage));
+ return;
+ }
+
+ Unused << SendToolbarAnimatorMessageFromCompositor(aMessage);
+}
+
+bool UiCompositorControllerParent::AllocPixelBuffer(const int32_t aSize,
+ ipc::Shmem* aMem) {
+ MOZ_ASSERT(aSize > 0);
+ return AllocShmem(aSize, aMem);
+}
+
+void UiCompositorControllerParent::NotifyLayersUpdated() {
+#ifdef MOZ_WIDGET_ANDROID
+ if (mCompositorLayersUpdateEnabled) {
+ ToolbarAnimatorMessageFromCompositor(LAYERS_UPDATED);
+ }
+#endif
+}
+
+void UiCompositorControllerParent::NotifyFirstPaint() {
+ ToolbarAnimatorMessageFromCompositor(FIRST_PAINT);
+}
+
+void UiCompositorControllerParent::NotifyUpdateScreenMetrics(
+ const GeckoViewMetrics& aMetrics) {
+#if defined(MOZ_WIDGET_ANDROID)
+ // TODO: Need to handle different x-and y-scales.
+ CSSToScreenScale scale = ViewTargetAs<ScreenPixel>(
+ aMetrics.mZoom, PixelCastJustification::ScreenIsParentLayerForRoot);
+ ScreenPoint scrollOffset = aMetrics.mVisualScrollOffset * scale;
+ CompositorThread()->Dispatch(NewRunnableMethod<ScreenPoint, CSSToScreenScale>(
+ "UiCompositorControllerParent::SendRootFrameMetrics", this,
+ &UiCompositorControllerParent::SendRootFrameMetrics, scrollOffset,
+ scale));
+#endif
+}
+
+UiCompositorControllerParent::UiCompositorControllerParent(
+ const LayersId& aRootLayerTreeId)
+ : mRootLayerTreeId(aRootLayerTreeId)
+#ifdef MOZ_WIDGET_ANDROID
+ ,
+ mCompositorLayersUpdateEnabled(false)
+#endif
+ ,
+ mMaxToolbarHeight(0) {
+ MOZ_COUNT_CTOR(UiCompositorControllerParent);
+}
+
+UiCompositorControllerParent::~UiCompositorControllerParent() {
+ MOZ_COUNT_DTOR(UiCompositorControllerParent);
+}
+
+void UiCompositorControllerParent::InitializeForSameProcess() {
+ // This function is called by UiCompositorControllerChild in the main thread.
+ // So dispatch to the compositor thread to Initialize.
+ if (!CompositorThreadHolder::IsInCompositorThread()) {
+ SetOtherProcessId(base::GetCurrentProcId());
+ SynchronousTask task(
+ "UiCompositorControllerParent::InitializeForSameProcess");
+
+ CompositorThread()->Dispatch(NS_NewRunnableFunction(
+ "UiCompositorControllerParent::InitializeForSameProcess", [&]() {
+ AutoCompleteTask complete(&task);
+ InitializeForSameProcess();
+ }));
+
+ task.Wait();
+ return;
+ }
+
+ Initialize();
+}
+
+void UiCompositorControllerParent::InitializeForOutOfProcess() {
+ MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
+ Initialize();
+}
+
+void UiCompositorControllerParent::Initialize() {
+ MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
+ LayerTreeState* state =
+ CompositorBridgeParent::GetIndirectShadowTree(mRootLayerTreeId);
+ MOZ_ASSERT(state);
+ MOZ_ASSERT(state->mParent);
+ if (!state || !state->mParent) {
+ return;
+ }
+ state->mUiControllerParent = this;
+}
+
+void UiCompositorControllerParent::Open(
+ Endpoint<PUiCompositorControllerParent>&& aEndpoint) {
+ MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
+ if (!aEndpoint.Bind(this)) {
+ // We can't recover from this.
+ MOZ_CRASH("Failed to bind UiCompositorControllerParent to endpoint");
+ }
+ InitializeForOutOfProcess();
+}
+
+void UiCompositorControllerParent::Shutdown() {
+ MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
+ LayerTreeState* state =
+ CompositorBridgeParent::GetIndirectShadowTree(mRootLayerTreeId);
+ if (state) {
+ state->mUiControllerParent = nullptr;
+ }
+}
+
+} // namespace layers
+} // namespace mozilla