void
TextureClientPool::ReturnTextureClient(TextureClient *aClient)
{
  if (!aClient) {
    return;
  }
#ifdef GFX_DEBUG_TRACK_CLIENTS_IN_POOL
  DebugOnly<bool> ok = TestClientPool("return", aClient, this);
  MOZ_ASSERT(ok);
#endif
  // Add the client to the pool:
  MOZ_ASSERT(mOutstandingClients > mTextureClientsDeferred.size());
  mOutstandingClients--;
  mTextureClients.push(aClient);

  // Shrink down if we're beyond our maximum size
  ShrinkToMaximumSize();

  // Kick off the pool shrinking timer if there are still more unused texture
  // clients than our desired minimum cache size.
  if (mTextureClients.size() > sMinCacheSize) {
    mTimer->InitWithFuncCallback(ShrinkCallback, this, mShrinkTimeoutMsec,
                                 nsITimer::TYPE_ONE_SHOT);
  }
}
TemporaryRef<TextureClient>
TextureClientPool::GetTextureClient()
{
  mOutstandingClients++;

  // Try to fetch a client from the pool
  RefPtr<TextureClient> textureClient;
  if (mTextureClients.size()) {
    textureClient = mTextureClients.top();
    textureClient->WaitReleaseFence();
    mTextureClients.pop();
    return textureClient;
  }

  // We're increasing the number of outstanding TextureClients without reusing a
  // client, we may need to free a deferred-return TextureClient.
  ShrinkToMaximumSize();

  // No unused clients in the pool, create one
  if (gfxPrefs::ForceShmemTiles()) {
    // gfx::BackendType::NONE means use the content backend
    textureClient = TextureClient::CreateBufferTextureClient(mSurfaceAllocator,
      mFormat, TextureFlags::IMMEDIATE_UPLOAD, gfx::BackendType::NONE);
  } else {
    textureClient = TextureClient::CreateTextureClientForDrawing(mSurfaceAllocator,
      mFormat, TextureFlags::IMMEDIATE_UPLOAD, gfx::BackendType::NONE, mSize);
  }
  textureClient->AllocateForSurface(mSize, ALLOC_DEFAULT);

  return textureClient;
}
void
TextureClientPool::ReturnDeferredClients()
{
  if (mTextureClientsDeferred.empty()) {
    return;
  }

  TCP_LOG("TexturePool %p returning %u deferred clients to pool\n",
      this, mTextureClientsDeferred.size());

  ReturnUnlockedClients();
  ShrinkToMaximumSize();
}
void
TextureClientPool::ReturnTextureClientDeferred(TextureClient *aClient)
{
  if (!aClient) {
    return;
  }
#ifdef GFX_DEBUG_TRACK_CLIENTS_IN_POOL
  DebugOnly<bool> ok = TestClientPool("defer", aClient, this);
  MOZ_ASSERT(ok);
#endif
  mTextureClientsDeferred.push(aClient);
  ShrinkToMaximumSize();
}
void
TextureClientPool::ReturnTextureClientDeferred(TextureClient *aClient)
{
  if (!aClient) {
    return;
  }
#ifdef GFX_DEBUG_TRACK_CLIENTS_IN_POOL
  DebugOnly<bool> ok = TestClientPool("defer", aClient, this);
  MOZ_ASSERT(ok);
#endif
  mTextureClientsDeferred.push(aClient);
  TCP_LOG("TexturePool %p had client %p defer-returned, size %u outstanding %u\n",
      this, aClient, mTextureClientsDeferred.size(), mOutstandingClients);
  ShrinkToMaximumSize();
}
void
TextureClientPool::ReturnDeferredClients()
{
  while (!mTextureClientsDeferred.empty()) {
    mTextureClients.push(mTextureClientsDeferred.top());
    mTextureClientsDeferred.pop();

    MOZ_ASSERT(mOutstandingClients > 0);
    mOutstandingClients--;
  }
  ShrinkToMaximumSize();

  // Kick off the pool shrinking timer if there are still more unused texture
  // clients than our desired minimum cache size.
  if (mTextureClients.size() > sMinCacheSize) {
    mTimer->InitWithFuncCallback(ShrinkCallback, this, mShrinkTimeoutMsec,
                                 nsITimer::TYPE_ONE_SHOT);
  }
}
TemporaryRef<TextureClient>
TextureClientPool::GetTextureClient()
{
  // Try to fetch a client from the pool
  RefPtr<TextureClient> textureClient;
  if (mTextureClients.size()) {
    mOutstandingClients++;
    textureClient = mTextureClients.top();
    mTextureClients.pop();
#ifdef GFX_DEBUG_TRACK_CLIENTS_IN_POOL
    DebugOnly<bool> ok = TestClientPool("fetch", textureClient, this);
    MOZ_ASSERT(ok);
#endif
    TCP_LOG("TexturePool %p giving %p from pool; size %u outstanding %u\n",
        this, textureClient.get(), mTextureClients.size(), mOutstandingClients);
    return textureClient;
  }

  // We're increasing the number of outstanding TextureClients without reusing a
  // client, we may need to free a deferred-return TextureClient.
  ShrinkToMaximumSize();

  // No unused clients in the pool, create one
  if (gfxPrefs::ForceShmemTiles()) {
    // gfx::BackendType::NONE means use the content backend
    textureClient = TextureClient::CreateForRawBufferAccess(mSurfaceAllocator,
      mFormat, mSize, gfx::BackendType::NONE,
      TextureFlags::IMMEDIATE_UPLOAD, ALLOC_DEFAULT);
  } else {
    textureClient = TextureClient::CreateForDrawing(mSurfaceAllocator,
      mFormat, mSize, gfx::BackendType::NONE, TextureFlags::IMMEDIATE_UPLOAD);
  }

  mOutstandingClients++;
#ifdef GFX_DEBUG_TRACK_CLIENTS_IN_POOL
  if (textureClient) {
    textureClient->mPoolTracker = this;
  }
#endif
  TCP_LOG("TexturePool %p giving new %p; size %u outstanding %u\n",
      this, textureClient.get(), mTextureClients.size(), mOutstandingClients);
  return textureClient;
}
void
TextureClientPool::ReturnTextureClient(TextureClient *aClient)
{
  if (!aClient) {
    return;
  }
  MOZ_ASSERT(mOutstandingClients);
  mOutstandingClients--;

  // Add the client to the pool and shrink down if we're beyond our maximum size
  mTextureClients.push(aClient);
  ShrinkToMaximumSize();

  // Kick off the pool shrinking timer if there are still more unused texture
  // clients than our desired minimum cache size.
  if (mTextureClients.size() > sMinCacheSize) {
    mTimer->InitWithFuncCallback(ShrinkCallback, this, sShrinkTimeout,
                                 nsITimer::TYPE_ONE_SHOT);
  }
}
void
TextureClientPool::ReturnTextureClientDeferred(TextureClient *aClient)
{
  mTextureClientsDeferred.push(aClient);
  ShrinkToMaximumSize();
}