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