ring_buffer.h revision 5821806d5e7f356e8fa4b058a389a808ea183019
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 "../../gpu_export.h"
13#include "../common/logging.h"
14#include "../common/types.h"
15
16namespace gpu {
17class 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.
22class 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.
113class 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    GPU_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