gfx/layers/ipc/CompositorChild.cpp

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:f81e13753cbb
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

mercurial