UiCompositorControllerParent.cpp (9166B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 #include "UiCompositorControllerParent.h" 7 8 #if defined(MOZ_WIDGET_ANDROID) 9 # include "apz/src/APZCTreeManager.h" 10 # include "mozilla/widget/AndroidCompositorWidget.h" 11 #endif 12 #include <utility> 13 14 #include "FrameMetrics.h" 15 #include "SynchronousTask.h" 16 #include "mozilla/gfx/Types.h" 17 #include "mozilla/ipc/Endpoint.h" 18 #include "mozilla/layers/Compositor.h" 19 #include "mozilla/layers/CompositorBridgeParent.h" 20 #include "mozilla/layers/CompositorThread.h" 21 #include "mozilla/layers/UiCompositorControllerMessageTypes.h" 22 #include "mozilla/layers/WebRenderBridgeParent.h" 23 24 namespace mozilla { 25 namespace layers { 26 27 typedef CompositorBridgeParent::LayerTreeState LayerTreeState; 28 29 /* static */ 30 RefPtr<UiCompositorControllerParent> 31 UiCompositorControllerParent::GetFromRootLayerTreeId( 32 const LayersId& aRootLayerTreeId) { 33 RefPtr<UiCompositorControllerParent> controller; 34 CompositorBridgeParent::CallWithIndirectShadowTree( 35 aRootLayerTreeId, [&](LayerTreeState& aState) -> void { 36 controller = aState.mUiControllerParent; 37 }); 38 return controller; 39 } 40 41 /* static */ 42 RefPtr<UiCompositorControllerParent> UiCompositorControllerParent::Start( 43 const LayersId& aRootLayerTreeId, 44 Endpoint<PUiCompositorControllerParent>&& aEndpoint) { 45 RefPtr<UiCompositorControllerParent> parent = 46 new UiCompositorControllerParent(aRootLayerTreeId); 47 48 RefPtr<Runnable> task = 49 NewRunnableMethod<Endpoint<PUiCompositorControllerParent>&&>( 50 "layers::UiCompositorControllerParent::Open", parent, 51 &UiCompositorControllerParent::Open, std::move(aEndpoint)); 52 CompositorThread()->Dispatch(task.forget()); 53 54 return parent; 55 } 56 57 mozilla::ipc::IPCResult UiCompositorControllerParent::RecvPause() { 58 CompositorBridgeParent* parent = 59 CompositorBridgeParent::GetCompositorBridgeParentFromLayersId( 60 mRootLayerTreeId); 61 if (parent) { 62 parent->PauseComposition(); 63 } 64 return IPC_OK(); 65 } 66 67 mozilla::ipc::IPCResult UiCompositorControllerParent::RecvResume( 68 bool* aOutResumed) { 69 *aOutResumed = false; 70 CompositorBridgeParent* parent = 71 CompositorBridgeParent::GetCompositorBridgeParentFromLayersId( 72 mRootLayerTreeId); 73 if (parent) { 74 *aOutResumed = parent->ResumeComposition(); 75 } 76 return IPC_OK(); 77 } 78 79 mozilla::ipc::IPCResult UiCompositorControllerParent::RecvResumeAndResize( 80 const int32_t& aX, const int32_t& aY, const int32_t& aWidth, 81 const int32_t& aHeight, bool* aOutResumed) { 82 *aOutResumed = false; 83 CompositorBridgeParent* parent = 84 CompositorBridgeParent::GetCompositorBridgeParentFromLayersId( 85 mRootLayerTreeId); 86 if (parent) { 87 // Front-end expects a first paint callback upon resume/resize. 88 parent->ForceIsFirstPaint(); 89 #if defined(MOZ_WIDGET_ANDROID) 90 parent->GetWidget()->AsAndroid()->NotifyClientSizeChanged( 91 LayoutDeviceIntSize(aWidth, aHeight)); 92 #endif 93 *aOutResumed = parent->ResumeCompositionAndResize(aX, aY, aWidth, aHeight); 94 } 95 return IPC_OK(); 96 } 97 98 mozilla::ipc::IPCResult 99 UiCompositorControllerParent::RecvInvalidateAndRender() { 100 CompositorBridgeParent* parent = 101 CompositorBridgeParent::GetCompositorBridgeParentFromLayersId( 102 mRootLayerTreeId); 103 if (parent) { 104 parent->ScheduleComposition(wr::RenderReasons::OTHER); 105 } 106 return IPC_OK(); 107 } 108 109 mozilla::ipc::IPCResult UiCompositorControllerParent::RecvMaxToolbarHeight( 110 const int32_t& aHeight) { 111 mMaxToolbarHeight = aHeight; 112 113 return IPC_OK(); 114 } 115 116 mozilla::ipc::IPCResult UiCompositorControllerParent::RecvFixedBottomOffset( 117 const int32_t& aOffset) { 118 #if defined(MOZ_WIDGET_ANDROID) 119 CompositorBridgeParent* parent = 120 CompositorBridgeParent::GetCompositorBridgeParentFromLayersId( 121 mRootLayerTreeId); 122 if (parent) { 123 parent->SetFixedLayerMargins(0, aOffset); 124 } 125 #endif // defined(MOZ_WIDGET_ANDROID) 126 127 return IPC_OK(); 128 } 129 130 mozilla::ipc::IPCResult UiCompositorControllerParent::RecvDefaultClearColor( 131 const uint32_t& aColor) { 132 LayerTreeState* state = 133 CompositorBridgeParent::GetIndirectShadowTree(mRootLayerTreeId); 134 135 if (state && state->mWrBridge) { 136 state->mWrBridge->SetClearColor(gfx::DeviceColor::UnusualFromARGB(aColor)); 137 } 138 139 return IPC_OK(); 140 } 141 142 mozilla::ipc::IPCResult 143 UiCompositorControllerParent::RecvRequestScreenPixels() { 144 #if defined(MOZ_WIDGET_ANDROID) 145 LayerTreeState* state = 146 CompositorBridgeParent::GetIndirectShadowTree(mRootLayerTreeId); 147 148 if (state && state->mWrBridge) { 149 state->mWrBridge->RequestScreenPixels(this); 150 state->mWrBridge->ScheduleForcedGenerateFrame(wr::RenderReasons::OTHER); 151 } 152 #endif // defined(MOZ_WIDGET_ANDROID) 153 154 return IPC_OK(); 155 } 156 157 mozilla::ipc::IPCResult 158 UiCompositorControllerParent::RecvEnableLayerUpdateNotifications( 159 const bool& aEnable) { 160 #if defined(MOZ_WIDGET_ANDROID) 161 // Layers updates are need by Robocop test which enables them 162 mCompositorLayersUpdateEnabled = aEnable; 163 #endif // defined(MOZ_WIDGET_ANDROID) 164 165 return IPC_OK(); 166 } 167 168 void UiCompositorControllerParent::ActorDestroy(ActorDestroyReason aWhy) { 169 MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread()); 170 Shutdown(); 171 } 172 173 void UiCompositorControllerParent::ToolbarAnimatorMessageFromCompositor( 174 int32_t aMessage) { 175 // This function can be call from ether compositor or controller thread. 176 if (!CompositorThreadHolder::IsInCompositorThread()) { 177 CompositorThread()->Dispatch(NewRunnableMethod<int32_t>( 178 "layers::UiCompositorControllerParent::" 179 "ToolbarAnimatorMessageFromCompositor", 180 this, 181 &UiCompositorControllerParent::ToolbarAnimatorMessageFromCompositor, 182 aMessage)); 183 return; 184 } 185 186 (void)SendToolbarAnimatorMessageFromCompositor(aMessage); 187 } 188 189 bool UiCompositorControllerParent::AllocPixelBuffer(const int32_t aSize, 190 ipc::Shmem* aMem) { 191 MOZ_ASSERT(aSize > 0); 192 return AllocShmem(aSize, aMem); 193 } 194 195 void UiCompositorControllerParent::NotifyLayersUpdated() { 196 #ifdef MOZ_WIDGET_ANDROID 197 if (mCompositorLayersUpdateEnabled) { 198 ToolbarAnimatorMessageFromCompositor(LAYERS_UPDATED); 199 } 200 #endif 201 } 202 203 void UiCompositorControllerParent::NotifyFirstPaint() { 204 ToolbarAnimatorMessageFromCompositor(FIRST_PAINT); 205 } 206 207 void UiCompositorControllerParent::NotifyCompositorScrollUpdate( 208 const CompositorScrollUpdate& aUpdate) { 209 CompositorThread()->Dispatch(NewRunnableMethod<CompositorScrollUpdate>( 210 "UiCompositorControllerParent::SendNotifyCompositorScrollUpdate", this, 211 &UiCompositorControllerParent::SendNotifyCompositorScrollUpdate, 212 aUpdate)); 213 } 214 215 UiCompositorControllerParent::UiCompositorControllerParent( 216 const LayersId& aRootLayerTreeId) 217 : mRootLayerTreeId(aRootLayerTreeId) 218 #ifdef MOZ_WIDGET_ANDROID 219 , 220 mCompositorLayersUpdateEnabled(false) 221 #endif 222 , 223 mMaxToolbarHeight(0) { 224 MOZ_COUNT_CTOR(UiCompositorControllerParent); 225 } 226 227 UiCompositorControllerParent::~UiCompositorControllerParent() { 228 MOZ_COUNT_DTOR(UiCompositorControllerParent); 229 } 230 231 void UiCompositorControllerParent::InitializeForSameProcess() { 232 // This function is called by UiCompositorControllerChild in the main thread. 233 // So dispatch to the compositor thread to Initialize. 234 if (!CompositorThreadHolder::IsInCompositorThread()) { 235 SetOtherEndpointProcInfo(ipc::EndpointProcInfo::Current()); 236 SynchronousTask task( 237 "UiCompositorControllerParent::InitializeForSameProcess"); 238 239 CompositorThread()->Dispatch(NS_NewRunnableFunction( 240 "UiCompositorControllerParent::InitializeForSameProcess", [&]() { 241 AutoCompleteTask complete(&task); 242 InitializeForSameProcess(); 243 })); 244 245 task.Wait(); 246 return; 247 } 248 249 Initialize(); 250 } 251 252 void UiCompositorControllerParent::InitializeForOutOfProcess() { 253 MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread()); 254 Initialize(); 255 } 256 257 void UiCompositorControllerParent::Initialize() { 258 MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread()); 259 LayerTreeState* state = 260 CompositorBridgeParent::GetIndirectShadowTree(mRootLayerTreeId); 261 MOZ_ASSERT(state); 262 MOZ_ASSERT(state->mParent); 263 if (!state || !state->mParent) { 264 return; 265 } 266 state->mUiControllerParent = this; 267 } 268 269 void UiCompositorControllerParent::Open( 270 Endpoint<PUiCompositorControllerParent>&& aEndpoint) { 271 MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread()); 272 if (!aEndpoint.Bind(this)) { 273 // We can't recover from this. 274 MOZ_CRASH("Failed to bind UiCompositorControllerParent to endpoint"); 275 } 276 InitializeForOutOfProcess(); 277 } 278 279 void UiCompositorControllerParent::Shutdown() { 280 MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread()); 281 LayerTreeState* state = 282 CompositorBridgeParent::GetIndirectShadowTree(mRootLayerTreeId); 283 if (state) { 284 state->mUiControllerParent = nullptr; 285 } 286 } 287 288 } // namespace layers 289 } // namespace mozilla