// 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();
}
void
LayerTransactionChild::Destroy()
{
  if (!IPCOpen()) {
    return;
  }
  // mDestroyed is used to prevent calling Send__delete__() twice.
  // When this function is called from CompositorChild::Destroy(),
  // under Send__delete__() call, this function is called from
  // ShadowLayerForwarder's destructor.
  // When it happens, IPCOpen() is still true.
  // See bug 1004191.
  mDestroyed = true;
  MOZ_ASSERT(0 == ManagedPLayerChild().Count(),
             "layers should have been cleaned up by now");

  const ManagedContainer<PTextureChild>& textures = ManagedPTextureChild();
  for (auto iter = textures.ConstIter(); !iter.Done(); iter.Next()) {
    TextureClient* texture = TextureClient::AsTextureClient(iter.Get()->GetKey());
    if (texture) {
      texture->Destroy();
    }
  }

  SendShutdown();
}
void
LayerTransactionChild::Destroy()
{
  if (!IPCOpen()) {
    return;
  }
  // mDestroyed is used to prevent calling Send__delete__() twice.
  // When this function is called from CompositorChild::Destroy(),
  // under Send__delete__() call, this function is called from
  // ShadowLayerForwarder's destructor.
  // When it happens, IPCOpen() is still true.
  // See bug 1004191.
  mDestroyed = true;
  MOZ_ASSERT(0 == ManagedPLayerChild().Length(),
             "layers should have been cleaned up by now");

  for (size_t i = 0; i < ManagedPTextureChild().Length(); ++i) {
    TextureClient* texture = TextureClient::AsTextureClient(ManagedPTextureChild()[i]);
    if (texture) {
      texture->ForceRemove();
    }
  }

  SendShutdown();
}
TextureClient*
PersistentBufferProviderShared::GetTextureClient()
{
  // Can't access the front buffer while drawing.
  MOZ_ASSERT(!mDrawTarget);
  TextureClient* texture = GetTexture(mFront);
  if (texture) {
    texture->EnableReadLock();
  } else {
    gfxCriticalNote << "PersistentBufferProviderShared: front buffer unavailable";
  }
  return texture;
}
void
PersistentBufferProviderShared::Destroy()
{
  mSnapshot = nullptr;
  mDrawTarget = nullptr;

  for (uint32_t i = 0; i < mTextures.length(); ++i) {
    TextureClient* texture = mTextures[i];
    if (texture && texture->IsLocked()) {
      MOZ_ASSERT(false);
      texture->Unlock();
    }
  }

  mTextures.clear();
}
bool
PersistentBufferProviderShared::ReturnDrawTarget(already_AddRefed<gfx::DrawTarget> aDT)
{
  RefPtr<gfx::DrawTarget> dt(aDT);
  MOZ_ASSERT(mDrawTarget == dt);
  // Can't change the current front buffer while its snapshot is borrowed!
  MOZ_ASSERT(!mSnapshot);

  mDrawTarget = nullptr;
  dt = nullptr;

  TextureClient* back = GetTexture(mBack);
  MOZ_ASSERT(back);

  if (back) {
    back->Unlock();
    mFront = mBack;
  }

  return !!back;
}
Beispiel #7
0
void
ClientLayerManager::ReportClientLost(TextureClient& aClient) {
    GetTexturePool(aClient.GetFormat())->ReportClientLost();
}
Beispiel #8
0
void
ClientLayerManager::ReturnTextureClient(TextureClient& aClient) {
    GetTexturePool(aClient.GetFormat())->ReturnTextureClient(&aClient);
}
void
ClientLayerManager::ReturnTextureClientDeferred(TextureClient& aClient) {
  GetTexturePool(aClient.GetFormat(),
                 aClient.GetFlags())->ReturnTextureClientDeferred(&aClient);
}
already_AddRefed<gfx::DrawTarget>
PersistentBufferProviderShared::BorrowDrawTarget(const gfx::IntRect& aPersistedRect)
{
  if (!mFwd->GetTextureForwarder()->IPCOpen()) {
    return nullptr;
  }

  MOZ_ASSERT(!mSnapshot);

  if (IsActivityTracked()) {
    mFwd->GetActiveResourceTracker().MarkUsed(this);
  } else {
    mFwd->GetActiveResourceTracker().AddObject(this);
  }

  if (mDrawTarget) {
    RefPtr<gfx::DrawTarget> dt(mDrawTarget);
    return dt.forget();
  }

  mFront = Nothing();

  auto previousBackBuffer = mBack;

  TextureClient* tex = GetTexture(mBack);

  // First try to reuse the current back buffer. If we can do that it means
  // we can skip copying its content to the new back buffer.
  if (tex && tex->IsReadLocked()) {
    // The back buffer is currently used by the compositor, we can't draw
    // into it.
    tex = nullptr;
  }

  if (!tex) {
    // Try to grab an already allocated texture if any is available.
    for (uint32_t i = 0; i < mTextures.length(); ++i) {
      if (!mTextures[i]->IsReadLocked()) {
        mBack = Some(i);
        tex = mTextures[i];
        break;
      }
    }
  }

  if (!tex) {
    // We have to allocate a new texture.
    if (mTextures.length() >= 4) {
      // We should never need to buffer that many textures, something's wrong.
      MOZ_ASSERT(false);
      // In theory we throttle the main thread when the compositor can't keep up,
      // so we shoud never get in a situation where we sent 4 textures to the
      // compositor and the latter as not released any of them.
      // This seems to happen, however, in some edge cases such as just after a
      // device reset (cf. Bug 1291163).
      // It would be pretty bad to keep piling textures up at this point so we
      // call NotifyInactive to remove some of our textures.
      NotifyInactive();
      // Give up now. The caller can fall-back to a non-shared buffer provider.
      return nullptr;
    }

    RefPtr<TextureClient> newTexture = TextureClient::CreateForDrawing(
      mFwd, mFormat, mSize,
      BackendSelector::Canvas,
      TextureFlags::DEFAULT,
      TextureAllocationFlags::ALLOC_DEFAULT
    );

    MOZ_ASSERT(newTexture);
    if (newTexture) {
      if (mTextures.append(newTexture)) {
        tex = newTexture;
        mBack = Some<uint32_t>(mTextures.length() - 1);
      }
    }
  }

  if (!tex || !tex->Lock(OpenMode::OPEN_READ_WRITE)) {
    return nullptr;
  }

  if (mBack != previousBackBuffer && !aPersistedRect.IsEmpty()) {
    TextureClient* previous = GetTexture(previousBackBuffer);
    if (previous && previous->Lock(OpenMode::OPEN_READ)) {
      DebugOnly<bool> success = previous->CopyToTextureClient(tex, &aPersistedRect, nullptr);
      MOZ_ASSERT(success);

      previous->Unlock();
    }
  }

  mDrawTarget = tex->BorrowDrawTarget();

  RefPtr<gfx::DrawTarget> dt(mDrawTarget);
  return dt.forget();
}