1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/layers/ipc/ImageBridgeChild.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1034 @@ 1.4 +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- 1.5 + * This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "ImageBridgeChild.h" 1.10 +#include <vector> // for vector 1.11 +#include "CompositorParent.h" // for CompositorParent 1.12 +#include "ImageBridgeParent.h" // for ImageBridgeParent 1.13 +#include "ImageContainer.h" // for ImageContainer 1.14 +#include "Layers.h" // for Layer, etc 1.15 +#include "ShadowLayers.h" // for ShadowLayerForwarder 1.16 +#include "base/message_loop.h" // for MessageLoop 1.17 +#include "base/platform_thread.h" // for PlatformThread 1.18 +#include "base/process.h" // for ProcessHandle 1.19 +#include "base/process_util.h" // for OpenProcessHandle 1.20 +#include "base/task.h" // for NewRunnableFunction, etc 1.21 +#include "base/thread.h" // for Thread 1.22 +#include "base/tracked.h" // for FROM_HERE 1.23 +#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc 1.24 +#include "mozilla/Monitor.h" // for Monitor, MonitorAutoLock 1.25 +#include "mozilla/ReentrantMonitor.h" // for ReentrantMonitor, etc 1.26 +#include "mozilla/ipc/MessageChannel.h" // for MessageChannel, etc 1.27 +#include "mozilla/ipc/Transport.h" // for Transport 1.28 +#include "mozilla/gfx/Point.h" // for IntSize 1.29 +#include "mozilla/layers/CompositableClient.h" // for CompositableChild, etc 1.30 +#include "mozilla/layers/ISurfaceAllocator.h" // for ISurfaceAllocator 1.31 +#include "mozilla/layers/ImageClient.h" // for ImageClient 1.32 +#include "mozilla/layers/LayersMessages.h" // for CompositableOperation 1.33 +#include "mozilla/layers/PCompositableChild.h" // for PCompositableChild 1.34 +#include "mozilla/layers/TextureClient.h" // for TextureClient 1.35 +#include "mozilla/mozalloc.h" // for operator new, etc 1.36 +#include "nsAutoPtr.h" // for nsRefPtr 1.37 +#include "nsISupportsImpl.h" // for ImageContainer::AddRef, etc 1.38 +#include "nsTArray.h" // for nsAutoTArray, nsTArray, etc 1.39 +#include "nsTArrayForwardDeclare.h" // for AutoInfallibleTArray 1.40 +#include "nsThreadUtils.h" // for NS_IsMainThread 1.41 +#include "nsXULAppAPI.h" // for XRE_GetIOMessageLoop 1.42 +#include "mozilla/StaticPtr.h" // for StaticRefPtr 1.43 +#include "mozilla/layers/TextureClient.h" 1.44 + 1.45 +struct nsIntRect; 1.46 + 1.47 +using namespace base; 1.48 +using namespace mozilla::ipc; 1.49 +using namespace mozilla::gfx; 1.50 + 1.51 +namespace mozilla { 1.52 +namespace ipc { 1.53 +class Shmem; 1.54 +} 1.55 + 1.56 +namespace layers { 1.57 + 1.58 +class PGrallocBufferChild; 1.59 +typedef std::vector<CompositableOperation> OpVector; 1.60 + 1.61 +struct CompositableTransaction 1.62 +{ 1.63 + CompositableTransaction() 1.64 + : mSwapRequired(false) 1.65 + , mFinished(true) 1.66 + {} 1.67 + ~CompositableTransaction() 1.68 + { 1.69 + End(); 1.70 + } 1.71 + bool Finished() const 1.72 + { 1.73 + return mFinished; 1.74 + } 1.75 + void Begin() 1.76 + { 1.77 + MOZ_ASSERT(mFinished); 1.78 + mFinished = false; 1.79 + } 1.80 + void End() 1.81 + { 1.82 + mFinished = true; 1.83 + mSwapRequired = false; 1.84 + mOperations.clear(); 1.85 + } 1.86 + bool IsEmpty() const 1.87 + { 1.88 + return mOperations.empty(); 1.89 + } 1.90 + void AddNoSwapEdit(const CompositableOperation& op) 1.91 + { 1.92 + NS_ABORT_IF_FALSE(!Finished(), "forgot BeginTransaction?"); 1.93 + mOperations.push_back(op); 1.94 + } 1.95 + void AddEdit(const CompositableOperation& op) 1.96 + { 1.97 + AddNoSwapEdit(op); 1.98 + mSwapRequired = true; 1.99 + } 1.100 + 1.101 + OpVector mOperations; 1.102 + bool mSwapRequired; 1.103 + bool mFinished; 1.104 +}; 1.105 + 1.106 +struct AutoEndTransaction { 1.107 + AutoEndTransaction(CompositableTransaction* aTxn) : mTxn(aTxn) {} 1.108 + ~AutoEndTransaction() { mTxn->End(); } 1.109 + CompositableTransaction* mTxn; 1.110 +}; 1.111 + 1.112 +void 1.113 +ImageBridgeChild::UseTexture(CompositableClient* aCompositable, 1.114 + TextureClient* aTexture) 1.115 +{ 1.116 + MOZ_ASSERT(aCompositable); 1.117 + MOZ_ASSERT(aTexture); 1.118 + MOZ_ASSERT(aCompositable->GetIPDLActor()); 1.119 + MOZ_ASSERT(aTexture->GetIPDLActor()); 1.120 + mTxn->AddNoSwapEdit(OpUseTexture(nullptr, aCompositable->GetIPDLActor(), 1.121 + nullptr, aTexture->GetIPDLActor())); 1.122 +} 1.123 + 1.124 +void 1.125 +ImageBridgeChild::UseComponentAlphaTextures(CompositableClient* aCompositable, 1.126 + TextureClient* aTextureOnBlack, 1.127 + TextureClient* aTextureOnWhite) 1.128 +{ 1.129 + MOZ_ASSERT(aCompositable); 1.130 + MOZ_ASSERT(aTextureOnWhite); 1.131 + MOZ_ASSERT(aTextureOnBlack); 1.132 + MOZ_ASSERT(aCompositable->GetIPDLActor()); 1.133 + MOZ_ASSERT(aTextureOnWhite->GetIPDLActor()); 1.134 + MOZ_ASSERT(aTextureOnBlack->GetIPDLActor()); 1.135 + MOZ_ASSERT(aTextureOnBlack->GetSize() == aTextureOnWhite->GetSize()); 1.136 + mTxn->AddNoSwapEdit(OpUseComponentAlphaTextures(nullptr, aCompositable->GetIPDLActor(), 1.137 + nullptr, aTextureOnBlack->GetIPDLActor(), 1.138 + nullptr, aTextureOnWhite->GetIPDLActor())); 1.139 +} 1.140 + 1.141 +void 1.142 +ImageBridgeChild::UpdatedTexture(CompositableClient* aCompositable, 1.143 + TextureClient* aTexture, 1.144 + nsIntRegion* aRegion) 1.145 +{ 1.146 + MOZ_ASSERT(aCompositable); 1.147 + MOZ_ASSERT(aTexture); 1.148 + MOZ_ASSERT(aCompositable->GetIPDLActor()); 1.149 + MOZ_ASSERT(aTexture->GetIPDLActor()); 1.150 + MaybeRegion region = aRegion ? MaybeRegion(*aRegion) 1.151 + : MaybeRegion(null_t()); 1.152 + mTxn->AddNoSwapEdit(OpUpdateTexture(nullptr, aCompositable->GetIPDLActor(), 1.153 + nullptr, aTexture->GetIPDLActor(), 1.154 + region)); 1.155 +} 1.156 + 1.157 +void 1.158 +ImageBridgeChild::UpdatePictureRect(CompositableClient* aCompositable, 1.159 + const nsIntRect& aRect) 1.160 +{ 1.161 + MOZ_ASSERT(aCompositable); 1.162 + MOZ_ASSERT(aCompositable->GetIPDLActor()); 1.163 + mTxn->AddNoSwapEdit(OpUpdatePictureRect(nullptr, aCompositable->GetIPDLActor(), aRect)); 1.164 +} 1.165 + 1.166 +// Singleton 1.167 +static StaticRefPtr<ImageBridgeChild> sImageBridgeChildSingleton; 1.168 +static StaticRefPtr<ImageBridgeParent> sImageBridgeParentSingleton; 1.169 +static Thread *sImageBridgeChildThread = nullptr; 1.170 + 1.171 +void ReleaseImageBridgeParentSingleton() { 1.172 + sImageBridgeParentSingleton = nullptr; 1.173 +} 1.174 + 1.175 +// dispatched function 1.176 +static void ImageBridgeShutdownStep1(ReentrantMonitor *aBarrier, bool *aDone) 1.177 +{ 1.178 + ReentrantMonitorAutoEnter autoMon(*aBarrier); 1.179 + 1.180 + NS_ABORT_IF_FALSE(InImageBridgeChildThread(), 1.181 + "Should be in ImageBridgeChild thread."); 1.182 + if (sImageBridgeChildSingleton) { 1.183 + // Force all managed protocols to shut themselves down cleanly 1.184 + InfallibleTArray<PCompositableChild*> compositables; 1.185 + sImageBridgeChildSingleton->ManagedPCompositableChild(compositables); 1.186 + for (int i = compositables.Length() - 1; i >= 0; --i) { 1.187 + CompositableClient::FromIPDLActor(compositables[i])->Destroy(); 1.188 + } 1.189 + InfallibleTArray<PTextureChild*> textures; 1.190 + sImageBridgeChildSingleton->ManagedPTextureChild(textures); 1.191 + for (int i = textures.Length() - 1; i >= 0; --i) { 1.192 + TextureClient::AsTextureClient(textures[i])->ForceRemove(); 1.193 + } 1.194 + sImageBridgeChildSingleton->SendWillStop(); 1.195 + sImageBridgeChildSingleton->MarkShutDown(); 1.196 + // From now on, no message can be sent through the image bridge from the 1.197 + // client side except the final Stop message. 1.198 + } 1.199 + *aDone = true; 1.200 + aBarrier->NotifyAll(); 1.201 +} 1.202 + 1.203 +// dispatched function 1.204 +static void ImageBridgeShutdownStep2(ReentrantMonitor *aBarrier, bool *aDone) 1.205 +{ 1.206 + ReentrantMonitorAutoEnter autoMon(*aBarrier); 1.207 + 1.208 + NS_ABORT_IF_FALSE(InImageBridgeChildThread(), 1.209 + "Should be in ImageBridgeChild thread."); 1.210 + 1.211 + sImageBridgeChildSingleton->SendStop(); 1.212 + 1.213 + sImageBridgeChildSingleton = nullptr; 1.214 + 1.215 + *aDone = true; 1.216 + aBarrier->NotifyAll(); 1.217 +} 1.218 + 1.219 +// dispatched function 1.220 +static void CreateImageClientSync(RefPtr<ImageClient>* result, 1.221 + ReentrantMonitor* barrier, 1.222 + CompositableType aType, 1.223 + bool *aDone) 1.224 +{ 1.225 + ReentrantMonitorAutoEnter autoMon(*barrier); 1.226 + *result = sImageBridgeChildSingleton->CreateImageClientNow(aType); 1.227 + *aDone = true; 1.228 + barrier->NotifyAll(); 1.229 +} 1.230 + 1.231 + 1.232 +struct GrallocParam { 1.233 + IntSize size; 1.234 + uint32_t format; 1.235 + uint32_t usage; 1.236 + MaybeMagicGrallocBufferHandle* handle; 1.237 + PGrallocBufferChild** child; 1.238 + 1.239 + GrallocParam(const IntSize& aSize, 1.240 + const uint32_t& aFormat, 1.241 + const uint32_t& aUsage, 1.242 + MaybeMagicGrallocBufferHandle* aHandle, 1.243 + PGrallocBufferChild** aChild) 1.244 + : size(aSize) 1.245 + , format(aFormat) 1.246 + , usage(aUsage) 1.247 + , handle(aHandle) 1.248 + , child(aChild) 1.249 + {} 1.250 +}; 1.251 + 1.252 +// dispatched function 1.253 +static void AllocGrallocBufferSync(const GrallocParam& aParam, 1.254 + Monitor* aBarrier, 1.255 + bool* aDone) 1.256 +{ 1.257 + MonitorAutoLock autoMon(*aBarrier); 1.258 + 1.259 + sImageBridgeChildSingleton->AllocGrallocBufferNow(aParam.size, 1.260 + aParam.format, 1.261 + aParam.usage, 1.262 + aParam.handle, 1.263 + aParam.child); 1.264 + *aDone = true; 1.265 + aBarrier->NotifyAll(); 1.266 +} 1.267 + 1.268 +// dispatched function 1.269 +static void ConnectImageBridge(ImageBridgeChild * child, ImageBridgeParent * parent) 1.270 +{ 1.271 + MessageLoop *parentMsgLoop = parent->GetMessageLoop(); 1.272 + ipc::MessageChannel *parentChannel = parent->GetIPCChannel(); 1.273 + child->Open(parentChannel, parentMsgLoop, mozilla::ipc::ChildSide); 1.274 +} 1.275 + 1.276 +ImageBridgeChild::ImageBridgeChild() 1.277 + : mShuttingDown(false) 1.278 +{ 1.279 + mTxn = new CompositableTransaction(); 1.280 +} 1.281 +ImageBridgeChild::~ImageBridgeChild() 1.282 +{ 1.283 + delete mTxn; 1.284 +} 1.285 + 1.286 +void 1.287 +ImageBridgeChild::MarkShutDown() 1.288 +{ 1.289 + MOZ_ASSERT(!mShuttingDown); 1.290 + mShuttingDown = true; 1.291 +} 1.292 + 1.293 +void 1.294 +ImageBridgeChild::Connect(CompositableClient* aCompositable) 1.295 +{ 1.296 + MOZ_ASSERT(aCompositable); 1.297 + MOZ_ASSERT(!mShuttingDown); 1.298 + uint64_t id = 0; 1.299 + PCompositableChild* child = 1.300 + SendPCompositableConstructor(aCompositable->GetTextureInfo(), &id); 1.301 + MOZ_ASSERT(child); 1.302 + aCompositable->InitIPDLActor(child, id); 1.303 +} 1.304 + 1.305 +PCompositableChild* 1.306 +ImageBridgeChild::AllocPCompositableChild(const TextureInfo& aInfo, uint64_t* aID) 1.307 +{ 1.308 + MOZ_ASSERT(!mShuttingDown); 1.309 + return CompositableClient::CreateIPDLActor(); 1.310 +} 1.311 + 1.312 +bool 1.313 +ImageBridgeChild::DeallocPCompositableChild(PCompositableChild* aActor) 1.314 +{ 1.315 + return CompositableClient::DestroyIPDLActor(aActor); 1.316 +} 1.317 + 1.318 + 1.319 +Thread* ImageBridgeChild::GetThread() const 1.320 +{ 1.321 + return sImageBridgeChildThread; 1.322 +} 1.323 + 1.324 +ImageBridgeChild* ImageBridgeChild::GetSingleton() 1.325 +{ 1.326 + return sImageBridgeChildSingleton; 1.327 +} 1.328 + 1.329 +bool ImageBridgeChild::IsCreated() 1.330 +{ 1.331 + return GetSingleton() != nullptr; 1.332 +} 1.333 + 1.334 +void ImageBridgeChild::StartUp() 1.335 +{ 1.336 + NS_ASSERTION(NS_IsMainThread(), "Should be on the main Thread!"); 1.337 + ImageBridgeChild::StartUpOnThread(new Thread("ImageBridgeChild")); 1.338 +} 1.339 + 1.340 +#ifdef MOZ_NUWA_PROCESS 1.341 +#include "ipc/Nuwa.h" 1.342 +#endif 1.343 + 1.344 +static void 1.345 +ConnectImageBridgeInChildProcess(Transport* aTransport, 1.346 + ProcessHandle aOtherProcess) 1.347 +{ 1.348 + // Bind the IPC channel to the image bridge thread. 1.349 + sImageBridgeChildSingleton->Open(aTransport, aOtherProcess, 1.350 + XRE_GetIOMessageLoop(), 1.351 + ipc::ChildSide); 1.352 +#ifdef MOZ_NUWA_PROCESS 1.353 + if (IsNuwaProcess()) { 1.354 + sImageBridgeChildThread 1.355 + ->message_loop()->PostTask(FROM_HERE, 1.356 + NewRunnableFunction(NuwaMarkCurrentThread, 1.357 + (void (*)(void *))nullptr, 1.358 + (void *)nullptr)); 1.359 + } 1.360 +#endif 1.361 +} 1.362 + 1.363 +static void ReleaseImageClientNow(ImageClient* aClient) 1.364 +{ 1.365 + MOZ_ASSERT(InImageBridgeChildThread()); 1.366 + aClient->Release(); 1.367 +} 1.368 + 1.369 +// static 1.370 +void ImageBridgeChild::DispatchReleaseImageClient(ImageClient* aClient) 1.371 +{ 1.372 + if (!IsCreated()) { 1.373 + // CompositableClient::Release should normally happen in the ImageBridgeChild 1.374 + // thread because it usually generate some IPDL messages. 1.375 + // However, if we take this branch it means that the ImageBridgeChild 1.376 + // has already shut down, along with the CompositableChild, which means no 1.377 + // message will be sent and it is safe to run this code from any thread. 1.378 + MOZ_ASSERT(aClient->GetIPDLActor() == nullptr); 1.379 + aClient->Release(); 1.380 + return; 1.381 + } 1.382 + 1.383 + sImageBridgeChildSingleton->GetMessageLoop()->PostTask( 1.384 + FROM_HERE, 1.385 + NewRunnableFunction(&ReleaseImageClientNow, aClient)); 1.386 +} 1.387 + 1.388 +static void ReleaseTextureClientNow(TextureClient* aClient) 1.389 +{ 1.390 + MOZ_ASSERT(InImageBridgeChildThread()); 1.391 + aClient->Release(); 1.392 +} 1.393 + 1.394 +// static 1.395 +void ImageBridgeChild::DispatchReleaseTextureClient(TextureClient* aClient) 1.396 +{ 1.397 + if (!IsCreated()) { 1.398 + // TextureClient::Release should normally happen in the ImageBridgeChild 1.399 + // thread because it usually generate some IPDL messages. 1.400 + // However, if we take this branch it means that the ImageBridgeChild 1.401 + // has already shut down, along with the TextureChild, which means no 1.402 + // message will be sent and it is safe to run this code from any thread. 1.403 + MOZ_ASSERT(aClient->GetIPDLActor() == nullptr); 1.404 + aClient->Release(); 1.405 + return; 1.406 + } 1.407 + 1.408 + sImageBridgeChildSingleton->GetMessageLoop()->PostTask( 1.409 + FROM_HERE, 1.410 + NewRunnableFunction(&ReleaseTextureClientNow, aClient)); 1.411 +} 1.412 + 1.413 +static void UpdateImageClientNow(ImageClient* aClient, ImageContainer* aContainer) 1.414 +{ 1.415 + MOZ_ASSERT(aClient); 1.416 + MOZ_ASSERT(aContainer); 1.417 + sImageBridgeChildSingleton->BeginTransaction(); 1.418 + aClient->UpdateImage(aContainer, Layer::CONTENT_OPAQUE); 1.419 + aClient->OnTransaction(); 1.420 + sImageBridgeChildSingleton->EndTransaction(); 1.421 +} 1.422 + 1.423 +//static 1.424 +void ImageBridgeChild::DispatchImageClientUpdate(ImageClient* aClient, 1.425 + ImageContainer* aContainer) 1.426 +{ 1.427 + if (!IsCreated()) { 1.428 + return; 1.429 + } 1.430 + 1.431 + if (InImageBridgeChildThread()) { 1.432 + UpdateImageClientNow(aClient, aContainer); 1.433 + return; 1.434 + } 1.435 + sImageBridgeChildSingleton->GetMessageLoop()->PostTask( 1.436 + FROM_HERE, 1.437 + NewRunnableFunction< 1.438 + void (*)(ImageClient*, ImageContainer*), 1.439 + ImageClient*, 1.440 + nsRefPtr<ImageContainer> >(&UpdateImageClientNow, aClient, aContainer)); 1.441 +} 1.442 + 1.443 +static void FlushAllImagesSync(ImageClient* aClient, ImageContainer* aContainer, bool aExceptFront, ReentrantMonitor* aBarrier, bool* aDone) 1.444 +{ 1.445 + ImageBridgeChild::FlushAllImagesNow(aClient, aContainer, aExceptFront); 1.446 + 1.447 + ReentrantMonitorAutoEnter autoMon(*aBarrier); 1.448 + *aDone = true; 1.449 + aBarrier->NotifyAll(); 1.450 +} 1.451 + 1.452 +//static 1.453 +void ImageBridgeChild::FlushAllImages(ImageClient* aClient, ImageContainer* aContainer, bool aExceptFront) 1.454 +{ 1.455 + if (!IsCreated()) { 1.456 + return; 1.457 + } 1.458 + 1.459 + MOZ_ASSERT(!sImageBridgeChildSingleton->mShuttingDown); 1.460 + 1.461 + if (InImageBridgeChildThread()) { 1.462 + FlushAllImagesNow(aClient, aContainer, aExceptFront); 1.463 + return; 1.464 + } 1.465 + 1.466 + ReentrantMonitor barrier("CreateImageClient Lock"); 1.467 + ReentrantMonitorAutoEnter autoMon(barrier); 1.468 + bool done = false; 1.469 + 1.470 + sImageBridgeChildSingleton->GetMessageLoop()->PostTask( 1.471 + FROM_HERE, 1.472 + NewRunnableFunction(&FlushAllImagesSync, aClient, aContainer, aExceptFront, &barrier, &done)); 1.473 + 1.474 + // should stop the thread until the ImageClient has been created on 1.475 + // the other thread 1.476 + while (!done) { 1.477 + barrier.Wait(); 1.478 + } 1.479 +} 1.480 + 1.481 +//static 1.482 +void ImageBridgeChild::FlushAllImagesNow(ImageClient* aClient, ImageContainer* aContainer, bool aExceptFront) 1.483 +{ 1.484 + MOZ_ASSERT(aClient); 1.485 + sImageBridgeChildSingleton->BeginTransaction(); 1.486 + if (aContainer && !aExceptFront) { 1.487 + aContainer->ClearCurrentImage(); 1.488 + } 1.489 + aClient->FlushAllImages(aExceptFront); 1.490 + aClient->OnTransaction(); 1.491 + sImageBridgeChildSingleton->EndTransaction(); 1.492 +} 1.493 + 1.494 +void 1.495 +ImageBridgeChild::BeginTransaction() 1.496 +{ 1.497 + MOZ_ASSERT(!mShuttingDown); 1.498 + MOZ_ASSERT(mTxn->Finished(), "uncommitted txn?"); 1.499 + mTxn->Begin(); 1.500 +} 1.501 + 1.502 +class MOZ_STACK_CLASS AutoRemoveTextures 1.503 +{ 1.504 +public: 1.505 + AutoRemoveTextures(ImageBridgeChild* aImageBridge) 1.506 + : mImageBridge(aImageBridge) {} 1.507 + 1.508 + ~AutoRemoveTextures() 1.509 + { 1.510 + mImageBridge->RemoveTexturesIfNecessary(); 1.511 + } 1.512 +private: 1.513 + ImageBridgeChild* mImageBridge; 1.514 +}; 1.515 + 1.516 +void 1.517 +ImageBridgeChild::EndTransaction() 1.518 +{ 1.519 + MOZ_ASSERT(!mShuttingDown); 1.520 + MOZ_ASSERT(!mTxn->Finished(), "forgot BeginTransaction?"); 1.521 + 1.522 + AutoEndTransaction _(mTxn); 1.523 + AutoRemoveTextures autoRemoveTextures(this); 1.524 + 1.525 + if (mTxn->IsEmpty()) { 1.526 + return; 1.527 + } 1.528 + 1.529 + AutoInfallibleTArray<CompositableOperation, 10> cset; 1.530 + cset.SetCapacity(mTxn->mOperations.size()); 1.531 + if (!mTxn->mOperations.empty()) { 1.532 + cset.AppendElements(&mTxn->mOperations.front(), mTxn->mOperations.size()); 1.533 + } 1.534 + ShadowLayerForwarder::PlatformSyncBeforeUpdate(); 1.535 + 1.536 + AutoInfallibleTArray<EditReply, 10> replies; 1.537 + 1.538 + if (mTxn->mSwapRequired) { 1.539 + if (!SendUpdate(cset, &replies)) { 1.540 + NS_WARNING("could not send async texture transaction"); 1.541 + return; 1.542 + } 1.543 + } else { 1.544 + // If we don't require a swap we can call SendUpdateNoSwap which 1.545 + // assumes that aReplies is empty (DEBUG assertion) 1.546 + if (!SendUpdateNoSwap(cset)) { 1.547 + NS_WARNING("could not send async texture transaction (no swap)"); 1.548 + return; 1.549 + } 1.550 + } 1.551 + for (nsTArray<EditReply>::size_type i = 0; i < replies.Length(); ++i) { 1.552 + const EditReply& reply = replies[i]; 1.553 + switch (reply.type()) { 1.554 + case EditReply::TOpTextureSwap: { 1.555 + const OpTextureSwap& ots = reply.get_OpTextureSwap(); 1.556 + 1.557 + CompositableClient* compositable = 1.558 + CompositableClient::FromIPDLActor(ots.compositableChild()); 1.559 + 1.560 + MOZ_ASSERT(compositable); 1.561 + 1.562 + compositable->SetDescriptorFromReply(ots.textureId(), ots.image()); 1.563 + break; 1.564 + } 1.565 + case EditReply::TReturnReleaseFence: { 1.566 + const ReturnReleaseFence& rep = reply.get_ReturnReleaseFence(); 1.567 + FenceHandle fence = rep.fence(); 1.568 + PTextureChild* child = rep.textureChild(); 1.569 + 1.570 + if (!fence.IsValid() || !child) { 1.571 + break; 1.572 + } 1.573 + RefPtr<TextureClient> texture = TextureClient::AsTextureClient(child); 1.574 + if (texture) { 1.575 + texture->SetReleaseFenceHandle(fence); 1.576 + } 1.577 + break; 1.578 + } 1.579 + default: 1.580 + NS_RUNTIMEABORT("not reached"); 1.581 + } 1.582 + } 1.583 +} 1.584 + 1.585 + 1.586 +PImageBridgeChild* 1.587 +ImageBridgeChild::StartUpInChildProcess(Transport* aTransport, 1.588 + ProcessId aOtherProcess) 1.589 +{ 1.590 + NS_ASSERTION(NS_IsMainThread(), "Should be on the main Thread!"); 1.591 + 1.592 + ProcessHandle processHandle; 1.593 + if (!base::OpenProcessHandle(aOtherProcess, &processHandle)) { 1.594 + return nullptr; 1.595 + } 1.596 + 1.597 + sImageBridgeChildThread = new Thread("ImageBridgeChild"); 1.598 + if (!sImageBridgeChildThread->Start()) { 1.599 + return nullptr; 1.600 + } 1.601 + 1.602 + sImageBridgeChildSingleton = new ImageBridgeChild(); 1.603 + sImageBridgeChildSingleton->GetMessageLoop()->PostTask( 1.604 + FROM_HERE, 1.605 + NewRunnableFunction(ConnectImageBridgeInChildProcess, 1.606 + aTransport, processHandle)); 1.607 + 1.608 + return sImageBridgeChildSingleton; 1.609 +} 1.610 + 1.611 +void ImageBridgeChild::ShutDown() 1.612 +{ 1.613 + MOZ_ASSERT(NS_IsMainThread(), "Should be on the main Thread!"); 1.614 + if (ImageBridgeChild::IsCreated()) { 1.615 + MOZ_ASSERT(!sImageBridgeChildSingleton->mShuttingDown); 1.616 + 1.617 + { 1.618 + ReentrantMonitor barrier("ImageBridge ShutdownStep1 lock"); 1.619 + ReentrantMonitorAutoEnter autoMon(barrier); 1.620 + 1.621 + bool done = false; 1.622 + sImageBridgeChildSingleton->GetMessageLoop()->PostTask(FROM_HERE, 1.623 + NewRunnableFunction(&ImageBridgeShutdownStep1, &barrier, &done)); 1.624 + while (!done) { 1.625 + barrier.Wait(); 1.626 + } 1.627 + } 1.628 + 1.629 + { 1.630 + ReentrantMonitor barrier("ImageBridge ShutdownStep2 lock"); 1.631 + ReentrantMonitorAutoEnter autoMon(barrier); 1.632 + 1.633 + bool done = false; 1.634 + sImageBridgeChildSingleton->GetMessageLoop()->PostTask(FROM_HERE, 1.635 + NewRunnableFunction(&ImageBridgeShutdownStep2, &barrier, &done)); 1.636 + while (!done) { 1.637 + barrier.Wait(); 1.638 + } 1.639 + } 1.640 + 1.641 + delete sImageBridgeChildThread; 1.642 + sImageBridgeChildThread = nullptr; 1.643 + } 1.644 +} 1.645 + 1.646 +bool ImageBridgeChild::StartUpOnThread(Thread* aThread) 1.647 +{ 1.648 + NS_ABORT_IF_FALSE(aThread, "ImageBridge needs a thread."); 1.649 + if (sImageBridgeChildSingleton == nullptr) { 1.650 + sImageBridgeChildThread = aThread; 1.651 + if (!aThread->IsRunning()) { 1.652 + aThread->Start(); 1.653 + } 1.654 + sImageBridgeChildSingleton = new ImageBridgeChild(); 1.655 + sImageBridgeParentSingleton = new ImageBridgeParent( 1.656 + CompositorParent::CompositorLoop(), nullptr); 1.657 + sImageBridgeChildSingleton->ConnectAsync(sImageBridgeParentSingleton); 1.658 + return true; 1.659 + } else { 1.660 + return false; 1.661 + } 1.662 +} 1.663 + 1.664 +bool InImageBridgeChildThread() 1.665 +{ 1.666 + return sImageBridgeChildThread->thread_id() == PlatformThread::CurrentId(); 1.667 +} 1.668 + 1.669 +MessageLoop * ImageBridgeChild::GetMessageLoop() const 1.670 +{ 1.671 + return sImageBridgeChildThread->message_loop(); 1.672 +} 1.673 + 1.674 +void ImageBridgeChild::ConnectAsync(ImageBridgeParent* aParent) 1.675 +{ 1.676 + GetMessageLoop()->PostTask(FROM_HERE, NewRunnableFunction(&ConnectImageBridge, 1.677 + this, aParent)); 1.678 +} 1.679 + 1.680 +void 1.681 +ImageBridgeChild::IdentifyCompositorTextureHost(const TextureFactoryIdentifier& aIdentifier) 1.682 +{ 1.683 + if (sImageBridgeChildSingleton) { 1.684 + sImageBridgeChildSingleton->IdentifyTextureHost(aIdentifier); 1.685 + } 1.686 +} 1.687 + 1.688 +TemporaryRef<ImageClient> 1.689 +ImageBridgeChild::CreateImageClient(CompositableType aType) 1.690 +{ 1.691 + if (InImageBridgeChildThread()) { 1.692 + return CreateImageClientNow(aType); 1.693 + } 1.694 + ReentrantMonitor barrier("CreateImageClient Lock"); 1.695 + ReentrantMonitorAutoEnter autoMon(barrier); 1.696 + bool done = false; 1.697 + 1.698 + RefPtr<ImageClient> result = nullptr; 1.699 + GetMessageLoop()->PostTask(FROM_HERE, NewRunnableFunction(&CreateImageClientSync, 1.700 + &result, &barrier, aType, &done)); 1.701 + // should stop the thread until the ImageClient has been created on 1.702 + // the other thread 1.703 + while (!done) { 1.704 + barrier.Wait(); 1.705 + } 1.706 + return result.forget(); 1.707 +} 1.708 + 1.709 +TemporaryRef<ImageClient> 1.710 +ImageBridgeChild::CreateImageClientNow(CompositableType aType) 1.711 +{ 1.712 + MOZ_ASSERT(!sImageBridgeChildSingleton->mShuttingDown); 1.713 + RefPtr<ImageClient> client 1.714 + = ImageClient::CreateImageClient(aType, this, 0); 1.715 + MOZ_ASSERT(client, "failed to create ImageClient"); 1.716 + if (client) { 1.717 + client->Connect(); 1.718 + } 1.719 + return client.forget(); 1.720 +} 1.721 + 1.722 +PGrallocBufferChild* 1.723 +ImageBridgeChild::AllocPGrallocBufferChild(const IntSize&, const uint32_t&, const uint32_t&, 1.724 + MaybeMagicGrallocBufferHandle*) 1.725 +{ 1.726 +#ifdef MOZ_HAVE_SURFACEDESCRIPTORGRALLOC 1.727 + return GrallocBufferActor::Create(); 1.728 +#else 1.729 + NS_RUNTIMEABORT("No gralloc buffers for you"); 1.730 + return nullptr; 1.731 +#endif 1.732 +} 1.733 + 1.734 +bool 1.735 +ImageBridgeChild::DeallocPGrallocBufferChild(PGrallocBufferChild* actor) 1.736 +{ 1.737 +#ifdef MOZ_HAVE_SURFACEDESCRIPTORGRALLOC 1.738 + delete actor; 1.739 + return true; 1.740 +#else 1.741 + NS_RUNTIMEABORT("Um, how did we get here?"); 1.742 + return false; 1.743 +#endif 1.744 +} 1.745 + 1.746 +bool 1.747 +ImageBridgeChild::AllocUnsafeShmem(size_t aSize, 1.748 + ipc::SharedMemory::SharedMemoryType aType, 1.749 + ipc::Shmem* aShmem) 1.750 +{ 1.751 + MOZ_ASSERT(!mShuttingDown); 1.752 + if (InImageBridgeChildThread()) { 1.753 + return PImageBridgeChild::AllocUnsafeShmem(aSize, aType, aShmem); 1.754 + } else { 1.755 + return DispatchAllocShmemInternal(aSize, aType, aShmem, true); // true: unsafe 1.756 + } 1.757 +} 1.758 + 1.759 +bool 1.760 +ImageBridgeChild::AllocShmem(size_t aSize, 1.761 + ipc::SharedMemory::SharedMemoryType aType, 1.762 + ipc::Shmem* aShmem) 1.763 +{ 1.764 + if (InImageBridgeChildThread()) { 1.765 + return PImageBridgeChild::AllocShmem(aSize, aType, aShmem); 1.766 + } else { 1.767 + return DispatchAllocShmemInternal(aSize, aType, aShmem, false); // false: unsafe 1.768 + } 1.769 +} 1.770 + 1.771 +// NewRunnableFunction accepts a limited number of parameters so we need a 1.772 +// struct here 1.773 +struct AllocShmemParams { 1.774 + RefPtr<ISurfaceAllocator> mAllocator; 1.775 + size_t mSize; 1.776 + ipc::SharedMemory::SharedMemoryType mType; 1.777 + ipc::Shmem* mShmem; 1.778 + bool mUnsafe; 1.779 + bool mSuccess; 1.780 +}; 1.781 + 1.782 +static void ProxyAllocShmemNow(AllocShmemParams* aParams, 1.783 + ReentrantMonitor* aBarrier, 1.784 + bool* aDone) 1.785 +{ 1.786 + MOZ_ASSERT(aParams); 1.787 + MOZ_ASSERT(aDone); 1.788 + MOZ_ASSERT(aBarrier); 1.789 + 1.790 + if (aParams->mUnsafe) { 1.791 + aParams->mSuccess = aParams->mAllocator->AllocUnsafeShmem(aParams->mSize, 1.792 + aParams->mType, 1.793 + aParams->mShmem); 1.794 + } else { 1.795 + aParams->mSuccess = aParams->mAllocator->AllocShmem(aParams->mSize, 1.796 + aParams->mType, 1.797 + aParams->mShmem); 1.798 + } 1.799 + 1.800 + ReentrantMonitorAutoEnter autoMon(*aBarrier); 1.801 + *aDone = true; 1.802 + aBarrier->NotifyAll(); 1.803 +} 1.804 + 1.805 +bool 1.806 +ImageBridgeChild::DispatchAllocShmemInternal(size_t aSize, 1.807 + SharedMemory::SharedMemoryType aType, 1.808 + ipc::Shmem* aShmem, 1.809 + bool aUnsafe) 1.810 +{ 1.811 + ReentrantMonitor barrier("AllocatorProxy alloc"); 1.812 + ReentrantMonitorAutoEnter autoMon(barrier); 1.813 + 1.814 + AllocShmemParams params = { 1.815 + this, aSize, aType, aShmem, aUnsafe, true 1.816 + }; 1.817 + bool done = false; 1.818 + 1.819 + GetMessageLoop()->PostTask(FROM_HERE, 1.820 + NewRunnableFunction(&ProxyAllocShmemNow, 1.821 + ¶ms, 1.822 + &barrier, 1.823 + &done)); 1.824 + while (!done) { 1.825 + barrier.Wait(); 1.826 + } 1.827 + return params.mSuccess; 1.828 +} 1.829 + 1.830 +static void ProxyDeallocShmemNow(ISurfaceAllocator* aAllocator, 1.831 + ipc::Shmem* aShmem, 1.832 + ReentrantMonitor* aBarrier, 1.833 + bool* aDone) 1.834 +{ 1.835 + MOZ_ASSERT(aShmem); 1.836 + MOZ_ASSERT(aDone); 1.837 + MOZ_ASSERT(aBarrier); 1.838 + 1.839 + aAllocator->DeallocShmem(*aShmem); 1.840 + 1.841 + ReentrantMonitorAutoEnter autoMon(*aBarrier); 1.842 + *aDone = true; 1.843 + aBarrier->NotifyAll(); 1.844 +} 1.845 + 1.846 +void 1.847 +ImageBridgeChild::DeallocShmem(ipc::Shmem& aShmem) 1.848 +{ 1.849 + if (InImageBridgeChildThread()) { 1.850 + PImageBridgeChild::DeallocShmem(aShmem); 1.851 + } else { 1.852 + ReentrantMonitor barrier("AllocatorProxy Dealloc"); 1.853 + ReentrantMonitorAutoEnter autoMon(barrier); 1.854 + 1.855 + bool done = false; 1.856 + GetMessageLoop()->PostTask(FROM_HERE, 1.857 + NewRunnableFunction(&ProxyDeallocShmemNow, 1.858 + this, 1.859 + &aShmem, 1.860 + &barrier, 1.861 + &done)); 1.862 + while (!done) { 1.863 + barrier.Wait(); 1.864 + } 1.865 + } 1.866 +} 1.867 + 1.868 +PGrallocBufferChild* 1.869 +ImageBridgeChild::AllocGrallocBuffer(const IntSize& aSize, 1.870 + uint32_t aFormat, 1.871 + uint32_t aUsage, 1.872 + MaybeMagicGrallocBufferHandle* aHandle) 1.873 +{ 1.874 + if (InImageBridgeChildThread()) { 1.875 + PGrallocBufferChild* child = nullptr; 1.876 + ImageBridgeChild::AllocGrallocBufferNow(aSize, aFormat, aUsage, aHandle, &child); 1.877 + return child; 1.878 + } 1.879 + 1.880 + Monitor barrier("AllocGrallocBuffer Lock"); 1.881 + MonitorAutoLock autoMon(barrier); 1.882 + bool done = false; 1.883 + PGrallocBufferChild* child = nullptr; 1.884 + 1.885 + GetMessageLoop()->PostTask( 1.886 + FROM_HERE, 1.887 + NewRunnableFunction(&AllocGrallocBufferSync, 1.888 + GrallocParam(aSize, aFormat, aUsage, aHandle, &child), &barrier, &done)); 1.889 + 1.890 + while (!done) { 1.891 + barrier.Wait(); 1.892 + } 1.893 + 1.894 + return child; 1.895 +} 1.896 + 1.897 +void 1.898 +ImageBridgeChild::AllocGrallocBufferNow(const gfx::IntSize& aSize, 1.899 + uint32_t aFormat, uint32_t aUsage, 1.900 + MaybeMagicGrallocBufferHandle* aHandle, 1.901 + PGrallocBufferChild** aChild) 1.902 +{ 1.903 +#ifdef MOZ_WIDGET_GONK 1.904 + *aChild = SendPGrallocBufferConstructor(aSize, 1.905 + aFormat, 1.906 + aUsage, 1.907 + aHandle); 1.908 +#else 1.909 + NS_RUNTIMEABORT("not implemented"); 1.910 + aChild = nullptr; 1.911 +#endif 1.912 +} 1.913 + 1.914 +static void ProxyDeallocGrallocBufferNow(ISurfaceAllocator* aAllocator, 1.915 + PGrallocBufferChild* aChild, 1.916 + ReentrantMonitor* aBarrier, 1.917 + bool* aDone) 1.918 +{ 1.919 + MOZ_ASSERT(aChild); 1.920 + MOZ_ASSERT(aDone); 1.921 + MOZ_ASSERT(aBarrier); 1.922 + 1.923 +#ifdef MOZ_WIDGET_GONK 1.924 + PGrallocBufferChild::Send__delete__(aChild); 1.925 +#else 1.926 + NS_RUNTIMEABORT("not implemented"); 1.927 +#endif 1.928 + 1.929 + ReentrantMonitorAutoEnter autoMon(*aBarrier); 1.930 + *aDone = true; 1.931 + aBarrier->NotifyAll(); 1.932 +} 1.933 + 1.934 +void 1.935 +ImageBridgeChild::DeallocGrallocBuffer(PGrallocBufferChild* aChild) 1.936 +{ 1.937 + MOZ_ASSERT(aChild); 1.938 + if (InImageBridgeChildThread()) { 1.939 +#ifdef MOZ_WIDGET_GONK 1.940 + PGrallocBufferChild::Send__delete__(aChild); 1.941 +#else 1.942 + NS_RUNTIMEABORT("not implemented"); 1.943 +#endif 1.944 + } else { 1.945 + ReentrantMonitor barrier("AllocatorProxy Dealloc"); 1.946 + ReentrantMonitorAutoEnter autoMon(barrier); 1.947 + 1.948 + bool done = false; 1.949 + GetMessageLoop()->PostTask(FROM_HERE, 1.950 + NewRunnableFunction(&ProxyDeallocGrallocBufferNow, 1.951 + this, 1.952 + aChild, 1.953 + &barrier, 1.954 + &done)); 1.955 + while (!done) { 1.956 + barrier.Wait(); 1.957 + } 1.958 + } 1.959 +} 1.960 + 1.961 +PTextureChild* 1.962 +ImageBridgeChild::AllocPTextureChild(const SurfaceDescriptor&, 1.963 + const TextureFlags&) 1.964 +{ 1.965 + MOZ_ASSERT(!mShuttingDown); 1.966 + return TextureClient::CreateIPDLActor(); 1.967 +} 1.968 + 1.969 +bool 1.970 +ImageBridgeChild::DeallocPTextureChild(PTextureChild* actor) 1.971 +{ 1.972 + return TextureClient::DestroyIPDLActor(actor); 1.973 +} 1.974 + 1.975 +PTextureChild* 1.976 +ImageBridgeChild::CreateTexture(const SurfaceDescriptor& aSharedData, 1.977 + TextureFlags aFlags) 1.978 +{ 1.979 + MOZ_ASSERT(!mShuttingDown); 1.980 + return SendPTextureConstructor(aSharedData, aFlags); 1.981 +} 1.982 + 1.983 +void 1.984 +ImageBridgeChild::RemoveTextureFromCompositable(CompositableClient* aCompositable, 1.985 + TextureClient* aTexture) 1.986 +{ 1.987 + MOZ_ASSERT(!mShuttingDown); 1.988 + if (aTexture->GetFlags() & TEXTURE_DEALLOCATE_CLIENT) { 1.989 + mTxn->AddEdit(OpRemoveTexture(nullptr, aCompositable->GetIPDLActor(), 1.990 + nullptr, aTexture->GetIPDLActor())); 1.991 + } else { 1.992 + mTxn->AddNoSwapEdit(OpRemoveTexture(nullptr, aCompositable->GetIPDLActor(), 1.993 + nullptr, aTexture->GetIPDLActor())); 1.994 + } 1.995 + // Hold texture until transaction complete. 1.996 + HoldUntilTransaction(aTexture); 1.997 +} 1.998 + 1.999 +static void RemoveTextureSync(TextureClient* aTexture, ReentrantMonitor* aBarrier, bool* aDone) 1.1000 +{ 1.1001 + aTexture->ForceRemove(); 1.1002 + 1.1003 + ReentrantMonitorAutoEnter autoMon(*aBarrier); 1.1004 + *aDone = true; 1.1005 + aBarrier->NotifyAll(); 1.1006 +} 1.1007 + 1.1008 +void ImageBridgeChild::RemoveTexture(TextureClient* aTexture) 1.1009 +{ 1.1010 + if (InImageBridgeChildThread()) { 1.1011 + MOZ_ASSERT(!mShuttingDown); 1.1012 + aTexture->ForceRemove(); 1.1013 + return; 1.1014 + } 1.1015 + 1.1016 + ReentrantMonitor barrier("RemoveTexture Lock"); 1.1017 + ReentrantMonitorAutoEnter autoMon(barrier); 1.1018 + bool done = false; 1.1019 + 1.1020 + sImageBridgeChildSingleton->GetMessageLoop()->PostTask( 1.1021 + FROM_HERE, 1.1022 + NewRunnableFunction(&RemoveTextureSync, aTexture, &barrier, &done)); 1.1023 + 1.1024 + // should stop the thread until the ImageClient has been created on 1.1025 + // the other thread 1.1026 + while (!done) { 1.1027 + barrier.Wait(); 1.1028 + } 1.1029 +} 1.1030 + 1.1031 +bool ImageBridgeChild::IsSameProcess() const 1.1032 +{ 1.1033 + return OtherProcess() == ipc::kInvalidProcessHandle; 1.1034 +} 1.1035 + 1.1036 +} // layers 1.1037 +} // mozilla