зеркало из https://github.com/mozilla/gecko-dev.git
380 строки
8.9 KiB
C++
380 строки
8.9 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 "mozilla/layers/UiCompositorControllerChild.h"
|
|
|
|
#include "mozilla/dom/ContentChild.h"
|
|
#include "mozilla/layers/CompositorThread.h"
|
|
#include "mozilla/layers/UiCompositorControllerMessageTypes.h"
|
|
#include "mozilla/layers/UiCompositorControllerParent.h"
|
|
#include "mozilla/gfx/GPUProcessManager.h"
|
|
#include "mozilla/StaticPtr.h"
|
|
#include "nsBaseWidget.h"
|
|
#include "nsThreadUtils.h"
|
|
|
|
#if defined(MOZ_WIDGET_ANDROID)
|
|
#include "mozilla/widget/AndroidUiThread.h"
|
|
|
|
static RefPtr<nsThread>
|
|
GetUiThread()
|
|
{
|
|
return mozilla::GetAndroidUiThread();
|
|
}
|
|
#else
|
|
static RefPtr<nsThread>
|
|
GetUiThread()
|
|
{
|
|
MOZ_CRASH("Platform does not support UiCompositorController");
|
|
return nullptr;
|
|
}
|
|
#endif // defined(MOZ_WIDGET_ANDROID)
|
|
|
|
static bool
|
|
IsOnUiThread()
|
|
{
|
|
return GetUiThread()->SerialEventTarget()->IsOnCurrentThread();
|
|
}
|
|
|
|
namespace mozilla {
|
|
namespace layers {
|
|
|
|
|
|
// public:
|
|
/* static */ RefPtr<UiCompositorControllerChild>
|
|
UiCompositorControllerChild::CreateForSameProcess(const int64_t& aRootLayerTreeId)
|
|
{
|
|
RefPtr<UiCompositorControllerChild> child = new UiCompositorControllerChild(0);
|
|
child->mParent = new UiCompositorControllerParent(aRootLayerTreeId);
|
|
GetUiThread()->Dispatch(
|
|
NewRunnableMethod("layers::UiCompositorControllerChild::OpenForSameProcess",
|
|
child,
|
|
&UiCompositorControllerChild::OpenForSameProcess),
|
|
nsIThread::DISPATCH_NORMAL);
|
|
return child;
|
|
}
|
|
|
|
/* static */ RefPtr<UiCompositorControllerChild>
|
|
UiCompositorControllerChild::CreateForGPUProcess(const uint64_t& aProcessToken,
|
|
Endpoint<PUiCompositorControllerChild>&& aEndpoint)
|
|
{
|
|
RefPtr<UiCompositorControllerChild> child = new UiCompositorControllerChild(aProcessToken);
|
|
|
|
RefPtr<nsIRunnable> task =
|
|
NewRunnableMethod<Endpoint<PUiCompositorControllerChild>&&>(
|
|
"layers::UiCompositorControllerChild::OpenForGPUProcess",
|
|
child,
|
|
&UiCompositorControllerChild::OpenForGPUProcess,
|
|
Move(aEndpoint));
|
|
|
|
GetUiThread()->Dispatch(task.forget(), nsIThread::DISPATCH_NORMAL);
|
|
return child;
|
|
}
|
|
|
|
bool
|
|
UiCompositorControllerChild::Pause()
|
|
{
|
|
if (!mIsOpen) {
|
|
return false;
|
|
}
|
|
return SendPause();
|
|
}
|
|
|
|
bool
|
|
UiCompositorControllerChild::Resume()
|
|
{
|
|
if (!mIsOpen) {
|
|
return false;
|
|
}
|
|
return SendResume();
|
|
}
|
|
|
|
bool
|
|
UiCompositorControllerChild::ResumeAndResize(const int32_t& aWidth, const int32_t& aHeight)
|
|
{
|
|
if (!mIsOpen) {
|
|
mResize = Some(gfx::IntSize(aWidth, aHeight));
|
|
// Since we are caching these values, pretend the call succeeded.
|
|
return true;
|
|
}
|
|
return SendResumeAndResize(aWidth, aHeight);
|
|
}
|
|
|
|
bool
|
|
UiCompositorControllerChild::InvalidateAndRender()
|
|
{
|
|
if (!mIsOpen) {
|
|
return false;
|
|
}
|
|
return SendInvalidateAndRender();
|
|
}
|
|
|
|
bool
|
|
UiCompositorControllerChild::SetMaxToolbarHeight(const int32_t& aHeight)
|
|
{
|
|
if (!mIsOpen) {
|
|
mMaxToolbarHeight = Some(aHeight);
|
|
// Since we are caching this value, pretend the call succeeded.
|
|
return true;
|
|
}
|
|
return SendMaxToolbarHeight(aHeight);
|
|
}
|
|
|
|
bool
|
|
UiCompositorControllerChild::SetPinned(const bool& aPinned, const int32_t& aReason)
|
|
{
|
|
if (!mIsOpen) {
|
|
return false;
|
|
}
|
|
return SendPinned(aPinned, aReason);
|
|
}
|
|
|
|
bool
|
|
UiCompositorControllerChild::ToolbarAnimatorMessageFromUI(const int32_t& aMessage)
|
|
{
|
|
if (!mIsOpen) {
|
|
return false;
|
|
}
|
|
|
|
if (aMessage == IS_COMPOSITOR_CONTROLLER_OPEN) {
|
|
RecvToolbarAnimatorMessageFromCompositor(COMPOSITOR_CONTROLLER_OPEN);
|
|
return true;
|
|
}
|
|
|
|
return SendToolbarAnimatorMessageFromUI(aMessage);
|
|
}
|
|
|
|
bool
|
|
UiCompositorControllerChild::SetDefaultClearColor(const uint32_t& aColor)
|
|
{
|
|
if (!mIsOpen) {
|
|
mDefaultClearColor = Some(aColor);
|
|
// Since we are caching this value, pretend the call succeeded.
|
|
return true;
|
|
}
|
|
|
|
return SendDefaultClearColor(aColor);
|
|
}
|
|
|
|
bool
|
|
UiCompositorControllerChild::RequestScreenPixels()
|
|
{
|
|
if (!mIsOpen) {
|
|
return false;
|
|
}
|
|
|
|
return SendRequestScreenPixels();
|
|
}
|
|
|
|
bool
|
|
UiCompositorControllerChild::EnableLayerUpdateNotifications(const bool& aEnable)
|
|
{
|
|
if (!mIsOpen) {
|
|
mLayerUpdateEnabled = Some(aEnable);
|
|
// Since we are caching this value, pretend the call succeeded.
|
|
return true;
|
|
}
|
|
|
|
return SendEnableLayerUpdateNotifications(aEnable);
|
|
}
|
|
|
|
bool
|
|
UiCompositorControllerChild::ToolbarPixelsToCompositor(Shmem& aMem, const ScreenIntSize& aSize)
|
|
{
|
|
if (!mIsOpen) {
|
|
return false;
|
|
}
|
|
|
|
return SendToolbarPixelsToCompositor(aMem, aSize);
|
|
}
|
|
|
|
void
|
|
UiCompositorControllerChild::Destroy()
|
|
{
|
|
if (!IsOnUiThread()) {
|
|
GetUiThread()->Dispatch(
|
|
NewRunnableMethod("layers::UiCompositorControllerChild::Destroy",
|
|
this,
|
|
&UiCompositorControllerChild::Destroy),
|
|
nsIThread::DISPATCH_SYNC);
|
|
return;
|
|
}
|
|
|
|
if (mIsOpen) {
|
|
// Close the underlying IPC channel.
|
|
PUiCompositorControllerChild::Close();
|
|
mIsOpen = false;
|
|
}
|
|
}
|
|
|
|
void
|
|
UiCompositorControllerChild::SetBaseWidget(nsBaseWidget* aWidget)
|
|
{
|
|
mWidget = aWidget;
|
|
}
|
|
|
|
bool
|
|
UiCompositorControllerChild::AllocPixelBuffer(const int32_t aSize, Shmem* aMem)
|
|
{
|
|
MOZ_ASSERT(aSize > 0);
|
|
return AllocShmem(aSize, ipc::SharedMemory::TYPE_BASIC, aMem);
|
|
}
|
|
|
|
bool
|
|
UiCompositorControllerChild::DeallocPixelBuffer(Shmem& aMem)
|
|
{
|
|
return DeallocShmem(aMem);
|
|
}
|
|
|
|
// protected:
|
|
void
|
|
UiCompositorControllerChild::ActorDestroy(ActorDestroyReason aWhy)
|
|
{
|
|
mIsOpen = false;
|
|
mParent = nullptr;
|
|
|
|
if (mProcessToken) {
|
|
gfx::GPUProcessManager::Get()->NotifyRemoteActorDestroyed(mProcessToken);
|
|
mProcessToken = 0;
|
|
}
|
|
}
|
|
|
|
void
|
|
UiCompositorControllerChild::DeallocPUiCompositorControllerChild()
|
|
{
|
|
if (mParent) {
|
|
mParent = nullptr;
|
|
}
|
|
Release();
|
|
}
|
|
|
|
void
|
|
UiCompositorControllerChild::ProcessingError(Result aCode, const char* aReason)
|
|
{
|
|
MOZ_RELEASE_ASSERT(aCode == MsgDropped, "Processing error in UiCompositorControllerChild");
|
|
}
|
|
|
|
void
|
|
UiCompositorControllerChild::HandleFatalError(const char* aName, const char* aMsg) const
|
|
{
|
|
dom::ContentChild::FatalErrorIfNotUsingGPUProcess(aName, aMsg, OtherPid());
|
|
}
|
|
|
|
mozilla::ipc::IPCResult
|
|
UiCompositorControllerChild::RecvToolbarAnimatorMessageFromCompositor(const int32_t& aMessage)
|
|
{
|
|
#if defined(MOZ_WIDGET_ANDROID)
|
|
if (mWidget) {
|
|
mWidget->RecvToolbarAnimatorMessageFromCompositor(aMessage);
|
|
}
|
|
#endif // defined(MOZ_WIDGET_ANDROID)
|
|
|
|
return IPC_OK();
|
|
}
|
|
|
|
mozilla::ipc::IPCResult
|
|
UiCompositorControllerChild::RecvRootFrameMetrics(const ScreenPoint& aScrollOffset, const CSSToScreenScale& aZoom)
|
|
{
|
|
#if defined(MOZ_WIDGET_ANDROID)
|
|
if (mWidget) {
|
|
mWidget->UpdateRootFrameMetrics(aScrollOffset, aZoom);
|
|
}
|
|
#endif // defined(MOZ_WIDGET_ANDROID)
|
|
|
|
return IPC_OK();
|
|
}
|
|
|
|
mozilla::ipc::IPCResult
|
|
UiCompositorControllerChild::RecvScreenPixels(ipc::Shmem&& aMem, const ScreenIntSize& aSize)
|
|
{
|
|
#if defined(MOZ_WIDGET_ANDROID)
|
|
if (mWidget) {
|
|
mWidget->RecvScreenPixels(Move(aMem), aSize);
|
|
}
|
|
#endif // defined(MOZ_WIDGET_ANDROID)
|
|
|
|
return IPC_OK();
|
|
}
|
|
|
|
// private:
|
|
UiCompositorControllerChild::UiCompositorControllerChild(const uint64_t& aProcessToken)
|
|
: mIsOpen(false)
|
|
, mProcessToken(aProcessToken)
|
|
, mWidget(nullptr)
|
|
{
|
|
}
|
|
|
|
UiCompositorControllerChild::~UiCompositorControllerChild()
|
|
{
|
|
}
|
|
|
|
void
|
|
UiCompositorControllerChild::OpenForSameProcess()
|
|
{
|
|
MOZ_ASSERT(IsOnUiThread());
|
|
|
|
mIsOpen = Open(mParent->GetIPCChannel(),
|
|
mozilla::layers::CompositorThreadHolder::Loop(),
|
|
mozilla::ipc::ChildSide);
|
|
|
|
if (!mIsOpen) {
|
|
mParent = nullptr;
|
|
return;
|
|
}
|
|
|
|
mParent->InitializeForSameProcess();
|
|
AddRef();
|
|
SendCachedValues();
|
|
// Let Ui thread know the connection is open;
|
|
RecvToolbarAnimatorMessageFromCompositor(COMPOSITOR_CONTROLLER_OPEN);
|
|
}
|
|
|
|
void
|
|
UiCompositorControllerChild::OpenForGPUProcess(Endpoint<PUiCompositorControllerChild>&& aEndpoint)
|
|
{
|
|
MOZ_ASSERT(IsOnUiThread());
|
|
|
|
mIsOpen = aEndpoint.Bind(this);
|
|
|
|
if (!mIsOpen) {
|
|
// The GPU Process Manager might be gone if we receive ActorDestroy very
|
|
// late in shutdown.
|
|
if (gfx::GPUProcessManager* gpm = gfx::GPUProcessManager::Get()) {
|
|
gpm->NotifyRemoteActorDestroyed(mProcessToken);
|
|
}
|
|
return;
|
|
}
|
|
|
|
AddRef();
|
|
SendCachedValues();
|
|
// Let Ui thread know the connection is open;
|
|
RecvToolbarAnimatorMessageFromCompositor(COMPOSITOR_CONTROLLER_OPEN);
|
|
}
|
|
|
|
void
|
|
UiCompositorControllerChild::SendCachedValues()
|
|
{
|
|
MOZ_ASSERT(mIsOpen);
|
|
if (mResize) {
|
|
SendResumeAndResize(mResize.ref().width, mResize.ref().height);
|
|
mResize.reset();
|
|
}
|
|
if (mMaxToolbarHeight) {
|
|
SendMaxToolbarHeight(mMaxToolbarHeight.ref());
|
|
mMaxToolbarHeight.reset();
|
|
}
|
|
if (mDefaultClearColor) {
|
|
SendDefaultClearColor(mDefaultClearColor.ref());
|
|
mDefaultClearColor.reset();
|
|
}
|
|
if (mLayerUpdateEnabled) {
|
|
SendEnableLayerUpdateNotifications(mLayerUpdateEnabled.ref());
|
|
mLayerUpdateEnabled.reset();
|
|
}
|
|
}
|
|
|
|
} // namespace layers
|
|
} // namespace mozilla
|