gfx/layers/ipc/ImageBridgeChild.cpp

branch
TOR_BUG_9701
changeset 8
97036ab72558
equal deleted inserted replaced
-1:000000000000 0:98b847a36b8d
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 #include "ImageBridgeChild.h"
7 #include <vector> // for vector
8 #include "CompositorParent.h" // for CompositorParent
9 #include "ImageBridgeParent.h" // for ImageBridgeParent
10 #include "ImageContainer.h" // for ImageContainer
11 #include "Layers.h" // for Layer, etc
12 #include "ShadowLayers.h" // for ShadowLayerForwarder
13 #include "base/message_loop.h" // for MessageLoop
14 #include "base/platform_thread.h" // for PlatformThread
15 #include "base/process.h" // for ProcessHandle
16 #include "base/process_util.h" // for OpenProcessHandle
17 #include "base/task.h" // for NewRunnableFunction, etc
18 #include "base/thread.h" // for Thread
19 #include "base/tracked.h" // for FROM_HERE
20 #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
21 #include "mozilla/Monitor.h" // for Monitor, MonitorAutoLock
22 #include "mozilla/ReentrantMonitor.h" // for ReentrantMonitor, etc
23 #include "mozilla/ipc/MessageChannel.h" // for MessageChannel, etc
24 #include "mozilla/ipc/Transport.h" // for Transport
25 #include "mozilla/gfx/Point.h" // for IntSize
26 #include "mozilla/layers/CompositableClient.h" // for CompositableChild, etc
27 #include "mozilla/layers/ISurfaceAllocator.h" // for ISurfaceAllocator
28 #include "mozilla/layers/ImageClient.h" // for ImageClient
29 #include "mozilla/layers/LayersMessages.h" // for CompositableOperation
30 #include "mozilla/layers/PCompositableChild.h" // for PCompositableChild
31 #include "mozilla/layers/TextureClient.h" // for TextureClient
32 #include "mozilla/mozalloc.h" // for operator new, etc
33 #include "nsAutoPtr.h" // for nsRefPtr
34 #include "nsISupportsImpl.h" // for ImageContainer::AddRef, etc
35 #include "nsTArray.h" // for nsAutoTArray, nsTArray, etc
36 #include "nsTArrayForwardDeclare.h" // for AutoInfallibleTArray
37 #include "nsThreadUtils.h" // for NS_IsMainThread
38 #include "nsXULAppAPI.h" // for XRE_GetIOMessageLoop
39 #include "mozilla/StaticPtr.h" // for StaticRefPtr
40 #include "mozilla/layers/TextureClient.h"
41
42 struct nsIntRect;
43
44 using namespace base;
45 using namespace mozilla::ipc;
46 using namespace mozilla::gfx;
47
48 namespace mozilla {
49 namespace ipc {
50 class Shmem;
51 }
52
53 namespace layers {
54
55 class PGrallocBufferChild;
56 typedef std::vector<CompositableOperation> OpVector;
57
58 struct CompositableTransaction
59 {
60 CompositableTransaction()
61 : mSwapRequired(false)
62 , mFinished(true)
63 {}
64 ~CompositableTransaction()
65 {
66 End();
67 }
68 bool Finished() const
69 {
70 return mFinished;
71 }
72 void Begin()
73 {
74 MOZ_ASSERT(mFinished);
75 mFinished = false;
76 }
77 void End()
78 {
79 mFinished = true;
80 mSwapRequired = false;
81 mOperations.clear();
82 }
83 bool IsEmpty() const
84 {
85 return mOperations.empty();
86 }
87 void AddNoSwapEdit(const CompositableOperation& op)
88 {
89 NS_ABORT_IF_FALSE(!Finished(), "forgot BeginTransaction?");
90 mOperations.push_back(op);
91 }
92 void AddEdit(const CompositableOperation& op)
93 {
94 AddNoSwapEdit(op);
95 mSwapRequired = true;
96 }
97
98 OpVector mOperations;
99 bool mSwapRequired;
100 bool mFinished;
101 };
102
103 struct AutoEndTransaction {
104 AutoEndTransaction(CompositableTransaction* aTxn) : mTxn(aTxn) {}
105 ~AutoEndTransaction() { mTxn->End(); }
106 CompositableTransaction* mTxn;
107 };
108
109 void
110 ImageBridgeChild::UseTexture(CompositableClient* aCompositable,
111 TextureClient* aTexture)
112 {
113 MOZ_ASSERT(aCompositable);
114 MOZ_ASSERT(aTexture);
115 MOZ_ASSERT(aCompositable->GetIPDLActor());
116 MOZ_ASSERT(aTexture->GetIPDLActor());
117 mTxn->AddNoSwapEdit(OpUseTexture(nullptr, aCompositable->GetIPDLActor(),
118 nullptr, aTexture->GetIPDLActor()));
119 }
120
121 void
122 ImageBridgeChild::UseComponentAlphaTextures(CompositableClient* aCompositable,
123 TextureClient* aTextureOnBlack,
124 TextureClient* aTextureOnWhite)
125 {
126 MOZ_ASSERT(aCompositable);
127 MOZ_ASSERT(aTextureOnWhite);
128 MOZ_ASSERT(aTextureOnBlack);
129 MOZ_ASSERT(aCompositable->GetIPDLActor());
130 MOZ_ASSERT(aTextureOnWhite->GetIPDLActor());
131 MOZ_ASSERT(aTextureOnBlack->GetIPDLActor());
132 MOZ_ASSERT(aTextureOnBlack->GetSize() == aTextureOnWhite->GetSize());
133 mTxn->AddNoSwapEdit(OpUseComponentAlphaTextures(nullptr, aCompositable->GetIPDLActor(),
134 nullptr, aTextureOnBlack->GetIPDLActor(),
135 nullptr, aTextureOnWhite->GetIPDLActor()));
136 }
137
138 void
139 ImageBridgeChild::UpdatedTexture(CompositableClient* aCompositable,
140 TextureClient* aTexture,
141 nsIntRegion* aRegion)
142 {
143 MOZ_ASSERT(aCompositable);
144 MOZ_ASSERT(aTexture);
145 MOZ_ASSERT(aCompositable->GetIPDLActor());
146 MOZ_ASSERT(aTexture->GetIPDLActor());
147 MaybeRegion region = aRegion ? MaybeRegion(*aRegion)
148 : MaybeRegion(null_t());
149 mTxn->AddNoSwapEdit(OpUpdateTexture(nullptr, aCompositable->GetIPDLActor(),
150 nullptr, aTexture->GetIPDLActor(),
151 region));
152 }
153
154 void
155 ImageBridgeChild::UpdatePictureRect(CompositableClient* aCompositable,
156 const nsIntRect& aRect)
157 {
158 MOZ_ASSERT(aCompositable);
159 MOZ_ASSERT(aCompositable->GetIPDLActor());
160 mTxn->AddNoSwapEdit(OpUpdatePictureRect(nullptr, aCompositable->GetIPDLActor(), aRect));
161 }
162
163 // Singleton
164 static StaticRefPtr<ImageBridgeChild> sImageBridgeChildSingleton;
165 static StaticRefPtr<ImageBridgeParent> sImageBridgeParentSingleton;
166 static Thread *sImageBridgeChildThread = nullptr;
167
168 void ReleaseImageBridgeParentSingleton() {
169 sImageBridgeParentSingleton = nullptr;
170 }
171
172 // dispatched function
173 static void ImageBridgeShutdownStep1(ReentrantMonitor *aBarrier, bool *aDone)
174 {
175 ReentrantMonitorAutoEnter autoMon(*aBarrier);
176
177 NS_ABORT_IF_FALSE(InImageBridgeChildThread(),
178 "Should be in ImageBridgeChild thread.");
179 if (sImageBridgeChildSingleton) {
180 // Force all managed protocols to shut themselves down cleanly
181 InfallibleTArray<PCompositableChild*> compositables;
182 sImageBridgeChildSingleton->ManagedPCompositableChild(compositables);
183 for (int i = compositables.Length() - 1; i >= 0; --i) {
184 CompositableClient::FromIPDLActor(compositables[i])->Destroy();
185 }
186 InfallibleTArray<PTextureChild*> textures;
187 sImageBridgeChildSingleton->ManagedPTextureChild(textures);
188 for (int i = textures.Length() - 1; i >= 0; --i) {
189 TextureClient::AsTextureClient(textures[i])->ForceRemove();
190 }
191 sImageBridgeChildSingleton->SendWillStop();
192 sImageBridgeChildSingleton->MarkShutDown();
193 // From now on, no message can be sent through the image bridge from the
194 // client side except the final Stop message.
195 }
196 *aDone = true;
197 aBarrier->NotifyAll();
198 }
199
200 // dispatched function
201 static void ImageBridgeShutdownStep2(ReentrantMonitor *aBarrier, bool *aDone)
202 {
203 ReentrantMonitorAutoEnter autoMon(*aBarrier);
204
205 NS_ABORT_IF_FALSE(InImageBridgeChildThread(),
206 "Should be in ImageBridgeChild thread.");
207
208 sImageBridgeChildSingleton->SendStop();
209
210 sImageBridgeChildSingleton = nullptr;
211
212 *aDone = true;
213 aBarrier->NotifyAll();
214 }
215
216 // dispatched function
217 static void CreateImageClientSync(RefPtr<ImageClient>* result,
218 ReentrantMonitor* barrier,
219 CompositableType aType,
220 bool *aDone)
221 {
222 ReentrantMonitorAutoEnter autoMon(*barrier);
223 *result = sImageBridgeChildSingleton->CreateImageClientNow(aType);
224 *aDone = true;
225 barrier->NotifyAll();
226 }
227
228
229 struct GrallocParam {
230 IntSize size;
231 uint32_t format;
232 uint32_t usage;
233 MaybeMagicGrallocBufferHandle* handle;
234 PGrallocBufferChild** child;
235
236 GrallocParam(const IntSize& aSize,
237 const uint32_t& aFormat,
238 const uint32_t& aUsage,
239 MaybeMagicGrallocBufferHandle* aHandle,
240 PGrallocBufferChild** aChild)
241 : size(aSize)
242 , format(aFormat)
243 , usage(aUsage)
244 , handle(aHandle)
245 , child(aChild)
246 {}
247 };
248
249 // dispatched function
250 static void AllocGrallocBufferSync(const GrallocParam& aParam,
251 Monitor* aBarrier,
252 bool* aDone)
253 {
254 MonitorAutoLock autoMon(*aBarrier);
255
256 sImageBridgeChildSingleton->AllocGrallocBufferNow(aParam.size,
257 aParam.format,
258 aParam.usage,
259 aParam.handle,
260 aParam.child);
261 *aDone = true;
262 aBarrier->NotifyAll();
263 }
264
265 // dispatched function
266 static void ConnectImageBridge(ImageBridgeChild * child, ImageBridgeParent * parent)
267 {
268 MessageLoop *parentMsgLoop = parent->GetMessageLoop();
269 ipc::MessageChannel *parentChannel = parent->GetIPCChannel();
270 child->Open(parentChannel, parentMsgLoop, mozilla::ipc::ChildSide);
271 }
272
273 ImageBridgeChild::ImageBridgeChild()
274 : mShuttingDown(false)
275 {
276 mTxn = new CompositableTransaction();
277 }
278 ImageBridgeChild::~ImageBridgeChild()
279 {
280 delete mTxn;
281 }
282
283 void
284 ImageBridgeChild::MarkShutDown()
285 {
286 MOZ_ASSERT(!mShuttingDown);
287 mShuttingDown = true;
288 }
289
290 void
291 ImageBridgeChild::Connect(CompositableClient* aCompositable)
292 {
293 MOZ_ASSERT(aCompositable);
294 MOZ_ASSERT(!mShuttingDown);
295 uint64_t id = 0;
296 PCompositableChild* child =
297 SendPCompositableConstructor(aCompositable->GetTextureInfo(), &id);
298 MOZ_ASSERT(child);
299 aCompositable->InitIPDLActor(child, id);
300 }
301
302 PCompositableChild*
303 ImageBridgeChild::AllocPCompositableChild(const TextureInfo& aInfo, uint64_t* aID)
304 {
305 MOZ_ASSERT(!mShuttingDown);
306 return CompositableClient::CreateIPDLActor();
307 }
308
309 bool
310 ImageBridgeChild::DeallocPCompositableChild(PCompositableChild* aActor)
311 {
312 return CompositableClient::DestroyIPDLActor(aActor);
313 }
314
315
316 Thread* ImageBridgeChild::GetThread() const
317 {
318 return sImageBridgeChildThread;
319 }
320
321 ImageBridgeChild* ImageBridgeChild::GetSingleton()
322 {
323 return sImageBridgeChildSingleton;
324 }
325
326 bool ImageBridgeChild::IsCreated()
327 {
328 return GetSingleton() != nullptr;
329 }
330
331 void ImageBridgeChild::StartUp()
332 {
333 NS_ASSERTION(NS_IsMainThread(), "Should be on the main Thread!");
334 ImageBridgeChild::StartUpOnThread(new Thread("ImageBridgeChild"));
335 }
336
337 #ifdef MOZ_NUWA_PROCESS
338 #include "ipc/Nuwa.h"
339 #endif
340
341 static void
342 ConnectImageBridgeInChildProcess(Transport* aTransport,
343 ProcessHandle aOtherProcess)
344 {
345 // Bind the IPC channel to the image bridge thread.
346 sImageBridgeChildSingleton->Open(aTransport, aOtherProcess,
347 XRE_GetIOMessageLoop(),
348 ipc::ChildSide);
349 #ifdef MOZ_NUWA_PROCESS
350 if (IsNuwaProcess()) {
351 sImageBridgeChildThread
352 ->message_loop()->PostTask(FROM_HERE,
353 NewRunnableFunction(NuwaMarkCurrentThread,
354 (void (*)(void *))nullptr,
355 (void *)nullptr));
356 }
357 #endif
358 }
359
360 static void ReleaseImageClientNow(ImageClient* aClient)
361 {
362 MOZ_ASSERT(InImageBridgeChildThread());
363 aClient->Release();
364 }
365
366 // static
367 void ImageBridgeChild::DispatchReleaseImageClient(ImageClient* aClient)
368 {
369 if (!IsCreated()) {
370 // CompositableClient::Release should normally happen in the ImageBridgeChild
371 // thread because it usually generate some IPDL messages.
372 // However, if we take this branch it means that the ImageBridgeChild
373 // has already shut down, along with the CompositableChild, which means no
374 // message will be sent and it is safe to run this code from any thread.
375 MOZ_ASSERT(aClient->GetIPDLActor() == nullptr);
376 aClient->Release();
377 return;
378 }
379
380 sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
381 FROM_HERE,
382 NewRunnableFunction(&ReleaseImageClientNow, aClient));
383 }
384
385 static void ReleaseTextureClientNow(TextureClient* aClient)
386 {
387 MOZ_ASSERT(InImageBridgeChildThread());
388 aClient->Release();
389 }
390
391 // static
392 void ImageBridgeChild::DispatchReleaseTextureClient(TextureClient* aClient)
393 {
394 if (!IsCreated()) {
395 // TextureClient::Release should normally happen in the ImageBridgeChild
396 // thread because it usually generate some IPDL messages.
397 // However, if we take this branch it means that the ImageBridgeChild
398 // has already shut down, along with the TextureChild, which means no
399 // message will be sent and it is safe to run this code from any thread.
400 MOZ_ASSERT(aClient->GetIPDLActor() == nullptr);
401 aClient->Release();
402 return;
403 }
404
405 sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
406 FROM_HERE,
407 NewRunnableFunction(&ReleaseTextureClientNow, aClient));
408 }
409
410 static void UpdateImageClientNow(ImageClient* aClient, ImageContainer* aContainer)
411 {
412 MOZ_ASSERT(aClient);
413 MOZ_ASSERT(aContainer);
414 sImageBridgeChildSingleton->BeginTransaction();
415 aClient->UpdateImage(aContainer, Layer::CONTENT_OPAQUE);
416 aClient->OnTransaction();
417 sImageBridgeChildSingleton->EndTransaction();
418 }
419
420 //static
421 void ImageBridgeChild::DispatchImageClientUpdate(ImageClient* aClient,
422 ImageContainer* aContainer)
423 {
424 if (!IsCreated()) {
425 return;
426 }
427
428 if (InImageBridgeChildThread()) {
429 UpdateImageClientNow(aClient, aContainer);
430 return;
431 }
432 sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
433 FROM_HERE,
434 NewRunnableFunction<
435 void (*)(ImageClient*, ImageContainer*),
436 ImageClient*,
437 nsRefPtr<ImageContainer> >(&UpdateImageClientNow, aClient, aContainer));
438 }
439
440 static void FlushAllImagesSync(ImageClient* aClient, ImageContainer* aContainer, bool aExceptFront, ReentrantMonitor* aBarrier, bool* aDone)
441 {
442 ImageBridgeChild::FlushAllImagesNow(aClient, aContainer, aExceptFront);
443
444 ReentrantMonitorAutoEnter autoMon(*aBarrier);
445 *aDone = true;
446 aBarrier->NotifyAll();
447 }
448
449 //static
450 void ImageBridgeChild::FlushAllImages(ImageClient* aClient, ImageContainer* aContainer, bool aExceptFront)
451 {
452 if (!IsCreated()) {
453 return;
454 }
455
456 MOZ_ASSERT(!sImageBridgeChildSingleton->mShuttingDown);
457
458 if (InImageBridgeChildThread()) {
459 FlushAllImagesNow(aClient, aContainer, aExceptFront);
460 return;
461 }
462
463 ReentrantMonitor barrier("CreateImageClient Lock");
464 ReentrantMonitorAutoEnter autoMon(barrier);
465 bool done = false;
466
467 sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
468 FROM_HERE,
469 NewRunnableFunction(&FlushAllImagesSync, aClient, aContainer, aExceptFront, &barrier, &done));
470
471 // should stop the thread until the ImageClient has been created on
472 // the other thread
473 while (!done) {
474 barrier.Wait();
475 }
476 }
477
478 //static
479 void ImageBridgeChild::FlushAllImagesNow(ImageClient* aClient, ImageContainer* aContainer, bool aExceptFront)
480 {
481 MOZ_ASSERT(aClient);
482 sImageBridgeChildSingleton->BeginTransaction();
483 if (aContainer && !aExceptFront) {
484 aContainer->ClearCurrentImage();
485 }
486 aClient->FlushAllImages(aExceptFront);
487 aClient->OnTransaction();
488 sImageBridgeChildSingleton->EndTransaction();
489 }
490
491 void
492 ImageBridgeChild::BeginTransaction()
493 {
494 MOZ_ASSERT(!mShuttingDown);
495 MOZ_ASSERT(mTxn->Finished(), "uncommitted txn?");
496 mTxn->Begin();
497 }
498
499 class MOZ_STACK_CLASS AutoRemoveTextures
500 {
501 public:
502 AutoRemoveTextures(ImageBridgeChild* aImageBridge)
503 : mImageBridge(aImageBridge) {}
504
505 ~AutoRemoveTextures()
506 {
507 mImageBridge->RemoveTexturesIfNecessary();
508 }
509 private:
510 ImageBridgeChild* mImageBridge;
511 };
512
513 void
514 ImageBridgeChild::EndTransaction()
515 {
516 MOZ_ASSERT(!mShuttingDown);
517 MOZ_ASSERT(!mTxn->Finished(), "forgot BeginTransaction?");
518
519 AutoEndTransaction _(mTxn);
520 AutoRemoveTextures autoRemoveTextures(this);
521
522 if (mTxn->IsEmpty()) {
523 return;
524 }
525
526 AutoInfallibleTArray<CompositableOperation, 10> cset;
527 cset.SetCapacity(mTxn->mOperations.size());
528 if (!mTxn->mOperations.empty()) {
529 cset.AppendElements(&mTxn->mOperations.front(), mTxn->mOperations.size());
530 }
531 ShadowLayerForwarder::PlatformSyncBeforeUpdate();
532
533 AutoInfallibleTArray<EditReply, 10> replies;
534
535 if (mTxn->mSwapRequired) {
536 if (!SendUpdate(cset, &replies)) {
537 NS_WARNING("could not send async texture transaction");
538 return;
539 }
540 } else {
541 // If we don't require a swap we can call SendUpdateNoSwap which
542 // assumes that aReplies is empty (DEBUG assertion)
543 if (!SendUpdateNoSwap(cset)) {
544 NS_WARNING("could not send async texture transaction (no swap)");
545 return;
546 }
547 }
548 for (nsTArray<EditReply>::size_type i = 0; i < replies.Length(); ++i) {
549 const EditReply& reply = replies[i];
550 switch (reply.type()) {
551 case EditReply::TOpTextureSwap: {
552 const OpTextureSwap& ots = reply.get_OpTextureSwap();
553
554 CompositableClient* compositable =
555 CompositableClient::FromIPDLActor(ots.compositableChild());
556
557 MOZ_ASSERT(compositable);
558
559 compositable->SetDescriptorFromReply(ots.textureId(), ots.image());
560 break;
561 }
562 case EditReply::TReturnReleaseFence: {
563 const ReturnReleaseFence& rep = reply.get_ReturnReleaseFence();
564 FenceHandle fence = rep.fence();
565 PTextureChild* child = rep.textureChild();
566
567 if (!fence.IsValid() || !child) {
568 break;
569 }
570 RefPtr<TextureClient> texture = TextureClient::AsTextureClient(child);
571 if (texture) {
572 texture->SetReleaseFenceHandle(fence);
573 }
574 break;
575 }
576 default:
577 NS_RUNTIMEABORT("not reached");
578 }
579 }
580 }
581
582
583 PImageBridgeChild*
584 ImageBridgeChild::StartUpInChildProcess(Transport* aTransport,
585 ProcessId aOtherProcess)
586 {
587 NS_ASSERTION(NS_IsMainThread(), "Should be on the main Thread!");
588
589 ProcessHandle processHandle;
590 if (!base::OpenProcessHandle(aOtherProcess, &processHandle)) {
591 return nullptr;
592 }
593
594 sImageBridgeChildThread = new Thread("ImageBridgeChild");
595 if (!sImageBridgeChildThread->Start()) {
596 return nullptr;
597 }
598
599 sImageBridgeChildSingleton = new ImageBridgeChild();
600 sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
601 FROM_HERE,
602 NewRunnableFunction(ConnectImageBridgeInChildProcess,
603 aTransport, processHandle));
604
605 return sImageBridgeChildSingleton;
606 }
607
608 void ImageBridgeChild::ShutDown()
609 {
610 MOZ_ASSERT(NS_IsMainThread(), "Should be on the main Thread!");
611 if (ImageBridgeChild::IsCreated()) {
612 MOZ_ASSERT(!sImageBridgeChildSingleton->mShuttingDown);
613
614 {
615 ReentrantMonitor barrier("ImageBridge ShutdownStep1 lock");
616 ReentrantMonitorAutoEnter autoMon(barrier);
617
618 bool done = false;
619 sImageBridgeChildSingleton->GetMessageLoop()->PostTask(FROM_HERE,
620 NewRunnableFunction(&ImageBridgeShutdownStep1, &barrier, &done));
621 while (!done) {
622 barrier.Wait();
623 }
624 }
625
626 {
627 ReentrantMonitor barrier("ImageBridge ShutdownStep2 lock");
628 ReentrantMonitorAutoEnter autoMon(barrier);
629
630 bool done = false;
631 sImageBridgeChildSingleton->GetMessageLoop()->PostTask(FROM_HERE,
632 NewRunnableFunction(&ImageBridgeShutdownStep2, &barrier, &done));
633 while (!done) {
634 barrier.Wait();
635 }
636 }
637
638 delete sImageBridgeChildThread;
639 sImageBridgeChildThread = nullptr;
640 }
641 }
642
643 bool ImageBridgeChild::StartUpOnThread(Thread* aThread)
644 {
645 NS_ABORT_IF_FALSE(aThread, "ImageBridge needs a thread.");
646 if (sImageBridgeChildSingleton == nullptr) {
647 sImageBridgeChildThread = aThread;
648 if (!aThread->IsRunning()) {
649 aThread->Start();
650 }
651 sImageBridgeChildSingleton = new ImageBridgeChild();
652 sImageBridgeParentSingleton = new ImageBridgeParent(
653 CompositorParent::CompositorLoop(), nullptr);
654 sImageBridgeChildSingleton->ConnectAsync(sImageBridgeParentSingleton);
655 return true;
656 } else {
657 return false;
658 }
659 }
660
661 bool InImageBridgeChildThread()
662 {
663 return sImageBridgeChildThread->thread_id() == PlatformThread::CurrentId();
664 }
665
666 MessageLoop * ImageBridgeChild::GetMessageLoop() const
667 {
668 return sImageBridgeChildThread->message_loop();
669 }
670
671 void ImageBridgeChild::ConnectAsync(ImageBridgeParent* aParent)
672 {
673 GetMessageLoop()->PostTask(FROM_HERE, NewRunnableFunction(&ConnectImageBridge,
674 this, aParent));
675 }
676
677 void
678 ImageBridgeChild::IdentifyCompositorTextureHost(const TextureFactoryIdentifier& aIdentifier)
679 {
680 if (sImageBridgeChildSingleton) {
681 sImageBridgeChildSingleton->IdentifyTextureHost(aIdentifier);
682 }
683 }
684
685 TemporaryRef<ImageClient>
686 ImageBridgeChild::CreateImageClient(CompositableType aType)
687 {
688 if (InImageBridgeChildThread()) {
689 return CreateImageClientNow(aType);
690 }
691 ReentrantMonitor barrier("CreateImageClient Lock");
692 ReentrantMonitorAutoEnter autoMon(barrier);
693 bool done = false;
694
695 RefPtr<ImageClient> result = nullptr;
696 GetMessageLoop()->PostTask(FROM_HERE, NewRunnableFunction(&CreateImageClientSync,
697 &result, &barrier, aType, &done));
698 // should stop the thread until the ImageClient has been created on
699 // the other thread
700 while (!done) {
701 barrier.Wait();
702 }
703 return result.forget();
704 }
705
706 TemporaryRef<ImageClient>
707 ImageBridgeChild::CreateImageClientNow(CompositableType aType)
708 {
709 MOZ_ASSERT(!sImageBridgeChildSingleton->mShuttingDown);
710 RefPtr<ImageClient> client
711 = ImageClient::CreateImageClient(aType, this, 0);
712 MOZ_ASSERT(client, "failed to create ImageClient");
713 if (client) {
714 client->Connect();
715 }
716 return client.forget();
717 }
718
719 PGrallocBufferChild*
720 ImageBridgeChild::AllocPGrallocBufferChild(const IntSize&, const uint32_t&, const uint32_t&,
721 MaybeMagicGrallocBufferHandle*)
722 {
723 #ifdef MOZ_HAVE_SURFACEDESCRIPTORGRALLOC
724 return GrallocBufferActor::Create();
725 #else
726 NS_RUNTIMEABORT("No gralloc buffers for you");
727 return nullptr;
728 #endif
729 }
730
731 bool
732 ImageBridgeChild::DeallocPGrallocBufferChild(PGrallocBufferChild* actor)
733 {
734 #ifdef MOZ_HAVE_SURFACEDESCRIPTORGRALLOC
735 delete actor;
736 return true;
737 #else
738 NS_RUNTIMEABORT("Um, how did we get here?");
739 return false;
740 #endif
741 }
742
743 bool
744 ImageBridgeChild::AllocUnsafeShmem(size_t aSize,
745 ipc::SharedMemory::SharedMemoryType aType,
746 ipc::Shmem* aShmem)
747 {
748 MOZ_ASSERT(!mShuttingDown);
749 if (InImageBridgeChildThread()) {
750 return PImageBridgeChild::AllocUnsafeShmem(aSize, aType, aShmem);
751 } else {
752 return DispatchAllocShmemInternal(aSize, aType, aShmem, true); // true: unsafe
753 }
754 }
755
756 bool
757 ImageBridgeChild::AllocShmem(size_t aSize,
758 ipc::SharedMemory::SharedMemoryType aType,
759 ipc::Shmem* aShmem)
760 {
761 if (InImageBridgeChildThread()) {
762 return PImageBridgeChild::AllocShmem(aSize, aType, aShmem);
763 } else {
764 return DispatchAllocShmemInternal(aSize, aType, aShmem, false); // false: unsafe
765 }
766 }
767
768 // NewRunnableFunction accepts a limited number of parameters so we need a
769 // struct here
770 struct AllocShmemParams {
771 RefPtr<ISurfaceAllocator> mAllocator;
772 size_t mSize;
773 ipc::SharedMemory::SharedMemoryType mType;
774 ipc::Shmem* mShmem;
775 bool mUnsafe;
776 bool mSuccess;
777 };
778
779 static void ProxyAllocShmemNow(AllocShmemParams* aParams,
780 ReentrantMonitor* aBarrier,
781 bool* aDone)
782 {
783 MOZ_ASSERT(aParams);
784 MOZ_ASSERT(aDone);
785 MOZ_ASSERT(aBarrier);
786
787 if (aParams->mUnsafe) {
788 aParams->mSuccess = aParams->mAllocator->AllocUnsafeShmem(aParams->mSize,
789 aParams->mType,
790 aParams->mShmem);
791 } else {
792 aParams->mSuccess = aParams->mAllocator->AllocShmem(aParams->mSize,
793 aParams->mType,
794 aParams->mShmem);
795 }
796
797 ReentrantMonitorAutoEnter autoMon(*aBarrier);
798 *aDone = true;
799 aBarrier->NotifyAll();
800 }
801
802 bool
803 ImageBridgeChild::DispatchAllocShmemInternal(size_t aSize,
804 SharedMemory::SharedMemoryType aType,
805 ipc::Shmem* aShmem,
806 bool aUnsafe)
807 {
808 ReentrantMonitor barrier("AllocatorProxy alloc");
809 ReentrantMonitorAutoEnter autoMon(barrier);
810
811 AllocShmemParams params = {
812 this, aSize, aType, aShmem, aUnsafe, true
813 };
814 bool done = false;
815
816 GetMessageLoop()->PostTask(FROM_HERE,
817 NewRunnableFunction(&ProxyAllocShmemNow,
818 &params,
819 &barrier,
820 &done));
821 while (!done) {
822 barrier.Wait();
823 }
824 return params.mSuccess;
825 }
826
827 static void ProxyDeallocShmemNow(ISurfaceAllocator* aAllocator,
828 ipc::Shmem* aShmem,
829 ReentrantMonitor* aBarrier,
830 bool* aDone)
831 {
832 MOZ_ASSERT(aShmem);
833 MOZ_ASSERT(aDone);
834 MOZ_ASSERT(aBarrier);
835
836 aAllocator->DeallocShmem(*aShmem);
837
838 ReentrantMonitorAutoEnter autoMon(*aBarrier);
839 *aDone = true;
840 aBarrier->NotifyAll();
841 }
842
843 void
844 ImageBridgeChild::DeallocShmem(ipc::Shmem& aShmem)
845 {
846 if (InImageBridgeChildThread()) {
847 PImageBridgeChild::DeallocShmem(aShmem);
848 } else {
849 ReentrantMonitor barrier("AllocatorProxy Dealloc");
850 ReentrantMonitorAutoEnter autoMon(barrier);
851
852 bool done = false;
853 GetMessageLoop()->PostTask(FROM_HERE,
854 NewRunnableFunction(&ProxyDeallocShmemNow,
855 this,
856 &aShmem,
857 &barrier,
858 &done));
859 while (!done) {
860 barrier.Wait();
861 }
862 }
863 }
864
865 PGrallocBufferChild*
866 ImageBridgeChild::AllocGrallocBuffer(const IntSize& aSize,
867 uint32_t aFormat,
868 uint32_t aUsage,
869 MaybeMagicGrallocBufferHandle* aHandle)
870 {
871 if (InImageBridgeChildThread()) {
872 PGrallocBufferChild* child = nullptr;
873 ImageBridgeChild::AllocGrallocBufferNow(aSize, aFormat, aUsage, aHandle, &child);
874 return child;
875 }
876
877 Monitor barrier("AllocGrallocBuffer Lock");
878 MonitorAutoLock autoMon(barrier);
879 bool done = false;
880 PGrallocBufferChild* child = nullptr;
881
882 GetMessageLoop()->PostTask(
883 FROM_HERE,
884 NewRunnableFunction(&AllocGrallocBufferSync,
885 GrallocParam(aSize, aFormat, aUsage, aHandle, &child), &barrier, &done));
886
887 while (!done) {
888 barrier.Wait();
889 }
890
891 return child;
892 }
893
894 void
895 ImageBridgeChild::AllocGrallocBufferNow(const gfx::IntSize& aSize,
896 uint32_t aFormat, uint32_t aUsage,
897 MaybeMagicGrallocBufferHandle* aHandle,
898 PGrallocBufferChild** aChild)
899 {
900 #ifdef MOZ_WIDGET_GONK
901 *aChild = SendPGrallocBufferConstructor(aSize,
902 aFormat,
903 aUsage,
904 aHandle);
905 #else
906 NS_RUNTIMEABORT("not implemented");
907 aChild = nullptr;
908 #endif
909 }
910
911 static void ProxyDeallocGrallocBufferNow(ISurfaceAllocator* aAllocator,
912 PGrallocBufferChild* aChild,
913 ReentrantMonitor* aBarrier,
914 bool* aDone)
915 {
916 MOZ_ASSERT(aChild);
917 MOZ_ASSERT(aDone);
918 MOZ_ASSERT(aBarrier);
919
920 #ifdef MOZ_WIDGET_GONK
921 PGrallocBufferChild::Send__delete__(aChild);
922 #else
923 NS_RUNTIMEABORT("not implemented");
924 #endif
925
926 ReentrantMonitorAutoEnter autoMon(*aBarrier);
927 *aDone = true;
928 aBarrier->NotifyAll();
929 }
930
931 void
932 ImageBridgeChild::DeallocGrallocBuffer(PGrallocBufferChild* aChild)
933 {
934 MOZ_ASSERT(aChild);
935 if (InImageBridgeChildThread()) {
936 #ifdef MOZ_WIDGET_GONK
937 PGrallocBufferChild::Send__delete__(aChild);
938 #else
939 NS_RUNTIMEABORT("not implemented");
940 #endif
941 } else {
942 ReentrantMonitor barrier("AllocatorProxy Dealloc");
943 ReentrantMonitorAutoEnter autoMon(barrier);
944
945 bool done = false;
946 GetMessageLoop()->PostTask(FROM_HERE,
947 NewRunnableFunction(&ProxyDeallocGrallocBufferNow,
948 this,
949 aChild,
950 &barrier,
951 &done));
952 while (!done) {
953 barrier.Wait();
954 }
955 }
956 }
957
958 PTextureChild*
959 ImageBridgeChild::AllocPTextureChild(const SurfaceDescriptor&,
960 const TextureFlags&)
961 {
962 MOZ_ASSERT(!mShuttingDown);
963 return TextureClient::CreateIPDLActor();
964 }
965
966 bool
967 ImageBridgeChild::DeallocPTextureChild(PTextureChild* actor)
968 {
969 return TextureClient::DestroyIPDLActor(actor);
970 }
971
972 PTextureChild*
973 ImageBridgeChild::CreateTexture(const SurfaceDescriptor& aSharedData,
974 TextureFlags aFlags)
975 {
976 MOZ_ASSERT(!mShuttingDown);
977 return SendPTextureConstructor(aSharedData, aFlags);
978 }
979
980 void
981 ImageBridgeChild::RemoveTextureFromCompositable(CompositableClient* aCompositable,
982 TextureClient* aTexture)
983 {
984 MOZ_ASSERT(!mShuttingDown);
985 if (aTexture->GetFlags() & TEXTURE_DEALLOCATE_CLIENT) {
986 mTxn->AddEdit(OpRemoveTexture(nullptr, aCompositable->GetIPDLActor(),
987 nullptr, aTexture->GetIPDLActor()));
988 } else {
989 mTxn->AddNoSwapEdit(OpRemoveTexture(nullptr, aCompositable->GetIPDLActor(),
990 nullptr, aTexture->GetIPDLActor()));
991 }
992 // Hold texture until transaction complete.
993 HoldUntilTransaction(aTexture);
994 }
995
996 static void RemoveTextureSync(TextureClient* aTexture, ReentrantMonitor* aBarrier, bool* aDone)
997 {
998 aTexture->ForceRemove();
999
1000 ReentrantMonitorAutoEnter autoMon(*aBarrier);
1001 *aDone = true;
1002 aBarrier->NotifyAll();
1003 }
1004
1005 void ImageBridgeChild::RemoveTexture(TextureClient* aTexture)
1006 {
1007 if (InImageBridgeChildThread()) {
1008 MOZ_ASSERT(!mShuttingDown);
1009 aTexture->ForceRemove();
1010 return;
1011 }
1012
1013 ReentrantMonitor barrier("RemoveTexture Lock");
1014 ReentrantMonitorAutoEnter autoMon(barrier);
1015 bool done = false;
1016
1017 sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
1018 FROM_HERE,
1019 NewRunnableFunction(&RemoveTextureSync, aTexture, &barrier, &done));
1020
1021 // should stop the thread until the ImageClient has been created on
1022 // the other thread
1023 while (!done) {
1024 barrier.Wait();
1025 }
1026 }
1027
1028 bool ImageBridgeChild::IsSameProcess() const
1029 {
1030 return OtherProcess() == ipc::kInvalidProcessHandle;
1031 }
1032
1033 } // layers
1034 } // mozilla

mercurial