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 RingBuffer class.
      6 
      7 #ifndef GPU_COMMAND_BUFFER_CLIENT_RING_BUFFER_H_
      8 #define GPU_COMMAND_BUFFER_CLIENT_RING_BUFFER_H_
      9 
     10 #include <deque>
     11 
     12 #include "base/logging.h"
     13 #include "gpu/command_buffer/common/types.h"
     14 #include "gpu/gpu_export.h"
     15 
     16 namespace gpu {
     17 class CommandBufferHelper;
     18 
     19 // RingBuffer manages a piece of memory as a ring buffer. Memory is allocated
     20 // with Alloc and then a is freed pending a token with FreePendingToken.  Old
     21 // allocations must not be kept past new allocations.
     22 class GPU_EXPORT RingBuffer {
     23  public:
     24   typedef unsigned int Offset;
     25 
     26   // Creates a RingBuffer.
     27   // Parameters:
     28   //   base_offset: The offset of the start of the buffer.
     29   //   size: The size of the buffer in bytes.
     30   //   helper: A CommandBufferHelper for dealing with tokens.
     31   RingBuffer(
     32       Offset base_offset, unsigned int size, CommandBufferHelper* helper);
     33 
     34   ~RingBuffer();
     35 
     36   // Allocates a block of memory. If the buffer is out of directly available
     37   // memory, this function may wait until memory that was freed "pending a
     38   // token" can be re-used.
     39   //
     40   // Parameters:
     41   //   size: the size of the memory block to allocate.
     42   //
     43   // Returns:
     44   //   the offset of the allocated memory block.
     45   Offset Alloc(unsigned int size);
     46 
     47   // Frees a block of memory, pending the passage of a token. That memory won't
     48   // be re-allocated until the token has passed through the command stream.
     49   //
     50   // Parameters:
     51   //   offset: the offset of the memory block to free.
     52   //   token: the token value to wait for before re-using the memory.
     53   void FreePendingToken(Offset offset, unsigned int token);
     54 
     55   // Gets the size of the largest free block that is available without waiting.
     56   unsigned int GetLargestFreeSizeNoWaiting();
     57 
     58   // Gets the size of the largest free block that can be allocated if the
     59   // caller can wait. Allocating a block of this size will succeed, but may
     60   // block.
     61   unsigned int GetLargestFreeOrPendingSize() {
     62     return size_;
     63   }
     64 
     65  private:
     66   enum State {
     67     IN_USE,
     68     PADDING,
     69     FREE_PENDING_TOKEN
     70   };
     71   // Book-keeping sturcture that describes a block of memory.
     72   struct Block {
     73     Block(Offset _offset, unsigned int _size, State _state)
     74         : offset(_offset),
     75           size(_size),
     76           token(0),
     77           state(_state) {
     78     }
     79     Offset offset;
     80     unsigned int size;
     81     unsigned int token;  // token to wait for.
     82     State state;
     83   };
     84 
     85   typedef std::deque<Block> Container;
     86   typedef unsigned int BlockIndex;
     87 
     88   void FreeOldestBlock();
     89 
     90   CommandBufferHelper* helper_;
     91 
     92   // Used blocks are added to the end, blocks are freed from the beginning.
     93   Container blocks_;
     94 
     95   // The base offset of the ring buffer.
     96   Offset base_offset_;
     97 
     98   // The size of the ring buffer.
     99   Offset size_;
    100 
    101   // Offset of first free byte.
    102   Offset free_offset_;
    103 
    104   // Offset of first used byte.
    105   // Range between in_use_mark and free_mark is in use.
    106   Offset in_use_offset_;
    107 
    108   DISALLOW_IMPLICIT_CONSTRUCTORS(RingBuffer);
    109 };
    110 
    111 // This class functions just like RingBuffer, but its API uses pointers
    112 // instead of offsets.
    113 class RingBufferWrapper {
    114  public:
    115   // Parameters:
    116   //   base_offset: The offset to the start of the buffer
    117   //   size: The size of the buffer in bytes.
    118   //   helper: A CommandBufferHelper for dealing with tokens.
    119   //   base: The physical address that corresponds to base_offset.
    120   RingBufferWrapper(RingBuffer::Offset base_offset,
    121                     unsigned int size,
    122                     CommandBufferHelper* helper,
    123                     void* base)
    124       : allocator_(base_offset, size, helper),
    125         base_(static_cast<int8*>(base) - base_offset) {
    126   }
    127 
    128   // Allocates a block of memory. If the buffer is out of directly available
    129   // memory, this function may wait until memory that was freed "pending a
    130   // token" can be re-used.
    131   //
    132   // Parameters:
    133   //   size: the size of the memory block to allocate.
    134   //
    135   // Returns:
    136   //   the pointer to the allocated memory block, or NULL if out of
    137   //   memory.
    138   void* Alloc(unsigned int size) {
    139     RingBuffer::Offset offset = allocator_.Alloc(size);
    140     return GetPointer(offset);
    141   }
    142 
    143   // Allocates a block of memory. If the buffer is out of directly available
    144   // memory, this function may wait until memory that was freed "pending a
    145   // token" can be re-used.
    146   // This is a type-safe version of Alloc, returning a typed pointer.
    147   //
    148   // Parameters:
    149   //   count: the number of elements to allocate.
    150   //
    151   // Returns:
    152   //   the pointer to the allocated memory block, or NULL if out of
    153   //   memory.
    154   template <typename T> T* AllocTyped(unsigned int count) {
    155     return static_cast<T*>(Alloc(count * sizeof(T)));
    156   }
    157 
    158   // Frees a block of memory, pending the passage of a token. That memory won't
    159   // be re-allocated until the token has passed through the command stream.
    160   //
    161   // Parameters:
    162   //   pointer: the pointer to the memory block to free.
    163   //   token: the token value to wait for before re-using the memory.
    164   void FreePendingToken(void* pointer, unsigned int token) {
    165     DCHECK(pointer);
    166     allocator_.FreePendingToken(GetOffset(pointer), token);
    167   }
    168 
    169   // Gets a pointer to a memory block given the base memory and the offset.
    170   void* GetPointer(RingBuffer::Offset offset) const {
    171     return static_cast<int8*>(base_) + offset;
    172   }
    173 
    174   // Gets the offset to a memory block given the base memory and the address.
    175   RingBuffer::Offset GetOffset(void* pointer) const {
    176     return static_cast<int8*>(pointer) - static_cast<int8*>(base_);
    177   }
    178 
    179   // Gets the size of the largest free block that is available without waiting.
    180   unsigned int GetLargestFreeSizeNoWaiting() {
    181     return allocator_.GetLargestFreeSizeNoWaiting();
    182   }
    183 
    184   // Gets the size of the largest free block that can be allocated if the
    185   // caller can wait.
    186   unsigned int GetLargestFreeOrPendingSize() {
    187     return allocator_.GetLargestFreeOrPendingSize();
    188   }
    189 
    190  private:
    191   RingBuffer allocator_;
    192   void* base_;
    193   DISALLOW_IMPLICIT_CONSTRUCTORS(RingBufferWrapper);
    194 };
    195 
    196 }  // namespace gpu
    197 
    198 #endif  // GPU_COMMAND_BUFFER_CLIENT_RING_BUFFER_H_
    199