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_
14 #include "base/bind.h"
15 #include "base/logging.h"
16 #include "base/macros.h"
17 #include "gpu/gpu_export.h"
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
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
{
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
,
44 CommandBufferHelper
*helper
,
45 const base::Closure
& poll_callback
);
49 // Allocates a block of memory. If the buffer is out of directly available
50 // memory, this function may wait until memory that was freed "pending a
51 // token" can be re-used.
54 // size: the size of the memory block to allocate.
57 // the offset of the allocated memory block, or kInvalidOffset if out of
59 Offset
Alloc(unsigned int size
);
61 // Frees a block of memory.
64 // offset: the offset of the memory block to free.
65 void Free(Offset offset
);
67 // Frees a block of memory, pending the passage of a token. That memory won't
68 // be re-allocated until the token has passed through the command stream.
71 // offset: the offset of the memory block to free.
72 // token: the token value to wait for before re-using the memory.
73 void FreePendingToken(Offset offset
, int32 token
);
75 // Frees any blocks pending a token for which the token has been read.
78 // Gets the size of the largest free block that is available without waiting.
79 unsigned int GetLargestFreeSize();
81 // Gets the size of the largest free block that can be allocated if the
82 // caller can wait. Allocating a block of this size will succeed, but may
84 unsigned int GetLargestFreeOrPendingSize();
86 // Checks for consistency inside the book-keeping structures. Used for
88 bool CheckConsistency();
90 // True if any memory is allocated.
93 // Return bytes of memory that is IN_USE
94 size_t bytes_in_use() const { return bytes_in_use_
; }
97 // Status of a block of memory, for book-keeping.
104 // Book-keeping sturcture that describes a block of memory.
109 int32_t token
; // token to wait for in the FREE_PENDING_TOKEN case.
112 // Comparison functor for memory block sorting.
115 bool operator() (const Block
&left
, const Block
&right
) {
116 return left
.offset
< right
.offset
;
120 typedef std::vector
<Block
> Container
;
121 typedef unsigned int BlockIndex
;
123 static const int32_t kUnusedToken
= 0;
125 // Gets the index of a memory block, given its offset.
126 BlockIndex
GetBlockByOffset(Offset offset
);
128 // Collapse a free block with its neighbours if they are free. Returns the
129 // index of the collapsed block.
130 // NOTE: this will invalidate block indices.
131 BlockIndex
CollapseFreeBlock(BlockIndex index
);
133 // Waits for a FREE_PENDING_TOKEN block to be usable, and free it. Returns
134 // the new index of that block (since it may have been collapsed).
135 // NOTE: this will invalidate block indices.
136 BlockIndex
WaitForTokenAndFreeBlock(BlockIndex index
);
138 // Allocates a block of memory inside a given block, splitting it in two
139 // (unless that block is of the exact requested size).
140 // NOTE: this will invalidate block indices.
141 // Returns the offset of the allocated block (NOTE: this is different from
142 // the other functions that return a block index).
143 Offset
AllocInBlock(BlockIndex index
, unsigned int size
);
145 CommandBufferHelper
*helper_
;
146 base::Closure poll_callback_
;
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
{
157 FencedAllocatorWrapper(unsigned int size
,
158 CommandBufferHelper
* helper
,
159 const base::Closure
& poll_callback
,
161 : allocator_(size
, helper
, poll_callback
),
164 // Allocates a block of memory. If the buffer is out of directly available
165 // memory, this function may wait until memory that was freed "pending a
166 // token" can be re-used.
169 // size: the size of the memory block to allocate.
172 // the pointer to the allocated memory block, or NULL if out of
174 void *Alloc(unsigned int size
) {
175 FencedAllocator::Offset offset
= allocator_
.Alloc(size
);
176 return GetPointer(offset
);
179 // Allocates a block of memory. If the buffer is out of directly available
180 // memory, this function may wait until memory that was freed "pending a
181 // token" can be re-used.
182 // This is a type-safe version of Alloc, returning a typed pointer.
185 // count: the number of elements to allocate.
188 // the pointer to the allocated memory block, or NULL if out of
190 template <typename T
> T
*AllocTyped(unsigned int count
) {
191 return static_cast<T
*>(Alloc(count
* sizeof(T
)));
194 // Frees a block of memory.
197 // pointer: the pointer to the memory block to free.
198 void Free(void *pointer
) {
200 allocator_
.Free(GetOffset(pointer
));
203 // Frees a block of memory, pending the passage of a token. That memory won't
204 // be re-allocated until the token has passed through the command stream.
207 // pointer: the pointer to the memory block to free.
208 // token: the token value to wait for before re-using the memory.
209 void FreePendingToken(void *pointer
, int32 token
) {
211 allocator_
.FreePendingToken(GetOffset(pointer
), token
);
214 // Frees any blocks pending a token for which the token has been read.
216 allocator_
.FreeUnused();
219 // Gets a pointer to a memory block given the base memory and the offset.
220 // It translates FencedAllocator::kInvalidOffset to NULL.
221 void *GetPointer(FencedAllocator::Offset offset
) {
222 return (offset
== FencedAllocator::kInvalidOffset
) ?
223 NULL
: static_cast<char *>(base_
) + offset
;
226 // Gets the offset to a memory block given the base memory and the address.
227 // It translates NULL to FencedAllocator::kInvalidOffset.
228 FencedAllocator::Offset
GetOffset(void *pointer
) {
230 static_cast<FencedAllocator::Offset
>(
231 static_cast<char*>(pointer
) - static_cast<char*>(base_
)) :
232 FencedAllocator::kInvalidOffset
;
235 // Gets the size of the largest free block that is available without waiting.
236 unsigned int GetLargestFreeSize() {
237 return allocator_
.GetLargestFreeSize();
240 // Gets the size of the largest free block that can be allocated if the
242 unsigned int GetLargestFreeOrPendingSize() {
243 return allocator_
.GetLargestFreeOrPendingSize();
246 // Checks for consistency inside the book-keeping structures. Used for
248 bool CheckConsistency() {
249 return allocator_
.CheckConsistency();
252 // True if any memory is allocated.
254 return allocator_
.InUse();
257 FencedAllocator
&allocator() { return allocator_
; }
259 size_t bytes_in_use() const { return allocator_
.bytes_in_use(); }
262 FencedAllocator allocator_
;
264 DISALLOW_IMPLICIT_CONSTRUCTORS(FencedAllocatorWrapper
);
269 #endif // GPU_COMMAND_BUFFER_CLIENT_FENCED_ALLOCATOR_H_