コード例 #1
0
already_AddRefed<ImageContainerChild> ImageBridgeChild::CreateImageContainerChild()
{
  if (InImageBridgeChildThread()) {
    return ImageBridgeChild::CreateImageContainerChildNow(); 
  } 

  // ImageContainerChild can only be alocated on the ImageBridgeChild thread, so se
  // dispatch a task to the thread and block the current thread until the task has been
  // executed.
  nsRefPtr<ImageContainerChild> result = nullptr;

  ReentrantMonitor barrier("CreateImageContainerChild Lock");
  ReentrantMonitorAutoEnter autoMon(barrier);
  bool done = false;

  GetMessageLoop()->PostTask(FROM_HERE, NewRunnableFunction(&CreateContainerChildSync,
                                                            &result, &barrier, &done));

  // should stop the thread until the ImageContainerChild has been created on 
  // the other thread
  while (!done) {
    barrier.Wait();
  }
  return result.forget();
}
コード例 #2
0
void
AsyncTransactionWaiter::WaitComplete()
{
  MOZ_ASSERT(!InImageBridgeChildThread());

  MonitorAutoLock mon(mCompletedMonitor);
  int count = 0;
  const int maxCount = 5;
  while (mWaitCount > 0 && (count < maxCount)) {
    if (!NS_SUCCEEDED(mCompletedMonitor.Wait(PR_MillisecondsToInterval(10000)))) {
      NS_WARNING("Failed to wait Monitor");
      return;
    }
    if (count > 1) {
      printf_stderr("Waiting async transaction complete.\n");
    }
    count++;
  }

  if (mWaitCount > 0) {
    printf_stderr("Timeout of waiting transaction complete.");
  }

  if (count == maxCount) {
    gfxDevCrash(gfx::LogReason::AsyncTransactionTimeout) << "Bug 1244883: AsyncTransactionWaiter timed out.";
  }
}
コード例 #3
0
void ImageContainerChild::SendImageNow(Image* aImage)
{
  NS_ABORT_IF_FALSE(InImageBridgeChildThread(),
                    "Should be in ImageBridgeChild thread.");

  if (mStop) {
    return;
  }

  bool needsCopy = false;
  // If the image can be converted to a shared image, no need to do a copy.
  SharedImage* img = AsSharedImage(aImage);
  if (!img) {
    needsCopy = true;
    // Try to get a compatible shared image from the pool
    img = GetSharedImageFor(aImage);
    if (!img && mActiveImageCount < (int)MAX_ACTIVE_SHARED_IMAGES) {
      // If no shared image available, allocate a new one
      img = AllocateSharedImageFor(aImage);
    }
  }

  if (img && (!needsCopy || CopyDataIntoSharedImage(aImage, img))) {
    // Keep a reference to the image we sent to compositor to maintain a
    // correct reference count.
    mImageQueue.AppendElement(aImage);
    SendPublishImage(*img);
  } else {
    NS_WARNING("Failed to send an image to the compositor");
  }
  delete img;
  return;
}
コード例 #4
0
void ImageContainerChild::SendImageAsync(ImageContainer* aContainer,
        Image* aImage)
{
    if(!aContainer || !aImage) {
        return;
    }

    if (mStop) {
        return;
    }

    if (InImageBridgeChildThread()) {
        SharedImage *img = ImageToSharedImage(aImage);
        if (img) {
            SendPublishImage(*img);
        } else {
            NS_WARNING("Failed to create a shared image!");
        }
        delete img;
        return;
    }

    // Sending images and (potentially) allocating shmems must be done
    // on the ImageBridgeChild thread.
    Task *t = new ImageBridgeCopyAndSendTask(this, aContainer, aImage);
    GetMessageLoop()->PostTask(FROM_HERE, t);
}
コード例 #5
0
// dispatched function
static void ImageBridgeShutdownStep1(ReentrantMonitor *aBarrier, bool *aDone)
{
  ReentrantMonitorAutoEnter autoMon(*aBarrier);

  MOZ_ASSERT(InImageBridgeChildThread(),
             "Should be in ImageBridgeChild thread.");

  MediaSystemResourceManager::Shutdown();

  if (sImageBridgeChildSingleton) {
    // Force all managed protocols to shut themselves down cleanly
    InfallibleTArray<PCompositableChild*> compositables;
    sImageBridgeChildSingleton->ManagedPCompositableChild(compositables);
    for (int i = compositables.Length() - 1; i >= 0; --i) {
      CompositableClient::FromIPDLActor(compositables[i])->Destroy();
    }
    InfallibleTArray<PTextureChild*> textures;
    sImageBridgeChildSingleton->ManagedPTextureChild(textures);
    for (int i = textures.Length() - 1; i >= 0; --i) {
      TextureClient* client = TextureClient::AsTextureClient(textures[i]);
      if (client) {
        client->ForceRemove();
      }
    }
    sImageBridgeChildSingleton->SendWillStop();
    sImageBridgeChildSingleton->MarkShutDown();
    // From now on, no message can be sent through the image bridge from the
    // client side except the final Stop message.
  }

  *aDone = true;
  aBarrier->NotifyAll();
}
コード例 #6
0
void ImageBridgeChild::DestroyBridge()
{
  NS_ABORT_IF_FALSE(!InImageBridgeChildThread(),
                    "This method must not be called in this thread.");
  // ...because we are about to dispatch synchronous messages to the 
  // ImageBridgeChild thread.

  if (!IsCreated()) {
    return;
  }

  ReentrantMonitor barrier("ImageBridgeDestroyTask lock");
  ReentrantMonitorAutoEnter autoMon(barrier);

  bool done = false;
  sImageBridgeChildSingleton->GetMessageLoop()->PostTask(FROM_HERE, 
                  NewRunnableFunction(&StopImageBridgeSync, &barrier, &done));
  while (!done) {
    barrier.Wait();
  }

  done = false;
  sImageBridgeChildSingleton->GetMessageLoop()->PostTask(FROM_HERE, 
                  NewRunnableFunction(&DeleteImageBridgeSync, &barrier, &done));
  while (!done) {
    barrier.Wait();
  }

}
コード例 #7
0
void ImageContainerChild::DestroySharedImage(const SharedImage& aImage)
{
  NS_ABORT_IF_FALSE(InImageBridgeChildThread(),
                    "Should be in ImageBridgeChild thread.");

  --mActiveImageCount;
  DeallocSharedImageData(this, aImage);
}
コード例 #8
0
SharedImage* ImageContainerChild::CreateSharedImageFromData(Image* image)
{
  NS_ABORT_IF_FALSE(InImageBridgeChildThread(),
                  "Should be in ImageBridgeChild thread.");
  
  ++mActiveImageCount;

  // TODO: I don't test for BasicManager()->IsCompositingCheap() here,
  // is this a problem? (the equvivalent code in PCompositor does that)
  if (image->GetFormat() == Image::PLANAR_YCBCR ) {
    PlanarYCbCrImage *YCbCrImage = static_cast<PlanarYCbCrImage*>(image);
    const PlanarYCbCrImage::Data *data = YCbCrImage->GetData();
    NS_ASSERTION(data, "Must be able to retrieve yuv data from image!");
    
    nsRefPtr<gfxSharedImageSurface> tempBufferY;
    nsRefPtr<gfxSharedImageSurface> tempBufferU;
    nsRefPtr<gfxSharedImageSurface> tempBufferV;
    
    if (!this->AllocBuffer(data->mYSize, gfxASurface::CONTENT_ALPHA,
                           getter_AddRefs(tempBufferY)) ||
        !this->AllocBuffer(data->mCbCrSize, gfxASurface::CONTENT_ALPHA,
                           getter_AddRefs(tempBufferU)) ||
        !this->AllocBuffer(data->mCbCrSize, gfxASurface::CONTENT_ALPHA,
                           getter_AddRefs(tempBufferV))) {
      NS_RUNTIMEABORT("creating SharedImage failed!");
    }

    for (int i = 0; i < data->mYSize.height; i++) {
      memcpy(tempBufferY->Data() + i * tempBufferY->Stride(),
             data->mYChannel + i * data->mYStride,
             data->mYSize.width);
    }
    for (int i = 0; i < data->mCbCrSize.height; i++) {
      memcpy(tempBufferU->Data() + i * tempBufferU->Stride(),
             data->mCbChannel + i * data->mCbCrStride,
             data->mCbCrSize.width);
      memcpy(tempBufferV->Data() + i * tempBufferV->Stride(),
             data->mCrChannel + i * data->mCbCrStride,
             data->mCbCrSize.width);
    }

    SharedImage* result = new SharedImage( 
              *(new YUVImage(tempBufferY->GetShmem(),
                                             tempBufferU->GetShmem(),
                                             tempBufferV->GetShmem(),
                                             data->GetPictureRect())));
    NS_ABORT_IF_FALSE(result->type() == SharedImage::TYUVImage,
                      "SharedImage type not set correctly");
    return result;
  } else if (image->GetFormat() == Image::GONK_IO_SURFACE) {
    GonkIOSurfaceImage* gonkImage = static_cast<GonkIOSurfaceImage*>(image);
    SharedImage* result = new SharedImage(gonkImage->GetSurfaceDescriptor());
    return result;
  } else {
    NS_RUNTIMEABORT("TODO: Only YUVImage is supported here right now.");
  }
  return nsnull;
}
コード例 #9
0
void ImageContainerChild::ClearSharedImagePool()
{
  NS_ABORT_IF_FALSE(InImageBridgeChildThread(),
                    "Should be in ImageBridgeChild thread.");
  for(unsigned int i = 0; i < mSharedImagePool.Length(); ++i) {
    DeallocSharedImageData(this, *mSharedImagePool[i]);
  }
  mSharedImagePool.Clear();
}
コード例 #10
0
void ImageContainerChild::DestroyNow()
{
  NS_ABORT_IF_FALSE(InImageBridgeChildThread(),
                    "Should be in ImageBridgeChild thread.");

  ClearSharedImagePool();

  Send__delete__(this);
}
コード例 #11
0
SharedRGBImage::~SharedRGBImage()
{
  MOZ_COUNT_DTOR(SharedRGBImage);

  if (mCompositable->GetAsyncID() != 0 &&
      !InImageBridgeChildThread()) {
    ImageBridgeChild::DispatchReleaseTextureClient(mTextureClient.forget().drop());
    ImageBridgeChild::DispatchReleaseImageClient(mCompositable.forget().drop());
  }
}
コード例 #12
0
bool
ImageBridgeChild::AllocShmem(size_t aSize,
                             ipc::SharedMemory::SharedMemoryType aType,
                             ipc::Shmem* aShmem)
{
  if (InImageBridgeChildThread()) {
    return PImageBridgeChild::AllocShmem(aSize, aType, aShmem);
  } else {
    return DispatchAllocShmemInternal(aSize, aType, aShmem, false); // false: unsafe
  }
}
コード例 #13
0
// dispatched function
static void DeleteImageBridgeSync(ReentrantMonitor *aBarrier, bool *aDone)
{
  ReentrantMonitorAutoEnter autoMon(*aBarrier);

  NS_ABORT_IF_FALSE(InImageBridgeChildThread(),
                    "Should be in ImageBridgeChild thread.");
  delete sImageBridgeChildSingleton;
  sImageBridgeChildSingleton = nullptr;
  *aDone = true;
  aBarrier->NotifyAll();
}
コード例 #14
0
static void ReleaseImageClientNow(ImageClient* aClient,
                                  PImageContainerChild* aChild)
{
  MOZ_ASSERT(InImageBridgeChildThread());
  if (aClient) {
    aClient->Release();
  }
  if (aChild) {
    aChild->SendAsyncDelete();
  }
}
コード例 #15
0
//static
void ImageBridgeChild::FlushAllImages(ImageClient* aClient, ImageContainer* aContainer, bool aExceptFront)
{
  if (!IsCreated()) {
    return;
  }
  MOZ_ASSERT(aClient);
  MOZ_ASSERT(!sImageBridgeChildSingleton->mShuttingDown);
  MOZ_ASSERT(!InImageBridgeChildThread());
  if (InImageBridgeChildThread()) {
    NS_ERROR("ImageBridgeChild::FlushAllImages() is called on ImageBridge thread.");
     return;
   }

  RefPtr<AsyncTransactionTracker> status = aClient->PrepareFlushAllImages();

  sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
    FROM_HERE,
    NewRunnableFunction(&FlushAllImagesSync, aClient, aContainer, aExceptFront, status));

  status->WaitComplete();
}
コード例 #16
0
// dispatched function
static void ImageBridgeShutdownStep2(ReentrantMonitor *aBarrier, bool *aDone)
{
  ReentrantMonitorAutoEnter autoMon(*aBarrier);

  MOZ_ASSERT(InImageBridgeChildThread(),
             "Should be in ImageBridgeChild thread.");

  sImageBridgeChildSingleton->SendStop();

  *aDone = true;
  aBarrier->NotifyAll();
}
コード例 #17
0
// dispatched function
static void StopImageBridgeSync(ReentrantMonitor *aBarrier, bool *aDone)
{
  ReentrantMonitorAutoEnter autoMon(*aBarrier);

  NS_ABORT_IF_FALSE(InImageBridgeChildThread(),
                    "Should be in ImageBridgeChild thread.");
  if (sImageBridgeChildSingleton) {

    sImageBridgeChildSingleton->SendStop();
  }
  *aDone = true;
  aBarrier->NotifyAll();
}
コード例 #18
0
void ImageContainerChild::DestroyNow()
{
  NS_ABORT_IF_FALSE(InImageBridgeChildThread(),
                    "Should be in ImageBridgeChild thread.");
  NS_ABORT_IF_FALSE(mDispatchedDestroy,
                    "Incorrect state in the destruction sequence.");

  ClearSharedImagePool();
  mImageQueue.Clear();

  // will decrease the refcount and, in most cases, delete the ImageContainerChild
  Send__delete__(this);
  Release(); // corresponds to the AddRef in DispatchDestroy
}
コード例 #19
0
//static
void ImageBridgeChild::DispatchImageClientUpdate(ImageClient* aClient,
                                                 ImageContainer* aContainer)
{
  if (InImageBridgeChildThread()) {
    UpdateImageClientNow(aClient, aContainer);
    return;
  }
  sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
    FROM_HERE,
    NewRunnableFunction<
      void (*)(ImageClient*, ImageContainer*),
      ImageClient*,
      nsRefPtr<ImageContainer> >(&UpdateImageClientNow, aClient, aContainer));
}
コード例 #20
0
//static
void ImageBridgeChild::FlushAllImages(ImageClient* aClient,
                                      ImageContainer* aContainer)
{
  if (!IsCreated()) {
    return;
  }
  MOZ_ASSERT(aClient);
  MOZ_ASSERT(!sImageBridgeChildSingleton->mShuttingDown);
  MOZ_ASSERT(!InImageBridgeChildThread());
  if (InImageBridgeChildThread()) {
    NS_ERROR("ImageBridgeChild::FlushAllImages() is called on ImageBridge thread.");
    return;
  }

  RefPtr<AsyncTransactionWaiter> waiter = new AsyncTransactionWaiter();
  // This increment is balanced by the decrement in FlushAllImagesSync
  waiter->IncrementWaitCount();

  sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
    FROM_HERE,
    NewRunnableFunction(&FlushAllImagesSync, aClient, aContainer, waiter));

  waiter->WaitComplete();
}
コード例 #21
0
bool ImageContainerChild::AddSharedImageToPool(SharedImage* img)
{
  NS_ABORT_IF_FALSE(InImageBridgeChildThread(), 
                    "AddSharedImageToPool must be called in the ImageBridgeChild thread");
  if (mStop) {
    return false;
  }

  if (mSharedImagePool.Length() >= POOL_MAX_SHARED_IMAGES) {
    return false;
  }
  if (img->type() == SharedImage::TYCbCrImage) {
    mSharedImagePool.AppendElement(img);
    return true;
  }
  return false; // TODO accept more image formats in the pool
}
コード例 #22
0
void ImageContainerChild::Destroy()
{
  if (mStop) return;

  mStop = true;

  if (mImageContainer) {
    mImageContainer->SetImageContainerChild(nsnull);
  }
  if (InImageBridgeChildThread()) {
    DestroyNow();
    return;
  }

  // destruction must be done on the ImageBridgeChild thread
  Task * t = new ImageContainerChildDestroyTask(this);   
  GetMessageLoop()->PostTask(FROM_HERE, t);  
}
コード例 #23
0
void ImageContainerChild::SetIdle()
{
    if (mStop) return;

    if (InImageBridgeChildThread()) {
        return SetIdleNow();
    }

    Monitor barrier("SetIdle Lock");
    MonitorAutoLock autoMon(barrier);
    bool done = false;

    GetMessageLoop()->PostTask(FROM_HERE,
                               NewRunnableMethod(this, &ImageContainerChild::SetIdleSync, &barrier, &done));

    while (!done) {
        barrier.Wait();
    }
}
コード例 #24
0
SharedImage* ImageContainerChild::AllocateSharedImageFor(Image* image)
{
  NS_ABORT_IF_FALSE(InImageBridgeChildThread(),
                  "Should be in ImageBridgeChild thread.");
  if (!image) {
    return nullptr;
  }

  if (image->GetFormat() == PLANAR_YCBCR ) {
    PlanarYCbCrImage *planarYCbCrImage = static_cast<PlanarYCbCrImage*>(image);
    const PlanarYCbCrImage::Data *data = planarYCbCrImage->GetData();
    NS_ASSERTION(data, "Must be able to retrieve yuv data from image!");
    if (!data) {
      return nullptr;
    }

    SharedMemory::SharedMemoryType shmType = OptimalShmemType();
    size_t size = ShmemYCbCrImage::ComputeMinBufferSize(data->mYSize,
                                                        data->mCbCrSize);
    Shmem shmem;
    if (!AllocUnsafeShmem(size, shmType, &shmem)) {
      return nullptr;
    }

    ShmemYCbCrImage::InitializeBufferInfo(shmem.get<uint8_t>(),
                                          data->mYSize,
                                          data->mCbCrSize);
    ShmemYCbCrImage shmemImage(shmem);

    if (!shmemImage.IsValid()) {
      NS_WARNING("Failed to properly allocate image data!");
      DeallocShmem(shmem);
      return nullptr;
    }

    ++mActiveImageCount;
    return new SharedImage(YCbCrImage(shmem, 0, data->GetPictureRect()));
  } else {
    NS_RUNTIMEABORT("TODO: Only YCbCrImage is supported here right now.");
  }
  return nullptr;
}
コード例 #25
0
void ImageContainerChild::SendImageAsync(ImageContainer* aContainer,
                                         Image* aImage)
{
  if(!aContainer || !aImage) {
      return;
  }

  if (mStop) {
    return;
  }

  if (InImageBridgeChildThread()) {
    SendImageNow(aImage);
  }

  // Sending images and (potentially) allocating shmems must be done 
  // on the ImageBridgeChild thread.
  Task *t = new ImageBridgeCopyAndSendTask(this, aContainer, aImage);   
  GetMessageLoop()->PostTask(FROM_HERE, t);
}
コード例 #26
0
bool
ImageBridgeChild::DeallocSurfaceDescriptorGralloc(const SurfaceDescriptor& aBuffer)
{
  if (InImageBridgeChildThread()) {
    return ImageBridgeChild::DeallocSurfaceDescriptorGrallocNow(aBuffer);
  }

  Monitor barrier("DeallocSurfaceDescriptor Lock");
  MonitorAutoLock autoMon(barrier);
  bool done = false;

  GetMessageLoop()->PostTask(FROM_HERE, NewRunnableFunction(&DeallocSurfaceDescriptorGrallocSync,
                                                            aBuffer, &barrier, &done));

  while (!done) {
    barrier.Wait();
  }

  return true;
}
コード例 #27
0
// static
void ImageBridgeChild::DispatchImageClientUpdate(ImageClient* aClient,
                                                 ImageContainer* aContainer)
{
  if (!ImageBridgeChild::IsCreated() || ImageBridgeChild::IsShutDown()) {
    NS_WARNING("Something is holding on to graphics resources after the shutdown"
               "of the graphics subsystem!");
    return;
  }
  if (!aClient || !aContainer || !IsCreated()) {
    return;
  }

  if (InImageBridgeChildThread()) {
    UpdateImageClientNow(aClient, aContainer);
    return;
  }
  sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
    FROM_HERE,
    NewRunnableFunction(&UpdateImageClientNow, aClient, RefPtr<ImageContainer>(aContainer)));
}
コード例 #28
0
SharedImage* ImageContainerChild::ImageToSharedImage(Image* aImage)
{
  if (mStop) return nsnull;
  if (mActiveImageCount > MAX_ACTIVE_SHARED_IMAGES) {
    // Too many active shared images, perhaps the compositor is hanging.
    // Skipping current image
    return nsnull;
  }

  NS_ABORT_IF_FALSE(InImageBridgeChildThread(),
                    "Should be in ImageBridgeChild thread.");
  SharedImage* img = PopSharedImageFromPool();
  if (img) {
    CopyDataIntoSharedImage(aImage, img);
  } else {
    img = CreateSharedImageFromData(aImage);
  }
  mImageQueue.AppendElement(aImage);
  return img;
}
コード例 #29
0
TemporaryRef<ImageClient>
ImageBridgeChild::CreateImageClient(CompositableType aType)
{
  if (InImageBridgeChildThread()) {
    return CreateImageClientNow(aType);
  }
  ReentrantMonitor barrier("CreateImageClient Lock");
  ReentrantMonitorAutoEnter autoMon(barrier);
  bool done = false;

  RefPtr<ImageClient> result = nullptr;
  GetMessageLoop()->PostTask(FROM_HERE, NewRunnableFunction(&CreateImageClientSync,
                                                            &result, &barrier, aType, &done));
  // should stop the thread until the ImageClient has been created on
  // the other thread
  while (!done) {
    barrier.Wait();
  }
  return result.forget();
}
コード例 #30
0
void
ImageBridgeChild::DeallocShmem(ipc::Shmem& aShmem)
{
  if (InImageBridgeChildThread()) {
    PImageBridgeChild::DeallocShmem(aShmem);
  } else {
    ReentrantMonitor barrier("AllocatorProxy Dealloc");
    ReentrantMonitorAutoEnter autoMon(barrier);

    bool done = false;
    GetMessageLoop()->PostTask(FROM_HERE,
                               NewRunnableFunction(&ProxyDeallocShmemNow,
                                                   this,
                                                   &aShmem,
                                                   &barrier,
                                                   &done));
    while (!done) {
      barrier.Wait();
    }
  }
}