Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=99: */
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 :
7 : #include "mozilla/layers/UiCompositorControllerChild.h"
8 :
9 : #include "mozilla/dom/ContentChild.h"
10 : #include "mozilla/layers/CompositorThread.h"
11 : #include "mozilla/layers/UiCompositorControllerMessageTypes.h"
12 : #include "mozilla/layers/UiCompositorControllerParent.h"
13 : #include "mozilla/gfx/GPUProcessManager.h"
14 : #include "mozilla/StaticPtr.h"
15 : #include "nsBaseWidget.h"
16 : #include "nsThreadUtils.h"
17 :
18 : #if defined(MOZ_WIDGET_ANDROID)
19 : #include "mozilla/widget/AndroidUiThread.h"
20 :
21 : static RefPtr<nsThread>
22 : GetUiThread()
23 : {
24 : return mozilla::GetAndroidUiThread();
25 : }
26 : #else
27 : static RefPtr<nsThread>
28 0 : GetUiThread()
29 : {
30 0 : MOZ_CRASH("Platform does not support UiCompositorController");
31 : return nullptr;
32 : }
33 : #endif // defined(MOZ_WIDGET_ANDROID)
34 :
35 : static bool
36 0 : IsOnUiThread()
37 : {
38 0 : return GetUiThread()->SerialEventTarget()->IsOnCurrentThread();
39 : }
40 :
41 : namespace mozilla {
42 : namespace layers {
43 :
44 :
45 : // public:
46 : /* static */ RefPtr<UiCompositorControllerChild>
47 0 : UiCompositorControllerChild::CreateForSameProcess(const int64_t& aRootLayerTreeId)
48 : {
49 0 : RefPtr<UiCompositorControllerChild> child = new UiCompositorControllerChild(0);
50 0 : child->mParent = new UiCompositorControllerParent(aRootLayerTreeId);
51 0 : GetUiThread()->Dispatch(
52 0 : NewRunnableMethod("layers::UiCompositorControllerChild::OpenForSameProcess",
53 : child,
54 : &UiCompositorControllerChild::OpenForSameProcess),
55 0 : nsIThread::DISPATCH_NORMAL);
56 0 : return child;
57 : }
58 :
59 : /* static */ RefPtr<UiCompositorControllerChild>
60 0 : UiCompositorControllerChild::CreateForGPUProcess(const uint64_t& aProcessToken,
61 : Endpoint<PUiCompositorControllerChild>&& aEndpoint)
62 : {
63 0 : RefPtr<UiCompositorControllerChild> child = new UiCompositorControllerChild(aProcessToken);
64 :
65 : RefPtr<nsIRunnable> task =
66 0 : NewRunnableMethod<Endpoint<PUiCompositorControllerChild>&&>(
67 : "layers::UiCompositorControllerChild::OpenForGPUProcess",
68 : child,
69 : &UiCompositorControllerChild::OpenForGPUProcess,
70 0 : Move(aEndpoint));
71 :
72 0 : GetUiThread()->Dispatch(task.forget(), nsIThread::DISPATCH_NORMAL);
73 0 : return child;
74 : }
75 :
76 : bool
77 0 : UiCompositorControllerChild::Pause()
78 : {
79 0 : if (!mIsOpen) {
80 0 : return false;
81 : }
82 0 : return SendPause();
83 : }
84 :
85 : bool
86 0 : UiCompositorControllerChild::Resume()
87 : {
88 0 : if (!mIsOpen) {
89 0 : return false;
90 : }
91 0 : return SendResume();
92 : }
93 :
94 : bool
95 0 : UiCompositorControllerChild::ResumeAndResize(const int32_t& aWidth, const int32_t& aHeight)
96 : {
97 0 : if (!mIsOpen) {
98 0 : mResize = Some(gfx::IntSize(aWidth, aHeight));
99 : // Since we are caching these values, pretend the call succeeded.
100 0 : return true;
101 : }
102 0 : return SendResumeAndResize(aWidth, aHeight);
103 : }
104 :
105 : bool
106 0 : UiCompositorControllerChild::InvalidateAndRender()
107 : {
108 0 : if (!mIsOpen) {
109 0 : return false;
110 : }
111 0 : return SendInvalidateAndRender();
112 : }
113 :
114 : bool
115 0 : UiCompositorControllerChild::SetMaxToolbarHeight(const int32_t& aHeight)
116 : {
117 0 : if (!mIsOpen) {
118 0 : mMaxToolbarHeight = Some(aHeight);
119 : // Since we are caching this value, pretend the call succeeded.
120 0 : return true;
121 : }
122 0 : return SendMaxToolbarHeight(aHeight);
123 : }
124 :
125 : bool
126 0 : UiCompositorControllerChild::SetPinned(const bool& aPinned, const int32_t& aReason)
127 : {
128 0 : if (!mIsOpen) {
129 0 : return false;
130 : }
131 0 : return SendPinned(aPinned, aReason);
132 : }
133 :
134 : bool
135 0 : UiCompositorControllerChild::ToolbarAnimatorMessageFromUI(const int32_t& aMessage)
136 : {
137 0 : if (!mIsOpen) {
138 0 : return false;
139 : }
140 :
141 0 : if (aMessage == IS_COMPOSITOR_CONTROLLER_OPEN) {
142 0 : RecvToolbarAnimatorMessageFromCompositor(COMPOSITOR_CONTROLLER_OPEN);
143 0 : return true;
144 : }
145 :
146 0 : return SendToolbarAnimatorMessageFromUI(aMessage);
147 : }
148 :
149 : bool
150 0 : UiCompositorControllerChild::SetDefaultClearColor(const uint32_t& aColor)
151 : {
152 0 : if (!mIsOpen) {
153 0 : mDefaultClearColor = Some(aColor);
154 : // Since we are caching this value, pretend the call succeeded.
155 0 : return true;
156 : }
157 :
158 0 : return SendDefaultClearColor(aColor);
159 : }
160 :
161 : bool
162 0 : UiCompositorControllerChild::RequestScreenPixels()
163 : {
164 0 : if (!mIsOpen) {
165 0 : return false;
166 : }
167 :
168 0 : return SendRequestScreenPixels();
169 : }
170 :
171 : bool
172 0 : UiCompositorControllerChild::EnableLayerUpdateNotifications(const bool& aEnable)
173 : {
174 0 : if (!mIsOpen) {
175 0 : mLayerUpdateEnabled = Some(aEnable);
176 : // Since we are caching this value, pretend the call succeeded.
177 0 : return true;
178 : }
179 :
180 0 : return SendEnableLayerUpdateNotifications(aEnable);
181 : }
182 :
183 : bool
184 0 : UiCompositorControllerChild::ToolbarPixelsToCompositor(Shmem& aMem, const ScreenIntSize& aSize)
185 : {
186 0 : if (!mIsOpen) {
187 0 : return false;
188 : }
189 :
190 0 : return SendToolbarPixelsToCompositor(aMem, aSize);
191 : }
192 :
193 : void
194 0 : UiCompositorControllerChild::Destroy()
195 : {
196 0 : if (!IsOnUiThread()) {
197 0 : GetUiThread()->Dispatch(
198 0 : NewRunnableMethod("layers::UiCompositorControllerChild::Destroy",
199 : this,
200 : &UiCompositorControllerChild::Destroy),
201 0 : nsIThread::DISPATCH_NORMAL);
202 0 : return;
203 : }
204 :
205 0 : if (mIsOpen) {
206 : // Close the underlying IPC channel.
207 0 : PUiCompositorControllerChild::Close();
208 0 : mIsOpen = false;
209 : }
210 : }
211 :
212 : void
213 0 : UiCompositorControllerChild::SetBaseWidget(nsBaseWidget* aWidget)
214 : {
215 0 : mWidget = aWidget;
216 0 : }
217 :
218 : bool
219 0 : UiCompositorControllerChild::AllocPixelBuffer(const int32_t aSize, Shmem* aMem)
220 : {
221 0 : MOZ_ASSERT(aSize > 0);
222 0 : return AllocShmem(aSize, ipc::SharedMemory::TYPE_BASIC, aMem);
223 : }
224 :
225 : bool
226 0 : UiCompositorControllerChild::DeallocPixelBuffer(Shmem& aMem)
227 : {
228 0 : return DeallocShmem(aMem);
229 : }
230 :
231 : // protected:
232 : void
233 0 : UiCompositorControllerChild::ActorDestroy(ActorDestroyReason aWhy)
234 : {
235 0 : mIsOpen = false;
236 0 : mParent = nullptr;
237 :
238 0 : if (mProcessToken) {
239 0 : gfx::GPUProcessManager::Get()->NotifyRemoteActorDestroyed(mProcessToken);
240 0 : mProcessToken = 0;
241 : }
242 0 : }
243 :
244 : void
245 0 : UiCompositorControllerChild::DeallocPUiCompositorControllerChild()
246 : {
247 0 : if (mParent) {
248 0 : mParent = nullptr;
249 : }
250 0 : Release();
251 0 : }
252 :
253 : void
254 0 : UiCompositorControllerChild::ProcessingError(Result aCode, const char* aReason)
255 : {
256 0 : MOZ_RELEASE_ASSERT(aCode == MsgDropped, "Processing error in UiCompositorControllerChild");
257 0 : }
258 :
259 : void
260 0 : UiCompositorControllerChild::HandleFatalError(const char* aName, const char* aMsg) const
261 : {
262 0 : dom::ContentChild::FatalErrorIfNotUsingGPUProcess(aName, aMsg, OtherPid());
263 0 : }
264 :
265 : mozilla::ipc::IPCResult
266 0 : UiCompositorControllerChild::RecvToolbarAnimatorMessageFromCompositor(const int32_t& aMessage)
267 : {
268 : #if defined(MOZ_WIDGET_ANDROID)
269 : if (mWidget) {
270 : mWidget->RecvToolbarAnimatorMessageFromCompositor(aMessage);
271 : }
272 : #endif // defined(MOZ_WIDGET_ANDROID)
273 :
274 0 : return IPC_OK();
275 : }
276 :
277 : mozilla::ipc::IPCResult
278 0 : UiCompositorControllerChild::RecvRootFrameMetrics(const ScreenPoint& aScrollOffset, const CSSToScreenScale& aZoom)
279 : {
280 : #if defined(MOZ_WIDGET_ANDROID)
281 : if (mWidget) {
282 : mWidget->UpdateRootFrameMetrics(aScrollOffset, aZoom);
283 : }
284 : #endif // defined(MOZ_WIDGET_ANDROID)
285 :
286 0 : return IPC_OK();
287 : }
288 :
289 : mozilla::ipc::IPCResult
290 0 : UiCompositorControllerChild::RecvScreenPixels(ipc::Shmem&& aMem, const ScreenIntSize& aSize)
291 : {
292 : #if defined(MOZ_WIDGET_ANDROID)
293 : if (mWidget) {
294 : mWidget->RecvScreenPixels(Move(aMem), aSize);
295 : }
296 : #endif // defined(MOZ_WIDGET_ANDROID)
297 :
298 0 : return IPC_OK();
299 : }
300 :
301 : // private:
302 0 : UiCompositorControllerChild::UiCompositorControllerChild(const uint64_t& aProcessToken)
303 : : mIsOpen(false)
304 0 : , mProcessToken(aProcessToken)
305 0 : , mWidget(nullptr)
306 : {
307 0 : }
308 :
309 0 : UiCompositorControllerChild::~UiCompositorControllerChild()
310 : {
311 0 : }
312 :
313 : void
314 0 : UiCompositorControllerChild::OpenForSameProcess()
315 : {
316 0 : MOZ_ASSERT(IsOnUiThread());
317 :
318 0 : mIsOpen = Open(mParent->GetIPCChannel(),
319 : mozilla::layers::CompositorThreadHolder::Loop(),
320 : mozilla::ipc::ChildSide);
321 :
322 0 : if (!mIsOpen) {
323 0 : mParent = nullptr;
324 0 : return;
325 : }
326 :
327 0 : mParent->InitializeForSameProcess();
328 0 : AddRef();
329 0 : SendCachedValues();
330 : // Let Ui thread know the connection is open;
331 0 : RecvToolbarAnimatorMessageFromCompositor(COMPOSITOR_CONTROLLER_OPEN);
332 : }
333 :
334 : void
335 0 : UiCompositorControllerChild::OpenForGPUProcess(Endpoint<PUiCompositorControllerChild>&& aEndpoint)
336 : {
337 0 : MOZ_ASSERT(IsOnUiThread());
338 :
339 0 : mIsOpen = aEndpoint.Bind(this);
340 :
341 0 : if (!mIsOpen) {
342 : // The GPU Process Manager might be gone if we receive ActorDestroy very
343 : // late in shutdown.
344 0 : if (gfx::GPUProcessManager* gpm = gfx::GPUProcessManager::Get()) {
345 0 : gpm->NotifyRemoteActorDestroyed(mProcessToken);
346 : }
347 0 : return;
348 : }
349 :
350 0 : AddRef();
351 0 : SendCachedValues();
352 : // Let Ui thread know the connection is open;
353 0 : RecvToolbarAnimatorMessageFromCompositor(COMPOSITOR_CONTROLLER_OPEN);
354 : }
355 :
356 : void
357 0 : UiCompositorControllerChild::SendCachedValues()
358 : {
359 0 : MOZ_ASSERT(mIsOpen);
360 0 : if (mResize) {
361 0 : SendResumeAndResize(mResize.ref().width, mResize.ref().height);
362 0 : mResize.reset();
363 : }
364 0 : if (mMaxToolbarHeight) {
365 0 : SendMaxToolbarHeight(mMaxToolbarHeight.ref());
366 0 : mMaxToolbarHeight.reset();
367 : }
368 0 : if (mDefaultClearColor) {
369 0 : SendDefaultClearColor(mDefaultClearColor.ref());
370 0 : mDefaultClearColor.reset();
371 : }
372 0 : if (mLayerUpdateEnabled) {
373 0 : SendEnableLayerUpdateNotifications(mLayerUpdateEnabled.ref());
374 0 : mLayerUpdateEnabled.reset();
375 : }
376 0 : }
377 :
378 : } // namespace layers
379 : } // namespace mozilla
|