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 "base/macros.h"
14#include "gpu/gpu_export.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  //   alignment: Alignment for allocations.
29  //   base_offset: The offset of the start of the buffer.
30  //   size: The size of the buffer in bytes.
31  //   helper: A CommandBufferHelper for dealing with tokens.
32  //   base: The physical address that corresponds to base_offset.
33  RingBuffer(unsigned int alignment, Offset base_offset,
34             unsigned int size, CommandBufferHelper* helper, void* base);
35
36  ~RingBuffer();
37
38  // Allocates a block of memory. If the buffer is out of directly available
39  // memory, this function may wait until memory that was freed "pending a
40  // token" can be re-used.
41  //
42  // Parameters:
43  //   size: the size of the memory block to allocate.
44  //
45  // Returns:
46  //   the pointer to the allocated memory block.
47  void* Alloc(unsigned int size);
48
49  // Frees a block of memory, pending the passage of a token. That memory won't
50  // be re-allocated until the token has passed through the command stream.
51  //
52  // Parameters:
53  //   pointer: the pointer to the memory block to free.
54  //   token: the token value to wait for before re-using the memory.
55  void FreePendingToken(void* pointer, unsigned int token);
56
57  // Gets the size of the largest free block that is available without waiting.
58  unsigned int GetLargestFreeSizeNoWaiting();
59
60  // Gets the size of the largest free block that can be allocated if the
61  // caller can wait. Allocating a block of this size will succeed, but may
62  // block.
63  unsigned int GetLargestFreeOrPendingSize() {
64    return size_;
65  }
66
67  // Gets a pointer to a memory block given the base memory and the offset.
68  void* GetPointer(RingBuffer::Offset offset) const {
69    return static_cast<int8*>(base_) + offset;
70  }
71
72  // Gets the offset to a memory block given the base memory and the address.
73  RingBuffer::Offset GetOffset(void* pointer) const {
74    return static_cast<int8*>(pointer) - static_cast<int8*>(base_);
75  }
76
77  // Rounds the given size to the alignment in use.
78  unsigned int RoundToAlignment(unsigned int size) {
79    return (size + alignment_ - 1) & ~(alignment_ - 1);
80  }
81
82
83 private:
84  enum State {
85    IN_USE,
86    PADDING,
87    FREE_PENDING_TOKEN
88  };
89  // Book-keeping sturcture that describes a block of memory.
90  struct Block {
91    Block(Offset _offset, unsigned int _size, State _state)
92        : offset(_offset),
93          size(_size),
94          token(0),
95          state(_state) {
96    }
97    Offset offset;
98    unsigned int size;
99    unsigned int token;  // token to wait for.
100    State state;
101  };
102
103  typedef std::deque<Block> Container;
104  typedef unsigned int BlockIndex;
105
106  void FreeOldestBlock();
107
108  CommandBufferHelper* helper_;
109
110  // Used blocks are added to the end, blocks are freed from the beginning.
111  Container blocks_;
112
113  // The base offset of the ring buffer.
114  Offset base_offset_;
115
116  // The size of the ring buffer.
117  Offset size_;
118
119  // Offset of first free byte.
120  Offset free_offset_;
121
122  // Offset of first used byte.
123  // Range between in_use_mark and free_mark is in use.
124  Offset in_use_offset_;
125
126  // Alignment for allocations.
127  unsigned int alignment_;
128
129  // The physical address that corresponds to base_offset.
130  void* base_;
131
132  DISALLOW_IMPLICIT_CONSTRUCTORS(RingBuffer);
133};
134
135}  // namespace gpu
136
137#endif  // GPU_COMMAND_BUFFER_CLIENT_RING_BUFFER_H_
138