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