gecko-dev/gfx/layers/ipc/UiCompositorControllerParen...

322 строки
9.1 KiB
C++

/* -*- 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"
#endif
#include "mozilla/layers/Compositor.h"
#include "mozilla/layers/CompositorBridgeParent.h"
#include "mozilla/layers/CompositorThread.h"
#include "mozilla/layers/LayerManagerComposite.h"
#include "mozilla/gfx/Types.h"
#include "mozilla/Move.h"
#include "mozilla/Unused.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));
CompositorThreadHolder::Loop()->PostTask(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()
{
CompositorBridgeParent* parent = CompositorBridgeParent::GetCompositorBridgeParentFromLayersId(mRootLayerTreeId);
if (parent) {
parent->ResumeComposition();
}
return IPC_OK();
}
mozilla::ipc::IPCResult
UiCompositorControllerParent::RecvResumeAndResize(const int32_t& aWidth,
const int32_t& aHeight)
{
CompositorBridgeParent* parent = CompositorBridgeParent::GetCompositorBridgeParentFromLayersId(mRootLayerTreeId);
if (parent) {
// Front-end expects a first paint callback upon resume/resize.
parent->ForceIsFirstPaint();
parent->ResumeCompositionAndResize(aWidth, aHeight);
}
return IPC_OK();
}
mozilla::ipc::IPCResult
UiCompositorControllerParent::RecvInvalidateAndRender()
{
CompositorBridgeParent* parent = CompositorBridgeParent::GetCompositorBridgeParentFromLayersId(mRootLayerTreeId);
if (parent) {
parent->Invalidate();
parent->ScheduleComposition();
}
return IPC_OK();
}
mozilla::ipc::IPCResult
UiCompositorControllerParent::RecvMaxToolbarHeight(const int32_t& aHeight)
{
mMaxToolbarHeight = aHeight;
#if defined(MOZ_WIDGET_ANDROID)
if (mAnimator) {
mAnimator->SetMaxToolbarHeight(mMaxToolbarHeight);
}
#endif // defined(MOZ_WIDGET_ANDROID)
return IPC_OK();
}
mozilla::ipc::IPCResult
UiCompositorControllerParent::RecvPinned(const bool& aPinned, const int32_t& aReason)
{
#if defined(MOZ_WIDGET_ANDROID)
if (mAnimator) {
mAnimator->SetPinned(aPinned, aReason);
}
#endif // defined(MOZ_WIDGET_ANDROID)
return IPC_OK();
}
mozilla::ipc::IPCResult
UiCompositorControllerParent::RecvToolbarAnimatorMessageFromUI(const int32_t& aMessage)
{
#if defined(MOZ_WIDGET_ANDROID)
if (mAnimator) {
mAnimator->ToolbarAnimatorMessageFromUI(aMessage);
}
#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->mLayerManager) {
Compositor* compositor = state->mLayerManager->GetCompositor();
if (compositor) {
// Android Color is ARGB which is apparently unusual.
compositor->SetDefaultClearColor(gfx::Color::UnusualFromARGB(aColor));
}
}
return IPC_OK();
}
mozilla::ipc::IPCResult
UiCompositorControllerParent::RecvRequestScreenPixels()
{
#if defined(MOZ_WIDGET_ANDROID)
LayerTreeState* state = CompositorBridgeParent::GetIndirectShadowTree(mRootLayerTreeId);
if (state && state->mLayerManager && state->mParent) {
state->mLayerManager->RequestScreenPixels(this);
state->mParent->Invalidate();
state->mParent->ScheduleComposition();
}
#endif // defined(MOZ_WIDGET_ANDROID)
return IPC_OK();
}
mozilla::ipc::IPCResult
UiCompositorControllerParent::RecvEnableLayerUpdateNotifications(const bool& aEnable)
{
#if defined(MOZ_WIDGET_ANDROID)
if (mAnimator) {
mAnimator->EnableLayersUpdateNotifications(aEnable);
}
#endif // defined(MOZ_WIDGET_ANDROID)
return IPC_OK();
}
mozilla::ipc::IPCResult
UiCompositorControllerParent::RecvToolbarPixelsToCompositor(Shmem&& aMem, const ScreenIntSize& aSize)
{
#if defined(MOZ_WIDGET_ANDROID)
if (mAnimator) {
// By adopting the Shmem, the animator is responsible for deallocating.
mAnimator->AdoptToolbarPixels(std::move(aMem), aSize);
} else {
DeallocShmem(aMem);
}
#endif // defined(MOZ_WIDGET_ANDROID)
return IPC_OK();
}
void
UiCompositorControllerParent::ActorDestroy(ActorDestroyReason aWhy)
{
}
void
UiCompositorControllerParent::DeallocPUiCompositorControllerParent()
{
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
Shutdown();
Release(); // For AddRef in Initialize()
}
#if defined(MOZ_WIDGET_ANDROID)
void
UiCompositorControllerParent::RegisterAndroidDynamicToolbarAnimator(AndroidDynamicToolbarAnimator* aAnimator)
{
MOZ_ASSERT(!mAnimator);
mAnimator = aAnimator;
if (mAnimator) {
mAnimator->SetMaxToolbarHeight(mMaxToolbarHeight);
}
}
#endif // defined(MOZ_WIDGET_ANDROID)
void
UiCompositorControllerParent::ToolbarAnimatorMessageFromCompositor(int32_t aMessage)
{
// This function can be call from ether compositor or controller thread.
if (!CompositorThreadHolder::IsInCompositorThread()) {
CompositorThreadHolder::Loop()->PostTask(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, ipc::SharedMemory::TYPE_BASIC, aMem);
}
UiCompositorControllerParent::UiCompositorControllerParent(const LayersId& aRootLayerTreeId)
: mRootLayerTreeId(aRootLayerTreeId)
, 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()) {
CompositorThreadHolder::Loop()->PostTask(NewRunnableMethod(
"layers::UiCompositorControllerParent::InitializeForSameProcess",
this,
&UiCompositorControllerParent::InitializeForSameProcess));
return;
}
Initialize();
}
void
UiCompositorControllerParent::InitializeForOutOfProcess()
{
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
Initialize();
}
void
UiCompositorControllerParent::Initialize()
{
MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
AddRef();
LayerTreeState* state = CompositorBridgeParent::GetIndirectShadowTree(mRootLayerTreeId);
MOZ_ASSERT(state);
MOZ_ASSERT(state->mParent);
state->mUiControllerParent = this;
#if defined(MOZ_WIDGET_ANDROID)
AndroidDynamicToolbarAnimator* animator = state->mParent->GetAndroidDynamicToolbarAnimator();
// It is possible the compositor has already started shutting down and
// the AndroidDynamicToolbarAnimator could be a nullptr.
if (animator) {
animator->Initialize(mRootLayerTreeId);
}
#endif
}
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());
#if defined(MOZ_WIDGET_ANDROID)
if (mAnimator) {
mAnimator->Shutdown();
}
#endif // defined(MOZ_WIDGET_ANDROID)
LayerTreeState* state = CompositorBridgeParent::GetIndirectShadowTree(mRootLayerTreeId);
if (state) {
state->mUiControllerParent = nullptr;
}
}
} // namespace layers
} // namespace mozilla