|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* vim: set sw=2 ts=2 et 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 |
|
7 #include "CompositorChild.h" |
|
8 #include <stddef.h> // for size_t |
|
9 #include "ClientLayerManager.h" // for ClientLayerManager |
|
10 #include "base/message_loop.h" // for MessageLoop |
|
11 #include "base/process_util.h" // for OpenProcessHandle |
|
12 #include "base/task.h" // for NewRunnableMethod, etc |
|
13 #include "base/tracked.h" // for FROM_HERE |
|
14 #include "mozilla/layers/LayerTransactionChild.h" |
|
15 #include "mozilla/layers/PLayerTransactionChild.h" |
|
16 #include "mozilla/mozalloc.h" // for operator new, etc |
|
17 #include "nsDebug.h" // for NS_RUNTIMEABORT |
|
18 #include "nsIObserver.h" // for nsIObserver |
|
19 #include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc |
|
20 #include "nsTArray.h" // for nsTArray, nsTArray_Impl |
|
21 #include "nsXULAppAPI.h" // for XRE_GetIOMessageLoop, etc |
|
22 #include "FrameLayerBuilder.h" |
|
23 #include "mozilla/dom/TabChild.h" |
|
24 |
|
25 using mozilla::layers::LayerTransactionChild; |
|
26 |
|
27 namespace mozilla { |
|
28 namespace layers { |
|
29 |
|
30 /*static*/ CompositorChild* CompositorChild::sCompositor; |
|
31 |
|
32 Atomic<int32_t> CompositableForwarder::sSerialCounter(0); |
|
33 |
|
34 CompositorChild::CompositorChild(ClientLayerManager *aLayerManager) |
|
35 : mLayerManager(aLayerManager) |
|
36 { |
|
37 MOZ_COUNT_CTOR(CompositorChild); |
|
38 } |
|
39 |
|
40 CompositorChild::~CompositorChild() |
|
41 { |
|
42 MOZ_COUNT_DTOR(CompositorChild); |
|
43 } |
|
44 |
|
45 void |
|
46 CompositorChild::Destroy() |
|
47 { |
|
48 mLayerManager->Destroy(); |
|
49 mLayerManager = nullptr; |
|
50 while (size_t len = ManagedPLayerTransactionChild().Length()) { |
|
51 LayerTransactionChild* layers = |
|
52 static_cast<LayerTransactionChild*>(ManagedPLayerTransactionChild()[len - 1]); |
|
53 layers->Destroy(); |
|
54 } |
|
55 SendStop(); |
|
56 } |
|
57 |
|
58 bool |
|
59 CompositorChild::LookupCompositorFrameMetrics(const FrameMetrics::ViewID aId, |
|
60 FrameMetrics& aFrame) |
|
61 { |
|
62 SharedFrameMetricsData* data = mFrameMetricsTable.Get(aId); |
|
63 if (data) { |
|
64 data->CopyFrameMetrics(&aFrame); |
|
65 return true; |
|
66 } |
|
67 return false; |
|
68 } |
|
69 |
|
70 /*static*/ PCompositorChild* |
|
71 CompositorChild::Create(Transport* aTransport, ProcessId aOtherProcess) |
|
72 { |
|
73 // There's only one compositor per child process. |
|
74 MOZ_ASSERT(!sCompositor); |
|
75 |
|
76 nsRefPtr<CompositorChild> child(new CompositorChild(nullptr)); |
|
77 ProcessHandle handle; |
|
78 if (!base::OpenProcessHandle(aOtherProcess, &handle)) { |
|
79 // We can't go on without a compositor. |
|
80 NS_RUNTIMEABORT("Couldn't OpenProcessHandle() to parent process."); |
|
81 return nullptr; |
|
82 } |
|
83 if (!child->Open(aTransport, handle, XRE_GetIOMessageLoop(), ipc::ChildSide)) { |
|
84 NS_RUNTIMEABORT("Couldn't Open() Compositor channel."); |
|
85 return nullptr; |
|
86 } |
|
87 // We release this ref in ActorDestroy(). |
|
88 return sCompositor = child.forget().take(); |
|
89 } |
|
90 |
|
91 /*static*/ CompositorChild* |
|
92 CompositorChild::Get() |
|
93 { |
|
94 // This is only expected to be used in child processes. |
|
95 MOZ_ASSERT(XRE_GetProcessType() != GeckoProcessType_Default); |
|
96 return sCompositor; |
|
97 } |
|
98 |
|
99 PLayerTransactionChild* |
|
100 CompositorChild::AllocPLayerTransactionChild(const nsTArray<LayersBackend>& aBackendHints, |
|
101 const uint64_t& aId, |
|
102 TextureFactoryIdentifier*, |
|
103 bool*) |
|
104 { |
|
105 LayerTransactionChild* c = new LayerTransactionChild(); |
|
106 c->AddIPDLReference(); |
|
107 return c; |
|
108 } |
|
109 |
|
110 bool |
|
111 CompositorChild::DeallocPLayerTransactionChild(PLayerTransactionChild* actor) |
|
112 { |
|
113 static_cast<LayerTransactionChild*>(actor)->ReleaseIPDLReference(); |
|
114 return true; |
|
115 } |
|
116 |
|
117 bool |
|
118 CompositorChild::RecvInvalidateAll() |
|
119 { |
|
120 FrameLayerBuilder::InvalidateAllLayers(mLayerManager); |
|
121 return true; |
|
122 } |
|
123 |
|
124 bool |
|
125 CompositorChild::RecvDidComposite(const uint64_t& aId) |
|
126 { |
|
127 if (mLayerManager) { |
|
128 MOZ_ASSERT(aId == 0); |
|
129 mLayerManager->DidComposite(); |
|
130 } else if (aId != 0) { |
|
131 dom::TabChild *child = dom::TabChild::GetFrom(aId); |
|
132 if (child) { |
|
133 child->DidComposite(); |
|
134 } |
|
135 } |
|
136 return true; |
|
137 } |
|
138 |
|
139 void |
|
140 CompositorChild::ActorDestroy(ActorDestroyReason aWhy) |
|
141 { |
|
142 MOZ_ASSERT(sCompositor == this); |
|
143 |
|
144 #ifdef MOZ_B2G |
|
145 // Due to poor lifetime management of gralloc (and possibly shmems) we will |
|
146 // crash at some point in the future when we get destroyed due to abnormal |
|
147 // shutdown. Its better just to crash here. On desktop though, we have a chance |
|
148 // of recovering. |
|
149 if (aWhy == AbnormalShutdown) { |
|
150 NS_RUNTIMEABORT("ActorDestroy by IPC channel failure at CompositorChild"); |
|
151 } |
|
152 #endif |
|
153 if (sCompositor) { |
|
154 sCompositor->Release(); |
|
155 sCompositor = nullptr; |
|
156 } |
|
157 // We don't want to release the ref to sCompositor here, during |
|
158 // cleanup, because that will cause it to be deleted while it's |
|
159 // still being used. So defer the deletion to after it's not in |
|
160 // use. |
|
161 MessageLoop::current()->PostTask( |
|
162 FROM_HERE, |
|
163 NewRunnableMethod(this, &CompositorChild::Release)); |
|
164 } |
|
165 |
|
166 bool |
|
167 CompositorChild::RecvSharedCompositorFrameMetrics( |
|
168 const mozilla::ipc::SharedMemoryBasic::Handle& metrics, |
|
169 const CrossProcessMutexHandle& handle, |
|
170 const uint32_t& aAPZCId) |
|
171 { |
|
172 SharedFrameMetricsData* data = new SharedFrameMetricsData(metrics, handle, aAPZCId); |
|
173 mFrameMetricsTable.Put(data->GetViewID(), data); |
|
174 return true; |
|
175 } |
|
176 |
|
177 bool |
|
178 CompositorChild::RecvReleaseSharedCompositorFrameMetrics( |
|
179 const ViewID& aId, |
|
180 const uint32_t& aAPZCId) |
|
181 { |
|
182 SharedFrameMetricsData* data = mFrameMetricsTable.Get(aId); |
|
183 // The SharedFrameMetricsData may have been removed previously if |
|
184 // a SharedFrameMetricsData with the same ViewID but later APZCId had |
|
185 // been store and over wrote it. |
|
186 if (data && (data->GetAPZCId() == aAPZCId)) { |
|
187 mFrameMetricsTable.Remove(aId); |
|
188 } |
|
189 return true; |
|
190 } |
|
191 |
|
192 CompositorChild::SharedFrameMetricsData::SharedFrameMetricsData( |
|
193 const ipc::SharedMemoryBasic::Handle& metrics, |
|
194 const CrossProcessMutexHandle& handle, |
|
195 const uint32_t& aAPZCId) : |
|
196 mBuffer(nullptr), |
|
197 mMutex(nullptr), |
|
198 mAPZCId(aAPZCId) |
|
199 { |
|
200 mBuffer = new ipc::SharedMemoryBasic(metrics); |
|
201 mBuffer->Map(sizeof(FrameMetrics)); |
|
202 mMutex = new CrossProcessMutex(handle); |
|
203 MOZ_COUNT_CTOR(SharedFrameMetricsData); |
|
204 } |
|
205 |
|
206 CompositorChild::SharedFrameMetricsData::~SharedFrameMetricsData() |
|
207 { |
|
208 // When the hash table deletes the class, delete |
|
209 // the shared memory and mutex. |
|
210 delete mMutex; |
|
211 delete mBuffer; |
|
212 MOZ_COUNT_DTOR(SharedFrameMetricsData); |
|
213 } |
|
214 |
|
215 void |
|
216 CompositorChild::SharedFrameMetricsData::CopyFrameMetrics(FrameMetrics* aFrame) |
|
217 { |
|
218 FrameMetrics* frame = static_cast<FrameMetrics*>(mBuffer->memory()); |
|
219 MOZ_ASSERT(frame); |
|
220 mMutex->Lock(); |
|
221 *aFrame = *frame; |
|
222 mMutex->Unlock(); |
|
223 } |
|
224 |
|
225 FrameMetrics::ViewID |
|
226 CompositorChild::SharedFrameMetricsData::GetViewID() |
|
227 { |
|
228 FrameMetrics* frame = static_cast<FrameMetrics*>(mBuffer->memory()); |
|
229 MOZ_ASSERT(frame); |
|
230 // Not locking to read of mScrollId since it should not change after being |
|
231 // initially set. |
|
232 return frame->GetScrollId(); |
|
233 } |
|
234 |
|
235 uint32_t |
|
236 CompositorChild::SharedFrameMetricsData::GetAPZCId() |
|
237 { |
|
238 return mAPZCId; |
|
239 } |
|
240 |
|
241 } // namespace layers |
|
242 } // namespace mozilla |
|
243 |