gfx/layers/ipc/ImageBridgeChild.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial