author George Wright <>
Fri, 29 Jul 2016 14:14:09 -0400
changeset 349883 a1d6e5e2864b11d5224c4002b4f8b9b41d2992cc
parent 349485 81aab5c5f3d04bda4c8f9fda722db13fdc738ffc
child 360418 b7ead4d4eb90ac9e8f112574dc194691e507658e
permissions -rw-r--r--
Bug 1289525 - Shrink the TextureClientPool to maximum size after a short delay, and clear the pool after a longer delay. r=jrmuizel, a=ritu

/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at */


#include "mozilla/gfx/Types.h"
#include "mozilla/gfx/Point.h"
#include "mozilla/RefPtr.h"
#include "TextureClient.h"
#include "nsITimer.h"
#include <stack>
#include <list>

namespace mozilla {
namespace layers {

class ISurfaceAllocator;
class TextureForwarder;
class TextureReadLock;

class TextureClientAllocator
  virtual ~TextureClientAllocator() {}

  virtual already_AddRefed<TextureClient> GetTextureClient() = 0;

   * Return a TextureClient that is not yet ready to be reused, but will be
   * imminently.
  virtual void ReturnTextureClientDeferred(TextureClient *aClient) = 0;

  virtual void ReportClientLost() = 0;

class TextureClientPool final : public TextureClientAllocator

  TextureClientPool(LayersBackend aBackend,
                    gfx::SurfaceFormat aFormat,
                    gfx::IntSize aSize,
                    TextureFlags aFlags,
                    uint32_t aShrinkTimeoutMsec,
                    uint32_t aClearTimeoutMsec,
                    uint32_t aInitialPoolSize,
                    uint32_t aPoolUnusedSize,
                    TextureForwarder* aAllocator);

   * Gets an allocated TextureClient of size and format that are determined
   * by the initialisation parameters given to the pool. This will either be
   * a cached client that was returned to the pool, or a newly allocated
   * client if one isn't available.
   * All clients retrieved by this method should be returned using the return
   * functions, or reported lost so that the pool can manage its size correctly.
  already_AddRefed<TextureClient> GetTextureClient() override;

   * Return a TextureClient that is no longer being used and is ready for
   * immediate re-use or destruction.
  void ReturnTextureClient(TextureClient *aClient);

   * Return a TextureClient that is not yet ready to be reused, but will be
   * imminently.
  void ReturnTextureClientDeferred(TextureClient *aClient) override;

   * Return any clients to the pool that were previously returned in
   * ReturnTextureClientDeferred.
  void ReturnDeferredClients();

   * Attempt to shrink the pool so that there are no more than
   * mInitialPoolSize outstanding.
  void ShrinkToMaximumSize();

   * Report that a client retrieved via GetTextureClient() has become
   * unusable, so that it will no longer be tracked.
  virtual void ReportClientLost() override;

   * Calling this will cause the pool to attempt to relinquish any unused
   * clients.
  void Clear();

  LayersBackend GetBackend() const { return mBackend; }
  gfx::SurfaceFormat GetFormat() { return mFormat; }
  TextureFlags GetFlags() const { return mFlags; }

   * Clear the pool and put it in a state where it won't recycle any new texture.
  void Destroy();

  void ReturnUnlockedClients();

  /// Allocate a single TextureClient to be returned from the pool.
  void AllocateTextureClient();

  /// Reset and/or initialise timers for shrinking/clearing the pool.
  void ResetTimers();

  /// Backend passed to the TextureClient for buffer creation.
  LayersBackend mBackend;

  /// Format is passed to the TextureClient for buffer creation.
  gfx::SurfaceFormat mFormat;

  /// The width and height of the tiles to be used.
  gfx::IntSize mSize;

  /// Flags passed to the TextureClient for buffer creation.
  const TextureFlags mFlags;

  /// How long to wait after a TextureClient is returned before trying
  /// to shrink the pool to its maximum size of mPoolUnusedSize.
  uint32_t mShrinkTimeoutMsec;

  /// How long to wait after a TextureClient is returned before trying
  /// to clear the pool.
  uint32_t mClearTimeoutMsec;

  // The initial number of unused texture clients to seed the pool with
  // on construction
  uint32_t mInitialPoolSize;

  // How many unused texture clients to try and keep around if we go over
  // the initial allocation
  uint32_t mPoolUnusedSize;

  /// This is a total number of clients in the wild and in the stack of
  /// deferred clients (see below).  So, the total number of clients in
  /// existence is always mOutstandingClients + the size of mTextureClients.
  uint32_t mOutstandingClients;

  // On b2g gonk, std::queue might be a better choice.
  // On ICS, fence wait happens implicitly before drawing.
  // Since JB, fence wait happens explicitly when fetching a client from the pool.
  std::stack<RefPtr<TextureClient> > mTextureClients;

  std::list<RefPtr<TextureClient>> mTextureClientsDeferred;
  RefPtr<nsITimer> mShrinkTimer;
  RefPtr<nsITimer> mClearTimer;
  // This mSurfaceAllocator owns us, so no need to hold a ref to it
  TextureForwarder* mSurfaceAllocator;

  // Keep track of whether this pool has been destroyed or not. If it has,
  // we won't accept returns of TextureClients anymore, and the refcounting
  // should take care of their destruction.
  bool mDestroyed;

} // namespace layers
} // namespace mozilla