Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / gpu / command_buffer / client / fenced_allocator.h
blob95dcccec81b103c9779d3812f6be6194e1e54d1d
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.
5 // This file contains the definition of the FencedAllocator class.
7 #ifndef GPU_COMMAND_BUFFER_CLIENT_FENCED_ALLOCATOR_H_
8 #define GPU_COMMAND_BUFFER_CLIENT_FENCED_ALLOCATOR_H_
10 #include <stdint.h>
12 #include <vector>
14 #include "base/bind.h"
15 #include "base/logging.h"
16 #include "base/macros.h"
17 #include "gpu/gpu_export.h"
19 namespace gpu {
20 class CommandBufferHelper;
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.
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;
38 // Allocation alignment, must be a power of two.
39 static const unsigned int kAllocAlignment = 16;
41 // Creates a FencedAllocator. Note that the size of the buffer is passed, but
42 // not its base address: everything is handled as offsets into the buffer.
43 FencedAllocator(unsigned int size, CommandBufferHelper* helper);
45 ~FencedAllocator();
47 // Allocates a block of memory. If the buffer is out of directly available
48 // memory, this function may wait until memory that was freed "pending a
49 // token" can be re-used.
51 // Parameters:
52 // size: the size of the memory block to allocate.
54 // Returns:
55 // the offset of the allocated memory block, or kInvalidOffset if out of
56 // memory.
57 Offset Alloc(unsigned int size);
59 // Frees a block of memory.
61 // Parameters:
62 // offset: the offset of the memory block to free.
63 void Free(Offset offset);
65 // Frees a block of memory, pending the passage of a token. That memory won't
66 // be re-allocated until the token has passed through the command stream.
68 // Parameters:
69 // offset: the offset of the memory block to free.
70 // token: the token value to wait for before re-using the memory.
71 void FreePendingToken(Offset offset, int32 token);
73 // Frees any blocks pending a token for which the token has been read.
74 void FreeUnused();
76 // Gets the size of the largest free block that is available without waiting.
77 unsigned int GetLargestFreeSize();
79 // Gets the size of the largest free block that can be allocated if the
80 // caller can wait. Allocating a block of this size will succeed, but may
81 // block.
82 unsigned int GetLargestFreeOrPendingSize();
84 // Gets the total size of all free blocks that are available without waiting.
85 unsigned int GetFreeSize();
87 // Checks for consistency inside the book-keeping structures. Used for
88 // testing.
89 bool CheckConsistency();
91 // True if any memory is allocated.
92 bool InUse();
94 // Return bytes of memory that is IN_USE
95 size_t bytes_in_use() const { return bytes_in_use_; }
97 private:
98 // Status of a block of memory, for book-keeping.
99 enum State {
100 IN_USE,
101 FREE,
102 FREE_PENDING_TOKEN
105 // Book-keeping sturcture that describes a block of memory.
106 struct Block {
107 State state;
108 Offset offset;
109 unsigned int size;
110 int32_t token; // token to wait for in the FREE_PENDING_TOKEN case.
113 // Comparison functor for memory block sorting.
114 class OffsetCmp {
115 public:
116 bool operator() (const Block &left, const Block &right) {
117 return left.offset < right.offset;
121 typedef std::vector<Block> Container;
122 typedef unsigned int BlockIndex;
124 static const int32_t kUnusedToken = 0;
126 // Gets the index of a memory block, given its offset.
127 BlockIndex GetBlockByOffset(Offset offset);
129 // Collapse a free block with its neighbours if they are free. Returns the
130 // index of the collapsed block.
131 // NOTE: this will invalidate block indices.
132 BlockIndex CollapseFreeBlock(BlockIndex index);
134 // Waits for a FREE_PENDING_TOKEN block to be usable, and free it. Returns
135 // the new index of that block (since it may have been collapsed).
136 // NOTE: this will invalidate block indices.
137 BlockIndex WaitForTokenAndFreeBlock(BlockIndex index);
139 // Allocates a block of memory inside a given block, splitting it in two
140 // (unless that block is of the exact requested size).
141 // NOTE: this will invalidate block indices.
142 // Returns the offset of the allocated block (NOTE: this is different from
143 // the other functions that return a block index).
144 Offset AllocInBlock(BlockIndex index, unsigned int size);
146 CommandBufferHelper *helper_;
147 Container blocks_;
148 size_t bytes_in_use_;
150 DISALLOW_IMPLICIT_CONSTRUCTORS(FencedAllocator);
153 // This class functions just like FencedAllocator, but its API uses pointers
154 // instead of offsets.
155 class FencedAllocatorWrapper {
156 public:
157 FencedAllocatorWrapper(unsigned int size,
158 CommandBufferHelper* helper,
159 void* base)
160 : allocator_(size, helper), base_(base) {}
162 // Allocates a block of memory. If the buffer is out of directly available
163 // memory, this function may wait until memory that was freed "pending a
164 // token" can be re-used.
166 // Parameters:
167 // size: the size of the memory block to allocate.
169 // Returns:
170 // the pointer to the allocated memory block, or NULL if out of
171 // memory.
172 void *Alloc(unsigned int size) {
173 FencedAllocator::Offset offset = allocator_.Alloc(size);
174 return GetPointer(offset);
177 // Allocates a block of memory. If the buffer is out of directly available
178 // memory, this function may wait until memory that was freed "pending a
179 // token" can be re-used.
180 // This is a type-safe version of Alloc, returning a typed pointer.
182 // Parameters:
183 // count: the number of elements to allocate.
185 // Returns:
186 // the pointer to the allocated memory block, or NULL if out of
187 // memory.
188 template <typename T> T *AllocTyped(unsigned int count) {
189 return static_cast<T *>(Alloc(count * sizeof(T)));
192 // Frees a block of memory.
194 // Parameters:
195 // pointer: the pointer to the memory block to free.
196 void Free(void *pointer) {
197 DCHECK(pointer);
198 allocator_.Free(GetOffset(pointer));
201 // Frees a block of memory, pending the passage of a token. That memory won't
202 // be re-allocated until the token has passed through the command stream.
204 // Parameters:
205 // pointer: the pointer to the memory block to free.
206 // token: the token value to wait for before re-using the memory.
207 void FreePendingToken(void *pointer, int32 token) {
208 DCHECK(pointer);
209 allocator_.FreePendingToken(GetOffset(pointer), token);
212 // Frees any blocks pending a token for which the token has been read.
213 void FreeUnused() {
214 allocator_.FreeUnused();
217 // Gets a pointer to a memory block given the base memory and the offset.
218 // It translates FencedAllocator::kInvalidOffset to NULL.
219 void *GetPointer(FencedAllocator::Offset offset) {
220 return (offset == FencedAllocator::kInvalidOffset) ?
221 NULL : static_cast<char *>(base_) + offset;
224 // Gets the offset to a memory block given the base memory and the address.
225 // It translates NULL to FencedAllocator::kInvalidOffset.
226 FencedAllocator::Offset GetOffset(void *pointer) {
227 return pointer ?
228 static_cast<FencedAllocator::Offset>(
229 static_cast<char*>(pointer) - static_cast<char*>(base_)) :
230 FencedAllocator::kInvalidOffset;
233 // Gets the size of the largest free block that is available without waiting.
234 unsigned int GetLargestFreeSize() {
235 return allocator_.GetLargestFreeSize();
238 // Gets the size of the largest free block that can be allocated if the
239 // caller can wait.
240 unsigned int GetLargestFreeOrPendingSize() {
241 return allocator_.GetLargestFreeOrPendingSize();
244 // Gets the total size of all free blocks.
245 unsigned int GetFreeSize() { return allocator_.GetFreeSize(); }
247 // Checks for consistency inside the book-keeping structures. Used for
248 // testing.
249 bool CheckConsistency() {
250 return allocator_.CheckConsistency();
253 // True if any memory is allocated.
254 bool InUse() {
255 return allocator_.InUse();
258 FencedAllocator &allocator() { return allocator_; }
260 size_t bytes_in_use() const { return allocator_.bytes_in_use(); }
262 private:
263 FencedAllocator allocator_;
264 void* base_;
265 DISALLOW_IMPLICIT_CONSTRUCTORS(FencedAllocatorWrapper);
268 } // namespace gpu
270 #endif // GPU_COMMAND_BUFFER_CLIENT_FENCED_ALLOCATOR_H_