Home | History | Annotate | Download | only in client
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // This file contains the definition of the FencedAllocator class.
      6 
      7 #ifndef GPU_COMMAND_BUFFER_CLIENT_FENCED_ALLOCATOR_H_
      8 #define GPU_COMMAND_BUFFER_CLIENT_FENCED_ALLOCATOR_H_
      9 
     10 #include <stdint.h>
     11 
     12 #include <vector>
     13 
     14 #include "base/bind.h"
     15 #include "base/logging.h"
     16 #include "base/macros.h"
     17 #include "gpu/gpu_export.h"
     18 
     19 namespace gpu {
     20 class CommandBufferHelper;
     21 
     22 // FencedAllocator provides a mechanism to manage allocations within a fixed
     23 // block of memory (storing the book-keeping externally). Furthermore this
     24 // class allows to free data "pending" the passage of a command buffer token,
     25 // that is, the memory won't be reused until the command buffer has processed
     26 // that token.
     27 //
     28 // NOTE: Although this class is intended to be used in the command buffer
     29 // environment which is multi-process, this class isn't "thread safe", because
     30 // it isn't meant to be shared across modules. It is thread-compatible though
     31 // (see http://www.corp.google.com/eng/doc/cpp_primer.html#thread_safety).
     32 class GPU_EXPORT FencedAllocator {
     33  public:
     34   typedef unsigned int Offset;
     35   // Invalid offset, returned by Alloc in case of failure.
     36   static const Offset kInvalidOffset = 0xffffffffU;
     37 
     38   // Creates a FencedAllocator. Note that the size of the buffer is passed, but
     39   // not its base address: everything is handled as offsets into the buffer.
     40   FencedAllocator(unsigned int size,
     41                   CommandBufferHelper *helper,
     42                   const base::Closure& poll_callback);
     43 
     44   ~FencedAllocator();
     45 
     46   // Allocates a block of memory. If the buffer is out of directly available
     47   // memory, this function may wait until memory that was freed "pending a
     48   // token" can be re-used.
     49   //
     50   // Parameters:
     51   //   size: the size of the memory block to allocate.
     52   //
     53   // Returns:
     54   //   the offset of the allocated memory block, or kInvalidOffset if out of
     55   //   memory.
     56   Offset Alloc(unsigned int size);
     57 
     58   // Frees a block of memory.
     59   //
     60   // Parameters:
     61   //   offset: the offset of the memory block to free.
     62   void Free(Offset offset);
     63 
     64   // Frees a block of memory, pending the passage of a token. That memory won't
     65   // be re-allocated until the token has passed through the command stream.
     66   //
     67   // Parameters:
     68   //   offset: the offset of the memory block to free.
     69   //   token: the token value to wait for before re-using the memory.
     70   void FreePendingToken(Offset offset, int32 token);
     71 
     72   // Frees any blocks pending a token for which the token has been read.
     73   void FreeUnused();
     74 
     75   // Gets the size of the largest free block that is available without waiting.
     76   unsigned int GetLargestFreeSize();
     77 
     78   // Gets the size of the largest free block that can be allocated if the
     79   // caller can wait. Allocating a block of this size will succeed, but may
     80   // block.
     81   unsigned int GetLargestFreeOrPendingSize();
     82 
     83   // Checks for consistency inside the book-keeping structures. Used for
     84   // testing.
     85   bool CheckConsistency();
     86 
     87   // True if any memory is allocated.
     88   bool InUse();
     89 
     90   // Return bytes of memory that is IN_USE
     91   size_t bytes_in_use() const { return bytes_in_use_; }
     92 
     93  private:
     94   // Status of a block of memory, for book-keeping.
     95   enum State {
     96     IN_USE,
     97     FREE,
     98     FREE_PENDING_TOKEN
     99   };
    100 
    101   // Book-keeping sturcture that describes a block of memory.
    102   struct Block {
    103     State state;
    104     Offset offset;
    105     unsigned int size;
    106     int32_t token;  // token to wait for in the FREE_PENDING_TOKEN case.
    107   };
    108 
    109   // Comparison functor for memory block sorting.
    110   class OffsetCmp {
    111    public:
    112     bool operator() (const Block &left, const Block &right) {
    113       return left.offset < right.offset;
    114     }
    115   };
    116 
    117   typedef std::vector<Block> Container;
    118   typedef unsigned int BlockIndex;
    119 
    120   static const int32_t kUnusedToken = 0;
    121 
    122   // Gets the index of a memory block, given its offset.
    123   BlockIndex GetBlockByOffset(Offset offset);
    124 
    125   // Collapse a free block with its neighbours if they are free. Returns the
    126   // index of the collapsed block.
    127   // NOTE: this will invalidate block indices.
    128   BlockIndex CollapseFreeBlock(BlockIndex index);
    129 
    130   // Waits for a FREE_PENDING_TOKEN block to be usable, and free it. Returns
    131   // the new index of that block (since it may have been collapsed).
    132   // NOTE: this will invalidate block indices.
    133   BlockIndex WaitForTokenAndFreeBlock(BlockIndex index);
    134 
    135   // Allocates a block of memory inside a given block, splitting it in two
    136   // (unless that block is of the exact requested size).
    137   // NOTE: this will invalidate block indices.
    138   // Returns the offset of the allocated block (NOTE: this is different from
    139   // the other functions that return a block index).
    140   Offset AllocInBlock(BlockIndex index, unsigned int size);
    141 
    142   CommandBufferHelper *helper_;
    143   base::Closure poll_callback_;
    144   Container blocks_;
    145   size_t bytes_in_use_;
    146 
    147   DISALLOW_IMPLICIT_CONSTRUCTORS(FencedAllocator);
    148 };
    149 
    150 // This class functions just like FencedAllocator, but its API uses pointers
    151 // instead of offsets.
    152 class FencedAllocatorWrapper {
    153  public:
    154   FencedAllocatorWrapper(unsigned int size,
    155                          CommandBufferHelper* helper,
    156                          const base::Closure& poll_callback,
    157                          void* base)
    158       : allocator_(size, helper, poll_callback),
    159         base_(base) { }
    160 
    161   // Allocates a block of memory. If the buffer is out of directly available
    162   // memory, this function may wait until memory that was freed "pending a
    163   // token" can be re-used.
    164   //
    165   // Parameters:
    166   //   size: the size of the memory block to allocate.
    167   //
    168   // Returns:
    169   //   the pointer to the allocated memory block, or NULL if out of
    170   //   memory.
    171   void *Alloc(unsigned int size) {
    172     FencedAllocator::Offset offset = allocator_.Alloc(size);
    173     return GetPointer(offset);
    174   }
    175 
    176   // Allocates a block of memory. If the buffer is out of directly available
    177   // memory, this function may wait until memory that was freed "pending a
    178   // token" can be re-used.
    179   // This is a type-safe version of Alloc, returning a typed pointer.
    180   //
    181   // Parameters:
    182   //   count: the number of elements to allocate.
    183   //
    184   // Returns:
    185   //   the pointer to the allocated memory block, or NULL if out of
    186   //   memory.
    187   template <typename T> T *AllocTyped(unsigned int count) {
    188     return static_cast<T *>(Alloc(count * sizeof(T)));
    189   }
    190 
    191   // Frees a block of memory.
    192   //
    193   // Parameters:
    194   //   pointer: the pointer to the memory block to free.
    195   void Free(void *pointer) {
    196     DCHECK(pointer);
    197     allocator_.Free(GetOffset(pointer));
    198   }
    199 
    200   // Frees a block of memory, pending the passage of a token. That memory won't
    201   // be re-allocated until the token has passed through the command stream.
    202   //
    203   // Parameters:
    204   //   pointer: the pointer to the memory block to free.
    205   //   token: the token value to wait for before re-using the memory.
    206   void FreePendingToken(void *pointer, int32 token) {
    207     DCHECK(pointer);
    208     allocator_.FreePendingToken(GetOffset(pointer), token);
    209   }
    210 
    211   // Frees any blocks pending a token for which the token has been read.
    212   void FreeUnused() {
    213     allocator_.FreeUnused();
    214   }
    215 
    216   // Gets a pointer to a memory block given the base memory and the offset.
    217   // It translates FencedAllocator::kInvalidOffset to NULL.
    218   void *GetPointer(FencedAllocator::Offset offset) {
    219     return (offset == FencedAllocator::kInvalidOffset) ?
    220         NULL : static_cast<char *>(base_) + offset;
    221   }
    222 
    223   // Gets the offset to a memory block given the base memory and the address.
    224   // It translates NULL to FencedAllocator::kInvalidOffset.
    225   FencedAllocator::Offset GetOffset(void *pointer) {
    226     return pointer ?
    227         static_cast<FencedAllocator::Offset>(
    228             static_cast<char*>(pointer) - static_cast<char*>(base_)) :
    229         FencedAllocator::kInvalidOffset;
    230   }
    231 
    232   // Gets the size of the largest free block that is available without waiting.
    233   unsigned int GetLargestFreeSize() {
    234     return allocator_.GetLargestFreeSize();
    235   }
    236 
    237   // Gets the size of the largest free block that can be allocated if the
    238   // caller can wait.
    239   unsigned int GetLargestFreeOrPendingSize() {
    240     return allocator_.GetLargestFreeOrPendingSize();
    241   }
    242 
    243   // Checks for consistency inside the book-keeping structures. Used for
    244   // testing.
    245   bool CheckConsistency() {
    246     return allocator_.CheckConsistency();
    247   }
    248 
    249   // True if any memory is allocated.
    250   bool InUse() {
    251     return allocator_.InUse();
    252   }
    253 
    254   FencedAllocator &allocator() { return allocator_; }
    255 
    256   size_t bytes_in_use() const { return allocator_.bytes_in_use(); }
    257 
    258  private:
    259   FencedAllocator allocator_;
    260   void* base_;
    261   DISALLOW_IMPLICIT_CONSTRUCTORS(FencedAllocatorWrapper);
    262 };
    263 
    264 }  // namespace gpu
    265 
    266 #endif  // GPU_COMMAND_BUFFER_CLIENT_FENCED_ALLOCATOR_H_
    267